25
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

discord.pyのCogとExtensionを理解する

Last updated at Posted at 2020-06-14

はじめに

discord.pyでext.commandsフレームワークを使い始めたときに、Cogを使おうと思っても、うまくいかない人が多いです。そんな人のために、解説をしていきたいと思います。

追記: discord.py 2.0aの、extension/cogの読み込みが非同期になるというアップデートに対応しました。

Cogとは?

Cogの解説にも書いてありますが、Bot開発においてコマンドやリスナー、いくつかの状態を一つのクラスにまとめるために作られました。
例えば、コマンドのカテゴリーごとの分類や、リスナーを機能ごとに切り分けたようなものです。オブジェクト指向ですね。
Cogはcommands.Cogを継承したクラスを作れば作ることが可能です。
こんな感じ:

from discord.ext import commands


class MyCog(commands.Cog):
    pass

Cogの中でコマンドを作る

Cogの中でコマンドを作るためには、ちょっと違う方法を使います。
普通botでコマンドを作るときは、@bot.command()を使いますが、Cogの中で作るときは@commands.command()を使います。
こんな感じ:

from discord.ext import commands


class MyCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def cat(self, ctx):
        await ctx.send('にゃーん?')

    @commands.command()
    async def dog(self, ctx):
        await ctx.send('わん!')

Cogの中でイベントリスナーを使う

Cogの中で@bot.eventのようにイベントを取得したい場合は、@commands.Cog.listener()を使用します。
このlistenerにはname引数があり、これを使うことでどんな名前の関数でもリスナーにできます!
また、全てのリスナーが独立しているので、いくらでも作ることが可能です。
こんな感じ:

from discord.ext import commands


class MyCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.Cog.listener(name='on_message')
    async def good_reaction(self, message):
        if message.author.bot:
            return
        if 'いいね' in message.content:
            await message.add_reaction('\U0001f44d')

__init__にbot引数つけてること多いけど何?

例えばbotにある関数、例えばbot.reload_extensionなどを使いたいとき、Botのインスタンスを参照する必要があります。なので、__init__するときに渡すことで、後から参照できるということです。

Extensionとは?

Extensionの解説にもありますが、ホットリロードを簡単に行えるようにするための機能です。これがあることで、Botを落とさないでコマンドを変更可能です。
Extensionはload/reload/unloadが可能です。
**Extensionのファイルにはsetup関数が必要です。**このsetup関数は、Extensionがloadされたときに必ず呼び出されます。
逆に、unloadされたときにはteardown関数が呼び出されます。

例えば:

async def setup(bot):
    print('ロードされました')

とだけ書いたファイルを読み込めば、それだけでExtensionを使うことができます。

Extensionの例はこちら

CogとExtensionの合わせ技

世の中にあるCogは、例えば:

from cogfile import MyCog
from discord.ext import commands

bot = commands.Bot()

...
await bot.add_cog(MyCog(bot))

とすることでロードできますが、Cogの中身を変えたときにBotを落とさずリロードしたいことがあります。そんなとき、CogとExtensionの合わせ技を使うと、超絶簡単にかけるのです!:

cogfile.py
from discord.ext import commands


class MyCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.Cog.listener(name='on_message')
    async def good_reaction(self, message):
        if message.author.bot:
            return
        if 'いいね' in message.content:
            await message.add_reaction('\U0001f44d')


# これが重要
async def setup(bot):
    await bot.add_cog(MyCog(bot))

こうして

# from cogfile import MyCog
from discord.ext import commands

bot = commands.Bot()

# bot.add_cog(MyCog(bot))
...
await bot.load_extension('cogfile')

とすることで、ホットリロードができる形でロードできます!

注意

世の中にあるCogは8割ほどがCogとExtensionを両方使用しているものですが、それを写したときにsetup関数を忘れエラーになる人が多いです。setup関数は必須です

また、CogとExtensionは別物です!同じものと勘違いをされている方がいるので、是非教えてあげてください。

さいごに

CogやExtensionでこういう説明/解説が欲しい!という方は、是非コメントにお書きください。

25
16
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
25
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?