はじめに
こんにちは、KUDs です。
今回は、Twitter (X) で片思い中のフォローをフィルター表示するツールを作成したので紹介です!
※ほぼネタ回です
開発の背景
Twitter で、『片思い中のアカウントを一括でフォロー解除するツール』があったんだけど、最近 X の仕様変更で使えなくなったみたい。作って。
承知ですー。(片思いってなんだろう。。。)
Twitter における「片思い」とは
Twitter における「片思い」とはどういう意味ですか?
Twitter における「片思い」とは、あなたが他のユーザーをフォローしているけれど、そのユーザーがあなたをフォローしていない状態を指す日本語のスラングです。これは実際の「片思い」、つまり一方的な恋愛感情を持っている状態にたとえて使われています。逆に、お互いにフォローし合っている状態を「両思い」と言うこともあります。
要するに、知人は「片思いしている相手を一括で消し去りたい」ということなのでしょう。
(文字に起こすと少し物騒ですね。。。)
Twitter ガイドラインの確認
何を開発するにおいても、利用規約やガイドラインの確認は重要です。
作った結果、私だけが怒られるなら良いのですが(良くはないですが)、利用者のアカウントが凍結されたりしたら大変です。
そこまでの責任は取れませんが、最大限配慮すべきですので、確認します。
1. 基本原則
行ってもよいこと
- ツイートで有用な情報を自動的に広めるソリューションを開発する。
- 自社のコンテンツに反応したアカウントに自動返信するクリエイティブキャンペーンを実施する。
- ダイレクトメッセージで利用者に自動返信するソリューションを開発する。
- 利用者の役に立つ新しいサービスに挑戦する(ただし、Twitterのルールを遵守する)。
- アプリケーションが快適に動作し、優れたユーザーエクスペリエンスを達成できるようにする(その状態を長期的に維持する)。
行ってはならないこと
https://help.twitter.com/ja/rules-and-policies/twitter-automation
- Twitterのルールやポリシーに違反する。攻撃的な行為や利用者のプライバシーに関するルールについては特に注意してください。
- Twitter APIを悪用したり、レート制限を回避しようとする。
- Twitterのウェブサイトを操作するスクリプトを作成するなど、API以外の方法で自動化を行う。このような方法で自動化を行った場合、アカウントが一時的にロックされるか、永久凍結されることがあります。
- スパム送信や迷惑行為を行う、または利用者に一方的にメッセージを送信する。
「自動化」は基本的に避けた方がよさそうです。
自動化は往々にしてサーバへの高負荷を引き起こします。
そのため、多くの SNS はこういった「自動化」「Bot」に対して厳しく制限をかけています。
今回の場合、「一括フォロー解除」も自動化に分類されるかもしれません。
また、Twitter の API 有料化も念頭に置く必要があります。
そこで、すごく保守的なツール(?)を作成することにしました。
その名も、「Twitter (X) 片思い表示」です!
またしても全く需要がなさそうなものを生み出してしまいました。
とはいえ、せっかく生み出したので、生みの親として紹介していきます。
「Twitter (X) 片思い表示」とは
大きく分けて、2 つの機能があります。
【機能1】片思いフォロー中のアカウントのみを表示する
Twitter (X) 上で、片思いフォロー中の相手のみを表示することができます。
まずは「プロフィール」→「フォロー中」のページに移動してください。
URLは、 https://twitter.com/{your-twitter-id}/following です。
次に、ボタン「片思い ONLY」のボタンを押します。
ON にすることで、片思いフォロー中のアカウントのみを表示します。
OFF にすることで、通常通りの表示に切り替わります。
※あくまで片思い中の相手をフィルター表示するだけのものです。フォロー解除自動化の機能はないため、手動でポチポチ頑張る必要があります
※なお、動画では、KUDs のフォロー相手に「片思いフォロー中のアカウントが存在しない」ためボタンを押すと何も映らなくなっております
【機能2】両思いフォロー中のアカウントを強調表示する
ボタン「両思い HIGHLIGHT」を押すことで、フォローされている場合のみ強調表示することができます。
ON にすることで、「フォローされています」が、「両思いです♡」に切り替わります。なお、カラーはピンクです♡
OFF にすることで、通常通りの表示に切り替わります。
※本当に要らない機能だと製作者本人も自負しております
※利用者からの FB 次第では、粛々と消します
利用上の注意点
「フォロー中」ページ以外での利用について
Twitter は SPA なので、他のページに移動してもボタンは残るようになってます。
もちろん、別のページでもボタンを押すと、スクリプト通りの処理は実行されます。
しかし、「プロフィール」→「フォロー中」のページでなければ、厳密には「片思い」や「両思い」の定義からは外れるためご了承ください。
例:「フォロワー」の画面でも、「両思い HIGHLIGHT: ON」にすることで、「フォローされています」が「両思いです♡」に切り替わりますが、それは必ずしも「両思い」とは限りません
(真面目にこの文章を打っていることが馬鹿らしくなってきました。。。)
サポートブラウザについて
Chrome のみです! (動確したのは)
Firefox については CSP の関係上利用不可です。(試しに使ってみたら OOM 発生したんでお気を付けください)
「Firefox で使いたい!」ていう要望が多数あればこのアプリを拡張機能に進化させることも検討しますが、まぁそこまで需要はないでしょう。。
その他のブラウザについては調べてすらいません!(怠惰!!)
インストール方法
スクリプトは以下からインストールできます。
なお、このスクリプトをインストールするには、Tampermonkey 等の拡張機能のインストールが必要です。
まだインストールしていない方は、ブラウザの拡張機能からインストールしてください。
スクリプト紹介
上記のリンクでも確認できますが、こちらにも転記しておきます。
// ==UserScript==
// @name Twitter (X) 片思い表示
// @namespace https://kuds.win/
// @version 1.0
// @description Twitter (X) で片思いフォロー中のアカウントのみを表示できます。また、両思いフォロー中のアカウントは強調表示できます。
// @author KUDs
// @match https://twitter.com/*
// @grant none
// @license GPL-3.0-or-later
// ==/UserScript==
(function () {
"use strict";
// デフォルトは非表示&ハイライト無し
let isHiding = false;
let isHighlighting = false;
// ボタン作成時に共通スタイル適用
function createStyledButton(text, clickHandler) {
const button = document.createElement("button");
button.textContent = text;
// 共通スタイル
Object.assign(button.style, {
border: "none",
borderRadius: "20px",
padding: "10px 20px",
marginTop: "10px",
cursor: "pointer",
transition: "filter 0.3s, transform 0.3s",
});
button.addEventListener("mouseover", () => {
Object.assign(button.style, {
filter: "brightness(1.25)",
transform: "scale(1.05)",
});
});
button.addEventListener("mouseout", () => {
Object.assign(button.style, {
filter: "brightness(1)",
transform: "scale(1)",
});
});
button.addEventListener("click", clickHandler);
return button;
}
// hide button click ハンドラ
function handleHideButtonClick() {
isHiding = !isHiding;
hideButton.textContent = isHiding ? "片思い ONLY: ON" : "片思い ONLY: OFF";
hideButton.style.backgroundColor = isHiding ? "skyblue" : "gray";
updateDOM();
}
// highlight button click ハンドラ
function handleHighlightButtonClick() {
isHighlighting = !isHighlighting;
highlightButton.textContent = isHighlighting
? "両思い HIGHLIGHT: ON"
: "両思い HIGHLIGHT: OFF";
highlightButton.style.backgroundColor = isHighlighting ? "pink" : "gray";
updateDOM();
}
const hideButton = createStyledButton(
"片思い ONLY: OFF",
handleHideButtonClick
);
hideButton.style.backgroundColor = "gray";
const highlightButton = createStyledButton(
"両思い HIGHLIGHT: OFF",
handleHighlightButtonClick
);
highlightButton.style.backgroundColor = "gray";
highlightButton.style.display = "none";
// ボタン配置の初期化
function initializeButtons() {
const targetNavElement = document.querySelector(
'[data-testid="SideNav_NewTweet_Button"]'
);
if (targetNavElement) {
const parentNavElement = targetNavElement.parentNode;
if (parentNavElement && !hideButton.parentNode) {
parentNavElement.appendChild(hideButton);
parentNavElement.appendChild(highlightButton);
}
}
}
// UserCellの表示/非表示の更新
function updateUserCellVisibility(node) {
if (
node.textContent.includes("フォローされています") ||
node.textContent.includes("両思いです♡")
) {
node.style.display = isHiding ? "none" : "";
}
}
// userFollowIndicatorの表示の更新
function updateFollowIndicator(node) {
if (
node.textContent.trim() === "フォローされています" ||
node.textContent.trim() === "両思いです♡"
) {
const spanElement = node.querySelector("span");
if (isHighlighting) {
node.style.backgroundColor = "pink";
spanElement.textContent = "両思いです♡";
} else {
node.style.backgroundColor = "";
spanElement.textContent = "フォローされています";
}
}
}
// DOMのアップデート
function updateDOM(mutationsList = []) {
// 既存のDOMノードに対する更新を追加
const userCells = document.querySelectorAll('div[data-testid="UserCell"]');
userCells.forEach(updateUserCellVisibility);
const userFollowIndicators = document.querySelectorAll(
'[data-testid="userFollowIndicator"]'
);
userFollowIndicators.forEach(updateFollowIndicator);
for (let mutation of mutationsList) {
if (mutation.addedNodes && mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach((node) => {
// SideNavへのボタン追加
if (
node.matches &&
node.matches('[data-testid="SideNav_NewTweet_Button"]')
) {
initializeButtons();
}
// UserCellとuserFollowIndicatorの処理
if (node.matches && node.matches('div[data-testid="UserCell"]')) {
updateUserCellVisibility(node);
}
if (
node.matches &&
node.matches('[data-testid="userFollowIndicator"]')
) {
updateFollowIndicator(node);
}
});
}
}
// highlightButtonの表示/非表示
highlightButton.style.display = isHiding ? "none" : "";
// ボタン配置を再確認
initializeButtons();
}
const observer = new MutationObserver(updateDOM);
observer.observe(document.body, {
childList: true,
subtree: true,
});
// スクリプトの最後で初期化関数を実行
initializeButtons();
})();
※ただし、ブログ上のスクリプトはメンテナンスしない可能性があるため、最新のスクリプトはリンクからインストール・確認してください。
Release Note
version 1.1
- X アイコン追加
version 1.2
- 片思い表示の不具合修正
- @match に x.com 追加
- twitter.com -> x.com へのドメイン移管が完了したようなのでこのタイミングで対応しました。
さいごに
正直、作っているときは「こんなもの誰に需要があるんだ。。」と半信半疑でした。
しかし、作り終えて、いざ自分のリア垢の方で使ってみると、意外とアリでした。
というのも、片思い中のアカウントをフィルターすると、「以前住んでた家の近くのカラオケ店」とか、「大学入学時にフォローしてたよくわからんサークル」とかが出てくるんですよね。
そのため、意外とフォロー整理が捗る捗る。
結果、痒い所に手が届く系ツールにはなれたんじゃないかと思います。
痒い所がある方は是非使ってみてください。
(といっても、一通りフォロー整理が済んだら、ボタンが目障りでしかないので、速攻でスクリプトを無効に切り替えたんですが。。)
以上です。
コメント
2024/5/14現在、Xの片思い表示ボタンを押しても反応しなくなってしまいました。
反応遅れてしまいすみません!
既にご確認済みでしたら恐縮ですが、ver 1.2 にアップデートすれば解消するかと思います!
下記 URL からアップデートをお試しください!
https://greasyfork.org/ja/scripts/475224-twitter-x-%E7%89%87%E6%80%9D%E3%81%84%E8%A1%A8%E7%A4%BA
2024/7/27 現在、最新版を利用してもボタンが現れません。
対応していただけると嬉しいです。
ご連絡ありがとうございます!
確認しましたが、当方の環境では事象が再現できておりません。
まずはキャッシュの削除、ブラウザのスーパーリロードで事象が改善するかご確認いただけますと幸いです。
もし改善しない場合、お手数ですが事象再現時の「URL (ドメインのみで可)、ブラウザのバージョン、Twitter (X) 片思い表示のバージョン、OS」をお知らせください。
もし複数の環境で再現している場合は、上記の情報を複数いただけると大変助かります。