Slash Commands
Slash commands is the go-to way for users to interact with your bot on Discord.
They provide a lot of benefits over traditional message-based commands, such as:
- Discoverability: Users can easily find available commands by typing
/in the chat. - Structured Input: Commands can have predefined options and parameters, reducing user errors.
- Permissions Handling: Discord can automatically handle command permissions based on user roles (e.g. some commands are only available to moderators).
- Autocomplete: Commands can provide suggestions as users type, making it easier to use complex commands.
…and more!
Creating your first Slash Command
Let’s create the hello world equivalent of slash commands, aka “The Ping Pong Command”.
The user will run the /ping command and the bot will respond with Pong!.
Define the Command
var (
token = os.Getenv("DISCORD_BOT_TOKEN")
guildID = snowflake.GetEnv("DISCORD_GUILD_ID")
commands = []discord.ApplicationCommandCreate{
discord.SlashCommandCreate{
Name: "ping",
Description: "Respond with Pong!",
},
}
)A discord slash command is defined using the discord.SlashCommandCreate struct.
It requires a Name and optionally a Description.Name is what the user will type after the / to invoke the command.
Create the Command Handler
We defined our command, now we need to create a handler that will be called when a user uses our command.
func pingCommandHandler(data discord.SlashCommandInteractionData, e *handler.CommandEvent) error {
return e.CreateMessage(discord.MessageCreate{
Content: "Pong!",
})
}This function listens for ApplicationCommandInteractionCreate events, which are triggered when a user uses an application command (Slash Command being one of them).
Register the Command
In order to use our command in Discord, we first need to register it with Discord’s API.
You can register commands globally (available in all guilds your bot is in) or per-guild (only available in specific guilds).
We’re going to take a look at how to register a command in a specific guild first, as it allows for faster testing and iteration. (Also you don’t want to deploy commands globally while you’re still testing them!)
//... inside main function, before creating the client
h := handler.New()
h.SlashCommand("/ping", pingCommandHandler)
if err := handler.SyncCommands(client, commands, []snowflake.ID{guildID}); err != nil {
panic(err)
}
//... when creating the client
bot.WithEventListeners(h),This code snippet does a few things:
- It creates a new handler using
handler.New(). - It registers our
pingCommandHandlerfunction to handle the/pingcommand usingh.SlashCommand. - It synchronizes our defined commands with Discord using
handler.SyncCommands, specifying the guild ID where we want to register the command. - It adds the handler as an event listener to the bot client using
bot.WithEventListeners(h).
If you’ve been following along, your updated main.go file should now look like this:
| |
Now try to run your bot and use the /ping command in your specified guild! You should see your bot respond with Pong!. 🏓
/ping command in your guild, try to refresh Discord (Ctrl + R / ⌘ + R) or wait a couple of minutes as sometimes it takes a bit of time for new commands to appear.Creating a Commands Directory
If you’ve been following this tutorial, our project directory should now look like this
- go.mod
- go.sum
- main.go
All our code is currently in the main.go file. While this is fine for small bots, as your bot grows in complexity, it’s a good idea to start organizing your code into separate files and directories. This makes it easier to manage and maintain your codebase.
Make a new folder called 📂commands/ in the root of your project directory. This folder will hold all your command-related code.
Make a file in it called commands.go that will contain our slash command code.
package commands
import (
"github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/handler"
)
var Commands = []discord.ApplicationCommandCreate{
discord.SlashCommandCreate{
Name: "ping",
Description: "Respond with Pong!",
},
}
func PingCommandHandler(data discord.SlashCommandInteractionData, e *handler.CommandEvent) error {
return e.CreateMessage(discord.MessageCreate{
Content: "Pong!",
})
}Then, update your main.go file to use the new commands package.
import(
//... other imports
"awesome-discord-bot/commands"
)
//... inside main function, after creating the client
h.SlashCommand("/ping", commands.PingCommandHandler)
if err := handler.SyncCommands(client, commands.Commands, []snowflake.ID{guildID}); err != nil {
panic(err)
}You can choose to add more commands in this file or create separate files for each command as your bot grows.