"""Thin wrapper around the bits of the Immich API this project needs.""" from __future__ import annotations import httpx class ImmichClient: def __init__(self, base_url: str, api_key: str): self.base_url = base_url.rstrip("/") self._headers = {"x-api-key": api_key} def list_albums(self) -> list[dict]: resp = httpx.get(f"{self.base_url}/api/albums", headers=self._headers, timeout=10) resp.raise_for_status() return resp.json() def list_album_assets(self, album_id: str) -> list[dict]: """GET /api/albums/{id} doesn't embed assets in this Immich version (AlbumResponseDto only has assetCount) -- assets live behind the general search API instead, filtered by albumIds. Only returns the first page. Fine for a photo frame cycling through an album; worth adding nextPage pagination if someone points this at an album large enough to need it. """ resp = httpx.post( f"{self.base_url}/api/search/metadata", headers=self._headers, json={"albumIds": [album_id]}, timeout=15, ) resp.raise_for_status() return resp.json().get("assets", {}).get("items", []) def download_asset_preview(self, asset_id: str) -> bytes: resp = httpx.get( f"{self.base_url}/api/assets/{asset_id}/thumbnail", params={"size": "preview"}, headers=self._headers, timeout=30, ) resp.raise_for_status() return resp.content