Display workouts as "#N" based on each user's own ordered list of
non-deleted workouts (rank by timestamp ascending). Global auto-
increment id stays the primary key, used only internally and in
exports. User-visible surfaces now all use the per-user number:
- /history listing
- /delete now accepts the per-user number
- Save confirmations (bot text and Mini App toast)
Deleting a workout renumbers the later ones downward, as expected
for a pure display transform.
New db helpers: get_user_workout_number, resolve_user_number, and
get_workouts now includes user_number per row via SQLite window
function.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Users can send /feedback <text> to record feedback. Stored in a new
feedback table with user_id, text, created_at. Updated /start help text.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Parser now supports per-set notation (8x25, 5x35, 6x40),
bodyweight exercises (3x10), and asterisk separators.
Failed parse lines get user-facing error feedback instead of
being silently ignored.
Added /delete <id> and /export commands. Stats computed in SQL
instead of loading all workouts into memory. API gains DELETE,
CSV and JSON export endpoints.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- server.py: aiohttp API serving webapp/ and REST endpoints using existing db.py
- start.py: orchestrator that loads token, starts server + localtunnel + bot
- webapp/: Mini App frontend (Log, History, Stats) with Telegram-native theming
- bot.py: added Mini App menu button and inline button on /start
- flake.nix: added aiohttp + localtunnel, nix run now uses start.py
Python bot that parses workout messages (Exercise: SetsxRepsxWeight),
detects supersets from consecutive lines, extracts machine IDs, stores
both raw message text and parsed data in SQLite, and reads original
timestamps from forwarded Saved Messages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>