A Discord counting game app. Users count up in sequence in a channel, but cannot count twice in a row. If someone counts out of order or repeats, the count resets. Every 10th number triggers a celebration message. The game state is saved per channel in a database.
- Features
- Setup Instructions
- Running as a Service (systemd)
- Docker
- How the Counting Game Works
- Folder Structure
- Customization
- Testing
- Support
- License
- Simple counting game: Users type the next number in sequence in a Discord channel.
- Prevents double-counting: No user can count twice in a row.
- Automatic reset: Wrong numbers or double-counting reset the count to 0.
- Celebration messages: Every 10th number triggers a special message.
- Persistent state: Game state is saved in a database per channel.
- Localization: All messages are defined in
locales/en-US.json(add more locales as needed). - Discord.js-based app with ESM support
- Command and event handler architecture
- Environment variable support via dotenv
- Logging and signal handling via
@purinton/common - Ready for deployment with systemd or Docker
- Jest for testing
- Go to the Discord Developer Portal and click "New Application".
- Name your application and save.
- Go to the "app" tab and click "Add Bot".
- Copy the Application (Client) ID and Token—you'll need these for your .env file.
- Under "Privileged Gateway Intents", enable Message Content Intent (required for reading message content).
- Under "OAuth2 > URL Generator", select:
- Scopes: bot
- Bot Permissions: Send Messages, Read Message History
- Copy the generated URL and use it to invite the app to your server.
git clone https://github.com/purinton/counting.git
cd countingnpm installThis app uses a MySQL/MariaDB database to store the counting state. Import the provided schema:
# Replace with your DB credentials and database name
mysql -u <db_user> -p <db_name> < schema.sqlThis creates the counting_state table required for the app to function.
Copy .env.example to .env if it exists, or create a .env file. Set your Discord app token, client ID, and database credentials:
DISCORD_TOKEN=your-app-token
DISCORD_CLIENT_ID=your-client-id
LOG_LEVEL=info
DB_HOST=localhost
DB_USER=your-db-user
DB_PASS=your-db-password
DB_NAME=your-db-name
node counting.mjs- Copy
counting.serviceto/usr/lib/systemd/system/counting.service. - Edit the paths and user/group as needed.
- Reload systemd and start the service:
sudo systemctl daemon-reload
sudo systemctl enable counting
sudo systemctl start counting
sudo systemctl status counting-
Build the Docker image:
docker build -t counting . -
Run the container:
docker run --env-file .env counting
- Type the next number in sequence in the channel.
- You cannot count twice in a row—wait for someone else!
- If you enter the wrong number or count twice, the count resets to 0.
- Every 10th number, a celebration message appears.
- The game state is saved, so you can continue anytime.
All game logic is handled in events/messageCreate.mjs.
All user-facing messages are defined in locales/en-US.json. You can add more languages by creating additional files in locales/.
events/ # Event handlers (main logic: messageCreate.mjs)
locales/ # Locale JSON files (main: en-US.json)
commands/ # Command definitions and handlers (/help)
schema.sql # Database schema
.env # Environment variables (not committed)
- Add new commands in the
commands/directory. - Each command has a
.jsondefinition (for Discord registration/localization) and a.mjshandler (for logic).
- Add or modify event handlers in the
events/directory. - Each Discord event (e.g.,
ready,messageCreate,interactionCreate) has its own handler file.
- Add or update language files in the
locales/directory. - Localize command names, descriptions, and app responses.
-
Run tests with:
npm test -
Add your tests in the
tests/folder or alongside your code.
For help, questions, or to chat with the author and community, visit:


