テックブログ巡回が爆速に！いいね＆フォローを自動化するChrome拡張


## はじめに

こんにちは。[@yug1224（Yuji Yamaguchi）](https://x.com/yug1224)です。

テックブログやLT資料を見ていて、いいねやスターを付けたり、フォローしたりすることってありますよね。

良い記事や資料と出会う度に、何度もクリックするのが面倒だと思ったので、一瞬で完了できるChrome拡張機能を作りました。

## TL;DR

git cloneをして、そのままブラウザに読み込ませてください。

拡張機能のアイコンをクリックするか、Shift+Ctrl+Lのキーボードショートカットで実行できます。（他のショートカットと競合したらChromeの設定から適宜変更してください）

https://github.com/yug1224/social-interaction-booster

| Qiita                             | Zenn                            | note                            | Speaker Deck                                  |
| --------------------------------- | ------------------------------- | ------------------------------- | --------------------------------------------- |
| ![画面収録-Qiita][画面収録-Qiita] | ![画面収録-Zenn][画面収録-Zenn] | ![画面収録-note][画面収録-note] | ![画面収録-SpeakerDeck][画面収録-SpeakerDeck] |
| [Link][Link-Qiita]                | [Link][Link-Zenn]               | [Link][Link-note]               | [Link][Link-SpeakerDeck]                      |

[画面収録-Qiita]: https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106236/61647894-82e2-a6d7-094f-9a9b9076193e.gif
[Link-Qiita]: https://qiita.com/_ken_/items/c5aa4841be74b06530b4
[画面収録-Zenn]: https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106236/14e37219-99a2-ad3c-4868-35bbb6ab3cf6.gif
[Link-Zenn]: https://zenn.dev/hrbrain/articles/731574815d1fb4
[画面収録-note]: https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106236/64f53124-6a57-2e9e-1805-3366f8b9771d.gif
[Link-note]: https://note.com/makedonuts/n/nfec91a622632
[画面収録-SpeakerDeck]: https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106236/210fe14d-4b7c-c427-24a7-a641a9dc2151.gif
[Link-SpeakerDeck]: https://speakerdeck.com/raorao1011/xin-zu-1nian-mu-depjmtokai-fa-ze-ren-zhe-woren-saretahua

## ソースコード

やっていることは単純で、いいね・ストック・フォローの要素を取得し、順番に`click()`を実行しているだけです。

連続でクリックし過ぎると、クリック時の処理がうまく動かない場合があったので、200msの間隔を空けるようにしています。

```js:background.js
// background.js
chrome.action.onClicked.addListener((tab) => {
  chrome.scripting.executeScript({
    target: { tabId: tab.id },
    func: contentScriptFunc,
  });
});

async function contentScriptFunc() {
  // 任意の時間待機する
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

  // ボタンをクリックする
  const click = async (el) => {
    el && (el.click() || console.log(el));
    await sleep(200);
  };

  // Qiitaのいいね、ストック、フォローをクリックする
  const qiitaFn = async () => {
    const a = Array.from(
      document.querySelectorAll(
        'div.p-items_main > div:nth-child(1) button[aria-label="いいねする"],div.p-items_main > div:nth-child(1) button[aria-label="ストックする"]',
      ),
    );
    const b = Array.from(
      document.querySelectorAll('div.p-items_main > div:nth-child(2) button'),
    ).filter((v) => v.textContent === 'フォロー');
    for await (const v of [...a, ...b]) {
      await click(v);
    }
  };

  // Zennのいいね、フォローをクリックする
  const zennFn = async () => {
    const a = document.querySelector('#share button[aria-label="いいね"][class^="LikeButton_button__"]');
    const b = Array.from(
      document.querySelectorAll('div[class^="Container_default__"] button[class^="FollowButton_button__"]'),
    ).filter((v) => v.textContent === 'フォロー');
    for await (const v of [a, ...b]) {
      await click(v);
    }
  };

  // noteのいいね、フォローをクリックする
  const noteFn = async () => {
    const a = document.querySelector('div.p-article__action button[aria-label="スキ"]');
    const b = document.querySelector('#sideCreatorProfile > span > span > button[data-type="primary"]');
    for await (const v of [a, b]) {
      await click(v);
    }
  };

  // Speaker Deckのいいね、フォローをクリックする
  const speakerdeckFn = async () => {
    const a = document.querySelector('.deck a[data-method="post"][href$="/star"]');
    const b = document.querySelector('.deck a[data-method="post"][href^="/connections/"]');
    for await (const v of [a, b]) {
      await click(v);
    }
  };

  // サービスを判別する
  if (location.origin === 'https://qiita.com') {
    await qiitaFn();
  } else if (location.origin === 'https://zenn.dev') {
    await zennFn();
  } else if (
    location.origin === 'https://note.com' || !!document.querySelector('a[aria-label="home"][href="https://note.com/"]')
  ) {
    await noteFn();
  } else if (location.origin === 'https://speakerdeck.com') {
    await speakerdeckFn();
  } else {
    // その他のサイトの場合
  }
}
```

```json:manifest.json
{
  "manifest_version": 3,
  "name": "Social Interaction Booster",
  "description": "",
  "version": "1.0",
  "permissions": ["activeTab", "scripting"],
  "background": {
    "service_worker": "background.js"
  },
  "action": {},
  "commands": {
    "_execute_action": {
      "suggested_key": {
        "default": "Shift+Ctrl+L",
        "mac": "Shift+MacCtrl+L"
      }
    }
  }
}
```

## まとめ

今回は4つのサービスに対応したChrome拡張機能を作成しましたが、他のサービスも同様の方法で対応できると思います。

以上、一瞬でいいねやフォローを完了させるChrome拡張機能の紹介でした。

## PR

HRBrainでは一緒に働く仲間を募集しています。歴史に残るトライをしよう！

https://www.hrbrain.co.jp/recruit