Slash Commands¶
So you want to make a slash command (or interaction, as they are officially called), but don't know how to get started? Then this is the right place for you.
Your First Command¶
To create an interaction, simply define an asynchronous function and use the @slash_command()
decorator above it.
Interactions need to be responded to within 3 seconds. To do this, use await ctx.send()
. If your code needs more time, don't worry. You can use await ctx.defer()
to increase the time until you need to respond to the command to 15 minutes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Note
Command names must be lowercase and can only contain -
and _
as special symbols and must not contain spaces.
When testing, it is recommended to use non-global commands, as they sync instantly. For that, you can either define scopes
in every command or set debug_scope
in the bot instantiation which sets the scope automatically for all commands.
You can define non-global commands by passing a list of guild ids to scopes
in the interaction creation.
1 2 3 |
|
For more information, please visit the API reference here.
Subcommands¶
If you have multiple commands that fit under the same category, subcommands are perfect for you.
Let's define a basic subcommand:
1 2 3 4 5 6 7 8 9 10 |
|
This will show up in discord as /base group command
. There are more ways to add additional subcommands:
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 9 10 |
|
Note: This is particularly useful if you want to split subcommands into different files.
1 2 3 4 5 6 7 8 |
|
For all of these, the "group" parts are optional, allowing you to do /base command
instead.
Note
You cannot mix group subcommands and non-group subcommands into one base command - you must either use all group subcommands or normal subcommands.
Options¶
Interactions can also have options. There are a bunch of different types of options:
Option Type | Return Type | Description |
---|---|---|
OptionType.STRING | str | Limit the input to a string. |
OptionType.INTEGER | int | Limit the input to a integer. |
OptionType.NUMBER | float | Limit the input to a float. |
OptionType.BOOLEAN | bool | Let the user choose either True or False . |
OptionType.USER | Member in guilds, else User | Let the user choose a discord user from an automatically-generated list of options. |
OptionType.CHANNEL | GuildChannel in guilds, else DMChannel | Let the user choose a discord channel from an automatically-generated list of options. |
OptionType.ROLE | Role | Let the user choose a discord role from an automatically-generated list of options. |
OptionType.MENTIONABLE | DiscordObject | Let the user chose any discord mentionable from an automatically generated list of options. |
OptionType.ATTACHMENT | Attachment | Let the user upload an attachment. |
Now that you know all the options you have for options, you can opt into adding options to your interaction.
You do that by using the @slash_option()
decorator and passing the option name as a function parameter:
1 2 3 4 5 6 7 8 9 10 11 |
|
Options can either be required or not. If an option is not required, make sure to set a default value for them.
Always make sure to define all required options first, this is a Discord requirement!
1 2 3 4 5 6 7 8 9 |
|
For more information, please visit the API reference here.
Restricting Options¶
If you are using an OptionType.CHANNEL
option, you can restrict the channel a user can choose by setting channel_types
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
You can also set an upper and lower limit for both OptionType.INTEGER
and OptionType.NUMBER
by setting min_value
and max_value
:
1 2 3 4 5 6 7 8 9 10 11 |
|
The same can be done with the length of an option when using OptionType.STRING
by setting min_length
and max_length
:
1 2 3 4 5 6 7 8 9 10 11 |
|
Option Names
Be aware that the option name
and the function parameter need to be the same (In this example both are integer_option
).
Option Choices¶
If your users are dumb constantly misspell specific strings, it might be wise to set up choices. With choices, the user can no longer freely input whatever they want, instead, they must choose from a pre-defined list.
To create a choice, simply fill choices
in @slash_option()
. An option can have up to 25 choices. The name of a choice is what will be shown in the Discord client of the user, while the value is what the bot will receive in its callback. Both can be the same.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
For more information, please visit the API reference here.
Autocomplete / More than 25 choices needed¶
If you have more than 25 choices the user can choose from, or you want to give a dynamic list of choices depending on what the user is currently typing, then you will need autocomplete options. The downside is that you need to supply the choices on request, making this a bit more tricky to set up.
To use autocomplete options, set autocomplete=True
in @slash_option()
:
1 2 3 4 5 6 7 8 9 10 |
|
Then you need to register the autocomplete callback, aka the function Discord calls when users fill in the option.
In there, you have three seconds to return whatever choices you want to the user. In this example we will simply return their input with "a", "b" or "c" appended:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Command definition without decorators¶
There are currently four different ways to define interactions, one does not need any decorators at all.
1 2 3 4 5 6 7 8 9 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Restrict commands using permissions¶
It is possible to disable interactions (slash commands as well as context menus) for users that do not have a set of permissions.
This functionality works for permissions, not to confuse with roles. If you want to restrict some command if the user does not have a certain role, this cannot be done on the bot side. However, it can be done on the Discord server side, in the Server Settings > Integrations page.
Warning
Remember that administrators of a Discord server have all permissions and therefore will always see the commands.
If you do not want admins to be able to overwrite your permissions, or the permissions are not flexible enough for you, you should use checks.
In this example, we will limit access to the command to members with the MANAGE_EVENTS
and MANAGE_THREADS
permissions. There are two ways to define permissions.
1 2 3 4 5 6 |
|
1 2 3 4 5 6 7 8 |
|
Multiple permissions are defined with the bitwise OR operator |
.
Blocking Commands in DMs¶
You can also block commands in DMs. To do that, just set dm_permission
to false.
1 2 3 4 5 6 |
|
Checks¶
Checks allow you to define who can use your commands however you want.
There are a few pre-made checks for you to use, and you can simply create your own custom checks.
Check that the author is the owner of the bot:
1 2 3 4 5 6 |
|
Check that the author's username starts with a
:
1 2 3 4 5 6 7 8 9 |
|
You can reuse checks in extensions by adding them to the extension check list
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
The check will be checked for every command in the extension.
Avoid redefining the same option everytime¶
If you have multiple commands that all use the same option, it might be both annoying and bad programming to redefine it multiple times.
Luckily, you can simply make your own decorators that themselves call @slash_option()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
The same principle can be used to reuse autocomplete options.
Simplified Error Handling¶
If you want error handling for all commands, you can override the default error listener and define your own. Any error from interactions will trigger CommandError
. That includes context menus.
In this example, we are logging the error and responding to the interaction if not done so yet:
1 2 3 4 5 6 7 8 |
|
There also is CommandCompletion
which you can overwrite too. That fires on every interactions usage.
Custom Parameter Type¶
If your bot is complex enough, you might find yourself wanting to use custom models in your commands.
To do this, you'll want to use a string option, and define a converter. Information on how to use converters can be found on the converter page.
Prefixed/Text Commands¶
To use prefixed commands, instead of typing /my_command
, you will need to type instead !my_command
, provided that the prefix you set is !
.
Hybrid commands are are slash commands that also get converted to an equivalent prefixed command under the hood. They are their own extension, and require prefixed commands to be set up beforehand. After that, use the setup
function in the hybrid_commands
extension in your main bot file.
Your setup can (but doesn't necessarily have to) look like this:
1 2 3 4 5 6 7 |
|
To actually make slash commands, simply replace @slash_command
with @hybrid_slash_command
, and SlashContext
with HybridContext
, like so:
1 2 3 4 5 |
|
Suggesting you are using the default mention settings for your bot, you should be able to run this command by @BotPing my_command
.
As you can see, the only difference between hybrid commands and slash commands, from a developer perspective, is that they use HybridContext
, which attempts to seamlessly allow using the same context for slash and prefixed commands. You can always get the underlying context via inner_context
, though.
Of course, keep in mind that supporting two different types of commands is hard - some features may not get represented well in prefixed commands, and autocomplete is not possible at all.
Created: January 28, 2023