zephyr.discord
Discord actions. Ids are passed as strings, and Discord API failures surface as Lua runtime errors. Message, embed, button, modal, channel, and permission specs reject unknown fields.
30 functions
send_message
zephyr.discord.send_message(channel_id, message)Send a message to a channel.
Parameters
channel_idstringTarget channel id.
messageMessageSpecMessage content, embeds, buttons, select menus, and attachments.
Returns
The new message id.
Raises an error if
- the
discord:send_messagepermission is not granted
Example
zephyr.discord.send_message(channel_id, { content = "Hello" })edit_message
zephyr.discord.edit_message(channel_id, message_id, message)Edit an existing channel message.
Omitted content, empty embeds, empty components, and empty attachments are not sent to Discord by the host builder.
Parameters
channel_idstringChannel containing the message.
message_idstringMessage to edit.
messageMessageSpecNew message content, embeds, buttons, select menus, and attachments.
Returns
Nothing.
Raises an error if
- the
discord:send_messagepermission is not granted
dm_user
zephyr.discord.dm_user(user_id, message)Send a direct message to a user.
Parameters
user_idstringRecipient user id.
messageMessageSpecMessage content, embeds, buttons, select menus, and attachments.
Returns
The new message id.
Raises an error if
- the
discord:dmpermission is not granted
respond
zephyr.discord.respond(message)Respond to the current command, component, or modal interaction.
Must be called while handling an interaction-backed event.
Parameters
messageMessageSpecResponse content. Set ephemeral = true for a private reply.
Returns
Nothing.
Raises an error if
- the
discord:interactionspermission is not granted
Example
zephyr.discord.respond({ content = "Pong", ephemeral = true })update_message
zephyr.discord.update_message(message)Update the source message of the current component interaction.
Must be called while handling an interaction-backed event.
Parameters
messageMessageSpecNew message content, embeds, buttons, select menus, and attachments.
Returns
Nothing.
Raises an error if
- the
discord:interactionspermission is not granted
open_modal
zephyr.discord.open_modal(modal)Open a modal for the current interaction.
Parameters
modalModalSpecModal with custom_id, title, and inputs.
Returns
Nothing.
Raises an error if
- the
discord:interactionspermission is not granted
Example
zephyr.discord.open_modal({
custom_id = "example:modal",
title = "Example",
inputs = {
{ custom_id = "subject", label = "Subject", style = "short", required = true },
},
})wait_for_component
zephyr.discord.wait_for_component(predicate, options?)Suspend the handler until a component interaction matches a predicate.
Parks the calling handler until an incoming component (button) interaction satisfies predicate(event), then returns that interaction's payload. The matched interaction is acknowledged automatically; respond to it with edit_message/send_message using the returned ids. Returns nil if no match arrives within the timeout. The predicate runs for every candidate component, so keep it cheap and side-effect free.
Parameters
predicatefunctionfn(event) -> boolean testing a candidate component interaction (fields: custom_id, user_id, message_id, channel_id, guild_id).
optionstableoptionalOptional { timeout = seconds } (default 60).
Returns
The matching component interaction, or nil on timeout.
Raises an error if
- the
discord:interactionspermission is not granted
Example
local click = zephyr.discord.wait_for_component(function(e)
return e.user_id == ctx.user_id and e.custom_id == "confirm"
end, { timeout = 30 })
if click ~= nil then
zephyr.discord.edit_message(click.channel_id, click.message_id, { content = "Confirmed." })
endmember_count
zephyr.discord.member_count(guild_id)Return the member count of a guild.
Parameters
guild_idstringGuild id.
Returns
The guild member count.
Raises an error if
- the
discord:member_countpermission is not granted
create_text_channel
zephyr.discord.create_text_channel(spec)Create a text channel.
Parameters
spectableChannel spec: guild_id and name (required), plus optional category_id, topic, permission_overwrites, and reason.
Returns
The created channel id.
Raises an error if
- the
discord:channelspermission is not granted
Example
local channel_id = zephyr.discord.create_text_channel({
guild_id = guild_id,
name = "ticket-123",
category_id = category_id,
})create_voice_channel
zephyr.discord.create_voice_channel(spec)Create a voice channel.
Parameters
spectableVoice channel spec: guild_id and name (required), plus optional category_id, user_limit, bitrate, permission_overwrites, and reason.
Returns
The created channel id.
Raises an error if
- the
discord:channelspermission is not granted
Example
local channel_id = zephyr.discord.create_voice_channel({
guild_id = guild_id,
name = "match-42",
permission_overwrites = {
{ kind = "member", id = user_id, allow = { "view_channel", "connect", "speak" } },
},
})rename_channel
zephyr.discord.rename_channel(channel_id, name, reason?)Rename a channel.
Parameters
channel_idstringChannel to rename.
namestringNew channel name.
reasonstringoptionalAudit-log reason.
Returns
Nothing.
Raises an error if
- the
discord:channelspermission is not granted
move_channel
zephyr.discord.move_channel(channel_id, category_id?, reason?)Move a channel into (or out of) a category.
Pass nil or an empty category_id to remove the channel's category.
Parameters
channel_idstringChannel to move.
category_idstringoptionalDestination category id, or nil to remove.
reasonstringoptionalAudit-log reason.
Returns
Nothing.
Raises an error if
- the
discord:channelspermission is not granted
delete_channel
zephyr.discord.delete_channel(channel_id, reason?)Delete a channel.
Parameters
channel_idstringChannel to delete.
reasonstringoptionalAudit-log reason.
Returns
Nothing.
Raises an error if
- the
discord:channelspermission is not granted
set_channel_permission
zephyr.discord.set_channel_permission(channel_id, overwrite)Set a permission overwrite on a channel.
Parameters
channel_idstringTarget channel.
overwritetableOverwrite: kind (member/role), id, and allow/deny permission-name arrays.
Returns
Nothing.
Raises an error if
- the
discord:channelspermission is not granted
delete_channel_permission
zephyr.discord.delete_channel_permission(channel_id, kind, id)Remove a permission overwrite from a channel.
Parameters
channel_idstringTarget channel.
kindstringmember or role.
idstringUser id for member, role id for role.
Returns
Nothing.
Raises an error if
- the
discord:channelspermission is not granted
fetch_messages
zephyr.discord.fetch_messages(channel_id, limit?)Fetch recent messages from a channel in chronological order.
Parameters
channel_idstringChannel to read.
limitnumberoptionalMaximum messages. Defaults to 100, clamped to 1..100.
Returns
Message summaries with id, author_id, author_name, author_is_bot, content, and timestamp.
Raises an error if
- the
discord:read_messagespermission is not granted
voice_channel
zephyr.discord.voice_channel(guild_id, user_id)Return the voice channel a guild member is connected to.
Reads from the gateway voice-state cache. The bot requests the voice-state intent when any module declares discord:voice_states.
Parameters
guild_idstringGuild id.
user_idstringMember user id.
Returns
The voice channel id, or nil if the member is not connected.
Raises an error if
- the
discord:voice_statespermission is not granted
voice_channel_user_count
zephyr.discord.voice_channel_user_count(guild_id, channel_id)Return the number of users currently connected to a voice channel, excluding the bot itself.
Reads from the gateway voice-state cache. The bot requests the voice-state intent when any module declares discord:voice_states.
Parameters
guild_idstringGuild id.
channel_idstringVoice channel id.
Returns
Connected user count excluding the bot user.
Raises an error if
- the
discord:voice_statespermission is not granted
kick_member
zephyr.discord.kick_member(guild_id, user_id, reason)Kick a member from a guild.
Parameters
guild_idstringGuild id.
user_idstringMember to kick.
reasonstringAudit-log reason.
Returns
Nothing.
Raises an error if
- the
discord:moderationpermission is not granted
ban_member
zephyr.discord.ban_member(guild_id, user_id, reason, delete_message_days?)Ban a member from a guild.
Parameters
guild_idstringGuild id.
user_idstringMember to ban.
reasonstringAudit-log reason.
delete_message_daysnumberoptionalDays of the member's messages to delete. Defaults to 0, capped at 7.
Returns
Nothing.
Raises an error if
- the
discord:moderationpermission is not granted
unban_member
zephyr.discord.unban_member(guild_id, user_id)Lift a ban on a user.
Parameters
guild_idstringGuild id.
user_idstringUser to unban.
Returns
Nothing.
Raises an error if
- the
discord:moderationpermission is not granted
timeout_member
zephyr.discord.timeout_member(guild_id, user_id, until_unix, reason)Time a member out until a given timestamp.
Parameters
guild_idstringGuild id.
user_idstringMember to time out.
until_unixnumberUnix timestamp (seconds) when the timeout ends.
reasonstringAudit-log reason.
Returns
Nothing.
Raises an error if
- the
discord:moderationpermission is not granted
remove_timeout
zephyr.discord.remove_timeout(guild_id, user_id, reason)Clear an active timeout on a member.
Parameters
guild_idstringGuild id.
user_idstringMember whose timeout to clear.
reasonstringAudit-log reason.
Returns
Nothing.
Raises an error if
- the
discord:moderationpermission is not granted
add_role
zephyr.discord.add_role(guild_id, user_id, role_id, reason?)Assign a role to a member.
Parameters
guild_idstringGuild id.
user_idstringMember to assign the role to.
role_idstringRole to assign.
reasonstringoptionalAudit-log reason.
Returns
Nothing.
Raises an error if
- the
discord:rolespermission is not granted
remove_role
zephyr.discord.remove_role(guild_id, user_id, role_id, reason?)Unassign a role from a member.
Parameters
guild_idstringGuild id.
user_idstringMember to unassign the role from.
role_idstringRole to remove.
reasonstringoptionalAudit-log reason.
Returns
Nothing.
Raises an error if
- the
discord:rolespermission is not granted
add_reaction
zephyr.discord.add_reaction(channel_id, message_id, emoji)Add a reaction to a message. Use to seed a reaction-role panel with its emoji.
Parameters
channel_idstringChannel the message is in.
message_idstringMessage to react to.
emojistringUnicode emoji (e.g. "🎉") or a custom emoji as name:id.
Returns
Nothing.
Raises an error if
- the
discord:reactionspermission is not granted
Example
-- React to a panel so members can click the emoji to self-assign a role.
zephyr.discord.add_reaction(channel_id, message_id, "🔔")guild_roles
zephyr.discord.guild_roles(guild_id)List a guild's roles (id, name, position, managed, color).
Parameters
guild_idstringGuild id.
Returns
Array of { id, name, position, managed, color }, highest position last.
Raises an error if
- the
discord:rolespermission is not granted
Example
for _, role in ipairs(zephyr.discord.guild_roles(guild_id)) do
print(role.name)
endset_status
zephyr.discord.set_status(status)Set the bot's online status while keeping the current activity.
status accepts online, idle/away, dnd, and invisible/offline.
Parameters
statusstringOnline status to apply.
Returns
Nothing.
Raises an error if
- the
discord:presencepermission is not granted - the status is not one of the supported values
Example
zephyr.discord.set_status("away")set_activity
zephyr.discord.set_activity(activity?)Set or clear the bot's activity while keeping the current online status.
Pass nil to clear the activity. Activity tables accept kind (or type) as playing, listening, watching, competing, custom, or streaming; text can be provided as name, description, or state. Streaming activities also require url.
Parameters
activityActivitySpecoptionalActivity to display, or nil to clear it.
Returns
Nothing.
Raises an error if
- the
discord:presencepermission is not granted - the activity kind or streaming URL is invalid
Example
zephyr.discord.set_activity({ kind = "watching", description = "tickets" })set_presence
zephyr.discord.set_presence(status, activity?)Set the bot's online status and activity together.
status accepts online, idle/away, dnd, and invisible/offline. activity uses the same table shape as set_activity; pass nil to clear the activity.
Parameters
statusstringOnline status to apply.
activityActivitySpecoptionalActivity to display, or nil to clear it.
Returns
Nothing.
Raises an error if
- the
discord:presencepermission is not granted - the status, activity kind, or streaming URL is invalid
Example
zephyr.discord.set_presence("dnd", { kind = "playing", name = "ranked matches" })