Per-guild configurable XP/level bot that tracks:
- Messages
- Reactions
- Voice minutes (per-minute ticker; ignores muted/deafened users and alone-in-channel idling)
Includes:
- Per-guild settings stored in SQLite (zero-setup for self-hosting)
- Tunable decay (daily cron)
- Level → Role automation with drop-below grace days
- Command restriction to allowed channels per guild
- Admin/mod commands for configuration
Requirements: Node.js, Discord.js 14+ (13.x will not work)
- Install dependencies
npm install- Create
.env
cp .env.example .env
# edit .env- Register slash commands
- Production (multi-guild): register global commands (default). Note: global command updates can take time to propagate.
- Development (fast): set
DEV_GUILD_IDin.envto register instantly to one guild.
npm run register- Run bot
npm start- Enable the Message Content Intent if you want
messageCreateto fire reliably for all message events.- Without it, the bot may not receive message content and (depending on gateway/intents configuration) may not receive message events as expected.
- Create Bot & Token from Discord Developer Portal. Bot must have the following permissions:

User commands:
/xp [user]/leaderboard
Admin/mod commands (requires Manage Guild by default):
/setxp message:<int> reaction:<int> voice:<int> msgcooldown:<int> reactioncooldown:<int>/setdecay enabled:<bool> messages:<int> days:<int> percent:<0-95>/leveltorole set role:<role> level:<int> dropdays:<int>/leveltorole remove role:<role>/leveltorole list/setcommandchannel add channel:<channel>/setcommandchannel remove channel:<channel>/setcommandchannel list/settings(shows current guild settings, role mappings, allowed channels)
The bot stores all data in xpbot.sqlite. Regular backups are recommended:
# Manual backup
cp xpbot.sqlite xpbot.sqlite.backup
# Automated daily backup (cron)
0 0 * * * cp /path/to/xpbot.sqlite /backups/xpbot-$(date +\%Y\%m\%d).sqliteTo restore from backup:
# Stop the bot first
cp xpbot.sqlite.backup xpbot.sqlite
# Restart the bot- Bot must have Manage Roles permission and its highest role must be above roles it manages.
- Voice XP is awarded once per minute for eligible users:
- not muted/deafened (self or server)
- and in a voice channel with at least 2 eligible human users
- SQLite DB file (
xpbot.sqlite) is created automatically in the project root. - Ensure you have a font installed that handles symbols and emoji. (sudo apt install fonts-noto-core fonts-noto fonts-dejavu-core fonts-noto-color-emoji)
- Roles for auto-granting must be BELOW the bot's role in the discord server's role settings (Drag bot's role above the desired roles to grant)
Disclaimer: GPT 5.2 was used for debugging and assisting with creation of the leaderboard extents. Bot logo was AI generated.