Skip to main content

Registering Chat Input Commands

A Chat Input Command can be registered to the Discord API by letting the command registry know about its existence. To do so we need to use the registerApplicationCommands to have access to the ApplicationCommandRegistry to perform operations on it. You can learn how to do this on the page Acquiring an Application Command Registry.

How to register a Chat Input Command

The easiest way to register a Chat Input Command is to implement the registerApplicationCommands method on a Command class. In that method the first parameter is the ApplicationCommandRegistry (commonly called registry in code) on which you can call registerChatInputCommand. This looks like:

import { Command } from '@sapphire/framework';export class SlashCommand extends Command {  public constructor(context: Command.Context, options: Command.Options) {    super(context, {      ...options,      description: 'Send a Slash Command.'    });  }  public override registerApplicationCommands(registry: Command.Registry) {    registry.registerChatInputCommand((builder) =>      builder //        .setName(this.name)        .setDescription(this.description)    );  }  public override chatInputRun(interaction: Command.ChatInputInteraction) {    // ...  }}
info

We use // next to builder // here to short-circuit Prettier putting everything on the same line. If you do not use prettier you can remove this, or if you do not care for it being on the same line then you can remove it.

In this code snippet we have registered the Chat Input Command in the most simple way referencing the already defined name and description. We also use the builder pattern which means you get verification of your input before a command gets registered in a faulty way. It will also make sure that you are not providing unnecessary or incorrect JSON keys because you're not building the JSON yourself. All that said, it is the method we recommend everyone to use. If you are experienced with Chat Input Commands you can also opt to write your own raw JSON object, however this guide will not cover that.

In the code snippet above we passed 1 parameter to the registerChatInputCommand method, to build the object that gets send to Discord for registering the command. The registerChatInputCommand however also takes a second parameter which we will cover next.

Registering Chat Input Commands with options

Shown above is how to register a Chat Input Command without options, but in many cases you will actually want to receive some data from the user, which is where options come in. Options are similar to the Arguments that Sapphire offers for Message Commands, however they are built right into Discord.

In this example we will add an option that will prompt the user of the command to select another user that they want to greet. This option is required and the command will not send at all if the option is not provided. This is really useful as compared to Sapphire Arguments you no longer have to validate whether a required argument was provided or not.

import { Command } from '@sapphire/framework';export class SlashCommand extends Command {  public constructor(context: Command.Context, options: Command.Options) {    super(context, {      ...options,      description: 'Say hello to a user.'    });  }  public override registerApplicationCommands(registry: Command.Registry) {    registry.registerChatInputCommand((builder) =>      builder //        .setName(this.name)        .setDescription(this.description)        .addUserOption((option) =>          option //            .setName('user')            .setDescription('User to say hello to')            .setRequired(true)        )    );  }  public override chatInputRun(interaction: Command.ChatInputInteraction) {    // ...  }}

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 the meta options that is passed into the command registry for a Chat Input Command to control its behavior. Let's take a look on them one by one.

idHints

These are the unique command ids from the Discord API that the registry uses to identify the command in case you decide to change the name of the command. Normally if you would change the name without providing idHints then a new command would get registered, instead of overwriting the existing command. We therefore strongly recommend you to specify the idHints.

On top of the advantages in registering the command, having the ID of a command noted somewhere will also help you identify the command elsewhere in your code, such as in interaction handlers.

When Sapphire registers a application command it will log the command id for the command in console with the help of default logger provided by Sapphire. The command ID is logged on the info level, which is the default, however, if you have configured the Sapphire Logger to only log errors or fatal messages then please check Configuring Log Level Guide to learn how to change it.

guildIds

This is an array of guild ids for which the command should be registered. By default it is undefined, which means that the command will be registered for all guilds (i.e. globally). If you want to register the command for a specific guild, you can pass in the guild id in the command registry.

note

When the guildIds is an empty array the command will also be registered globally. This is useful for when you're getting the guildIds from an external source, i.e. through a getGuildIds function. You can make that external source default to an empty array which is often easier than undefined, especially when it comes from an external source that using a difference programming language from JavaScript/TypeScript (i.e. an external API or database).

behaviorWhenNotIdentical

This options tells the registry that how to behave when the command is not identical to the one which is already registered on Discord API. By default it's set to OVERWRITE which means that when there is a difference between your local code and the Discord API then the data on the Discord API will get overwritten.

If you want the registry to only inform you about differences with logging, you can 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.

Chat Input Command Registry Methods

danger

To register a Chat Input Command, you need to acquire the ApplicationCommandRegistry. Please see the ApplicationCommandRegistry section for more details.

registerChatInputCommand

The method which is responsible for telling the registry that this command should be registered. It takes two parameters:

An example of this method was shown above at How to register a Chat Input Command.

addChatInputCommandNames

The command names which let the registry know that these names should trigger the registry. These names doesn't register the command but only let the registry know that these names should trigger the command, i.e. the names are only stored in command store to be used by the registry. Names can be passed as strings.

addChatInputCommandIds

The command ids that informs the registry to trigger it for the specified ids only. Ids can be passed as strings.

danger

addChatInputCommandNames or addChatInputCommandIds should only be used when you don't want Sapphire to manage the application commands automatically for you else consider using idHints instead.

Whenever the addChatInputCommandIds method is called with an invalid id (we expect a string that can be turned into a BigInt), then it will ALWAYS warn in the console. No, this cannot be turned off.

Full Example

Now that we have covered everything there is to registering a Chat Input Command lets look at how a full example could look like. This builds on the examples provided above while also implementing the chatInputRun method to read the option and send a response.

import { Command } from '@sapphire/framework';import { Formatters } from 'discord.js';export class SlashCommand extends Command {  public constructor(context: Command.Context, options: Command.Options) {    super(context, {      ...options,      description: 'Say hello to a user.'    });  }  public override registerApplicationCommands(registry: Command.Registry) {    registry.registerChatInputCommand((builder) =>      builder //        .setName(this.name)        .setDescription(this.description)        .addUserOption((option) =>          option //            .setName('user')            .setDescription('User to say hello to')            .setRequired(true)        )    );  }  public override chatInputRun(interaction: Command.ChatInputInteraction) {    const userToGreet = interaction.options.getUser('user', true);    const userToGreetMention = Formatters.userMention(userToGreet.id);    const interactionUserMention = Formatters.userMention(interaction.user.id);    return interaction.reply({      content: `Hey ${userToGreetMention}, ${interactionUserMention} says hello!`,      allowedMentions: {        users: [userToGreet.id, interaction.user.id]      }    });  }}