Slash Commands
This guide covers registering a global slash command and responding to it when a user runs it.
Building a command
Section titled “Building a command”Use builders.interaction.interaction to describe the command before registering it.
local discord = require("@self/../luau_packages/discord")local classes = require("@self/../luau_packages/classes")local builders = require("@self/../luau_packages/builders")local env = require("@self/../.env")
local pingCommand = builders.interaction.interaction.new() :setName("ping") :setDescription("Replies with Pong!") :setType("ChatInput") :addIntegrationType("GuildInstall") :addContext("Guild") :build()| Method | Required | Notes |
|---|---|---|
:setName(name) | Yes | 1-32 characters, lowercase |
:setDescription(desc) | Yes | 1-100 characters |
:setType(type) | No | "ChatInput" for slash commands (default when omitted) |
:addIntegrationType(type) | Yes | At least one - "GuildInstall" or "UserInstall" |
:addContext(context) | Yes | At least one - "Guild", "BotDm", or "PrivateChannel" |
Registering the command
Section titled “Registering the command”Global commands are registered via bot.application, which is available after onAllShardsReady. Registration is asynchronous - global commands can take up to an hour to propagate to all Discord servers.
local bot = discord.bot.new({ token = env.DISCORD_BOT_TOKEN, intents = builders.intents.new({ "Guilds" }):build(), reconnect = true,})
bot.onAllShardsReady:listenOnce(function() local result = bot.application:createSlashCommandAsync(pingCommand):await()
if result:isErr() then warn("Failed to register command:", result:unwrapErr()) return end
print("Registered command:", result:unwrapOk().name)end)Handling the interaction
Section titled “Handling the interaction”Listen to bot.onCommandInteraction to receive slash command interactions. The interaction object provides :messageAsync() to send a response.
bot.onCommandInteraction:listen(function(interaction: classes.TypesCommand) if interaction.data.name ~= "ping" then return end
interaction:messageAsync( builders.message.message.new() :setContent("Pong!") :build() ):await()end)
bot:connectAsync():await()Adding options
Section titled “Adding options”Use builders.interaction.option to add parameters to a command. Options must be built and passed to :addOption() before calling :build() on the command.
local greetCommand = builders.interaction.interaction.new() :setName("greet") :setDescription("Greet a user by name") :setType("ChatInput") :addIntegrationType("GuildInstall") :addContext("Guild") :addOption( builders.interaction.option.new() :setType("String") :setName("name") :setDescription("The name to greet") :build() ) :build()Deferring a response
Section titled “Deferring a response”If your handler needs more than three seconds (e.g. to fetch data), defer the interaction first to show a loading state, then edit the response when ready.
bot.onCommandInteraction:listen(function(interaction: classes.TypesCommand) if interaction.data.name ~= "slow" then return end
interaction:deferAsync():await()
-- ... do slow work ...
interaction:editResponseAsync( builders.message.message.new() :setContent("Done!") :build() ):await()end)Full script
local discord = require("@self/../luau_packages/discord")local classes = require("@self/../luau_packages/classes")local builders = require("@self/../luau_packages/builders")local env = require("@self/../.env")
local pingCommand = builders.interaction.interaction.new() :setName("ping") :setDescription("Replies with Pong!") :setType("ChatInput") :addIntegrationType("GuildInstall") :addContext("Guild") :build()
local bot = discord.bot.new({ token = env.DISCORD_BOT_TOKEN, intents = builders.intents.new({ "Guilds" }):build(), reconnect = true,})
bot.onAllShardsReady:listenOnce(function() local result = bot.application:createSlashCommandAsync(pingCommand):await()
if result:isErr() then warn("Failed to register command:", result:unwrapErr()) return end
print("Registered command:", result:unwrapOk().name)end)
bot.onCommandInteraction:listen(function(interaction: classes.TypesCommand) if interaction.data.name ~= "ping" then return end
interaction:messageAsync( builders.message.message.new() :setContent("Pong!") :build() ):await()end)
bot:connectAsync():await()References
Section titled “References”- Bot - the
discord.botclass, gateway connection and event emitters - Interaction builder -
builders.interaction.interaction, constructs slash command definitions - Interaction Option builder -
builders.interaction.option, adds typed parameters to commands - Message builder -
builders.message.message, constructs response payloads - Intents builder -
builders.intents, constructs the gateway intent bitfield - Futures - the
FutureLikeasync primitive returned by async calls