A production-ready Discord bot for managing user points with a leaderboard system. Users can give or remove points from others, and view their stats and the global leaderboard.
- Point giving system (
@user++) - Point removal system (
@user--) - Stats and leaderboard (
@Bro stats) - Role-based permissions
- Self-pointing prevention
- SQLite database for persistence
- Railway-ready deployment
- Node.js 18.0.0 or higher
- A Discord Bot Token
- Discord Developer Portal access
- Go to Discord Developer Portal
- Click "New Application" and give it a name
- Go to the "Bot" section
- Click "Add Bot" and confirm
- Under "Privileged Gateway Intents", enable:
- Server Members Intent
- Message Content Intent
- Under "TOKEN" section, click "Reset Token" or "Copy" to get your bot token
⚠️ IMPORTANT: Copy this token immediately - you won't be able to see it again!- This is the
DISCORD_TOKENyou'll use in your.envfile
- Go to "OAuth2" → "URL Generator"
- Select scopes:
botapplications.commands(optional, not required for this bot)
- Select bot permissions:
- Read Messages/View Channels
- Send Messages
- Read Message History
- Copy the generated invite URL and use it to invite your bot to your server
-
Clone or download this repository
-
Install dependencies:
npm install
-
Create a
.envfile in the root directory:DISCORD_TOKEN=your_bot_token_here BOT_NAME=Bro POINT_GIVER_ROLE_NAMES=b28,b27,b26 DATABASE_FILE=./points.db
-
Replace
your_bot_token_herewith your actual bot token from the Discord Developer Portal (step 6 above)- The token looks like:
- In your Discord server, go to Server Settings → Roles
- Create the roles that should be able to give/remove points (e.g.,
b28,b27,b26) - In your
.envfile, setPOINT_GIVER_ROLE_NAMESto a comma-separated list of role names:POINT_GIVER_ROLE_NAMES=b28,b27,b26
- Users with ANY of these roles can give/remove points
- For a single role, just use:
POINT_GIVER_ROLE_NAMES=PointGiver
- Assign these roles to users who should be able to give/remove points
- Regular users without these roles can still use the stats command
npm startThe bot should now be online and ready to use!
@username++
- Adds +1 point to the mentioned user
- Requires one of the configured point giver roles (see Configuration)
- Cannot give points to yourself
- Example:
@John++
@username--
- Removes -1 point from the mentioned user
- Requires one of the configured point giver roles (see Configuration)
- Cannot remove points from yourself
- Example:
@John--
@Bro stats
- Shows your current points
- Shows the global top 10 leaderboard
- Available to everyone (no role required)
- Example:
@Bro stats
Note: Replace Bro with your configured BOT_NAME if different.
All configuration is done via environment variables in the .env file:
| Variable | Description | Default |
|---|---|---|
DISCORD_TOKEN |
Your Discord bot token (required) | - |
BOT_NAME |
The bot's name for stats command | Bro |
POINT_GIVER_ROLE_NAMES |
Comma-separated list of role names that can modify points | PointGiver |
DATABASE_FILE |
Path to SQLite database file | ./points.db |
Note: POINT_GIVER_ROLE_NAMES accepts multiple roles separated by commas. Users with ANY of these roles can give/remove points. Example: POINT_GIVER_ROLE_NAMES=b28,b27,b26
.
├── index.js # Main entry point
├── package.json # Dependencies and scripts
├── .env # Environment variables (create this)
├── .env.example # Example environment file
├── .gitignore # Git ignore rules
├── Dockerfile # Docker configuration
├── Procfile # Railway/Heroku process file
├── README.md # This file
└── src/
├── config/
│ └── config.js # Configuration loader
├── database/
│ └── db.js # Database operations
├── services/
│ └── pointsService.js # Business logic layer
├── commands/
│ ├── messageHandler.js # Message processing
│ └── statsCommand.js # Stats command handler
└── utils/
└── logger.js # Logging utility
The bot uses SQLite to store user points. The database file is created automatically on first run.
Table: points
user_id(TEXT, PRIMARY KEY) - Discord user IDscore(INTEGER) - User's current point total
- Create a Railway account at railway.app
- Create a new project
- Connect your GitHub repository (or deploy directly)
- IMPORTANT: Add environment variables BEFORE the bot starts:
- Click on your project in Railway
- Click on the "Variables" tab (or go to your service → Variables)
- Click "New Variable" or "Raw Editor"
- Add these variables (one per line, or use the form):
DISCORD_TOKEN=your_actual_bot_token_here BOT_NAME=Bro POINT_GIVER_ROLE_NAMES=b28,b27,b26 DATABASE_FILE=/app/data/points.db - Click "Save" or "Deploy"
- Railway will automatically detect the
Procfileand deploy - The bot will start automatically once
DISCORD_TOKENis set
Step-by-step:
- In Railway dashboard, select your project
- Click on your service (the deployed app)
- Go to the "Variables" tab
- Click "New Variable" for each variable, OR click "Raw Editor" to add multiple at once
- Add these exact variable names and values:
DISCORD_TOKEN=your_bot_token_from_discord_developer_portalBOT_NAME=Bro(optional)POINT_GIVER_ROLE_NAMES=b28,b27,b26(your roles, comma-separated)DATABASE_FILE=/app/data/points.db(optional, for persistence)
- DO NOT include quotes around the values
- DO NOT use
DISCORD_TOKEN=your_bot_token_here- use your actual token - Variables are case-sensitive:
DISCORD_TOKENnotdiscord_token - After adding variables, Railway will automatically redeploy
- If the bot crashes with "DISCORD_TOKEN is required", check that the variable name is exactly
DISCORD_TOKEN(all caps)
You can also deploy using Docker:
docker build -t discord-points-bot .
docker run -d --env-file .env discord-points-bot- Never crashes on database failures (graceful error handling)
- Logs all major actions
- Handles empty leaderboards gracefully
- Handles missing roles safely
- Validates all mentions before processing
- Prevents self-pointing
- Ignores bot messages and DMs
If you see this error in Railway logs:
-
Check that the variable is set:
- Go to Railway dashboard → Your Project → Your Service → Variables tab
- Verify
DISCORD_TOKENexists (exact spelling, all caps) - Check that the value is not empty
-
Verify the variable name:
- Must be exactly:
DISCORD_TOKEN(notDISCORD_BOT_TOKEN,TOKEN, etc.) - Case-sensitive: all uppercase
- Must be exactly:
-
Check for extra characters:
- Make sure there are no quotes around the token value
- No spaces before/after the token
- Copy the token directly from Discord Developer Portal
-
Redeploy after adding variables:
- After adding/changing variables, Railway should auto-redeploy
- If not, manually trigger a redeploy
-
View logs to confirm:
- Check Railway logs to see if the variable is being read
- The bot should log "Bot logged in successfully" if the token is correct
- Check that the bot is online in your server
- Verify the bot has "Read Messages" and "Send Messages" permissions
- Check that Message Content Intent is enabled in Discord Developer Portal
- Verify the point giver roles exist in your server (e.g.,
b28,b27,b26) - Check that users have at least one of the configured roles assigned
- Ensure the role names in environment variables match exactly (case-sensitive)
- For multiple roles, use comma-separated format:
POINT_GIVER_ROLE_NAMES=b28,b27,b26
- Check file permissions for the database file
- Ensure the directory exists for the database path
- On Railway, use
/app/data/points.dbfor persistent storage
MIT
For issues or questions, please check:
- That all environment variables are set correctly
- That the bot has proper permissions in your server
- That the required Discord intents are enabled
- The logs for any error messages