Discord bot for the Virtual Pinball Chat league - manages weekly competitions, high scores, playoffs, and leaderboards.
- Node.js 24
- discord.js 14
- @sapphire/framework
- @sapphire/plugin-subcommands
- MongoDB
-
Install dependencies:
npm install
-
Configure environment variables:
BOT_TOKEN- Discord bot tokenGUILD_ID- Discord server IDCOMMANDS_DIR- Path to commands directoryCONTEST_CHANNELS- Comma-separated list of channel IDs where contests are activeCOMPETITION_CHANNEL_NAME- Main competition channel nameHIGHSCORES_CHANNEL_NAME- High scores channel nameBOT_COMPETITION_ADMIN_ROLE_NAME- Role name for competition adminsBOT_HIGH_SCORE_ADMIN_ROLE_NAME- Role name for high score admins
-
Start the bot:
npm start
The bot performs several maintenance tasks automatically based on a schedule:
- Weekly Raffle & Competition Rollover: Every Monday at 12:00 AM PT, the bot runs the weekly raffle, selects winners, and prepares the next competition week.
- Tournament Maintenance: Every day at 12:05 AM PT, the bot:
- Ends any active tournaments that have reached their end date.
- Announces any new tournaments that are starting that day by posting the tournament details card.
These commands are available to all users in the appropriate channels.
Post your score for the current weekly competition. Requires an attached screenshot.
/post-score 1234567
/post-score 1,234,567
/post-score 9876543 y # Also post to high scores channelPost a high score to a specific table. Requires an attached screenshot.
/post-high-score 5000000 medieval madness
/post-high-score 12345678 attack from marsDisplay the current weekly leaderboard for the competition.
/show-leaderboardShow your current score in the weekly competition.
/show-scoreDisplay the teams for the current team competition.
/show-teamsShow the current playoff bracket and standings.
/show-playoffsShow the active tournament for the current channel and its associated tables.
/show-tournamentPost a score for a specific table in the active tournament. Requires an attached screenshot and table selection.
/post-tournament-score score:1234567 table:Medieval MadnessDisplay the overall standings for the active tournament.
/show-tournament-leaderboardShow the tournament rules and how points are scored.
/show-tournament-rulesGenerate a random number between 1 and a specified maximum.
/generate-random-number max:100These commands require the Competition Admin or High Score Admin role.
Create a new weekly competition by VPS ID.
/create-week vpsid:xyz123 romrequired:true mode:classic
/create-week vpsid:xyz123 romrequired:false mode:default startdateoverride:2024-01-15 enddateoverride:2024-01-22| Parameter | Description |
|---|---|
| vpsid | VPS table ID |
| romrequired | Whether ROM is required |
| mode | Game mode (default, classic, etc.) |
| startdateoverride | Optional start date |
| enddateoverride | Optional end date |
| b2sidoverride | Optional B2S ID override |
| notes | Optional notes |
Edit the current week's settings.
/edit-current-week weeknumber:5 table:Medieval Madness mode:classicEdit a user's score in the current competition.
/edit-score username:PlayerName score:5000000Remove a score by rank from the current competition.
/remove-score rank:3Create a new tournament in the current channel.
/create-tournament name:"Spring Classic" vpsids:"vps1,vps2" startdate:2024-04-01 enddate:2024-04-15| Parameter | Description |
|---|---|
| name | Tournament name |
| vpsids | VPS IDs for the tables (comma or space separated) |
| startdate | Start date (YYYY-MM-DD) |
| enddate | End date (YYYY-MM-DD) |
Edit a tournament's ROM info, dates, or notes. You can explicitly select a tournament via the tournament option, or leave it blank to select one from a list of active tournaments in the channel. Running this command also synchronizes the tournament's tables with the bot's table collection.
/edit-tournament tournament:"One Off" table:Medieval Madness romname:"v1.2" notes:"Updated rules"
/edit-tournament tournament:"EMs" startdate:2024-04-05 enddate:2024-04-20
/edit-tournament # Select from list and synchronize tables| Parameter | Description |
|---|---|
| tournament | The target active tournament to edit (autocomplete supported) |
| table | Table to edit ROM info for |
| romname | New ROM name/version |
| romurl | New ROM download URL |
| mode | New game mode |
| startdate | New start date (YYYY-MM-DD) |
| enddate | New end date (YYYY-MM-DD) |
| notes | Optional notes |
Add a table to a tournament. After providing the VPS ID, you must select the target tournament from a dropdown menu.
/add-tournament-table vpsid:xyz123Remove a table from a tournament. After providing the VPS ID, you must select the target tournament from a dropdown menu.
/remove-tournament-table vpsid:xyz123Edit a player's score for a specific table in the active tournament.
/edit-tournament-score table:Medieval Madness username:PlayerName score:6000000Remove a player's score from a table in the active tournament.
/remove-tournament-score table:Medieval Madness username:PlayerNameRemove a scheduled tournament that is not currently ongoing.
/remove-tournamentEnd the active tournament and announce the winner.
/end-tournamentCreate a new season.
/create-season seasonnumber:5 seasonname:Spring 2024 seasonstart:2024-03-01 seasonend:2024-05-31Edit the current season's settings.
/edit-current-season seasonnumber:5 seasonname:Spring 2024 seasonstart:2024-03-01 seasonend:2024-05-31Display the season leaderboard.
/show-season-leaderboardCreate a new team for the current competition.
/create-team team:Team Alpha: player1, player2, player3Rename an existing team.
/edit-team-name current-team-name:Team Alpha new-team-name:Team OmegaRemove a team from the current competition.
/remove-team team:Team AlphaAuto-suggest balanced teams based on player history.
/suggest-teams messageId:123456789 numberOfWeeksToTotal:4 numberOfTeams:4 minTeamSize:3Create a new playoff from the current season leaderboard.
/create-playoffCreate a new playoff round.
/create-playoff-round roundName:Quarterfinals gameList:game1,game2,game3,game4Create a new high score table by VPS ID.
/create-high-score-table vpsid:xyz123Remove a specific high score entry.
/remove-high-score vpsid:xyz123 username:PlayerName score:5000000Search and display high scores for a table.
/show-table-high-scores tablesearchterm:medieval madness
/show-table-high-scores vpsid:xyz123Display the list of available high score tables.
/show-table-listCreate a placeholder message authored by the bot.
/create-messageRepin the competition corner pinned message.
/repin-messageRun a raffle for the current competition participants.
/run-raffleShow all available commands (admin only).
/show-commandsBuild and run with Docker Compose:
# From vpc-compose directory
docker-compose -f docker-compose-local.yml up -d --build vpc-bot
# View logs
docker-compose -f docker-compose-local.yml logs --tail=50 vpc-botThe project follows a modular structure within the src/ directory:
commands/: Contains various command handlers for user and admin interactions, categorized by function (e.g.,competition,highscores,teams,utility).lib/: Houses reusable logic and data handling, such as data pipelines, VPC/VPS data, and output formatting.listeners/: Handles Discord events and custom event listeners.preconditions/: Implements checks for command execution (e.g., channel restrictions, role requirements).services/: Contains core business logic, like database interactions (database.js).utils/: Provides utility functions for argument parsing, formatting, and logging.index.js: The main entry point for the application, responsible for initializing the Discord client, database connection, and logging in.
- Slash commands use
/prefix (e.g.,/show-leaderboard) - Error messages auto-delete after 10 seconds
- Screenshots are required when posting scores