<prefix>-0001Override the bot's display name and avatar for this server. Applies to all notification embeds sent to this server.
Discord does not revert anything automatically when a bot leaves. Every channel, role, permission overwrite, and message the bot created stays exactly as-is — Discord owns that data, not the bot. To clean up before uninstalling, use the optional cleanup steps in the uninstall confirmation dialog (accessible from the server selector).
When the bot is re-invited, on_ready runs a full recovery sequence for every server it joins.
What happens depends on which channel was deleted and whether the bot is currently running.
[!] Channel {id} not in cache. Functions that target that channel (mod log, error alerts, slash commands) silently fail until restart.ensure_system_channels automatically recreates the missing channel under "MAMA NUI System" and updates the saved ID.ensure_new_member_channels automatically recreates any missing channel under the "New Member" category.Sources are external accounts the bot actively monitors. When new content is detected (video, tweet, email, game update, RSS post), a notification embed is delivered to the Discord channels mapped in Routing.
- 1Go to Sources → click + Add Account
- 2Select a platform and fill in the required identifier (Channel ID, App ID, username, or feed URL)
- 3Save — the source card appears with a status indicator
- 4Go to Routing and create a rule linking this source to a Discord channel. Without a routing rule, no notification is ever delivered.
| State | Behavior |
|---|---|
| ON | Source is actively polled at the configured interval. New content triggers a Discord notification. |
| OFF | Source is paused. No polling occurs and no notifications are sent until re-enabled. |
| Error | Reason | Fix |
|---|---|---|
| Invalid Channel ID | YouTube channel ID is wrong or the channel doesn't exist | Verify the ID starts with UC… on YouTube Studio → Settings |
| Twitter cookie expired | Session cookies (auth_token / ct0) have been invalidated — Twitter rotates them periodically | Re-paste fresh cookies from browser DevTools → Application → Cookies on twitter.com |
| Gmail not authorized | No OAuth token found for this Gmail account | Go to Settings → Gmail Authorization → Authorize Gmail |
| Failed to fetch RSS | Feed URL returned an error or is unreachable | Confirm the URL is valid and publicly accessible |
| No routing targets | Source has no enabled routing rule pointing to an active channel | Add a rule on the Routing page |
Reddit embeds are kept up to date automatically. Every day at midnight the bot fetches the latest score and comment count for every Reddit post it delivered in the last 7 days and edits the Discord embed in-place. The last line of each embed (💬 X comments • ⬆️ Y) is replaced with the fresh values. Posts older than 7 days are dropped from the update queue.
| Behavior | Detail |
|---|---|
| Trigger | Once daily at midnight (server local time) — independent of the per-source check interval |
| Scope | All Reddit posts delivered within the configured update window (default 1 day), across all subreddits and all servers. Configurable in Owner Controls. |
| What changes | Only the score/comment stats line at the bottom of the embed description — title, URL, flair, and image are untouched |
| Post deleted on Reddit | Fetch returns no data — that post is silently skipped; its Discord embed is left as-is |
| Discord message deleted | Edit fails — logged as a warning, loop continues to the next post |
| Bot stopped at midnight | Daily update does not run for that day — embeds keep the last-refreshed stats until the next midnight the bot is running |
By default the bot delivers a Discord embed with title, 300-char description and a thumbnail URL. Each source can opt into Repost mode (Edit Source → Repost section) for richer delivery:
| Mode | Behavior |
|---|---|
| Standard embed | Default. Title + 300-char description + thumbnail URL. Discord auto-unfurls the link. |
| Repost | Drops the truncated embed. Include text sends the full body (no 300-char cap, up to 4096 chars). Include media downloads the image/video and uploads it as a native Discord attachment. |
| Trigger repost | Same as Repost — but only when the post matches a keyword (case-insensitive substring) or regex pattern. No match → falls back to standard embed. |
Trigger search fields: any subset of Title, Body, Tags / flair / hashtags. Empty keywords + empty patterns = always match. If a downloaded file exceeds Discord's 25 MB upload limit, the bot silently falls back to the standard embed for that post. YouTube (videos too large) and Twitch (live streams) cannot upload their primary media — the dashboard warns when these modes are picked for those platforms.
Discord channels eligible to receive source notifications. A channel must exist here and have a matching Routing rule to receive any messages.
- 1Go to Channels → Notification tab → click + Add Channel
- 2Pick a Discord channel from the dropdown (fetched live from your server)
- 3Toggle the channel ON to activate it, then create a Routing rule
| State | Behavior |
|---|---|
| ON | Channel is active. Routing rules targeting it will deliver notifications. |
| OFF | Channel is disabled. No notifications are delivered even if a Routing rule targets it. |
Channels auto-created in a New Member category. New members can only access these channels until they pick a role via Role Gate. This is also where the welcome message is sent.
| Channel | Toggle ON | Toggle OFF |
|---|---|---|
| #welcome | Welcome embed is sent to this dedicated channel when a new member joins | Welcome message falls back to Discord's default system channel (typically general chat) |
| #rules | Rules channel is visible in the New Member category | Channel is hidden / removed from the category |
| #roles-picker | Reaction roles message is posted here; members react to pick a role | Role Gate cannot function — no channel for members to pick roles from |
| #anonymous | Members can type here and the bot intercepts the message, deletes the original, and reposts it as 💬 Anonymous — identity hidden from everyone except the anonymous-log | The anonymous channel is removed; /anon command still works if used in other channels but the channel-based auto-intercept stops |
When a member posts in #anonymous or runs /anon, the bot deletes their original message and reposts it with a 💬 Anonymous header. The member's real identity is never shown in public — only visible in #anonymous-log (System channel) for moderation. This is by design.
Hidden management channels auto-created under a MAMA NUI System category. Only the configured Admin Role can see this category.
| Channel | Toggle ON | Toggle OFF |
|---|---|---|
| #commands | Bot slash command output is delivered here; visible to Admin Role only | No dedicated channel for command output |
| #submissions | /submit form results are posted here | Submissions are not forwarded anywhere |
| #admin-review | Admin review panel available | Feature disabled |
| #mod-log | All mod actions (kick/ban/warn/timeout) are logged here | Mod actions are not logged to Discord |
| #errors | Bot runtime errors are reported here in real time | Errors are only visible in the Dashboard Logs page |
| #anonymous-log | Every anonymous message posted via /anon or #anonymous channel is logged here with the real sender's identity, channel, and message content — visible only to Admin Role | Anonymous messages are still delivered publicly but the real sender is never recorded anywhere |
Set via System tab → Admin Role dropdown. Only members with this role can see the MAMA NUI System category. Without an Admin Role set, the category is visible only to server administrators (Manage Server permission).
Routing rules are the bridge between a Source and a Discord channel. Without a routing rule, no notification is ever delivered — there is no default fallback. Each rule maps one source to one or more notification channels.
- 1Add a source on the Sources page (e.g. a YouTube channel)
- 2Add a Discord channel on Channels → Notification tab and toggle it ON
- 3Go to Routing → click + Add Rule
- 4Select the source and the target channel(s) → Save
- 5Ensure the rule toggle is ON to activate delivery
| State | Behavior |
|---|---|
| ON | Rule is active. New content from the source is delivered to the mapped channel(s). |
| OFF | Rule is paused. Source is still monitored but no message is sent to Discord. Use this to temporarily mute a source without deleting the rule. |
Each routing rule has a Send Latest Post button. Clicking it fetches the most recent item from that source and delivers it immediately to the mapped channel(s) — identical to an automatic notification, including any configured ping role. The item is also marked as seen so the bot will not re-post it on the next check.
| Error | Reason | Fix |
|---|---|---|
| No targets found | Source has no enabled routing rule pointing to an active channel | Create or enable a routing rule and ensure the target channel is toggled ON |
| Channel not found | The mapped Discord channel was deleted from the server | Remove the rule, re-add the channel in Channels, and create a new rule |
| Missing permission: Send Messages | Bot does not have "Send Messages" in the target channel | Grant the bot that permission in Discord's channel settings |
Per-platform notification settings. Each platform has two fields:
| Field | What it does |
|---|---|
| Prefix Message | Text displayed above the embed in Discord when a notification is sent. Leave blank for no prefix text. |
| Ping Role | A Discord role that gets @mentioned alongside every notification for that platform. Members with this role receive a ping. Leave unset for silent delivery. |
How often (in minutes) the bot polls each platform for new content. Minimum 10 minutes per source — enforced server-side. Lower intervals are more real-time but increase API load.
Twitter/X is accessed via browser session cookies — no official API key. Three values are required: auth_token, ct0, and Bearer Token.
| Error | Reason | Fix |
|---|---|---|
| Cookie expired / 403 | Twitter invalidated the session. Happens every few weeks. | Open twitter.com → DevTools (F12) → Application → Cookies → copy fresh auth_token and ct0 |
| Validate: FAIL | Cookies are present but invalid or mismatched | Log out and back into twitter.com, then re-copy all three values |
Gmail uses OAuth2. Requires credentials.json (from Google Cloud Console) to be uploaded first. Each user then authorizes their Gmail account once via the dashboard popup. The token auto-refreshes.
| Error | Reason | Fix |
|---|---|---|
| credentials.json missing | Google OAuth2 app credentials have not been uploaded | Settings → Google Console → Upload File |
| Token expired / revoked | User revoked access in Google Account settings, or token is corrupt | Re-authorize via Settings → Gmail Authorization → Authorize Gmail |
| Popup blocked | Browser blocked the OAuth authorization popup | Allow popups for the dashboard domain in browser settings |
Export your entire config (sources, channels, routing, moderation) as a JSON file for backup or transfer. Import overwrites the current server config. Optionally include Twitter cookies in the export.
Twitch is accessed via the official Helix API. Two values are required: Client ID and Client Secret from a registered Twitch application.
- 1Go to dev.twitch.tv → Log in → Your Console
- 2Click Register Your Application → fill in name and redirect URI (any URL)
- 3Copy the generated Client ID and generate a Client Secret
- 4Paste both into Settings → Twitch Credentials → Validate Credentials
| Error | Reason | Fix |
|---|---|---|
| Validate: FAIL | Client ID or Secret is wrong or the app was deleted | Re-check dev.twitch.tv → regenerate Client Secret if needed |
| 401 Unauthorized | Access token request failed — credentials rejected by Twitch | Ensure the application is not deactivated on the Twitch developer console |
Override the bot's display name and avatar for your server. Changes take effect immediately in Discord.
| Field | Notes |
|---|---|
| Bot Name | Leave blank to use the global default name set by the admin |
| Avatar URL | Must be a direct image link (PNG, JPG). Leave blank to use the global default avatar. |
Define server rules as sections (header + content). The bot posts them to the #rules channel. The #rules channel must be enabled in Channels → New Member tab.
| Mode | Behavior |
|---|---|
| Embed (per section) | Each rule section is posted as a separate Discord embed message |
| Merged (single message) | All sections are combined into one embed |
An embed message sent automatically when a new member joins the server. Supports two placeholders: {user} mentions the new member, {server} inserts the server name.
| State | Behavior |
|---|---|
| #welcome ON | Welcome embed is sent to the dedicated #welcome channel inside the New Member category |
| #welcome OFF | Welcome embed falls back to Discord's default system channel (the server's built-in "system messages channel", usually general chat) |
| State | Behavior |
|---|---|
| Mention ON | Welcome message includes an @mention of the new member, sending them a notification |
| Mention OFF | Message is posted without pinging the new member |
Word and phrase rules that trigger automatic moderation actions when a member's message matches.
| Action | What happens |
|---|---|
| Warn | Bot sends a warning message in the channel; no role or permission change |
| Timeout | Member is server-muted for a configurable duration |
| Kick | Member is removed from the server (can rejoin) |
| Ban | Member is permanently banned (cannot rejoin unless unbanned) |
| State | Behavior |
|---|---|
| ON | Rule is active — matching messages trigger the configured action immediately |
| OFF | Rule is paused — matching messages pass through without any action |
| Error | Reason | Fix |
|---|---|---|
| Missing permission: Ban Members | Bot's role lacks the Ban permission in Discord | Server Settings → Roles → bot role → enable "Ban Members" |
| Missing permission: Kick Members | Same as above, for Kick | Grant "Kick Members" to the bot's role |
| Cannot timeout member above bot | Target member has a higher role than the bot in the role hierarchy | Move the bot's role above all member-facing roles in the Discord role list |
Customizes the modal fields shown when a member runs /submit. Up to 5 fields, each with a label, placeholder, and optional required toggle. Completed submissions are posted to #submissions (must be enabled in Channels → System tab).
Rate-limits message sending in specific channels. Certain roles can be exempt so moderators are never throttled.
| Condition | Behavior |
|---|---|
| No exempt roles configured | Uses Discord's native slowmode — enforced by Discord's own infrastructure |
| One or more exempt roles set | Bot-enforced slowmode — only members without an exempt role are rate-limited; exempt members post freely |
Discord resolves permissions from lowest to highest specificity. A more specific rule always wins.
| Level | Applies to | Can be overridden by |
|---|---|---|
| Category | All channels inside it (inherited) | Channel-level setting |
| Channel | That specific channel only | Role or Member override |
View all server roles, create new ones (name + color), or delete existing ones. Changes apply directly to Discord in real time.
Four sub-panels for controlling what roles and members can see or do:
| Sub-panel | What it controls |
|---|---|
| Default Visibility | Which categories newly created roles cannot see by default |
| Role Preset | Apply a server-wide permission level to a role (View-only / Standard / Moderator / Admin) |
| Role Channel Permission | Allow/Deny specific permissions on channels or categories for a role. Empty role = @everyone. Empty channel = server-wide. |
| Member Channel Permission | Same as Role Channel Permission but targets individual members |
Members gain or lose a role by reacting with an emoji to a bot message posted in #roles-picker.
- 1Roles → Button Roles → Emoji-Role Pairs → + Add Pair — map one emoji to one role
- 2Reaction Role Messages → + Create Message — group pairs into a message
- 3Click Post to #roles-picker
Restricts new members to the New Member category — only #roles-picker is accessible — until they react to pick a role. Once a role is chosen, they gain full server access.
| State | Behavior |
|---|---|
| ON | All new members are locked to #roles-picker on join. All other channels are inaccessible until a role is picked. |
| OFF | Members can access all channels they have permission for immediately after joining. No role requirement. |
| Error | Reason | Fix |
|---|---|---|
| No pairs selected | Role Gate has no role pairs — members have no buttons to click | Create emoji-role pairs first (Button Roles tab), then select them in Role Gate config |
| #roles-picker not enabled | Channel is OFF or was never created | Enable #roles-picker in Channels → New Member tab |
| Scenario | What happens |
|---|---|
| Gate post deleted in Discord | No roles are stripped. Members who already have the gate role keep it and retain their channel access. The stored message_id becomes orphaned — no new member can unlock until you re-post the gate message. |
| Swap both emoji and role (emoji A + role A → emoji B + role B) | Members who already have role A keep it — nothing strips it. Channel permission overwrites for role A are not removed (perm setup is additive only), so those members still see channels. New members must react with emoji B to get role B. |
| Change which role an emoji maps to (emoji A → role A becomes emoji A → role B) | Emoji A now only maps to role B in the config. New reactions grant role B. Members who previously got role A keep it as an orphaned leftover — it is never stripped. Channel access via role A's old overwrites also remains. |
| Change which emoji maps to a role (emoji A → role A becomes emoji B → role A) | Role A is now triggered by emoji B. Reactions on emoji B grant role A correctly. Old members who reacted with emoji A already have role A — nothing changes for them. New members must use emoji B. |
| Old gate role's channel overwrites after a swap | The old role's view_channel=True overwrites are never automatically removed. To clean up, manually remove the old role's channel overwrites in Discord server settings, or delete the role entirely. |
Restrict a role via Discord permission denies — applied as long as the role is assigned. Useful for a muted or punished role. Optional auto-timeout fires on role assign and clears on removal.
| Penalty | Effect |
|---|---|
| Cannot Send Messages | Read-only access to all channels |
| Cannot Attach Files | No image or file uploads |
| Cannot Post Links | No link embeds or previews |
| Cannot Add Reactions | Cannot react to any message |
| Cannot Use External Emoji | Only this server's own emoji are allowed |
| Auto-Timeout on Assign | Server-wide timeout (minutes) applied when role is assigned; 0 = disabled |
Grant a trusted role extra permissions that override default restrictions. Applied directly to the Discord role — enforced by Discord.
| Privilege | Effect |
|---|---|
| Bypass Slowmode | Can send messages freely regardless of any channel slowmode |
| Post Links | Link embeds and previews always allowed |
| Attach Files | Can upload images and files in any channel |
| Use External Emoji | Can use emoji from other Discord servers |
| Mention @everyone / @here | Can ping all members (use carefully) |
Notification Roles let members self-subscribe to @mention pings for specific content types (e.g. coupons, game updates). Members click a button in Discord to opt in or out — no commands needed.
| Step | What happens |
|---|---|
| 1. See panel in #roles-picker | Panel posted by admin with subscribe buttons |
| 2. Click a button | Bot gives them the notification role (ephemeral: 🔔 Subscribed) |
| 3. Bot posts notification | Bot @mentions the role → only subscribers get pinged |
| 4. Click again to unsubscribe | Role removed, no more pings (ephemeral: 🔕 Unsubscribed) |
| Step | Where |
|---|---|
| 1. Create Discord roles for notifications | Discord or Roles Manager |
| 2. Add emoji→role pairs in Button Roles tab | Roles → Button Roles |
| 3. Build a panel using those pairs as buttons | Roles → 🔔 Notif Roles → Create Panel |
| 4. Post the panel to #roles-picker | 📤 Post (auto-selects #roles-picker) |
| 5. (Optional) Set trigger words per button | Saved Panels → button row → trigger field → ✓ |
Each notification button can have an optional trigger word or emoji. When an admin or the bot posts a message containing that trigger, the bot replies and @mentions the subscribed role.
| Type | Matching rule | Example |
|---|---|---|
| Keyword | Case-insensitive substring — trigger appears anywhere in the message | Trigger: COUPON → matches "New COUPON code!" |
| Emoji | Exact match — the emoji must appear in the message | Trigger: 🎫 → matches "🎫 Redeem now" |
Notification roles must have zero channel permission overwrites. They are purely for @mentions — not for controlling access.
If a notification role has a deny overwrite on a channel, it will override the gate role's allow, and verified members who subscribe will lose channel access.
In Settings → Default Messages, each platform (YouTube, Steam, Twitter, etc.) has its own ping roles list. Every notification from that platform automatically @mentions the configured roles — no trigger word needed.
| Feature | When it pings | Who sets it up |
|---|---|---|
| Notif Role button | Only when a trigger word matches (optional) | Admin enters trigger per button |
| Per-source ping roles | Every single notification from that platform | Admin adds role in Settings → Default Messages |
All three tabs (Button Roles, Role Gate, Notification Roles) post to #roles-picker and store a message_id to track the live Discord message. The behavior differs per tab in edge cases.
| Tab | What "Edit/Save" does | How to push changes to Discord |
|---|---|---|
| ⚡ Button Roles | Updates saved data only — Discord message unchanged | Click Update Post to PATCH the live message in-place |
| 🚪 Role Gate | Updates config only — Discord message unchanged | Click Update Post to PATCH the live message in-place |
| 🔔 Notif Roles | Updates saved data only — Discord message unchanged | Click ✏ Edit Post to PATCH the live message in-place |
| Tab | What happens |
|---|---|
| ⚡ Button Roles | Stale message_id is auto-cleared next time the tab loads (404 check). "Update Post" will fail until cleared. Click 📤 Post to create a new message. |
| 🚪 Role Gate | Stale message_id is auto-cleared on every dashboard load (404 check). Re-post when ready. |
| 🔔 Notif Roles | No auto-check. If ✏ Update Post fails with a "Message was deleted" error, the stale reference is cleared automatically then. Click 📤 Post to create a new message. |
| Tab | What happens |
|---|---|
| ⚡ Button Roles | New message created, message_id updated. Old Discord message becomes an orphan — buttons on it are silently ignored by the bot. Delete the old message manually. |
| 🚪 Role Gate | Same — new message created, old message orphaned. Reactions on the old message are ignored. Delete it manually. |
| 🔔 Notif Roles | The old Discord message is automatically deleted before the new one is posted — no orphan left in the channel. |
| Tab | What happens |
|---|---|
| ⚡ Button Roles | Discord message stays. Reactions no longer assign roles (bot can't find the entry). Delete the Discord message manually to avoid confusion. |
| 🔔 Notif Roles | Discord message stays with working buttons — the bot resolves role from the button's custom_id regardless of whether a panel entry exists. Delete the Discord message manually before removing the panel. |
Slash commands available in Discord. Built-in commands cover bot status and moderation. Custom commands let you define your own keyword triggers.
| Command | What it does | Default permission |
|---|---|---|
| /status | Shows bot status and uptime | Any member |
| /submit | Opens the Form Builder modal for member submissions | Any member |
| /role | Assigns or removes a role from a member | Manage Roles |
| /kick | Kicks a member from the server | Kick Members |
| /ban | Permanently bans a member | Ban Members |
| /timeout | Temporarily mutes a member (Discord server timeout) | Moderate Members |
| /warn | Issues a formal warning to a member | Kick Members |
| /reddit_update | Manually refreshes score and comment counts on all Reddit embeds posted in the last 7 days | Administrator |
| /anon | Sends a message anonymously to the current channel — bot deletes the original and reposts it as 💬 Anonymous. Real identity is logged in #anonymous-log. | Any member (if anonymous is enabled) |
| /embed <url> [note] | Posts a rich embed for any URL. Twitter/X uses the API (full author + text); YouTube falls back to a plain link so Discord renders the native player; all others use Open Graph tags (title, description, image). Optional note appears above the embed. | Any member |
| — Ticketing — | ||
| /ticket panel | Posts the Open Ticket embed + button in this channel. Members click it to open a ticket. | Manage Channels |
| /ticket close [reason] | Closes the current ticket — saves full transcript, posts to log channel, deletes channel after 5 s. | Ticket opener or Manage Channels |
| /ticket claim | Claims (or releases) the current ticket. Claimer is recorded in the close log embed. | Support role or Manage Channels |
| /ticket add <user> | Grants a member view + send access to the current ticket channel. | Manage Channels |
| /ticket remove <user> | Revokes a member's access. Cannot remove the ticket opener. | Manage Channels |
Override the default Discord permission with a specific role requirement. If set, only members with that role can run the command, regardless of their native Discord permissions.
| State | Behavior |
|---|---|
| No role set | Discord's own permission system applies (e.g. /kick requires "Kick Members") |
| Role set | Only members with the specified role can run the command. Native Discord permissions are bypassed. |
Create your own slash commands with a custom name and a bot response (plain text or embed). Useful for FAQs, server info, or pinned announcements triggered on demand.
| Error | Reason | Fix |
|---|---|---|
| Missing applications.commands scope | Bot was not invited with the slash commands OAuth scope | Re-invite the bot including the applications.commands scope |
| Unknown command | A new command was added but not yet synced to Discord | Wait for the next bot restart — commands sync on startup. Contact the bot admin if it persists. |
| Missing permissions | Bot lacks the Discord permission required for the action | Review the bot's role permissions in Discord Server Settings → Roles |
Two log streams — Bot activity and Dashboard changes — displayed in a real-time viewer with level filters and date navigation.
| Filter | What it shows |
|---|---|
| All | Every log entry without filtering |
| Info | Bot startup events, task lifecycle, general status messages |
| Posts | Notifications successfully delivered to Discord (one entry per delivery) |
| Error | Failed fetches, authentication errors, missing permissions, unhandled exceptions |
Records every configuration change made through the dashboard (who changed what and when). Kept forever — never rotated or deleted.
Bot logs rotate daily. The date picker shows up to the last 7 days of history. Logs older than 7 days are automatically deleted. "Today" always points to the current live log file.
| Action | Behavior |
|---|---|
| ↺ Refresh | Fetches the latest entries from the server immediately |
| Clear View | Clears the displayed log in your browser only — the log file on disk is not affected |
Community profile cards for your server members. Each member registers a profile with stats, collection info, and a customizable Armory — rendered as a Pillow-generated PNG card. Achievements are auto-assigned based on activity milestones.
| Command | Who can use | What it does |
|---|---|---|
| /card register | Any member | Opens a template in chat. Member fills it in and sends it back. Bot parses, validates, saves, and renders the profile card. |
| /card edit | Any member with a profile | Same template flow as register — pre-fills existing values for editing. |
| /card profile [user] | Any member | Displays the profile card for the specified user, or the caller's own card if no user is provided. |
| /card delete | Any member with a profile | Permanently deletes the caller's profile. |
| /card badges | Any member with a profile | Shows the caller's current achievement badge slots and progress toward locked achievements. |
Right-click any member → Apps → View Profile Card — delivers their card as an ephemeral message visible only to you.
If a commands channel is set in Card → Settings, all /card commands only work in that channel. Members attempting to use them elsewhere get a silent ephemeral error.
Browse all registered member profiles for the selected server. The count is shown next to the tab label.
Runs the achievement evaluation logic across every profile in the server. Useful after adding new achievement definitions or changing thresholds — auto-assigns the best earned badge to each empty slot without waiting for the daily loop.
Define the achievement badges members can earn. Each achievement has a condition type and a threshold value. Achievements are evaluated on profile save, on the daily midnight loop, and when "↻ Re-check All" is triggered.
| Condition | Triggers when |
|---|---|
| Total Logins | Member's cumulative login count reaches the threshold |
| Login Streak | Member's consecutive daily login streak reaches the threshold |
| Stars | Member's star count (profile field) reaches the threshold |
| Col. Taimanin (X/Y) | Member's Taimanin collection count reaches the threshold |
| Server Booster | Member is actively boosting the server (no threshold — binary) |
Each profile has 6 badge slots mapped to these condition categories: server_booster · logins · streak · stars · collection · undecided. When multiple achievements qualify for the same slot, the one with the highest threshold value is used.
Customize the fields shown in the template members fill in during /card register and /card edit. Toggle individual fields off to hide them from the template.
| Setting | Behavior |
|---|---|
| Enable Profile Card System | When OFF, all /card commands return an error to the member. Existing profiles are preserved on disk — nothing is deleted. |
| Commands Channel | If set, /card commands are restricted to this channel. Leave unset to allow commands in any channel. |
Sets the denominator for the collection progress bar on the profile card. For example, if Taimanin max is 42, a member with 20 shows 20/42. Used for display only — does not gate registration.
Toggle individual /card sub-commands on or off globally. Disabled commands return an error to members — useful for temporarily locking registration while migrating data.
| Command | Toggle OFF effect |
|---|---|
| /card register | New members cannot register profiles |
| /card edit | Existing members cannot update their profile |
| /card profile | No one can view profile cards via slash command |
| /card delete | Members cannot delete their own profile |
| View Profile Card (right-click) | The context menu App entry is disabled — right-clicking a member no longer shows it |
Every midnight (server local time) the bot increments total_logins +1 and login_streak +1 for every registered profile. If a full day was missed (the last loop ran more than ~24 h ago), the streak resets to 1.
After incrementing stats, the daily loop re-evaluates all achievement conditions for every profile and auto-assigns newly earned badges — same logic as "↻ Re-check All" in the dashboard.
An escrow system that runs entirely inside Discord. Any server member initiates a trade by calling /mm_rmt, selects the buyer, seller, and middleman, and the bot creates a private thread for all three parties. The bot DMs the buyer with payment instructions and the seller requesting their bank details. All confirmation flow happens through buttons inside the thread.
| Command | Who | What it does |
|---|---|---|
| /mm_rmt | Any member (allowed channels only) | Opens an escrow. Parameters: @buyer, @seller, @middleman, amount (IDR), description. |
| /mm_dispute | Buyer or seller (inside thread) | Raises a dispute, locks the thread, and pings the middleman. |
The middleman provides static bank/e-wallet details or a static QRIS image URL. Payment transfer and fund forwarding are done manually by the middleman.
- Bot DMs buyer with the middleman's bank account or QRIS.
- Bot DMs seller asking for their bank/e-wallet receiving details.
- Buyer transfers money to middleman, then clicks Payment Sent to Middleman.
- Middleman verifies receipt, then clicks Forward Payment to Seller.
- Seller receives funds, then clicks Payment Received from Middleman.
- All three parties click Close Transaction → thread archived.
1 hour. If the buyer does not confirm payment before expiry, the transaction is marked expired and the thread is archived automatically.
The middleman configures a Xendit or Flip API key (per middleman, not shared). The bot generates a dynamic QRIS or Virtual Account and sends it to the buyer. Webhook callbacks auto-detect payment receipt.
- Bot generates QRIS/VA via API and DMs the buyer.
- Bot DMs seller asking for their bank/e-wallet receiving details.
- Xendit/Flip webhook fires → bot auto-announces payment confirmed in thread.
- Buyer and Middleman both click Forward Payment to Seller to release funds.
- Bot calls the disbursement API automatically if amount < configured threshold. Otherwise, admin clicks Disburse in dashboard.
- Seller + buyer click Transaction Complete → thread archived.
24 hours from transaction creation.
Configurable per middleman. Transactions below the threshold are disbursed automatically via API. Those at or above the threshold are flagged pending_disbursement and require admin approval in the Transactions tab.
Select which channels allow /mm_rmt. Leave empty to allow the command everywhere.
Copy these URLs into your Xendit or Flip dashboard as the callback/webhook URL. Requires WEBHOOK_BASE_URL to be set in .env.
Add any server member as a middleman. Per-middleman settings:
| Setting | Description |
|---|---|
| Mode | Manual (static bank/QRIS) or Automatic (Xendit/Flip API) |
| Bank / QRIS | Manual only: bank name, account number, account name, or a static QRIS image URL |
| Provider & API Keys | Auto only: Xendit or Flip; separate payment key and disbursement key |
| Payment Method | Auto only: QRIS (QR image sent to buyer) or Virtual Account |
| Fee Type / Value | Flat IDR amount or percentage — added to buyer's total |
| Auto-disburse | Whether to call disbursement API automatically vs. wait for admin approval |
| Threshold (IDR) | Amounts below this are auto-disbursed; at or above require admin click |
View all escrow transactions for the selected server. Filter by status. Click any row to see full detail (bank info, confirmation flags, disbursement ID).
| Status | Meaning |
|---|---|
| pending_payment | Waiting for buyer to pay the middleman |
| payment_confirmed | Payment received (webhook) or buyer confirmed (manual) |
| pending_disbursement | Both parties clicked Forward; amount ≥ threshold — admin must click Disburse |
| disbursed | Funds sent to seller (API or manual) |
| completed | All required parties clicked Close — thread archived |
| disputed | Dispute raised — thread locked, awaiting admin resolution |
| expired | Timer elapsed before payment was confirmed |
| cancelled | Dispute resolved with Refund Buyer outcome |
Appears on pending_disbursement rows. For automatic mode, calls the Xendit/Flip disbursement API using the seller's bank details captured via DM. For manual mode, simply marks the transaction as disbursed (admin did it physically).
Click Resolve on a disputed transaction. Choose Refund Buyer (cancels transaction) or Pay Seller (moves to pending_disbursement for manual disburse). Does not move funds automatically — admin must handle the actual transfer for refunds.
Discord-native support ticket system. Each ticket is a private text channel under a "Tickets" category, visible only to the opener, configured support roles, and the bot. Configured in the Ticketing dashboard page — no JSON editing required.
| Command | Who can use | What it does |
|---|---|---|
| /ticket panel | Manage Channels | Posts the Open Ticket embed + button in the current channel. Members click it to open a ticket. |
| /ticket close [reason] | Ticket opener or Manage Channels | Saves full transcript, logs it to the log channel, then deletes the channel after 5 seconds. |
| /ticket claim | Support role or Manage Channels | Claims (or releases) this ticket. The claimer is recorded in the close log. Also available as the Claim button in the ticket channel. |
| /ticket add <user> | Manage Channels | Grants a user view + send access to the current ticket channel. |
| /ticket remove <user> | Manage Channels | Revokes a user's access. Cannot remove the ticket opener. |
Member clicks Open Ticket → modal asks for a subject → bot creates a private channel → welcome embed + Close Ticket and Claim buttons posted. Support roles are pinged in the same message (configurable).
Full transcript (no limit). Posted to the log channel as a code block (≤1900 chars) or a .txt file. Close embed includes: subject, opener, closer, claimer, message count, open time, and optional reason.
Set auto_close_hours > 0. The bot checks every 30 minutes using Discord snowflake timestamps (no extra API calls). At hours − 1, it warns the opener; at hours it closes automatically.
| Field | Default | Effect |
|---|---|---|
| enabled | false | Feature toggle — must be true for the Open Ticket button to work |
| support_role_ids | [] | Roles that get view + manage_messages on every ticket and can claim tickets |
| category_id | null | Category to create tickets under; auto-creates "Tickets" if not set |
| log_channel_id | null | Channel where closed-ticket transcripts are posted |
| max_open_per_user | 1 | How many open tickets a single member can have at once |
| ticket_prefix | "ticket" | Channel name prefix (e.g. "ticket-0001") |
| ping_support_on_open | true | Whether to @ping support roles when a ticket is opened |
| auto_close_hours | 0 | Hours of inactivity before auto-close; 0 = disabled |
Post a plain-text message to any Discord channel on a schedule. The bot checks every 60 seconds for due schedules across all guilds.
| Type | When it fires | After firing |
|---|---|---|
| once | At the specified date/time (ISO format) | Auto-disabled — will not fire again |
| daily | Every day at the specified HH:MM (server local time) | Repeats indefinitely |
| weekly | On selected weekdays at the specified HH:MM (server local time) | Repeats on those days |
Each schedule stores a last_run timestamp. Daily and weekly schedules will not fire more than once per calendar day, regardless of bot restarts.