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

# 前置き
本記事では**discord.py 2.0**を使います。
まだダウンロードしてない場合は
```shell: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.実際に試してみる
```py: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ファイルは以下のような感じです。
```py: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内で展開するか説明します(というか今回のメインテーマここ...?)

```py: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を使えるようにしなければいけないです。

```py
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には英語版の詳細な文献がありますが...)ので備考録(兼みなさんのために)的に書いてみました。
よかったらフォロー・いいねください。モチベーションが高まります。