DiscordLua
discorddiscord
v1.2.4
Install

Examples

Guide
On 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.

lua
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.

lua
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.

lua
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.

lua
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.

lua
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.

lua
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.

lua
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.

lua
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.

lua
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.

lua
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.

lua
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.

lua
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.

Search Ctrl K Navigate Open Esc