Commit Graph

10 Commits

Author SHA1 Message Date
Davide Scaini 0eb25620ef Add headless Garmin background sync (systemd timer)
New `bincio sync-garmin` command mirrors sync-strava: discovers all users
with garmin_creds.json, refreshes cached garth OAuth2 session, imports new
activities, and optionally POSTs to the rebuild endpoint.

systemd timer fires every 3h offset by 1h30m from Strava to avoid
simultaneous rebuilds. Status written to _garmin_sync_status.json per user.
2026-05-16 20:13:12 +02:00
Davide Scaini 5307ae287c Explore: personal GPS heatmap tab under Athlete page
- bincio/explore.py: bake_tracks() simplifies GPS coords (RDP ε=0.0001),
  strips to [lng,lat], groups by sport type, writes per-handle tracks.json
- bake-tracks CLI command; render CLI calls _bake_tracks() after each build;
  strava_zip runs it once at end of batch
- /api/me/tracks endpoint serves the baked file; wipe_user cleans it up
- Explore.svelte: MapLibre full-screen map with sidebar — type pills,
  year/month date filter, Lines / Heatmap (global or by-type) view modes
- AthleteView: Explore tab visible only to profile owner (checks __bincioMe)
- Base.astro: fullscreen prop + Planner nav link
2026-05-14 14:31:21 +02:00
Davide Scaini 4d2df860ce Segments Phase 3: detection algorithm, CLI, ingest hook, and efforts API
- detect.py: ActivityTrack + detect_one/detect_all (bbox pre-filter →
  start/end proximity 25m → path conformance 50m/30% → effort extraction
  with avg speed/HR/power and Coggan NP)
- cli.py: `bincio segments detect` for retroactive detection over stored
  timeseries JSONs, with optional --activity-id / --segment-id filters
- ingest.py: non-fatal hook at end of ingest_parsed runs detect_all
- server.py: GET /api/segments/{id}/efforts and POST /api/segments/{id}/detect
2026-05-13 00:50:39 +02:00
Davide Scaini 12693dbd60 feat: scheduled Strava sync + admin suspend/delete account
- Add bincio sync-strava command: headless multi-user Strava sync
  designed for systemd timer. Discovers users via strava_token.json,
  skips users without their own strava_credentials.json, respects
  Strava visibility (only_me → unlisted). Treats 404 stream errors as
  no-GPS activities rather than retrying every run.
- Add deploy/systemd/bincio-sync.{service,timer}: runs every 3 hours,
  Persistent=true to catch up after downtime.
- Add POST /api/internal/rebuild: webhook for sync timer to trigger
  site rebuild, authenticated via X-Sync-Secret header.
- Add suspended column to users table with auto-migration on open_db.
  Suspended users are blocked at login and session lookup (covers both
  activity site and wiki, which share instance.db).
- Add POST /api/admin/users/{handle}/suspend|unsuspend and
  DELETE /api/admin/users/{handle}/account endpoints.
- Admin panel: Suspend/Unsuspend toggle, Del account button, suspended
  badge on user row.
2026-05-08 10:36:21 +02:00
Davide Scaini 1a563012e2 reextract-originals: run as subprocess to avoid OOM
The in-process approach loaded all 2015 Strava originals into the server
process memory, causing OOM kills. Now spawns `bincio reextract-originals`
as a child process; heavy work runs in an isolated Python interpreter that
exits when done, freeing all memory.

Also adds `bincio reextract-originals` as a standalone CLI command that
prints JSON-lines progress to stdout — useful for running directly on the
VPS via SSH for large backlogs.
2026-04-15 09:42:31 +02:00
Davide Scaini 98c42dc443 unify single user and multi user behaviour 2026-04-09 08:59:40 +02:00
Davide Scaini f76cc0ce7e towards multi-user 2026-04-08 19:37:10 +02:00
Davide Scaini d806072546 improve configs, update docs 2026-03-30 13:30:43 +02:00
Davide Scaini 1d3848f85e feat: activity sidecar edits via bincio edit --serve
- bincio/render/merge.py: parse sidecar .md files (YAML frontmatter +
     markdown body), produce data/_merged/ with symlinks for unmodified
     activities and real merged files for overridden ones; filters private
     activities from index.json; sorts highlighted activities first.
     Keeps extracted data pristine — re-running extract never clobbers edits.

   - bincio/edit/: FastAPI edit server (port 4041) with embedded HTML/JS
     edit UI; GET/POST /api/activity/{id} reads/writes sidecars; multipart
     image upload to edits/images/{id}/; DELETE for image cleanup.

   - bincio render now calls merge_all() before build/serve and symlinks
     public/data → data/_merged/ instead of data/ directly.

   - ActivityDetail.svelte: edit button (links to edit server) when
     PUBLIC_EDIT_URL env var is set; respects custom.hide_stats to suppress
     stat panels; description supports whitespace-preserving rendering.

   - 15 unit tests covering parse_sidecar, apply_sidecar, and merge_all.
2026-03-29 15:06:55 +02:00
Davide Scaini 38c5423aeb backend: initial commit 2026-03-28 13:59:36 +01:00