From 8a8087ae9972e46d2810a2089cf93e24ca4e1c67 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Mon, 6 Jul 2026 06:49:43 +0200 Subject: [PATCH] feat(plex): classify collection-strip source (franchise/imdb/tmdb/smart) Derive a `source` bucket per collection from the already-synced title + smart flag (no schema change, no re-sync): external list providers (IMDb/TMDb/TVDb/ Trakt) by leading token, Plex smart lists via the smart flag, everything else a genuine "collection". Returned on each info-page collection strip so the client can show/hide each type independently. Adds the stripSource labels (en/hu/de). --- backend/app/routes/plex.py | 25 ++++++++++++++++++++++++- frontend/src/i18n/locales/de/plex.json | 8 ++++++++ frontend/src/i18n/locales/en/plex.json | 8 ++++++++ frontend/src/i18n/locales/hu/plex.json | 8 ++++++++ frontend/src/lib/api.ts | 4 +++- 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/backend/app/routes/plex.py b/backend/app/routes/plex.py index 77638a4..d7b6f81 100644 --- a/backend/app/routes/plex.py +++ b/backend/app/routes/plex.py @@ -684,6 +684,22 @@ def person_image(u: str, _: User = Depends(current_user)) -> Response: return _img_response(r.content, ct) +# Known external list providers that seed Plex collections (via plextraktsync et al). A collection's +# "source" buckets the info-page strips so the user can show/hide each type independently (e.g. hide +# the noisy 'IMDb Popular'/'TMDb Trending' auto-lists but keep genuine franchise collections). Derived +# from the already-synced title/smart — no schema change, no re-sync. Unknown providers stay "collection". +_STRIP_PROVIDERS = ("imdb", "tmdb", "tvdb", "trakt") + + +def _collection_source(col: PlexCollection) -> str: + first = (col.title or "").strip().split(" ", 1)[0].lower() + if first in _STRIP_PROVIDERS: + return first + if col.smart: + return "smart" + return "collection" + + def _collection_strips(db: Session, it: PlexItem, user_id: int) -> list[dict]: """The collections this movie belongs to, each with its member titles (playable cards) — the 'Avatar Collection' strip on the info page. Pure local lookup (no Plex call).""" @@ -714,7 +730,14 @@ def _collection_strips(db: Session, it: PlexItem, user_id: int) -> list[dict]: PlexState.user_id == user_id, PlexState.item_id.in_(ids or [0]) ) } - out.append({"id": rk, "title": col.title, "items": [_movie_card(m, states.get(m.id)) for m in members]}) + out.append( + { + "id": rk, + "title": col.title, + "source": _collection_source(col), + "items": [_movie_card(m, states.get(m.id)) for m in members], + } + ) return out diff --git a/frontend/src/i18n/locales/de/plex.json b/frontend/src/i18n/locales/de/plex.json index 4882360..8c9bd70 100644 --- a/frontend/src/i18n/locales/de/plex.json +++ b/frontend/src/i18n/locales/de/plex.json @@ -98,6 +98,14 @@ "customize": "Ansicht anpassen", "prefArtBg": "Dezenter Hintergrund", "prefCast": "Besetzung", + "stripSource": { + "collection": "Sammlungen", + "imdb": "IMDb", + "tmdb": "TMDb", + "tvdb": "TVDb", + "trakt": "Trakt", + "smart": "Smart-Listen" + }, "openImdb": "Bei IMDb öffnen", "director": "Regie", "cast": "Besetzung & Crew", diff --git a/frontend/src/i18n/locales/en/plex.json b/frontend/src/i18n/locales/en/plex.json index c8aa1d4..ce7d554 100644 --- a/frontend/src/i18n/locales/en/plex.json +++ b/frontend/src/i18n/locales/en/plex.json @@ -98,6 +98,14 @@ "customize": "Customize view", "prefArtBg": "Faint backdrop", "prefCast": "Cast & crew", + "stripSource": { + "collection": "Collections", + "imdb": "IMDb", + "tmdb": "TMDb", + "tvdb": "TVDb", + "trakt": "Trakt", + "smart": "Smart lists" + }, "openImdb": "Open on IMDb", "director": "Director", "cast": "Cast & crew", diff --git a/frontend/src/i18n/locales/hu/plex.json b/frontend/src/i18n/locales/hu/plex.json index f9b6f95..3868d93 100644 --- a/frontend/src/i18n/locales/hu/plex.json +++ b/frontend/src/i18n/locales/hu/plex.json @@ -98,6 +98,14 @@ "customize": "Nézet testreszabása", "prefArtBg": "Halvány háttér", "prefCast": "Szereplők", + "stripSource": { + "collection": "Kollekciók", + "imdb": "IMDb", + "tmdb": "TMDb", + "tvdb": "TVDb", + "trakt": "Trakt", + "smart": "Smart listák" + }, "openImdb": "Megnyitás az IMDb-n", "director": "Rendező", "cast": "Szereplők & stáb", diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index fbac7ba..44a99c8 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -714,7 +714,9 @@ export interface PlexItemDetail { episode_number?: number | null; prev_id?: string | null; next_id?: string | null; - collections?: { id: string; title: string; items: PlexCard[] }[]; + // `source` buckets the strip so each type can be shown/hidden independently on the info page: + // "collection" (genuine franchise), "imdb"/"tmdb"/"tvdb"/"trakt" (external auto-lists), "smart". + collections?: { id: string; title: string; source: string; items: PlexCard[] }[]; } export interface PlexCollection { id: string;