Project Fx 2.0

怪文書と備忘録を書きます

GitHub API v3で「自分がstarを付けたリポジトリの一覧」を取得する

表題のとおりです。
自分がstarを押したGitHubリポジトリのURLをChromeのブックマークに追加したくなったので、GitHub側で用意されているREST APIを使って情報を取得することにしました。
個人的な備忘録も兼ねて、順を追って方法を解説します。

1. 任意のユーザーの情報を取得するREST APIを使い、自分が押したstarの情報を取得する

1-1. star情報取得APIの叩き方

curl

curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/users/stepney141/starred

wget

wget --no-check-certificate --header="Accept: application/vnd.github.v3+json" -q -O - https://api.github.com/users/stepney141/starred

このように、 GET api.github.com/users/ユーザー名/starred が該当するエンドポイントとなります。上の例では私のアカウントを指定しています。
情報は普通にjsonで返ってきます。エンドポイント自体の詳しい仕様は、下記参考文献 1.を参照してください。

1-2. とりあえずこうやればOK

curlの使い方をよく知らないので、個人的に使い慣れているwgetを使って叩いてみます。APIというと何かとcurlが使われがちですが、wgetでも普通に行けます。

#!/bin/bash
wget --no-check-certificate \
    --header="Accept: application/vnd.github.v3+json" \
    -q -O - \
    https://api.github.com/users/stepney141/starred\?per_page=100\&page={1..3} \
    | jq add -s \
    | jq '.[] | [ .full_name, .html_url, .description ] | @csv' -r \
    > stars_repo.txt

処理の流れとしては
Bashのブレース展開を使用し、wgetjsonを一気に3つ入手
-> jqに渡して結合
-> さらにjqに渡して『リポジトリ名』『ブラウザ用URL』『リポジトリ説明文』のみを抽出、CSV
-> txtに出力」
という感じです。

wgetのオプションについて:
--no-check-certificate:接続先のSSL証明書のチェックを切る。wgetSSL関連エラーはこれをつければとりあえず全て解決する
-qwgetからのシステム出力(エラー表示やダウンロード情報など)を全てミュートする
-O -:ダウンロードした内容を標準出力に流す

補足事項

  • ?と&のエスケープは必須
  • GitHub側でのstar数表示は225個(2020-08-17時点)なので、とりあえず100件ずつ3回叩けばOK
  • 1度に取得できるのは最大100件まで

2. 現在認証中のユーザーの情報を取得するREST APIを使い、同じことをする

さて、上の手順ではprivate repositoriesの情報が取得できません。なので、認証してprivate repositoriesの情報も取れるようにします。
というのも、GitHubのユーザーページの表示では「この人は225個のstarを押してますよ」と出ていたにも関わらず、上のAPIで私が取れたのは224個だけだったのです。
このため「もしかしてprivate repositoryが抜けてるのかな?」と考え、認証して試してみることにしました。

GitHubの認証方法にはいくつかあるようですが、今回はネットですぐ情報が集まり、なおかつTwitter APIで触ったことのあるOAuth Appを使うことにしました。

2-1. OAuth Appの認証のやり方

※出典:下記参考文献3.と4.

その1.

https://github.com/settings/applications/new からGitHubアカウントに紐付けられたOAuth Appを作成し、Client IDとClient Secretを入手する。

※Client ID 、Client Secretはそれぞれ環境変数 CLIENT_ID 、CLIENT_SECRET として保存しておくことを推奨します。
※Callback URLの設定は必須です。ぶっちゃけ何のURLを入れようと問題ないっぽいが、一応自分が保有/管理しているURLを使う方がいいかも? 自分は自身のgithub.ioのURLを入力しました。

その2.

https://github.com/login/oauth/authorize?client_id=$CLIENT_ID&scope=repo にブラウザでアクセスする。
そうするとApp Authorizationの画面が出てくるので、ボタンを押して承認する。

その3.

ボタンを押して承認すると、 https://stepney141.github.io/?code=0123456789abcdefg みたいな感じで、自分が指定したCallback URLにリダイレクトされる。
末尾にqueryとしてぶら下がっているCodeをコピペしておく。
※Codeは環境変数 CODE として保存しておくことを推奨します。

その4.

Code、Client ID、Client Secretを https://github.com/login/oauth/access_token にPOSTする(以下はcurlでの例)。
※この例ではCode、Client ID、Client Secretの情報がBash環境変数として保存されていることを想定しています。適当に読み替えられたし。

curl -X POST \
    -d "code=$CODE" \
    -d "client_id=$CLIENT_ID" \
    -d "client_secret=$CLIENT_SECRET" \
    https://github.com/login/oauth/access_token

その5.

POSTすると access_token=0123456789abcdef0123456789abcdef01234567&token_type=bearer というような形式でアクセストークンが返ってくる。
これをリクエストヘッダに入れてAPIを叩く。
※アクセストークンは例によって環境変数 ACCESS_TOKEN として保存しておくことを推奨

2-2. とりあえずこうやればOK

GET api.github.com/user/starred が今回の目的に合致するエンドポイントです。詳細は下記参考文献2. を参照してください。

下に私が使った入力を示します。例によってwget環境変数を使っているので、適当に読み替えて下さい。

#!/bin/bash
wget --no-check-certificate \
    --header="Accept: application/vnd.github.v3+json" \
    --header="Authorization: bearer $ACCESS_TOKEN"\
    -q -O - \
    https://api.github.com/user/starred\?per_page=100\&page={1..3} \
    | jq add -s \
    | jq '.[] | [ .full_name, .html_url, .description ] | @csv' -r \
    > stars_repo_auth.txt

これはエンドポイントが変わっただけで、処理の内容自体は上の例と全く変わっていません。
エンドポイントの詳しい仕様は下記参考文献 2.を参照してください。

で、結局このエンドポイントを使っても取れたリポジトリは224個のまま変わりませんでした。つまり、妖怪いちたりないの正体はプライベートリポジトリではありませんでした。
原因は何なのか、結局この取れなかった1個の正体は何だったのかは不明です。
個人的にはGitHub側のバグを疑ってます(実は224個が正しい数字で、GitHubの表示自体が間違っている説)。

とりあえずこの224個を手作業でChromeブックマークに追加するのは御免蒙りたいところですので、Chrome拡張機能を作ってどうにかしようと考えています。作業完了したらまた備忘録を書きます。

その後

starしたGitHubリポジトリの情報や上で書いたワンライナーは、全部まとめてGitHubリポジトリとして管理することにしました。(Git運用法としてはEvil感がありますが)とりあえずシェルスクリプトスクリプトを実行してパスワードを入力する度にリポジトリの最新情報がpushされるようにしています。

github.com

参考文献

  1. https://docs.github.com/en/rest/reference/activity#list-repositories-starred-by-a-user
  2. https://docs.github.com/en/rest/reference/activity#list-repositories-starred-by-the-authenticated-user
  3. https://qiita.com/ngs/items/34e51186a485c705ffdb
  4. https://qiita.com/developer-kikikaikai/items/5f4f0e2ea274326d7157