| Event | Parameters | Fires when |
| messageCreate | message | Message sent |
| messageDelete | message | Message deleted |
| messageEdit | message | Message edited |
| memberJoin | member | Member joined |
| memberLeave | member | Member left |
| memberUpdate | member | Member updated |
| buttonClick | interaction | Button clicked |
| selectMenu | interaction | Menu selected |
| command | "nome", message, args | Prefix command |
| reactionAdd | emoji, user, message | Reaction added |
| reactionRemove | emoji, user, message | Reaction removed |
| voiceJoin | member | Joined voice channel |
| voiceLeave | member | Left voice channel |
| banAdd | user | User banned |
| banRemove | user | Ban removed |
| channelCreate | channel | Channel created |
| channelDelete | channel | Channel deleted |
| Property / Method | Type | Description |
| .id | string | Message ID |
| .content | string | Message text |
| .author | object | Author — id, username, isBot… |
| .channel | string | Channel ID |
| .reply(texto, opts?) | function | Replies to the message. opts.embed, opts.components |
| .edit(texto, opts?) | function | Edits the message |
| .delete() | function | Deletes the message |
| .react(emoji) | function | Adds a reaction. E.g.: "👋" |
| .pin() | function | Pins the message |
| .unpin() | function | Unpins the message |
| Property / Method | Type | Description |
| .id | string | User ID |
| .username | string | Username |
| .nickname | string | Server nickname |
| .avatar | string | Avatar URL |
| .roles | array | Role IDs |
| .createdAt | string | Account creation date (ISO) |
| .joinedAt | string | Server join date (ISO) |
| .isBot | bool | Whether it's a bot |
| .permissions | string | Permissions bitfield |
| .send(texto, opts?) | function | Sends a DM |
| .addRole(id) | function | Adds a role |
| .removeRole(id) | function | Removes a role |
| .timeout(ms) | function | Applies a timeout in milliseconds |
| .removeTimeout() | function | Removes timeout |
| .ban(motivo?) | function | Bans the user |
| .kick() | function | Kicks from the server |
| Property / Method | Type | Description |
| .id | string | Channel ID |
| .name | string | Channel name |
| .type | number | Type (0=text, 2=voice, 5=announcement…) |
| .category | string | Parent category ID |
| .send(texto, opts?) | function | Sends a message in the channel |
| .rename(nome) | function | Renames the channel |
| .lock() | function | Locks sending for @everyone |
| .unlock() | function | Unlocks the channel |
| Property | Type | Description |
| .id | string | Server ID |
| .name | string | Server name |
| .memberCount | number | Total members |
| .owner | string | Owner's ID |
| .roles | array | IDs of all roles |
| .channels | array | IDs of all channels |
| Property / Method | Type | Description |
| .customId | string | ID of the clicked component |
| .values | array | Selected values (SelectMenu) |
| .userId | string | ID of whoever triggered the interaction |
| .user() | function | Returns the full User object of whoever triggered the interaction (async) |
| .reply(texto, opts?) | function | Replies. opts.ephemeral, opts.embed, opts.components |
| .update(texto, opts?) | function | Updates the component's own message (same opts as .reply()) — only works in response to a not-yet-answered buttonClick/selectMenu |
| .defer(ephemeral?) | function | Defers the reply (shows loading) |
| .edit(texto, opts?) | function | Edits the original reply |
| .followUp(texto, opts?) | function | Sends a follow-up message |
| .showModal(modal) | Modal | Opens a popup form — see the Modal section |
| Method | Parameter | Description |
| .setTitle(v) | string | Embed title |
| .setDescription(v) | string | Description |
| .setColor(v) | string | number | Color. E.g.: "#A9D6FF", "Blurple", 0x5865F2 |
| .setURL(v) | string | Title URL |
| .setTimestamp(v?) | string | nil | Timestamp. nil = now |
| .setThumbnail(url) | string | Small image (top-right) |
| .setImage(url) | string | Large image (bottom) |
| .setAuthor(opts) | object | { name, url?, iconURL? } |
| .setFooter(opts) | object | { text, iconURL? } |
| .addFields(...fields) | object[] | { name, value, inline? } — multiple |
| .setFields(...fields) | object[] | Replaces all fields |
Color names available in setColor()
Default
White
Aqua
Green
Blue
Yellow
Purple
LuminousVividPink
Fuchsia
Gold
Orange
Red
Grey
Navy
DarkGold
DarkOrange
Blurple
Greyple
DarkButNotBlack
NotQuiteBlack
DarkGreen
DarkBlue
DarkRed
DarkGrey
DarkerGrey
LightGrey
DarkNavy
Random
| Method | Parameter | Description |
| .setTitle(v) | string | Form title (max. 45 characters) |
| .addTextInput(customId, label, opts?) | string, string, object? | Adds a text field. opts: { style: "short"|"long", placeholder, required, minLength, maxLength, value } |
| .onSubmit(fn, opts?) | function, object? | Registers the form submission. fn(interaction, fields) — fields holds each field's value by customId. opts: { user: true|"id", ttl: ms } |
| On the interaction object | Parameter | Description |
| interaction.showModal(modal) | Modal | Opens the form. modal must have already gone through .onSubmit(fn) |
Discord limitation: a Modal only opens in response to an existing interaction (inside on(buttonClick) or on(selectMenu), or in the temporary .onClick() of a Button/SelectMenu) — never from on(command), which is a plain message with no interaction token behind it.
on command("feedback", message, args)
let btn = Button()
.setLabel("Dar feedback")
.onClick(function(interaction)
let modal = Modal()
.setTitle("Feedback")
.addTextInput("nota", "Nota de 1 a 5", { style: "short" })
.addTextInput("comentario", "Comentário", { style: "long", required: false })
.onSubmit(function(interaction, fields)
interaction.reply("Recebido! Nota: " .. fields.nota .. " — " .. fields.comentario)
end)
interaction.showModal(modal)
end)
message.reply("Clica pra dar feedback:", { components: [btn] })
end
| Method | Parameters | Returns |
| db.set(chave, valor) | string, any | — |
| db.get(chave) | string | any | nil |
| db.has(chave) | string | bool |
| db.delete(chave) | string | — |
| Method | Parameters | Returns |
| .set(chave, valor) | string, any | — |
| .get(chave) | string | any | nil |
| .has(chave) | string | bool |
| .add(chave, n) | string, number | number (novo valor) |
| .sub(chave, n) | string, number | number (novo valor) |
| Method | Parameters | Returns |
| .set(chave, valor) | string, any | — |
| .get(chave) | string | any | nil |
| Function | Parameters | Returns |
| length(s) | string | number |
| contains(s, sub) | string, string | bool |
| replace(s, de, para) | string, string, string | string |
| split(s, sep) | string, string | array |
| join(arr, sep) | array, string | string |
| lower(s) | string | string |
| upper(s) | string | string |
| trim(s) | string | string |
| tostring(v) | any | string |
| tonumber(s) | string | number |
| type(v) | any | string |
| Function | Parameters | Returns |
| random(min, max) | number, number | number — integer between min and max |
| random() | — | number — decimal between 0 and 1 |
| round(n) | number | number |
| floor(n) | number | number |
| ceil(n) | number | number |
| abs(n) | number | number |
| max(a, b, …) | ...number | number |
| min(a, b, …) | ...number | number |
| Function | Parameters | Returns |
| push(arr, v) | array, any | array |
| pop(arr) | array | any — last element |
| insert(arr, i, v) | array, number, any | array |
| remove(arr, i) | array, number | array |
| size(v) | array | object | number |
| keys(obj) | object | array of strings |
| values(obj) | object | array of values |
| Function | Parameters | Returns |
| json.encode(v) | any | string — JSON |
| json.decode(s) | string | object | nil |
| Function | Parameters | Description |
| print(…) | ...any | Prints to the Dashboard console |
| wait(ms) | number | Waits N ms. Accumulated max: 30,000ms per run |
| sendMessage(canal, texto, opts?) | string|object, string, object? | Sends a message. opts.embed, opts.components |
| sendDM(user, texto, opts?) | string|object, string, object? | Sends a direct DM |
| getUser() | — | Returns the current context's user |
| getChannel(id?) | string? | Returns a channel (from context or by ID) |
| getGuild() | — | Returns the current server |
| getInteraction() | — | Returns the current interaction |
| getMessage() | — | Returns the context's message |
| PREFIX | string | Constant with the server's configured command prefix (e.g. "!") — not a function, it's a global variable |
| runFlow(flowId) | string |
Runs a Logic Builder Flow by ID, sharing the current context's server/channel/user.
🌙 Lua Crescente+
|
HTTP requests to outside Discord. Always go through the same security filter: response size limit, timeout, blocking of localhost/private IPs, and a request limit per script run.
| Function | Parameters | Returns |
| http.get(url, opts?) | string, object? | { ok, status, headers, body, json, text } |
| http.post(url, body?, opts?) | string, any?, object? |
| http.put(url, body?, opts?) | string, any?, object? |
| http.patch(url, body?, opts?) | string, any?, object? |
| http.delete(url, opts?) | string, object? |
opts.headers accepts a custom headers object in every method. On servers without this feature unlocked, calling any http method throws an error explaining which plan is required.
| Function | Parameters | Returns |
| webhook.send(url, texto, opts?) |
string, string, object? |
{ ok, status } |
Sends a message via a Discord Webhook (external URL). opts.username, opts.avatarUrl, and opts.embed are optional.
Every time parameter below accepts 3 formats: a number in milliseconds (60000), a duration as text ("1h", "30m", "10s", "2d"), or a fixed time in "HH:MM" format (e.g. "9:00") — in which case it runs the next time that time comes around.
| Function | Parameters | Description |
| schedule(tempo, canal, texto, opts?) |
number|string, string|object, string, object? |
Schedules a message. Without opts.recurring, it runs once. With { recurring: true }: if time is a time of day ("9:00"), it repeats every day at that time; if it's a duration ("2h"), it repeats every that interval. Returns the schedule's id.
|
| cancelSchedule(id) | string | Cancels a pending schedule by the id returned by schedule() |
| listSchedules() | — | Lists this server's pending schedules: { id, channelId, texto, executeAt, recorrente }[] |
| cooldown(chave, tempo) | string, number|string | Returns true if the current user can act now (and marks the cooldown); false if still on cooldown |
| cooldownRestante(chave) | string | Milliseconds remaining on the cooldown with that key for the current user (0 if none) |
on command("bomdia", message, args)
schedule("9:00", message.channel, "☀️ Bom dia!", { recorrente: true })
message.reply("Agendado pra todo dia às 9h.")
end
on command("lembrar", message, args)
if not cooldown("lembrar", "1m") then
message.reply("⏳ Espera um pouco antes de criar outro lembrete.")
return
end
schedule("1h", message.channel, "⏰ Lembrete: " .. args._[0])
message.reply("Beleza! Te lembro em 1 hora.")
end
| Op. | Description | Exemplo |
| + | Addition | 2 + 3 → 5 |
| - | Subtraction | 10 - 4 → 6 |
| * | Multiplication | 3 * 4 → 12 |
| / | Division | 10 / 2 → 5 |
| % | Modulo | 10 % 3 → 1 |
| .. | Concatenation | "Oi ".."Ayami" |
| Op. | Description |
| == | Equal |
| != | Not equal |
| < | Less than |
| > | Greater than |
| <= | Less than or equal to |
| >= | Greater than or equal to |
| and | Logical AND |
| or | Logical OR |
| not | Negation |
let
const
function
return
if
elseif
else
then
end
while
for
in
do
break
continue
on
import
export
from
and
or
not
true
false
nil
new
| Limit | Value |
| Steps per run | 50 000 |
| Recursion depth | 200 levels |
| Total wait() per run | 30 000ms |
| Concurrent scripts per server | 20 |
| print() outputs per run | 200 lines |
| Log TTL | 7 days |
| Plan | .logic files | Functions per file | HTTP / Webhook / runFlow | /daily bonus |
| Free | 6 | 15 | ❌ Locked | — |
| New Star | 15 | 40 | ❌ Locked | 1.5x |
| Crescent Moon | 35 | Unlimited | ✅ Unlocked | 2.5x |
| Constellation | Unlimited | Unlimited | ✅ Unlocked | 3.5x |
"Functions per file" only counts function/export function declarations at the top level of the file (outside on(...) blocks). HTTP, Webhook, and runFlow() are unlocked from the Crescent Moon plan onward — calling them without the required plan throws an error explaining the minimum plan needed.