Donkcord Docs

Introduction

Donkcord is a Discord bot with a web panel. Most things can be done either with a slash command in Discord or from the panel, and a few things (DonkGuard, logging, integrations, the embed builder) only live in the panel.

These docs go through each module: what it does, how to set it up, and the commands that belong to it. If you just want to get going, start with Adding the bot and then Using the panel.

Where things are

The panel sidebar is split into the same groups used here. Moderation covers the day to day stuff (warns, mutes, bans, the audit log). Utility is where welcome messages, tickets, starboard and the other community features sit. Tools has the embed builder, reactions, integrations and the scheduler.

Getting help

If a command replies with a permission error, check Permissions first. Almost every problem people run into comes down to the bot's role sitting too low in the role list, or the bot missing a channel permission.

Adding the bot

You need Manage Server on a server to add Donkcord to it.

Click Add to server at the top of this page, pick the server, and keep the permissions ticked. The invite asks for everything the bot uses: managing messages, roles, channels, webhooks and threads, plus kick, ban and timeout.

If you are already signed in to the panel, the same link is under your avatar menu as Add to a server.

After inviting

  • Open Server Settings, Roles and drag the Donkcord role above every role you want it to manage. It cannot give, remove or punish anyone whose top role is at or above its own.
  • Slash commands show up on their own. If they don't appear within a minute, restart your Discord client.
  • Sign in to the panel with Continue with Discord and pick the server.

Discord permissions still apply on top of the bot's. If a channel denies the bot Send Messages, nothing the bot is told to post there will arrive.

Using the panel

The panel is the website you sign in to with Discord. It shows every server you share with the bot where you have mod permissions.

To sign in you need at least one of Manage Messages, Moderate Members, Ban Members or Administrator in a server the bot is in. Pick a server from the dropdown at the top of the sidebar to switch between them.

Pages

PageWhat it's for
DashboardMember count, recent actions and a quick look at the server.
MembersSearch members, see their history, and warn, mute, kick or ban from one place. Accounts younger than 7 days are flagged.
Audit LogDiscord's audit log and the bot's own records together, including deleted and edited messages.
Muted, Ban ListEveryone currently timed out or banned, with a button to lift it.
InfractionsMembers with active warnings, plus warning expiry and punishments.
CommandsRun the moderation and role commands without opening Discord.

Anything that takes a member has a search box. Type part of a username or nickname and pick from the list, or paste an ID. Discord only matches from the start of a name, so ben finds "benny" but nny won't.

Timezone

Times in placeholders like {time} and {date} use the server's timezone, which defaults to UTC. Change it on the Scheduler page.

Permissions

Two things are checked for every action: whether you are allowed, and whether the bot is able.

For slash commands

Each command lists the Discord permission it needs on its page. Administrator always passes. Server admins can also change who sees a command under Server Settings, Integrations, Donkcord, but the bot still checks the permission itself when the command runs.

For the panel

Anyone with one of Administrator, Ban Members, Kick Members, Moderate Members, Manage Messages or Manage Channels can open a server in the panel and use Command permissions. Some pages need more than that:

NeedsPages and actions
Manage ServerGiveaways, Suggestion settings, DonkGuard, Discord AutoMod, Logging, Mod settings, Welcome, Levels, Raid mode, Verification, Milestones, Economy, Integrations and webhooks, Archive
Manage MessagesPolls, Social alerts, answering suggestions, Embed builder, Starboard settings, Site embeds, posting from the channel monitor, Superpurge, purge
Manage RolesReaction roles, verifying someone by hand, giving, removing and editing roles
Ban MembersBan, unban
Moderate MembersWarn, mute, unmute
Manage ChannelsSlowmode, lock, unlock
Any mod permissionCustom Commands / Reactions, Scheduler, Tickets, Submissions, Members, Audit Log, the suggestion list

Voicemail boxes need Administrator, Manage Server or Manage Channels. Removing the bot from a server is limited to the server owner and Administrators, and you have to type the server name to confirm.

Role hierarchy

You can only give or take roles that sit below your own highest role, and the bot can only touch roles below its own. The role autocomplete in commands only lists roles that pass both checks.

Moderation commands

The basic set. Every action is recorded as an infraction and shows up on the member's history.

CommandDescriptionUsageExample
/muteTimes a member out. Needs Moderate Members./mute user duration [reason]/mute @Sam 30 spamming
/unmuteRemoves a timeout. Needs Moderate Members./unmute user/unmute @Sam
/kickKicks a member. Needs Kick Members./kick user [reason]/kick @Sam alt account
/banBans a member, or anyone by user ID even if they've left. Can delete up to 7 days of their messages. Needs Ban Members./ban user [delete_days] [reason]/ban @Sam 1 scam links
/unbanUnbans by user ID. Needs Ban Members./unban user_id [reason]/unban 123456789012345678
/purgeDeletes up to 100 recent messages. With a user, only their messages among the last 100. Needs Manage Messages./purge amount [user]/purge 50 @Sam
/slowmodeSets slowmode in the current channel, up to 6 hours. 0 turns it off. Needs Manage Channels./slowmode seconds/slowmode 10
/lockStops @everyone from sending in the current channel. Needs Manage Channels./lock [reason]/lock raid
/unlockUndoes /lock. Needs Manage Channels./unlock/unlock
/announcePosts an embed to a channel. Needs Manage Messages./announce channel title message [color]/announce #news Update Server is back #5865f2
/infractionsShows a member's last 10 infractions. Needs Moderate Members./infractions user/infractions @Sam

/mute takes minutes, up to 40320 (28 days, Discord's limit). To ban someone who isn't in the server, paste their user ID into the user option. The panel's ban takes an ID the same way. They won't get a DM, since the bot can't message people it doesn't share a server with.

From the panel

The Commands page and the Members page run the same actions. Actions taken there use the DM and mod log settings from Mod log.

Warnings and punishments

Warnings add up. You can set what happens when a member reaches a certain number.

CommandDescriptionUsageExample
/warnWarns a member and DMs them. Weight lets one warning count as several. Needs Moderate Members./warn user [reason] [weight]/warn @Sam slurs 3
/warnlogLists a member's warnings with their index numbers. Needs Moderate Members./warnlog user/warnlog @Sam
/warnlogallEveryone with warnings, 15 per page. Needs Moderate Members./warnlogall [page]/warnlogall 2
/warnclearClears all of a member's warnings, or one by index. Needs Ban Members./warnclear user [index]/warnclear @Sam 2
/warndeleteDeletes one warning for good. Cleared warnings stay in the history, deleted ones don't. Needs Ban Members./warndelete user index/warndelete @Sam 1
/warnexpireHow many days until warnings expire. 0 means never. Run it with no options to see the current value. Needs Manage Server./warnexpire [days] [delete]/warnexpire 30
/warnpunish setWhat happens at a warning count. Needs Ban Members./warnpunish set count punishment [time] [role]/warnpunish set 3 Mute 2h
/warnpunish removeRemoves the punishment at a count./warnpunish remove count/warnpunish remove 3
/warnpunish listShows every punishment you've set./warnpunish list/warnpunish list

Punishments

PunishmentWhat it does
BanBans. With a time, they're unbanned when it runs out.
SoftbanBans and unbans straight away, which clears 7 days of their messages.
KickKicks.
MuteTimeout. 1 hour if you don't give a time, 28 days at most.
VoiceMuteServer mutes them in voice. Only works if they're in a voice channel at the time.
AddRoleGives a role. Needs the role option. With a time, the role comes off again.
RemoveRolesTakes away every role the bot is able to remove.

Times are written like 30m, 2h, 7d or combined, 2d12h.

Role commands

Give, take and edit roles. All of these need Manage Roles, and the role has to be below both yours and the bot's.

Every role option autocompletes. You can also type the role's name, paste an ID, or @mention it.

CommandDescriptionUsageExample
/setroleGives a member a role./setrole user role [reason]/setrole @Sam Verified
/removeroleTakes a role from a member./removerole user role [reason]/removerole @Sam Verified
/removeallrolesTakes every role below yours from a member./removeallroles user [reason]/removeallroles @Sam
/temproleGives a role that comes off by itself. Up to 365 days./temprole duration user role [reason]/temprole 7d @Sam Event
/createroleMakes a new role./createrole name [color] [hoist] [mentionable]/createrole Helpers ffba55
/deleteroleDeletes a role./deleterole role [reason]/deleterole Old Event
/renameroleRenames a role./renamerole role name/renamerole Helpers Support
/rolecolorShows or sets a role's colour. none clears it./rolecolor role [color]/rolecolor Support 3ba55c
/rolehoistToggles whether the role shows separately in the member list./rolehoist role [value]/rolehoist Support
/rolementionableToggles whether anyone can @mention the role./rolementionable role [value]/rolementionable Support false
/roleinfoID, colour, member count, position and key permissions./roleinfo role/roleinfo Support

Mod log

Found under Moderation in the panel. Controls where panel actions get posted and what the member is told.

Manage Server

  • Mod log channel gets an embed for each action you pick: warn, mute, unmute, timeout, untimeout, hardmute, kick, ban, tempban, softban and unban.
  • DM can be set per action. None sends nothing, Action tells them what happened, Full adds the reason and who did it. Warns, mutes and timeouts default to Full, everything else to None.
  • Mute role is used for hardmutes, where a role is given instead of a Discord timeout.
  • Defaults are the prefilled durations: timeout 60 minutes, and how many days of messages a ban or tempban deletes.

These settings apply to actions taken in the panel. Slash commands don't use them.

Superpurge

Deletes every message one person sent, across the whole server or in one channel.

Manage Messages

It's on the Commands page. Search for the member or paste their ID, pick a channel or leave it on the whole server, and optionally set a date range.

  • Threads are included by default. Archived threads are opened, cleaned and archived again.
  • Discord only bulk deletes messages under 14 days old. Anything older goes one at a time, so a big cleanup can take a while. It keeps running on the bot if you leave the page.
  • One superpurge per server at a time. Cancel stops it where it is.

DonkGuard

The bot's own automod. It reads every message and acts when one breaks a rule you turned on.

Manage Server

Each module has its own switch, its own actions and its own DM text. When a message trips more than one, only the first one in this list counts.

ModuleCatchesSettings
Bad wordsWords from your list. Accents and punctuation are stripped first, so b.a.d still matches.Word list, whole word only
Bad linksLinks to blocked domains, or anything off your allow list. Subdomains count.Blacklist or whitelist, domains, links per time window
InvitesDiscord invites, including discord.gg, dsc.gg, invite.gg, discord.me and disboard join links.Allowed codes, allow this server's own invite
MentionsToo many users or roles pinged in one message, or across several.Per message, per time window
AttachmentsToo many files in a short time.Files per window
CapsMostly capital letters.Percent (default 70), minimum length (default 10)
SpamToo many messages too fast, or the same message over and over.Messages per window, block duplicates, duplicate limit
EmojiToo many emoji in one message.Limit (default 10)
NewlinesWalls of blank lines.Limit (default 15)
HoneypotAnything posted in the channels you pick. Make a channel nobody should talk in and let bots walk into it.Channels

Actions

Pick any mix. They always run in this order: delete, DM, warn, timeout, mute, kick, softban, ban.

  • Timeout, mute and ban use the module's duration. Mute gives the mute role from General, and with a duration it's removed later. Ban with a duration unbans later.
  • Warn adds a normal warning with the reason "DonkGuard: ...", so your warning punishments still apply.
  • DM sends the module's DM text. It takes the same placeholders as custom reactions.

General

  • Log channel gets an embed for every hit.
  • Immune roles and ignored channels are skipped. Ignoring a category covers the channels inside it.
  • Media channels only allow posts with an attachment or a link. Plain text gets deleted.
  • Delete risky files removes executables and scripts (exe, bat, scr, msi, jar, apk, ps1 and so on). You can add your own extensions.

Administrators and anyone with Manage Server are never touched by DonkGuard. Test it from an account without those.

Discord AutoMod

A panel for Discord's built-in AutoMod rules, the same ones under Server Settings, Safety Setup.

Manage Server

These run on Discord's side, so they block a message before anyone sees it. DonkGuard can only delete after it's posted. Use this for hard blocks and DonkGuard for anything that needs counting over time or a punishment.

Rule typeNotes
Keyword filterWords, wildcards and regex. Discord allows several of these.
Keyword presetDiscord's lists: profanity, sexual content, slurs.
Mention spamBlocks messages over a mention count.
Spam, Harmful link, Member profileDiscord's own detection, nothing to configure beyond on or off and the actions.

Actions are block the message, send an alert to a channel, and time the member out. Each rule can exempt roles and channels.

Logging

Posts server events to channels you pick. Everything starts off, so turn on what you want.

Manage Server

There's a default channel plus optional channels for messages, members, server, voice and joins/leaves. An event goes to its own channel if you set one, otherwise the default.

ChannelEvents
MessagesDeleted, edited and purged messages
Joins and leavesMembers joining and leaving. A leave that was really a kick or ban says so.
MembersRole changes, name changes, avatar changes, bans, unbans, timeouts and timeouts removed
ServerChannels, threads and roles being created, changed or deleted, server setting changes, emoji changes
VoiceJoining, moving between and leaving voice channels

Log entries have buttons to copy the user ID and jump to the message. Where Discord's audit log knows who did something, the moderator is shown too. You can ignore channels (or whole categories) and roles.

Raid mode

When a burst of accounts joins at once, lock the doors, deal with the joins, and open up again later.

Manage Server

CommandDescriptionUsage
/raid onTurns raid mode on now./raid on
/raid offLifts it./raid off
/raid statusWhether it is on, how many joined and how many were dealt with./raid status

Detection

Set how many joins inside how many seconds should trip it. Ten joins in sixty seconds is the default. Detection can be off while you still switch raid mode on by hand, from the panel, or from any script with {run:raid on}.

While it is on

Every account that joins is kicked, banned, given a quarantine role, or let through. You can limit that to accounts younger than a number of days so regulars rejoining are left alone. Kicked and banned accounts get a DM first if you write one.

Channels can be locked for everyone. Tick the ones that matter or leave the list empty to lock every text channel. The bot remembers what each channel looked like and puts it back when raid mode lifts. Channels that were already locked are not touched.

Lifting

Raid mode lifts itself after the number of minutes you set, or waits for /raid off, the panel button, or {run:raid off}.

Announcements and scripts

A message goes to the notify channel when it starts and when it lifts, with a role ping if you pick one. Both messages and the two scripts take placeholders: {count}, {window}, {threshold}, {actionword}, {joins}, {actioned}, {trigger}, {by}, {duration} and {server.*}. The scripts use the same directives as button scripts, so raid mode can set slowmode, post to staff, or anything else you can write.

{run:slowmode #general 30}
{post:#staff} Raid mode tripped at {count} joins in {window} seconds.

Every start and lift is written to the audit log, and the history list on the page keeps the last events.

Command permissions

Turn off a whole module or one slash command in certain channels or for certain roles, set the prefix, and choose which commands also answer to it.

Any moderator

How it works

Pick a module from the first dropdown. With the second left on Whole module, the channel and role lists you tick apply to every command in that module. Pick a command instead and the lists apply to that one command only, on top of whatever the module already blocks. Tick a channel to block there, tick a role to block for anyone holding it. Save writes it, Clear removes every block for that pick.

Nobody bypasses a block, admins included. A blocked member who runs the command gets a reply only they can see saying it is turned off. Blocking a channel also blocks its threads. Commands in a blocked module still show in Discord's command picker, since that list comes from Discord.

Custom commands and integrations are not on this page. Each of those has its own allowed and ignored channels and roles in its editor.

Prefix

The prefix at the top of the page is what prefix commands and command integrations start with. It is ! by default, 1 to 5 characters, no spaces.

Prefix commands

Every built in command is a slash command. Prefix versions like !rank or !betflip 50 are off until you turn them on, per module with the checkbox or per command with the Prefix command dropdown, which can also turn one command off inside a module that is on. Custom commands and integrations always use the prefix and are not affected by this switch; if one of them has the same name as a built in command, it wins.

A prefix command checks exactly what the slash command checks: the permission it needs, the blocks on this page and whether the module is enabled. !kick needs Kick Members no matter who types it. Arguments go in the order the slash command lists them, so !mute @Mira 10 spamming is user, duration, reason. Choices accept a short form when it is clear, !betflip 10 h. The last text argument takes the rest of the line. You can also name them, !mute user:Mira duration:10 reason:"being loud". Subcommands come first, !birthday set 14 march. Members, channels and roles can be mentions, ids or names. Missing or wrong arguments get a usage line back.

Replies to prefix commands are normal messages in the channel. There is no private reply outside slash commands, so anything the slash version would show only to you is visible to everyone. Parts that need a form, like typing a verification code from a button, still need the slash command.

In effect

The list at the bottom shows every module and command with a block or a prefix setting. Click one to open it.

Verification

New members prove they are a person before they get the role that unlocks the server.

Manage Server

CommandDescriptionUsage
/verifyVerify yourself, with the command method or with a code./verify [code]
/verify userVerify someone else. Needs Manage Roles./verify user:@member

How it works

Pick the role verified members get. Set your channels so that role is what lets people see and talk. Optionally pick an unverified role that new members hold until they verify; it is taken away when they do.

Choose one of three methods. Button: the bot posts a message in the verification channel with a Verify button. Command: members run /verify. Code: the bot DMs each new member a six character code, and they press the Verify button and type it into the form that opens, or run /verify code:ABC123. Five wrong codes lock them out until a moderator steps in. Every reply is only visible to the member.

Extra checks

A minimum account age refuses accounts newer than the number of days you set and tells them when they can try again. Remove unverified after a number of minutes kicks anyone who joined while the gate was on and never verified, with a DM first if you write one. Both are off by default.

Moderators

Anyone with Manage Roles can verify someone else with /verify user:@member, from the Unverified members list on the page, or from a script with {run:verify @user}.

Messages and scripts

The verification message, the join DM, every reply and the script after verifying take placeholders. {code} is the member's code in the DM, {eligible} the unix time their account becomes old enough, {tries_left} how many code attempts remain, {via} how they verified and {waited} the minutes between joining and verifying.

{post:#general} Welcome {clicker.mention}, you are in.
{run:setrole {clicker.id} Newcomer}

Welcome and join roles

Greet new members, DM them, and hand out roles when they join.

Manage Server

Join roles

Up to 10 roles for people and a separate list of up to 10 for bots. A role gets skipped if it's above the bot's own role, managed by an integration, or deleted.

Welcome message

Pick a channel and write the message. It can be plain text or an embed with a title, colour and the member's avatar as the thumbnail. You can have it deleted after a number of seconds, and choose whether the new member gets pinged.

Welcome {user} to {server}. You are member number {server.membercount}.

Welcome DM

Sent privately. Members with DMs closed just don't get it.

Thanks for joining {server}. Read the rules in {#rules} and say hello.

Both take every placeholder and condition. {user} is the new member. Send a test posts the welcome message to the channel with you as the new member.

Bots are skipped for messages by default, but still get the bot roles.

Reaction roles

One message with a button or reaction per role. Members pick a role to take it and pick it again to drop it.

Manage Roles

CommandDescriptionUsage
/rolepanel sendPosts a panel, here or in another channel./rolepanel send name [channel]
/rolepanel refreshRe-renders a posted panel and fixes its buttons or reactions./rolepanel refresh name
/rolepanel removeDeletes the posted message but keeps the panel./rolepanel remove name
/rolepanel listEvery panel and where it is posted./rolepanel list

Buttons or reactions

Each panel uses one or the other. Buttons put a button per role under the message, labelled with the role name or your label, with an optional emoji and a colour of your choice. Pressing one gives or takes the role and the reply is only visible to the member. Reactions add an emoji per role. Reacting gives the role and removing the reaction takes it off, so a member's reactions always match what they hold. With reactions the bot needs Add Reactions, and Manage Messages so it can undo reactions it refused.

Building a panel

A panel is one message. Give it a name, add rows, and pick a role for each. The emoji is optional with buttons; with reactions a blank one gets a number. Paste the emoji itself, or a server emoji as <:name:id>. Labels and descriptions are optional and show in the generated list. Up to 20 roles per panel, 25 panels per server.

The message is text, an embed, or both, and the role list is added for you. Put {rolelist} anywhere in the text or embed to place it yourself, and edit the line format to change how each row reads. Preview shows the rendered result before you post.

Modes

ModeWhat it does
TogglePick to take the role, pick again to drop it. Set a cap so members can hold at most so many roles from the panel.
One at a timeOne role from the panel at a time. Picking another swaps it.
Add onlyPick to take the role. It cannot be dropped from this message.
Remove onlyPick to drop the role. Nothing is ever given.

Panels can require one of a set of roles, refuse members holding any of another set, and have a per member cooldown on buttons. Every reply a member sees is a template you can edit or blank, or turn the whole panel silent.

Posting

Post from the page or with /rolepanel send. Saving a panel that is already posted updates the message in place, including switching between buttons and reactions. Scripts and the scheduler can post one with {run:rolepanel Name #channel}.

Scripts

Each row can run a script when its role is given and another when it is taken away, and the panel can run one after any change. They take the same directives as button scripts, with {clicker.*} for the member, {role.*} for the role, {action} (added, removed or swapped), {item.label}, {item.index}, {panel.name} and {held} for how many roles from the panel they now hold.

{if:action == added}
{post:#role-log} {clicker.tag} took {role.name}
{endif}

Panels export and import as JSON from the page. Roles are matched by ID, so a panel from another server needs its roles picked again.

Starboard

When a message gets enough of a reaction, it's reposted to a starboard channel.

Manage Messages

SettingDefaultNotes
Emoji⭐Any emoji, including this server's custom ones.
Threshold3Reactions needed to post.
Self starOffWhether the author's own reaction counts.
Remove below thresholdOnTakes the post down if reactions drop again.
Ignore NSFWOnMessages from NSFW channels never get posted.
Allow botsOffWhether bot messages can be starred.

You can also ignore channels, pick the embed colour, and choose whether attachments show.

Levels

Members earn XP for chatting and time in voice, level up, and get roles at the levels you pick.

CommandDescriptionUsageExample
/rankShows a rank card with level, XP, rank, messages, voice time and join date./rank [user]/rank user:@Mira
/leaderboardThe top ten, with a button to the full leaderboard page. With prefix commands on for Levels, !lb is a shortcut./leaderboard/leaderboard
/levelnotifyChoose whether you hear about your own level ups in the server, by DM, or not at all./levelnotify mode/levelnotify dm
/give-xpAdds XP to a member. Needs Manage Server./give-xp user amount/give-xp @Mira 500
/remove-xpTakes XP away. They can drop a level and lose reward roles. Needs Manage Server./remove-xp user amount/remove-xp @Mira 200

Levels are off until you turn them on from the Levels page in the panel.

How XP is earned

  • Each message earns a random amount between 15 and 25 XP. Both numbers can be changed.
  • XP is given at most once a minute per member, so sending ten short messages earns the same as one. The wait can be changed too.
  • Bots, webhooks and bot commands earn nothing. Add other bots' prefixes on the Levels page so their commands don't count either.
  • Channels, categories and roles can be set to earn no XP at all.

Messages sent during the wait still count toward the message total on the rank card. They just don't earn XP.

Levels

Going from level L to the next takes 5 x L² + 50 x L + 100 XP, the same curve MEE6 uses. Level 1 takes 100 XP, level 10 takes about 4,700 in total, and level 50 about 268,000.

Multipliers

The server multiplier applies to everyone. Role multipliers apply to members with that role, and if someone has several, the highest wins. Pick the Server Booster role here for a booster bonus. Channel multipliers apply to a channel or a whole category. All three are multiplied together, so a 2x booster in a 1.5x channel gets 3x.

Voice

Turn on voice XP to give a set amount per minute in a voice channel. It only counts when you aren't muted or deafened, aren't in the AFK channel, and at least two people are in the call. The number of people needed can be raised. While voice XP is on, voice time shows on rank cards and the leaderboard, counting only minutes that earned XP. With it off, voice time is hidden.

Level up messages

By default the bot replies in the channel where someone levelled up. It can post to one channel instead, DM the member, or say nothing. The message takes {user}, {user.name}, {user.nick}, {level}, {xp}, {rank}, {next} (XP left to the next level), {reward} (roles earned at this level) and {server}.

GG {user}, you reached level {level}. {reward}

XP changed by staff never sends a level up message.

Role rewards

Add a level and a role, and members get the role when they reach it. With Keep earlier rewards on, members keep every role they've earned. With it off, they only hold the highest one and the ones below are taken away. If a member loses XP and drops below a reward level, the role is removed. The bot's role has to sit above the reward roles.

Leaderboard page

Each server gets a public page at /levels/ followed by the server ID, which the Full leaderboard button links to. It has all time, last 30 days and last 7 days tabs, 50 members a page, and the list of role rewards. Turn off Public web leaderboard to hide the page and the button.

Other settings

  • Rank card color sets the accent on the card and the leaderboard page. The panel shows a preview with your own card.
  • Wipe XP when they leave deletes a member's XP as soon as they leave. It's off by default, so people who come back keep their level.
  • The Levels page lists every ranked member. You can give, take or set XP for anyone, reset one member, or reset the whole server.

{user.level}, {user.xp} and {user.rank} work in custom reactions and anywhere else placeholders do, and so do the {target.*} versions.

Economy

A currency per server with a daily reward, two games, a shop, and balances any script can read and move.

Manage Server

Setting it up

Name the currency (one and many, like donk and donks), add a symbol if you want one in front of amounts, and set what everyone starts with. Earning by chatting is off until you turn it on: a random amount between two numbers, at most once per cooldown, skipping ! commands and any channels you tick. A level up bonus pays when Levels raises someone. Turning the economy off freezes everything, including scripts.

Commands

CommandWhat it does
/balance [user]Balance and rank.
/dailyClaims the daily amount. Claiming again within two cooldowns keeps a streak, and each streak day adds the bonus until the cap.
/pay user amountMoves currency to someone. Amounts accept 2k, 1.5m, all and half.
/richestThe leaderboard.
/betflip amount [call]Win double or lose the bet, between the min and max you set. The result shows the coin face. !bf is a prefix shortcut.
/coinflipFlips a coin, no bet. Works even with the economy off.
/slots amountThree reels. Two alike, three alike and three sevens each pay the multiplier you set.
/shop, /buy itemSee and buy shop items. The item name autocompletes, and a partial name works.
/award user amount [reason], /take user amountManage Server. Give or remove currency; take stops at zero.

Shop

An item has a name, price, optional stock, and what it does: a role to give, a script to run, or both. Scripts use the same directives as button scripts with {clicker.*} for the buyer and {item.name} and {item.price} for the item. Items export and import as JSON.

In scripts

{user.coins} works anywhere placeholders do, $1.user.coins for a mentioned member, and {clicker.coins} in button and shop scripts. {if:clicker.coins >= 100} is a normal condition. Four run commands move currency: {run:award @user 50} and {run:take @user 50} need a role set on the button, like warn and kick; {run:charge @user 50} and {run:pay @from @to 50} are always allowed and stop the script with a message when the sender cannot afford it. Every change is logged on the page with who and why.

{if:clicker.coins < 50}{reply:That costs 50 and you have {clicker.coins}.}{stop}{endif}
{run:charge {clicker.id} 50}
{run:setrole {clicker.id} VIP}
{reply:VIP for you.}

Milestones

Birthdays, join anniversaries, member count milestones and community events, posted to one channel.

Manage Server

CommandDescriptionUsage
/birthday setSave your birthday./birthday set 14 march
/birthday showYour birthday, or someone else's./birthday show [user]
/birthday nextWho is up next./birthday next
/birthday removeForget yours./birthday remove
/eventsWhat is coming up, with each event's ID./events
/event addAdd an event. Needs Manage Server./event add name when [description]
/event removeRemove one by ID. Needs Manage Server./event remove id

Setting it up

Pick the channel and the hour of the day for daily posts. The hour follows the server timezone from the Scheduler page. Each of the four parts has its own switch and its own message, and every message takes placeholders and conditions.

Birthdays

Members save their own with /birthday set and a date like 14 march, march 14 1995, 14/03 or 2001-03-14. Numeric dates are day first. Adding a year lets {age} fill in. Moderators can add and remove birthdays on the page, and can turn off members saving their own.

The post can be plain or an embed, can ping the member, and can hand out a role for the day that is taken back at the next daily run. Birthdays on 29 February are celebrated on the 28th in other years.

Happy birthday {user.mention}!{if:{age}} {age} today.{endif} Everyone say something nice.

Join anniversaries

Every member whose join date is today and who has been here a whole number of years gets a post, or only the years you list. {years} and {joined} are available, and {ord:{years}} gives 1st, 2nd, 3rd.

Member count

Post every N members, at specific numbers, or both. Each number is announced once even if people leave and it is crossed again. {milestone} is the number reached and {user.mention} the member who tipped it.

Events

Add an event on the page with a date and time, a description, an optional channel of its own, reminders a number of hours before, and a repeat of weekly, monthly or yearly. In Discord, /event add takes a time like 3d, 2h or 2026-12-24T18:00 in the server timezone. Reminders use the default hours unless the event has its own; when an event is added inside a reminder window only the nearest reminder goes out. The start message posts when the time arrives, then the event is marked done or rolled forward by its repeat.

**{event.name}** starts {event.in} ({event.when}). {event.description}

Giveaways

Post a prize, members press Enter, and winners are drawn when the time runs out.

Manage Server

CommandDescriptionUsageExample
/giveaway startStarts one. Winners defaults to 1, the channel to where you ran it./giveaway start prize duration [winners] [channel] [role] [description]/giveaway start Nitro 2d 2
/giveaway endEnds it now and draws the winners./giveaway end id/giveaway end 4
/giveaway rerollDraws new winners for one that has ended. Earlier winners are left out./giveaway reroll id [count]/giveaway reroll 4
/giveaway listShows the ones still running./giveaway list/giveaway list

The id is in the footer of the giveaway message. A giveaway can run from 30 seconds to 60 days and have up to 20 winners.

Entering

Pressing Enter puts you in. Pressing it again takes you out. The button shows how many people are in. If you set a role, only members with that role can enter.

Drawing

When time is up, winners are picked at random from the entries. Anyone who has left the server or lost the role since entering is skipped. The message is updated with the winners and the bot replies under it with a ping for each one.

The Giveaways page in the panel does the same things: start one, end it early, reroll, or delete it along with its message.

Polls

A question with a button for each option and a live tally on the message.

Manage Messages

CommandDescriptionUsageExample
/poll createPosts a poll. Split the options with |./poll create question options [duration] [multiple] [hide_results] [channel]/poll create Lunch? Pizza | Tacos | Sushi 1d
/poll closeStops voting and shows the results./poll close id/poll close 7

Polls take 2 to 10 options. Leave the duration empty to close it yourself, or set anything from 1 minute to 30 days.

  • Voting: press an option. Press it again to take the vote back. Picking a different option moves your vote, unless the poll allows more than one.
  • Hide results: the tally stays hidden until the poll closes, so early votes don't sway anyone.
  • Each voter gets a private note saying what they voted for.

The Polls page shows every poll with its results as bars. You can post, close and delete polls from there too.

Reminders

Ask the bot to remind you about something later.

CommandDescriptionUsageExample
/remind meSets a reminder. Repeat makes it come back every so often./remind me in text [repeat]/remind me 2h check the oven
/remind listYour reminders and when they are due./remind list/remind list
/remind cancelDeletes one of yours./remind cancel id/remind cancel 12

Times look like 30m, 2h, 1d12h or 1w, from 30 seconds up to a year. Repeats have to be at least 10 minutes apart. You can have 25 at once.

The reminder comes by DM. If your DMs are closed, the bot pings you in the channel where you set it instead. Only you can see or cancel your reminders.

Suggestions

Members post ideas, everyone votes, and staff give an answer that shows on the message.

Setting it up

Open the Suggestions page, pick a channel and turn it on. This part needs Manage Server.

SettingWhat it does
Suggestions channelWhere new suggestions go.
Move answered ones toOptional. Approved, denied and implemented suggestions are reposted here without buttons, and the original is deleted.
Hide who posted itThe message doesn't show the author. Staff can still see it in the panel.
DM the authorTells them when their suggestion gets an answer, with the reason.
Open a threadStarts a thread on each suggestion for discussion.
Wait between suggestionsHow long a member has to wait before posting another. 60 seconds by default.

Commands

CommandDescriptionUsageExample
/suggestPosts a suggestion. Anyone can use it./suggest text/suggest Add a music channel
/suggestion approveNeeds Manage Messages. Same for the three below./suggestion approve number [reason]/suggestion approve 3 Coming this week
/suggestion denyVoting closes./suggestion deny number [reason]/suggestion deny 5 We have one already
/suggestion considerMarks it as being looked at. Voting stays open./suggestion consider number [reason]/suggestion consider 4
/suggestion implementMarks it as done./suggestion implement number [reason]/suggestion implement 3

Suggestions are numbered per server. Votes are Upvote and Downvote buttons with the counts on them; press the same one again to take your vote back. From the panel you can filter by status, answer, reopen or delete any suggestion.

Tickets

A button in a channel that opens a private thread between the member and your staff.

Setting up a panel

  • Panel channel is where the button goes.
  • Ticket channel is where the private threads get made. The bot needs Create Private Threads there.
  • Staff roles are the only ones, besides admins, who can resolve or close a ticket. Only the member who opened it is added to the thread, so give staff Manage Threads in the ticket channel or they won't see new tickets.
  • Log channel gets a record when a ticket is closed, and notify channel gets pinged when one opens.
  • Max open is how many tickets one member can have at once. Default 1.

The panel message can be plain text or a full embed. When someone presses the button they get a short form: subject, details, and an optional sub-category. You can rename these fields, change their hints, or turn them off.

Closing

Inside the ticket there's a Resolve and a Close button. Either one asks for a reason, posts the result, sends it to the log channel and deletes the thread a few seconds later.

Transcripts

Set Transcript on the panel and the whole ticket is saved as a file and attached to the close message in the log channel. Each panel picks its own format.

FormatWhat you get
Text (.txt)One line per message with the time and name. Opens anywhere.
JSON (.json)Every message with IDs, embeds and attachments, for scripts or your own tools.
Web page (.html)Looks like the Discord channel: avatars, formatting, embeds, images and reply links. Open it in a browser.

Transcripts need a log channel, and the bot needs Attach Files there. Images in a transcript point at Discord's copies, which stop loading after a while, so save anything you need to keep. Very long tickets are trimmed to fit Discord's upload limit, and the file says when that happened.

Submissions

A form members fill in from a button. Each entry is posted to a channel.

Build the form with up to five fields, short or paragraph, required or not. One field must be the link field (this is meant for things like clip or art submissions), and you can mark another as the message.

Entries post as "Submission from name" with the message and link, and a button to submit again.

Reading entries from your own site

Create an API token on the panel. Tokens are shown once, so copy it then. Then:

GET /api/ext/submissions?token=dk_yourtoken

You get back a list with the submitter's name, message, link, whether it's been viewed, and when it came in. A token only sees entries from the last so many days (you choose, up to 365) and can have an expiry date.

Voicemail

A channel that only takes voice messages, with limits on how often people can post, and an optional public page to listen back.

Manage Channels

Point a box at a channel. Anything that isn't a single recorded voice message (text, files, stickers, polls) is removed, and the member can be told why.

Limits

  • Off: post as often as you like.
  • Cooldown: one message per member every so often. A week by default.
  • Deadline: a set number of messages per window, and the window resets daily, weekly, every two weeks or monthly.

You can also set a minimum and maximum length, and who can post, who can only listen, and who skips the rules. Turn on manage permissions and the bot sets the channel overwrites for you.

Feed

The feed is a page at /v/your-name that plays the messages in order. Pick a title, colour and page size, and whether names and downloads are shown. From the panel, staff can star, hide or archive messages and leave notes.

Cooldown messages can use {user} and {when}, and the confirmation can use {user} and {duration}.

Custom Commands / Reactions

The bot replies when someone says a trigger word. Replies can be text or embeds, can take arguments, and can have buttons.

Reactions don't use a prefix. If you want !rules, make the trigger !rules.

Commands

CommandDescriptionUsageExample
/customreaction addAdds a reaction. Setting a title or colour makes it an embed. Needs Manage Messages./customreaction add trigger response [match] [embed_title] [embed_color]/customreaction add !rules Read #rules before posting.
/customreaction editChanges the response./customreaction edit trigger response/customreaction edit !rules See #rules.
/customreaction removeDeletes a reaction./customreaction remove trigger/customreaction remove !rules
/customreaction listLists the first 25./customreaction list/customreaction list

The panel has everything else: full embeds, buttons, role and channel limits, cooldowns and so on.

Matching

MatchFires when
Whole wordThe trigger appears as its own word. Default.
ContainsThe trigger appears anywhere, even inside another word.
Starts withThe message starts with the trigger. Use this for commands that take arguments.
ExactThe whole message is the trigger and nothing else.

Matching ignores case. Only one reaction fires per message.

Arguments

Words after the trigger are arguments. $1 is the first, $2+ is everything from the second on, and $* is all of it. If an argument is a member (a mention or an ID), you can read their details with $1.user.name, $1.user.joinedat and so on. The full list is on Placeholders.

Set Required args and the reaction won't fire until that many are given.

Trigger:  !hug
Match:    Starts with
Response: {user} hugs $1.user.mention{if:$2} because $2+{endif}

Options

  • Allowed and ignored roles and channels decide where it works and for who. Allowing a category covers its channels.
  • Cooldown is per member, up to 10 minutes.
  • Delete trigger removes the message that set it off. Delete after removes the reply after some seconds.
  • DM response sends the reply privately. Response channel sends it somewhere else.
  • Allow @everyone lets {everyone} and {here} actually ping. It needs Manage Server to turn on.

Modifiers

You can put these anywhere in the response. They change how it behaves and are removed from what gets posted.

ModifierEffect
{require:role}Only members with that role. Use a name, an ID or a role mention. Add several and any one is enough.
{require:#channel}Only in that channel.
{require:mod}Only members with Manage Messages or Moderate Members. {require:serveradmin} means Administrator.
{not:role} {not:#channel}Never for that role, or in that channel.
{respond:#channel}Reply in a different channel.
{dm}DM the reply to the person who triggered it. {dm:@someone} DMs someone else.
{delete}Delete the trigger message.
{silent}Send nothing. Useful with {delete} to quietly remove a word.
{react:emoji}Reacts to the message that triggered it. Up to 5, separated by spaces. Use the emoji itself, or a custom one from this server as <:name:id>.
{noeveryone}Never ping @everyone or @here, even if it's allowed.

Examples

New servers get five example reactions: !banr, !roles, !whois, !serverinfo and !8ball. They're off until you turn them on, and you can edit or delete them like any other. !banr is a good one to read through: a mod files a ban request and the card has Approve and Deny buttons.

Each reaction has Duplicate and Export buttons. See Import and export.

Embed builder

Write a message with up to 10 embeds and 5 buttons, see it as it'll look, and post it.

Manage Messages

Each embed has an author, title, link, description, colour, thumbnail, image, fields (up to 25), footer and timestamp. There's a message body above the embeds too.

Posted messages are saved. Open one later and you can edit it in place, copy it to another channel, or delete it. Deleting in the panel asks whether to remove the Discord message too.

Placeholders

Server, time, random and mention placeholders work, and so do conditions. Since nobody triggers an embed, {user} is you, the person posting it, and {channel} is where it's going.

Messages can be exported to a file, imported back, or duplicated.

Buttons

Buttons can go on custom reactions, integration replies and messages from the embed builder. Up to 5 per message.

Kinds

  • Link buttons open a URL. Nothing else to set up.
  • Script buttons run a short script when pressed. The script uses the script directives.

Each button has a label, a colour (grey, blue, green or red), a per-member cooldown, and a list of roles allowed to press it. Leave roles empty and anyone can.

What a button can run

Any script button can give and remove roles and post announcements. Punishment commands (warn, mute, unmute, kick, ban, unban) and channel commands (slowmode, lock, unlock) only work once you've set roles on the button. Otherwise anyone could press it.

Who pressed it

Inside a button script, {clicker.*} is the person who pressed it. {clicker.mention}, {clicker.id}, {clicker.rolenames}, {clicker.isadmin} and the rest are on Placeholders. You also get {message.link}, {button.label}, and {button.index} for its position on the message counting from 1. {clicker.coins} and {clicker.level} read their balance and level.

Buttons on reactions

On a custom reaction, $1, $2+ and $1.user.* are filled in when the reaction is posted, so the button remembers the arguments. {clicker.*} is filled in later, when someone presses it. That's how a ban request can carry the target and the reason through to whoever approves it.

{require:clicker.id == 123456789012345678}
{run:ban $1.user.id {if:$2}$2+{else}Ban request approved{endif}}
{edit:Ban request for $1.user.tag approved by {clicker.mention}.}

If someone else presses it, {require:} stops the script. To tell them why, branch instead:

{if:clicker.id != 123456789012345678}
{reply:Only the owner can approve this.}
{stop}
{endif}
{run:ban $1.user.id $2+}
{edit:Ban request for $1.user.tag approved by {clicker.mention}.}

What the presser sees

After a button runs, the person who pressed it gets a reply only they can see. By default it says what happened. Use {reply:text} to write your own.

Scheduler

Run things later, or over and over.

From Discord

CommandDescriptionUsageExample
/schedule createPosts a message after a delay, and optionally repeats it. Needs Manage Messages./schedule create in message [channel] [every] [name]/schedule create 1h Drink water #general 6h
/schedule listActive tasks with their IDs./schedule list/schedule list
/schedule cancelDeletes a task./schedule cancel id/schedule cancel 4

Times here are a number and one unit: 30s, 10m, 2h, 1d, 1w. Repeats have to be at least a minute apart.

From the panel

The panel does a lot more. A task has a schedule and up to 10 actions.

ScheduleRuns
OnceAt a set date and time.
IntervalEvery so often, from a start time. Can stop after a number of runs or on a date.
LimitedA set number of runs spread evenly across a window. Five posts over a day, for example.
ActionDoes
MessagePosts text to a channel.
EmbedPosts an embed, with optional text above it.
CommandPurge, slowmode, lock or unlock a channel.
Ticket or submission panelReposts the panel, so the button stays at the bottom of a busy channel.
IntegrationRuns one of your integrations with the arguments you give it.

Placeholders work in scheduled messages, but nobody triggered them, so {user} is the bot and $1 is empty. Run now fires a task straight away without changing its schedule.

Integrations

A command that calls an API and posts what comes back. Weather, stats, a game server's player count, anything with a URL.

Manage Server

Integration commands use the server's prefix, ! unless you change it under Command permissions. An integration with the trigger weather runs on !weather london.

Request

  • Method and URL. GET, POST, PUT, PATCH or DELETE. The URL has to be a public address.
  • Headers, up to 20.
  • Body as JSON, form data or plain text.
  • Timeout, 30 seconds by default, 2 minutes at most.

$1, $2+ and $* can go in the URL and body. So can {user.id}, {server.id} and the rest of the placeholders.

https://api.example.com/weather?city=$*&units=metric

Secrets

Save API keys under Credentials and use them as {secret.NAME} in headers, the URL or the body. They're stored encrypted and never shown again after you save them.

Authorization: Bearer {secret.WEATHER_KEY}

Response

Set a response path to pull one field out of JSON, like data.current.temp or results.0.name. Then write the reply with {resp.*}:

It's {resp.current.temp} degrees in {resp.location.name}. ({resp.ms}ms)
VariableIs
{resp.value}The field at the response path, or the whole body
{resp.field.sub}Any field in a JSON reply
{resp.list.0.name}An item from a list, counting from 0
{resp.status}HTTP status code
{resp.ok}true or false
{resp.error}The error body when it failed
{resp.ms}How long it took

There's a separate error template for when the call fails. The reply can be text, an embed, or an image if the API returns one, and it can go as a reply, to a set channel, by DM, or nowhere. Integration replies can have buttons.

Like reactions, integrations have role and channel limits, a cooldown, and a required argument count with a usage hint.

Run test calls the API with the arguments you type and shows the response. Click a field in it to make it the response path.

Incoming webhooks

A URL other services can send data to. A short script decides what the bot does with it.

Manage Server

Create one under Integrations and you get a URL like https://your-panel/hooks/abc123.... Anything that can send a POST (GitHub, a form service, your own server) can use it. Up to 3 per server.

The script

The incoming body is {payload}. Reach into it with dots: {payload.repository.full_name}, {payload.items.0.id}. Headers are {headers.name}.

{require:payload.action == opened}
{not:payload.pull_request.draft}
{post:#dev} New PR in {payload.repository.full_name}: {payload.pull_request.title}
{post:#dev} {payload.pull_request.html_url}

Every directive is on Script directives. Paste a sample body in the panel and hit Preview to see what the script would do without doing it.

Signing

Set a signing secret and the bot will reject anything not signed with it. It checks an HMAC-SHA256 of the raw body in X-Hub-Signature-256, X-Signature-256 or X-Signature, with or without sha256= in front. That's the same format GitHub uses, so for GitHub just paste the same secret in both places.

Each URL takes 60 requests a minute and bodies up to 256 KB.

Social alerts

Post in a channel when a Twitch streamer goes live, a YouTube channel uploads, or an RSS feed gets a new post.

Manage Messages

Open Social Alerts in the panel, pick the kind, paste the channel or feed, and choose where it posts. You can also pick a role to ping and write your own message.

KindWhat to pasteWhen it postsPer server
TwitchA twitch.tv link or the channel nameAs soon as the stream starts, once per stream3
YouTubeA channel link, an @handle, or a channel id starting with UCAs soon as a video goes up5
RSSThe full address of an RSS or Atom feedChecked on a timer you pick, from every minute to every hour. 5 minutes by default25

Twitch and YouTube tell the bot the moment something happens. The bot also checks each one every hour, in case a notice got lost while it was restarting. RSS feeds can't send notices, so they're checked on the timer you set for each feed.

Only things posted after you add the alert are sent, so you won't get a flood of old videos. If a feed has a lot of new entries at once, the three newest go out and the rest are skipped. Editing an old video's title doesn't post it again.

The message

Leave it empty for the default, or write your own with these, plus any function or condition:

PlaceholderGives
{alert.name}The streamer, channel or feed name
{alert.title}Stream title, video title or post title
{alert.url}Link to the stream, video or post
{alert.game} {alert.viewers}Twitch only
{alert.summary}YouTube description or the start of the post
{alert.author}RSS post author, when the feed has one
{alert.thumbnail}Image link, when there is one
{alert.name} is live playing {alert.game}{if:{alert.viewers} > 100}, and it's busy in there{endif}

With embed on, the post includes a card with the title, link and thumbnail. With it off, the link goes at the end of the message so Discord shows its own preview.

Custom embed and buttons

Tick Customize the embed and add buttons to open the full editor. It starts filled in with the default layout, so you can change one part and leave the rest. Every box takes the {alert.*} variables, functions and conditions: title, link, description, colour, author, images, footer, up to 25 fields, and whether to show the post time. Back to the default layout resets it.

You can add up to 5 buttons. Link buttons can use a variable as the address, like {alert.url}. Script buttons work like everywhere else, and the alert's variables are filled in when the post goes out, so a button can say {reply:{clicker.name} is watching {alert.title}}.

Test posts the latest video or feed entry, or the current stream if the channel is live, so you can check how it looks.

If something goes wrong, the error shows under that alert in the panel, like a feed that stopped working or a channel the bot can't post in.

Import and export

Move reactions, integrations and embeds between servers, or keep a backup.

Reactions, Integrations and the Embed builder each have Export and Import at the top. Export saves everything on that page to a JSON file. Each item also has its own Export for just that one, and Duplicate to make a copy you can change.

When importing, pick what to do with items that already exist: skip them, or replace them. Reactions are matched by trigger, integrations by trigger and then name.

  • Duplicates start switched off. Imported items keep whatever on or off state they were exported with.
  • Imported webhooks get a new URL and no signing secret, so update whatever sends to them.
  • Credentials are never exported. Add them again on the new server.
  • Embed imports load into the builder so you can check them before posting.
{
  "donkcord": 1,
  "kind": "reactions",
  "items": [
    { "trigger_text": "!rules", "match_type": "word", "response_type": "text", "response": "Read {#rules} before posting." }
  ]
}

Placeholders

Words in braces that get swapped for real values when the message is sent. They aren't case sensitive.

Custom reactions, welcome messages and DonkGuard DMs get the full set. The embed builder, ticket and submission panels and scheduled posts get everything except the member ones, since nobody triggered them. Button and webhook scripts have their own set, further down.

Member

PlaceholderGives
{user}A mention of the member
{user.name}Username
{user.nick}Nickname here, or display name
{user.id}User ID
{user.tag}Account tag
{user.mention}Same as {user}
{user.avatar}Avatar URL
{user.createdat}Account creation date
{user.joinedat}When they joined this server
{user.game}What they're playing, if Discord shares it
{user.level}Their level, from Levels
{user.xp}Their total XP
{user.rank}Their place on the leaderboard, empty if they have no XP
{user.coins}Their balance, from Economy

Server and channel

PlaceholderGives
{server}Server name
{server.id}Server ID
{server.icon}Icon URL
{server.membercount}Member count
{server.ownerid}Owner's user ID
{server.createdat}When the server was made
{channel}A link to the channel
{channel.name}Channel name
{channel.id}Channel ID

Arguments

Reactions only. These don't take braces.

PlaceholderGives
$1 $2The first, second word after the trigger
$2+Everything from the second word on
$*Everything after the trigger
$1.user.nameWhen $1 is a member, their username. Also .nick, .id, .mention, .tag, .avatar, .createdat, .joinedat, .game

Mentions

PlaceholderGives
{@name}Mentions a member by username or nickname
{&role}Mentions a role by name
{#channel}Links a channel by name
{everyone} {here}Only ping when @everyone is allowed on that reaction

In any message box in the panel you can type @ to search members and roles.

Random and time

PlaceholderGives
{random(1,10)}A whole number between the two, inclusive
{choose(a,b,c)}One of the options
{choose:a;b;c}Picks one without printing it. Print it later with {choice}
{time} {time12}Current time, 24 or 12 hour
{date}Today's date
{datetime} {datetime12}Both
{timestamp}Unix time in seconds
{iso}ISO 8601 time
{uuid}A random ID

Times use the server timezone. Wrap {timestamp} in Discord's format to get a time that shows in each reader's own timezone: <t:{timestamp}:R>.

In button scripts

PlaceholderGives
{clicker} {clicker.mention}A mention of whoever pressed it
{clicker.id} .name .nick .tag .avatarTheir details
{clicker.roles}Their role IDs, comma separated
{clicker.rolenames}Their role names, comma separated
{clicker.rolecount}How many roles they have
{clicker.coins} {clicker.level}Their balance and level
{clicker.isowner} {clicker.isadmin}true, or empty
{clicker.joinedat} {clicker.createdat}Join and account dates
{message.id} {message.link}The message the button is on
{button.label}The label of the button pressed
{button.index}Its position on the message, counting from 1
{server.*} {channel.*}Same as above

In a button script {user} also means the person who pressed it.

In webhook scripts

{payload.*} for the body, {headers.*} for headers, {hook.name}, and {server.name}, {server.id}, {server.membercount}. Headers carrying keys or signatures are hidden. There's no channel, since nothing was posted.

Conditions

Show different text depending on who, where or what. Works everywhere placeholders do, including buttons and webhooks.

{if:user.name == sam}Hey Sam.{elseif:$1}You said $1.{else}Hi {user}.{endif}

A block starts with {if:test}, can have any number of {elseif:test}, one {else}, and ends with {endif}. Blocks can be nested.

Tests

TestPasses when
a == bBoth sides are the same
a != bThey're different
a ~ bThe left side contains the right, ignoring case
a !~ bThe left side doesn't contain the right
a > b a >= b a < b a <= bCompares numbers. Put a space on each side. If either side isn't a number, the test fails
aIt has a value. Empty, 0, false and null don't count

You can leave the braces off the left side. {if:user.name == sam} and {if:{user.name} == sam} are the same. Arguments work too: {if:$2} checks whether a second word was given.

Joining tests

&& means both have to pass, || means either one. && is checked first, so a && b || c reads as "a and b, or c".

{if:$1 >= 1 && $1 <= 6}You rolled a $1.{else}Pick a number from 1 to 6.{endif}
{if:clicker.rolenames ~ Moderator}
Welcome back, mod.
{else}
This one's for mods.
{endif}

When a tag sits on a line by itself, the line break goes with it, so you can lay blocks out over several lines without leaving gaps in the message.

In a button on a reaction, a test that uses {clicker.*} is left alone when the reaction posts and checked when the button is pressed.

Functions and counters

Do sums, change text, pick things at random, keep values for later, and count things across messages. These work everywhere placeholders do.

Functions

FunctionGivesExample
{math:expression}Works out a sum. + - * / % ^, brackets, and round, floor, ceil, abs, min, max, sqrt. Prints NaN if it can't{math:round($1 * 1.2)}
{upper:text} {lower:text}Capital or small letters{upper:$1}
{length:text}How many characters{length:$*}
{replace:find|with|text}Swaps every find for with{replace:_| |$1}
{ord:number}1st, 2nd, 23rdYou are our {ord:{server.membercount}} member
{list:n|a;b;c}Item number n. -1 is the last. With no semicolons it splits on spaces{list:-1|$*}
{weighted:a=9;b=1}Random pick, higher numbers come up more often{weighted:common=80;rare=19;legendary=1}
{random(1,100):seed}A random number that's always the same for the same seed{random(1,100):{user.id}}
{choose(a,b,c):seed}A pick that's always the same for the same seed{choose(cat,dog,owl):{target.id}}
{since:date} {until:date}How long ago, or how long until. Takes a unix time or a date placeholder{since:{user.createdat}}

Functions can go inside each other and inside placeholders: {upper:{list:2|$*}}. Anything a member types stays as plain text, so nobody can slip a function into an argument.

$1+ means "everything from the first word on", so in a sum put spaces around the plus: {math:$1 + $2}.

Variables

{set:name|value} saves a value without printing anything, and {var:name} prints it. In reactions and welcome messages a variable lasts for that message. In button and webhook scripts it lasts for the rest of the script.

{set:total|{math:$1 * $2}}
$1 x $2 = {var:total}{if:{var:total} > 100}, that's a lot{endif}

Counters

Counters are numbers the bot keeps for the server, so they carry over between messages and restarts.

UseDoes
{counter:name}Adds 1 and prints the new number
{counter:name|5}Adds 5. Use a minus number to take away
{counter:name|=0}Sets it to a number
{count:name}Prints it without changing it

Put a placeholder in the name to get one counter per member: {counter:hugs.{target.id}}. A counter only moves once per message, even if you use it in the title and the text. Embed builder posts, ticket and submission panels only read counters, they never change them. A server can have 5,000 counters.

Trigger:  !hug
Match:    Starts with
Response: {user} hugs {target}. That's hug number {counter:hugs.{target.id}} for {target.nick}.

{target} and {uses}

In reactions, {target} is the first member named after the trigger, or the person who used it if nobody was named. It has the same parts as {user}: {target.nick}, {target.id}, {target.avatar}, {target.joinedat} and so on. {uses} is how many times the reaction has been used, counting this time.

Script directives

Button and webhook scripts are a few lines, run top to bottom. A line that starts with a directive does that thing. Any other line is posted as a message.

DirectiveDoesExample
{post:#channel} textPosts to a channel. Use a #name, a channel mention or an ID.{post:#mod-log} {clicker} opened the door
{post} textOn a button, replies under the button's message. A plain line does the same.{post} Thanks, {clicker}.
{embed:#channel} titlePosts an embed with that title.{embed:#news} Server restart in 5 minutes
{embed:#channel} with {endembed}A full embed from settings. See below.{embed:#news}
{embedjson:#channel}A full embed from Discord embed JSON, on the same line or in a block.{embedjson:#news} {"title": "Hi"}
{react:emoji}Reacts to the message the button is on. Up to 5, separated by spaces.{react:👍 👎}
{run:command}Runs a bot command. See below.{run:setrole {clicker.id} Verified}
{dm:@user} textDMs a member. Use an ID or mention.{dm:{clicker.id}} You're in.
{reply:text}Buttons only. What the presser sees, only to them.{reply:Role added.}
{edit:text}Buttons only. Rewrites the button's message and removes its buttons. Embeds stay.{edit:Closed by {clicker.mention}.}
{editkeep:text}Buttons only. Same, but the buttons stay, so it can be pressed again.{editkeep:High bid {var:b}.}
{edit:link} textRewrites the text of another message the bot posted. Its embeds and buttons stay.{edit:1234567890 Updated}
{editembed:link}Replaces the embed on another message the bot posted. Same settings as {embed}, closed with {endembed}.{editembed:1234567890}
{editembedjson:link}Same, from embed JSON.{editembedjson:123} {"title": "Closed"}
{disable:link}Takes the buttons off another message the bot posted.{disable:1234567890}
{disable}Buttons only. Takes the buttons off and leaves the rest.{disable}
{remove}Buttons only. Deletes the button's message after everything else has run.{remove}
{set:name|value}Saves a value for the rest of the script. Read it with {var:name}.{set:n|{math:{clicker.rolecount} + 1}}
{require:test}Stops unless the test passes.{require:clicker.isadmin}
{not:test}Stops if the test passes.{not:payload.draft}
{stop}Ends the script there.{stop}
{if} {elseif} {else} {endif}Run lines only when a test passes. Each on its own line.See Conditions

Lines starting with // are skipped, so you can leave yourself notes. A script can post up to 10 times and run up to 5 commands.

Directives can sit on one line together, the same way they do in custom reactions. These are the same script:

{if:clicker.isadmin != true}{reply:Admins only.}{stop}{endif}
{reply:Welcome back.}
{if:clicker.isadmin != true}
{reply:Admins only.}
{stop}
{endif}
{reply:Welcome back.}

Embed blocks

Open with {embed:#channel} on a line of its own and close with {endembed}. Each line inside is a setting. Lines that aren't a setting join the description.

{embed:#news}
title: Restart in 5 minutes
color: #ff0000
desc: We are moving to a bigger machine.
Back in about ten minutes.
field: When | In 5 minutes | inline
field: Who | Everyone
thumb: https://example.com/icon.png
footer: Lemon Party
{endembed}

Embeds from JSON

{embedjson:#channel} takes Discord's own embed JSON, the format you get from an embed builder like Discohook. It works on one line or as a block closed with {endembed}. A wrapper of {"embeds": [ ... ]} is unwrapped for you, and placeholders render before the JSON is read.

{embedjson:#news} {"title": "Restart", "description": "Back in ten.", "color": 16711680}
{embedjson:#news}
{"embeds": [{"title": "Rules", "color": 5793266, "fields": [{"name": "1", "value": "Be decent", "inline": true}]}]}
{endembed}

Colours can be a number, as Discord writes them, or #5865f2. If the JSON does not parse, the text is posted as an ordinary message instead of failing silently.

Editing messages

A script can change any message the bot itself posted, anywhere in the server. Discord does not let any bot edit somebody else's message, so that is the limit. Point at a message with its link, its ID, or channelid/messageid. A bare ID means the channel the script is running in.

To changeUse
Text{edit:link} new text
Embed{editembed:link} block, or {editembedjson:link}
Buttons{disable:link} to remove them

They are separate on purpose: editing the text leaves the embed and the buttons alone, and editing the embed leaves the text alone. Use two lines to change two parts.

{edit:{var:board}} Auction closed.
{editembed:{var:board}}
title: Sold
desc: Winning bid {var:bid} by {clicker.nick}
{endembed}
{disable:{var:board}}

On the message a button is on, {edit:} with no link still works and still removes the buttons, and {editkeep:} leaves them. With a link the buttons always stay, since nothing suggests you meant to remove them.

Embed settings

Settings are title, desc, color, url, author, author_icon, author_url, image, thumb, footer, footer_icon, timestamp and field: Name | Value | inline, up to 25 fields. Colours are 6-digit hex. Placeholders and functions work on every line. Leave out {endembed} and the lines are posted as plain text instead.

Commands for {run:}

CommandFormat
setrole, removerolesetrole user role
announceannounce #channel text
warnwarn user [reason]
mutemute user [minutes] [reason], 10 minutes if left out
unmuteunmute user
kickkick user [reason]
ban, unbanban user [reason]
slowmodeslowmode #channel seconds
lock, unlocklock #channel [reason]
raidraid on or raid off
verifyverify user
rolepanelrolepanel Name [#channel]
award, takeaward user amount [reason]
chargecharge user amount [reason], stops the script if they cannot afford it
paypay from to amount [reason], stops the script if the sender cannot afford it

A user can be an ID or a mention. On a button, setrole, removerole, announce, verify, rolepanel, charge and pay always work. Everything else needs roles set on the button first.

Reaction modifiers like {delete} and {silent} don't do anything in scripts. To delete the message a button is on, use {remove}.

Channel monitor

Watch a channel live from the panel and post into it as the bot.

Messages show up with the formatting, replies, embeds and attachments you'd see in Discord, starting with the last 100. You only see channels you can see in Discord.

Posting needs Manage Messages and Send Messages in that channel. Deleting a message from the monitor needs Manage Messages.

Archive and viewer

Save a whole channel to a file, then read it back later in the panel.

Manage Server

CommandDescriptionUsageExample
/archive channelStarts an archive. 0 or no limit means every message. Before and after take message IDs./archive channel channel [limit] [before] [after]/archive channel #general
/archive statusArchives running and ready to download./archive status/archive status
/archive cancelStops one that's running./archive cancel channel/archive cancel #general

Text channels, announcement channels, threads and voice channel chats all work. The finished file is a .jsonl, one message per line. The download link only lasts a few minutes, so grab it when it's ready.

Viewer

Open the file on the Archive page. It's read in your browser and never uploaded. You can search, filter by member and date, and narrow down to images, files, links, embeds, replies, edited or pinned messages. Clicking a reply jumps to the original.

Site embeds

Put a live Discord channel on your own website. Visitors read it, and if you allow it, sign in with Discord and post.

Manage Messages

Each embed gives you a snippet to paste into your site. Up to 3 per server.

Who can see and post

  • Viewing: anyone, anyone signed in, server members, people who can see the channel in Discord, or certain roles.
  • Posting: anyone signed in, members only, certain roles, or guests. You can also set a minimum account age and block users.
  • Allowed sites: the domains it's allowed to load on. *.example.com works.

Posts from the site show up in Discord through a webhook named after the poster, name (web) by default. They go through the embed's own word filter and DonkGuard if you turn it on, and you can set a cooldown, a per-minute limit and a max length.

Looks

Light, dark or match the visitor. Accent colour, background, spacing, font size, corner radius, which parts of messages show (avatars, times, images, embeds, replies), and what the lock screen says when someone isn't allowed in.