Nosedrum.ApplicationCommand behaviour (nosedrum v0.4.0) View Source

The application command behaviour specifies the interface that a slash, user, or message command module should implement.

Like regular commands, application command modules are stateless on their own. Implementations of the callbacks defined by this behaviour are invoked from other modules/functions, notably a Nosedrum.Interactor.

The types defined in this module reflect the official Application Command docs.

Example Slash Command

This command echos the passed message back to the user.

# In your application command module file, e.g. ./lib/my_app/commands/echo.ex
defmodule MyApp.Commands.Echo do
  @behaviour Nosedrum.ApplicationCommand

  @impl true
  def description() do
    "Echos a message."
  end

  @impl true
  def command(interaction) do
    [%{name: "message", value: message}] = interaction.data.options
    [
      content: message,
      ephemeral?: true
    ]
  end

  @impl true
  def type() do
    :slash
  end

  @impl true
  def options() do
    [
      %{
        type: :string,
        name: "message",
        description: "The message for the bot to echo.",
        required: true
      }
    ]
  end
end
# In your Nostrum.Consumer file, e.g. ./lib/my_app/consumer.ex
defmodule MyApp.Consumer do
  use Nostrum.Consumer

  # ...

  # You may use `:global` instead of a guild id at GUILD_ID_HERE, but note
  # that global commands could take up to an hour to become available.
  def handle_event({:READY, _data, _ws_state}) do
    case Nosedrum.Interactor.Dispatcher.add_command("echo", MyApp.Commands.Echo, GUILD_ID_HERE) do
      {:ok, _} -> IO.puts("Registered Echo command.")
      e -> IO.inspect(e, label: "An error occurred registering the Echo command")
    end
  end
end

You will also need to start the Nosedrum.Interactor.Dispatcher as part of your supervision tree, for example, by adding this to your application start function:

# ./lib/my_app/application.ex
defmodule MyApp.Application do
  # ...
  def start(type, args) do
    children = [
      # ...
      {Nosedrum.Interactor.Dispatcher, name: Nosedrum.Interactor.Dispatcher},
    ]

    options = [strategy: :rest_for_one, name: Bolt.Supervisor]
    Supervisor.start_link(children, options)
  end
end

Link to this section Summary

Types

A choice for an option.

An option (argument) for an application command.

A keyword list of fields to include in the interaction response, after running the command/1 callback.

A field in a keyword list interaction response.

Callbacks

Execute the command invoked by the given Nostrum.Struct.Interaction.t/0. Returns a response/0

Returns a description of the command. Used when registering the command with Discord. This is what the user will see in the autofill command-selection menu.

An optional callback that returns a list of options (arguments) that the command takes. Used when registering the command with Discord. Only valid for CHAT_INPUT application commands, aka slash commands.

Returns one of :slash, :message, or :user, indicating what kind of application command this module represents.

Link to this section Types

Specs

choice() :: %{name: String.t(), value: String.t() | number()}

A choice for an option.

See callback options/0 documentation for examples.

Specs

option() :: %{
  optional(:required) => true | false,
  optional(:choices) => [choice()],
  optional(:options) => [option()],
  :type =>
    :sub_command
    | :sub_command_group
    | :string
    | :integer
    | :boolean
    | :user
    | :channel
    | :role
    | :mentionable
    | :number,
  :name => String.t(),
  :description => String.t()
}

An option (argument) for an application command.

See callback options/0 documentation for examples.

Specs

response() :: [response_field()]

A keyword list of fields to include in the interaction response, after running the command/1 callback.

If :type is not specified, it will default to :channel_message_with_source, though one of either :embeds or :content must be present.

Example

def command(interaction) do
  # Since `:content` is included, Nosedrum will infer `type: :channel_message_with_source`
  [
    content: "Hello, world!",
    ephemeral?: true,
    allowed_mentions: ["users", "roles"]
  ]
end

Specs

response_field() ::
  {:type, response_type()}
  | {:content, String.t()}
  | {:embeds, [Embed.t()]}
  | {:components, [map()]}
  | {:ephemeral?, boolean()}
  | {:tts?, boolean()}
  | {:allowed_mentions, [String.t()] | []}

A field in a keyword list interaction response.

Special notes:

  • :type is required, unless :content or :embeds is present, in which case it defaults to :channel_message_with_source.
  • :allowed_mentions is a list that should contain "users", "roles", and/or "everyone", or be empty.

Specs

response_type() ::
  :channel_message_with_source
  | :deferred_channel_message_with_source
  | :deferred_update_message
  | :pong
  | :update_message

Link to this section Callbacks

Specs

command(interaction :: Interaction.t()) :: response()

Execute the command invoked by the given Nostrum.Struct.Interaction.t/0. Returns a response/0

Example

defmodule MyApp.MyCommand do
  @behaviour Nosedrum.ApplicationCommand

  # ...

  @impl true
  def command(interaction) do
    %{name: opt_name} = List.first(interaction.data.options)
    [content: "Hello World #{opt_name}!"]
  end
end

Specs

description() :: String.t()

Returns a description of the command. Used when registering the command with Discord. This is what the user will see in the autofill command-selection menu.

Example

def description, do: "This is a command description."

Specs

options() :: [option()]

An optional callback that returns a list of options (arguments) that the command takes. Used when registering the command with Discord. Only valid for CHAT_INPUT application commands, aka slash commands.

Read more in the official Application Command documentation.

Example options callback for a "/role" command

def options, do:
  [
    %{
      type: :user,
      name: "user",
      description: "The user to assign the role to.",
      required: true # Defaults to false if not specified.
    },
    %{
      type: :role,
      name: "role",
      description: "The role to be assigned.",
      required: true,
      choices: [
        %{
          name: "Event Notifications",
          value: 123456789123456789 # A role ID, passed to your `command/1` callback via the Interaction struct.
        },
        %{
          name: "Announcements",
          value: 123456789123456790
        }
      ]
    }
  ]

Specs

type() :: :slash | :message | :user

Returns one of :slash, :message, or :user, indicating what kind of application command this module represents.