deno-puppeteer と GitHub Actions で LeetCode の ストリーク をREADMEに掲載する
最近、アルゴリズムとデータ構造の勉強のために、LeetCode を 1 日 1 問解いています。今朝ふと LeetCode のストリークを GitHub の README に載せたいなと思い立ちやってみました。
🦾 作ったもの
以下画像のように LeetCode のプロフィールページのストリークと回答問題数を、 GitHub リポジトリの README.md に掲載するスクリプトを作りました。
ダークモードにも対応しています。
Easy しかほぼ解いていないところに実力ががが... 🥹
🛠️ 仕組み
仕組みはとてもシンプルです。
以下一覧の処理を GitHub Actions の cron で定期実行しています。
- LeetCode のプロフィールページの画像を撮影しファイルとして保存
- README.md を更新
- 変更をコミット
コードはすべてこちらにあります。
1. deno-puppeteer でのスクリーンショットの撮影
LeetCode のプロフィールページの撮影には deno-puppeteer を利用しています。
xpath で対象要素(ストリークと、回答問題)を指定してスクリーンショットを撮影し、指定のフォルダーに保存しています。
ポイントは、通常用と dark モード用の 2 枚を撮影している点です。
dark モードの切り替えは html タグのdark
クラスの付け替えで行っています。
emulateMediaFeaturesという API でできるという記事もあったのですが、LeetCode の画面の場合、それではうまく動かずこちらの方法にしました。
await page.evaluate((html) => {
html.classList.add("dark");
}, await page.$("html"));
await streakElement?.screenshot({ path: `images/${name}_dark.png` });
またスクリーンショットの解像度をあげるため大きめの viewport にして、さらにdeviceScaleFactor を調整しています。
await page.setViewport({
width: 1920,
height: 1080,
deviceScaleFactor: 2,
});
2. README の更新
README の更新はこちらの関数で行っています。
あらかじめ README.md に記載しておいた以下のマーカーコメントを、画像タグと更新日時のテキストを使って置き換えることでデータを更新しています。
<!--START_SECTION:leetcode-streak-updated-time-->
<!--END_SECTION:leetcode-streak-updated-time-->
dark モードで画像を切り替えるために、<picture>
タグの media 属性にprefers-color-scheme
を指定しています。
<a href="https://leetcode.com/${user}/" target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./images/problems_dark.png" width="500">
<img alt="" src="./images/problems.png" width="500">
</picture>
</a>
3. GitHub Actins での定期実行
1, 2 の処理を実行するスクリプトを定期実行し、差分をコミットする GitHub Actions を作っています。
deno-puppeteer の実行のための Chromium のインストールが必要なので注意です。
- name: Install Puppeteer
run: PUPPETEER_PRODUCT=chrome deno run -A --unstable https://deno.land/x/puppeteer@16.2.0/install.ts
- name: Capture streak
run: PUPPETEER_PRODUCT=chrome deno task run
env:
LEET_CODE_USER_NAME: kawamataryo
変更差分の Commit は、EndBug/add-and-commitを使っています。
default_author をgithub_actions
とすれば、勝手に bot ユーザーでコミットをしてくれるのはとても便利ですね。
- uses: EndBug/add-and-commit@v9
with:
default_author: github_actions
最後に 1 日 1 回 GitHub Actions の cron で実行されるように設定すれば完成です。
on:
push:
branches:
- main
schedule:
- cron: '0 0 * * *'
おわりに
deno の開発体験が素晴らしく思いのほかサクサク進みました。
後で時間がとれれば、もっと手軽に利用できるよう GitHub Actions のカスタムアクションとして作り直し、GitHub Marketplace に公開したいです。
Discussion