Хорошая практика
Выполнение кода при загрузке кога
Большинство людей привыкли выполнять всё в __init__
, но это не позволяет выполнять асинхронный код. В этом случае вы
можете использовать метод cog_load
.
class MyCog(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
async def cog_load(self):
self.data = await bot.fetch_database_data()
@commands.slash_command()
async def command(self, interaction: disnake.ApplicationCommandInteraction, user: disnake.User):
await interaction.response.send_message(self.data[user.id])
Перезагрузка вашего бота
Одной из менее известных функций библиотеки disnake являет reload
(перезагрузка) - именованный аргумент для вашего
бота. Он перезагружает дополнения каждый раз, когда они редактируются, позволяя вам тестировать свой код в реальном
времени. Это особенно полезно, если запуск бота занимает много времени, так как будет перезагружаться только одно
дополнение.
from disnake.ext import commands
bot = commands.Bot(..., reload=True)
Это следует использовать исключительно для отладки. Пожалуйста, не используйте это в продакшн (production).
Преобразование аргументов в командах
discord.py использовал класс Converter
для преобразования аргументов, если они указаны. Однако их было очень сложно
использовать с проверкой типов, потому что тип параметка на самом деле никогда не является самим преобразователем.
Disnake стремиться устранить эту проблему, разрешая преобразование только встроенных типов, так как disnake.Member
,
disnake.Emoji
и т.д. Если вы когда-нибудь захотите иметь свой преобразователь, вы должны использовать аргумент
converter
в Param
.
- disnake
- discord.py
async def convert_data(inter: disnake.ApplicationCommandInteraction, arg: str):
parts = arg.split(",")
return {"a": parts[0], "b": int(parts[1]), "c": parts[2].lower()}
@commands.slash_command()
async def command(
self,
inter: disnake.ApplicationCommandInteraction,
data: Dict[str, Any] = commands.Param(converter=convert_data),
):
...
class DataConverter(commands.Converter):
async def convert(self, ctx: commands.Context, arg: str):
parts = arg.split(",")
return {"a": parts[0], "b": int(parts[1]), "c": parts[2].lower()}
@commands.command()
async def command(self, ctx: commands.Context, data: DataConverter):
...
Если вы хотите иметь возможность использовать классы, вы можете использовать декоратор @classmethod
. В качестве
альтернативы, установить метод класса в качестве преобразователя, используя converter_method
- classmethod converter
- converter method
from dataclasses import dataclass
@dataclass
class Data:
a: str
b: int
@classmethod
async def from_option(cls, inter: disnake.CommandInteraction, arg: str):
a, b = arg.split(",")
return cls(a, int(b))
@commands.slash_command()
async def command(
self,
inter: disnake.CommandInteraction,
data: Data = commands.Param(converter=Data.from_option),
):
...
from dataclasses import dataclass
@dataclass
class Data:
a: str
b: int
@commands.converter_method
async def from_option(cls, inter: disnake.CommandInteraction, arg: str):
a, b = arg.split(",")
return cls(a, int(b))
@commands.slash_command()
async def command(
self,
inter: disnake.CommandInteraction,
data: Data,
):
...
Цели контекстных команд
Вместо использования inter.target
вы можете использовать параметр в вашей команды.
@commands.user_command()
async def command(self, inter: disnake.ApplicationCommandInteraction, user: disnake.User):
await inter.response.send_message(f"Used on {user.mention}")
Описания слэш команды
Вы можете использовать документационные строки для описания команд и аргументов. Всё, что находится перед
Parameters
, является описанием команды. Всё, что находиться ниже Paramaters
, - это описания аргументов.
@commands.slash_command()
async def command(
self,
inter: disnake.ApplicationCommandInteraction,
category: str,
item: str,
details: bool,
):
"""Показать информацию о товаре
Parameters
----------
category: Категория поиска
item: Товар для отображения
details: Подробности, которые нужно узнать
"""
Команды только для серверов
В то время как disnake предоставляет декоратор @commands.guild_only()
, он по-прежнему требует вас обрабатывать
guild
как необязательный в случае, если вы используете линтеры. Для решения этой проблемы вы должны использовтаь
GuildCommandInteraction
.
# до
@commands.slash_command()
@commands.guild_only()
async def command(inter: disnake.ApplicationCommandInteraction):
assert inter.guild is not None
await inter.send(inter.guild.name)
# после
@commands.slash_command()
async def command(inter: disnake.GuildCommandInteraction):
await inter.send(inter.guild.name)