はじめに
こんにちは。
しゅみでdiscordのbotをつくったりしているものです。
discord.py(rewrite版)の Cog を触ってみたので備忘として残しておこうと思います。
前提
Discord向けのbotを実装するにはいくつか選択肢がありますが、pythonで実装する場合は Rapptz/discord.py を使う人が多いと思います。
disocord.pyには「async版」と「rewrite版」という2つのバージョンが存在します。
2つのバージョンの違いについては以下の記事にあるとおりです。
現在おもに開発が続いているのは「rewrite版」のほうです。
Cogとは
Cogという単語をググった結果、
Cog
主な意味 (歯車の)歯、(企業・事業などで)必要だがつまらぬ仕事をしている人、「歯車」
らしいです。
ではdiscord.pyのCogはどういうものかというと、
There comes a point in your bot's development when you want to organize a collection of commands, listeners, and some state into one class. Cogs allow you to do just that.
複数のコマンドやリスナーをまとめたり、様々なステータスをクラス化したい時に使えるフレームワーク
と説明されています。
コマンドやリスナーなどをbotを構成する歯車として機能単位で分割するイメージでしょうか。
これまでは冗長になってくると都度モジュール化したりしてましたが、Cogを使えばもっとシンプルに実装できそうです。
実装
絵文字を揃えて遊ぶ「slot」というコマンドをCogとして切り出してみようと思います。
(コマンドの処理ロジックはここでは割愛します)
Cogとして実装する為には以下の要件を満たす必要があります。
-
commands.Cog
のサブクラスであること - コマンドは
commands.command()
で修飾されること - リスナーは
commands.Cog.listener()
で修飾されること - Cogは
Bot.add_cog()
を呼んでbotに登録する - 登録したCogを削除する場合は
Bot.remove_cog()
を呼ぶ
上記を踏まえて以下のように実装してみました。
import configparser
import random
from discord.ext import commands
class Game(commands.Cog):
def __init__(self, bot, config):
self.bot = bot
self.config = config
self.slot_game_counter = 0
self.bingo_game_counter = 0
@commands.command()
async def slot(self, ctx):
# 内部処理
await ctx.send(message)
def setup(bot, config):
bot.add_cog(Game(bot, config))
commands.Cog
のサブクラスとしてGame
というクラスを定義しました。
__init__
で必要なパラメータを引数で受け取りプロパティとして保持しています。
コマンドは@commands.command()
アノテーションを付与しています。
これをcogs
というフォルダに置きました。
次はこのCogをbotに登録します。
botの本体を以下のように実装します。
import os
import configparser
import discord
import random
import cogs.game as game
from discord.ext import commands
config = configparser.ConfigParser()
config.read('src/config.ini')
bot = commands.Bot(command_prefix='!')
async def send2developer(text):
developer = bot.get_user(config.getint('BOT', 'developer'))
dm = await developer.create_dm()
await dm.send(text)
@bot.event
async def on_ready():
print('------')
print('Logged in as')
print(bot.user.name)
print(bot.user.id)
print('------')
text = f'Logged on as {bot.user}!'
game.setup(bot, config)
await send2developer(text)
bot.run(os.environ['BOT_TOKEN'])
cogs.game
をimportし、on_ready
関数内でGame
クラスのsetup
関数を呼び出しています。
setup
関数内で引数に渡ってきたbotに対してadd_cog
で登録するというフローです。
おわり
この記事ではCogの基本的な使い方を試してみました。
(この記事を下書きしている間に有志の方がドキュメントを日本語訳されていました)
・コグ
discord.pyは使いやすいフレームワークです。
開発や有志の方によるドキュメント翻訳など活発に活動しているようなので、またなにか学んだら記事を書こうと思います。
最後まで読んでいただきありがとうございました!