Pass series URLs through navigation for faster serienstream

This commit is contained in:
2026-02-01 21:37:50 +01:00
parent 3689aedd23
commit 09c6a32043
2 changed files with 73 additions and 14 deletions

View File

@@ -944,11 +944,12 @@ def _show_plugin_search_results(plugin_name: str, query: str) -> None:
display_label = _label_with_duration(title, info_labels)
display_label = _label_with_playstate(display_label, playstate)
direct_play = bool(plugin_name.casefold() == "einschalten" and _get_setting_bool("einschalten_enable_playback", default=False))
extra_params = _series_url_params(plugin, title)
_add_directory_item(
handle,
display_label,
"play_movie" if direct_play else "seasons",
{"plugin": plugin_name, "title": title},
{"plugin": plugin_name, "title": title, **extra_params},
is_folder=not direct_play,
info_labels=merged_info,
art=art,
@@ -1025,6 +1026,17 @@ def _run_async(coro):
return asyncio.run(coro)
def _series_url_params(plugin: BasisPlugin, title: str) -> dict[str, str]:
getter = getattr(plugin, "series_url_for_title", None)
if not callable(getter):
return {}
try:
series_url = str(getter(title) or "").strip()
except Exception:
return {}
return {"series_url": series_url} if series_url else {}
def _show_search() -> None:
_log("Suche gestartet.")
dialog = xbmcgui.Dialog()
@@ -1071,11 +1083,12 @@ def _show_search_results(query: str) -> None:
direct_play = bool(
plugin_name.casefold() == "einschalten" and _get_setting_bool("einschalten_enable_playback", default=False)
)
extra_params = _series_url_params(plugin, title)
_add_directory_item(
handle,
label,
"play_movie" if direct_play else "seasons",
{"plugin": plugin_name, "title": title},
{"plugin": plugin_name, "title": title, **extra_params},
is_folder=not direct_play,
info_labels=merged_info,
art=art,
@@ -1084,7 +1097,7 @@ def _show_search_results(query: str) -> None:
xbmcplugin.endOfDirectory(handle)
def _show_seasons(plugin_name: str, title: str) -> None:
def _show_seasons(plugin_name: str, title: str, series_url: str = "") -> None:
handle = _get_handle()
_log(f"Staffeln laden: {plugin_name} / {title}")
plugin = _discover_plugins().get(plugin_name)
@@ -1092,6 +1105,13 @@ def _show_seasons(plugin_name: str, title: str) -> None:
xbmcgui.Dialog().notification("Staffeln", "Plugin nicht gefunden.", xbmcgui.NOTIFICATION_INFO, 3000)
xbmcplugin.endOfDirectory(handle)
return
if series_url:
remember_series_url = getattr(plugin, "remember_series_url", None)
if callable(remember_series_url):
try:
remember_series_url(title, series_url)
except Exception:
pass
# Einschalten liefert Filme. Für Playback soll nach dem Öffnen des Titels direkt ein
# einzelnes abspielbares Item angezeigt werden: <Titel> -> (<Titel> abspielbar).
@@ -1227,7 +1247,7 @@ def _show_seasons(plugin_name: str, title: str) -> None:
handle,
_label_with_playstate(season, season_state),
"episodes",
{"plugin": plugin_name, "title": title, "season": season},
{"plugin": plugin_name, "title": title, "season": season, "series_url": series_url},
is_folder=True,
info_labels=merged_labels or None,
art=merged_art,
@@ -1236,7 +1256,7 @@ def _show_seasons(plugin_name: str, title: str) -> None:
xbmcplugin.endOfDirectory(handle)
def _show_episodes(plugin_name: str, title: str, season: str) -> None:
def _show_episodes(plugin_name: str, title: str, season: str, series_url: str = "") -> None:
handle = _get_handle()
_log(f"Episoden laden: {plugin_name} / {title} / {season}")
plugin = _discover_plugins().get(plugin_name)
@@ -1244,6 +1264,13 @@ def _show_episodes(plugin_name: str, title: str, season: str) -> None:
xbmcgui.Dialog().notification("Episoden", "Plugin nicht gefunden.", xbmcgui.NOTIFICATION_INFO, 3000)
xbmcplugin.endOfDirectory(handle)
return
if series_url:
remember_series_url = getattr(plugin, "remember_series_url", None)
if callable(remember_series_url):
try:
remember_series_url(title, series_url)
except Exception:
pass
season_number = _extract_first_int(season)
if season_number is not None:
xbmcplugin.setPluginCategory(handle, f"{title} - Staffel {season_number}")
@@ -1439,7 +1466,7 @@ def _show_genre_titles_page(plugin_name: str, genre: str, page: int = 1) -> None
handle,
display_label,
"play_movie" if direct_play else "seasons",
{"plugin": plugin_name, "title": title},
{"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)},
is_folder=not direct_play,
info_labels=info_labels,
art=art,
@@ -1456,7 +1483,7 @@ def _show_genre_titles_page(plugin_name: str, genre: str, page: int = 1) -> None
handle,
_label_with_playstate(title, playstate),
"play_movie" if direct_play else "seasons",
{"plugin": plugin_name, "title": title},
{"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)},
is_folder=not direct_play,
info_labels=_apply_playstate_to_info({"title": title}, playstate),
)
@@ -1672,7 +1699,7 @@ def _show_popular(plugin_name: str | None = None, page: int = 1) -> None:
handle,
display_label,
"seasons",
{"plugin": plugin_name, "title": title},
{"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)},
is_folder=True,
info_labels=info_labels,
art=art,
@@ -1685,7 +1712,7 @@ def _show_popular(plugin_name: str | None = None, page: int = 1) -> None:
handle,
_label_with_playstate(title, playstate),
"seasons",
{"plugin": plugin_name, "title": title},
{"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)},
is_folder=True,
info_labels=_apply_playstate_to_info({"title": title}, playstate),
)
@@ -1817,7 +1844,7 @@ def _show_new_titles(plugin_name: str, page: int = 1) -> None:
handle,
display_label,
"play_movie" if direct_play else "seasons",
{"plugin": plugin_name, "title": title},
{"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)},
is_folder=not direct_play,
info_labels=info_labels,
art=art,
@@ -1834,7 +1861,7 @@ def _show_new_titles(plugin_name: str, page: int = 1) -> None:
handle,
_label_with_playstate(title, playstate),
"play_movie" if direct_play else "seasons",
{"plugin": plugin_name, "title": title},
{"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)},
is_folder=not direct_play,
info_labels=_apply_playstate_to_info({"title": title}, playstate),
)
@@ -1986,7 +2013,7 @@ def _show_genre_series_group(plugin_name: str, genre: str, group_code: str, page
handle,
display_label,
"seasons",
{"plugin": plugin_name, "title": title},
{"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)},
is_folder=True,
info_labels=info_labels,
art=art,
@@ -1999,7 +2026,7 @@ def _show_genre_series_group(plugin_name: str, genre: str, group_code: str, page
handle,
_label_with_playstate(title, playstate),
"seasons",
{"plugin": plugin_name, "title": title},
{"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)},
is_folder=True,
info_labels=_apply_playstate_to_info({"title": title}, playstate),
)
@@ -2373,12 +2400,13 @@ def run() -> None:
elif action == "settings":
_open_settings()
elif action == "seasons":
_show_seasons(params.get("plugin", ""), params.get("title", ""))
_show_seasons(params.get("plugin", ""), params.get("title", ""), params.get("series_url", ""))
elif action == "episodes":
_show_episodes(
params.get("plugin", ""),
params.get("title", ""),
params.get("season", ""),
params.get("series_url", ""),
)
elif action == "play_episode":
_play_episode(

View File

@@ -835,6 +835,17 @@ class SerienstreamPlugin(BasisPlugin):
if cached is not None:
return list(cached)
series = self._series_results.get(title)
if not series:
catalog = self._ensure_catalog()
lookup_key = title.casefold().strip()
for entries in catalog.values():
for entry in entries:
if entry.title.casefold().strip() == lookup_key:
series = entry
self._series_results[entry.title] = entry
break
if series:
break
if not series:
return []
try:
@@ -844,6 +855,26 @@ class SerienstreamPlugin(BasisPlugin):
self._season_links_cache[title] = list(seasons)
return list(seasons)
def remember_series_url(self, title: str, series_url: str) -> None:
title = (title or "").strip()
series_url = (series_url or "").strip()
if not title or not series_url:
return
self._series_results[title] = SeriesResult(title=title, description="", url=series_url)
def series_url_for_title(self, title: str) -> str:
title = (title or "").strip()
if not title:
return ""
direct = self._series_results.get(title)
if direct and direct.url:
return direct.url
lookup_key = title.casefold().strip()
for entry in self._series_results.values():
if entry.title.casefold().strip() == lookup_key and entry.url:
return entry.url
return ""
def _ensure_season_episodes(self, title: str, season_number: int) -> Optional[SeasonInfo]:
seasons = self._season_cache.get(title) or []
for season in seasons: