Mirror — primary at git.dannydannydanny.me
Find a file
Danny 7f061c5b11 feat(server): version badge now shows ISO date + short SHA
Format: 'YYYY-MM-DD <short-sha>'. Preferred path uses
`git log -1 --format='%cs %h'`.

Fallback path (no git on PATH) resolves HEAD (loose or packed refs)
and parses the loose commit object via zlib to extract committer
date, converted to UTC date. Degrades gracefully to SHA-only if
the commit object is packed or unreadable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 19:31:30 +02:00
tests feat(tg-fitness-bot): add test suite with pre-commit hook 2026-04-13 20:41:03 +02:00
webapp ui(webapp): split current exercise and next-exercise input into separate cards 2026-04-18 18:52:26 +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
bot.py feat(tg-fitness-bot): /feedback command, feedback SQLite table 2026-04-17 11:22:43 +02:00
db.py feat(tg-fitness-bot): /feedback command, feedback SQLite table 2026-04-17 11:22:43 +02:00
flake.lock feat(tg-fitness-bot): initial Telegram workout tracker bot 2026-03-24 15:50:05 +01:00
flake.nix feat(tg-fitness-bot): add test suite with pre-commit hook 2026-04-13 20:41:03 +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 docs: add muscle emoji to README heading 2026-04-17 14:41:40 +02:00
requirements.txt feat(tg-fitness-bot): initial Telegram workout tracker bot 2026-03-24 15:50:05 +01:00
ROADMAP.md docs: tick off #1 and version display; leave semver tags open 2026-04-18 19:26:58 +02:00
server.py feat(server): version badge now shows ISO date + short SHA 2026-04-18 19:31:30 +02:00
start.py fix(start): force http2 protocol and drain cloudflared output 🐛 2026-03-29 18:58:16 +02:00

BigBiggerBiggestBot 💪

A Telegram bot for logging gym workouts, with an embedded Mini App.

Send workouts as plain text, forward them from Saved Messages, or tap through a structured log form inside Telegram. History, stats, notes, edit & delete, JSON/CSV export — all per-user, all in SQLite.

Format

Send messages like:

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

Commands

  • /start — help & open Mini App
  • /history — recent workouts
  • /stats — summary (total workouts, sets, volume)
  • /delete <id> — soft-delete a workout
  • /export — download all data as JSON
  • /feedback <text> — send feedback to the bot author

Run locally

nix run

This launches:

  • API server (port 8080)
  • cloudflared tunnel for the Mini App
  • Telegram bot (polling)

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

Runs as a systemd service. A timer pulls this repo periodically and restarts the service when the remote has new commits — push to main and the bot redeploys itself within ~15 minutes.

The SQLite database lives next to the code at workouts.db (gitignored).

Architecture

  • bot.py — Telegram command handlers, polling, message parsing
  • server.py — aiohttp REST API + static file server for the Mini App
  • db.py — SQLite data layer (workouts, supersets, exercises, feedback; soft delete)
  • parser.py — workout text → structured data
  • webapp/ — Mini App (HTML/CSS/vanilla JS, Telegram WebApp SDK)
  • start.py — orchestrator: starts server + tunnel + bot, wires up the Mini App URL
  • tests/ — pytest suite for parser + db

License

MIT — see LICENSE.