nabeliwo blog

nabeliwo blog は nabeliwo の日々の出来事だったり生活の中で感じたことだったりを雑にお届けします。

GAS で Discord Bot を作る良い感じのアーキテクチャを考えた

Google Apps Script (GAS) で Discord Bot を作るときに色々考えたのでメモ。

経緯

我が家は家族のチャットツールとして Slack を使っていた。
自分も妻も Slack は慣れ親しんでいるし、アプリ連携が豊富で簡単に様々な通知を作れるのも良くて概ね満足していた。
ただ一点、有料にしないと過去ログが見られないのが厳しくて、ふとあの話どうなってたっけと思って Slack を漁ろうとするも見られないので困るということにたまになっている。

その為に有料にするかというのも悩ましい話で、他に無料で使えるツールがいっぱいある中でチャットツールにお金を払い続けるモチベーションがあまり上がらなかった。

ということで、家庭内のチャットツールを過去ログが無料で見られる Discord に移行した。

(決定事項をチャットツールに残して終わっていることが問題であってあとから確認したいこととかであれば何処か別の場所にストックするべきという話もあるがそれは一旦置いておいて…)

Discord 困りポイント

個人的な話ですが、Discord は過去ログの面でも UI の好みという面でも素晴らしいんだけれど、公式で用意されているインテグレーション(App Directory というやつ)が用途にハマるものがあまりなく、基本は Webhook で色々作らないといけない。

もちろん検索すれば Discord の Webhook で色々やるためのツールや、個人で作った人の記事とか無限に出てくるのでそれらを使えば良いんだけど微妙に自分が求めるものとずれていたりするので、参考にこそすれ結局は自分で作らないといけない。

ということで Slack の頃から使っている Bot の中でもとりあえず必須な Google Calendar のスケジュール通知と天気予報の Bot の2つだけでも作ることにした。

GAS で Discord Bot を作る話

GAS って自分の場合は毎回書き捨てのスクリプトで終わってしまうのであまりちゃんと管理せず雑に JavaScript をつらつら〜っと書いて終わりだったんだけれど、どうせなら今回はしっかり管理してメンテしやすい状態に持っていこうかなと考えて良い感じの構成を練ってみた。

@google/clasp を使うのは当然なんだけれど、ディレクトリ構成についてとか複数種類の Bot をまとめて管理したいだとか、いろいろと考えることがあった。

ということで色々考えて作ったのがこれ。
nabeliwo/gas-discord-bots

個別の Bot の実装の話はしないが、全体的な構成について少し詳しく書いていく。

技術の話詳しく

pnpm workspace を使った monorepo 構成にしている。

monorepo のディレクトリとしては botspackages という2つのディレクトリがある。
bots の中は 1 bot 1ディレクトリーという分け方をしていて、今回の場合は bots/google-calendarbots/weather がある。そしてそれぞれが clasp のプロジェクトのルートになっていて、それぞれで GAS にプッシュできる。

今回の場合はどのスクリプトの最終的なアウトプットは Discord へのポストになるので、Discord へのポスト処理は packages の中に一つのパッケージとして作って、それぞれの bot ディレクトリーから参照できるようにしている。
今後他にも共通で使える処理が出てきたら packages の中に増やしていく形。

あとビルド周りについては、言語は TypeScript で書いていて、pnpm の script で push コマンドを叩くとまず TypeScript が esbuild でビルドされて単一の JS ファイルを吐く。その JS ファイルを GAS にプッシュする。
esbuild-gas-plugin っていう便利なプラグインがあって、これを使えばビルドしてプッシュしたときにそれぞれの関数を GAS から実行できるようにしてくれる。

あとはツールの話で、今回はテストは書いていないけれど monorepo になっているのでそれぞれの Bot に対して同じテストツールでテストができるので、テスト書きたくなったら環境を簡単に用意できる。linter は ESLint を使っていて、そっちは一つの ESLint の設定で全てを管理できている。

前提として、複数のやりたいことを1つの Bot に全部まとめて一つのスクリプトでやるっていうやり方もあってそうしたら構成とかに頭を捻る必要がなくて楽なんだけど、そうすると複雑度がどんどん上がっていってメンテが辛くなっていくので、長く使う前提であれば今回のやり方はだいぶ見通しが良くて気に入っている。

具体的な実装に興味を持った方はぜひ GitHub のリポジトリを見ておくれ。
nabeliwo/gas-discord-bots

まだ気になりポイントはいくつかあって、例として一つ挙げると、それぞれの Bot のディレクトリ配下に build.js というのが置いてあって、中身も全部同じなので全然 DRY じゃないのでこれは共通にしちゃいたい、とか。
そんな感じでいろいろあるんだけどちょっとずつ改善をしていく予定です。

おわり

多分もっと調べたらこれより良いやり方が全然あるんだろうけど、とりあえず自分が管理しやすくて今後も追加しやすい構成が作れたので一旦満足している。
感想として、多分知ってる人には当たり前の話なんだけど、GAS 自体を久々に触ったしちゃんと GAS で開発するのは初めてという自分からすると、めっちゃ開発しやすいように整備されていてもうこれでなんでもやれるやんとなった。
GAS すごい。