DiscordのSlashコマンドを使ってみます。
https://discord.com/developers/docs/interactions/slash-commands
アプリの作成
https://discord.com/developers/applications
Developer PortalのApplicationsから新規作成します。
作成したら、OAuth2の設定ページに遷移して、OAuth2 URL Generatorの下にあるSCOPESから Bot
, applications.commands
を選択して、さらに Bot Permissions
の Send Meesages
にチェックを入れます。(必要に応じて追加でチェックを入れてください)
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)
特定のサーバーでのみ使用するのであれば <GUILD ID>
を指定します。
このスクリプトを実行して成功すれば201が表示されて終了します。
特定のサーバーでのみのコマンドであれば即時反映されるので、実際にDiscord上でも確認ができます。/
を入力すると候補に /blep
が表示されるはずです。
ただこのままコマンドを送信してもエラーとなり何も発生しないので、ひとまずコマンドを送信したら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
import { verifyKey } from 'discord-interactions' | |
const discord_public_key = process.env.DISCORD_PUBLIC_KEY; | |
addEventListener('fetch', event => { | |
event.respondWith(handleRequest(event.request)) | |
}) | |
async function handleRequest(request) { | |
if (!request.headers.get('X-Signature-Ed25519') || !request.headers.get('X-Signature-Timestamp')) | |
return new Response('', { status: 401 }) | |
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 }) | |
} | |
const body = await request.json(); | |
let json; | |
if (body.type == 1) { | |
const data = { | |
"type": 1 | |
} | |
json = JSON.stringify(data, null, 2); | |
} else { | |
const data = { | |
"type": 4, | |
"data": { | |
"tts": false, | |
"content": "pong", | |
"embeds": [], | |
"allowed_mentions": { "parse": [] } | |
} | |
} | |
json = JSON.stringify(data, null, 2) | |
} | |
return new Response( | |
json, | |
{ | |
status: 200, | |
headers: { | |
"content-type": "application/json;charset=UTF-8" | |
} | |
} | |
) | |
} |
このコードは何かしらコマンドのリクエストがあれば pong
を返却するだけのものになっています。
以下のコードでヘッダーがちゃんと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 })
}
以降の処理は正しい形式で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を確認します。
そこに表示されているURLを Discordのアプリケーション設定ページの discord-interactions
にペーストしてセーブしてチェックがパスしたら完了です。
Top comments (0)