discord.pyでcogを使って開発しやすくする
はじめに
discord.pyでようせいさんというBotを作っています。ようせいさんの招待はこちら。
はじめはサーバー内でメンバーを募集する機能を作っていましたが,徐々に機能が増えてコードが1000行を超え始めて,修正作業や新しい機能の追加が大変になりました。
ファイルを分ける方法を調べるとcogというものが出てきたので調べながら実装してみました。
Cogの有効化の方法がよくわからない部分も多いです😭
参考ページ
ファイルを分ける
まずはファイルを分けます。
.
┣ main.py
┣ config.py
┗ cogs
┣ event.py
┗ general.py
機能ごとにまとめてファイル分けしてます。
cogの定義
それぞれのファイルの中でcommand.cogを継承してCogを定義します。
import discord
from discord import app_commands
from discord.ext import commands
class General(commands.Cog):
def __init__(self, bot):
self.bot: commands.Bot = bot
イベントリスナーを作成する
import discord
from discord.ext import commands
class Event(commands.Cog):
def __init__(self, bot):
self.bot: commands.Bot = bot
@commands.Cog.listener()
async def on_message(self, message: discord.Message) -> None:
# pass
@commands.Cog.listenerをつけることでイベントリスナーを定義できる。
スラッシュコマンドを作成する
import discord
from discord import app_commands
from discord.ext import commands
class General(commands.Cog):
def __init__(self, bot):
self.bot: commands.Bot = bot
@app_commands.command(name='r', description='募集を行います')
async def r(self, ctx: discord.Interaction, title: str, detail: str = None, max: int = None, role: str = None, channel: str = None):
"""募集を行う
Args:
title (str): 募集タイトル
detail (str): 募集内容
max (int): 募集人数
role (str): 付与するロール
channel (str): 新たなチャンネルを作成するかどうか(作成する場合"y"を入力)
"""
pass
@app_commands.command(name='dice', description='ダイスを振ります')
@app_commands.describe(num='ダイスの個数')
async def dice(self, ctx: discord.Interaction, num: int = 1):
pass
@app_commands.commandを使用してスラッシュコマンドを定義できます。
name=でスラッシュコマンドの名前,description=でコマンドの説明が追加できます。
スラッシュコマンドとコマンドの説明はdiscordで/を打ち込んだ時に表示されるコマンドの候補に↓のように表示されます。

async def コマンドの名前(self, ctx, 引数...)のように記載します。
ctxには自動的にdiscord.Interactionが入れられる。アノテーションつけるとVScodeで補完機能が使いやすくなるのでつけてます。
引数のアノテーションをつけるとdiscordが型チェックして意図しない引数が入力されるのを防ぐことができます。↓

引数=初期値で初期値が設定できたり,引数=Noneで任意の引数にできたりします。どこかに書いてた気がするけどどこに書いてたかわすれた。見つけたら追記します。
@app_commands.describeまたは,Google、Sphinx、Numpy スタイルのドキュメント文字列でコマンド引数の説明を追加できます。

参考↓
Cogを有効にする
main.pyでCogを有効にしてBotを起動します。ここが一番よくわからなかったです。
エクステンション?とやらを使って有効にしています。
詳しくは公式のドキュメントを参考に↓
まずCogファイルの末尾にsetup関数を追加します。
async def setup(bot):
await bot.add_cog(General(bot))
エクステンションは setup というエントリポイントを持つPythonファイルです。
らしいです。だからこれでCogが定義されているエクステンションが作成されたという理解をしています。間違えてたらごめんなさい。
そしてこのエクステンションをload_extension()を使用して読み込みます。
import discord
from discord.ext import commands
import config
INITIAL_EXTENSIONS = [
'cogs.general',
'cogs.event',
]
intents = discord.Intents.all()
intents.typing = False
class MyBot(commands.Bot):
async def setup_hook(self):
for cog in INITIAL_EXTENSIONS:
await self.load_extension(cog)
await self.tree.sync()
bot = MyBot(command_prefix='!', intents=intents)
bot.run(config.TOKEN)
INITIAL_EXTENSIONSにエクステンションを追加してforで読み込んでます。
await self.tree.sync()でアプリケーションコマンドをDiscordに同期します。
おわり
cogの有効化でめちゃくちゃつまづきました。エクステンションの理解が曖昧ですが動いているのでいいでしょう。ご指摘があればXかDiscordにご連絡ください。
Discussion