New SQLite table `exercise_aliases (alias, canonical, source)` seeded with ~40 common gym shorthand entries (OHP, RDL, "Bench", "Squat", plural/singular drifts, slang). Lookups go through this table first, then fall through to the strict exercise_db matcher — so the strict matcher's "false negative for ambiguous single tokens" property is preserved while still resolving every-day vocabulary. Schema decision: every seed row is tagged `source='seed'` and re-seeded on every init_db (deleted-then-reinserted), so editing the seed dict in code is the one source of truth. User-inserted rows are tagged `source='user'` and never touched by re-seeding. Migration path covers existing DBs where the `source` column didn't exist (those rows tagged 'seed' on first migration, then refreshed from the current seed). New helper db.lookup_exercise(name) wraps the alias resolution + the exercise_db.lookup() call. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| data | ||
| scripts | ||
| tests | ||
| webapp | ||
| .env.example | ||
| .gitignore | ||
| db.py | ||
| exercise_db.py | ||
| flake.lock | ||
| flake.nix | ||
| LICENSE | ||
| parser.py | ||
| README.md | ||
| requirements.txt | ||
| ROADMAP.md | ||
| server.py | ||
| start.py | ||
BigBiggerBiggestBot 💪
A Telegram Mini App for logging gym workouts. History, stats, notes, edit & delete, JSON/CSV export — all per-user, all in SQLite.
The slash-command bot was removed: the Mini App is the only interface.
A Telegram bot identity (token) is still required so the Mini App can
validate user sessions via initData HMAC.
Workout text format (still supported via "Paste as text" in the Mini App)
Bench press: 4x8x35
Shoulder press (3032): 8x25, 5x35, 6x40
Pull-ups: 3x10
SETSxREPSxWEIGHT— uniform setsREPSxWEIGHT, REPSxWEIGHT, ...— per-set (weight/reps vary)- Omit weight for bodyweight exercises
(machine_id)is optional (gym equipment ID)- Blank line separates superset groups; consecutive lines form a superset
- Both
,and.work as decimal separators
Run locally
nix run
This launches:
- API + Mini App server (port 8080)
- cloudflared Quick Tunnel for a public HTTPS URL (skipped if
WEBAPP_URLis already set in the environment, e.g. fronted by a reverse proxy)
Put your bot token (from @BotFather) in
~/.secrets/bigbiggerbiggestbot or a .env file:
BOT_TOKEN=123456:your-bot-token-here
nix develop drops you into a dev shell with Python + deps.
Tests
nix develop --command pytest tests/ -v
Deployment
Two environments share one host (sunken-ship):
- Production —
fitness-bot.service, working dir/home/danny/tg_fitness_bot, watchesorigin/main, served behind a stable URL via the VPS Caddy athttps://bbbot.dannydannydanny.me. - Shipyard staging —
fitness-bot-shipyard.service, working dir/home/danny/tg_fitness_bot_shipyard, watchesorigin/staging, served by the sharedshipyard_poc_botTelegram bot (B3Bot beta is the active POC tenant).
Each has its own pull timer that fetches every ~15 minutes and restarts the service when its branch has new commits.
Workflow:
git push origin <branch>:staging # → shipyard auto-deploys, test there
git push origin <branch>:main # → production auto-deploys
Each environment keeps its own workouts.db next to its code (gitignored),
so testing on shipyard never touches production data.
Architecture
server.py— aiohttp REST API + static file server for the Mini App; validates TelegraminitDataHMACs against the bot token.db.py— SQLite data layer (workouts, supersets, exercises, feedback, events, settings; soft delete).parser.py— workout text → structured data (used by the Mini App's "Paste as text" path).webapp/— Mini App (HTML/CSS/vanilla JS, Telegram WebApp SDK).start.py— orchestrator: loads token, starts server, optionally starts cloudflared.tests/— pytest suite for parser + db.
License
MIT — see LICENSE.