きゃべログ

Azure Functionsを使ってチーム分けDiscord Botを作ってみた

JavaScriptAzure個人開発

やったこと

Azure Functionsをバックエンドのサービスとして、チーム分けをするDiscord Botを作ってみました。 /grouping {グループ数} というフォーマットでコマンドを入力することで、チーム分け対象のメンバーを選択するセレクトメニューが表示され、選択が完了するとBotはチーム分けの結果を投稿してくれます。

グループ分けボットのデモ動画

GitHubリポジトリはこちらです。

cabbage63/discord-grouping-bot-azure-public: Discord bot hosted in Azure Functions to split channel members into some groups

背景

友人とオンラインでゲームで遊ぶときにチーム分けしたいことがあります。Web上でグループ分けしてくれるようなサービスやアプリはググれば見つかるのですが、毎回メンバーの名前を入力したり、そもそもググるのが面倒です。Discord上でサクッとできれば嬉しいなと思います。既存のDiscordアプリケーションや、Botにチーム分けしてくれる機能を持つものもあるかと思いますが、管理しているDiscordサーバーに誰が作ったかわからないアプリやBotを入れるのは個人的に抵抗があります。特にインストール時にメッセージのRead権限などを与える必要がある場合には一層慎重になります。なるべく自分の目の届く範囲で管理したいので、自分でDiscord Botを作ってみることにしました。

技術選定

DiscordはWeb APIを公開しており、公式チュートリアルではNode.jsを使ったサンプルを公開しています。素直にランタイムとしてはNode.jsを使って開発することにしました。

Node.jsを動かすコンピュータリソースには、なるべくコストがかからないものを利用したいと考えていました。個人的にいくつかのサーバーに導入して使うだけなので、そんなに頻繁にリクエストを裁く必要がないことから、常時サーバーを動かすのは非効率的です。サーバーレス・コンピューティングを採用するのが筋が良さそうです。選択肢としてはAWS lambda, Microsoft AzureのAzure Functions, GCPのCloud Functinsがあります。個人開発なので、超過分が自動で課金されるAWSはちょっと抵抗があったので、AzureかGCPに絞りました。中でもあんまり使ったことがないMicrosoft Azureを試してみたいことからAzure Functionsを使ってみることにしました。

厳密にはAzure Functionsで動くコードや構成ファイルがストレージアカウントのAzure Filesに保存され、ストレージアカウントは無料枠の対象外であるため若干のコストがかかります。Azure FunctionsでシンプルなAPIを作る場合はそんなにコストはかからないので、登録時に与えられるクレジットのおかげで賄えます。

お勉強

Discord AppもMicrosoft Azureもよくわからないので色々お勉強しました。多分どちらもチュートリアル的な記事をこなすと大体要領がわかるので、まずはそれに取り組んで、わからないことはドキュメントで補完するのがいいと思います。

アプリやアカウントなどの登録作業

Discord

Microsoft Azure

  • Microsoftアカウントでサインインする。
  • Microsoftアカウントを使ってMicrosoft Azureにサインアップする。
    • Microsoft Azureを使ったことがない場合は無料アカウントからスタート。
    • 無料アカウントでもカード情報の登録が必要。従量課金制サブスクリプションにアップグレードしない限り料金が発生することはないので安心。
    • 詳細はこちら: Azure の無料アカウントを今すぐ作成する | Microsoft Azure

実装

Discord Appのチュートリアルコードをベースに作ります。しかし、チュートリアルのAPIはExpress.jsで実装されているため、そのままではAzure Functionsのランタイムでは動きません。Azure Functionsのお作法に倣って、書き換えていく必要があります。

Discord Appの実装での工夫ポイントは、セレクトボックスでユーザーを選択し、結果を返してもらったあと、セレクトボックスを操作できないように無効化する処理を入れたところです。操作できないようにしておかないと、何度も同じセレクトボックスを操作される可能性があるためです。当該箇所は以下のURLです。

https://github.com/cabbage63/discord-grouping-bot-azure-public/blob/main/interaction/index.mjs#L124-L148

あとからセレクトメニューの有効・無効を上書きするために、メッセージを編集するためのDiscordのEdit Message APIを呼び出します。エンドポイントにChannelのIDやMessageのIDを指定する必要がありますが、Interactionオブジェクトの中に、channel.id, message.idが入っているのでそれを使います。

デプロイ

GitHub Actionsを使ってエレガントに継続的デプロイをやりたかったのですが、かなり時間をかけて何回トライしても失敗するので諦めました。

かわりにVisual Studio CodeのAzure Functions拡張機能でぽちぽち手動デプロイしました。手順としては数クリックで、時間も1分かからないくらいで反映までできてしまうので全然困っていないです。やりかたは以下を参考にしています。

https://learn.microsoft.com/ja-jp/azure/azure-functions/create-first-function-vs-code-node?pivots=nodejs-model-v3#deploy-the-project-to-azure

参照したドキュメントなど

Discord

チュートリアル

Interaction

Discordのスラッシュコマンドも、メッセージ中のUIに対するユーザーの入力も、Interactionという概念でサーバー側に届きます。処理の中心はInteractionになるので、中身を理解しておくことが重要っぽいです。

Microsoft Azure

Azure Functions

有志のブログ

蛇足

Discordのチュートリアルコードのタイポを見つけたので修正のプルリクを送ったらマージされました。やったぜ。

Fix typo in the example code of Getting Started by cabbage63 · Pull Request #29 · discord/discord-example-app

感想

作りたいものは作れました。 Discord AppもAzure Functionsもまだあんまり使いこなせるほどは理解できていないので、次何か作るときに本腰を入れてドキュメントを読み込みたい。


きゃべ / Masaya Kurahashi
きゃべ / Masaya Kurahashi
Software Engineer, Product Manager