- /card player lookup was a leading-wildcard substring match with a Python ulower() UDF over 6.16M player_games_hist rows — a full scan measured at 27s live before the ~2s render. Add a prefix fast-path (nick LIKE 'name%' COLLATE NOCASE) that uses the existing NOCASE index (~1ms), falling back to the ulower substring scan only when the prefix finds nothing. Same fix applied to _resolve_player_uids_batch (compare/stats). Lookup: 27,205ms -> 1ms. - Completed-season recap cache served ANY cached PNG forever, including files rendered mid-season (frozen at whatever point they were last viewed). Only serve from cache when the file's mtime is after season end; otherwise re-render. Fixed in both BOT/utils.py and web/server.js (shared cache). - Replace squadron card "Rating change" with "Place finished" (#rank / total), derived by ranking clans by final total_score among those active in-season. - Add (CARD)/(RECAP) timing logs for prod observability. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Installation
-
Clone the repository
git clone git@github.com:FURRO404/BOTS.git cd BOTS/SREBOT -
Set up the shared Python virtual environment (used by both SREBOT and TSSBOT)
python3 -m venv ../SHARED/.venv source ../SHARED/.venv/bin/activate -
Install dependencies
pip install -r ../SHARED/requirements.txt -
Configure environment variables
nano .env.envis the single source of truth for runtime config —ecosystem.config.jshas noenv:blocks; it loads.envviarequire('dotenv').config()and PM2 inherits the variables when spawning each app. Keys SREBOT reads:DISCORD_KEY=your_discord_bot_token_here DEEPL_KEY=your_deepl_api_key_here # Optional GITHUB_WEBHOOK_SECRET=your_webhook_secret # For auto-deployment STORAGE_VOL_PATH=/absolute/path/to/storage # Shared with TSSBOT SREBOT_API_BEARER_TOKEN=your_internal_api_token # Optional, protects /api/* SREBOT_API_PORT=6000 SREBOT_WEB_PORT=3001 SREBOT_WEBHOOK_PORT=9000 SREBOT_TTL_ALERT_WEBHOOK_URL=https://discord.com/api/webhooks/... SREBOT_EXTERNAL_HOST=0.0.0.0 SREBOT_EXTERNAL_PORT=18081 SREBOT_EXTERNAL_BEARER_TOKEN=your_external_bridge_token # Optional, protects the bridge API and websocket SREBOT_EXTERNAL_UPSTREAM_URL=http://127.0.0.1:6000 TSS_EXTERNAL_UPSTREAM_URL=http://127.0.0.1:6100 # Enables /api/tss/* proxy (omit -> 501) TSS_API_HOST=127.0.0.1 # tssbot-api bind host TSS_API_PORT=6100 # tssbot-api bind port SREBOT_TTL_ALERT_WEBHOOK_URL=https://discord.com/api/webhooks/... # Optional, maintains one Discord status message for TTL degradation/recovery NODE_ENV=production PYTHONUNBUFFERED=1 -
Run the bot
python BotScript.py
Relay gateway
ecosystem.config.js includes a unified PM2 app named relay-gateway
(code in BOTS/SHARED/relay_gateway/). It fronts both bots:
- proxies read-only queries:
/api/sre/*→ SREBOT's internal API (:6000);/api/tss/*→ the TSS HTTP API (:6100) or501until it is deployed - streams replay envelopes over
/ws/sreand/ws/tss - authenticates every request/socket against per-person keys at three levels
(
all/sre/tss) stored in$STORAGE_VOL_PATH/relay_keys.json(SHA-256-hashed tokens, hot-reloaded on change)
Outbox/state files live under the shared storage volume (STORAGE_VOL_PATH):
external_bridge_outbox.jsonl (sre) and tss_bridge_outbox.jsonl (tss).
Useful commands:
pm2 start ecosystem.config.js --only srebot-api
pm2 start ecosystem.config.js --only relay-gateway
pm2 logs relay-gateway
# manage downstream keys (run from BOTS/SHARED with the shared venv):
python -m relay_gateway.manage_keys --file "$STORAGE_VOL_PATH/relay_keys.json" add --name cn-axbot --level sre
python -m relay_gateway.manage_keys --file "$STORAGE_VOL_PATH/relay_keys.json" list
python -m relay_gateway.manage_keys --file "$STORAGE_VOL_PATH/relay_keys.json" revoke --name cn-axbot
Downstream consumers (e.g. BOT-RELAY) discover their channels from
GET /api/whoami and connect to /ws/<channel> + /api/<channel>/* using their
bearer token. Point them at http://<srebot-host>:18081.