はじめに
こんにちは、@nano_sudoです。
discord.pyでBotを作るとき、コードが長くなってしまうことがあります。
そんなときに便利なのが、Cog・Extensionです。
今回はdiscord.pyのCog・Extensionの使い方を説明します。
前提知識
- pythonの基礎的な文法(関数やクラスなど)
Cogとは
Botを機能ごとに分けることができる機能です。
以下はdiscord.py公式ドキュメントの説明です。
Bot開発においてコマンドやリスナー、いくつかの状態を一つのクラスにまとめてしまいたい場合があるでしょう。コグはそれを実現したものです。(discord.pyドキュメント)
Cog・Extensionを使うメリット
- 機能のグループ化
Cogを使用することで、Botの機能をグループに分けることができる。
(例:音楽コマンドや管理コマンドなど) - 再利用性の向上
Cogをコピーすれば、他のボットに同様の機能を簡単に実装することができる。 - 柔軟性
Extensionを利用するとCogの有効化や無効化を簡単に行えるので、必要に応じてBotの動作を変更することができる。 - 開発の快適性
Extensionにはホットリロード機能がついているので、開発がより快適にできるようになる。
Cogの最小構成
コマンドは従来のcommands.command()
ではなく、app_commands.command()
を使います。
app_commands
では、discordクライアントにコマンドの候補を表示することができます。
Cogを分ける基準
機能ごとに分けるのがおすすめです。
例:音楽コマンド、管理コマンドなど
ファイル構成
.
├── main.py
└── cogs
└── hello.py
from discord.ext import commands
from discord import app_commands
# commands.Cogを継承する
class MyCog(commands.Cog):
def __init__(self, bot)
self.bot = bot
# イベントリスナー(ボットが起動したときやメッセージを受信したとき等)
@commands.Cog.listener()
async def on_ready(self):
print("Cog ready!")
# コマンドデコレーター(descriptionで説明が書ける)
@app_commands.command(name="hello")
async def hello(self,interaction:discord.Interaction)
await interaction.response.send_message("hello!")
コードの解説
Cogの定義
class Hello(commands.Cog):
commands.Cog
を継承することで、Cogを定義することができます。
コンストラクター
def __init__(self,bot)
self.bot = bot
コンストラクターには必ずbot
引数を入れてください。
イベントリスナー
@commands.Cog.listener()
async def on_ready(self):
print("Cog ready!")
@commands.Cog.listener()
デコレーターをつけることで、イベントリスナーを定義することができます。
ほかにも、on_message
やon_member_join
などのイベントリスナーがあります。
コマンドデコレーター
@app_commands.command(name="hello")
async def hello(self,interaction:discord.Interaction)
await interaction.response.send_message("hello!")
@app_commands.command()
デコレーターをつけることで、コマンドを定義することができます。
description
引数でコマンドの説明を書くことができます。
name
引数と関数名が一致していないと、エラーが発生するので注意です。
Cogの有効化
from discord.ext import commands
from cogs.hello import MyCog
# Botの定義
class MyBot(commands.Bot):
def __init__(self):
super().__init__(
command_prefix="!",
intents=discord.Intents.all()
)
async def setup_hook(self) -> None:
guild_ids = [123456789012345678] # すぐに同期したいサーバーのIDを入れる
await self.tree.sync(guild=None)
for g in guild_ids:
try:
await self.tree.sync(guild=g)
except discord.errors.Forbidden:
# やりすぎるとForbiddenになるので、一応例外処理を入れておく
print(f"サーバーID:{g}に登録できませんでした。")
bot = MyBot()
if __name__ == "__main__":
# Cogを有効化
bot.add_cog(MyCog(bot))
# Botを起動
bot.run("token")
コマンドを使うには、Bot().tree.sync()
で一度同期する必要があります。
グローバルにコマンドを同期するには、guild=None
にします。
私はいつも、setup_hook
で同期していますが、ほかに良い方法があればぜひ教えてください!
bot.add_cog()
でCogを使ってCogを有効化することができます。
ExtensionからCogを有効化
Extension経由で読み込むと、ホットリロードや有効化・無効化が簡単にできるので、おすすめ
extensionを使用して読み込む場合は、Cogにsetup
関数を定義してください。
# 以下をファイルの最後に追加
async def setup(bot):
await bot.add_cog(MyCog(bot))
main.pyのif __name__ == "__main__"
以下をこのように変更してください。
# 以下をおきかえる
if __name__ == "__main__":
# Extensionを有効化
await bot.load_extension("cogs.hello")
# Botを起動
bot.run("token")
まとめ
いかがでしたか?
今回はdiscord.pyのCog・Extensionの使い方を説明しました。
discord.pyを使ってBotを作るときは、ぜひCog・Extensionを使ってみてください!
質問やご意見・ご指摘などあれば、Twitterかコメント欄にお願いします!
Zennにも投稿しています!