気になるページに関するtweetを１クリックで検索するChrome Extensionを作ってみた

Web上で面白い記事を見つけたとき、twitterで他に誰かつぶやいてないかなー、どんなことつぶやいてるかなーと気になることありませんか？
twitterの検索機能にURLをブッ込めば検索できるんですが、それも手間なんでChrome拡張（Chrome Extension）を作ってみました。

# 完成品
![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254216/117342f1-1966-e815-26cd-7b1e4da1035b.gif)
こんな感じにワンクリックでそのページのリンクが貼ってあるtweetを検索したページに遷移する。

ソースコードは[GitHub](https://github.com/at946/search_tweets_about_this_page_chrome_extension)にあります。

# 作るよ
Chrome extensionの基本の作り方はいろいろな方の記事を参考にさせていただきました。

- [Chromeブラウザの拡張機能を作ってみたい初心者向けに開発方法を紹介！【サンプルあり】 - Qiita](https://qiita.com/guru_taka/items/37a90766f4f845e963e5)
- [Chrome拡張の作り方 (超概要) - Qiita](https://qiita.com/RyBB/items/32b2a7b879f21b3edefc)
- [Chrome拡張機能の作り方｜コラム｜メンバーズ](https://blog.members.co.jp/article/37615)
- [Google Chromeのアイコンをクリックで実行する拡張機能の作り方](https://toolmania.info/post-8510/)
- [Chrome Extension の作り方 (その1: 3つの世界) - Qiita](https://qiita.com/sakaimo/items/416f36db1aa982d8d00c)

このあたりのサンプルありの記事を参考にサンプルアプリを言われた通りに作ることからはじめました。
で、なんとなくの感覚を掴んだら実際に今回作りたかったchrome extensionの開発を開始！

## `manifest.json`を書く
chrome extensionのベースの設定ファイル`manifest.json`を作ります。

```json:manifest.json
{
  "name": "Search tweets about this page",
  "description": "You can search tweets about this page only one click.",
  "manifest_version": 2,
  "version": "1.0",
  "browser_action": {},
  "background": {
    "scripts": [ "jquery.min.js", "scripts.js" ],
    "persistent": false
  },
  "permissions": [
    "tabs"
  ]
}
```
書き方は「[Chrome 拡張機能のマニフェストファイルの書き方 - Qiita](https://qiita.com/mdstoy/items/9866544e37987337dc79)」にきれいにまとめられています。

大切なところは以下。

- `background.scripts`で`jquery.min.js`と`scripts.js`を読み込んでる
- `permissions`で`tabs`を指定してchrome extensionが実行されたときのタブの情報を取得できるようにしてる

## `jquery.min.js`をダウンロード
`scripts.js`でjQueryを使うために`jquery.min.js`を[公式サイト](https://jquery.com/download/)からダウンロードしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254216/032bec5a-c765-d89c-7fbd-798bd5638674.png)
なんかまぁこんな感じでリンクがあるので「Download the compressed, production」のやつを選びましょう。
そうするとえげつない文字列のページにとばされると思うので全文コピーして`jquery.min.js`って名前で保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254216/6b1b0cee-ba7c-85f2-45ec-76c321d1cdfb.png)

## `scripts.js`を書く
で、これがほぼ実態となる`scripts.js`を記述していきましょう！

まずちょっと戦略を。
今回、「今閲覧しているサイトのURLをTwitterの検索窓で検索する」、ということをしようとしています。
Twitterの検索窓の検索は、実はURLパラメーターを使ってやっているだけなんですよね（参考: [Using standard search — Twitter Developers](https://developer.twitter.com/en/docs/tweets/search/guides/standard-operators)）
参考の公式サイトにも書いてある通り、例えば「twitterdev new premium」を検索したい時は、[https://twitter.com/search?q=twitterdev%20new%20premium](https://twitter.com/search?q=twitterdev%20new%20premium)にアクセスすればいいだけとなります。`%20`はスペース（" "）をURLエンコードした値なのでURLエンコードが必要なことがわかりますね。

なので、今回は今閲覧しているサイトのURLを`https://xxxxxxxxxx.com/`だとした場合、それをURLエンコードした値を`http://twitter.com/search?q=`の後に連結したURLを別タブで開かせればいいことになります。

この戦略でコーディングをすると、`scripts.js`を以下のように記述することができます。

```js:scripts.js
function search_tweets () {
  chrome.tabs.getSelected(tab => {
    target_url = "https://twitter.com/search?q=" + encodeURIComponent(tab.url)
    window.open(target_url, '_blank')
  })
}

$(function() {
  chrome.browserAction.onClicked.addListener(search_tweets)
})
```
超少量の記述である。

ちょっと解説。

```js
$(function() {
  chrome.browserAction.onClicked.addListener(search_tweets)
})
```
最後の３行、この部分でchrome extensionのアイコンがクリックされたことをトリガーにして`search_tweets`ファンクションを実行します。

```js
function search_tweets () {
  chrome.tabs.getSelected(tab => {
    target_url = "https://twitter.com/search?q=" + encodeURIComponent(tab.url)
    window.open(target_url, '_blank')
  })
}
```
それで呼び出される`search_tweets`ファンクションがこちらですね。

```js
chrome.tabs.getSelected(tab => {
  ...
})
```
で現在開いているタブの情報を変数`tab`から取得できるようにしています。（参考: [[ChromeExtension] 表示しているタブのURLを取得するサンプル | Tips of Rubbish](http://wordpress.ideacompo.com/?p=6895)）

```js
target_url = "https://twitter.com/search?q=" + encodeURIComponent(tab.url)
```
ここでtwitter検索のURLを生成しています。
大切なのは、`encodeURIComponent(tab.url)`の部分。
`chrome.tabs.getSelected(tab)`のおかげで`tab.url`で今閲覧しているページのURLを取得できるようになっています。
`encodeURIComponent`は文字列をURLエンコードしてくれる便利な関数です。（参考: [escape と encodeURI と encodeURIComponent を正しく使い分ける](https://aloerina01.github.io/blog/2017-04-28-1)）

これで`target_url`にアクセスすれば、今閲覧しているページを検索キーワードとしてtweetを検索できるようになるので最後に、`window.open(target_url, '_blank')`で別タブでそのURLにアクセスさせています。（参考: [jQueryを使って遷移先リンクを別タブで開く - Qiita](https://qiita.com/mochitech/items/2b1e119e2561b8aab937)）

### クエリパラメーターにWeb解析用のパラメーターがあるとうまく挙動しない
ここまでのコードで`chrome://extensions/`でコードを読み込んでやればやりたいことができるようになったんです。
ただちょっと落とし穴で、今って例えばGoogle analyticsで流入元を調査するためだったりでクエリパラメーターにいろいろなコードがついているリンクって多いんですよね。
例えば`https://xxxxxxxxxx.com?magazine_no=xxxxxxxxxx`みたいな。
この場合そのページ自体は`https://xxxxxxxxxx.com`までで十分で、tweetでもこっちでつぶやかれているので`https://xxxxxxxxxx.com?magazine_no=xxxxxxxxxx`で検索してもヒットしないってことがあります。

なので、クエリパラメーター以降を削除するように`scripts.js`を書き換えました。
クエリパラメーターは`?`以降に記述するルールなので`tab.url`の文字列を`?`で分割して、前半部分だけを`target_url`に連結します。

```js:scripts.js
function search_tweets () {
  chrome.tabs.getSelected(tab => {
    base_url = tab.url.split("?")[0]
    target_url = "https://twitter.com/search?q=" + encodeURIComponent(base_url)
    window.open(target_url, '_blank')
  })
}

$(function() {
  chrome.browserAction.onClicked.addListener(search_tweets)
})
```
変更点は

```js
base_url = tab.url.split("?")[0]
target_url = "https://twitter.com/search?q=" + encodeURIComponent(base_url)
```
この２行です。
まず、`tab.url.split("?")[0]`で今開いているページのURLの`?`より前のURLを`base_url`に代入しています。（参考: [jQueryで文字列を分割したり、特定の文字以降を削除する | フロントエンド | kigiroku](https://kigiroku.com/frontend/jquery_split.html)）
そして、`encodeURIComponent`の対象を`tab.url`から`base_url`に変更することで無駄なクエリパラメーターを除外してtweet検索ができるようになりました！

### 更なる落とし穴、クエリパラメーターでページを指定してる場合もある
これで行けるかなとも思ったんですけどね...
サイトの中には`https://xxxxxxxxxx.com?id=xx`みたいな形式でクエリパラメーターで表示するコンテンツを指定しているサイトもありました...
あれ、これはもうどっちかを救えばどっちかを救えないパターン...

と悩んだんですが、Twitterの検索機能にはOR検索があったので、もうクエリパラメーターあり版もなし版も両方検索してしまおうという結論に至りました。
TwitterのOR検索は「キーワードA OR キーワードB」って形で複数のキーワードの間に`OR`を入れることでどちらかにヒットするtweetを検索してくれます。

ということで、最終版の`scripts.js`がこちらです。


```js:scripts.js
function search_tweets () {
  chrome.tabs.getSelected(tab => {
    base_url = tab.url.split("?")[0]
    target_url = "https://twitter.com/search?q=" + encodeURIComponent(base_url) + "%20OR%20" + encodeURIComponent(tab.url)
    window.open(target_url, '_blank')
  })
}

$(function() {
  chrome.browserAction.onClicked.addListener(search_tweets)
})
```

変更点は`target_url`のところで、`+ "%20OR%20" + encodeURIComponent(tab.url)`を追記しています。
`%20`は先ほども出てきましたがスペースのURLエンコードされた文字列です。ので最終的には「<b>クエリパラメーターを削除したURLをエンコードした文字列 OR クエリパラメーターを含んだURLをエンコードした文字列</b>」を検索キーワードにしていることになります。

完成！！！

## chrome extensionに追加する
これはGitHubのREADMEにもちょっと書きましたが、

1. Chromeで [chrome://extensions](chrome://extensions) にアクセスする（拡張機能ページにいきます）
2. デベロッパーモードをONにする（ページ右上部にあるはず）
3. 「パッケージ化されていない拡張機能を読み込む」をクリックしてソースコードをおいているディレクトリを選択する

で完了です！

# まとめ
初めてのchrome extensionでしたが、コード量の少なさに驚きを隠しきれませんでした。
今回はやっていることも簡単なものなのでというのはありますが、大きくつまずくこともなく行けた感じがする。

成果物については、まだ`id=xxx`と`magazine_no=xxxxx`が混在していたらどうするの？みたいな課題があったりするんですが、chrome extensionでやってみよう！が今回の目的だったりしたのでまぁいいです。笑

エゴサや他の人がどんなコメントしてるか気になるページに出会ったときに、つかってこうと思います♪
成果物 => [at946/search_tweets_about_this_page_chrome_extension: You can search tweets about this page only one click.](https://github.com/at946/search_tweets_about_this_page_chrome_extension)