### startStage(channelId, topic, options?) Source: https://mallard.bot/docs/functions Starts a stage in a stage channel with a topic and returns the stage instance's ID. options.notify pings @everyone that the stage started. ```APIDOC ## startStage(channelId, topic, options?) ### Description Starts a stage in a stage channel with a topic and returns the stage instance's ID. options.notify pings @everyone that the stage started. ### Method async ### Endpoint startStage(channelId, topic, options?) ### Parameters #### Path Parameters - **channelId** (string) - Required - The stage channel. - **topic** (string) - Required - What the stage is about (1-120 characters). - **options** ({ notify?: boolean }, optional) - Extras. ### Response #### Success Response - **Promise** - The stage instance ID. #### Response Example ```json "stage_instance_id" ``` ``` -------------------------------- ### getKV(key, options?) Source: https://mallard.bot/docs/functions Gets a value from the guild's key-value store, optionally locking the key for safe read-modify-write. ```APIDOC ## getKV(key, options?) ### Description Retrieves a value from the guild's key-value store. Reads don't lock by default; pass `{ lock: true }` to take the key's lock for a safe read-modify-write. The reserved system key "env" is not accessible here. ### Method Function ### Endpoint getKV(key, options?) ### Parameters - **key** (`string`) - Required - Key to look up. - **options** (`{ lock?: boolean }`, optional) - `lock`: take the key's lock before reading. ### Returns `Promise` - The stored JSON string, or null if not found / expired. ``` -------------------------------- ### createAutoModRule(options) Source: https://mallard.bot/docs/functions Creates an AutoMod rule: setup wizards, a /raidmode toggle, word lists synced from the key-value store. Discord allows 6 keyword rules and one each of spam, preset, mentionSpam and memberProfile. Rules that would match every message (an empty-matching regex, the keyword "*") are refused. The audit log names the script. A run can create, change or delete 5 rules. ```APIDOC ## createAutoModRule(options) ### Description Creates an AutoMod rule: setup wizards, a /raidmode toggle, word lists synced from the key-value store. Discord allows 6 keyword rules and one each of spam, preset, mentionSpam and memberProfile. Rules that would match every message (an empty-matching regex, the keyword "*") are refused. The audit log names the script. A run can create, change or delete 5 rules. ### Requirements Mallard needs: ManageGuild ### Parameters - **options** (AutoModRuleOptions) - Required - e.g. { name: "No invites", trigger: "keyword", keywords: ["discord.gg/*"], actions: [{ type: "block", message: "No invite links" }] }. ### Returns - **Promise** - The new rule's ID. ``` -------------------------------- ### /ban command: TriggerConfig options and script body Source: https://mallard.bot/docs/commands Worked example adapted from the seeded `/ban` command (the mod-role permission guard is omitted). The JSON block defines the command options: one required `User`, one required `String`, and two optional `Integer` options. The script body shows the `parseInt()` conversion and the `ctx.args.reason || "No reason provided"` fallback idiom, plus DM-before-ban, KV-store pending unban logging, and the `editResponse` summary. ```json { "options": [ { "name": "user", "type": "User", "description": "The user to ban", "required": true }, { "name": "reason", "type": "String", "description": "Reason for the ban", "required": true }, { "name": "duration_min", "type": "Integer", "description": "Duration in minutes (0 = permanent)", "required": false }, { "name": "delete_message_days", "type": "Integer", "description": "Days of messages to delete", "required": false } ] } ``` ```javascript var userId = ctx.args.user; var reason = ctx.args.reason || "No reason provided"; var durationMin = ctx.args.duration_min ? parseInt(ctx.args.duration_min) : 0; var deleteDays = ctx.args.delete_message_days ? parseInt(ctx.args.delete_message_days) : 0; var isPermanent = durationMin <= 0; var target = getMember(userId); var targetName = target ? target.username : userId; // DM before the ban: afterwards there's no mutual guild left to DM through. // false means their DMs are closed, and the ban still goes ahead. var dmSent = sendDm(userId, "", [{ title: isPermanent ? "Permanent Ban" : "Temporary Ban", description: "Reason: " + reason, }]); ban(userId, reason, deleteDays); if (!isPermanent) { // Actions can't be delayed, so log the unban due time to the KV store; // a Scheduled script sweeps due entries on its next run. var pending = JSON.parse(getKV("mod:pending_unbans") || "[]"); pending.push({ userId: userId, unbanAt: Date.now() + durationMin * 60000, reason: reason }); setKV("mod:pending_unbans", JSON.stringify(pending)); } var target = getMember(userId); var targetName = target ? target.username : userId; editResponse("Banned " + targetName + " (" + userId + "). Reason: " + reason + (dmSent ? "" : " (could not DM them the appeal link)")); ``` -------------------------------- ### expectReply(userId, channelId, scriptName, timeoutSeconds, payload?) Source: https://mallard.bot/docs/functions Waits for a user's next message in a channel and hands it to a ReplyReceived script, with a payload. This is the building block for step-by-step setups. If they don't answer within the timeout, the same script runs with ctx.reply.timedOut true. A new wait for the same user and channel replaces the old one. ```APIDOC ## expectReply(userId, channelId, scriptName, timeoutSeconds, payload?) ### Description Waits for a user's next message in a channel and hands it to a ReplyReceived script, with a payload. This is the building block for step-by-step setups. If they don't answer within the timeout, the same script runs with ctx.reply.timedOut true. A new wait for the same user and channel replaces the old one. ### Parameters - **userId** (string) - Required - Whose reply to wait for. - **channelId** (string) - Required - Where (a channel or thread in this server). - **scriptName** (string) - Required - Name of a script with the ReplyReceived trigger. - **timeoutSeconds** (number) - Required - How long to wait (5 seconds to 24 hours). - **payload** (any, optional) - Anything JSON-serialisable, read back as ctx.reply.payload. ### Returns - **void** ``` -------------------------------- ### createThread(channelId, name, isPrivate, userIds?, initialMessage?, options?) Source: https://mallard.bot/docs/functions Creates a thread under a channel, optionally adding initial members and an opening message. Returns the created thread's snowflake ID. On a forum or media channel this creates a post, using initialMessage (or the name, when empty) as its body; createForumPost() gives more control there. To start a thread from an existing message, use createThreadFromMessage(). ```APIDOC ## createThread(channelId, name, isPrivate, userIds?, initialMessage?, options?) ### Description Creates a thread under a channel, optionally adding initial members and an opening message. Returns the created thread's snowflake ID. On a forum or media channel this creates a post, using initialMessage (or the name, when empty) as its body; createForumPost() gives more control there. To start a thread from an existing message, use createThreadFromMessage(). ### Method async ### Endpoint createThread(channelId, name, isPrivate, userIds?, initialMessage?, options?) ### Parameters #### Path Parameters - **channelId** (string) - Required - Discord snowflake ID of the parent channel. - **name** (string) - Required - Thread name. - **isPrivate** (boolean) - Required - Create a private thread. - **userIds** (string | string[], optional) - User IDs to add, as an array or a comma-separated string (empty for none). - **initialMessage** (string, optional) - Message posted into the thread after creation, or empty string. - **options** ({ autoArchiveMinutes?: number, slowmode?: number, tagIds?: string[], reason?: string }, optional) - autoArchiveMinutes is 60, 1440, 4320 or 10080; tagIds applies to forum posts. ### Response #### Success Response - **Promise** - The created thread's snowflake ID. #### Response Example ```json "thread_id" ``` ``` -------------------------------- ### createThreadFromMessage Source: https://mallard.bot/docs/functions Starts a thread from an existing message and returns the thread ID. ```APIDOC ## createThreadFromMessage ### Description Starts a thread from an existing message (the "Create Thread" item on a message) and returns the thread ID. Auto-thread every post in a channel from a MessageCreate script. ### Signature `createThreadFromMessage(channelId, messageId, name, options?): Promise` ### Parameters - **channelId** (`string`) - Required - The channel the message is in. - **messageId** (`string`) - Required - The message to start from. - **name** (`string`) - Required - Thread name (1-100 characters). - **options** (`{ autoArchiveMinutes?: number, slowmode?: number, reason?: string }`, optional) - Extras. ### Returns `Promise` - The new post's thread ID. ### Permissions Mallard needs: CreatePublicThreads ``` -------------------------------- ### zIncr(set, member, by?) Source: https://mallard.bot/docs/functions Adds to a member's score in a sorted set (a missing member starts at 0) and returns the new score. Atomic, so any number of runs can add at once without a lock: the way to keep XP, message counts or invite counts for a leaderboard. Each member costs its length plus 16 bytes of storage; a set holds up to 10,000 members on Free (25k Plus, 50k Pro, 100k Ultra) and a server can have 100 sets. ```APIDOC ## zIncr(set, member, by?) ### Description Adds to a member's score in a sorted set (a missing member starts at 0) and returns the new score. Atomic, so any number of runs can add at once without a lock: the way to keep XP, message counts or invite counts for a leaderboard. Each member costs its length plus 16 bytes of storage; a set holds up to 10,000 members on Free (25k Plus, 50k Pro, 100k Ultra) and a server can have 100 sets. ### Parameters - **set** (string) - Required - The set's name, e.g. "xp". - **member** (string) - Required - Who or what is scored, usually a user ID (up to 100 characters). - **by** (number, optional) - Amount to add (may be negative; defaults to 1). ### Returns - **Promise** - The member's new score. ``` -------------------------------- ### zRank(set, member, options?) Source: https://mallard.bot/docs/functions Gets a member's position, counting from 0 at the highest score (so rank + 1 is their place on the leaderboard). Pass { asc: true } to count from the lowest instead. ```APIDOC ## zRank(set, member, options?) ### Description Gets a member's position, counting from 0 at the highest score (so rank + 1 is their place on the leaderboard). Pass { asc: true } to count from the lowest instead. ### Parameters - **set** (string) - Required - The set's name. - **member** (string) - Required - The member. - **options** ({ asc?: boolean }, optional) - Ascending order instead of descending. ### Returns - **Promise** - The member's rank, or null when not in the set. ``` -------------------------------- ### zGet(set, member) Source: https://mallard.bot/docs/functions Gets a member's score. ```APIDOC ## zGet(set, member) ### Description Gets a member's score. ### Parameters - **set** (string) - Required - The set's name. - **member** (string) - Required - The member. ### Returns - **Promise** - The score, or null when the member isn't in the set. ``` -------------------------------- ### listKV(prefix?, limit?, afterKey?) Source: https://mallard.bot/docs/functions Lists stored keys with optional prefix, limit, and pagination. ```APIDOC ## listKV(prefix?, limit?, afterKey?) ### Description Lists server's stored keys, optionally filtered by prefix, in alphabetical order. Returns keys, not values. Page past the limit with afterKey. Expired keys and the reserved "env" row are never listed. ### Method Function ### Endpoint listKV(prefix?, limit?, afterKey?) ### Parameters - **prefix** (`string`, optional) - Only keys starting with this. Empty or omitted lists everything. - **limit** (`number`, optional) - How many to return (1-1000; defaults to 100). - **afterKey** (`string`, optional) - Return keys after this one (the last key of previous page). ### Returns `Promise` - Array of matching keys. ``` -------------------------------- ### getAutoModRule(ruleId) Source: https://mallard.bot/docs/functions Gets a single AutoMod rule. ```APIDOC ## getAutoModRule(ruleId) ### Description Gets a single AutoMod rule. ### Requirements Mallard needs: ManageGuild ### Parameters - **ruleId** (string) - Required - The rule's ID. ### Returns - **Promise** - The rule, or null when it doesn't exist. ``` -------------------------------- ### fetch() Source: https://mallard.bot/docs/subsystems Documentation for the fetch() function, the only network access available to scripts. ```APIDOC ## fetch() ### Description Performs outbound HTTP requests from scripts. HTTPS-only by default, with configurable timeout and automatic decompression. Supports GET, POST, PUT, PATCH, DELETE, and HEAD methods. Blocks private/internal addresses (SSRF-guarded). ### Method GET, POST, PUT, PATCH, DELETE, HEAD ### Endpoint N/A (outbound HTTP) ### Parameters #### Options (object or JSON string) - **method** (string) - Optional - HTTP method (default: GET) - **headers** (object) - Optional - Allowed headers: `accept`, `content-type`, `authorization`, `user-agent`, `client-id`, `api-key`, `anthropic-version`, and any `x-*` header. Others are dropped. - **body** (string | object) - Optional - Request body, capped at 64 KB. - **timeoutMs** (number) - Optional - Timeout in milliseconds, up to 30000 (default: 5000). ### Request Example ```json { "method": "POST", "headers": { "content-type": "application/json" }, "body": { "key": "value" }, "timeoutMs": 10000 } ``` ### Response #### Success Response - Response body auto-decompressed, capped at 1 MB (post-decompression). ### Notes - HTTPS-only by default; HTTP allowed only when env record has `fetch_allow_http` set. - Standard ports only. - Private/internal addresses are blocked. - `{{secret:NAME}}` placeholders in URL, header values, or body are substituted server-side. - Per-guild limits: 30 requests/minute (flat sliding window) and hourly call budget by tier (10/30/60/120 on Free/Plus/Pro/Ultra). - Live remaining calls available via `ctx.fetchCallsRemaining`. ``` -------------------------------- ### getVoiceState(userId) Source: https://mallard.bot/docs/functions Gets a member's current voice state. ```APIDOC ## getVoiceState ### Description Where a member is in voice right now, or null when they aren't connected. ### Parameters - **userId** (string) - Required - Discord snowflake ID of the member. ### Returns - **Promise\** - Their voice state. ``` -------------------------------- ### createChannel(name, type, parentIdOrOptions?, topic?, reason?) Source: https://mallard.bot/docs/functions Creates a channel in the guild and returns its snowflake ID. Pass an options object as the third argument to set everything at once, including permission overwrites, which is how a private ticket channel is made in a single step: createChannel("ticket-42", "text", { parentId, overwrites: [{ targetId: ctx.guildId, deny: ["ViewChannel"] }, { targetId: ctx.actorId, targetIsRole: false, allow: ["ViewChannel", "SendMessages"] }] }). ```APIDOC ## createChannel(name, type, parentIdOrOptions?, topic?, reason?) ### Description Creates a channel in the guild and returns its snowflake ID. Pass an options object as the third argument to set everything at once, including permission overwrites, which is how a private ticket channel is made in a single step: createChannel("ticket-42", "text", { parentId, overwrites: [{ targetId: ctx.guildId, deny: ["ViewChannel"] }, { targetId: ctx.actorId, targetIsRole: false, allow: ["ViewChannel", "SendMessages"] }] }). ### Parameters - **name** (`string`) - Required - Name for the new channel. - **type** (`string`) - Required - Channel kind: "text", "voice", "category", "announcement", "forum", "media", or "stage". - **parentIdOrOptions** (`string | ChannelOptions`, optional) - Category ID to nest under (empty for none), or an options object: {parentId, topic, position, nsfw, slowmode, userLimit, bitrate, overwrites: [{targetId, targetIsRole?, allow?, deny?}]}. - **topic** (`string`, optional) - Channel topic/description (empty for none). - **reason** (`string`, optional) - Audit log reason. ### Returns `Promise` - The created channel's snowflake ID. ``` -------------------------------- ### lockThread(threadId, locked, reason?) Source: https://mallard.bot/docs/functions Locks or unlocks a thread / forum post (locked threads can't get new messages). ```APIDOC ## lockThread(threadId, locked, reason?) ### Description Locks or unlocks a thread / forum post (locked threads can't get new messages). ### Method async ### Endpoint lockThread(threadId, locked, reason?) ### Parameters #### Path Parameters - **threadId** (string) - Required - Discord snowflake ID of the thread. - **locked** (boolean) - Required - true to lock, false to unlock. - **reason** (string, optional) - Audit log reason. ### Response #### Success Response No return value. ``` -------------------------------- ### pauseInvites(hours, reason?) Source: https://mallard.bot/docs/functions Pauses joining through invites for up to 24 hours. Requires the ManageGuild permission. ```APIDOC ## pauseInvites(hours, reason?) ### Description Pauses joining through invites for up to 24 hours (Discord's own raid-mode switch, shown to members as "invites paused"). 0 resumes them. The other pause (DMs) is left as it is. ### Method async function ### Parameters - **hours** (number) - Required - How long to pause (0-24; fractions allowed). 0 resumes. - **reason** (string, optional) - Optional - Audit log reason. ### Returns void ### Permissions Mallard needs: ManageGuild ``` -------------------------------- ### getKVMany(keys) Source: https://mallard.bot/docs/functions Batch retrieves multiple keys from the KV store in a single call. ```APIDOC ## getKVMany(keys) ### Description Reads many keys in one call, e.g. every key listKV() returned. Missing keys come back null. ### Method Function ### Endpoint getKVMany(keys) ### Parameters - **keys** (`string[]`) - Required - Up to 1000 keys. ### Returns `Promise>` - Mapping of key to stored JSON string, or null if missing. ``` -------------------------------- ### getStickers() Source: https://mallard.bot/docs/functions Returns the server's stickers. ```APIDOC ## getStickers() ### Description Returns the server's stickers, whose IDs MessageOptions.stickerIds takes. Live REST read. ### Method async function ### Signature getStickers(): Promise ### Returns Promise - The server's stickers. ``` -------------------------------- ### setKV(key, value, ttlSeconds?) Source: https://mallard.bot/docs/functions Stores a value in the guild's key-value store, overwriting existing values, with optional TTL. ```APIDOC ## setKV(key, value, ttlSeconds?) ### Description Stores a value in the guild's key-value store, overwriting any existing value. Strings are stored as-is (should be JSON); other values are JSON-encoded. Written immediately, survives script errors. The reserved system key "env" cannot be written. ### Method Function ### Endpoint setKV(key, value, ttlSeconds?) ### Parameters - **key** (`string`) - Required - Key to store under. - **value** (`any`) - Required - A JSON string, or any value to be JSON-encoded. - **ttlSeconds** (`number`, optional) - Time-to-live in seconds; 0 or omitted for no expiry. ### Returns `void` - Nothing. ``` -------------------------------- ### setVerificationLevel(level, reason?) Source: https://mallard.bot/docs/functions Changes the server's verification level, raid mode's other half: "high" makes new accounts wait 10 minutes in the server before talking. ```APIDOC ## setVerificationLevel(level, reason?) ### Description Changes the server's verification level, raid mode's other half: "high" makes new accounts wait 10 minutes in the server before talking. ### Parameters - **level** (`string`) - Required - "none", "low", "medium", "high" or "veryHigh". - **reason** (`string`, optional) - Audit log reason. ### Returns `Promise` ``` -------------------------------- ### getIntegrations() Source: https://mallard.bot/docs/functions Lists the server's integrations: bots, Twitch/YouTube subscription roles and other connections. Pair with the GuildIntegrationsUpdate trigger. ```APIDOC ## getIntegrations() ### Description Lists the server's integrations: bots, Twitch/YouTube subscription roles and other connections. Pair with the GuildIntegrationsUpdate trigger. ### Method async ### Endpoint getIntegrations() ### Parameters None ### Response #### Success Response - **IntegrationSummary[]** - The server's integrations. #### Response Example ```json [] ``` ``` -------------------------------- ### listChannels() Source: https://mallard.bot/docs/functions Lists the guild's cached channels (id, name, type, category, position; no threads). This is a cheap cached read with no REST call. ```APIDOC ## listChannels() ### Description Lists the guild's cached channels (id, name, type, category, position; no threads). Cheap cached read (no REST), like listMembers. type and parentId fill in when the bot next reconnects for channels cached before this field existed. ### Method Function ### Signature `listChannels(): Promise` ### Parameters None ### Returns `Promise` - Array of the guild's channels. ``` -------------------------------- ### listLater(scriptName?) Source: https://mallard.bot/docs/functions Lists the server's pending runLater() jobs, soonest first. Optionally filter by script name. ```APIDOC ## listLater(scriptName?) ### Description Lists the server's pending runLater() jobs, soonest first. Optionally filter by script name. ### Parameters - **scriptName** (string, optional) - Only jobs for this script. ### Returns - **Promise** - Pending jobs. ``` -------------------------------- ### Send a leaderboard layout with top 10 XP Source: https://mallard.bot/docs/subsystems Builds a layout message showing the top 10 XP members using zRange and a container with two text blocks. The text block content is joined with newlines. ```javascript // A leaderboard card const top = zRange("xp", 0, 9, { withScores: true }); sendMessage(channelId, { layout: [{ type: "container", accentColor: 0xF1C40F, children: [ { type: "text", text: "## ๐Ÿ† Top 10" }, { type: "text", text: top.map((e, i) => `**${i + 1}.** <@${e.member}> ยท ${e.score} XP`).join("\n") } ]}]}); ``` -------------------------------- ### createEmoji(name, mediaId, reason?) Source: https://mallard.bot/docs/functions Creates a custom emoji from an image on the server's Media page. Requires the CreateGuildExpressions permission. ```APIDOC ## createEmoji(name, mediaId, reason?) ### Description Creates a custom emoji from an image on the server's Media page (PNG, JPEG, WebP or GIF, 256 KB at most) and returns it. Only the Media page is a source: Mallard never fetches an arbitrary URL for this. ### Method Function ### Signature `createEmoji(name, mediaId, reason?): Promise` ### Parameters - **name** (string) - Required - Emoji name (2-32 letters, numbers or underscores). - **mediaId** (string) - Required - ID of an image on the Media page. - **reason** (string, optional) - Audit log reason. ### Required Permissions CreateGuildExpressions ### Returns `Promise` ``` -------------------------------- ### aiChat(promptOrOptions, options?) Source: https://mallard.bot/docs/functions Sends a chat completion request to OpenRouter. ```APIDOC ## aiChat ### Description Sends a chat completion request to OpenRouter using the server's configured OpenRouter API key. Pass a prompt string or an options object ({ prompt, messages, model, maxTokens, temperature, reasoning, webSearch, webFetch, datetime, imageGen, advisor, subagent, tools, timeoutMs }). Default server tools configured on the Integrations page run automatically unless overridden with shorthand boolean flags (e.g. webSearch: false) or tools: []. Returns { content, text, model, finishReason, usage }. ### Parameters - **promptOrOptions** (string | AiChatOptions) - Required - A prompt string, or an options object specifying messages, model, tools, or limits. - **options** (AiChatOptions) - Optional - Optional options object when the first parameter is a prompt string. ### Returns - **Promise\** - Contains content, text, model, finishReason, usage. ``` -------------------------------- ### hasAi() Source: https://mallard.bot/docs/functions Checks if AI integration is configured. ```APIDOC ## hasAi ### Description Returns true if the guild has an OpenRouter AI integration configured on the Integrations page. ### Returns - **boolean** - true if AI is configured, false otherwise. ``` -------------------------------- ### followUp(content, options?) Source: https://mallard.bot/docs/functions Sends an additional message to the interaction, after the first reply, and returns its ID. ```APIDOC ## followUp(content, options?) ### Description Sends an additional message to the interaction, after the first reply, and returns its ID. Unlike editResponse() it can be ephemeral or public whatever the script's Ephemeral setting: followUp("Only you can see this", { ephemeral: true }). Up to 15 minutes after the interaction. ### Method async function (interaction triggers only) ### Signature followUp(content, options?): Promise ### Parameters - **content** (string | MessageOptions) - Required - Content, or a MessageOptions object. - **options** (MessageOptions, optional) - Optional - Extras when content is a string, e.g. { ephemeral: true, embeds }. ### Returns Promise - The follow-up message's snowflake ID. ``` -------------------------------- ### setChannelTopic(channelId, topic, reason?) Source: https://mallard.bot/docs/functions Sets a channel's topic or description. Requires the ManageChannels permission. ```APIDOC ## setChannelTopic(channelId, topic, reason?) ### Description Sets a channel's topic/description. ### Method Function ### Signature `setChannelTopic(channelId, topic, reason?): Promise` ### Parameters - **channelId** (string) - Required - Discord snowflake ID of the channel. - **topic** (string) - Required - The new topic (empty to clear). - **reason** (string, optional) - Audit log reason. ### Required Permissions ManageChannels ### Returns `Promise` ``` -------------------------------- ### kick(userId, reason) Source: https://mallard.bot/docs/functions Kicks a user from the guild. Returns false if the user had already left. ```APIDOC ## kick(userId, reason) ### Description Kicks a user from the guild. Returns false (rather than failing the script) if they had already left. ### Method async function ### Parameters - **userId** (string) - Required - Discord snowflake ID of the user to kick. - **reason** (string) - Required - Reason for the kick. ### Returns Promise: true if the user was kicked, false if they weren't in the guild. ### Permissions Mallard needs: KickUsers ``` -------------------------------- ### createForumPost(forumId, title, content, options?) Source: https://mallard.bot/docs/functions Creates a post in a forum or media channel and returns its thread ID. The body is a string or a MessageOptions object, so a post can carry embeds, buttons and files; options.tagIds applies forum tags (see getForumTags()). ```APIDOC ## createForumPost(forumId, title, content, options?) ### Description Creates a post in a forum or media channel and returns its thread ID. The body is a string or a MessageOptions object, so a post can carry embeds, buttons and files; options.tagIds applies forum tags (see getForumTags()). ### Method async ### Endpoint createForumPost(forumId, title, content, options?) ### Parameters #### Path Parameters - **forumId** (string) - Required - The forum or media channel. - **title** (string) - Required - The post title. - **content** (string | MessageOptions) - Required - The opening message. - **options** ({ tagIds?: string[], autoArchiveMinutes?: number, slowmode?: number, reason?: string }, optional) - Extras. ### Response #### Success Response - **Promise** - The created thread ID. #### Response Example ```json "thread_id" ``` ``` -------------------------------- ### updateKV(key, fn, ttlSeconds?) Source: https://mallard.bot/docs/functions Atomically read-modify-writes a key using a callback, preventing concurrent update loss. ```APIDOC ## updateKV(key, fn, ttlSeconds?) ### Description Safely read-modify-writes one key: takes the key's lock, calls fn with the current value (parsed from JSON or null), and stores what fn returns (undefined leaves unchanged, null deletes). Returns the stored value. ### Method Function ### Endpoint updateKV(key, fn, ttlSeconds?) ### Parameters - **key** (`string`) - Required - Key to update. - **fn** (`(current: any) => any`) - Required - Computes the new value from the current one. - **ttlSeconds** (`number`, optional) - Time-to-live for the new value (0 or omitted: none). ### Returns `Promise` - The new value (parsed). ``` -------------------------------- ### getBans(limit?) Source: https://mallard.bot/docs/functions Returns the server's ban list, newest first. Requires the BanUsers permission. ```APIDOC ## getBans(limit?) ### Description Returns the server's ban list (userId, username, displayName, reason), newest first. Live REST read. ### Method async function ### Parameters - **limit** (number, optional) - Optional - How many to return (1-1000; defaults to 100). ### Returns Promise: Array of bans, capped at the requested limit. ### Permissions Mallard needs: BanUsers ``` -------------------------------- ### getMessages(channelId, max?, options?) Source: https://mallard.bot/docs/functions Fetches a channel's messages from Discord live over REST. ```APIDOC ## getMessages(channelId, max?, options?) ### Description Fetches a channel's messages from Discord live over REST, newest first (up to 100 per call). With no options it returns the most recent ones; pass { before: messageId } to page further back, { after: messageId } to get newer ones, or { around: messageId } for context around a message. Each message's reactions field is a per-emoji count/me summary. The channel must belong to this guild. ### Method async function ### Signature getMessages(channelId, max?, options?): Promise ### Parameters - **channelId** (string) - Required - Discord snowflake ID of the channel (must be in this guild). - **max** (number, optional) - Optional - Maximum messages to return (1-100; defaults to 100). - **options** ({ before?: string, after?: string, around?: string }, optional) - Optional - Page from a message ID instead of the newest message. ### Permissions Mallard needs: ReadMessageHistory ``` -------------------------------- ### Send a layout message with container, section, separator, and buttons Source: https://mallard.bot/docs/subsystems Use sendMessage with a layout array to create a Discord message with an accent bar, a section with a thumbnail, a separator, and a button row. The layout replaces content/embeds and cannot be combined with them. ```javascript sendMessage(channelId, { layout: [ { type: "container", accentColor: 0x5865F2, children: [ { type: "section", text: ["## Support", "Open a ticket and a moderator will reply."], accessory: { thumbnail: ctx.guild.iconUrl } }, { type: "separator" }, { type: "buttons", buttons: [{ label: "Open ticket", handler: "ticket-open", style: "success" }] } ]} ]}); ``` -------------------------------- ### listAutoModRules() Source: https://mallard.bot/docs/functions Lists the server's AutoMod rules (Discord's own filter, which blocks a message before anyone sees it and costs no runtime). createdByBot marks the ones Mallard's scripts made. Live REST read. ```APIDOC ## listAutoModRules() ### Description Lists the server's AutoMod rules (Discord's own filter, which blocks a message before anyone sees it and costs no runtime). createdByBot marks the ones Mallard's scripts made. Live REST read. ### Requirements Mallard needs: ManageGuild ### Returns - **Promise** - The rules. ``` -------------------------------- ### deleteKV(key) Source: https://mallard.bot/docs/functions Deletes a key from the guild's key-value store. ```APIDOC ## deleteKV(key) ### Description Deletes a key from the guild's key-value store. The reserved system key "env" cannot be deleted. ### Method Function ### Endpoint deleteKV(key) ### Parameters - **key** (`string`) - Required - Key to delete. ### Returns `void` - Nothing. ``` -------------------------------- ### Slash command options JSON Source: https://mallard.bot/docs/commands The JSON object stored on a SlashCommand script that defines its command options. Each option has name, type, description, and required flag. Discord enforces a 32-character name limit, 100-character description limit, and 25 options per command; required options are reordered before optional ones at registration. ```json { "options": [ { "name": "user", "type": "User", "description": "The user to ban", "required": true }, { "name": "reason", "type": "String", "description": "Reason for the ban", "required": true }, { "name": "duration_min", "type": "Integer", "description": "Duration in minutes (0 = permanent)", "required": false }, { "name": "delete_message_days", "type": "Integer", "description": "Days of messages to delete", "required": false } ] } ``` -------------------------------- ### incrKV(key, by?, ttlSeconds?) Source: https://mallard.bot/docs/functions Atomically increments a numeric value in the KV store and returns the new total. ```APIDOC ## incrKV(key, by?, ttlSeconds?) ### Description Atomically adds to a number stored under a key (missing counts as 0) and returns the new total. The safe way to count: XP, message counts, ticket numbers. ### Method Function ### Endpoint incrKV(key, by?, ttlSeconds?) ### Parameters - **key** (`string`) - Required - Key holding the number. - **by** (`number`, optional) - Amount to add (may be negative; defaults to 1). - **ttlSeconds** (`number`, optional) - Time-to-live to (re)apply (0 or omitted: keep none). ### Returns `Promise` - The new total. ``` -------------------------------- ### getEmojis() Source: https://mallard.bot/docs/functions Returns the server's custom emoji (id, name, animated, available, mention, imageUrl). Live REST read. ```APIDOC ## getEmojis() ### Description Returns the server's custom emoji (id, name, animated, available, mention, imageUrl). The mention field is the "<:name:id>" form you paste into message content. Live REST read. ### Method Function ### Signature `getEmojis(): Promise` ### Parameters None ### Returns `Promise` - Array of the server's custom emoji. ``` -------------------------------- ### searchMembers(query, limit?) Source: https://mallard.bot/docs/functions Finds members by username or nickname prefix. ```APIDOC ## searchMembers ### Description Finds members whose username or nickname starts with the query, e.g. for a text command that takes a name. ### Parameters - **query** (string) - Required - The start of a username or nickname. - **limit** (number) - Optional - Maximum to return (1-100; defaults to 25). ### Returns - **Promise\** - Matching members. ``` -------------------------------- ### fetchMember(userId) Source: https://mallard.bot/docs/functions Reads a member live from Discord. ```APIDOC ## fetchMember ### Description Reads a member live from Discord rather than the member cache, with every field (boost, timeout, pending, flags). For a member getMember() doesn't have yet, or when those fields matter. Null when they aren't in the server. ### Parameters - **userId** (string) - Required - Discord snowflake ID of the member. ### Returns - **Promise\** - The member, or null. ``` -------------------------------- ### TriggerConfig for /report command Source: https://mallard.bot/docs/commands TriggerConfig for the seeded /report command: one User option plus a one-field paragraph form. The form's answer is read on submit via ctx.interaction.values["details"]. ```json { "options": [ { "name": "user", "type": "User", "description": "Who are you reporting?", "required": true } ], "title": "Report a user", "inputs": [ { "id": "details", "label": "What happened?", "style": "paragraph", "required": true } ] } ``` -------------------------------- ### listActiveThreads Source: https://mallard.bot/docs/functions Lists the server's active (unarchived) threads and forum posts, optionally filtered by parent channel. ```APIDOC ## listActiveThreads ### Description Lists the server's active (unarchived) threads and forum posts, optionally only those under one channel. For stale-ticket sweeps and forum housekeeping. ### Signature `listActiveThreads(parentId?): Promise` ### Parameters - **parentId** (`string`, optional) - Only threads in this channel or forum. ### Returns `Promise` - The active threads. ``` -------------------------------- ### modifyChannel(channelId, nameOrOptions, topic?, reason?) Source: https://mallard.bot/docs/functions Changes a channel. The short form renames and/or re-topics it: an empty name leaves the name alone, while an empty topic CLEARS the topic (pass null or omit it to leave the topic alone). Pass an options object as the second argument to change anything else: modifyChannel(id, { parentId, position, userLimit, bitrate, nsfw, slowmode, syncPermissions: true }). Works on threads too (name, slowmode, autoArchiveMinutes). ```APIDOC ## modifyChannel(channelId, nameOrOptions, topic?, reason?) ### Description Changes a channel. The short form renames and/or re-topics it: an empty name leaves the name alone, while an empty topic CLEARS the topic (pass null or omit it to leave the topic alone). Pass an options object as the second argument to change anything else: modifyChannel(id, { parentId, position, userLimit, bitrate, nsfw, slowmode, syncPermissions: true }). Works on threads too (name, slowmode, autoArchiveMinutes). ### Parameters - **channelId** (`string`) - Required - Discord snowflake ID of the channel. - **nameOrOptions** (`string | ChannelOptions`) - Required - New name (empty to leave unchanged), or an options object: {name, topic, parentId, position, nsfw, slowmode, userLimit, bitrate, syncPermissions, autoArchiveMinutes}. - **topic** (`string | null`, optional) - New topic (empty to clear, null/omitted to keep). - **reason** (`string`, optional) - Audit log reason. ### Returns `Promise` ``` -------------------------------- ### getChannel(channelId) Source: https://mallard.bot/docs/functions Returns one channel's detail, or null when it doesn't exist. Reads from the bot's channel cache, with a REST read only for channels not fully cached. ```APIDOC ## getChannel(channelId) ### Description Returns one channel's detail (name, type, topic, parent, position, nsfw, slowmode, user limit, bitrate), or null when it doesn't exist. Read from the bot's channel cache, which gateway events keep current; a REST read only for a channel the cache hasn't fully recorded yet. ### Method Function ### Signature `getChannel(channelId): Promise` ### Parameters - **channelId** (string) - Required - Discord snowflake ID of the channel. ### Returns `Promise` - The channel, or null when it no longer exists. ``` -------------------------------- ### bulkBan(userIds, deleteMessageSeconds?, reason?) Source: https://mallard.bot/docs/functions Bans up to 200 users in one call. Requires BanUsers and ManageGuild permissions. ```APIDOC ## bulkBan(userIds, deleteMessageSeconds?, reason?) ### Description Bans up to 200 users in one call, the raid-cleanup primitive: far faster than 200 ban() calls. Returns who was banned and who couldn't be (already banned, or above Mallard in the role list). ### Method async function ### Parameters - **userIds** (string[]) - Required - Up to 200 user IDs. - **deleteMessageSeconds** (number, optional) - Optional - Seconds of their messages to delete (0-604800, i.e. up to 7 days). Defaults to 0. - **reason** (string, optional) - Optional - Audit log reason. ### Returns Promise: {succeeded, failed} user IDs. ### Permissions Mallard needs: BanUsers, ManageGuild ``` -------------------------------- ### timeout(userId, reason, durationMinutes) Source: https://mallard.bot/docs/functions Times out a user in the guild. Returns false if the user had already left. ```APIDOC ## timeout(userId, reason, durationMinutes) ### Description Times out a user in the guild. Returns false (rather than failing the script) if they had already left. The duration is in minutes but may be fractional, so parseDuration("30s") (0.5) works; Discord's maximum is 28 days (40320 minutes), and a longer value throws. 0 ends a timeout, like untimeout(). ### Method async function ### Parameters - **userId** (string) - Required - Discord snowflake ID of the user to time out. - **reason** (string) - Required - Reason for the timeout. - **durationMinutes** (number) - Required - Duration in minutes (fractions allowed, up to 40320). ### Returns Promise: true if the timeout was applied, false if the user wasn't in the guild. ### Permissions Mallard needs: ModerateUsers ``` -------------------------------- ### setBotProfile(options) Source: https://mallard.bot/docs/functions Updates the bot's profile in the server. ```APIDOC ## setBotProfile ### Description Changes how Mallard looks in this server only: nickname, avatar, banner and bio. Seasonal avatars on a cron schedule, or branding per event. Images come from the server's Media page. Pro and Ultra only, at most once every 10 minutes; the audit log names the script. Pass nick: "" to go back to the bot's own name. Requires the ChangeNickname permission. ### Parameters - **options** (object) - Required - Only what you pass changes. nick up to 32 characters, bio up to 190; image IDs from the Media page. - **nick** (string) - Optional - New nickname. - **avatarMediaId** (string) - Optional - Media ID for avatar. - **bannerMediaId** (string) - Optional - Media ID for banner. - **bio** (string) - Optional - New bio. ### Returns - **Promise\<{ nickname: string, avatarUrl: string }>** - The profile as Discord stored it. ```