Discord Bot
Discord Bot
The Voxy Discord bot is a standalone Java application — not a Minecraft plugin. It runs separately and communicates with your network via the same MongoDB and Redis connections as Voxy.
Features
- Account linking — Players link their Minecraft account to Discord in-game; the bot DMs them an approve/deny prompt
- Rank ↔ role sync — Minecraft ranks are mapped to Discord roles; roles are assigned and removed automatically as grants change
- Linked role — Optionally grant a special Discord role to all linked accounts
- Slash commands —
/profile,/unlink,/associate,/disassociate - Status rotation — Cycles through configurable bot presence messages
Setup
1. Create a Discord Application
- Go to the Discord Developer Portal and create a new application
- Under Bot, create a bot user and copy the token
- Enable the Server Members Intent under Privileged Gateway Intents
- Invite the bot to your server with
Manage RolesandSend Messagespermissions
The bot's role must be positioned above any rank-associated roles in your server's role list, otherwise it cannot assign them.
2. Configure settings.yml
discord:
token: "YOUR_BOT_TOKEN"
guild: "YOUR_GUILD_ID"
# Role ID to grant all linked accounts. Set to 0 to disable.
linked-role: 0
presence:
interval: 30 # Seconds between status rotations (minimum 5)
status: "online" # online | idle | dnd | invisible
activities:
- type: "Playing"
text: "On Your Network"
- type: "Custom"
text: "At your service!"
server:
identifier: "discord-bot"
display-name: "Discord Bot"
group: "bots"
database:
mongo:
host: "localhost"
port: 27017
database: "voxy"
srv: false
auth:
enabled: false
username: ""
password: ""
redis:
host: "localhost"
port: 6379
auth:
enabled: false
username: ""
password: ""
3. Start the bot
java -jar voxy-discord.jar
The bot exits with an error if MongoDB or Redis is unreachable.
Slash Commands
| Command | Who | Description |
|---|---|---|
/profile [user] |
Anyone | View a linked player's Minecraft profile (name, UUID, rank, level, XP, playtime, join date) |
/unlink |
Anyone | Unlinks your Discord account from Minecraft |
/associate <rank> <discord-role> |
Admin | Binds a Minecraft rank to a Discord role |
/disassociate <rank> |
Admin | Removes a rank-role binding |
All responses are ephemeral (visible only to the invoking user).
UI Scripting (YAML)
The Discord bot can render rich interactive messages using YAML definitions in messages.yml.
Each message is keyed by a dotted route (for example link.request or profile.summary) and is defined as a list of top-level container components. Supported top-level component types are:
- TEXT - a text display block (Markdown supported). Requires a
textkey. - SEPARATOR - a spacer/divider. Optional
spacing(SMALLorLARGE) anddivider(boolean). - SECTION - a block of
TEXTchildren with a required accessory (thumbnail or button). - ACTION_ROW - a horizontal row of interactive components, listed under
children. - BUTTON - a clickable action (inside an
ACTION_ROWor as a section accessory). - STRING_SELECT - dropdown menu of textual options.
- ENTITY_SELECT - dropdown for selecting users, roles, or channels.
- MEDIA_GALLERY - a grid of images.
- FILE_DISPLAY - a downloadable file.
Component notes
- A BUTTON uses the key
idfor its custom identifier (notcustom_id). Link-style buttons (style: LINK) useurlandlabelinstead ofid. - A SECTION requires a
childrenlist containing onlyTEXTitems, plus an accessory supplied as a map underaccessory(orthumbnail). A thumbnail accessory must be a map withtype: THUMBNAILand aurl- a bare URL string is rejected. A section cannot contain anACTION_ROW. - For the link prompt, the approve/deny button IDs are generated at runtime (they encode the request UUID, e.g.
discord-link:approve:<uuid>). Reference them in YAML with the{approve-id}and{deny-id}placeholders, which the bot substitutes before sending.
Example: link.request
link:
request:
- type: SECTION
accessory:
type: THUMBNAIL
source: URL
url: "https://cravatar.eu/helmavatar/{player-id}/800.png"
description: "Avatar for {player}"
children:
- type: TEXT
text: "## Account Link Request"
- type: TEXT
text: "Link request from **{player}**"
- type: SEPARATOR
spacing: SMALL
- type: TEXT
text: "This request expires in {minutes} minutes."
- type: ACTION_ROW
children:
- type: BUTTON
style: SUCCESS
id: "{approve-id}"
label: "Approve"
- type: BUTTON
style: DANGER
id: "{deny-id}"
label: "Deny"
When the bot renders this definition it builds the message from the listed components. Pressing Approve links the accounts, while Deny rejects the request. Placeholders such as {player}, {minutes}, {approve-id}, and {deny-id} are substituted at send time.
Account Linking
- Player runs
/linkdiscordin-game - Bot sends them a DM with Approve / Deny buttons
- Player clicks Approve — accounts are linked and role sync runs immediately
- Link requests expire after 5 minutes
To unlink, players run /unlinkdiscord in-game or /unlink on Discord.
Rank-Role Synchronization
Map a Minecraft rank to a Discord role with /associate:
/associate <rank> <discord-role>
Once associated, the bot automatically:
- Assigns the role when a player receives that rank grant
- Removes the role when the grant expires or is revoked
- Reconciles all existing members on startup
Multiple ranks can map to the same role. A rank can only have one associated role.