はじめに
はじめまして。@nahiro_tusです。
この記事は、Discordのアプリケーションコマンドのドキュメントを読むのが大変だったので、自分なりにまとめてみた記事になります。
原文は英語なので、DeepLなどを活用しながら少しずつ読み進めていきました。もし間違っている個所や表現がおかしい部分などがありましたらコメントを頂ければ修正します。
今後Discordのアプリケーションコマンドを作ってみたい方や作る予定の方、現在開発をしている方の参考になれば幸いです。
この記事は以下のページを参考にして作っています。
Application Commandsとは
Application Commandsを一言で表すなら、「ユーザーのアクションをトリガーとして処理を開始してくれる機能」です。これだけだと少々わかりにくいので、今までのDiscord botと比較してみましょう。
従来のDiscord botの構成は以下のようになっていました。
botが各Discordサーバーにbotユーザとしてログインし、コマンド受け付け状態になります。この状態でbotに登録されたコマンドをユーザーが手動で入力すると処理が開始されます。
Discordサーバーの呼び方について
開発者ドキュメントではDiscordサーバーのことを「ギルド」と呼んでいるので、以降はその呼び方で統一します。
この構成のデメリットとして、
- botが常時接続状態である必要がある
- コマンドの構文やパラメータはユーザが覚えている必要がある
が挙げられます。
また、bot用サーバ側で構文解析を行っている構成上、送信したメッセージはすべてbot用サーバに送信されます。
Application Commandsでは、これらのデメリットが解消されています。
Application Commandsのコマンドが実行されると、Discord botにあらかじめ設定されたエンドポイントへリクエストを実行します。その後、ギルドへHTTPレスポンスを返したりバックエンドからDiscord APIへのリクエストを行ったりすることにより、メッセージを返信したりギルドの情報を更新したりできます。
従来のDiscord botと比較すると
- bot用サーバーが不要になった
- botがDiscordに常時接続する必要がなくなったため、bot用のサーバを立てる必要がなくなった
- Discord botに設定したAPIエンドポイントにリクエストするので、サーバーレス構成も容易
- コマンドを暗記が不要になった
- スラッシュコマンドではコマンドが補完されるため、コマンドを覚える必要がなくなった
- さらに、入力値を選択式にできるので、入力するパラメータを制限できる
- コマンドの入力内容のみが送信されるので、セキュリティ的にも安心
などのメリットがあります。
Application Commandsの種類
Application Commandsは3種類あります。
- Slash Commands
- User Commands
- Message Commands
それぞれ簡単に解説します
Slash Commands
おそらく最もオーソドックスなコマンド。別名CHAT_INPUT
。
メッセージ入力欄に/
を入力するとSlash Commandが入力できます。
すでにビルドインで何種類か用意されており、テキストを強調するコマンドやちゃぶ台返しをするコマンドが使えるようになっています。
ちなみにちゃぶ台返しをするコマンドでは以下のようなメッセージを作れます。
テスト勉強なんてやってられんわ! (╯°□°)╯︵ ┻━┻
テスト勉強はちゃんとしましょう。
User Commands
別名USER
。ユーザーを右クリック(もしくはタップ)すると表示されるUIベースのコマンドです。
ユーザーに関係する処理を実行するときに便利です。特定のユーザーにロールをまとめてつけたり、ユーザー情報を自分に送るときなどに使えそうです。
Message Commands
別名MESSAGE
。メッセージを右クリック(もしくはタップ)すると表示されるUIベースのコマンドです。
メッセージに関係する処理を実行するときに便利です。メッセージをブックマークしたり、メッセージを翻訳するbotなどが作れそうです。
コマンドの登録・更新・削除
コマンドはHTTPエンドポイント経由でのみ登録することができます。画面から登録することはできません。
コマンドのスコープ
コマンドのスコープにはグローバルとギルドの2種類があります。
グローバルスコープ
アプリケーションを追加したすべてのギルドで使用可能です。
また、自分と相手が同じギルドに属しており、そのギルドにグローバルスコープのコマンドを持つアプリがある場合、DM(ダイレクトメッセージ)でもそのコマンドを使用することができます。
ギルドスコープ
そのコマンドを使用できるのは作成時に指定したギルドのみです。
また、DMで使用することもできません。
制約
コマンド名は、アプリケーションごと、タイプごと、各スコープごとに一意ある必要があります。以下は公式ドキュメントに書かれていた具体例です。
- 同じ名前の2つのグローバル
CHAT_INPUT
コマンドを含めることはできない
アプリケーション
スコープ:グローバル
タイプ:CHAT_INPUT
コマンド1:sample
スコープ:グローバル
タイプ:CHAT_INPUT
コマンド2:sample
- 同じギルドで同じ名前の2つのギルド
CHAT_INPUT
コマンドを含めることはできない
アプリケーション
スコープ:ギルドA
タイプ:CHAT_INPUT
コマンド名:sample
スコープ:ギルドA
タイプ:CHAT_INPUT
コマンド名:sample
- 同じ名前のグローバル
USER
コマンドを含めることができない
アプリケーション
スコープ:グローバル
タイプ:USER
コマンド名:sample
スコープ:グローバル
タイプ:USER
コマンド名:sample
- 同じ名前のグローバル
CHAT_INPUT
コマンドとギルドCHAT_INPUT
コマンドを含めることができる
アプリケーション
スコープ:グローバル
コマンド名:sample
スコープ:ギルドA
コマンド名sample
- 同じ名前のグローバル
CHAT_INPUT
コマンドとグローバルUSER
コマンドを含めることができる
アプリケーション
スコープ:グローバル
タイプ:CHAT_INPUT
コマンド名:sample
スコープ:グローバル
タイプ:USER
コマンド名:sample
- 複数のアプリに同じ名前のコマンドを含めることができる
アプリケーションA
コマンド名:sample
アプリケーションB
コマンド名:sample
つまり、アプリケーション名・スコープ・タイプ・コマンド名の4つのパラメータの組み合わせがユニークであればコマンドを登録することができます。
また、1つのアプリケーションあたりに登録できるコマンドの数はタイプごとに決まっています。
CHAT_INPUT
- 100個の(グローバルコマンド+ギルドコマンド)
USER
- 5個の(グローバルコマンド+ギルドコマンド)
MESSAGE
- 5個の(グローバルコマンド+ギルドコマンド)
登録リクエスト上限
1ギルドあたり、1日に登録できるコマンド数は200件まで
コマンドの登録方法
ここからはコマンド登録の具体的な方法について書いていきます。コマンドの登録は、特定のエンドポイントに対してPOST
メソッドでリクエストすると登録することができます。
パラメータの詳細については次回解説するので、ひとまず以下の内容を覚えておけば大丈夫です。
-
name
はコマンド名 -
type
はコマンドの種類 -
description
はコマンドの説明 -
option
はCHAT_INPUT
固有のパラメータ
グローバルコマンドの作成
グローバルコマンドはapplicationを招待したすべてのサーバーで使用可能なコマンドです。グローバルコマンドは登録時に読み取り修復機能処理が走ります。グローバルコマンドを更新する前に内部で整合性判定を行い、万が一チェックに失敗した場合はそのコマンドの更新が拒否されます。
登録するためには以下のようなHTTPリクエストを送信します。
import requests
my_application_id = <作成したdiscord app のID>
# credentioals_token か app_tokenのどちらかを宣言
my_bot_token = <作成したdiscord app のトークン>
# my_credentials_token = <applications.commands.update の権限を付与したcredentials_token>
url = f"https://discord.com/api/v10/applications/{my_application_id}/commands"
# 以下はスラッシュコマンドを登録するときの例です
json = {
"name": "blep",
"type": 1,
"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": f"Bot {my_bot_token}"
}
# credentials tokenを使用する場合はこのコメントアウトを外して、bot tokenのヘッダーをコメントアウトする
# headers = {
# "Authorization": f"Bearer {my_credentials_token}"
# }
r = requests.post(url, headers=headers, json=json)
コードを実行すると、以下のようなスラッシュコマンドが登録されます
ギルドコマンドの作成
ギルドコマンドは作成時に指定したギルドでのみ使用できるコマンドです。ギルドコマンドはグローバルコマンドとは違い、読み取り修復機能はありません。そのため、リクエストをすると即時に設定が反映されます。公式ドキュメントでは、開発やテストはギルドコマンドで実装し、一般公開時にグローバルコマンドへ変更することを推奨しています。
import requests
# ここに変更が入っている
url = "https://discord.com/api/v10/applications/<my_application_id>/guilds/<guild_id>/commands"
# This is an example USER command, with a type of 2
json = {
"name": "High Five",
"type": 2
}
# For authorization, you can use either your bot token
headers = {
"Authorization": "Bot <my_bot_token>"
}
# or a client credentials token for your app with the applications.commands.update scope
headers = {
"Authorization": "Bearer <my_credentials_token>"
}
r = requests.post(url, headers=headers, json=json)
type:2
を指定するとUSER
コマンドを登録することができます。
このコマンドを実行すると、ギルドUSER
コマンドが登録されます。
コマンドの更新方法
コマンドの更新と削除にはPATCH
メソッドとDELETE
メソッドを使います。
以下のエンドポントへPATCH
メソッドでリクエストすると更新、DELETE
メソッドでリクエストすると削除が行えます。
- グローバルコマンドの場合
https://discord.com/api/v10/applications/<my_application_id>/commands/<command_id>
- ギルドコマンドの場合
https://discord.com/api/v10/applications/<my_application_id>/guilds/<guild_id>/commands/<command_id>
また、コマンドはアプリケーション名、スコープ、名前、タイプで識別されているため、POST
メソッドはupsert
(データが存在しなければ追加(insert)、存在すれば更新(update))として処理されます。
そのため、アプリケーション内ですでに存在するスコープ、名前、タイプの組み合わせに対してPOST
でリクエストをすると、PATCH
でのリクエストと同じ処理になります。
まとめ
今回はDiscord Application Commandsの基本情報と種類、具体的な登録方法について紹介しました。Application Commands のリファレンスはボリュームが大きいので、複数回に分けて紹介するつもりです。今のところ全3回を予定しているので、続きが気になる方は「いいね」を押してもらえるとうれしいです。(「いいね」が多いと執筆スピードが上がります。)
次回はApplication Commandsの各パラメータの解説と、コマンドの種類ごとの特徴について書きたいと思っています。
お楽しみに。