35 lines
1.2 KiB
Python
35 lines
1.2 KiB
Python
|
|
"""HTTP client for diora's sync API (see the repo's CLAUDE.md, "Sync API for
|
||
|
|
local clients"). Status: that API is provisional — expect endpoint/field
|
||
|
|
changes as the server-side implementation settles.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import requests
|
||
|
|
|
||
|
|
|
||
|
|
class ApiError(Exception):
|
||
|
|
pass
|
||
|
|
|
||
|
|
|
||
|
|
def _headers(token: str) -> dict[str, str]:
|
||
|
|
return {"Authorization": f"Bearer {token}"}
|
||
|
|
|
||
|
|
|
||
|
|
def fetch_sync_snapshot(server_url: str, token: str) -> dict:
|
||
|
|
resp = requests.get(f"{server_url}/api/sync/", headers=_headers(token), timeout=30)
|
||
|
|
if resp.status_code == 401:
|
||
|
|
raise ApiError("Authentifizierung fehlgeschlagen — Token falsch oder abgelaufen?")
|
||
|
|
resp.raise_for_status()
|
||
|
|
return resp.json()
|
||
|
|
|
||
|
|
|
||
|
|
def fetch_book_data(server_url: str, token: str, book_id: int) -> dict:
|
||
|
|
resp = requests.get(f"{server_url}/books/{book_id}/data/", headers=_headers(token), timeout=120)
|
||
|
|
if resp.status_code == 401:
|
||
|
|
raise ApiError("Authentifizierung fehlgeschlagen — Token falsch oder abgelaufen?")
|
||
|
|
if resp.status_code == 404:
|
||
|
|
raise ApiError(f"Buch {book_id} nicht gefunden (falscher Owner oder gelöscht?)")
|
||
|
|
resp.raise_for_status()
|
||
|
|
return resp.json()
|