1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

itohalAdvent Calendar 2022

Day 5

discord pyでbotのコマンドをadd_command()で登録する

Posted at

前提

この記事ではdiscord.pyを使ったdiscord botにおいて,command treeのadd_command()を利用したコマンド登録を説明します.これに合わせて,コマンドのグループ化について少し触れます.

また,説明には以下のコードを使用し,これを発展させていきます.

サンプルコード
discordbot.py
import os
from discord import Intents, Client, Interaction
from discord.app_commands import CommandTree
from dotenv import load_dotenv
load_dotenv()


class MyClient(Client):
    def __init__(self, intents: Intents) -> None:
        super().__init__(intents=intents)
        self.tree = CommandTree(self)

    async def setup_hook(self) -> None:
        await self.tree.sync()

    async def on_ready(self):
        print(f"login: {self.user.name} [{self.user.id}]")
        print(self.get_guild(1047700283217686719))


intents = Intents.default()
client = MyClient(intents=intents)


@client.tree.command()
async def hello(interaction: Interaction):
    await interaction.response.send_message(f'Hello, {interaction.user.mention}')


client.run(os.getenv("TOKEN"))

CommandTree.add_command()

コマンドを追加する方法はサンプルコードにあるような@client.tree.command()の下にコマンドの下に関数を記述するだけでなく,CommandTreeのインスタンスからadd_command()を呼び出し,引数にコマンドを与えるという方法があります.

リファレンスを見てみると,

command (Union[Command, Group]) -- 追加するアプリケーションコマンドまたはグループ。

とあります.Union型は指定された型のどれかであればいいというものなので,CommandGroupのどちらかを指定すれば大丈夫です.

Command

Commandについて見ていきましょう.リファレンスによると,

これは通常手動で作成されず、代わりに以下のデコレータを使用して作成されます。

  • command()
  • Group.command
  • CommandTree.command

とあります.このどれもが結局discord.app_commands.commandによるデコレータです.デコレータなのでわかりずらいですが,デコレータの下に記述した関数がクラスになります.GitHubにある基のコードを見るほうがわかりやすいかもしれません.デコレータ部分でCommandクラスが返されています.つまりapp_command(function)とすればコマンドが登録されます.また,特に指定しなければ関数名が実行する際のコマンド名になります.

この@discord.app_commands.command(Command)を利用したサンプルコードを下記に置いておきます.

サンプルコード
discordbot.py
import os
- from discord import Intents, Client, Interaction
+ from discord import Intents, Client, Interaction, app_commands
from discord.app_commands import CommandTree
from dotenv import load_dotenv
load_dotenv()


+ @app_commands.command()
+ async def hello(interaction: Interaction):
+     await interaction.response.send_message(f'Hello, {interaction.user.mention}')


class MyClient(Client):
    def __init__(self, intents: Intents) -> None:
        super().__init__(intents=intents)
        self.tree = CommandTree(self)
+       self.tree.add_command(hello)

    async def setup_hook(self) -> None:
        await self.tree.sync()

    async def on_ready(self):
        print(f"login: {self.user.name} [{self.user.id}]")
        print(self.get_guild(1047700283217686719))


intents = Intents.default()
client = MyClient(intents=intents)


client.run(os.getenv("TOKEN"))

ただ,注意するべきことが一つあります.それは,コマンドの登録の反映がすぐには行われないということです.当たり前といえば当たり前ですが,私は散々これで悩んだので共有しておきます.エラーなく実行できてるのに期待した通りにならなくて,でも時折できてて,とても悩みました......
そのコマンドを実行しようとすれば更新がかかると思います.でも更新されないときがあるのでそのときは空でも眺めましょう.

Group

続いて,Groupを見ていきましょう.
そもそも,Groupによるコマンドとはコマンドの階層構造のようなものです.

MyGroup
├── subcommand
└── SubGroup
    └── subsubcommand

上記のようなコマンドグループがあったとして,subcommadを実行するには/MyGroup subcommandのように記述します.subsubcommandであれば/MyGroup SubGroup subsubcommandです.
このようにコマンドをカテゴリ別に分類することができます.

リファレンスによると,継承して使うクラスなので,継承したクラスを作りましょう.

コードは以下のような感じです.本当は上に示したような構成のグループにしたかったのですが,更新が思っているより遅くて億劫なので事前に実験したものを載せます.

サンプルコード
discordbot.py
import os
from discord import Intents, Client, Interaction, app_commands
from discord.app_commands import CommandTree
from dotenv import load_dotenv
load_dotenv()


@app_commands.command()
async def hello(interaction: Interaction):
    await interaction.response.send_message(f'Hello, {interaction.user.mention}')

+ class MyGroup(app_commands.Group):
+     def __init__(self, name: str):
+         super().__init__(name=name)
+
+     @app_commands.command()
+     async def hello(self, interaction: Interaction):
+         await interaction.response.send_message(f'Hello, {interaction.user.mention}')

class MyClient(Client):
    def __init__(self, intents: Intents) -> None:
        super().__init__(intents=intents)
        self.tree = CommandTree(self)
        self.tree.add_command(hello)
        self.tree.add_command(MyGroup("group"))

    async def setup_hook(self) -> None:
        await self.tree.sync()

    async def on_ready(self):
        print(f"login: {self.user.name} [{self.user.id}]")
        print(self.get_guild(1047700283217686719))


intents = Intents.default()
client = MyClient(intents=intents)


client.run(os.getenv("TOKEN"))

現在のサンプルコードでは一つのファイルにまとめていますが,別ファイルに作りそれをimportすることでコードの見通しが良くなると思います.

以上がdiscord pyでbotのコマンドをadd_command()での登録でした.
お疲れ様でした.

1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?