A Discord bot that monitors GZCTF platform for notifications and events, then pushes them to a Discord channel in real-time.
- Real-time Notifications: Monitors GZCTF platform for new notices and events
- Rich Discord Embeds: Beautiful formatted messages with colors and emojis
- Multiple Notification Types:
- π₯ First Blood notifications
- π₯ Second Blood notifications
- π₯ Third Blood notifications
- π‘ New hint releases
- π― New challenge releases
- π© Flag submissions
- π Container start/stop events
β οΈ Cheat detection alerts
- Duplicate Prevention: Tracks seen notifications to avoid spam
- Persistent State: Remembers last notification ID across restarts
- Configurable: Easy configuration via environment variables
- Smart Authentication: Automatically refreshes authentication tokens to maintain connection
- Robust Error Handling: Gracefully handles connection issues and API errors
- FirstBlood: First team to solve a challenge
- SecondBlood: Second team to solve a challenge
- ThirdBlood: Third team to solve a challenge
- NewHint: New hint released for a challenge
- NewChallenge: New challenge released
- Normal: General game announcements
- FlagSubmit: Flag submission attempts and results
- ContainerStart: Challenge container started
- ContainerDestroy: Challenge container destroyed
- CheatDetected: Cheating detection alerts
- Normal: General game events
- Python 3.8 or higher
- Discord Bot Token
- GZCTF platform access (username/password)
-
Clone the repository
git clone <repository-url> cd gzctf-notification
-
Install dependencies
pip install -r requirements.txt
-
Create Discord Bot
- Go to Discord Developer Portal
- Create a new application
- Go to "Bot" section and create a bot
- Copy the bot token
- Enable "Message Content Intent" under Privileged Gateway Intents
-
Invite Bot to Server
-
Go to "OAuth2" > "URL Generator"
-
Select "bot" scope
-
Select the following permissions:
Required Permissions:
- Send Messages - Allows bot to send notifications
- Embed Links - For rich embed message formatting
- Read Message History - Allows bot to read message history
- View Channels - Allows bot to see channels
Optional Permissions (Recommended):
- Manage Channels - For automatic channel creation for notifications and events
- Use External Emojis - For better emoji formatting in messages
- Mention Everyone - To mention @everyone when necessary
-
Copy the generated URL and invite the bot to your server
Channel Configuration:
- The bot will automatically create (or use existing) two channels:
- Notification channel (public): For general notices like First Blood, New Challenges
- Event channel (private): For sensitive data like flag submissions, user activities
- You can customize channel names via environment variables
- Note: If you don't grant
Manage Channels
permission, you need to manually create channels and configure permissions
-
-
Configure Environment
cp env.example .env
Edit
.env
with your configuration:# GZCTF Configuration GZCTF_BASE_URL=https://your-gzctf-instance.com GZCTF_USERNAME=your_username GZCTF_PASSWORD=your_password # Discord Bot Configuration DISCORD_TOKEN=your_discord_bot_token_here DISCORD_GUILD_ID=your_discord_server_id # Optional: Custom channel names (default: notification, event) NOTIFICATION_CHANNEL_NAME=notification EVENT_CHANNEL_NAME=event # Bot Configuration GAME_ID=1 POLL_INTERVAL=30 ENABLE_NOTICES=true ENABLE_EVENTS=true DEBUG=false TZ=Asia/Ho_Chi_Minh
Category | Variable | Required | Default | Description |
---|---|---|---|---|
GZCTF | GZCTF_BASE_URL |
Yes | - | GZCTF platform URL |
GZCTF | GZCTF_USERNAME |
Yes | - | Monitor user credentials |
GZCTF | GZCTF_PASSWORD |
Yes | - | Monitor user credentials |
Discord | DISCORD_TOKEN |
Yes | - | Bot token |
Discord | DISCORD_GUILD_ID |
Yes | - | Target server ID |
Bot | GAME_ID |
Yes | - | Target game ID |
Bot | POLL_INTERVAL |
No | 30 | Polling frequency (seconds) |
Bot | ENABLE_NOTICES |
No | true | Enable notice monitoring |
Bot | ENABLE_EVENTS |
No | true | Enable event monitoring |
Channels | NOTIFICATION_CHANNEL_NAME |
No | notification | Public channel name |
Channels | EVENT_CHANNEL_NAME |
No | event | Private channel name |
System | DEBUG |
No | false | Debug logging |
System | LOG_DIR |
No | /app/logs | Log directory |
System | TZ |
No | UTC | Timezone |
- Enable Developer Mode in Discord (User Settings > Advanced > Developer Mode)
- Right-click on the channel you want to use
- Click "Copy ID"
- Navigate to your GZCTF platform
- Go to the game you want to monitor
- The game ID is usually in the URL:
https://your-gzctf.com/game/{GAME_ID}
python bot/main.py
docker-compose up -d
The bot will:
- Authenticate with GZCTF platform using cookie-based authentication
- Connect to Discord
- Create/setup channels based on configuration:
- Public notification channel: Created only if ENABLE_NOTICES=true
- Private event channel: Created only if ENABLE_EVENTS=true
- Start polling for notifications every 30 seconds (configurable)
- Send formatted notifications to the appropriate Discord channels
- Write logs to
logs/gzctf_bot.log
locally or/app/logs/gzctf_bot.log
in Docker. - Automatically refresh authentication when needed:
- Every 30 polling cycles (approximately 15 minutes with default settings)
- After 1 hour regardless of polling count
- When token validation fails
The bot automatically creates a private event channel that only administrators and the bot can access. This protects sensitive information like:
- Flag submission attempts and results
- User activity logs
- Container start/stop events
- Cheat detection alerts
- @everyone: No access (cannot see the channel)
- Bot: Full access (can send messages and embeds)
- Admin/Moderator roles: Full access (automatically detected)
If you encounter issues, you can:
- Enable debug mode by setting
DEBUG=true
in your.env
file - Test API connectivity using the debug script:
python scripts/debug_api.py
- Test configuration using the test script:
python scripts/test_config.py
- Verify Discord permissions and private channel setup using the verifier:
python scripts/verify_permissions.py
- debug_api.py: Debug GZCTF endpoints using the same cookie-based auth as the bot
- Run:
python scripts/debug_api.py
- Logs auth status, game info, notices, events; detects 403 on events and warns
- Run:
- test_simple.py: Quick end-to-end test for auth + notices/events via
GZCTFClient
- Run:
python scripts/test_simple.py
- Run:
- test_config.py: Print the configuration loaded from
.env
- Run:
python scripts/test_config.py
- Run:
- verify_permissions.py: Verify guild/channel permissions and ensure the event channel is private
- Run:
python scripts/verify_permissions.py
- Run:
- generate_invite_link.py: Generate a bot invite link with recommended permissions
- Run:
python scripts/generate_invite_link.py
- Run:
- Scripts under
scripts/
add thebot/
folder tosys.path
at runtime, so imports work when executing scripts. - If your IDE (Pylance/Pyright) reports "reportMissingImports" for
config
orgzctf_client
, add this to.vscode/settings.json
:Alternatively, set{ "python.analysis.extraPaths": ["./bot"] }
PYTHONPATH
to thebot
folder for your editor session.
π₯ First Blood!
**Web Challenge** has been solved by **Team Alpha**!
Notice ID: 123
π‘ New Hint Available
New hint for **Crypto Challenge**: Check the file headers
Notice ID: 124
π© Flag Submission
β
Flag submitted for **Pwn Challenge** - **ACCEPTED!**
User: hacker123
Team: Team Beta
-
Authentication Failed
- Check your GZCTF credentials
- Ensure username/password are correct
- Verify the GZCTF base URL is accessible
- The bot now uses cookie-based authentication with GZCTF_Token
- Authentication is refreshed automatically based on:
- Every 30 polling cycles (configurable)
- After 1 hour of operation (time-based refresh)
- When token validation fails
-
Discord Bot Permission Errors (403 Forbidden)
- Ensure the bot has been invited to your Discord server
- Check that the bot has the following permissions in the target channel:
- Send Messages (Required)
- Embed Links (Required)
- View Channels (Required)
- Read Message History (Recommended)
- Verify
DISCORD_GUILD_ID
is correct - Make sure the bot can see and access the specified channel
- Check channel permissions - the bot role must have permission to send messages
-
Bot Cannot Send Messages
- Right-click on the target channel β Edit Channel β Permissions
- Add the bot role and ensure it has "Send Messages" permission
- Check if the channel has any permission overwrites that might block the bot
- If bot cannot auto-create channels, manually create channels and set permissions:
Notification Channel (Public): - @everyone: View Channel, Read Message History - Bot: Send Messages, Embed Links, View Channel Event Channel (Private): - @everyone: No permissions - Admin/Moderator: All permissions - Bot: Send Messages, Embed Links, View Channel
-
Discord Bot Not Responding
- Check the bot token is correct
- Ensure the bot has proper permissions in the channel
- Verify the channel ID is correct
-
No Notifications Received
- Check if the game ID is correct
- Verify the game has active notifications
- Check the bot logs for errors
-
Duplicate Notifications
- The bot tracks seen notifications to prevent duplicates
- If you restart the bot, it may send recent notifications again
By default, logs are written to ./logs/gzctf_bot.log
(local runs) or /app/logs/gzctf_bot.log
(Docker). You can override the folder with LOG_DIR
.
Log file uses rotation (5 MB, 3 backups). It includes detailed information about:
- Authentication status
- API requests and responses
- Discord message sending
- Errors and exceptions
The bot is organized with a clear modular structure:
- config.py: Manages configuration from environment variables
- gzctf_client.py: API client for communicating with GZCTF
- Handles cookie-based authentication with GZCTF_Token
- Manages session cookies with proper domain settings
- Implements automatic token refresh mechanisms
- notification_formatter.py: Formats notifications into Discord embeds
- discord_bot.py: Handles Discord connection and sending notifications
- Implements smart authentication refresh based on time and poll count
- Provides robust error handling for API and connection issues
- main.py: Entry point of the application
The project is designed for easy deployment with Docker:
- Dockerfile: Builds image from Python 3.11-slim
- docker-compose.yml: Defines service with a single volume for all persistent data
- Volume: Single volume stores both bot state and logs for simplicity
- Security: Runs container as non-root user
gzctf-notification/
βββ bot/
β βββ __init__.py
β βββ config.py # Configuration management
β βββ discord_bot.py # Discord bot implementation
β βββ gzctf_client.py # GZCTF API client
β βββ main.py # Main entry point
β βββ notification_formatter.py # Notification formatting
βββ scripts/ # Utility scripts
βββ docker-compose.yml # Docker Compose configuration
βββ Dockerfile # Docker configuration
βββ env.example # Example environment file
βββ requirements.txt # Python dependencies
βββ README.md # This documentation
- Update the
NotificationFormatter
class innotification_formatter.py
- Add new colors and emojis to the mapping dictionaries
- Implement formatting logic in the appropriate methods
This project is licensed under the MIT License - see the LICENSE file for details.
For issues and questions:
- Check the troubleshooting section
- Review the logs for error messages
- Open an issue on the repository
- GZCTF platform for providing the API
- Discord.py library for Discord integration
- Python community for excellent async libraries