GAS is a Python-based service designed to monitor game servers, track player activity, and send notifications about significant events via Discord and SMS.
- Game Server Monitoring: Receives status updates from game servers via a JSON POST request to the
/gameendpoint. - Event Tracking: Logs game server events (startup, player count changes) and player join/leave times in an SQLite database (
gameEvents.dbby default). - Server Status Tracking: Maintains a record of known servers and their last reported status (
serverTrackingtable). - Player Event Notifications:
- Sends Discord messages when a player joins or leaves a monitored game server.
- Sends optional SMS messages to opted-in users for player join/leave events.
- Sends a "last player left" notification to Discord and SMS when a server becomes empty.
- Daily System Sync:
- Uses APScheduler to run a daily task (default: 3 AM UTC).
- Checks for servers that have been empty (
currentplayers = 0) for over 24 hours based on their last update timestamp. - Updates the timestamp for these idle servers.
- Sends a single, consolidated notification to Discord summarizing how many idle servers had their timestamps updated.
- SMS/WhatsApp Interaction:
- Handles incoming SMS/WhatsApp messages via Twilio webhook at the
/incomingendpoint. - Supports user opt-in/out commands (
START,STOP,SUBSCRIBE,UNSUBSCRIBE). - Manages user phone numbers and preferences in the
userstable.
- Handles incoming SMS/WhatsApp messages via Twilio webhook at the
- Service Monitoring Endpoints:
/health: Basic health check, returns server time./alive: Returns startup time and uptime, confirming the service is running.
- Status Page:
/status: Provides an HTML page displaying the current status of tracked game servers and players.
- Rate Limiting: Protects endpoints from excessive requests.
- Logging: Comprehensive logging to both console/journald and a rotating file (
logs/gas.log).
- Web Framework: Flask
- WSGI Server: Gunicorn (recommended for production)
- Reverse Proxy: Nginx (recommended for production, handles SSL, proxies requests to Gunicorn)
- Database: SQLite
- Scheduling: APScheduler (for the daily sync task)
- SMS/WhatsApp: Twilio API
- Notifications: Discord Webhooks
-
Clone Repository:
git clone https://github.com/dillera/fujinetGameAlerts.git cd fujinetGameAlerts -
Python Version: Requires Python 3.10 or newer.
-
Create Virtual Environment:
python3 -m venv venv source venv/bin/activate -
Install Dependencies:
pip install -r requirements.txt
-
Environment Variables: Create a
.envfile in the project root directory and add the following variables:# Required TWILIO_ACCT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxx TWILIO_AUTH_TOKEN=your_twilio_auth_token TWILIO_TN=+1xxxxxxxxxx # Your Twilio phone number DISCORD_WEBHOOK=https://discord.com/api/webhooks/your/webhook_url # Optional (Defaults shown) # PORT=5100 # DATABASE=gameEvents.db # WORKING_DIRECTORY=/path/to/fujinetGameAlerts # Usually set automatically # DEBUG=False
TWILIO_ACCT_SID,TWILIO_AUTH_TOKEN,TWILIO_TN: Obtain from your Twilio account.DISCORD_WEBHOOK: Create a webhook integration in your Discord server.PORT: Port for the Flask development server or Gunicorn binding (if not using a socket).DATABASE: Path to the SQLite database file.WORKING_DIRECTORY: Base directory for logs and DB (usually the project root).DEBUG: Set toTruefor Flask debug mode (useful for development, do not use in production).
Ensure your .env file is configured and the virtual environment is active.
python gas.py- This runs the Flask development server.
- The APScheduler task for the daily sync will also start.
- Note: The development server runs with
use_reloader=Falseto prevent issues with the scheduler starting multiple times.
This is a typical production setup on a Linux server (e.g., Ubuntu).
-
Systemd Service (
gas.service): Create a service file (e.g.,/etc/systemd/system/gas.service) like the one included in the repository. Key aspects:- Sets the
User,Group, andWorkingDirectory. - Loads environment variables from the
.envfile. - Specifies the
ExecStartcommand to run Gunicorn, binding to a Unix socket (gas.sock). Binding to a socket is generally preferred over a port when using Nginx locally.
[Unit] Description=Gunicorn instance to serve GAS (Game Alert System) After=network.target [Service] User=ubuntu # Change to your deployment user Group=www-data # Or your deployment group WorkingDirectory=/home/ubuntu/fujinetGameAlerts # Change path as needed Environment="PATH=/home/ubuntu/fujinetGameAlerts/venv/bin" # Change path as needed EnvironmentFile=/home/ubuntu/fujinetGameAlerts/.env # Change path as needed ExecStart=/home/ubuntu/fujinetGameAlerts/venv/bin/gunicorn --workers 3 --bind unix:gas.sock -m 007 gas:app # Change path & worker count as needed Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
- Important: Adjust paths,
User,Group, and worker count as necessary for your environment. Ensure the.envfile path is correct. - Enable and start the service:
sudo systemctl enable gas.service sudo systemctl start gas.service sudo systemctl status gas.service
- Sets the
-
Web UI Service (
gasui.service): Similar to the main service, the web UI needs its own systemd service:sudo cp gasui.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable gasui.service sudo systemctl start gasui.serviceYou'll also need to configure Nginx to proxy to this service, similar to the main service configuration.
-
Nginx Configuration: Configure Nginx as a reverse proxy to forward requests to the Gunicorn socket. Create a site configuration (e.g.,
/etc/nginx/sites-available/gas):server { listen 80; server_name your_domain.com; # Replace with your domain or IP # Redirect HTTP to HTTPS (optional but recommended) return 301 https://$host$request_uri; } server { listen 443 ssl; server_name your_domain.com; # Replace with your domain or IP # SSL configuration (if using HTTPS) ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; # Main API endpoint location /game { # Proxy to the Gunicorn socket proxy_pass http://unix:/home/ubuntu/fujinetGameAlerts/gas.sock; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # Web UI endpoints (for gasui.py) location / { # Proxy to the gasui Gunicorn socket proxy_pass http://unix:/home/ubuntu/fujinetGameAlerts/gasui.sock; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # Special handling if game servers post to a different path prefix externally # For example, if servers post to http://your_domain.com/fuji/game location /fuji/game { # Proxy to the Gunicorn socket BUT tell Flask the route is /game proxy_pass http://unix:/home/ubuntu/fujinetGameAlerts/gas.sock:/game; # Adjust socket path proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # Add other locations as needed (e.g., for static files if any) }
- Important: Adjust
server_name, socket path, and SSL configuration as needed. The/fuji/gameblock is only necessary if your external URL differs from the internal Flask route (/game). - Enable the site and test Nginx configuration:
sudo ln -s /etc/nginx/sites-available/gas /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl restart nginx
- Important: Adjust
-
Deployment Script (
deploy.sh): The repository includes adeploy.sh.examplescript that automates pulling changes, running setup (installing/updating dependencies), and restarting both thegas.serviceandgasui.service.To use it:
# Copy the example to your actual deployment script cp deploy.sh.example deploy.sh # Edit the script to set your server details nano deploy.sh # Make it executable chmod +x deploy.sh # Run the deployment ./deploy.sh
Run it from your local machine where you have SSH access to the server. It assumes SSH keys are configured for passwordless login.
- Systemd Service Logs:
# Monitor the main service sudo journalctl -u gas.service -f # Monitor the web UI service sudo journalctl -u gasui.service -f # Monitor both services together sudo journalctl -u gas.service -u gasui.service -f
- Application Log File:
tail -f /path/to/fujinetGameAlerts/logs/gas.log
- Discord: Check the configured channel for startup messages, event notifications, and the daily sync message.
Game servers need to send POST requests with a JSON payload to the /game endpoint of the running GAS instance (e.g., http://your_domain.com/game or http://your_domain.com/fuji/game depending on your Nginx setup).
Required JSON Payload Fields:
game: (String) Name or identifier of the game being played.appkey: (String) A key for potential future use/authentication (currently logged but not strictly validated).server: (String) Identifier for the specific server instance (e.g., IP address, hostname).region: (String) Geographic region of the server (e.g., "US East", "EU West").serverurl: (String) A unique URL or identifier for the game instance, often including the game name/table ID (e.g.,http://lobby.example.com/?table=123). This is used as the primary key for tracking server state.curplayers: (Integer) The current number of players on the server at the time of the update.maxplayers: (Integer) The maximum player capacity of the server.
Example curl command:
curl -X POST http://your_domain.com/game \\
-H "Content-Type: application/json" \\
-d '{
"game": "Five Card Stud",
"appkey": "somekey",
"server": "192.168.1.100",
"region": "Local Dev",
"serverurl": "http://192.168.1.100:8081/?table=lobby",
"curplayers": 2,
"maxplayers": 5
}'