この記事は発展的な内容です。
初心者の方でも簡単に理解できるよう心がけて説明をしたつもりではありますが、Pythonやdiscord.pyをあまり理解できていない方は先にそちらを理解することを強く推奨します。
はじめに
2023年8月に記事をかなり書き換え、簡単な書き方からCogの仕組みまで理解できるようになりました。
この記事を読もうとしているそこのあなた!!
ちょっと待ってください!!
すでにドキュメントは読んでいますか??
読んでいない場合は下のリンクからすぐに読んできてください。読んでも理解ができなかった場合や、詳しい仕組みが知りたい場合はこの記事を読み進めてください。
この記事では仕組みなど初心者には難しいと思われる場所を、下のように折りたたんであります。詳しい仕組みが知りたい!という方はぜひクリックして読んでみてください。
クリックしてネ!
( ᐛ👐)パァ
そもそも Cog(コグ) って?
Bot開発においてコマンドやリスナー、いくつかの状態を一つのクラスにまとめてしまいたい場合があるでしょう。コグはそれを実現したものです。
https://discordpy.readthedocs.io/ja/latest/ext/commands/cogs.html
公式ドキュメントにも書いてある通り、CogはBotのプログラムをいくつかに分割するために使用します。
大きなBotの場合、一つのファイルにまとめると3000行とか大変なことになりますからね()
また後述のExtensionを使うとBotの再起動なしにプログラムを書き換えることもできます。
Cogを使う際の書き換え
コマンド
Cogを使わないときはコマンドを定義する際に以下のように書きますが、
@bot.command()
async def test(ctx):
pass #処理内容
Cog内でコマンドを定義するときは以下のように書きます。
@commands.command()
async def test(self, ctx):
pass #処理内容
違いは@bot.~
が@commands.~
なったのと、引数にself
が追加されたことぐらいですかね。
イベント
Cogを使わないときはイベントを定義する際に以下のように書きますが、
@bot.event
async def on_ready():
pass #処理内容
Cog内でイベントを定義するときは以下のように書きます。
@commands.Cog.listener()
async def on_ready(self):
pass #処理内容
違いは@bot.event
が@commands.Cog.listener()
になったことと、さっきと同じように引数にself
が追加されたことですね。
変数bot
の使い方
Cogを使わないときはBotのデータにアクセスする際に以下のように書きますが、
bot
Cog内でアクセスするときは以下のようになります。
self.bot
違いはself
を書かなければいけなくなったってことぐらいですね。
さっきから出てくるselfって何者??
selfはdiscord.pyの機能ではなく、PythonのClassの機能になります。
selfを使うことで同一クラス内の関数でデータを共有することができます。
詳しくは下の記事を読んでみてください。
Cogの追加
同一ファイルの時
import discord
from discord.ext import commands
bot = commands.Bot(command_prefix="!")
class MyCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command()
async def test(self, ctx):
await ctx.send("test!")
@bot.event
async def setup_hook():
await bot.add_cog(MyCog(bot))
こんな感じになります。
@bot.event
async def setup_hook():
await bot.add_cog(MyCog(bot))
の部分でCogを読み込んでいます。
Cog名(上でいうところのMyCog
)に特に決まりはないため、好きに決めることができます。
__init__ってなに??
これも、Pythonの機能になります。
Classの生成後に実行される関数です。
これを使うことでClassが生成されたとき(≒Cogが実行されたとき)の処理を書くことができます。
詳しくは下の記事を読んでみてください。
仕組み
-
Botの起動後
setup_hook
が呼び出される。 -
bot.add_cog
でCogを追加。
別ファイルのとき
このままだと、Classに分けることはできてもファイルは一つのままです。
そこで、Classの部分を別のファイルに移してみましょう。
.
┣━ main.py
┗━ sub.py
ファイル構成が上のようになっていてsub.py
にあるMyCog
を読み込みたいときは以下のようにします。
import discord
from discord.ext import commands
import sub
bot = commands.Bot(command_prefix="!")
@bot.event
async def setup_hook():
await bot.add_cog(sub.MyCog(bot))
import discord
from discord.ext import commands
class MyCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command()
async def test(self, ctx):
await ctx.send("test!")
main.py
を実行し、testコマンドを実行するとtest!と返ってきます。
仕組み
-
main.py
のimport sub
でsub.py
を読み込む。 -
bot.add_cog
でsub.py
にあるMyCog
を読み込む。
また、上記以外のディレクトリの場合も同じようにimport
を使うことで読み込みできます。
詳しくは、下の記事をご覧ください。
Extension
Extensionとは上でも言いましたが、Botの再起動なしにプログラムを書き換えることをできるようにする機能のことです。
一般的にCogとExtensionを同時に使うことが多いので、Cog≒Extensionと誤解しやすいですが、別の機能です。
.
┣━ main.py
┗━ sub.py
ファイル構成が上のようになっている場合、下のようにすることでExtensionを使えるようになります。
import discord
from discord.ext import commands
bot = commands.Bot(command_prefix="!")
@bot.event
async def setup_hook():
await bot.load_extension("sub")
import discord
from discord.ext import commands
class MyCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command()
async def test(self, ctx):
pass
async def setup(bot):
await bot.add_cog(MyCog(bot))
main.py
を実行し、testコマンドを実行するとtest!と返ってきます。
仕組み
-
main.py
のbot.load_extension
でsub.py
を読み込む。 -
sub.py
のsetup
関数が読み込まれる。 -
=== ここまでがExtensionの機能 ===
-
bot.add_cog
でsub.py
にあるMyCog
を読み込む。
.
┣━ main.py
┗━ cog
┗━ sub.py
ファイル構成が上のようになっている場合、await bot.load_extension("cog.sub")
で読み込みできます。
最後に
わからないこと、追加してほしいこと、誤字脱字等があれば遠慮なくコメントしてください。
ただ、忙しいので見れない可能性もあります。予めご了承ください。