ちゃなべの備忘録

ほぼ備忘録です。

「あれ?前回何やったっけ?」をなくす拡張機能【備忘録】

はじめに

いまこのようにhatenablogを書いているのはいくつか理由があります。
「アウトプットすることで、自身の理解の向上に繋げる」. 「誰かの参考になって欲しい」. など。

そして、「やったことを記録することで、前回どこまでやったかをするに思い出すようにしている」 というのもあります。

しかしこれ、googleの検索履歴とgithubのログからAIに分析してもらって、「前回ここまでやったよーー!」といってもらえるようにできないかな。と思いました。じゃあ作ってみましょう。

前提理解

  • googleの検索履歴からデータを取得して、それをchatGPTのAPIに流して学習させて、概要を表示する
  • もし「isDeveloper」をオンにしたら、githubのcommitメッセージ履歴からも判断させる→commitメッセージモード的な?
  • もし「readCode」をオンにしたら、githubのcommit履歴からも判断させる→codeモード的な?
  • 多分鬼門はgoogleの検索履歴データをちゃんと取得できるかどうか。→これがもしchrome拡張機能しか無理なら、それで作ろう。

調査

どうやらこんなAPIがあるっぽい。

developer.chrome.com

これでサイトの検索履歴が調べられる

あとはChatGPTのAPIはあるだろ。

openai.com

あとgithubAPIもある

qiita.com

いろいろ揃ってはいる。
ホントはこれらを使って事前に「ChatGPTでちゃんとやったことのまとめができるのか」をテストしないといけないと思うんだけど、もうめんどいからやんない。

簡単な拡張機能を作ってみよう

これを参考に簡単なものを作ってみましょう。

yuki.world

まずはアイコンが出てくるだけ

最初にfolerを作って、以下のファイルを作った。階層はこんな感じ。

daily-auto-summary/
└── src/
    ├── manifest.json
    └── popup.html
{
    "name": "HELLO WORLD",
    "description": "chrome拡張機能の基礎",
    "version": "0.0.1",
    "manifest_version": 3,
    "action": {
        "default_popup": "popup.html"
    }
}
<html>
  <body>
    <h1>HELLO WORLD</h1>
  </body>
</html>

じゃあこのfolerをupしてみよう。

chrome拡張機能のページに移動。

(僕はBraveを使っているので、URLはこれですが、それぞれのブラウザの拡張機能のページに行ってください。)

brave://extensions/

これを押して、さっき作成したフォルダの /src を選択する。

すると、できてる!

これの拡張機能をピンドメして、教えてみると、簡単なポップアップが出るようになりました。

h1タグのテキストを取得して表示する

じゃあページのテキストから取得してポップアップに表示してみる。

最終的にこんな感じ。(詳しいことは参考ページに書いてあるから見てみて)

daily-auto-summary/
└── src/
    ├── content.js
    ├── manifest.json
    ├── popup.html
    └── popup.js
{
  "name": "HELLO WORLD",
  "description": "chrome拡張機能の基礎",
  "version": "0.0.1",
  "manifest_version": 3,
  "action": {
    "default_popup": "popup.html"
  },
  "content_scripts": [
    {
      "js": ["content.js"],
      "matches": ["https://qiita.com/*"]
    }
  ]
}
<html>
  <body>
    <h1>HELLO WORLD</h1>
    <input type="text" id="title">
    <button id="btn">text change</button>
    <button id="btn_get">get</button>
    <script src="popup.js"></script>
  </body>
</html>
document.getElementById('btn').addEventListener('click', () => {
  document.querySelector('h1').textContent = document.getElementById('title').value;
})

document.getElementById('btn_get').addEventListener('click', () => {
  chrome.tabs.query( {active:true, currentWindow:true}, (tabs) => {
    chrome.tabs.sendMessage(tabs[0].id, {message: 'getname'}, (content) => {
      if(!content){
        alert('Cannot Get! Try Reload First!');
        return;
      }
      document.getElementById('title').value = content
    });
  });
});
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  let title = document.getElementsByTagName('h1')[0].textContent
  sendResponse(title);
});

これでQiitaの詳細ページのh1タグを取得できるよ。

chromeAPIで検索履歴を取得する

じゃあやってみよーー

まずは、chrome.historyを使えるようにするために、manifest.jsonを修正

+   "permissions": [
+     "history"
+   ],

これで使えるようになったらしい。

次に履歴を表示するためにpopup.htmlを修正

+     <button id="getHistory">getHistory</button>
+     <div>
+       <ul id="historyBox">
+       </ul>
+     </div>

じゃあpopup.jsでchrome.historyを呼び出す。 以下の記述を追加

document.getElementById('getHistory').addEventListener("click", async() => {
  const now = new Date();

  const text = "";
  const startTime = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1, 0, 0, 0).getTime();
  const endTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0).getTime();
  const maxResults = 10;
  const historyItems = await chrome.history.search({
    text,
    startTime,
    endTime,
    maxResults,
  });

  console.log(historyItems);

  const ul = document.getElementById('historyBox');
  historyItems.forEach((item) => {
    const li = document.createElement('li');
    li.setAttribute("id", item.id);
    li.setAttribute("key", item.id);
    li.innerHTML = item.title;
    ul.appendChild(li);
  })
})

おおーこれを反映すると取得することができた。

履歴見られるの恥ずかしいね。

GithubAPIでcommit履歴を取得する

手順は以下のように。

  1. アクセストークンを手動で取得して、そのアクセストークンをもとに自身のアカウントのすべてのレポジトリの、すべてのコミット履歴を取得できるか確認
  2. アクセストークンをOAuthなどで取得できるように修正

すべてのコミット履歴を取得する。

まず手動でアクセストークンを発行する。手順は以下。(ChatGPTで取得したけど、これでできることを確認済み)

  • GitHubにログインし、右上のユーザーアイコンをクリックします。
  • ドロップダウンメニューから「Settings」を選択します。
  • 左側のパネルから「Developer settings」をクリックします。
  • 「Personal access tokens」をクリックします。
  • 「Generate new token」ボタンをクリックします。
  • 「Note」に適当な名前を付け、有効期間を設定します。その後、必要な権限を選択します。この場合、「repo」の全ての権限を選択します。
  • 最後に「Generate token」ボタンをクリックします。新しいページに表示されたトークンをメモしてください。このトークンは再度表示されません。

これを使って、1. プライベートレポジトリを取得できるか 2. プライベートレポジトリのコミット履歴を取得できるか を確認する。

# さっき取得したトークンを変数に代入
$ token="your_personal_access_token"

# 1. プライベートレポジトリのみ取得
$ curl -H "Authorization: token $token" https://api.github.com/user/repos | jq -r '.[] | select(.private == true) | .name'

プライベートレポジトリ1
プライベートレポジトリ2
...

# 2. プライベートレポジトリのコミット履歴
$ curl -H "Authorization: token $token" https://api.github.com/repos/{owner}/{プライベートレポジトリ名}/commits

コミット履歴

# 5つのコミットのコミット名だけ取得
$ curl -H "Authorization: Bearer $token" https://api.github.com/repos/ayumu-1212/dnn_of_crystal_grain_diameter_distributional/commits\?per_page\=5 | jq -r '.[] | .commit.message'

できたので、これを拡張機能上でできるようにする。

<html>
  <body>
    <h1>HELLO WORLD</h1>
    <input type="text" id="title">
    <button id="btn">text change</button>
    <button id="btn_get">getH1</button>
+    <button id="getHistory">getHistory</button>
    <button id="getCommits">getCommits</button>
    <div>
      <ul id="historyBox">
      </ul>
    </div>
+    <div>
+      <ul id="commitsBox">
+      </ul>
+    </div>
    <script src="popup.js"></script>
  </body>
</html>
// 追加
document.getElementById('getCommits').addEventListener("click", async() => {

  const token="sample_token"

  const maxResults = 5;
  const commitItems = []

  await fetch(`https://api.github.com/repos/ayumu-1212/dnn_of_crystal_grain_diameter_distributional/commits?per_page=${maxResults}`, {
    headers: {
      Authorization: `token ${token}`
    }
  })
  .then(response => response.json())
  .then(data => {
    data.forEach(d => {
      commitItems.push(d.commit.message)
    });
  })
  .catch(error => console.error(error));

  const ul = document.getElementById('commitsBox');
  commitItems.forEach((item, index) => {
    const li = document.createElement('li');
    li.setAttribute("id", `commit-${index}`);
    li.setAttribute("key", `commit-${index}`);
    li.innerHTML = item;
    ul.appendChild(li);
  })
})

これで、拡張機能を開いて、ボタンを押すと。

いいですねぇ、プライベートレポジトリのcommit履歴を取得できています。

アクセストークンをOAuthとかで取得する

これはFirebaseログイン機能を実装して、そこでアクセストークンを発行すれば可能になりそう。

Firebaseでプロジェクトを作成して、Authenticationを開始する。

Sign-in-methodでGithubを選択し、表示されたCallbackURLをコピーする。

GithubのSettings / Developer Settingsを開き、OAuth Appsで[New OAuth App]を押す。

必要な情報を入力し、Authorization callback URLと表示されているところに、FirebaseでコピーしたURLを貼り付けて、完了する。

すると、クライアントIDクライアントシークレットが表示されるので、Firebaseに入力して[保存]をする。

次にブラウザの拡張機能の設定ページに行き、IDをコピーする。

Firebase / Authentication / Settingを開き、[ドメインの追加]を押す。

そこに先程コピーした拡張機能のIDを使って、 chrome-extension://CHROME_EXTENSION_ID と入力して、[追加]する。

と、ここまで作ってみて、「拡張機能を作るのに、テンプレートなしだときつい」という結論に至った。よって、chrome拡張機能を作成するテンプレートを使う。

plasmoの利用

ちょっと探してみたが、なんかこれしかなさそうだった。

www.plasmo.com

ちょっと使ってみよう。

ayumu1212.hatenablog.com

いいねぇ、使ってみたけど悪くない。

あとこれも読んだ。いいね。

zenn.dev

この段階でわかったことをまとめる。

  • manifestのバージョンによって書き方が結構違う (参考:Zenn)
  • plasmoが問題かと思ったけど、manifestバージョンが3になったことでfirebaseとの互換性がゴミになってる。
That worked. Thank you. For other people that might have this problem, Manifest v3 prohibits the loading external scripts in the script-src directive - all external scripts must be included in the application itself.
引用元:stack overflow

akita, gomen

参照

  • chromeのボイラーテンプレート

github.com

  • manifest ver3の書き方

qiita.com

  • chromeからのログイン機能(公式)

cloud.google.com

  • firebaseでのGithubのログイン機能実装

firebase.google.com