DEV Community

Yuta Goto
Yuta Goto

Posted on

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 にペーストしてセーブしてチェックがパスしたら完了です。

Top comments (0)