diff --git a/docs/ext/commands/cogs.rst b/docs/ext/commands/cogs.rst index df2d9cdc1..8a87d5db9 100644 --- a/docs/ext/commands/cogs.rst +++ b/docs/ext/commands/cogs.rst @@ -11,6 +11,7 @@ The gist: - Each cog is a Python class that subclasses :class:`.commands.Cog`. - Every command is marked with the :func:`.commands.command` decorator. +- Every hybrid command is marked with the :func:`.commands.hybrid_command` decorator. - Every listener is marked with the :meth:`.commands.Cog.listener` decorator. - Cogs are then registered with the :meth:`.Bot.add_cog` call. - Cogs are subsequently removed with the :meth:`.Bot.remove_cog` call. diff --git a/docs/ext/commands/commands.rst b/docs/ext/commands/commands.rst index 016168da6..22e568b06 100644 --- a/docs/ext/commands/commands.rst +++ b/docs/ext/commands/commands.rst @@ -1176,3 +1176,76 @@ For example, to block all DMs we could do the following: Be careful on how you write your global checks, as it could also lock you out of your own bot. .. need a note on global check once here I think + + +Hybrid Commands +--------------- + +.. versionadded:: 2.0 + +:class:`.commands.HybridCommand` is a command that can be invoked as both a text and a slash command. +This allows you to define a command as both slash and text command without writing separate code for +both counterparts. + + +In order to define a hybrid command, The command callback should be decorated with +:meth:`.Bot.hybrid_command` decorator. + +.. code-block:: python3 + + @bot.hybrid_command() + async def test(ctx): + await ctx.send("This is a hybrid command!") + +The above command can be invoked as both text and slash command. Note that you have to manually +sync your :class:`~app_commands.CommandTree` by calling :class:`~app_commands.CommandTree.sync` in order +for slash commands to appear. + +.. image:: /images/commands/hybrid1.png +.. image:: /images/commands/hybrid2.png + +You can create hybrid command groups and sub-commands using the :meth:`.Bot.hybrid_group` +decorator. + +.. code-block:: python3 + + @bot.hybrid_group(fallback="get") + async def tag(ctx, name): + await ctx.send(f"Showing tag: {name}") + + @tag.command() + async def create(ctx, name): + await ctx.send(f"Created tag: {name}") + +Due to a Discord limitation, slash command groups cannot be invoked directly so the ``fallback`` +parameter allows you to create a sub-command that will be bound to callback of parent group. + +.. image:: /images/commands/hybrid3.png +.. image:: /images/commands/hybrid4.png + +Due to certain limitations on slash commands, some features of text commands are not supported +on hybrid commands. You can define a hybrid command as long as it meets the same subset that is +supported for slash commands. + +Following are currently **not supported** by hybrid commands: + +- Variable number of arguments. e.g. ``*arg: int`` +- Group commands with a depth greater than 1. +- Most :class:`typing.Union` types. + - Unions of channel types are allowed + - Unions of user types are allowed + - Unions of user types with roles are allowed + +Apart from that, all other features such as converters, checks, autocomplete, flags etc. +are supported on hybrid commands. Note that due to a design constraint, decorators related to application commands +such as :func:`discord.app_commands.autocomplete` should be placed below the :func:`~ext.commands.hybrid_command` decorator. +decorator. + +For convenience and ease in writing code, The :class:`~ext.commands.Context` class implements +some behavioural changes for various methods and attributes: + +- :attr:`.Context.interaction` can be used to retrieve the slash command interaction. +- Since interaction can only be responded to once, The :meth:`.Context.send` automatically + determines whether to send an interaction response or a followup response. +- :meth:`.Context.defer` defers the interaction response for slash commands but shows typing + indicator for text commands. diff --git a/docs/images/commands/hybrid1.png b/docs/images/commands/hybrid1.png new file mode 100644 index 000000000..08609c8bf Binary files /dev/null and b/docs/images/commands/hybrid1.png differ diff --git a/docs/images/commands/hybrid2.png b/docs/images/commands/hybrid2.png new file mode 100644 index 000000000..1d93efcf3 Binary files /dev/null and b/docs/images/commands/hybrid2.png differ diff --git a/docs/images/commands/hybrid3.png b/docs/images/commands/hybrid3.png new file mode 100644 index 000000000..a20ad9e20 Binary files /dev/null and b/docs/images/commands/hybrid3.png differ diff --git a/docs/images/commands/hybrid4.png b/docs/images/commands/hybrid4.png new file mode 100644 index 000000000..8c671b7ea Binary files /dev/null and b/docs/images/commands/hybrid4.png differ