On March 24, 2021, Discord added Slash Commands to Discord as an easier, more efficient, and better way of using bot commands. Pycord has implemented Slash Commands into the library, so it's simple, efficient, and familiar.
info
Remember that Slash Commands require your bot to be invited with the application.commands
scope or Slash Commands will not show up. Bots already in the guild can simply be invited again with the scope; there is no need to kick the bot.
Let's create a simple Slash Command.
import discord
bot = discord.Bot()
# we need to limit the guilds for testing purposes
# so other users wouldn't see the command that we're testing
@bot.command(description="Sends the bot's latency.") # this decorator makes a slash command
async def ping(ctx): # a slash command will be created with the name "ping"
await ctx.respond(f"Pong! Latency is {bot.latency}")
bot.run("TOKEN")
BobDotComused /ping
RobocordBot06/05/2024
Pong! Latency is 335ms.
Let's go through the code.
First, we import Pycord's discord
package.
Next, we create a discord.Bot object and assign it to a variable bot
.
We then go ahead and use the @bot.command decorator, which registers a new Slash Command. We pass a description
parameter to give a description to the Slash Command. We can also pass a name
parameter to change the Slash Command's name. By default, the name of the Slash Command will be the name of the function, in this case, /ping
.
We create an async function called ping
with parameters ctx
, which, when called, sends the bot's ping/latency using ctx.respond.
Subcommand Groups
You might want to group certain commands together to make them more organised. A command group is exactly what it sounds like, a group of individual Slash Commands together.
In order to make a Slash Command group, you can use the bot.create_group
function.
import discord
bot = discord.Bot()
# create Slash Command group with bot.create_group
greetings = bot.create_group("greetings", "Greet people")
@greetings.command()
async def hello(ctx):
await ctx.respond(f"Hello, {ctx.author}!")
@greetings.command()
async def bye(ctx):
await ctx.respond(f"Bye, {ctx.author}!")
bot.run("TOKEN")
Or, you can instead manually make a SlashCommandGroup
class like so:
import discord
math = discord.SlashCommandGroup("math", "Math related commands")
@math.command()
async def add(ctx, num1: int, num2: int):
sum = num1 + num2
await ctx.respond(f"{num1} plus {num2} is {sum}.")
@math.command()
async def subtract(ctx, num1: int, num2: int):
sum = num1 - num2
await ctx.respond(f"{num1} minus {num2} is {sum}.")
# you'll have to manually add the manually created Slash Command group
bot.add_application_command(math)
Here's what the registered subcommands will look like in the Slash Command Menu:
You'll notice that there's the name of the Slash Command Group and then the name of the subcommand separated by a space.
:::
Cogs
If you are looking to add Slash Command Groups to cogs, please look at our Cogs page!
We've made a subcommand group, but did you know that you could create a group inside another?
from discord import SlashCommandGroup
from math import sqrt
math = SlashCommandGroup("math", "Math related commands")
advanced = math.create_subgroup("advanced", "Advanced math commands")
@advanced.command()
async def square_root(ctx, x: int):
await ctx.respond(sqrt(x))
bot.add_application_command(math)
The command created above can be invoked by typing /math advanced square_root
.
Options & Option Types
Whenever you're using Slash Commands, you might notice that you can specify parameters that the user has to set or can optionally set. These are called Options.
Options can also include a description to provide more information. You can learn more about Options in our documentation!
Since you want different inputs from Options, you'll have to specify the type for that Option; there are a few ways of doing this.
- Using Type Annotations
- Using option decorator
You could use Type Annotations and let Pycord figure out the option type or explicitly specified using the SlashCommandOptionType enum.
import discord
bot = discord.Bot()
@bot.command()
# pycord will figure out the types for you
async def add(ctx, first: discord.Option(int), second: discord.Option(int)):
# you can use them as they were actual integers
sum = first + second
await ctx.respond(f"The sum of {first} and {second} is {sum}.")
@bot.command()
# this explicitly tells pycord what types the options are instead
async def join(
ctx,
first: discord.Option(discord.SlashCommandOptionType.string),
second: discord.Option(discord.SlashCommandOptionType.string)
):
joined = first + second
await ctx.respond(f"When you join \"{first}\" and \"{second}\", you get: \"{joined}\".")
bot.run("TOKEN")
BobDotComused /add
RobocordBot06/05/2024
The sum of 1 and 1 is 2.
BobDotComused /join
RobocordBot06/05/2024
When you join "Py" and "cord", you get: "Pycord".
Discord's autocomplete allows developers to determine option choices that are used in a slash command option. You can do this by defining a function:
async def get_animal_types(ctx: discord.AutocompleteContext):
"""
Here we will check if 'ctx.options['animal_type']' is a marine or land animal and return respective option choices
"""
animal_type = ctx.options['animal_type']
if animal_type == 'Marine':
return ['Whale', 'Shark', 'Fish', 'Octopus', 'Turtle']
else: # is land animal
return ['Snake', 'Wolf', 'Lizard', 'Lion', 'Bird']
@bot.slash_command(name="animal")
async def animal_command(
ctx: discord.ApplicationContext,
animal_type: discord.Option(str, choices=['Marine', 'Land']),
animal: discord.Option(str, autocomplete=discord.utils.basic_autocomplete(get_animal_types))
):
await ctx.respond(f'You picked an animal type of `{animal_type}` that led you to pick `{animal}`!')
BobDotComused /animal
RobocordBot06/05/2024
You picked an animal type of Marine
that led you to pick Shark
!
danger
Autocomplete can only be used with slash commands.
Related Topics
- Interactions Index
- Rules and Common Practices
- Cogs