Message commands
Create a message command
The bot listens for the
MessageCreateEvent
event. If the
message content begins with one of the bots prefixes and a command name
immediately following that, the bot will attempt to invoke the commands
callback.
Note
Yami converts type hints in your callbacks function signature for basic Python types automatically.
@bot.command("echo", aliases=["say"], invoke_with=True)
async def echo_cmd(ctx: yami.MessageContext, text: str) -> None:
"""Echos what you said back to you."""
await ctx.message.delete()
ctx.shared.message = await ctx.respond(text)
Create a message subcommand
Subcommands in Yami do not have a special class. The only designation
they receive is the is_subcommand
and the
parent
properties.
Note
The subcommand
decorator should be used
as a method of the callback function of the parent command.
Subcommands must also pass each
Check
bound to its parent commands.
In this example the subcommand provides and optional interface to delete the message sent by the parent command.
# continued from above...
@echo_cmd.subcommand("-d", aliases=["--delete"])
async def echo_delete_cmd(
ctx: yami.MessageContext, _: str, timeout: float = 10.0
) -> None:
"""Optionally deletes the message after the given timeout."""
if m := ctx.shared.message:
await asyncio.sleep(timeout)
await ctx.rest.delete_message(ctx.channel_id, m)
else:
await ctx.respond("Something went wrong - no message to delete.")
Sub-subcommands
You can chain subcommands down as far as you would like. There is nothing holding you back :).
Warning
Chaining subcommands does have some side effects to be aware of.
The
allow_extra_args
kwarg forBot
is very helpful for allowing you to align the arguments of your subcommands.Yami disables the callback for all parent commands by default. This can be set using the
invoke_with
kwarg in theyami.command
,yami.Bot.command
, andyami.MessageCommand.subcommand
decorators.Varying number and type for arguments in the command callbacks can cause failures. Pay close attention to what type hints and what argument positions you occupy in each callback, as well as what defaults you set.
yami.MessageContext.shared
can be a powerful tool when used to share information between parent commands and their subcommands. Keep in mind that if something goes wrong in the first callback, you may receive aSharedNone
if you access an attribute that has not been set in a later subcommands callback.
@bot.command("config")
async def config_cmd(ctx: yami.MessageContext) -> None:
"""Configuration command."""
...
@config_cmd.subcommand("exp", aliases=["experience"])
async def exp_subcmd(ctx: yami.MessageContext) -> None:
"""Configures server experience gain."""
...
@exp_subcmd.subcommand("on")
async def exp_on_subcmd(ctx: yami.MessageContext) -> None:
"""Turns experience on."""
...
@exp_subcmd.subcommand("off")
async def exp_off_subcmd(ctx: yami.MessageContext) -> None:
"""Turns experience off."""
...