5
5

Discord.pyV2.0にてcogとSlashCommandを一緒に使う方法

Last updated at Posted at 2022-12-27

前置き

本記事ではdiscord.py 2.0を使います。
まだダウンロードしてない場合は

cmd
$ python -m pip install -U discord

でインストールしてください

1.commands.Botには...?

discord.pyV2.0にはSlashCommandを使うためのapp_commandsが入ってます。
discord.Clientは別の記事でも言いましたがtree = app_commands.CommandTreeを定義する必要がありました。ですがcommands.Botにはapp_commandsが入ったdiscord.Clientを継承してるので定義は必要ないです。

2.実際に試してみる

main.py
import discord
from discord import app_commands
from discord.ext import commands

INITAL_EXTENSIONS = [
    "cogs.help",
    "cogs.verify",
    # いろいろ入れます

]

class DiscordBot(commands.Bot):
    def __init__(self, intents: discord.Intents, help_command=None, command_prefix: str):
        super().__init__(
                    intents=intents,
                    help_command=help_command,
                    command_prefix=command_prefix
                    )
    
    async def setup_hook(self):
        self.tree.copy_global_to(guild=discord.Object(id=ここにサーバーID))
        await self.tree.sync(guild=discord.Object(id=ここにサーバーID))
        return await super().setup_hook()

intents = discord.Intents.all()
bot = DiscordBot(intents=intents, command_prefix="!")

@bot.event
async def on_ready():
    print("Logged!")

if __name__ == "__main__":
    async def boot():
        for cogs in INITAL_EXTENSTIONS:
            await bot.load_extenstion(cogs)
    asyncio.run(boot())
    bot.run("TOKEN_HERE")

ちなみにファイル構成は↓のような感じです

/
├ cogs
│ ├ help.py
│ └ verify.py
└ main.py

各cogs内のpythonファイルは以下のような感じです。

help.py
import discord
from discord.ext import commands
from discord import app_commands

class HogeCog(commands.Cog):
    def __init__(self, bot: commands.Bot):
        super().__init__()
        self.bot = bot

    @commands.Cog.listener()
    async def on_ready(self):
        print("[Cogs] HogeCog is ready.")

    @app_commands.command(name="hoge", description="hogehoge")
    async def hoge(self, interaction: discord.Interaction):
        await interaction.response.send_message("こんにちは世界")

async def setup(bot: commands.Bot): # この関数が超重要
    await bot.add_cog(HogeCog(bot))

はい。
最後の関数setupはめちゃめちゃ大切です。これがないとmain.pyが読み込んでくれません。
注意点として、HogeCogはcommands.Cogを継承しているクラスなので、__init__メゾットでselfキーワードを定義しているのでhogeメゾットにはもちろんselfを入れてください。
じゃないと引数がずれてエラーが出ます。

3.discord.uiを使ってみる

uiってなんだ。という方は世の中のbotを見てみて下さい。
そのbotたちには例えばボタンdiscord.ui.Buttonやそれを格納するビューdiscord.ui.View、あとは文字入力ウィンドウであるモーダルdiscord.ui.Modalがあると思います。
それをどのようにcog内で展開するか説明します(というか今回のメインテーマここ...?)

verify.py
import discord
from discord.ext import commands
from discord import app_commands

class HogeView(discord.ui.View):
    def __init__(self, bot: commands.Bot):
        super().__init__(
                        timeout=None
                        )
        self.bot = bot

    @discord.ui.button(label="hogebutton", style=discord.ButtonStyle.danger, custom_id="hoge_btn1")
    async def callback_hogebutton(self, button: discord.Button, interaction: discord.Interaction):
        await button.response.send_message("あなたはボタンを押しました")


class HogeCog(commands.Cog):
    def __init__(self, bot: commands.Bot):
        super().__init__()
        self.bot = bot

    @commands.Cog.listener()
    async def on_ready(self):
        print("[Cogs] HogeCog is ready.")

    @app_commands.command(name="hoge", description="hogehoge")
    async def hoge(self, interaction: discord.Interaction):
        await interaction.response.send_message(view=HogeView(bot=self.bot))

async def setup(bot: commands.Bot): 
    await bot.add_cog(HogeCog(bot))

こんな感じです。
もちろんclassを分離させるので、self.botを使いたいとき(bot.get_user()とか?)に使えません。そんなときにはHogeView__init__に引数としてbotを定義しましょう。
もちろんclass内の__init__に定義したので、self.bot = botでself.botを使えるようにしなければいけないです。

import discord.py
from discord.ext import commands

# 略

class HogeModal(discord.ui.Modal)
    def __init__(self, bot: commands.Bot):
        super().__init__(title="タイトル")
        self.text = discord.TextInput(label="何か入力してみよう...", style=discord.TextStyle.short, min_value=1, max_value=40, required=True)
        self.add_item(self.text)
    
    def on_submit(self, interaction: discord.Interaction):
        value = self.text.value
        await interaction.response.send_message("あなたの入力した文字はこれですね?¥n{}".format(value))

#略
    @app_commands.command(name="hoge_modal", description="HogeModal")
    async def hoge_modal(self, interaction: discord.Interaction):
        await interaction.response.send_modal(HogeModal(self.bot))

こんな感じです。
注意点としては、send_messageではなくsend_modalでModalを継承したクラスを送信することです。
また、ModalはModalで直接送信できません。要するにModalを継承したクラス内のon_submitメゾット内ではsend_modal()で新たなModalは送信できない事です。これは一つdiscord.ui.Viewを挟んだりしてModalを送ればいけます。

4.終わりに

cogsとSlashCommandを一緒に動かすといった日本語の文献が少なかった(GitHubには英語版の詳細な文献がありますが...)ので備考録(兼みなさんのために)的に書いてみました。
よかったらフォロー・いいねください。モチベーションが高まります。

5
5
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
5
5