WardenX

Getting Started

Getting Started

WardenX allows you to write custom Lua scripts to handle Discord events and commands. Scripts are sandboxed for security and have access to specific Discord objects.

Global Variables

These variables are automatically available in your scripts depending on the context.

  • interaction Discord: Available in command, button, and modal scripts.
  • guild Discord: The current server object.
  • member Discord: The member who triggered the event.
  • storage WardenX: Persistent data storage object for your server.
  • wardenx WardenX: Utility object for advanced script interactions.

Script Folders WardenX

Scripts are organized by their purpose. The dashboard handles the placement automatically when you create them in specific sections.

commands/
For slash commands. Use the --[[ @wardenx ... ]] metadata block at the top to declare options.
events/
For general Discord events like members joining or messages being sent.
buttons/
For handling button interactions (filename must match custom ID).
modals/
For handling modal submissions (filename must match custom ID).
lib/
For reusable libraries. Load them via wardenx.run("filename").

Command Metadata

--[[ @wardenx
description = "Greet a user"
options = {
    { name = "user", description = "The user to greet", type = "user", required = true }
}
--]]

Supported Events Discord

Discord IDs should always be treated as strings in Lua to prevent precision loss.

Member Join | Member Leave
Triggered when a member joins or leaves. Provides member or user object.
Message Received | Edited | Deleted
Triggered on message actions. Provides message object.
Voice State Change
Triggered when joining/leaving/moving voice channels. Provides member, channel, and oldChannel.
Role Created | Deleted
Provides the role object.
Channel Created | Deleted
Provides the channel object.

WardenX Utility WardenX

The wardenx global provides core functionality for script interaction.

wardenx.newEmbed()
Returns a new LuaEmbedBuilder instance.
wardenx.newButton(label, customId)
Returns a new LuaButton instance.
wardenx.run(scriptName, [argsOrFunc], [...args])
Executes another script from the lib/ or commands/ folder. If the second argument is a table, it is injected as globals. If it is a string, it calls that function in the target script.

Persistent Storage WardenX

Data saved in storage persists across restarts. Supports strings, numbers, booleans, and nested tables.

storage:set(key, value)
Saves a value associated with a key.
storage:get(key)
Retrieves a value. Returns nil if not found.
storage:remove(key)
Deletes a specific key.
storage:clear()
Deletes all data for the server.
storage:getAll()
Returns a table of all stored keys and values.

Moderation Logs WardenX

Created via guild:newModlog(). Automatically handles formatting and sending logs to the server's log channel.

modlog:setTarget(userOrMemberOrId)
Sets the subject of the moderation action.
modlog:setModerator(userOrMemberOrId)
Sets the moderator who performed the action.
modlog:setAction(actionName)
e.g., "Ban", "Mute", "Warning".
modlog:setReason(reason)
Sets the reason for the log.
modlog:setDetails(details)
Adds extra information to the log.
modlog:setLogType(type)
Sets the category (e.g., "MODERATION", "MESSAGE").
modlog:send()
Finalizes and sends the log.

Interactions Discord

The interaction object is used specifically for slash commands, button clicks, and modal submissions.

interaction:getType()
Returns SLASH_COMMAND, BUTTON, or MODAL.
interaction:reply(content, [embed], [components])
Sends a visible reply. components can be a single button or table of buttons.
interaction:replyEphemeral(content, [embed], [components])
Sends a private reply visible only to the user.
interaction:deferReply() / deferReplyEphemeral()
Acknowledges the interaction to prevent timeout.
interaction:editOrigin(content, [embed], [components])
Edits the original message the interaction was triggered on (for buttons).
interaction:getOption(name)
Retrieves value of a command option.
interaction:getModalValue(id)
Gets the value from a modal text input.
interaction:cancelJava() WardenX
Stops WardenX's built-in Java handler for this command.
interaction:getMember() / getUser()
Returns the LuaMember or LuaUser who triggered the interaction.
interaction:getChannel() / getGuild()
Returns where the interaction happened.

Servers (Guilds) Discord

guild:getId()
Returns the guild's unique ID string.
guild:getName()
Returns the server's name.
guild:getIconUrl()
Returns the URL of the guild's icon.
guild:getSelf()
Returns the LuaMember representing the bot.
guild:getMemberCount()
Returns number of members.
guild:getMembers()
Returns a list of all LuaMember objects.
guild:getMember(id)
Returns a LuaMember for the given ID.
guild:getOwner()
Returns the owner LuaMember.
guild:getRoles()
Returns a list of all LuaRole objects.
guild:getRole(id)
Returns a LuaRole by ID (use everyone for public role).
guild:getTextChannels() / getVoiceChannels()
Returns specific channel types.
guild:getChannel(id)
Returns a LuaChannel for the given ID.
guild:newModlog() WardenX
Returns a new LuaModlog instance.
guild:createTextChannel(name)
Creates a new text channel.
guild:sendMessage(channelId, content, [embed])
Sends a message to a specific channel.
guild:ban(userId, [options])
Bans a user. Options: {time, timescale, reason}. Supported timescales: HOURS, DAYS.
guild:softBan(userId, [options])
Bans and immediately unbans to clear messages.
guild:kick(userId, [reason])
Kicks a user.
guild:unban(userId)
Unbans a user.

Members & Users Discord

LuaMember objects represent a user within a specific server and inherit all LuaUser methods.

member:getId()
Returns the member's unique ID.
member:getUsername() / getGlobalName()
Returns unique username or global display name.
member:getEffectiveName()
Returns nickname, global name, or username (whichever is available).
member:getNickname()
Returns the guild-specific nickname.
member:getAvatarUrl()
Returns effective avatar URL.
member:getGuild()
Returns the LuaGuild the member belongs to.
member:canInteract(other)
Checks if member can interact with another member or role.
member:getHighestRole() / getRoles()
Returns role information.
member:hasPermission(name) / hasPermissions(...)
Checks for Discord permissions.
member:isOwner() / isBot()
Boolean status checks.
member:setNickname(name)
Changes the member's nickname.
member:addRole(roleId) / removeRole(roleId)
Manages member roles.
member:timeout(minutes, [reason])
Timeouts the member.
member:removeTimeout() / isTimedOut()
Timeout management.
member:kick([reason]) / ban([options])
Moderation actions.

LuaUser

Represents a global Discord user.

user:getId() / getUsername()
Basic user info.
user:getAvatarUrl()
Returns the URL of the user's avatar.
user:isBot()
Returns true if the user is a bot.

Roles Discord

role:getId()
Returns the role's unique ID.
role:getName() / role:setName(name)
Gets or sets the role name.
role:getPosition()
Returns the role's position in the hierarchy.
role:getColorHex() / role:setColor(hex)
Gets or sets the role color (e.g., "#FF0000").
role:isHoisted() / isMentionable() / isManaged()
Boolean status checks.
role:hasPermission(name) / hasPermissions(...)
Checks for Discord permissions.
role:delete()
Deletes the role from the server.

Channels & Categories Discord

channel:getId() / getName() / setName(name)
Basic channel info.
channel:sendMessage(content, [embed], [components])
Sends a message to the channel.
channel:getType()
Returns "TEXT", "VOICE", etc.
channel:getCategory()
Returns the parent LuaCategory.
channel:delete()
Deletes the channel.

LuaCategory

category:getName() / setName(name)
Category name management.
category:getChannels()
Returns a list of channels in the category.

Messages Discord

message:getId() / getContent()
Returns the ID or text content of the message.
message:getAuthor() / getAuthorId()
Returns author information.
message:getChannel() / getGuild()
Returns location of the message.
message:update(content, [embed], [components])
Updates the message (only if sent by the bot).
message:delete()
Deletes the message.

Embeds Discord

Use wardenx.newEmbed() to create a builder.

embed:setTitle(text, [url]) / setDescription(text)
Sets core embed content.
embed:addField(name, value, [inline])
Adds a field to the embed.
embed:setColor(hex) / setThumbnail(url) / setImage(url)
Visual styling.
embed:setAuthor(name, [url], [icon]) / setFooter(text, [icon])
Sets author and footer info.
embed:build()
Finalizes the builder and returns a LuaMessageEmbed.

LuaMessageEmbed

Read-only representation of a sent or received embed.

embed:getTitle() / getDescription() / getFields()
Retrieves embed data.
embed:getBuilder()
Returns a LuaEmbedBuilder pre-filled with this embed's data for easy editing.

Components (Buttons) Discord

button:setStyle(style)
Styles: PRIMARY, SECONDARY, SUCCESS, DANGER, LINK.
button:setAction(function(interaction) ... end) WardenX
Sets a Lua function to run when clicked.

Advanced Features WardenX

Type Casting

Use type hints in the editor for better autocomplete.

local m: member = guild:getMember("ID")
m:getNickname() -- Editor now knows 'm' is a member

Security & Limits WardenX

  • Sandboxing: os, io, and debug libraries are disabled.
  • Timeouts: Long-running scripts are terminated to prevent lag.
  • Memory: Scripts have strict memory limits.

Code Examples

Map users roles to global storage

function saveRoles(m: member)
    local roles = m:getRoles() or {}
    if #roles == 0 then return end

    local roleIds = {}
    for _,role in ipairs(roles) do
        print("saving " .. role:getName() .. " with role id: " .. tostring(role:getId()))
        table.insert(roleIds, tostring(role:getId()))
    end

    local existingData = storage:get("roleStores") or {}

    local userId = m:getId()
    existingData[userId] = roleIds

    storage:set("roleStores", existingData)
end

I'll add more eventually