OreoBot Wiki
A feature-rich Discord bot written in Go. This guide covers everything from first-time setup to every command available.
Requirements
Before running OreoBot, make sure you have the following installed and configured:
| Requirement | Notes |
|---|---|
Go 1.21+ | The language OreoBot is built with |
| Discord Bot Token | Create one at discord.com/developers |
| SQLite (default) or MongoDB | For storing warnings, mod cases, etc. SQLite works out of the box |
ffmpeg | Only needed with the direct music backend |
yt-dlp | Only needed with the direct music backend |
| Lavalink server | Only needed with the lavalink music backend |
| Minecraft + RCON | Only needed for /mc commands |
First-Time Setup
Go to discord.com/developers/applications → New Application. Under the Bot tab, click Add Bot.
Enable these Privileged Gateway Intents:
- Server Members Intent — required for welcome/leave & auto-role
- Message Content Intent — required for auto-moderation
Copy your Bot Token — you'll need it in config.json.
Go to OAuth2 → URL Generator, select scopes bot + applications.commands, then invite the bot with at minimum: Manage Roles, Manage Channels, Kick, Ban, Moderate Members, Send Messages, Embed Links, Read History, Connect, Speak.
Copy the example config and fill in your values:
cp config.example.json config.json
See the config.json reference for a full explanation of every field.
go build -o oreobot . ./oreobot # Or run directly: go run .
The bot registers all slash commands with Discord on startup. In a new server it can take up to 1 minute to appear — set guild_id for instant registration.
Running the Bot
On startup OreoBot performs the following in order:
Loads config.json → lang.yml → initializes database (SQLite/MongoDB)
Connects to Minecraft RCON (if enabled) → starts music system (if enabled)
Logs in → registers slash commands → restores active giveaway timers
Starts Minecraft link polling (if enabled)
guild_id in config.json makes them appear instantly in that server.
config.json — Full Reference
Every field in config.json is annotated below.
Discord
"discord": {
"token": "YOUR_BOT_TOKEN_HERE", // Bot token from Developer Portal
"guild_id": "YOUR_GUILD_ID", // Right-click server → Copy Server ID
"prefix": "!" // Unused — bot uses slash commands only
}
Database
"database": {
"driver": "sqlite", // "sqlite" or "mongodb"
"sqlite": {
"path": "data/bot.db" // Auto-created on first run
},
"mongodb": {
"uri": "mongodb://localhost:27017",
"database": "discord_bot"
}
}
Permissions
"permissions": {
"admin_roles": ["Admin", "Owner"], // Can use admin commands
"moderator_roles": ["Moderator", "Mod"], // Can use mod commands
"dj_roles": ["DJ", "Music"] // Can control music
}
Music
"music": {
"enabled": true,
"backend": "lavalink", // "direct" or "lavalink"
"max_queue_size": 100,
"max_song_duration": 600, // seconds (0 = no limit)
"allow_playlists": true,
"default_volume": 50,
"direct": {
"ytdlp_path": "./yt-dlp",
"ffmpeg_path": "ffmpeg"
},
"lavalink": {
"host": "localhost",
"port": 2333,
"password": "youshallnotpass",
"secure": false
}
}
Minecraft
"minecraft": {
"enabled": false,
"rcon_ip": "localhost",
"rcon_port": 25575,
"rcon_password": "your_rcon_password",
"link_backend": "file" // "file" or "mongodb"
}
Welcome / Leave
"welcome": {
"enabled": true,
"channel_id": "CHANNEL_ID",
"embed": {
"colour": "#f74343",
"title": "Welcome to Our Server!",
"message": "Welcome %joined_user%! Glad to have you here.",
"thumbnail": "USER", // "BOT", "USER", or any image URL
"image_enabled": false,
"image_url": ""
}
}
The leave block has the exact same structure.
Tickets
"tickets": {
"enabled": true,
"panel_channel": "CHANNEL_ID",
"log_channel": "CHANNEL_ID",
"staff_roles": "ROLE_ID_1,ROLE_ID_2",
"discord_category": "CATEGORY_ID",
"max_open_per_user": 3,
"categories": [
{
"id": "support",
"name": "Support",
"emoji": "🛠️",
"description": "Get help with any issue",
"staff_role": "ROLE_ID",
"subcategories": [
{ "id": "bug", "name": "Bug Report", "emoji": "🐛", "description": "Report a bug" }
]
}
]
}
Auto-Mod
"moderation": {
"mod_log_channel": "CHANNEL_ID",
"auto_mod": {
"enabled": true,
"max_mentions": 5,
"max_lines": 30,
"anti_spam_seconds": 5,
"anti_spam_count": 5
}
}
Chat Bridge
"chat_bridge": {
"enabled": true,
"rabbitmq_uri": "amqp://user:password@host:5672/%2F",
"channel_id": "DISCORD_CHANNEL_ID",
"mc_channel_id": "global", // OreoEssentials channel (global / local / trade / staff / help / announcements)
"ban_sync": false, // Sync Discord bans → Minecraft bans via RCON
"mod_sync": false // Sync Discord /mute → Minecraft MuteService via RabbitMQ
}
No-Ping
"no_ping": {
"enabled": true,
"protected_roles": ["ROLE_ID_1", "ROLE_ID_2"], // Role IDs (right-click role → Copy ID)
"message": "{user} You are not allowed to ping **{role}**!",
"delete_message": true
}
Counting Game
"counting_game": {
"enabled": true,
"channel_id": "COUNTING_CHANNEL_ID",
"fail_resets": true, // Reset to 0 on wrong number
"delete_wrong": true, // Delete wrong numbers
"delete_non_numbers": true // Delete non-number messages
}
Custom Commands
"custom_commands": [
{
"name": "rules",
"description": "Server rules",
"message": "**Rules:**\n1. Be respectful\n2. No spam",
"ephemeral": true
}
]
lang.yml — Language Settings
All bot messages are defined in lang.yml. Open it and change the first line to switch languages:
# Options: "en" (English) or "fr" (French) active_language: en
| Code | Language |
|---|---|
en | English |
fr | French |
Permission System
OreoBot uses a layered permission system:
| Level | Who has it | How it's determined |
|---|---|---|
| Admin | Server owners + members with roles in admin_roles | Role name match |
| Moderator | Members with roles in moderator_roles OR Discord "Ban Members" permission | Role name or Discord permission |
| DJ | Members with roles in dj_roles | Role name match |
| Everyone | All server members | — |
Commands — Moderation
All moderation commands require Moderator or Admin unless noted.
| Option | Required | Description |
|---|---|---|
user | Required | The member to ban |
reason | Optional | Reason for the ban |
delete_days | Optional | Days of messages to delete (0–7) |
| Option | Required | Description |
|---|---|---|
user_id | Required | The Discord user ID of the banned user |
reason | Optional | Reason for unbanning |
| Option | Required | Description |
|---|---|---|
user | Required | The member to kick |
reason | Optional | Reason for the kick |
| Option | Required | Description |
|---|---|---|
user | Required | The member to mute |
duration | Required | 10m, 2h, 1d, 7d … |
reason | Optional | Reason |
| Option | Required | Description |
|---|---|---|
user | Required | The member to unmute |
| Option | Required | Description |
|---|---|---|
user | Required | The member to warn |
reason | Required | Reason for the warning |
| Option | Required | Description |
|---|---|---|
user | Required | The member whose warnings to view |
| Option | Required | Description |
|---|---|---|
user | Required | The member to clear warnings for |
| Option | Required | Description |
|---|---|---|
count | Required | Number of messages to delete (1–100) |
user | Optional | Only delete messages from this user |
| Option | Required | Description |
|---|---|---|
seconds | Required | Delay in seconds (0 disables, max 21600) |
| Option | Required | Description |
|---|---|---|
channel | Required | The channel to use as the mod log |
| Option | Required | Description |
|---|---|---|
user | Optional | The member to look up (defaults to yourself) |
Commands — Ticket System
Initial Setup
Set tickets.enabled to true in config.json and fill in panel_channel, log_channel, staff_roles, discord_category.
Add your categories in the categories array, or use /ticket addcategory at runtime.
Run /ticket panel to post the ticket creation panel in the configured channel.
Commands
| Option | Required | Description |
|---|---|---|
panel_channel | Required | Channel for the ticket panel |
log_channel | Required | Channel for ticket logs |
staff_role | Required | Role that can manage all tickets |
category | Required | Discord category for ticket channels |
max_per_user | Optional | Max open tickets per user (default: 3) |
/ticket panel after adding.| Option | Required | Description |
|---|---|---|
id | Required | Unique ID (no spaces) |
name | Required | Display name |
emoji | Required | Emoji next to the name |
description | Required | Short description |
staff_role | Optional | Role ID specific to this category |
/ticket addcategory can be removed this way.| Option | Required | Description |
|---|---|---|
id | Required | The category ID to remove |
| Option | Required | Description |
|---|---|---|
parent_id | Required | ID of the parent category |
id | Required | Unique ID for the subcategory |
name | Required | Display name |
emoji | Required | Emoji |
description | Required | Short description |
| Option | Required | Description |
|---|---|---|
user | Required | The member to add |
| Option | Required | Description |
|---|---|---|
user | Required | The member to remove |
Commands — Auto-Role
Automatically assign a role to every new member when they join.
| Option | Required | Description |
|---|---|---|
role | Required | The role to assign |
Commands — Giveaways
Run giveaways with automatic timer, random winner selection, and reroll support. Giveaway timers survive bot restarts.
| Option | Required | Description |
|---|---|---|
prize | Required | What you're giving away |
duration | Required | 10m, 2h, 1d, 7d |
winners | Required | How many winners to pick |
channel | Optional | Channel to post in (defaults to current) |
| Option | Required | Description |
|---|---|---|
giveaway_id | Required | ID of the giveaway |
| Option | Required | Description |
|---|---|---|
giveaway_id | Required | ID of the ended giveaway |
Commands — Music
Play music in voice channels. Requires music.enabled: true in config.json. Music controls require a DJ role.
Direct Backend
Requires yt-dlp + ffmpeg installed locally. Easy setup, good for small bots.
Lavalink Backend
Connects to a Lavalink server. Recommended for stability and larger bots. Requires extra server setup.
| Option | Required | Description |
|---|---|---|
query | Required | Song name or YouTube URL |
| Option | Required | Description |
|---|---|---|
level | Required | Volume from 0 to 100 |
Commands — Minecraft Integration
Connect your Discord server to a Minecraft server via RCON.
Setup
In your Minecraft server.properties:
enable-rcon=true rcon.port=25575 rcon.password=your_password
In config.json:
"minecraft": {
"enabled": true,
"rcon_ip": "your.server.ip",
"rcon_port": 25575,
"rcon_password": "your_password"
}
| Option | Required | Description |
|---|---|---|
command | Required | The command to run (without the /) |
| Option | Required | Description |
|---|---|---|
action | Required | add or remove |
player | Required | Minecraft username |
| Option | Required | Description |
|---|---|---|
user | Optional | View another member's profile (Admin only) |
OreoEssentials Plugin
OreoEssentials is a companion Minecraft plugin that extends OreoBot's Minecraft integration. It must be installed on your Minecraft server to enable account linking and live player-data lookups.
How the bridge works
When a user runs a bot command that needs Minecraft data (like /mc profile), OreoBot sends a special RCON command to your server. OreoEssentials intercepts that command, reads the requested data (balance, homes, online status…), and replies through the RCON response. OreoBot then formats the reply and posts it as a Discord embed.
Discord side — OreoBot
Receives slash command → sends oe-discord <sub> <uuid> via RCON → parses response → posts embed to Discord
Minecraft side — OreoEssentials
Registers the oe-discord command → reads economy / homes / online data → replies with a one-line OK: … or ERR: … string
Account linking system
The linking flow is a two-step handshake between Discord and Minecraft. OreoEssentials owns the in-game half; OreoBot owns the Discord half.
/mc link in Discord
OreoBot generates a short 6-character code, saves a pending entry (Discord ID + expiry), and DMs the code to the user. The code expires in 10 minutes.
/discord link <code> in Minecraft
OreoEssentials' DiscordLinkCommand receives the code, calls DiscordLinkManager.confirmLink(), validates the pending file/document, and writes a confirmed link entry (Discord ID ↔ UUID ↔ username). If the code doesn't exist or is expired, the player gets a clear error message.
OreoBot detects the confirmed entry on its next polling cycle (≤ 15 seconds) and updates the Discord member's nickname and linked role automatically.
In-game command — /discord
OreoEssentials registers the /discord command for players inside Minecraft:
Link storage backend — config.yml
OreoEssentials stores pending and confirmed link data. The backend is configured in OreoEssentials' config.yml:
discord: link_backend: "file" # "file" (default) or "mongodb" for cross-network
| Value | Storage location | Best for |
|---|---|---|
"file" |
data/mc_links/pending/ — one .json file per code |
Single-server setups, no extra dependencies |
"mongodb" |
Collections: discord_link_pending, discord_link_confirmed, discord_links |
Multi-server / BungeeCord networks sharing one database |
config.json has its own minecraft.link_backend setting — keep it in sync with OreoEssentials' config.yml so both sides read from the same store.
RCON extension commands (oe-discord)
These are server-side-only commands registered by DiscordRconExtension. They are called automatically by OreoBot over RCON — players cannot run them. Each returns a one-line OK: … result or ERR: … on failure.
| RCON command | Returns | Used by |
|---|---|---|
oe-discord balance <uuid> |
Player's economy balance (e.g. OK: 1,250) |
/mc profile |
oe-discord homes <uuid> |
Comma-separated list of name@server (e.g. OK: base@survival,farm@survival) |
/mc profile |
oe-discord online <uuid> |
OK: ONLINE <name> or OK: OFFLINE <name> LASTSEEN <epoch> |
/mc profile |
oe-discord inventory <uuid> |
Top 12 items by quantity (e.g. OK: Diamond x64, Iron Ingot x32) |
Future — reserved for /mc inventory |
inventory sub-command works even for offline players — OreoEssentials reads the last saved inventory snapshot via InventoryService if the player is not currently online.
What REQUIRES OreoEssentials
/mc profile — balance
Shows *(fetch failed)* without the plugin
/mc profile — homes
Shows *(no data)* without the plugin
/mc profile — online status
Shows *(fetch failed)* without the plugin
Account linking
/discord link in-game requires the plugin to be present on the server
Link status check
/discord status in-game requires the plugin
Inventory lookup
Future /mc inventory support via oe-discord inventory
What works WITHOUT OreoEssentials
Everything that doesn't require live player data or in-game linking still works normally:
- Check server status —
/mc status - List online players —
/mc players - Run RCON commands —
/mc command - Manage the whitelist —
/mc whitelist - Broadcast messages in-game —
/mc say
/mc link in Discord will generate a code but users will have no way to confirm it in-game — the /discord link command won't exist on the server.
Commands — Utility
/mc say instead.
| Option | Required | Description |
|---|---|---|
channel | Required | The Discord channel to send the message in |
message | Required | The message text (use \n for line breaks) |
/say — it sends to the in-game chat, not to Discord.[Discord] YourUsername: your message
| Option | Required | Description |
|---|---|---|
message | Required | The message to broadcast in-game |
Requires Minecraft integration to be enabled in config.json.
| Option | Required | Description |
|---|---|---|
channel | Required | Channel to send the embed in |
title | Required | Embed title |
description | Required | Embed body text (use \n for line breaks) |
colour | Optional | Hex color code (e.g. #ff0000) |
image | Optional | URL of a large image shown at the bottom |
thumbnail | Optional | URL of a small image in the top right corner |
footer | Optional | Footer text |
author | Optional | Author name shown at the top of the embed |
author-icon | Optional | URL of a small icon shown next to the author name |
url | Optional | URL that the embed title links to when clicked |
Commands — Custom Commands
Define your own slash commands that reply with a fixed message. They appear alongside all built-in commands and are registered with Discord automatically on every startup.
Configuration
"custom_commands": [
{
"name": "rules", // Slash command name — users type /rules
"description": "Server rules",
"message": "**Rules:**\n1. Be respectful\n2. No spam",
"ephemeral": true // true = only the caller sees the reply
},
{
"name": "discord",
"description": "Join our Discord",
"message": "Join us at: https://discord.gg/example",
"ephemeral": false // false = reply visible to the whole channel
}
]
| Field | Type | Description |
|---|---|---|
name | string | The slash command name (lowercase, no spaces). Users type /name to trigger it. |
description | string | Short description shown in the Discord command picker. |
message | string | The reply message. Supports Discord markdown. Use \n for line breaks. |
ephemeral | bool | true — only the user who ran the command sees the reply. false — visible to everyone in the channel. |
ban, play, ticket, etc. Conflicting names will be silently overridden by the built-in handler.
Chat Bridge — Discord ↔ Minecraft
The Chat Bridge creates a live, bidirectional link between a Discord text channel and your Minecraft server's chat. Messages sent in the Discord channel appear in Minecraft, and Minecraft chat appears in Discord — in real time, over RabbitMQ.
How it works
Discord → Minecraft
A linked Discord user sends a message in the bridge channel → OreoBot publishes a CHANMSG payload to the chat_sync RabbitMQ fanout exchange → OreoEssentials receives it and routes it to the configured Minecraft channel (e.g. global). The message appears in-game as [Discord] PlayerName: text.
Minecraft → Discord
A player chats in-game → OreoEssentials publishes a CHANMSG payload to the chat_sync exchange → OreoBot receives it, resolves the player's linked Discord account (if any), and posts the message to the bridge channel as PlayerName (@mention): text.
Configuration — config.json
"chat_bridge": {
"enabled": true,
"rabbitmq_uri": "amqp://user:password@your-server:5672/%2F",
"channel_id": "YOUR_DISCORD_CHANNEL_ID", // The Discord channel used for the bridge
"mc_channel_id": "global", // OreoEssentials channel name (see table below)
"ban_sync": false, // true = Discord ban → Minecraft ban via RCON
"mod_sync": false // true = Discord /mute → Minecraft mute via RabbitMQ
}
| Field | Description |
|---|---|
rabbitmq_uri | AMQP connection URI for your RabbitMQ server. Format: amqp://user:pass@host:port/vhost. The default vhost %2F represents /. |
channel_id | Discord channel ID where bridged messages are posted and read from. Right-click the channel → Copy Channel ID. |
mc_channel_id | The OreoEssentials channel name to route messages to/from. Must match a channel ID defined in OreoEssentials' config.yml. Set to "global" for the default channel. This field is required for Discord→Minecraft to work when the OreoEssentials channel system is enabled. Leaving it empty causes the bot to send legacy-format messages that OreoEssentials ignores. |
ban_sync | When true, banning a linked user from Discord automatically bans their Minecraft account via RCON (ban username Banned from Discord). Lifting the Discord ban also pardons them in Minecraft. |
mod_sync | When true, using /mute on a linked Discord user publishes a CTRL;;MUTE control packet to RabbitMQ. OreoEssentials' MuteService receives it and applies the mute in-game. /unmute publishes CTRL;;UNMUTE to lift it. |
OreoEssentials Channels — mc_channel_id values
OreoEssentials' channel system separates different types of in-game chat. The mc_channel_id in your bot config must exactly match one of the channel IDs configured in OreoEssentials' config.yml. The default channels are:
| Channel ID | Who can see it | Typical use |
|---|---|---|
global ⭐ | All players on all connected servers (cross-server) | General chat — recommended for the bridge |
local | Players within a configurable radius | Proximity / area chat |
trade | All players | Buying and selling |
staff | Staff-permission players only | Internal staff communication |
help | All players | Player questions and support |
announcements | All players (read-only for non-staff) | Server announcements |
mc_channel_id to "global". It is the default OreoEssentials channel, cross-server, and reaches every online player.
OreoEssentials — Required config.yml Changes
For the chat bridge to work end-to-end, OreoEssentials' config.yml must match the bot config on two critical points:
# OreoEssentials config.yml — chat bridge relevant settings
discord:
link_backend: "mongodb" # MUST match minecraft.link_backend in bot config.json
# "mongodb" → shared MongoDB store (works across servers)
# "file" → local JSON files (single-server only)
chat_sync:
enabled: true
rabbitmq_uri: "amqp://user:password@your-server:5672/%2F" # Identical to bot config
channels:
- id: "global"
name: "Global"
default: true
cross_server: true
- id: "local"
name: "Local"
radius: 100
- id: "trade"
name: "Trade"
- id: "staff"
name: "Staff"
staff_only: true
- id: "help"
name: "Help"
- id: "announcements"
name: "Announcements"
default_channel: "global"
rabbitmq_uri must be identical in the bot's config.json and in OreoEssentials' config.yml. Both sides subscribe/publish to the same chat_sync fanout exchange.
discord.link_backend in OreoEssentials must match minecraft.link_backend in the bot's config.json. A mismatch causes "Invalid or Expired Code" errors when players try to link their accounts — the two sides look in different data stores and can never see each other's codes.
Ban & Mod Sync
Ban Sync (ban_sync: true)
When a linked user is banned from Discord, OreoBot automatically runs ban <username> Banned from Discord via RCON. Lifting the Discord ban also pardons them with pardon <username>. Requires Minecraft RCON to be configured and connected.
Mod Sync (mod_sync: true)
When /mute is used on a linked Discord user, OreoBot publishes CTRL;;MUTE;;DISCORD;;uuid;;expiryMs;;b64(reason);;b64(by) to RabbitMQ. All connected Minecraft servers running OreoEssentials receive it and mute the player. /unmute publishes CTRL;;UNMUTE to remove it.
Message Format
| Direction | Appears as |
|---|---|
| Discord → Minecraft | [Discord] PlayerName: message text |
| Minecraft → Discord | PlayerName (@DiscordUser if linked): message text |
The Discord @mention only appears next to the player name if the Minecraft player has a linked Discord account.
Troubleshooting the Bridge
- Ensure
mc_channel_idis set to a real OreoEssentials channel name (e.g."global") — an empty value sends legacy format which OreoEssentials ignores when its channel system is active. - Verify your Discord account is linked (
/mc link). Only linked accounts can bridge to Minecraft. - Make sure
discord.link_backendin OreoEssentials matchesminecraft.link_backendin bot config.
- Check that OreoEssentials has
chat_sync.enabled: trueand the same RabbitMQ URI. - Look for
[ChatBridge] Sub connect errorin the bot logs — it retries every 5 seconds. - If OreoEssentials previously used a durable
chat_syncexchange, delete it from RabbitMQ management and restart both sides.
No-Ping Protection
Automatically detect and delete messages that ping a protected role, then post a warning. Useful for protecting Admin, VIP, or any sensitive role from unsolicited @mentions.
Configuration
"no_ping": {
"enabled": true,
"protected_roles": ["ROLE_ID_1", "ROLE_ID_2"], // Role IDs, NOT role names
"message": "{user} You are not allowed to ping **{role}**!",
"delete_message": true // true = also delete the offending message
}
| Field | Description |
|---|---|
protected_roles | Array of role IDs (not role names) that cannot be pinged. Multiple IDs are supported. Enable Discord Developer Mode to copy role IDs. |
message | Warning message sent to the channel when a protected role is pinged. Placeholders: {user} = mention of the offending user, {role} = name of the pinged role. |
delete_message | true — the offending message is deleted before the warning is posted. false — only the warning is sent, the message stays. |
How to get a Role ID
Go to Discord User Settings → Advanced → toggle on Developer Mode.
Go to Server Settings → Roles → right-click the role you want to protect → Copy Role ID. Paste it into the protected_roles array in your config.
protected_roles array. The bot checks all of them on every message in every channel.
Counting Game
Turn a dedicated channel into a collaborative counting game. Members take turns posting the next number in sequence. Wrong numbers, repeated users, and non-number messages are all handled automatically.
Configuration
"counting_game": {
"enabled": true,
"channel_id": "YOUR_COUNTING_CHANNEL_ID",
"fail_resets": true, // true = reset count to 0 on a wrong number
"delete_wrong": true, // true = delete wrong-number messages automatically
"delete_non_numbers": true // true = delete any non-number messages from the channel
}
| Field | Description |
|---|---|
channel_id | The ID of the Discord channel dedicated to the counting game. Only messages in this channel are processed by the counting logic. |
fail_resets | true — the count resets back to 0 when someone sends the wrong number. false — wrong messages are handled (deleted / warned) but the count is not reset. |
delete_wrong | true — wrong numbers are automatically deleted to keep the channel clean. |
delete_non_numbers | true — any message that is not a valid integer is deleted. Keeps only actual counting messages in the channel. |
#counting), copy its ID (right-click → Copy Channel ID), and paste it into channel_id. The bot starts from 1 and tracks the current count and last counter in the database.
Welcome & Leave Messages
Automatically post an embed when someone joins or leaves your server.
Placeholders
| Placeholder | Replaced with |
|---|---|
%joined_user% | The member's mention (e.g. @Username) |
%username% | The member's plain username |
Thumbnail Options
| Value | Shows |
|---|---|
"BOT" | The bot's profile picture |
"USER" | The joining/leaving member's profile picture |
| Any URL | A custom image from that URL |
leave block has the exact same structure as welcome.Auto-Moderation
Automatically handle common spam and abuse patterns.
| Rule | What it does |
|---|---|
max_mentions | If a message mentions more than N users, auto-mod acts |
max_lines | If a message has more than N lines, auto-mod acts |
| Anti-spam | If a user sends more than anti_spam_count messages within anti_spam_seconds seconds, auto-mod acts |
"auto_mod": {
"enabled": true,
"max_mentions": 5,
"max_lines": 30,
"anti_spam_seconds": 5,
"anti_spam_count": 5
}
enabled: false to turn off auto-moderation entirely.Database & Storage
Guild State
Saved to data/guilds/{guild_id}.json. Contains warnings, auto-role config, role menus, giveaways, and ticket runtime state. Created automatically.
SQLite (default)
Creates data/bot.db automatically. No extra setup needed. Best for most use cases.
MongoDB
Set database.driver to "mongodb" and fill in your URI. Used for warnings and moderation cases.
Minecraft Links
Stored in data/mc_links/ as JSON by default. Set minecraft.link_backend to "mongodb" to use MongoDB instead.
Troubleshooting
- Commands can take up to 1 hour to appear globally
- Set
guild_idin config.json to your server ID for instant registration - Make sure the bot has the
applications.commandsscope when invited
- The bot's role must be above the target role in Server Settings → Roles
- Use
/joinrole checkto diagnose auto-role issues
- Check that
music.enabledistruein config.json - Direct backend: verify
yt-dlpandffmpegare installed and paths are correct - Lavalink backend: make sure your Lavalink server is running and credentials match
- You must be in a voice channel before using
/play
- Check that
minecraft.enabledistrue - Verify
rcon_ip,rcon_port, andrcon_passwordare correct - Make sure
enable-rcon=trueis set inserver.properties - Check that the RCON port is not blocked by a firewall
- Make sure
tickets.enabledistrue - Make sure
panel_channelis set to a valid channel ID - Make sure at least one category is configured
- Run
/ticket panelafter any configuration changes
- Role names in
permissions.admin_roles/permissions.moderator_rolesmust exactly match Discord role names (case-sensitive) - Easiest fix: give the bot the Administrator permission