From e5d93e3af6b51166369a716106e97bb2dfbb22af Mon Sep 17 00:00:00 2001 From: "itdrui.de" Date: Tue, 31 Mar 2026 20:57:51 +0200 Subject: [PATCH] =?UTF-8?q?dev:=20bump=20to=200.1.84.5-dev=20SerienStream?= =?UTF-8?q?=20Sammlungen=20mit=20Poster/Plot,=20Session-Cache=20f=C3=BCr?= =?UTF-8?q?=20Sammlungs-URLs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG-DEV.md | 4 ++ addon/addon.xml | 2 +- addon/default.py | 32 +++++++++++++--- addon/plugins/serienstream_plugin.py | 56 +++++++++++++++++++++++++++- 4 files changed, 86 insertions(+), 8 deletions(-) diff --git a/CHANGELOG-DEV.md b/CHANGELOG-DEV.md index 7b38eea..7295e48 100644 --- a/CHANGELOG-DEV.md +++ b/CHANGELOG-DEV.md @@ -1,3 +1,7 @@ +## 0.1.84.0-dev - 2026-03-16 + +- dev: bump to 0.1.83.5-dev Trakt Weiterschauen via watched/shows, Specials überspringen + ## 0.1.83.5-dev - 2026-03-15 - dev: SerienStream Suche via /suche?term=, Staffel 0 als Filme, Katalog-Suche entfernt diff --git a/addon/addon.xml b/addon/addon.xml index 040451e..f31d34a 100644 --- a/addon/addon.xml +++ b/addon/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/addon/default.py b/addon/default.py index d97b994..4a80f8b 100644 --- a/addon/default.py +++ b/addon/default.py @@ -4765,13 +4765,33 @@ def _show_collection_titles_page(plugin_name: str, collection: str, page: int = xbmcplugin.endOfDirectory(handle) return titles = [str(t).strip() for t in titles if t and str(t).strip()] - direct_play = bool(plugin_name.casefold() == "einschalten" - and _get_setting_bool("einschalten_enable_playback", default=False)) - for title in titles: - _add_directory_item(handle, title, "play_movie" if direct_play else "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=not direct_play) if titles: + use_source, show_tmdb, prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_list_enabled() + ) + plugin_meta = _collect_plugin_metadata(plugin, titles) if use_source else {} + show_plot = _get_setting_bool("tmdb_show_plot", default=True) + show_art = _get_setting_bool("tmdb_show_art", default=True) + tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {} + tmdb_titles = list(titles) if show_tmdb else [] + if show_tmdb and prefer_source and use_source: + tmdb_titles = [ + t for t in titles + if _needs_tmdb((plugin_meta.get(t) or ({},))[0], (plugin_meta.get(t) or ({}, {}))[1], + want_plot=show_plot, want_art=show_art) + ] + if show_tmdb and tmdb_titles: + with _busy_dialog(f"{collection} wird geladen..."): + tmdb_prefetched = _tmdb_labels_and_art_bulk(tmdb_titles) + for title in titles: + tmdb_info, tmdb_art, tmdb_cast = tmdb_prefetched.get(title, ({}, {}, [])) if show_tmdb else ({}, {}, []) + meta = plugin_meta.get(title) + info_labels, art, cast = _merge_metadata(title, tmdb_info, tmdb_art, tmdb_cast, meta) + info_labels = dict(info_labels or {}) + info_labels.setdefault("mediatype", "tvshow") + _add_directory_item(handle, title, "seasons", + {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, + is_folder=True, info_labels=info_labels, art=art, cast=cast) _add_directory_item(handle, "Naechste Seite", "collection_titles_page", {"plugin": plugin_name, "collection": collection, "page": str(page + 1)}, is_folder=True) xbmcplugin.endOfDirectory(handle) diff --git a/addon/plugins/serienstream_plugin.py b/addon/plugins/serienstream_plugin.py index a8c0da7..0e21e91 100644 --- a/addon/plugins/serienstream_plugin.py +++ b/addon/plugins/serienstream_plugin.py @@ -1027,6 +1027,7 @@ class SerienstreamPlugin(BasisPlugin): self._latest_hoster_cache: dict[str, list[str]] = {} self._series_metadata_cache: dict[str, tuple[dict[str, str], dict[str, str]]] = {} self._series_metadata_full: set[str] = set() + self._collection_url_cache: dict[str, str] = {} self.is_available = True self.unavailable_reason: str | None = None if not self._requests_available: # pragma: no cover - optional dependency @@ -1251,7 +1252,60 @@ class SerienstreamPlugin(BasisPlugin): def capabilities(self) -> set[str]: """Meldet unterstützte Features für Router-Menüs.""" - return {"popular_series", "genres", "latest_episodes", "alpha"} + return {"popular_series", "genres", "latest_episodes", "alpha", "collections"} + + def collections(self) -> list[str]: + """Liefert alle Sammlungs-Namen von /sammlungen (alle Seiten).""" + if not self._requests_available: + return [] + base = _get_base_url() + names: list[str] = [] + url_map: dict[str, str] = {} + page = 1 + while True: + url = f"{base}/sammlungen" if page == 1 else f"{base}/sammlungen?page={page}" + soup = _get_soup_simple(url) + found = False + for a in soup.select('a[href*="/sammlung/"]'): + h2 = a.find("h2") + if not h2: + continue + title = h2.get_text(strip=True) + href = (a.get("href") or "").strip() + if title and href: + url_map[title] = _absolute_url(href) + names.append(title) + found = True + if not found: + break + if not soup.select(f'a[href*="/sammlungen?page={page + 1}"]'): + break + page += 1 + if url_map: + _session_cache_set("collection_urls", url_map) + return names + + def titles_for_collection(self, collection: str, page: int = 1) -> list[str]: + """Liefert Serien-Titel einer Sammlung (paginiert).""" + if not self._requests_available: + return [] + url_map = _session_cache_get("collection_urls") + if isinstance(url_map, dict): + self._collection_url_cache.update(url_map) + url = self._collection_url_cache.get(collection) + if not url: + return [] + if page > 1: + url = f"{url}?page={page}" + soup = _get_soup_simple(url) + titles: list[str] = [] + for a in soup.select('h6 a[href*="/serie/"]'): + title = a.get_text(strip=True) + href = (a.get("href") or "").strip() + if title and href: + self._remember_series_result(title, _absolute_url(href), "") + titles.append(title) + return titles def popular_series(self) -> list[str]: """Liefert die Titel der beliebten Serien (Quelle: `/beliebte-serien`)."""