"""Per-user watch history. Every query here is scoped to a single ``user_id`` via the ``/Users/{id}/Items`` endpoint, so one user's history is never mixed with another's. """ from __future__ import annotations from .emby_collections import ITEM_FIELDS, normalize_item # Movies and series are what we recommend; episodes are folded into their series. WATCHED_ITEM_TYPES = "Movie,Series" async def get_watched_items(client, user_id: str, item_types: str = WATCHED_ITEM_TYPES) -> list[dict]: """Return the user's played items (normalized) for the given types.""" if not user_id: return [] raw_items = await client.get_all( f"/Users/{user_id}/Items", { "Recursive": "true", "IsPlayed": "true", "Filters": "IsPlayed", "IncludeItemTypes": item_types, "Fields": ITEM_FIELDS, "EnableUserData": "true", }, ) return [normalize_item(raw) for raw in raw_items] async def get_watched_item_ids(client, user_id: str, item_types: str = WATCHED_ITEM_TYPES) -> set[str]: """Return the set of item ids the user has watched.""" return {item["id"] for item in await get_watched_items(client, user_id, item_types) if item["id"]} async def is_item_watched(client, user_id: str, item_id: str) -> bool: """Whether ``user_id`` has played ``item_id`` (user-specific).""" if not (user_id and item_id): return False data = await client.get( f"/Users/{user_id}/Items", {"Ids": item_id, "EnableUserData": "true"}, ) items = data.get("Items", []) if isinstance(data, dict) else (data or []) if not items: return False user_data = items[0].get("UserData") or {} return bool(user_data.get("Played", False))