From 1d39cf68e596df162f0a7b2b77ca29e9e06c2bc0 Mon Sep 17 00:00:00 2001 From: FairTrade Date: Wed, 4 Mar 2026 19:39:32 +0100 Subject: [PATCH] Fixed NPO retrieving all seasons in series --- NPO/__init__.py | 58 +++++++++++++++++++++++++++++++++++-------------- NPO/config.yaml | 5 +++-- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/NPO/__init__.py b/NPO/__init__.py index 98c9b74..928b5d4 100644 --- a/NPO/__init__.py +++ b/NPO/__init__.py @@ -105,41 +105,67 @@ class NPO(Service): def get_titles(self) -> Titles_T: next_data = self._fetch_next_data(self.slug) - build_id = next_data["buildId"] # keep if needed elsewhere - page_props = next_data["props"]["pageProps"] queries = page_props["dehydratedState"]["queries"] - def get_data(fragment: str): + def get_query_data(fragment: str): return next((q["state"]["data"] for q in queries if fragment in str(q.get("queryKey", ""))), None) if self.kind == "serie": - series_data = get_data("series:detail-") + series_data = get_query_data("series:detail-") if not series_data: raise ValueError("Series metadata not found") - episodes = [] - seasons = get_data("series:seasons-") or [] - for season in seasons: - eps = get_data(f"programs:season-{season['guid']}") or [] - for e in eps: - episodes.append( + # Get list of all available seasons + seasons_list = get_query_data("series:seasons-") or [] + if not seasons_list: + self.log.warning("No seasons found for this series.") + + all_episodes = [] + series_type = series_data.get("type", "timeless_series") + + for season in seasons_list: + season_guid = season["guid"] + season_number = int(season.get("seasonKey", 0)) + + # Try to find episode data in the initial page data first + eps_data = get_query_data(f"programs:season-{season_guid}") + + # If not in initial data, fetch from the API + if not eps_data: + r = self.session.get( + self.config["endpoints"]["series_episodes"], + params={ + "guid": season_guid, + "type": series_type, + "includePremiumContent": "true" + } + ) + if r.ok: + eps_data = r.json() + + if not eps_data: + continue + + for e in eps_data: + all_episodes.append( Episode( id_=e["guid"], service=self.__class__, title=series_data["title"], - season=int(season["seasonKey"]), - number=int(e["programKey"]), - name=e["title"], + season=season_number, + number=int(e.get("programKey") or 0), + name=e.get("title"), description=(e.get("synopsis", {}) or {}).get("long", ""), language=Language.get("nl"), data=e, ) ) - return Series(episodes) + + return Series(all_episodes) - # Movie - item = get_data("program:detail-") or queries[0]["state"]["data"] + # Movie Logic + item = get_query_data("program:detail-") or queries[0]["state"]["data"] synopsis = item.get("synopsis", {}) desc = synopsis.get("long") or synopsis.get("short", "") if isinstance(synopsis, dict) else str(synopsis) year = (int(item["firstBroadcastDate"]) // 31536000 + 1970) if item.get("firstBroadcastDate") else None diff --git a/NPO/config.yaml b/NPO/config.yaml index b4546f6..42990ef 100644 --- a/NPO/config.yaml +++ b/NPO/config.yaml @@ -2,9 +2,10 @@ endpoints: metadata: "https://npo.nl/start/_next/data/{build_id}/video/{slug}.json" metadata_series: "https://npo.nl/start/_next/data/{build_id}/serie/{slug}/afleveringen.json" metadata_episode: "https://npo.nl/start/_next/data/{build_id}/serie/{series_slug}/seizoen-{season_slug}/{episode_slug}.json" + series_episodes: "https://npo.nl/start/api/domain/programs-by-season" streams: "https://prod.npoplayer.nl/stream-link" player_token: "https://npo.nl/start/api/domain/player-token?productId={product_id}" license: "https://npo-drm-gateway.samgcloud.nepworldwide.nl/authentication" homepage: "https://npo.nl/start" - search: " https://npo.nl/start/api/domain/search-collection-items" -DrmType: "widevine" \ No newline at end of file + search: "https://npo.nl/start/api/domain/search-collection-items" +DrmType: "widevine"