Examples
GuideOn this page
Copy these snippets into bot.lua and run dislua run bot.lua. Every call is a real DiscordLua API.
Getting started
A complete bot: construct a Client, listen for messages, reply, then login from DISCORD_TOKEN.
local discord = require("discord")
local client = discord.Client({
intents = { "Guilds", "GuildMessages", "MessageContent" }
})
client:on("ready", function()
print("Logged in as", client.user and client.user.tag)
end)
client:on("messageCreate", function(message)
if message.author and message.author.bot then return end
if message.content == "!ping" then
message:reply("Pong!")
end
end)
client:login(os.getenv("DISCORD_TOKEN"))Expected: the process stays running, prints the bot tag on ready, and replies Pong! to !ping.
Messages
Send, reply, edit, and delete through Message and the channel send helper.
channel:send("hello")
message:reply({ content = "hi" })
message:edit("updated")
message:delete()Important calls: TextChannel:send, Message:reply, Message:edit, Message:delete.
Embeds
Build a rich embed and attach it to a reply. setColor accepts a name, hex, or integer.
local embed = discord.EmbedBuilder()
:setTitle("Hello")
:setDescription("Built with DiscordLua")
:setColor("Blurple")
message:reply({ embeds = { embed } })Interactions
Handle a slash command. Register the command with the application command manager, then reply from interactionCreate.
local cmd = discord.SlashCommandBuilder()
:setName("ping")
:setDescription("Replies with Pong")
client.application.commands:set({ cmd }, function(err)
if err then error(err) end
end)
client:on("interactionCreate", function(interaction)
if interaction:isChatInputCommand() and interaction.commandName == "ping" then
interaction:reply("Pong!")
end
end)Expected: /ping appears after Discord refreshes commands, and the interaction receives Pong!.
Components
Send a button, then acknowledge the click with an ephemeral reply.
local row = discord.ActionRowBuilder():addComponents(
discord.ButtonBuilder():setCustomId("ok"):setLabel("OK"):setStyle(discord.ButtonStyle.Success)
)
channel:send({ content = "Choose", components = { row } })
client:on("interactionCreate", function(interaction)
if interaction:isButton() and interaction.customId == "ok" then
interaction:reply({ content = "clicked", ephemeral = true })
end
end)Guilds
Read the cache after ready, or fetch a guild by id through GuildManager.
client:on("ready", function()
local guild = client.guilds:first()
print(guild and guild.name, client.guilds:size())
end)
client.guilds:fetch("123", function(err, guild)
if err then print(err.message) return end
print(guild.name)
end)Channels
Create a guild text channel, then delete it. Guild:createChannel posts to REST; Channel:delete removes the channel.
guild:createChannel({
name = "bot-log",
type = discord.ChannelType.GuildText,
})
channel:delete()The client must have Manage Channels. Prefer a callback on manager methods when you need (err, result).
Roles
Create a role and add it to a member through the role manager.
guild.roles:create({ name = "lua" }, function(err, role)
if err then error(err) end
member.roles:add(role.id, function(addErr)
if addErr then error(addErr) end
end)
end)Webhooks
Send with a webhook id and token. Do not hard-code secrets in source.
local hook = discord.WebhookClient.new(
os.getenv("WEBHOOK_ID"),
os.getenv("WEBHOOK_TOKEN")
)
hook:send("hello")Events
Listen with string names or discord.Events. Handler arguments match the Client emit.
client:on("guildMemberAdd", function(member)
print(member.user and member.user.id)
end)
client:on(discord.Events.MessageCreate, function(message)
print(message.content)
end)Error handling
REST helpers take callback(err, result). Without a callback, failures raise.
channel:send("hi", function(err, message)
if err then
print(err.name, err.message)
return
end
print(message.id)
end)Advanced
Timers use the native runtime. Voice plays Opus. Sharding evaluates a Lua source string on every shard.
local runtime = require("runtime")
runtime.setTimeout(1000, function()
print("one second")
end)
local connection = voiceChannel:join()
connection:playFile("audio.opus")
manager:broadcastEval("return client.guilds:size()")See VoiceConnection and ShardingManager.