routes/plex/browse.py was a 1693-line god-module (libraries + facets + collections + playlists + show/item detail + people). Split it into focused sibling routers under the same /api/plex prefix — pure code motion, no SQL / route-path / response-shape changes: browse.py 1693 -> 469 (list_libraries, unified_library, facets) collections.py (new 253) browse + admin collection editor; owns _collection_source playlists.py (new 405) the user's orderable playlists detail.py (new 438) show/item detail + enrichment; _lib_key lives here people.py (new 139) cast/crew chips + person filmography Cross-module helpers _norm_lang + _content_libs move to _shared.py (their one home); detail imports _collection_source from collections (one-way, no cycle). __init__.py includes the four new routers. Three DB-lane tests follow the moved symbols (import path for _content_libs; monkeypatch targets for PlexClient / _show_enrichment now on detail). Behaviour-equivalent: ruff clean, 348 DB-lane pass (unchanged), parity net green.
42 lines
1.4 KiB
Python
42 lines
1.4 KiB
Python
"""Shared helpers, serializers and constants for the plex route package."""
|
|
|
|
import logging
|
|
|
|
from fastapi import HTTPException
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.models import (
|
|
PlexItem,
|
|
PlexLibrary,
|
|
)
|
|
from app.plex.lookups import by_rating_key
|
|
|
|
log = logging.getLogger("siftlode.plex")
|
|
|
|
|
|
def item_or_404(db: Session, rating_key: str) -> PlexItem:
|
|
it = by_rating_key(db, PlexItem, rating_key)
|
|
if it is None:
|
|
raise HTTPException(status_code=404, detail="Unknown Plex item")
|
|
return it
|
|
|
|
|
|
def _norm_lang(lang: str | None) -> str:
|
|
"""The overlay has an EN base + an optional HU twin; anything other than `hu` serves EN."""
|
|
return "hu" if lang == "hu" else "en"
|
|
|
|
|
|
def _content_libs(db: Session) -> tuple[list[int], list[int]]:
|
|
"""The BROWSABLE content libraries, partitioned into (movie_lib_ids, show_lib_ids) — the single
|
|
source of the browse scope. Excludes HU overlay libraries (`overlay_of` set): those are never
|
|
browsed on their own, they only lend their Hungarian metadata to the EN twin's rows (E5 S5)."""
|
|
libs = db.execute(
|
|
select(PlexLibrary).where(
|
|
PlexLibrary.enabled.is_(True), PlexLibrary.overlay_of.is_(None)
|
|
)
|
|
).scalars().all()
|
|
movie_lib_ids = [lb.id for lb in libs if lb.kind == "movie"]
|
|
show_lib_ids = [lb.id for lb in libs if lb.kind == "show"]
|
|
return movie_lib_ids, show_lib_ids
|