From 7057a4da2269f6da699fe3f774f19eb45bdad208 Mon Sep 17 00:00:00 2001 From: adrunkhuman <16039109+adrunkhuman@users.noreply.github.com> Date: Sun, 10 May 2026 20:29:00 +0200 Subject: [PATCH 1/4] docs: clarify hosted bot setup --- README.md | 194 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 113 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index 6169c5e..03ee255 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,80 @@ # TyperBot -Discord bot for weekly football prediction leagues. Admins create fixtures and enter results. Players submit score predictions in fixture threads or through `/predict`, which posts publicly into those threads. The bot stores picks, calculates points, and posts standings. +TyperBot is a Discord bot for football prediction leagues. One hosted TyperBot application can serve many Discord servers. Each server gets its own isolated league state: one configured league channel, one active season, fixtures, predictions, scoring rules, results, and standings. + +Server admins invite the hosted bot and configure it in Discord. They do not need to host their own bot process. ## Features -- Thread predictions -- `/predict` + +- Public fixture threads for predictions +- `/predict` modal that posts predictions into the selected fixture thread - Flexible score parsing -- Deadlines and late-pick handling -- Standings and results -- SQLite backups +- Deadlines, late prediction handling, and admin review for late partial predictions +- One active season per server +- Per-season scoring rules +- Standings and latest scored fixture summaries +- SQLite persistence and score-calculation backups -## Commands -### Player commands -- `/predict` - open a modal and post predictions publicly into the fixture thread -- `/fixtures` - show open fixtures and deadlines -- `/mypredictions` - show your saved predictions for open fixtures -- `/standings` - show the leaderboard and latest scored fixture +## Server Admin Setup + +Use this section if you administer a Discord server that has invited TyperBot. + +### Invite The Bot + +Ask the TyperBot operator for the invite link. The invite must grant the bot these permissions: + +- `Send Messages` +- `Send Messages in Threads` +- `Read Message History` +- `Add Reactions` +- `Create Public Threads` +- `Use Slash Commands` + +The hosted bot application also needs these privileged intents enabled by the operator: + +- `Message Content Intent` +- `Server Members Intent` + +### First Run -### Admin commands -- `/admin panel` - open the main admin surface, or start first-time setup when the server is not configured yet +Run `/admin panel` in your server. + +If the server is not configured yet, TyperBot prompts setup. Setup requires Discord `Administrator` or `Manage Server` permission. Choose: + +- TyperBot admin role: members with this role can use league admin actions after setup +- League channel: fixture announcements, fixture threads, and deadline reminders use this channel + +You can later run `/admin panel` and use `Setup TyperBot` to update those choices. + +### Start A League + +After setup, open `/admin panel` with the configured TyperBot admin role. + +Use the panel to: -The panel handles: - create fixtures -- delete fixtures +- delete open fixtures - jump to older open weeks not shown in the quick list - enter or correct results - calculate scores -- re-post the latest completed results with optional mentions +- re-post latest completed results with optional mentions - replace predictions - review late partial predictions - toggle late waivers +- edit scoring rules before scores exist for the active season +- start a new season after all active-season fixtures are closed -After setup, admins need the configured TyperBot admin role. Setup from `/admin panel` requires Discord `Administrator` or `Manage Server` permission. +TyperBot creates the first active season automatically when league data is first needed. Starting a new season archives the previous active season and resets scoring rules to defaults. -## Permissions -- `Send Messages` -- `Send Messages in Threads` -- `Read Message History` -- `Add Reactions` -- `Create Public Threads` -- `Use Slash Commands` +## Player Commands -## Privileged Intents -- Enable `Message Content Intent` in the Discord Developer Portal -- Enable `Server Members Intent` in the Discord Developer Portal +- `/predict` - open a modal and post predictions publicly into the fixture thread +- `/fixtures` - show open fixtures and deadlines +- `/mypredictions` - show your saved predictions for open fixtures +- `/standings` - show the active-season leaderboard and latest scored fixture + +## Prediction Flow -## Prediction flow - Reply in the fixture thread with one line per match. - Or run `/predict` anywhere in the server, choose the week if needed, fill the modal, and let the bot post it publicly in the fixture thread. - To replace a saved prediction, use `/predict` again; the bot posts an updated public message in the fixture thread. @@ -64,28 +93,39 @@ Team C - Team D 0:0 Team E - Team F 3:2 ``` -## Scoring -- Scoring rules are stored per season. The defaults are: +## Seasons And Scoring + +Each Discord server has one active season. Fixtures, predictions, scores, standings, and scoring rules are scoped to that server and active season. + +Default scoring rules for a new season: + - Exact score: 3 points - Correct outcome: 1 point - Wrong outcome: 0 points - Late full predictions: 0 points unless an admin waives the penalty -- Late predictions with missing games: excluded from scoring until reviewed by an admin -- Rule values must be whole numbers greater than or equal to zero. -- Changing rules is blocked after scores exist for that season, so stored scores do not silently go stale. -- Starting a new season resets its scoring rules to the defaults. -## Operational constraints -- Match data, predictions, results, and scores are stored in SQLite. -- Short-lived cooldowns are kept in memory, including the thread-post rate limiter and the score-calculation cooldown. -- The bot is intentionally single-process. If the process restarts, in-memory cooldowns reset. +Rules are stored per season. Rule values must be whole numbers greater than or equal to zero. Changing rules is blocked after scores exist for that season, so stored scores do not silently go stale. + +Late predictions with missing games are excluded from scoring until reviewed by an admin. + +## Operator Deployment + +Use this section if you run the hosted TyperBot application. + +### Runtime Model -## Configuration +Run one bot process for one Discord bot token. That process can serve many Discord guilds because all league state is guild-scoped in the database. + +Do not run multiple production deployments against the same live token. Discord will connect every deployment with a valid token, including non-production deployments. + +### Configuration + +Required: -### Required - `DISCORD_TOKEN` - Discord bot token -### Optional +Optional: + - `ENVIRONMENT` - environment label; use `production` for production deploys, default is `development` - `DATA_DIR` - base data directory; default `./data` locally, set `/app/data` on production deployments - `DB_PATH` - database path; default `{DATA_DIR}/typer.db` @@ -93,33 +133,43 @@ Team E - Team F 3:2 - `TZ` - timezone for admin deadline input; default `UTC` - `LOG_LEVEL` - logging level; default `INFO` -Run `/admin panel` in each server to store or update the admin role and league channel. Fixture announcements and deadline reminders both use that league channel. +Production data paths must live on a persistent volume. The default production pattern is: -## Deployment - -This bot runs anywhere you can deploy a persistent container. +```text +DATA_DIR=/app/data +DB_PATH=/app/data/typer.db +BACKUP_DIR=/app/data/backups +``` ### Coolify -1. Create a new Coolify worker/background service from this repo. +1. Create a worker/background service from this repo. 2. Use the included Dockerfile. 3. Disable HTTP/port health checks if Coolify enables them by default for the service. 4. Mount a persistent volume at `/app/data`. -5. Set variables: - - `DISCORD_TOKEN=` - - `ENVIRONMENT=production` - - `DATA_DIR=/app/data` - - optional: `TZ=Europe/Warsaw` +5. Set `DISCORD_TOKEN`, `ENVIRONMENT=production`, and `DATA_DIR=/app/data`. +6. Set `TZ` if the league uses a non-UTC local deadline timezone. -Use a separate token for previews and manual testing. Do not run multiple deployments against the same live token. +### Data And Backups -### Data +Match data, predictions, results, and scores are stored in SQLite. Short-lived cooldowns are kept in memory, including the thread-post rate limiter and score-calculation cooldown. If the process restarts, in-memory cooldowns reset. -Routine host migration is a direct copy of the live SQLite file at `DB_PATH` (default: `{DATA_DIR}/typer.db`). The `scripts/restore_db.py` helper is for restoring SQL dump backups during recovery, not for the normal host-to-host move. +Automatic backups run after each successful score calculation. The bot keeps the latest 10 backups in `BACKUP_DIR`. -If you override `DB_PATH` or `BACKUP_DIR`, keep them on the persistent volume too. +Routine host migration is a direct copy of the live SQLite file at `DB_PATH`. If you override `DB_PATH` or `BACKUP_DIR`, keep them on the persistent volume too. -## Running locally +Manual restore runs from the host or container shell where the live data volume is mounted: + +```bash +ls /app/data/backups/ +python scripts/restore_db.py /app/data/backups/backup_20260510_120000.sql +``` + +The restore script asks for confirmation, restores into a temporary SQLite file first, and only replaces the live database after success. + +### Non-Production And Manual Testing + +Use a separate bot token in a private test guild. Never point a preview deployment at the live production token. Local runs default to `ENVIRONMENT=development`, `DATA_DIR=./data`, and `TZ=UTC`. @@ -127,8 +177,7 @@ Local runs default to `ENVIRONMENT=development`, `DATA_DIR=./data`, and `TZ=UTC` git clone https://github.com/adrunkhuman/TyperBot cd TyperBot uv sync --group dev - -export DISCORD_TOKEN="your_token" +export DISCORD_TOKEN="your_test_bot_token" export ENVIRONMENT=development uv run python -m typer_bot ``` @@ -136,14 +185,12 @@ uv run python -m typer_bot Windows PowerShell: ```powershell -$env:DISCORD_TOKEN="your_token" +$env:DISCORD_TOKEN="your_test_bot_token" $env:ENVIRONMENT="development" uv run python -m typer_bot ``` -## Manual Discord Testing - -Use a separate bot token in a private test guild. Point it at an isolated data directory, not your normal local or deployed database. +Manual Discord testing with seeded data: ```powershell $env:DISCORD_TOKEN="your_test_bot_token" @@ -156,16 +203,12 @@ uv run python -m typer_bot Enable Discord Developer Mode, right-click your test server, and copy the server ID for `--guild-id`. The seed command resets that local test database and creates: + - one scored past fixture for standings/history - one open fixture with saved predictions - one late open fixture with a late prediction -Outside `./.local/manual-discord-test`, add `--force-reset`. - -`--force-reset` deletes the target DB, its `-wal` and `-shm` files, and the configured backup directory before reseeding. - -In a deployment shell, use the same command against that deployment's `DB_PATH` and `BACKUP_DIR`. -Those paths usually are not `./.local/manual-discord-test`, so add `--force-reset`. +Outside `./.local/manual-discord-test`, add `--force-reset`. `--force-reset` deletes the target DB, its `-wal` and `-shm` files, and the configured backup directory before reseeding. Create a real fixture when you need to test posting, thread creation, reactions, or modal-to-thread prediction posting. @@ -179,17 +222,6 @@ uv run ruff format --check . uv run ty check typer_bot ``` -## Backup and Restore - -- Automatic: the database is backed up after each successful score calculation. The bot keeps the latest 10 backups in `BACKUP_DIR`. -- Manual restore: run from the host or container shell where the live data volume is mounted. - -```bash -ls /app/data/backups/ -python scripts/restore_db.py /app/data/backups/backup_*.sql -``` - -The restore script asks for confirmation, restores into a temporary SQLite file first, and only replaces the live database after success. - ## License + MIT. From 4094bd84b1f856118a3ef2b51c5a7b880939f068 Mon Sep 17 00:00:00 2001 From: adrunkhuman <16039109+adrunkhuman@users.noreply.github.com> Date: Sun, 10 May 2026 20:32:57 +0200 Subject: [PATCH 2/4] docs: tighten setup README --- README.md | 195 +++++++++++++----------------------------------------- 1 file changed, 46 insertions(+), 149 deletions(-) diff --git a/README.md b/README.md index 03ee255..58f2ed2 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,20 @@ # TyperBot -TyperBot is a Discord bot for football prediction leagues. One hosted TyperBot application can serve many Discord servers. Each server gets its own isolated league state: one configured league channel, one active season, fixtures, predictions, scoring rules, results, and standings. +Discord bot for football prediction leagues. One hosted TyperBot application can be invited into multiple Discord servers; each server gets its own isolated league, active season, fixtures, predictions, scoring rules, and standings. -Server admins invite the hosted bot and configure it in Discord. They do not need to host their own bot process. +Server admins invite and configure the bot. They do not self-host it. -## Features +## What It Does -- Public fixture threads for predictions -- `/predict` modal that posts predictions into the selected fixture thread -- Flexible score parsing -- Deadlines, late prediction handling, and admin review for late partial predictions -- One active season per server -- Per-season scoring rules -- Standings and latest scored fixture summaries -- SQLite persistence and score-calculation backups +- Admins create fixture threads, enter results, calculate scores, and manage seasons. +- Players predict in fixture threads or with `/predict`, which posts publicly into the selected thread. +- Standings use the server's active season only. +- Scoring rules are stored per season and lock once scores exist. +- SQLite stores league data; backups run after successful score calculation. ## Server Admin Setup -Use this section if you administer a Discord server that has invited TyperBot. - -### Invite The Bot - -Ask the TyperBot operator for the invite link. The invite must grant the bot these permissions: +Ask the bot operator for the invite link. The bot needs: - `Send Messages` - `Send Messages in Threads` @@ -30,62 +23,23 @@ Ask the TyperBot operator for the invite link. The invite must grant the bot the - `Create Public Threads` - `Use Slash Commands` -The hosted bot application also needs these privileged intents enabled by the operator: - -- `Message Content Intent` -- `Server Members Intent` - -### First Run - -Run `/admin panel` in your server. - -If the server is not configured yet, TyperBot prompts setup. Setup requires Discord `Administrator` or `Manage Server` permission. Choose: - -- TyperBot admin role: members with this role can use league admin actions after setup -- League channel: fixture announcements, fixture threads, and deadline reminders use this channel - -You can later run `/admin panel` and use `Setup TyperBot` to update those choices. - -### Start A League - -After setup, open `/admin panel` with the configured TyperBot admin role. +The bot application also needs `Message Content Intent` and `Server Members Intent` enabled by the operator. -Use the panel to: +After inviting TyperBot, run `/admin panel`. First-time setup requires Discord `Administrator` or `Manage Server` permission and stores: -- create fixtures -- delete open fixtures -- jump to older open weeks not shown in the quick list -- enter or correct results -- calculate scores -- re-post latest completed results with optional mentions -- replace predictions -- review late partial predictions -- toggle late waivers -- edit scoring rules before scores exist for the active season -- start a new season after all active-season fixtures are closed +- admin role: who can use league admin actions +- league channel: where fixture announcements, threads, and reminders go -TyperBot creates the first active season automatically when league data is first needed. Starting a new season archives the previous active season and resets scoring rules to defaults. +After setup, members with the configured admin role use `/admin panel` to create fixtures, enter results, calculate scores, review late partial predictions, edit scoring rules, and start new seasons. ## Player Commands -- `/predict` - open a modal and post predictions publicly into the fixture thread -- `/fixtures` - show open fixtures and deadlines -- `/mypredictions` - show your saved predictions for open fixtures -- `/standings` - show the active-season leaderboard and latest scored fixture +- `/predict` - submit or replace predictions in a fixture thread +- `/fixtures` - show open fixtures +- `/mypredictions` - show your open-fixture predictions +- `/standings` - show active-season standings and latest scored fixture -## Prediction Flow - -- Reply in the fixture thread with one line per match. -- Or run `/predict` anywhere in the server, choose the week if needed, fill the modal, and let the bot post it publicly in the fixture thread. -- To replace a saved prediction, use `/predict` again; the bot posts an updated public message in the fixture thread. -- Partial predictions are allowed. Each partial line must name the game it applies to. -- Missing games count as no prediction. -- Late predictions with missing games stay under admin review until an admin approves or rejects them. -- Approved late submissions count the submitted lines normally, and missing games still count as no prediction. -- Rejected late submissions are discarded. -- Public review status stays visible in the fixture thread. - -Example: +Thread predictions use one line per match: ```text Team A - Team B 2:1 @@ -93,129 +47,72 @@ Team C - Team D 0:0 Team E - Team F 3:2 ``` -## Seasons And Scoring - -Each Discord server has one active season. Fixtures, predictions, scores, standings, and scoring rules are scoped to that server and active season. - -Default scoring rules for a new season: +Partial predictions are allowed if each line names the game. Missing games count as no prediction. Late partial predictions wait for admin approval. -- Exact score: 3 points -- Correct outcome: 1 point -- Wrong outcome: 0 points -- Late full predictions: 0 points unless an admin waives the penalty - -Rules are stored per season. Rule values must be whole numbers greater than or equal to zero. Changing rules is blocked after scores exist for that season, so stored scores do not silently go stale. - -Late predictions with missing games are excluded from scoring until reviewed by an admin. - -## Operator Deployment +## Seasons And Scoring -Use this section if you run the hosted TyperBot application. +Each server has one active season. Starting a new season archives the old active season and resets scoring rules to defaults: -### Runtime Model +- exact score: 3 +- correct outcome: 1 +- wrong outcome: 0 +- late full prediction: 0 unless waived -Run one bot process for one Discord bot token. That process can serve many Discord guilds because all league state is guild-scoped in the database. +Admins can edit scoring rules before scores exist in the active season. Rule values must be whole numbers greater than or equal to zero. -Do not run multiple production deployments against the same live token. Discord will connect every deployment with a valid token, including non-production deployments. +## Operator Notes -### Configuration +Run one bot process per Discord bot token. One process can serve many servers because all league state is guild-scoped. Do not run production and preview deployments against the same token. -Required: +Required environment variable: -- `DISCORD_TOKEN` - Discord bot token +- `DISCORD_TOKEN` -Optional: +Common optional variables: -- `ENVIRONMENT` - environment label; use `production` for production deploys, default is `development` -- `DATA_DIR` - base data directory; default `./data` locally, set `/app/data` on production deployments -- `DB_PATH` - database path; default `{DATA_DIR}/typer.db` -- `BACKUP_DIR` - backup directory; default `{DATA_DIR}/backups` -- `TZ` - timezone for admin deadline input; default `UTC` -- `LOG_LEVEL` - logging level; default `INFO` +- `ENVIRONMENT` - default `development`; use `production` for production deploys +- `DATA_DIR` - default `./data`; use `/app/data` in production +- `DB_PATH` - default `{DATA_DIR}/typer.db` +- `BACKUP_DIR` - default `{DATA_DIR}/backups` +- `TZ` - default `UTC` +- `LOG_LEVEL` - default `INFO` -Production data paths must live on a persistent volume. The default production pattern is: +Production data must live on a persistent volume. Typical production values: ```text +ENVIRONMENT=production DATA_DIR=/app/data -DB_PATH=/app/data/typer.db -BACKUP_DIR=/app/data/backups ``` -### Coolify - -1. Create a worker/background service from this repo. -2. Use the included Dockerfile. -3. Disable HTTP/port health checks if Coolify enables them by default for the service. -4. Mount a persistent volume at `/app/data`. -5. Set `DISCORD_TOKEN`, `ENVIRONMENT=production`, and `DATA_DIR=/app/data`. -6. Set `TZ` if the league uses a non-UTC local deadline timezone. +For Coolify, use the Dockerfile as a worker/background service, mount `/app/data`, and disable HTTP health checks if Coolify enables them for the service. -### Data And Backups - -Match data, predictions, results, and scores are stored in SQLite. Short-lived cooldowns are kept in memory, including the thread-post rate limiter and score-calculation cooldown. If the process restarts, in-memory cooldowns reset. - -Automatic backups run after each successful score calculation. The bot keeps the latest 10 backups in `BACKUP_DIR`. - -Routine host migration is a direct copy of the live SQLite file at `DB_PATH`. If you override `DB_PATH` or `BACKUP_DIR`, keep them on the persistent volume too. - -Manual restore runs from the host or container shell where the live data volume is mounted: +Routine host migration is a direct copy of the SQLite file at `DB_PATH`. Manual restore uses one backup file: ```bash ls /app/data/backups/ -python scripts/restore_db.py /app/data/backups/backup_20260510_120000.sql +python scripts/restore_db.py /app/data/backups/backup_YYYY-MM-DD_HH-MM-SS-ms.sql ``` -The restore script asks for confirmation, restores into a temporary SQLite file first, and only replaces the live database after success. - -### Non-Production And Manual Testing - -Use a separate bot token in a private test guild. Never point a preview deployment at the live production token. - -Local runs default to `ENVIRONMENT=development`, `DATA_DIR=./data`, and `TZ=UTC`. +## Local Development ```bash -git clone https://github.com/adrunkhuman/TyperBot -cd TyperBot uv sync --group dev export DISCORD_TOKEN="your_test_bot_token" -export ENVIRONMENT=development uv run python -m typer_bot ``` -Windows PowerShell: +Manual Discord testing can seed an isolated local database: ```powershell $env:DISCORD_TOKEN="your_test_bot_token" -$env:ENVIRONMENT="development" -uv run python -m typer_bot -``` - -Manual Discord testing with seeded data: - -```powershell -$env:DISCORD_TOKEN="your_test_bot_token" -$env:ENVIRONMENT="development" $env:DATA_DIR="./.local/manual-discord-test" uv run python -m typer_bot.dev.seed_test_data --tester-user-id "your_discord_user_id" --guild-id "your_discord_server_id" uv run python -m typer_bot ``` -Enable Discord Developer Mode, right-click your test server, and copy the server ID for `--guild-id`. - -The seed command resets that local test database and creates: - -- one scored past fixture for standings/history -- one open fixture with saved predictions -- one late open fixture with a late prediction - -Outside `./.local/manual-discord-test`, add `--force-reset`. `--force-reset` deletes the target DB, its `-wal` and `-shm` files, and the configured backup directory before reseeding. - -Create a real fixture when you need to test posting, thread creation, reactions, or modal-to-thread prediction posting. - -## Development +Run checks: ```bash -uv sync --group dev uv run pytest uv run ruff check . uv run ruff format --check . From 72f3162d3c244020039df03f3f973ec44a81e99d Mon Sep 17 00:00:00 2001 From: adrunkhuman <16039109+adrunkhuman@users.noreply.github.com> Date: Sun, 10 May 2026 20:35:26 +0200 Subject: [PATCH 3/4] docs: keep README user-focused --- AGENTS.md | 3 +++ README.md | 37 +------------------------------------ 2 files changed, 4 insertions(+), 36 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 301fb49..9de2df0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -24,6 +24,7 @@ You are working on `TyperBot`, a Discord bot for football prediction leagues. - **Logging:** Use `typer_bot.utils.logger.setup_logging()` early. Do not use `print()`. - **Timezones:** All datetime operations use timezone-aware objects. Use `utils.timezone.now()` instead of `datetime.now()`. Configure via `TZ` env var (default: `UTC`). - **Permissions:** Bot requires `Send Messages`, `Send Messages in Threads`, `Read Message History`, `Add Reactions`, `Create Public Threads`, and `Use Slash Commands`. +- **Discord Application:** Production application needs `Message Content Intent` and `Server Members Intent` enabled in the Discord Developer Portal. ## 3. Database Schema SQLite. Tables are initialized in `typer_bot/database/connection.py`. @@ -203,4 +204,6 @@ prek run ruff # Run specific hook - **Runtime:** The bot still connects to Discord in non-production environments; use a separate token for manual testing and previews - **Token Safety:** Any deployment with a valid token will connect; never run multiple environments against the same live token - **Production:** Set `ENVIRONMENT=production` in deployment variables for production deployments +- **Production Data:** Set `DATA_DIR=/app/data` on the persistent volume. `DB_PATH` defaults to `{DATA_DIR}/typer.db`; `BACKUP_DIR` defaults to `{DATA_DIR}/backups`. +- **Backups:** Automatic SQL backups are named `backup_YYYY-MM-DD_HH-MM-SS-ms.sql`. `scripts/restore_db.py` accepts one explicit backup file path, not a wildcard. - **Portability:** Works on any platform (Coolify, Railway, local, etc.) - just set the variable accordingly diff --git a/README.md b/README.md index 58f2ed2..981e338 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Server admins invite and configure the bot. They do not self-host it. ## Server Admin Setup -Ask the bot operator for the invite link. The bot needs: +Ask the repo owner for the invite link. The bot needs: - `Send Messages` - `Send Messages in Threads` @@ -23,8 +23,6 @@ Ask the bot operator for the invite link. The bot needs: - `Create Public Threads` - `Use Slash Commands` -The bot application also needs `Message Content Intent` and `Server Members Intent` enabled by the operator. - After inviting TyperBot, run `/admin panel`. First-time setup requires Discord `Administrator` or `Manage Server` permission and stores: - admin role: who can use league admin actions @@ -60,39 +58,6 @@ Each server has one active season. Starting a new season archives the old active Admins can edit scoring rules before scores exist in the active season. Rule values must be whole numbers greater than or equal to zero. -## Operator Notes - -Run one bot process per Discord bot token. One process can serve many servers because all league state is guild-scoped. Do not run production and preview deployments against the same token. - -Required environment variable: - -- `DISCORD_TOKEN` - -Common optional variables: - -- `ENVIRONMENT` - default `development`; use `production` for production deploys -- `DATA_DIR` - default `./data`; use `/app/data` in production -- `DB_PATH` - default `{DATA_DIR}/typer.db` -- `BACKUP_DIR` - default `{DATA_DIR}/backups` -- `TZ` - default `UTC` -- `LOG_LEVEL` - default `INFO` - -Production data must live on a persistent volume. Typical production values: - -```text -ENVIRONMENT=production -DATA_DIR=/app/data -``` - -For Coolify, use the Dockerfile as a worker/background service, mount `/app/data`, and disable HTTP health checks if Coolify enables them for the service. - -Routine host migration is a direct copy of the SQLite file at `DB_PATH`. Manual restore uses one backup file: - -```bash -ls /app/data/backups/ -python scripts/restore_db.py /app/data/backups/backup_YYYY-MM-DD_HH-MM-SS-ms.sql -``` - ## Local Development ```bash From ed7425f368741aaf2226065bb7a29b3ecc857dfe Mon Sep 17 00:00:00 2001 From: adrunkhuman <16039109+adrunkhuman@users.noreply.github.com> Date: Sun, 10 May 2026 20:37:29 +0200 Subject: [PATCH 4/4] docs: update agent project constraints --- AGENTS.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 9de2df0..b8ebec0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,7 +9,10 @@ You are working on `TyperBot`, a Discord bot for football prediction leagues. - **Tech:** Python 3.13+, discord.py, aiosqlite, portable container hosting. ## 2. Critical Constraints +- **Product Model:** One hosted TyperBot application serves many Discord guilds. Server admins invite/configure the bot; they do not self-host it. +- **League Scope:** Keep v3 simple: one league, one active season, one configured league channel, and one active scoring-rule set per guild. - **Persistence:** The database defaults to `./data/typer.db` locally. On production, set `DATA_DIR=/app/data` so the live DB stays on the mounted data volume. +- **Schema Changes:** Do not add broad startup compatibility migrations or backfills for historical schemas. Existing production DB changes should be verified and ported manually when needed; startup should validate/fail fast for unsafe current-schema violations. - **Transaction Safety:** Critical operations use atomic transactions (BEGIN/COMMIT/ROLLBACK) to ensure data consistency. Never modify transaction logic without understanding rollback implications. - **Prediction Contract:** Fixture threads are the public source of truth. `/predict` is a structured composer that posts publicly into the selected fixture thread. - **Configuration:** All data paths configurable via env vars in `utils/config.py`: @@ -122,7 +125,7 @@ guild_config ( - **Admin Panel UI:** Edit `commands/admin_panel/`. - **Workflow/Cooldown State:** Thread prediction cooldowns live in `handlers/thread_prediction_handler.py`; admin calculate cooldowns live in `commands/admin_commands.py`. Keep them process-local instead of introducing module-level globals. - **New Commands:** Add Cog to `commands/` folder, load in `bot.py`. -- **Database Changes:** Edit `typer_bot/database/connection.py` `initialize()` and the focused repositories in `typer_bot/database/` (handle migrations manually if needed). +- **Database Changes:** Edit `typer_bot/database/connection.py` `initialize()` and the focused repositories in `typer_bot/database/`. Keep fresh schema creation and startup validation explicit; handle production data ports manually when needed. - **Debugging:** Check `utils/logger.py` for config. Set `LOG_LEVEL=DEBUG` in env. - **Database Restore:** Use `scripts/restore_db.py` from the host or container shell for manual database restoration from backups. The script restores into a temporary SQLite file first, then atomically replaces the live DB only after success.