X(旧Twitter)の片思いフォローを整理するブックマークレット「バイバイ片思い」のご紹介

## ~~片思いフォロージェノサイド~~バイバイ片思い for X(Twitter)
X(旧Twitter)でふと、「片思いフォロー、整理したいな〜」って思ったことない？🤔 でもひとつひとつチェックしていくのって、めんどくさいよね😅 そんな時にピッタリなのが、「バイバイ片思いブックマークレット」だよ！

![emo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695403/f8944f3c-547d-c148-3cc2-689c9413f48e.gif)

この記事では、使ってみたいだけの人のために、どうやって使うのかを先にサクッと解説しちゃうね🚀
実際のコードについても後から解説するよ✨

:::note alert
インターネット上で掲載されているプログラムを安易に実行すると酷い目に遭うことがあるから、ちゃんとよく確認してから、気を付けて使うんだよ！
利用は自己責任で！
:::

使い方はめちゃくちゃ簡単で、誰でもすぐにできちゃうから、興味がある人はぜひ最後までチェックしてみてね！そして、このブックマークレットを使って、Xライフをもっと快適にしてね😍🌟

## 使い方😍📘

簡単操作で片思いフォローをキレイさっぱり🧹💨
ブックマークバーに追加したボタンをタップすると、1タップにつき1つ、片思いフォローを解除するよ！

### まずはブックマークレットを追加してみよう🔖

1. Google Chrome を開いて、ブックマークバーをチェック！表示されてなかったら、Chrome の設定からサクッと表示させちゃおう！
2. ブックマークバーで右クリックして、「ページをブックマークに追加...」をポチっとな
3. 名前は、ブックマークバーに表示されるだけだから、好きな名前を入れてね。「全殺」とかでも大丈夫💖
4. URLには下のminifyされたブックマークレットコードをぺたり

``` javascript:URLのところに入れるスクリプトだよ。コピペミスに気を付けて！
javascript:function searchKataomoiAndKill(){var o=window.location.href;if(o.startsWith("https://x.com/")&&o.endsWith("/following")){scrollToTargetDom("//div[@data-testid='cellInnerDiv' and not(descendant::span[text()='フォローされています'])]//span[text()='フォロー中']",(o=>{console.log(o),o.scrollIntoView({behavior:"smooth",block:"center"}),o.click(),setTimeout(sayGoodBye,500)}),0)}else alert("https://x.com/ユーザ名/followingにアクセスしてから実行してね！")}function scrollToTargetDom(o,t,e){let l=document.querySelector("html");var n=document.evaluate(o,document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;n?t(n):(console.log("↓にスクロール"),l.scrollBy({top:.8*window.innerHeight,behavior:"smooth"}),e!=l.scrollTop&&(e=l.scrollTop,setTimeout(scrollToTargetDom,400,o,t,e)))}function sayGoodBye(){document.evaluate("//span[text()='フォロー解除']",document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue.click()}searchKataomoiAndKill();void(0);
```

これで準備OK👌 ブックマークレットが使えるようになったよ！

### 使ってみよう🚀

でもね、使う前にちょっと待った🖐️ このブックマークレット、使う場所がめちゃくちゃ大事！**Xの特定のユーザーのフォロー一覧ページ** ([https://x.com/ユーザ名/following](https://x.com/EmokoMAUI/following)) でしか働かないんだ。間違えないようにね！

準備バッチリなら、ブックマークバー上の(設定した名前)をクリック！自動で片思いフォローを見つけ出して、ポチッとな👆💔

### 注意点をチェック⚠️

- このツールは自動でフォロー解除するから、間違えないようにね！
- 特定のアカウントを対象外にすることはできないよ！(今月中に出来るよう改善する！)
- **Xのページ構造が変わったら、動かなくなるかも...** 本記事公開時点(2024年2月)ではバッチリ動作確認済みだけど、将来的には変わる可能性もあるから、その時はごめんね🙏

# ソースコードについてちょこっと解説🔍

さてさて、このブックマークレットがどんな魔法を使ってるのか、ちょっと覗いてみよう！
chatGPTとペアプロでサクッと作ったから、ES6以降のモダンな書きっぷりにはなってないよ、文法はあてにしないでね🙇
```javascript:ブックマークレット化(minify)する前のソースコードだよ
// 片思い相手を探してkill
function searchKataomoiAndKill() {
    // 現在のページのURLを取得
    var currentUrl = window.location.href;

    // URLがhttps://x.com/で始まり、/followingで終わっているかチェック
    if (!currentUrl.startsWith('https://x.com/') || !currentUrl.endsWith('/following')) {
        alert('https://x.com/ユーザ名/followingにアクセスしてから実行してね！');
        return;
    }
    // XPath式を使って要素を取得
    var xpath = "//div[@data-testid='cellInnerDiv' and not(descendant::span[text()='フォローされています'])]//span[text()='フォロー中']";
    scrollToTargetDom(xpath, (matchingElement)=>{
        console.log(matchingElement);
        matchingElement.scrollIntoView({
            behavior: "smooth",
            block: "center"
        });
        matchingElement.click();
        // 500は解除確認ダイアログを押すまでの待機時間だから、好みで調整してね
        // この行を消せば、チェックだけ行えるよ！
        setTimeout(sayGoodBye, 500);
    }, 0);
}

// 片思い相手を探すよ
function scrollToTargetDom(xpath, callback, ypos) {
    let html = document.querySelector('html');
    var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

    if (matchingElement) {
        callback(matchingElement);
    } else {
        console.log("↓にスクロール");
        // 現在の表示位置から下に画面縦幅分*0.8スクロール
        html.scrollBy({
            top: window.innerHeight * 0.8,
            // 縦幅分スクロール
            behavior: 'smooth'// スムーススクロール
        });
        if(ypos != html.scrollTop){
            ypos = html.scrollTop;
            // 400はスクロール実行間隔だから好きに調整してね
            setTimeout(scrollToTargetDom, 400, xpath, callback, ypos);  
        }
    }
}

// バイバイ実行
function sayGoodBye() {
    document.evaluate("//span[text()='フォロー解除']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.click();
}

searchKataomoiAndKill();
```
### やっていること
- **URLチェック**：まずは、正しいXページにいるかチェック！間違ったページでは使えないからね。
- **片思い探し**：XPathの魔法で、「フォロー中だけどフォローされてない」アカウントを発見！
- **さよなら実行**：見つけたら、そのアカウントをスムーズにフォロー解除。スクロールしながら探すから、見逃し無し！

:::note warn
このブックマークレットは、データを大量に収集したりする意図はなくて、実際のユーザ操作を模倣してるだけだから、スクレイピングには該当しないと思ってるよ😉 だから安心して使ってね！
:::

## 終わりに
自動化してみたいことがあったら、気軽に相談してね🌟