fix strava import?
This commit is contained in:
+47
-19
@@ -76,24 +76,19 @@ def ingest_parsed(
|
||||
return activity_id
|
||||
|
||||
|
||||
def strava_sync(
|
||||
def strava_sync_iter(
|
||||
data_dir: Path,
|
||||
client_id: str,
|
||||
client_secret: str,
|
||||
originals_dir: Optional[Path] = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Fetch new Strava activities and ingest them into data_dir.
|
||||
):
|
||||
"""Generator version of strava_sync — yields progress dicts, then a final summary.
|
||||
|
||||
Args:
|
||||
data_dir: Per-user data directory.
|
||||
client_id: Strava OAuth client ID.
|
||||
client_secret: Strava OAuth client secret.
|
||||
|
||||
Returns:
|
||||
Dict with keys: ok, imported, skipped, error_count, errors.
|
||||
|
||||
Raises:
|
||||
RuntimeError: If Strava credentials are missing or API calls fail.
|
||||
Each yielded dict has a ``type`` key:
|
||||
- ``"fetching"`` — about to fetch the activity list from Strava
|
||||
- ``"progress"`` — one activity processed; keys: n, total, name, status ("imported"|"skipped"|"error")
|
||||
- ``"done"`` — final summary; keys: imported, skipped, error_count, errors
|
||||
- ``"error"`` — fatal error before processing started; key: message
|
||||
"""
|
||||
import time
|
||||
|
||||
@@ -109,28 +104,36 @@ def strava_sync(
|
||||
from bincio.extract.writer import make_activity_id
|
||||
|
||||
if not client_id or not client_secret:
|
||||
raise RuntimeError("Strava not configured (missing client_id or client_secret)")
|
||||
yield {"type": "error", "message": "Strava not configured"}
|
||||
return
|
||||
|
||||
try:
|
||||
token = ensure_fresh(data_dir, client_id, client_secret)
|
||||
except StravaError as e:
|
||||
raise RuntimeError(str(e)) from e
|
||||
yield {"type": "error", "message": str(e)}
|
||||
return
|
||||
|
||||
yield {"type": "fetching"}
|
||||
|
||||
after: Optional[int] = token.get("last_sync_at")
|
||||
try:
|
||||
activities = fetch_activities(token["access_token"], after=after)
|
||||
except StravaError as e:
|
||||
raise RuntimeError(str(e)) from e
|
||||
yield {"type": "error", "message": str(e)}
|
||||
return
|
||||
|
||||
total = len(activities)
|
||||
imported = 0
|
||||
skipped = 0
|
||||
errors: list[str] = []
|
||||
|
||||
for meta in activities:
|
||||
for n, meta in enumerate(activities, 1):
|
||||
name = meta.get("name", "Untitled")
|
||||
try:
|
||||
activity_id = make_activity_id(strava_meta_to_partial(meta))
|
||||
if (data_dir / "activities" / f"{activity_id}.json").exists():
|
||||
skipped += 1
|
||||
yield {"type": "progress", "n": n, "total": total, "name": name, "status": "skipped"}
|
||||
continue
|
||||
streams = fetch_streams(token["access_token"], meta["id"])
|
||||
if originals_dir is not None:
|
||||
@@ -142,16 +145,41 @@ def strava_sync(
|
||||
parsed = strava_to_parsed(meta, streams)
|
||||
ingest_parsed(parsed, data_dir, privacy="public", rdp_epsilon=0.0001)
|
||||
imported += 1
|
||||
yield {"type": "progress", "n": n, "total": total, "name": name, "status": "imported"}
|
||||
except Exception as exc:
|
||||
errors.append(f"{meta.get('id')}: {type(exc).__name__}")
|
||||
yield {"type": "progress", "n": n, "total": total, "name": name, "status": "error"}
|
||||
|
||||
token["last_sync_at"] = int(time.time())
|
||||
save_token(data_dir, token)
|
||||
|
||||
return {
|
||||
"ok": True,
|
||||
yield {
|
||||
"type": "done",
|
||||
"imported": imported,
|
||||
"skipped": skipped,
|
||||
"error_count": len(errors),
|
||||
"errors": errors[:5],
|
||||
}
|
||||
|
||||
|
||||
def strava_sync(
|
||||
data_dir: Path,
|
||||
client_id: str,
|
||||
client_secret: str,
|
||||
originals_dir: Optional[Path] = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Fetch new Strava activities and ingest them into data_dir.
|
||||
|
||||
Returns:
|
||||
Dict with keys: ok, imported, skipped, error_count, errors.
|
||||
|
||||
Raises:
|
||||
RuntimeError: If Strava credentials are missing or API calls fail.
|
||||
"""
|
||||
result: dict[str, Any] = {}
|
||||
for event in strava_sync_iter(data_dir, client_id, client_secret, originals_dir):
|
||||
if event["type"] == "error":
|
||||
raise RuntimeError(event["message"])
|
||||
if event["type"] == "done":
|
||||
result = event
|
||||
return {"ok": True, **{k: v for k, v in result.items() if k != "type"}}
|
||||
|
||||
Reference in New Issue
Block a user