๐ Help
Every bot module documented in one place. Each entry has the overview, setup steps, slash commands, and tips. Tap any card to expand. Per-guild settings live on each module's dashboard page โ sign in and pick a server to manage them.
Anti-nuke
Wick-equivalent: trip wires for bulk channel/role deletes + magic-link unfreeze.
Listens for bulk admin actions (channel deletes, role deletes, mass bans). If an actor exceeds the threshold within the time window, the bot strips their dangerous roles, freezes the guild's admin tier, takes a snapshot, and DMs the owner a single-use **magic link** to unfreeze. Fastest practical kill-switch for hostile-takeover scenarios.
Setup
- Visit Anti-nuke โ Config. Verify thresholds (defaults are conservative).
- Make sure the bot's role is above the roles it needs to strip.
- Confirm `SNAPSHOT_KEY` is set in the .env (snapshot blobs are AES-GCM encrypted).
Workflows
What happens during a freeze
Bot strips Manage-* perms from the actor โ freezes the guild (blocks new admin actions for the freeze duration) โ takes a snapshot โ DMs the owner with the magic link. Owner clicks link, confirms, freeze lifts.
Manual freeze
Anti-nuke โ Config โ Freeze. Same effect as the auto-trigger but driven by you.
Slash commands
| Command | What it does |
|---|---|
/antinuke status |
Show current state + freeze status. |
/antinuke freeze |
Manually freeze the guild. |
/antinuke unfreeze |
Manually clear a freeze (also via magic link). |
Tips
- Take periodic snapshots (Backups โ Take). They're the rollback for a real nuke.
- Add a few trusted admins above the bot's role so they bypass the trip wires.
Troubleshooting
- Auto-freeze didn't fire on a real attack
- Check audit-log lookup window (default 5s). Actions outside it can't be attributed to an actor; we fail open. Tune via the config.
- Lost the magic link DM
- Owner can also `/antinuke unfreeze` directly in Discord. Or trigger another DM from the dashboard's Anti-nuke page.
Anti-raid
Account-age + no-pfp gates, panic mode, join-rate spike auto-trigger.
Each `on_member_join` runs through gates in order: account age < min_days โ kick; no profile picture (if required) โ kick; panic mode active โ kick. Join-rate spike (configurable) auto-activates panic mode.
Setup
- Anti-raid โ Config form. Sane defaults: 7-day min age, 10 joins/60s spike threshold.
Slash commands
| Command | What it does |
|---|---|
/antiraid status |
Current state + active panic. |
/antiraid panic on duration_min:30 |
Manual panic mode. |
/antiraid config |
Slash-form alternative to dashboard. |
Automod
Regex / spam-rate / invite / link / badword / toxicity rule chains with heat scoring.
Per-message scan against enabled rules. Each rule has a chain of actions (delete + warn points + mute seconds). A per-user **heat score** (Redis ZSET, decays linearly) tracks repeat offenders and lets you scale severity adaptively.
Setup
- Automod โ + New rule. Pick a type and pattern.
- (Optional, toxicity only) Automod โ OpenAI key โ paste an `sk-...` key to enable AI moderation.
- Add rules incrementally. The heat-score per-user surfaces in the Top heat scores table.
Workflows
Block invite links
+ New rule โ type: `invite`, pattern: empty, action chain: delete + warn 1pt. Done. Built-in regex matches discord.gg / discord.com/invite.
Block specific bad words
Type: `badword`, pattern: comma-separated list (e.g. `slur1,slur2,scamword`). Match is case-insensitive substring.
Spam rate
Type: `spam_rate`, pattern: `{"count":5,"window_s":4}`. 5 messages in 4 seconds โ action chain fires.
Toxicity (BYO OpenAI key)
Type: `toxicity`. Pattern empty = match anything OpenAI flags. Optional: `{"categories":["harassment"],"threshold":0.8}` to filter to one category.
Slash commands
| Command | What it does |
|---|---|
/automod rule-add |
Quick add via slash. |
/automod rule-list |
Inline list. |
/automod heat @user |
Show their current decayed score. |
/automod openai-key |
Set/clear the per-guild key for the toxicity rule. |
Tips
- Start with a few rules; expand as patterns emerge in mod-log.
- Heat-score adaptive escalation: build rules that trigger only above a heat threshold.
Troubleshooting
- Toxicity rule never matches
- Check OpenAI key is configured (Automod page shows a green pill if so) and that you have an OpenAI account in good standing.
- Spam rate over-triggers
- Tune count/window_s upward, or use exempt_roles to skip moderators.
Backups
Snapshot + restore the guild's channel/role structure.
Take periodic snapshots (zstd JSON + AES-GCM if SNAPSHOT_KEY set). Restore wizard diffs the snapshot against the live guild and applies create/update ops. Default safe (no auto-deletes).
Setup
- Backups โ Take snapshot. Recommended: take one before risky restructures.
Slash commands
| Command | What it does |
|---|---|
/backup take / list / info / export / delete |
Slash equivalents. |
Branding
Per-guild bot nickname + dashboard accent color.
Discord allows per-guild nickname (and only nickname โ not avatar or status). Dashboard accent color repaints the chrome on this guild's pages.
Setup
- Branding โ set nickname + theme color.
Slash commands
| Command | What it does |
|---|---|
/branding nickname/theme/show/clear |
Slash equivalents. |
Custom commands
User-defined commands rendered via TagScript. Carl-bot-equivalent.
Members type `<prefix><name>` (default `!cmdname`) and the bot replies with the rendered template. Useful for FAQs, quick references, or running gags. TagScript is sandboxed โ 50ms render cap, 4KB output cap, no I/O.
Setup
- Custom commands โ tweak the prefix if `!` clashes with another bot.
- + New command โ name + body. Live preview validates as you type.
Workflows
Create a simple FAQ command
+ New command โ name: `rules`, body: `Read <#channel-id>! Be excellent.` Save. Now `!rules` in any channel renders that text.
Use TagScript variables
Body: `Hello {user.mention}, you're #{member_count} in {guild.name}!`. Renders dynamically per caller.
Slash commands
| Command | What it does |
|---|---|
/cmd add name:_ body:_ |
Slash equivalent of the dashboard New form. |
/cmd run name:_ |
Trigger by name when the prefix is unclear. |
/cmd list |
List all commands. |
/cmd prefix prefix:_ |
Change the prefix. |
Tips
- 200-command cap per guild. Plenty for FAQs.
- Permissions editor (role/channel restrict) is slash-only for now: `/cmd permissions`.
Troubleshooting
- Commands don't trigger from chat
- 1) Confirm Message Content Intent is on. 2) Confirm the prefix is what you think it is (Custom commands โ Prefix field shows current value).
- Command output is empty
- TagScript errored โ switch the command to a simpler body and re-build up. Live preview catches most errors.
Embed builder
Saved embed library with dual-pane editor + send-to-channel.
Build embeds with a form (title/desc/color/image/fields), see a live Discord-shaped preview, save by name, send to any channel.
Setup
- Embeds โ + New embed. Live preview updates 200ms after each keystroke.
Slash commands
| Command | What it does |
|---|---|
/embed save / send / list / view |
Slash equivalents. |
Giveaways
Timed prize draws with a persistent Enter button.
Create a giveaway โ bot posts an embed with an Enter button โ at deadline, picks N random winners + edits embed + DMs winners.
Setup
- Giveaways โ Start a giveaway. Pick prize + duration + winners + channel.
Slash commands
| Command | What it does |
|---|---|
/giveaway start prize:_ duration:_ winners:_ |
Inline create. |
/giveaway end <id> |
End now. |
/giveaway reroll <id> |
Pick new winners from same entries. |
Leveling
Mee6-compatible XP per message + role rewards on level-up.
Every non-bot message earns 15-25 XP (configurable) once the user clears the 60s anti-spam cooldown. Level curve is the standard Mee6 shape: 5Lยฒ+50L+100 per level. Hitting a configured **reward** level grants the matching role automatically via roles.service.grant_role.
Setup
- Leveling โ Config. Toggle Enabled, optionally tweak XP min/max + cooldown.
- Pick an announce channel (empty = post in the user's own channel).
- Add level rewards in the Rewards table (level + role picker).
Workflows
Tune XP rate
Leveling โ Config โ XP min / max. 15-25 is the Mee6 default and works for most communities. Lower for very chatty servers.
Reset a user's XP
Leveling โ Leaderboard โ Reset row. Deletes their XP row; they start at level 0.
Hide certain channels from XP
Leveling โ Config โ Ignore channels. Members chatting there earn nothing.
Slash commands
| Command | What it does |
|---|---|
/level get [@user] |
Show level + XP + progress bar. |
/level top |
Top 10 leaderboard. |
/level opt-out / opt-in |
Member-side toggle to stop earning XP. |
Tips
- Level rewards should be additive โ don't remove lower-level roles automatically.
- Combine with Roles โ Autoroles for a 'verified at level 5' badge.
Troubleshooting
- Members aren't earning XP
- 1) Confirm Enabled. 2) Confirm Message Content Intent is on in the Dev Portal. 3) Check the channel isn't in the ignore list. 4) Check the user isn't opted out.
Logging
80+ event types routed to per-category log channels with live tail + search.
On every meaningful event (message edit/delete, role change, member join, etc.) the bot writes a row to `event_logs` (partitioned monthly) and posts to the configured channel for that category. Message content is encrypted at rest.
Setup
- Run `/nabsetup`. Or Logging โ Settings โ set per-category channels.
Slash commands
| Command | What it does |
|---|---|
(no top-level slash) |
Configured via the dashboard. |
Tips
- Search past events at Logging โ Search. Live tail at Logging โ Live tail.
Moderation
Cases, escalation rules, modlog. The audited path for mod actions.
Every privileged action (warn, mute, kick, ban) creates a numbered **case** with a hash-chained audit row. Cases mirror to the modlog channel as embeds. Each rule in the **escalation** ladder watches a user's infraction points and auto-applies a follow-up action when the threshold is crossed (3 warns โ mute, 5 warns โ tempban, etc).
Setup
- Run `/nabsetup` once โ wires `#mod-log` automatically.
- Or visit Moderation โ Settings, paste a channel ID into Modlog channel, set Mute role.
- Add escalation rules under Moderation โ Escalation (optional but powerful).
Workflows
Issue a warning
In Discord: `/warn @user reason:_`. The case lands in #mod-log, the user is DMed, and the audit chain extends. From the dashboard: Moderation โ Cases โ no add-case form yet (slash is the entry point).
Edit a case reason
Cases page โ click a case # โ Edit reason. The audit chain logs the edit; previous text is preserved in the audit `before` field.
Configure escalation
Moderation โ Escalation. Add a rule (action, threshold, mute duration, etc). Subsequent warns count toward each user's points; once a threshold is hit, the auto-action fires immediately as a normal case.
Slash commands
| Command | What it does |
|---|---|
/warn @user reason:_ |
Add a warning. Increments infraction points. |
/mute @user duration:30m reason:_ |
Native timeout โค28d, role fallback above. |
/kick @user reason:_ |
Kick + audit + DM. |
/ban @user reason:_ |
Permanent ban. |
/tempban @user duration:7d reason:_ |
Auto-revoke at expiry. |
/case <number> |
Show a case + its audit trail. |
/history @user |
All cases for a member. |
/reason <case> new:_ |
Update a case's reason. |
Tips
- Run `/nabsetup` first โ it wires the mod-log channel automatically.
- Cases are immutable history; edits are tracked, never overwritten.
Troubleshooting
- Mute over 28 days didn't work
- Discord native timeouts cap at 28d; set a Mute role in settings as the >28d fallback.
- User wasn't DMed
- They likely have DMs from server members disabled. The case still lands in #mod-log.
Polls
Button or select-menu votes with auto-close at deadline.
โค5 options renders as buttons; 6+ renders a single select menu. Votes are stored per-user; tally is read-time GROUP BY.
Setup
- Polls โ Create a poll. Provide question + comma-separated options.
Slash commands
| Command | What it does |
|---|---|
/poll create question:_ options:_ multi:bool duration:_ |
Inline create. |
Roles
Reaction / button / select / verify panels + autoroles.
Four panel kinds. **Reaction**: members react with an emoji to claim a role. **Button**: click toggles. **Select**: pick from a dropdown. **Verify**: a single click grants a role + any on-event=verify autoroles. Autoroles fire on `join` or `verify`.
Setup
- Roles โ + Create panel. Pick kind + channel + title. Then click into the panel to add mappings.
Slash commands
| Command | What it does |
|---|---|
/roles panel-create kind:_ title:_ |
Slash create. |
/roles autorole-add role:@ event:join |
Auto-grant on join. |
Scheduled messages
Recurring messages on a 5-field cron.
One row per schedule. Worker fires due rows every 60s; payload is rendered through TagScript.
Setup
- Scheduled msgs โ Add schedule. Cron + channel + payload.
Slash commands
| Command | What it does |
|---|---|
/schedule add cron:_ channel:_ template:_ |
Inline create. |
Tips
- Daily 9am UTC = `0 9 * * *`. Hourly = `0 * * * *`. Test with a 5-min cron first.
Server stats
Voice-channel vanity counters that auto-update every 30s.
Pick a voice channel โ pick a kind (members, online, boosters, humans, bots) โ write a template like `Members: {count}`. The 30s worker renames the channel.
Setup
- Server stats โ Add a counter.
Slash commands
| Command | What it does |
|---|---|
/stats counter add channel:_ kind:_ template:_ |
Inline create. |
Suggestions
Community ideas with status workflow (pending โ approved/declined/implemented).
Members `/suggestion submit` โ bot posts in #suggestions with โฌ๏ธ/โฌ๏ธ + auto-thread. Admins flip status from the dashboard.
Setup
- Run `/nabsetup` for #suggestions. Or Suggestions โ set channel.
Slash commands
| Command | What it does |
|---|---|
/suggestion submit content:_ |
Submit (members). |
/suggestion approve/decline/implement <id> |
Decision (admins). |
Tickets
Modal-driven ticket panels with HTML transcripts on close.
An admin posts a **panel** (an embed with a button) in any channel. When a member clicks it, a modal asks pre-configured questions; answers + a private channel are created. On close, the bot generates a self-contained HTML transcript (avatars, timestamps, attachments) and uploads it to the configured log channel before deleting the channel.
Setup
- Run `/nabsetup` once โ wires `#ticket-transcripts`.
- Tickets โ + Create panel. Pick where the panel posts; the bot creates the message.
- Set the transcript channel on the panel (defaults to #ticket-transcripts if you ran /nabsetup).
Workflows
Open a ticket (member)
Click the button on the panel. Fill the modal. A new private channel appears with you, mods, and the bot.
Claim a ticket (mod)
From the ticket channel: `/ticket claim`. Or from the dashboard: Tickets โ row โ Claim.
Close + transcript
Tickets โ row โ Close. Bot generates HTML, uploads to transcript channel, deletes the channel.
Slash commands
| Command | What it does |
|---|---|
/ticket panel-create |
Create a panel from inside the target channel. |
/ticket claim |
Claim the current ticket channel. |
/ticket close |
Close + transcript. |
Tips
- Set a Tickets category on the panel so new ticket channels get organized.
- Up to 5 questions per panel โ keep them short; the modal has tight character caps.
Troubleshooting
- Panel button doesn't work after restart
- Persistent views are re-registered on cog_load by message_id. If the panel's DB row exists but the message was deleted, the bot can't find it. Recreate the panel.
- Transcript HTML upload failed
- Check the bot has Send Files permission in the transcript channel. The channel is still deleted โ the transcript is just lost. Increase staff's manual chat-log fallback if this is critical.
Watchlist
Flag user IDs; mods get an embed in #mod-log when they join or leave.
Add a Discord user ID to the watchlist. The bot listens for `on_member_join` and `on_member_remove` and, if the user is on the list, posts an alert embed (avatar, account age, watch note) to the configured `modlog_channel_id`. Useful for ban evaders, repeat offenders from other servers, or just "keep an eye on " cases.
Setup
- Run `/nabsetup` (wires the modlog channel) or set Moderation โ Settings โ Modlog channel.
- Watchlist โ add user IDs (or `/watchlist add @user note:_`).
Slash commands
| Command | What it does |
|---|---|
/watchlist add @user [note:_] |
Flag an in-guild user via mention. |
/watchlist add-id user_id:_ [note:_] |
Flag by raw Discord ID โ works even if the user is NOT in the guild yet (typical ban-evader case). |
/watchlist remove @user |
Stop watching them via mention. |
/watchlist remove-id user_id:_ |
Stop watching by ID. |
/watchlist list |
Show all watched users. |
Tips
- Enable Developer Mode in Discord โ right-click avatar โ Copy User ID.
- Add a note explaining *why* you're watching โ future-you (or another mod) will appreciate context.
- Alerts respect the modlog channel's existing permissions, so non-staff never see the embed.
Welcome
Join/leave embeds + DM + autorole, all TagScript-rendered.
Three optional templates: join_msg (posted in the welcome channel), leave_msg (posted in the same channel on leave), dm_msg (DM'd to the joiner). All three support TagScript โ `{user.mention}`, `{user.name}`, `{guild.name}`, `{member_count}`. Live preview shows you the rendered output as you type.
Setup
- Run `/nabsetup` โ wires `#welcome` and enables the module.
- Welcome โ fill in templates. Save.
- Optional: pick an autorole to grant on join.
Workflows
Edit the join message
Type into the Join message textarea. The preview updates 250ms after you stop typing. Save when happy.
Test a template
From Discord: `/welcome test`. Renders the template against you and posts it.
Slash commands
| Command | What it does |
|---|---|
/welcome config |
Slash equivalent of the dashboard form. |
/welcome test |
Render the template against the caller. |
Tips
- Image cards (Pillow-rendered) are deferred to v1.1; for now stick with embeds.
- Combine with Roles โ Autoroles for richer onboarding (verify gate, etc).
Troubleshooting
- DM didn't arrive
- Discord auto-blocks DMs from members of servers when 'Allow DMs from server members' is off. The join + leave channel posts still work.
- TagScript syntax error
- Check the live preview โ errors show inline as <em>. Common gotchas: missing closing brace, unknown variable name.