🐍
discord.pyとextensionでスラッシュコマンドを実装する
方法は複数あると思いますので方法の一つです。
discord.pyでスラッシュコマンドを実現するためにはバージョンを2.x系にアップデートする必要があります。
1.x系からのアップデートには破壊的変更があり、まずはその対応が必要です。
ファイル構成
.
├── cogs/
│ ├── ping.py
│ ├── sample1.py
│ └── sample2.py
└── main.py
本体 (main.py)
自分のサーバーで使うような小規模のBotを想定しています。
ギルドコマンドとグローバルコマンドというのがありますが、
グローバルコマンドはBotを立ち上げてからスラッシュコマンドが反映されるまでに時間がかかったり、同期しすぎると怒られたり(?) するようです。
今回はGuild IDを指定してそのギルドだけで使えるギルドコマンドです。
ギルドコマンドはBotを立ち上げると即時反映されます。
import os
import discord
from discord.ext import commands
DISCROD_TOKEN = os.environ["DISCORD_TOKEN"]
GUILD_ID = os.environ["GUILD_ID"]
class MyBot(commands.Bot):
def __init__(self):
super().__init__(
intents=discord.Intents.all(),
help_command=None
)
# 読み込むcogsのリストを作る
self.initial_extensions = [
"cogs.ping",
"cogs.sample1.py",
"cogs.sample2.py"
]
async def setup_hook(self):
await self.load_extension(extension)
# インタラクションをシンクする。ギルドコマンドなので即時反映。
await bot.tree.sync(guild=discord.Object(id=GUILD_ID))
# おまじない。
async def close(self):
await super().close()
await self.session.close()
async def on_ready(self):
print("Connected!")
await bot.change_presence(activity=discord.Game(name="~をプレイ中のコメント", type=1))
return
bot = MyBot()
bot.run(TOKEN)
Cogs
サンプルとしてBotの応答速度を返すシンプルなcogsです。
from discord import app_commands
を使います。
ping.py
import discord
from discord import app_commands
from discord.ext import commands
class Ping(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
@app_commands.command(
name="ping", #/pingコマンドになる
description="Catch the ping of the bot!" #コマンドの説明文
)
async def ping(
self,
interaction: discord.Interaction
):
# interactionは3秒以内にレスポンスしないといけないとエラーになるのでこの処理を入れる。
await interaction.response.defer()
latency: float = self.bot.latency
latency_ms: int = round(latency * 1000)
await interaction.followup.send(f'🏓Pong! ({latency_ms}ms)')
async def setup(bot: commands.Bot):
await bot.add_cog(
Ping(bot),
guilds = [discord.Object(id=xxxxxxxxxxxxxx)]
)
ポイントいろいろ
interactionsへのレスポンスは3秒以内に返す必要がある
処理に時間がかかる場合は注意です。3秒以内に返せない可能性がある場合は上のping.pyのような処理が必要です。
await interaction.response.defer()
処理
await interaction.followup.send("contents")
こうすることで「考え中」となって、3秒以上でもエラーになりません。
3秒以内に返せる通常の書き方はこうです。
処理
await interaction.response.send_message("contents")
interactionはNoneを返してくる
スラッシュコマンドへのBotレスポンス自体にリアクションをつけたりすることはできない。(おそらくです。)
コマンドに引数(オプション)を追加し、オプションの説明をつけたい場合
@app_commands.command(
name="hello",
description="Botの応答速度を返します。"
)
@app_commands.describe(user="ユーザーを指定します。※これが説明部分")
async def hello(
self,
interaction: discord.Interaction,
user: discord.Member # こうすることでユーザー指定に限定できる
):
オプションのタイプ一覧
OptionType | discord.pyでの型 |
---|---|
String(文字列) | str |
Integer(整数) | int |
bool(True,False) | bool |
Channel | discord.TextChanneldiscord.VoiceChannel |
Member | discord.Member |
Role | discord.Role |
Attachment(添付ファイル) | discord.Attachment |
オプションを必須項目でなくする
@app_commands.command(
name="hello",
description="ユーザーにhelloを返します。"
)
@app_commands.describe(user="ユーザーを指定します。※これが説明部分")
async def hello(
self,
interaction: discord.Interaction,
user: discord.Member = None
):
こうすることuserのデフォルト値をNoneとすることができる。
コマンドの権限を管理者のみにする
@app_commands.command(
name="admin",
description="admin専用コマンド"
)
@app_commands.default_permissions(administrator=True)
async def admin(
self,
interaction: discord.Interaction
):
サーバー管理者以外には表示されることもありません。
パーミッションの一覧はここ
オプションを選択肢型にしたい
@app_commands.command(
name= "apexrank",
description= "Apex Legendsのランクを取得します。"
)
@app_commands.describe(
platform="プラットフォームを選択してください",
user_id="ユーザーIDを入力してください"
)
@app_commands.choices(
platform=[
discord.app_commands.Choice(name="Origin & Steam(PC)",value="origin"),
discord.app_commands.Choice(name="Xbox",value="xbl"),
discord.app_commands.Choice(name="Play Station",value="psn")
]
)
async def apexrank(
self,
interaction: discord.Interaction,
platform: str,
user_id: str
):
Discussion