Application Commands

What is an application command?

Application commands are commands that an application can register to Discord. They provide users a first-class way of interacting directly with your application that feels deeply integrated into Discord.

From: Discord API docs

How do I register an application command?

Write to your script:

And then run discorb setup to register your application commands. Learn more about discorb setup.

Note

To register a global command, it will take 1 hour to be registered. Guild commands will be registered immediately.

Register Slash Commands

This example registers a slash command that says "Hello, world!" when the user types /hello.

require "discorb"

client = Discorb::Client.new

client.slash("hello", "Greet for you") do |interaction|
  interaction.post("Hello World!", ephemeral: true)
end

client.run(ENV["DISCORD_BOT_TOKEN"])

Discorb::ApplicationCommand::Handler#slash takes 5 arguments:

Argument Description
command_name The name of the command.
description The description of the command.
options A hash of options.
guild_ids The ID of the guild to register the command in.
block A block that will be called when the command is invoked.

Block will be called with a Discorb::Interaction object and specified options.

Register options

You can set hash to options argument. In options, hash should be like this:

{
  "name" => {
    type: :string,
    required: true,
    description: "The description of the command."
  }
}
Key Type Description
:name_localizations Hash{Symbol => String} Localizations of option name.
:description String Description of the option.
:required `Boolean(true\ false)`
:optional `Boolean(true\ false)`
:type Object Type of the option.
:choices Hash{String => String, Integer, Float} Choice of the option.
:choices_localizations Hash{String => Hash{Symbol => String}} Localization of the choice. Key must be the name of a choice. (See below for example)
:default Object Default value of the option.
:channel_types Array<Class<Discorb::Channel>> Type of the channel option.
:autocomplete Proc Autocomplete function.
:range Range Range of the option. Only valid for numeric options. (:int, :float)
:length Range Range of length of the option. Only valid for :string.

choices should be unspecified if you don't want to use it. choices example:

{
  "vocaloid" => {
    required: true,
    description: "The vocaloid which you like.",
    type: :string,
    choices: {
      "Hatsune Miku" => "miku",
      "Kagamine Rin" => "rin",
      "Kagamine Len" => "len",
      "Megurine Luka" => "luka",
      "MEIKO" => "meiko",
      "KAITO" => "kaito",
    }
  }
}

# Note: This aritcle is written in 8/31.

The key will be displayed in the user menu, and the value will be used as the argument.

In type, You must use one of the following:

Name Description Aliases
:string String argument. :str
:integer Integer argument. :int
:float Float argument. None
:boolean Boolean argument. :bool
:user User argument. :member
:channel Channel argument. None
:role Role argument. None

The block will receive the options as arguments.

client.slash("hello", "Bot greets", {
  "name" => {
    type: :string,
    description: "Name"
  }
}) do |interaction, name|
  interaction.post("Hello, #{name}!", ephemeral: true)
end

Group Slash Commands

To register a group of slash commands, use Discorb::ApplicationCommand::Handler#slash_group.

group = client.slash_group("settings", "Set settings of bot.")

group.slash("message_expand", "Whether bot should expand message.", {
  "enabled" => {
    type: :boolean,
    description: "Whether bot should expand message."
  }
}) do |interaction, enabled|
  # ...
end

group.slash("level", "Whether level system is enabled.", {
  "enabled" => {
    type: :boolean,
    description: "Whether level system is enabled."
  }
}) do |interaction, enabled|
  # ...
end

Since v0.5.1, You can use block for register commands.


client.slash_group("settings", "Set settings of bot.") do |group|
  group.slash("message_expand", "Whether bot should expand message.", {
    "enabled" => {
      type: :boolean,
      description: "Whether bot should expand message."
    }
  }) do |interaction, enabled|
    # ...
  end
  group.slash("bump_alert", "Whether level system is enabled.", {
    "enabled" => {
      type: :boolean,
      description: "Whether level system is enabled."
    }
  }) do |interaction, enabled|
    # ...
  end
end

You can make subcommand group by using Discorb::ApplicationCommand::Command::GroupCommand#group.

group = client.slash_group("permission", "Set/Get command permissions.")

group_user = group.group("user", "Set/Get user's command permissions.")

group_user.slash("set", "Set user's command permissions.", {
  "user_id" => {
      type: :user,
      description: "The user."
  },
  "value" => {
      type: :boolean,
      description: "Whether the user can use the command."
  }
}) do |interaction, user|
  # ...
end

group_user.slash("get", "Set user's command permissions.", {
    "user_id" => {
        type: :user,
        description: "The user."
    },
}) do |interaction, user|
  # ...
end

group_user = group.group("user", "Set/Get user's command permissions.")

group_user.slash("set", "Set user's command permissions.", {
    "user_id" => {
        type: :user,
        description: "The user."
    },
    "value" => {
        type: :boolean,
        description: "Whether the user can use the command."
    }
}) do |interaction, user|
  # ...
end

group_user.slash("get", "Set user's command permissions.", {
    "user_id" => {
        type: :user,
        description: "The user."
    },
}) do |interaction, user|
  # ...
end

group_role = group.group("role", "Set/Get role's command permissions.")

group_role.slash("set", "Set role's command permissions.", {
    "role_id" => {
        type: :role,
        description: "The role."
    },
    "value" => {
        type: :boolean,
        description: "Whether the role can use the command."
    }
}) do |interaction, role|
  # ...
end

group_role.slash("get", "Set role's command permissions.", {
    "role_id" => {
        type: :role,
        description: "The role."
    },
}) do |interaction, role|
  # ...
end

Same as above, you can use block for register commands since v0.5.1.

Use Auto Completing

Since v0.11.0, you can use auto-completion by setting Proc to :autocomplete in options. The proc will be called with interaction object and the argument. The proc should return a hash of the autocomplete result.

client.slash("hello2", "Greet for you", {
  "target" => {
    type: :string,
    description: "Person to greet",
    autocomplete: ->(interaction, target) {
      {
        "You" => interaction.target.to_s
      }
    },
  },
}) do |interaction, target|
  interaction.post("Hello, #{target}!")
end

In the above example, You will be displayed in the user menu. Due to the limitation of Discord API, the proc must return the result in less than 3 second.

Register User Context Menu Command

client.user_command("hello") do |interaction, user|
  interaction.post("Hello, #{user.name}!")
end

Discorb::ApplicationCommand::Handler#user_command takes 3 arguments:

Parameter Description
command_name The name of the command.
guild_ids The ID of the guild to register the command in.
block A block that will be called when the command is invoked.

block will be called with two arguments:

Parameter Description
interaction The interaction object.
user The user object.

Register Message Context Menu Command

client.message_command("Bookmark") do |interaction, message|
  # ...
end

Discorb::ApplicationCommand::Handler#message_command takes 3 arguments:

Parameter Description
command_name The name of the command.
guild_ids The ID of the guild to register the command in.
block A block that will be called when the command is invoked.

block will be called with two arguments:

Parameter Description
interaction The interaction object.
message The message object.

Localizing command

You can localize commands with passing parameters, or setting Hash to name. Also, you can change the text by checking interaction.locale and interaction.guild_locale.

Command name localize example:

localizations = {
  localized: {
    text: {
      en: "Hello, %s!",
      ja: "%sさん、こんにちは!",
    },
  },
}

client.slash({
  default: "greet",
  ja: "挨拶",
}, {
  default: "Bot greets. Cute OwO",
  ja: "Botが挨拶します。かわいいね",
}, {
  "name" => {
    name_localizations: {
      ja: "名前",
    },
    description: {
      default: "The name to greet.",
      ja: "挨拶する人の名前。",
    },
    type: :string,
    optional: true,
  },
}) do |interaction, name|
  interaction.post(
    (localizations[:localized][:text][interaction.locale] || localizations[:localized][:text][:en]) % [name || interaction.target.to_s_user],
    ephemeral: true,
  )
end

Option localize example:

{
  "vocaloid" => {
    name_localizations: {
      ja: "ボカロ",
    },
    required: true,
    description: "The vocaloid which you like.",
    description_localizations: {
      ja: "好きなボカロ。",
    },
    type: :string,
    choices: {
      "Hatsune Miku" => "miku",
      "Kagamine Rin" => "rin",
      "Kagamine Len" => "len",
      "Megurine Luka" => "luka",
      "MEIKO" => "meiko",
      "KAITO" => "kaito",
    },
    choice_localizations: {
      "Hatsune Miku" => {
        ja: "初音ミク",
      },
      "Kagamine Rin" => {
        ja: "鏡音リン",
      },
      "Kagamine Len" => {
        ja: "鏡音レン",
      },
      "Megurine Luka" => {
        ja: "巡音ルカ",
      },
      "MEIKO" => {
        ja: "MEIKO",
      },
      "KAITO" => {
        ja: "KAITO",
      },
    }
  }
}