Skip to main content

Registering Chat Input Commands

warning

To register a Chat Input Command (also known as a Slash Command) with Discord, you need to acquire an application command registry. If you missed how to do it, please see the Acquiring an Application Command Registry section for more details.

How to register a Chat Input Command

To register a Chat Input Command, implement the registerApplicationCommands method for the Command class. The method's parameter will be the command's pre-defined ApplicationCommandRegistry, on which you can call registerChatInputCommand to register your application command.

A brief breakdown of registerChatInputCommand

This method is responsible for describing how a Chat Input Command will be registered. It takes two parameters:

An example looks like the following:

const { Command } = require('@sapphire/framework');

class SlashCommand extends Command {
constructor(context, options) {
super(context, {
...options,
description: 'Send a Slash Command.'
});
}

registerApplicationCommands(registry) {
registry.registerChatInputCommand((builder) =>
builder //
.setName(this.name)
.setDescription(this.description)
);
}

chatInputRun(interaction) {
// ...
}
}
module.exports = {
SlashCommand
};
info

We're using // next to builder // to prevent Prettier from formatting everything on the same line. If you do not use Prettier, or don't care, you can remove this.

In the example above, we reused the class' name and description fields for brevity. However, you may set those to something else and the application command registry will still route the application command to the command.

We recommend most people use the SlashCommandBuilder as the argument for the registerChatInputCommand method, since it will ensure the data sent to Discord is properly structured. If you need more control over the application command, you can write the discord.js ApplicationCommandData JSON object yourself as the argument instead.

Registering Chat Input Commands with options

Chat Input Commands can take in options, which are similar to arguments for a function. These are similar to the Arguments that Sapphire offers for Message Commands, but they are built right into Discord instead!

const { Command } = require('@sapphire/framework');

class SlashCommand extends Command {
constructor(context, options) {
super(context, {
...options,
description: 'Say hello to a user.'
});
}

registerApplicationCommands(registry) {
registry.registerChatInputCommand((builder) =>
builder //
.setName(this.name)
.setDescription(this.description)
.addUserOption((option) =>
option //
.setName('user')
.setDescription('User to say hello to')
.setRequired(true)
)
);
}

chatInputRun(interaction) {
// ...
}
}
module.exports = {
SlashCommand
};

In this example, we will add an option that will ask for another user as input. The option can be configured with setRequired(true), which means Discord natively prevents the chat input command from ever being run if it isn't provided. This is really nice compared to using Sapphire's Arguments for input validation in message commands.

There are many other types of options that you can add to your Chat Input Command, and you can read all about them on the discord.js guide.

Chat Input Command Registry Options

These are options that we can pass into the registerChatInputCommand method as a second argument, not to be confused with a Chat Input Command's options in the previous section. Let's take a look at them below!

idHints

At a high level, an application command registry maps application command IDs and/or names to your command. By providing ID(s) to the idHints option, we can prevent new commands from accidentally being created.

warning

As mentioned in What is it?, Discord manages "Application Command Objects" on their end for each of your application commands. Whenever your bot registers a new application command with Discord, they create and store a new object like this:

{
"id": "1223334444555554444",
"application_id": "...",
// ...
"name": "foo",
"description": "bar!"
}

Let's say you want to change the application command's name (what users see in Discord). If you don't provide the ID above to idHints, then the application command registry will register an entirely new command with the new name, and the old one will still be there! You can delete an application command through discord.js or by interacting with Discord's API directly, but it's better to prevent this in the first place!

The first time an application command is registered, Sapphire will log this ID at the info level to the console. We highly recommend you copy this ID and add it to idHints option array. If you miss it the first time, Sapphire will continue to log this ID at the debug level. If you have configured Sapphire's Logger to only log errors or fatal messages, please check Configuring Log Level Guide to learn how to change the log level visibility.

guildIds

Discord allows you to register application commands either globally or for specific guilds. Providing guild ids to guildIds will only register the application command to those guilds.

By default, this is undefined which registers the application command globally. However, an empty array acts the same way which may be useful if you're fetching guild ids from another source (i.e. an external API or database).

behaviorWhenNotIdentical

This option defines the registry's behavior when the application command's options in your code are not synced with Discord, such as a new description. It's set to OVERWRITE by default, which will always overwrite Discord's corresponding Application Command Object with the data in your code. If you only want the registry to log differences instead, you should set this option to LOG_TO_CONSOLE.

registerCommandIfMissing

This is an option that defaults to true. If set to false, the command will not be registered if it is not already registered in the Discord API.

info

You will likely never have to touch this option, but it can be useful if you are not using Sapphire to register your commands and instead you're using something external to do so.

Implementing a Chat Input Command

Now that we've covered registering a Chat Input Command with Discord, the last step is to implement the chatInputRun method for the Command class so your bot can respond!

const { Command } = require('@sapphire/framework');
const { userMention } = require('discord.js');

class SlashCommand extends Command {
constructor(context, options) {
super(context, {
...options,
description: 'Say hello to a user.'
});
}

registerApplicationCommands(registry) {
registry.registerChatInputCommand((builder) =>
builder //
.setName(this.name)
.setDescription(this.description)
.addUserOption((option) =>
option //
.setName('user')
.setDescription('User to say hello to')
.setRequired(true)
)
);
}

chatInputRun(interaction) {
const userToGreet = interaction.options.getUser('user', true);

const userToGreetMention = userMention(userToGreet.id);
const interactionUserMention = userMention(interaction.user.id);

return interaction.reply({
content: `Hey ${userToGreetMention}, ${interactionUserMention} says hello!`,
allowedMentions: {
users: [userToGreet.id, interaction.user.id]
}
});
}
}
module.exports = {
SlashCommand
};

The chatInputRun example above uses interaction handlers, which are detailed in that section.