Mirror — primary at git.dannydannydanny.me
Find a file
Danny 214596e26f feat: exercise_aliases table + lookup_exercise() alias-aware wrapper
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>
2026-06-01 10:49:24 +03:00
data feat: bundle Free-Exercise-DB + name matcher (step 1) 2026-05-24 11:11:34 +02:00
scripts feat: scripts/set-bot-presence.py for chat-side bot presence 2026-05-23 12:01:39 +02:00
tests feat: exercise_aliases table + lookup_exercise() alias-aware wrapper 2026-06-01 10:49:24 +03:00
webapp feat: last-session recall when starting an exercise 2026-05-22 12:52:37 +02:00
.env.example feat(tg-fitness-bot): initial Telegram workout tracker bot 2026-03-24 15:50:05 +01:00
.gitignore feat(tg-fitness-bot): initial Telegram workout tracker bot 2026-03-24 15:50:05 +01:00
db.py feat: exercise_aliases table + lookup_exercise() alias-aware wrapper 2026-06-01 10:49:24 +03:00
exercise_db.py feat: exercise_aliases table + lookup_exercise() alias-aware wrapper 2026-06-01 10:49:24 +03:00
flake.lock feat(tg-fitness-bot): initial Telegram workout tracker bot 2026-03-24 15:50:05 +01:00
flake.nix refactor: drop the slash-command bot — Mini App is the only interface 2026-05-10 13:40:28 +02:00
LICENSE docs: add LICENSE (MIT) and README 2026-04-17 14:21:12 +02:00
parser.py feat(tg-fitness-bot): multi-set format, delete, export, SQL stats 2026-04-07 22:46:10 +02:00
README.md refactor: drop the slash-command bot — Mini App is the only interface 2026-05-10 13:40:28 +02:00
requirements.txt refactor: drop the slash-command bot — Mini App is the only interface 2026-05-10 13:40:28 +02:00
ROADMAP.md docs: add last-session recall to ROADMAP 2026-05-22 12:49:51 +02:00
server.py feat: bundle Free-Exercise-DB + name matcher (step 1) 2026-05-24 11:11:34 +02:00
start.py fix(start.py): line-buffer stdout so journals show progress promptly 2026-05-10 13:42:51 +02:00

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 sets
  • REPSxWEIGHT, 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_URL is 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):

  • Productionfitness-bot.service, working dir /home/danny/tg_fitness_bot, watches origin/main, served behind a stable URL via the VPS Caddy at https://bbbot.dannydannydanny.me.
  • Shipyard stagingfitness-bot-shipyard.service, working dir /home/danny/tg_fitness_bot_shipyard, watches origin/staging, served by the shared shipyard_poc_bot Telegram 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 Telegram initData HMACs 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.