Skip to main content

Creating a basic slash command

Creating a basic slash command is very similar to creating a basic command. To create a slash command you will have to define the registerApplicationCommands method in the command class.

For example, let's create a ping command:

import { Command } from '@sapphire/framework';export class PingCommand extends Command {  public constructor(context: Command.Context, options: Command.Options) {    super(context, { ...options });  }  public override registerApplicationCommands(registry: ChatInputCommand.Registry) {    registry.registerChatInputCommand((builder) =>      builder.setName('ping').setDescription('Ping bot to see if it is alive')    );  }}

The above example will create a slash command (chat input command) called ping with the description Ping bot to see if it is alive. Alternatively, we can also use this.name and this.description to pass the name and description to the builder which will take the data from the passed values in command class.

Example:

import { Command } from '@sapphire/framework';export class PingCommand extends Command {  public constructor(context: Command.Context, options: Command.Options) {    super(context, { ...options, name: 'ping', description: 'Ping bot to see if it is alive' });  }  public override registerApplicationCommands(registry: ChatInputCommand.Registry) {    registry.registerChatInputCommand((builder) => builder.setName(this.name).setDescription(this.description));  }}

Creating the chatInputRun method

To handle the command callback when the context menu command is ran we need to override the chatInputRun method of command class.

import { isMessageInstance } from '@sapphire/discord.js-utilities';import { Command } from '@sapphire/framework';export class PingCommand extends Command {  public constructor(context: Command.Context, options: Command.Options) {    // ...  }  public async chatInputRun(interaction: Command.ChatInputInteraction) {    const msg = await interaction.reply({ content: `Ping?`, ephemeral: true, fetchReply: true });    if (isMessageInstance(msg)) {      const diff = msg.createdTimestamp - interaction.createdTimestamp;      const ping = Math.round(this.container.client.ws.ping);      return interaction.editReply(`Pong 🏓! (Round trip took: ${diff}ms. Heartbeat: ${ping}ms.)`);    }    return interaction.editReply('Failed to retrieve ping :(');  }}

Creating a slash command with subcommands

caution

Currently, progress is still being made on updating the official Sapphire Plugin Subcommands. This section will fully work now, and will continue to work after the plugin is updated. However, once the plugin has been updated creating subcommands will be possible with less code.

To create the slash command with subcommand we need to override the registerApplicationCommands method of Command class. This method is called when the Client collects all the slash commands defined in the command directory on application startup to register them on the discord API. Let's see a quick example of how to make a slash command with subcommands.

Example

import { Command } from '@sapphire/framework';export class SubCommand extends Command {  public constructor(context: Command.Context, options: Command.Options) {    // ...  }  public async chatInputRun(interaction: Command.ChatInputInteraction) {    // ...  }  public override registerApplicationCommands(registry: Command.Registry) {    registry.registerChatInputCommand((builder) =>      builder        .setName('command')        .setDescription('Command with sub commands')        .addSubcommand((command) => command.setName('first').setDescription('First sub command'))        .addSubcommand((command) => command.setName('second').setDescription('Second sub command'))    );  }}

The above will create a slash command called command with the description Command with sub commands. The command will have two sub commands, first and second with description First sub command and Second sub command respectively.

To handle the command callback for the sub command we will have to perform checks in the chatInputRun method. Let's see a quick example of how to handle the sub command callback.

import { Command } from '@sapphire/framework';export class SubCommand extends Command {  public constructor(context: Command.Context, options: Command.Options) {    // ...  }  public async chatInputRun(interaction: Command.ChatInputInteraction) {    const subcommand = interaction.options.getSubcommand(true);    if (subcommand === 'first') {      return await this.first(interaction);    } else if (subcommand === 'second') {      return await this.second(interaction);    }    return interaction.reply('Invalid sub command');  }  private async first(interaction: Command.ChatInputInteraction) {    // private class method to handle the first sub command    return interaction.reply('First sub command executed');  }  private async second(interaction: Command.ChatInputInteraction) {    // private class method to handle the second sub command    return interaction.reply('Second sub command executed');  }  public override registerApplicationCommands(registry: Command.Registry) {    // ...  }}