discord の有名な reminder-bot がスケジュールリマインダー(特定の曜日に通知みたいなもの)に対応していなかったので、 自分で作成しました。今回は簡単にできるけど融通が効かないものと、面倒だけど融通が効くものを紹介していきます。
Cloud Scheduler + Cloud Workflow
完結に言うと、定期的に webhook するだけです。多分無料枠で納まります。 本来は Cloud Schduler から discord に直接送信したかったのですが、なぜか 400 エラーになってしまうので、Cloud Workflow 経由で実行しました。
作成手順
1. まず、discord 上でウェブフックを作成し、作成された URL を取得します。
2. workflow の作成
workflow は cloud console からの作成が容易なので、簡単なものならそちらで作成するのもいいと思います。コンソール上で以下のような workflow を作成します。
- postDiscord:
call: http.post
args:
url: 先程発行したdiscordのwebhook url
body: { "content": "メッセージは届いていますか?" }
headers:
Content-Typ: payload_json
content に入れたメッセージが実際にチャンネルに投稿される内容になります。body の内容次第ではよりリッチなメッセージを送ることも可能です。
参考
workflow を作成したら実際に実行してみると、メッセージが届くことが確認できると思います。
3. cloud scheduler の設定
こちらのドキュメントに沿ってやっています。 リンクが死ぬ可能性もあるので、やった手順を一応載せときます。
gcloud iam service-accounts create bot-shedular
# PROJECT_NAME を置換して下さい
gcloud projects add-iam-policy-binding PROJECT_NAME \
--member serviceAccount:bot-shedular@PROJECT_NAME.iam.gserviceaccount.com \
--role roles/workflows.invoker
# 平日の 17時に実行
gcloud scheduler jobs create http discord-reminder \
--schedule="0 17 * * 1-5" \
--uri="https://workflowexecutions.googleapis.com/v1/projects/PROJECT_NAME/locations/REGION_NAME/workflows/WORKFLOW_NAME/executions" \
--time-zone="Asia/Tokyo" \
--oauth-service-account-email="bot-shedular@PROJECT_NAME.iam.gserviceaccount.com"
cloud sheduler も実際に発火させて試してみることをお勧めします。
GCE + Datastore (+ Cloud Function + Cloud Scheduler)
こちらの方法を簡潔に言うと、ちゃんと Bot を作るです。 今回は discord.py で Bot の作成を行ないました。作成したものはこちらです。 後で知ったのですが、一番有名なのは discord.jsだったんですね。どっちの方が楽だったんだろうという気持ちになります。
discord の bot は起動し続ける必要があるため、色々なハックが紹介されているみたいです。
ですが、今回は正当(?)に GCE を使用して行ないました。
しかし、ただ GCE を使用すると課金が勿体ないので、プリミティブインスタンスを使用し費用を抑え、特定の時間はインスタンスを寝かせるようにしました。
デプロイ手順
手順は結構面倒な上に僕次第で結構変わると思うので、ここでは雑に書きます。(力尽きたわけじゃないよ)
インスタンスのデプロイ
readme にも書いてありますが、やることは以下の流れです。
- bot の作成
- artifact registry と service account の作成
- image の build
- image を使用した GCE インスタンスのデプロイ
インスタンスのスケジュール化
こちらは先程貼ったこちらのドキュメントに沿って実施していくだけです。こちらは gcp の nodejs のサンプルを使用していてサンプルが使えなくなる可能性があるので、リンクを貼るだけに留めておきます。
Bot の処理
一応 Bot の処理内容も書いておきます。
今回作成した Bot はインスタンスを寝かせることを考えて、その日のリマンダーのみをメモリに持たせてその時間が過ぎたら通知、というようなことをしています。 リマインダーは全て datastore に保存し、起動時にその日のリマインダーを取得します。フローとして書くと以下のようになります。
- 起動時に datastore からその日のリマインダーを取得してメモリに保存
- 毎秒毎にリマンダーリストをループして時刻を過ぎてないか確認
- 過ぎているものがあったら、そのメッセージを送信
- 1 に戻る
この処理に加えて、ユーザのメッセージをパースして、リマインダーを datastore に保存する処理があります。
感想
リマインダーと discord の性質を考えるとスケールするリマインダーを作成するのが結構大変というのが、今回作成してみてよく分かりました。 自分で作ってみるまでは何で定期リマンダーが有料なんだ、という気持ちが強かったですが悔い新ためました。