Table of Contents
Note

This article assumes you've recently read the article on writing your first bot.

Introduction to Application Commands

Discord provides built-in commands called: Application Commands.
Be sure to install the DisCatSharp.ApplicationCommands package from NuGet before continuing.

At the moment it is possible to create such commands:

  • Slash commands
  • User context menu commands
  • Message context menu commands

Writing an Application Commands

Creation of the first commands

Note

In order for the bot to be able to create commands in the guild, it must be added to a guild with applications.commands scope.

Each command is a method with the attribute SlashCommand or ContextMenu. They must be in classes that inherit from ApplicationCommandsModule. Also, the first argument to the method must be InteractionContext or ContextMenuContext.

Simple slash command:

public class MyCommand : ApplicationCommandsModule
{
    [SlashCommand("my_command", "This is description of the command.")]
    public async Task MySlashCommand(InteractionContext ctx)
    {

    }
}

Simple context menu command:

public class MySecondCommand : ApplicationCommandsModule
{
    [ContextMenu(ApplicationCommandType.User, "My Command")]
    public async Task MyContextMenuCommand(ContextMenuContext ctx)
    {

    }
}

Now let's add some actions to the commands, for example, send a reply:

await ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, new DiscordInteractionResponseBuilder()
{
    Content = "Hello :3"
});

If the command will be executed for more than 3 seconds, we must response at the beginning of execution and edit it at the end.

await ctx.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, new DiscordInteractionResponseBuilder());

await Task.Delay(5000); // Simulating a long command execution.

await ctx.EditResponseAsync(new DiscordWebhookBuilder()
{
    Content = "Hello :3"
});
Note

Note that you can make your commands static, but then you cannot use Dependency Injection in them.

Registration of commands

After writing the commands, we must register them. For this we need a DiscordClient.

var appCommands = client.UseApplicationCommands();

appCommands.RegisterGlobalCommands<MyCommand>();
appCommands.RegisterGlobalCommands<MySecondCommand>();

Simple, isn't it? You can register global and guild commands. Global commands will be available on all guilds of which the bot is a member. Guild commands will only appear in a specific guild.

Note

Global commands are updated within an hour, so it is recommended to use guild commands for testing and development.

To register guild commands, it is enough to specify the Id of the guild as the first argument of the registration method.

var appCommands = client.UseApplicationCommands();

appCommands.RegisterGuildCommands<MyCommand>(<guildId>);
appCommands.RegisterGuildCommands<MySecondCommand>(<guildId>);

Command Groups

Sometimes we may need to combine slash commands into groups. In this case, we need to wrap our class with commands in another class and add the SlashCommandGroup attribute.

public class MyCommand : ApplicationCommandsModule
{
    [SlashCommandGroup("my_command", "This is description of the command group.")]
    public class MyCommandGroup : ApplicationCommandsModule
    {
        [SlashCommand("first", "This is description of the command.")]
        public async Task MySlashCommand(InteractionContext ctx)
        {
            await ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, new DiscordInteractionResponseBuilder()
            {
                Content = "This is first subcommand."
            });
        }
        [SlashCommand("second", "This is description of the command.")]
        public async Task MySecondCommand(InteractionContext ctx)
        {
            await ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, new DiscordInteractionResponseBuilder()
            {
                Content = "This is second subcommand."
            });
        }
    }
}

Commands will now be available via /my_command first and /my_command second. Also, note that both classes must inherit ApplicationCommandsModule.