Cogs¶
В определенный момент при разработке бота возникнет ситуация, в которой вы захотите организовать команды, события и какие-то переменные состояния в отдельный класс. Cog’и существуют как раз для этого.
Основы:
Каждый cog - класс который является сабклассом
cog.Cog
.Каждая команда объявляется с декоратором
commands.command()
.Каждый листенер объявляется с декоратором
cog.Cog.listener()
.Cog’и добавляются в бота с помощью метода
Bot.add_cog()
.После чего можно использовать
Bot.remove_cog()
чтобы удалить их.
Пример¶
Этот пример создает cog с названием Greetings
, который содержит одну команду с названием hello
и одно событие.
class Greetings(cog.Cog):
def __init__(self, bot):
self.bot = bot
self._last_user = None
@cog.Cog.listener()
async def on_chat_invite_user(self, message):
user = await self.bot.get_user(message.action.member_id)
await message.send('Welcome {0.mention}!'.format(user))
@commands.command()
async def hello(self, ctx, user_id: int = None):
"""Says hello"""
user_id = user_id or ctx.author
user = await self.bot.get_user(user_id)
if self._last_user is None or self._last_user != user_id:
await ctx.send('Hello {0.mention}~'.format(user))
else:
await ctx.send('Hello {0.mention}... This feels familiar.'.format(user))
self._last_user = user_id
Пара технических деталей которые стоит взять на заметку:
Все листенеры должны быть объявлены с декоратором
listener()
.Название cog’а автоматически берется из названия класса, но может быть переназначено (см. Настройки метаданных).
Все команды теперь должны содержать параметр
self
для возможности использования аттрибутов экземпляра которые используются для сохранения состояния.
Добавление Cog’ов¶
После объявления cog’ов, их надо добавить в бота с помощью метода add_cog()
.
bot.add_cog(Greetings(bot))
Этот метод привязывает cog к боту, автоматически добавляя в него все команды и события.
Важно заметить, что cog упоминается с помощью названия, которое можно изменить через Настройки метаданных. Так что если этот ког в определенный момент необходимо удалить, это делается так.
bot.remove_cog('Greetings')
Использование Cog’ов¶
Так же как и удалить, cog можно получить по его названию. Это позволяет использовать cog для взаимодействия между командами. Например:
class Economy(cog.Cog):
...
async def withdraw_money(self, member, money):
# implementation here
...
async def deposit_money(self, member, money):
# implementation here
...
class Gambling(cog.Cog):
def __init__(self, bot):
self.bot = bot
def coinflip(self):
return random.randint(0, 1)
@commands.command()
async def gamble(self, ctx, money: int):
"""Gambles some money."""
economy = self.bot.get_cog('Economy')
if economy is not None:
await economy.withdraw_money(ctx.author, money)
if self.coinflip() == 1:
await economy.deposit_money(ctx.author, money * 1.5)
Особые методы¶
Когда cog’и становятся более сложными и количество команд в них растет, наступает момент когда их хочется более сильно персонализировать.
Для этого есть следующие методы:
Для более подробной информации можно посмотреть на эти методы в справочнике.
Настройки метаданных¶
В основе cog’а лежит метакласс cog.CogMeta
, который принимает различные настройки, позволяющие персонализировать некоторые аспекты cog’ов. Для этого необходимо передать аргументы с ключевыми словами в строку объявления класса. Например чтобы поменять имя cog’а, можно передать аргумент name
примерно так:
class MyCog(cog.Cog, name='My Cog'):
pass
Больше опций можно найти в справке к классу cog.CogMeta
.
Просмотр свойств¶
Так как cog’и по сути являются просто классами, некоторые их свойства можно просматривать.
Чтобы получить list
команд, можно использовать Cog.get_commands()
.
>>> cog = bot.get_cog('Greetings')
>>> commands = cog.get_commands()
>>> print([c.name for c in commands])
Чтобы получить события, можно использовать Cog.get_listeners()
. Этот метод возвращает список кортежей – первый элемент которого - название события, а второй - сама функция.
>>> for name, func in cog.get_listeners():
... print(name, '->', func)