discord.pyでslash command【cogを使用する場合】

自分用のメモです。

discord.pyの2.0からslash commandが使えるようになりました。
ただ、サンプルコードを漁ってもcogを用いた例があまり見つからなかったので、備忘録として残します。

ディレクトリ構成は以下の通りです。
・main.py
・cogs
  └ xxx.py
・env
  └ config.ini
  └ config.py

環境変数

config.ini

[TOKEN]
TOKEN=自分のbotのトークン

config.py

# env/config.py

import configparser
import os

class Config():
    def __init__(self):
        path = os.path.join(os.path.dirname(__file__), 'config.ini')
        self.config = configparser.ConfigParser()
        self.config.read(path, 'UTF-8')

    @property
    def token(self) -> str:
        return str(self.config['TOKEN']['TOKEN'])

メイン

# main.py

import asyncio
import discord
from discord.ext import commands
from env.config import Config

INITIAL_EXTENSIONS = [
    'cogs.xxx',
]

config = Config()

TOKEN = config.token

intents = discord.Intents.all()
activity = discord.Activity(name="MyBot", type=discord.ActivityType.competing)

bot = commands.Bot(command_prefix='h!', intents = intents, activity = activity)

async def load_extension():
    for cog in INITIAL_EXTENSIONS:
        await bot.load_extension(cog)

async def main():
    async with bot:
        await load_extension()
        await bot.start(TOKEN)

asyncio.run(main())

ここまでは何の変哲もありません。

コマンド処理を書いたcog

# cogs/xxx.py

import discord
from discord import app_commands
from discord.ext import commands

class Xxx(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.Cog.listener()
    async def on_ready(self):
        print('Successfully loaded : PostForum')
        await self.bot.tree.sync(guild=discord.Object(自分のギルドID))
        print("sync")

    @app_commands.command(name = "bottest", description = "テスト")
    @app_commands.guilds(自分のギルドID)
    @app_commands.checks.has_permissions(administrator=True)
    async def bottest(self, interaction: discord.Interaction):
        await interaction.response.send_message("test", ephemeral=True)
            
async def setup(bot: commands.Bot):
    await bot.add_cog(Xxx(bot))

まず、ほとんどのサイトでは

client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client)

このように discord.Client() を使用していました。

今回の例で用いられた、discord.Client() のサブクラスである
discord.ext.commands.Bot() は、以下にあるようにCommandTreeを作成する必要がありません。

Discord Botを表します。

このクラスは discord.Client のサブクラスのため、 discord.Client でできることと同じことをこのBotで行うことができます。

また、 GroupMixin も継承しており、コマンド管理の機能も使用可能です。

discord.Client とは異なり、このクラスでは CommandTree を手動で設定する必要はなく、クラスのインスタンスを作成する際に自動的に設定されます。

https://discordpy.readthedocs.io/ja/latest/ext/commands/api.html?highlight=commands%20bot#discord.ext.commands.Bot

そのため、コマンドを追加・削除・編集した際に必ず実行する

tree.sync()

については、以下のように書くことができます。

bot.tree.sync()

今回の例では、cogのon_ready関数内に記述しています。

以上。

この記事が気に入ったらサポートをしてみませんか?