Discord Slash Commandをつくる

yutagoto

Yuta Goto

Posted on July 21, 2021

Discord Slash Commandをつくる

DiscordのSlashコマンドを使ってみます。

https://discord.com/developers/docs/interactions/slash-commands

アプリの作成

https://discord.com/developers/applications

Developer PortalのApplicationsから新規作成します。

6cdf0c93-e499-491a-a1aa-b897f9dde692

作成したら、OAuth2の設定ページに遷移して、OAuth2 URL Generatorの下にあるSCOPESから Bot, applications.commands を選択して、さらに Bot PermissionsSend Meesages にチェックを入れます。(必要に応じて追加でチェックを入れてください)

336c21e0-e3b4-48b5-9080-7803bafa178a

SCOPESにあるURLにアクセスしてBOTユーザをサーバーに招待します。

ここでBOTの下準備は完了です。

スラッシュコマンドの登録

https://discord.com/developers/docs/interactions/slash-commands#registering-a-command

公式のドキュメントにある通りスクリプトを組んで実行します。

import requests

url = "https://discord.com/api/v8/applications/<APPLICATION ID>/guilds/<GUILD ID>/commands"

json = {
    "name": "blep",
    "description": "Send a random adorable animal photo",
    "options": [
        {
            "name": "animal",
            "description": "The type of animal",
            "type": 3,
            "required": True,
            "choices": [
                {
                    "name": "Dog",
                    "value": "animal_dog"
                },
                {
                    "name": "Cat",
                    "value": "animal_cat"
                },
                {
                    "name": "Penguin",
                    "value": "animal_penguin"
                }
            ]
        },
        {
            "name": "only_smol",
            "description": "Whether to show only baby animals",
            "type": 5,
            "required": False
        }
    ]
}

headers = {
    "Authorization": "Bot <BOT TOKEN>"
}

r = requests.post(url, headers=headers, json=json)
print(r.status_code)
Enter fullscreen mode Exit fullscreen mode

特定のサーバーでのみ使用するのであれば <GUILD ID> を指定します。
このスクリプトを実行して成功すれば201が表示されて終了します。
特定のサーバーでのみのコマンドであれば即時反映されるので、実際にDiscord上でも確認ができます。/ を入力すると候補に /blep が表示されるはずです。

1cb19898-9309-4d47-97bd-790333eed9fe

ただこのままコマンドを送信してもエラーとなり何も発生しないので、ひとまずコマンドを送信したらBOTがメッセージを送信する処理を実装します。

コマンド送信後の実装

今回、本番環境では Cloudflare Workers KV を使用します。GoogleCloudRunなどのサーバレスのものを利用しても問題ないですが、CloudRunはアクセスがあってから起動するまでに時間がかかってしまい、Discord側でタイムアウト判定になってしまう可能性があります。Cloudflare Workers KVは起動がCloudRunよりもかなり早いので正常にレスポンスできるはずです。

https://www.cloudflare.com/ja-jp/products/workers-kv/

Cloudflare Workers KVのセットアップは割愛します。https://developers.cloudflare.com/workers/ に環境構築からデプロイまでかかれています。
外部ライブラリを利用するのでWebpackも利用します。

Discordのリクエストを受け付ける

discord-interactions を使って実装します。

https://www.npmjs.com/package/discord-interactions

このコードは何かしらコマンドのリクエストがあれば pong を返却するだけのものになっています。

スクリーンショット 2021-07-21 AM1.09.05

以下のコードでヘッダーがちゃんとDiscordから来たものかを判定します。Discordで Interactions Endpoint URL を登録する際にあえて誤ったリクエストヘッダーがついたリクエストがくるので、それの判定を行います。

const valid = verifyKey(
  await request.clone().arrayBuffer(),
  request.headers.get('X-Signature-Ed25519'),
  request.headers.get('X-Signature-Timestamp'),
  discord_public_key
)

if (!valid) {
  return new Response('', { status: 401 })
}
Enter fullscreen mode Exit fullscreen mode

以降の処理は正しい形式でJSONを返却します。 https://discord.com/developers/docs/interactions/slash-commands#responding-to-an-interaction にもサンプルが書いています。

デプロイ

外部パッケージを使用しているのでwebpackした後のコードをデプロイします。webpackやその設定の説明は端折ります。

デプロイもcloudflareのチュートリアルにある通りにコマンド一発で完了します。 https://developers.cloudflare.com/workers/get-started/guide#8-publish-your-project

デプロイが完了したらCloudflareのWorkers一覧ページにアクセスして、そこに表示されているURLを確認します。

Screenshot 2021-07-21 at 01-21-22 Workers Account Cloudflare - Web Performance Security

そこに表示されているURLを Discordのアプリケーション設定ページの discord-interactions にペーストしてセーブしてチェックがパスしたら完了です。

💖 💪 🙅 🚩
yutagoto
Yuta Goto

Posted on July 21, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Discord Slash Commandをつくる
discord Discord Slash Commandをつくる

July 21, 2021