nightly: bump to 0.1.60 and finalize menu, resolver, settings cleanup

This commit is contained in:
2026-02-23 20:21:44 +01:00
parent 7ba24532ad
commit ef531ea0aa
8 changed files with 188 additions and 147 deletions

View File

@@ -131,6 +131,7 @@ _TMDB_LOCK = threading.RLock()
WATCHED_THRESHOLD = 0.9
POPULAR_MENU_LABEL = "Haeufig gesehen"
LATEST_MENU_LABEL = "Neuste Titel"
LIST_PAGE_SIZE = 20
atexit.register(close_all_sessions)
@@ -305,10 +306,6 @@ def _playstate_key(*, plugin_name: str, title: str, season: str, episode: str) -
return f"{plugin_name}\t{title}\t{season}\t{episode}"
def _playstate_path() -> str:
return _get_log_path("playstate.json")
def _load_playstate() -> dict[str, dict[str, object]]:
return {}
@@ -2574,7 +2571,7 @@ def _plugins_with_popular() -> list[tuple[str, BasisPlugin, str]]:
def _show_popular(plugin_name: str | None = None, page: int = 1) -> None:
handle = _get_handle()
page_size = 10
page_size = LIST_PAGE_SIZE
page = max(1, int(page or 1))
if plugin_name:
@@ -2701,7 +2698,7 @@ def _show_popular(plugin_name: str | None = None, page: int = 1) -> None:
def _show_new_titles(plugin_name: str, page: int = 1, *, action_name: str = "new_titles") -> None:
handle = _get_handle()
page_size = 10
page_size = LIST_PAGE_SIZE
page = max(1, int(page or 1))
plugin_name = (plugin_name or "").strip()
@@ -2949,7 +2946,7 @@ def _show_latest_titles(plugin_name: str, page: int = 1) -> None:
def _show_genre_series_group(plugin_name: str, genre: str, group_code: str, page: int = 1) -> None:
handle = _get_handle()
page_size = 10
page_size = LIST_PAGE_SIZE
page = max(1, int(page or 1))
plugin = _discover_plugins().get(plugin_name)
if plugin is None:
@@ -3182,23 +3179,28 @@ def _extract_first_int(value: str) -> int | None:
return None
def _duration_label(duration_seconds: int) -> str:
try:
duration_seconds = int(duration_seconds or 0)
except Exception:
duration_seconds = 0
if duration_seconds <= 0:
return ""
total_minutes = max(0, duration_seconds // 60)
hours = max(0, total_minutes // 60)
minutes = max(0, total_minutes % 60)
return f"{hours:02d}:{minutes:02d} Laufzeit"
def _label_with_duration(label: str, info_labels: dict[str, str] | None) -> str:
return label
def _resolveurl_last_error() -> str:
try:
from resolveurl_backend import get_last_error # type: ignore
except Exception:
return ""
try:
return str(get_last_error() or "")
except Exception:
return ""
def _is_cloudflare_challenge_error(message: str) -> bool:
text = str(message or "").casefold()
if not text:
return False
return "cloudflare" in text or "challenge" in text or "attention required" in text
def _play_final_link(
link: str,
*,
@@ -3242,10 +3244,6 @@ def _play_final_link(
player.play(item=link, listitem=list_item)
def _track_playback_and_update_state(key: str) -> None:
return
def _track_playback_and_update_state_async(key: str) -> None:
# Eigenes Resume/Watched ist deaktiviert; Kodi verwaltet das selbst.
return
@@ -3334,8 +3332,30 @@ def _play_episode(
xbmcgui.Dialog().notification("Wiedergabe", "Kein Stream gefunden.", xbmcgui.NOTIFICATION_INFO, 3000)
return
_log(f"Stream-Link: {link}", xbmc.LOGDEBUG)
final_link = plugin.resolve_stream_link(link) or link
resolved_link = plugin.resolve_stream_link(link)
if not resolved_link:
err = _resolveurl_last_error()
if _is_cloudflare_challenge_error(err):
_log(f"ResolveURL Cloudflare-Challenge: {err}", xbmc.LOGWARNING)
xbmcgui.Dialog().notification(
"Wiedergabe",
"Hoster durch Cloudflare geschuetzt. Bitte spaeter erneut probieren.",
xbmcgui.NOTIFICATION_INFO,
4500,
)
return
final_link = resolved_link or link
final_link = normalize_resolved_stream_url(final_link, source_url=link)
err = _resolveurl_last_error()
if _is_cloudflare_challenge_error(err) and final_link.strip() == link.strip():
_log(f"ResolveURL Cloudflare-Challenge (unresolved): {err}", xbmc.LOGWARNING)
xbmcgui.Dialog().notification(
"Wiedergabe",
"Hoster durch Cloudflare geschuetzt. Bitte spaeter erneut probieren.",
xbmcgui.NOTIFICATION_INFO,
4500,
)
return
finally:
if restore_hosters is not None and callable(preferred_setter):
preferred_setter(restore_hosters)
@@ -3422,8 +3442,30 @@ def _play_episode_url(
xbmcgui.Dialog().notification("Wiedergabe", "Kein Stream gefunden.", xbmcgui.NOTIFICATION_INFO, 3000)
return
_log(f"Stream-Link: {link}", xbmc.LOGDEBUG)
final_link = plugin.resolve_stream_link(link) or link
resolved_link = plugin.resolve_stream_link(link)
if not resolved_link:
err = _resolveurl_last_error()
if _is_cloudflare_challenge_error(err):
_log(f"ResolveURL Cloudflare-Challenge: {err}", xbmc.LOGWARNING)
xbmcgui.Dialog().notification(
"Wiedergabe",
"Hoster durch Cloudflare geschuetzt. Bitte spaeter erneut probieren.",
xbmcgui.NOTIFICATION_INFO,
4500,
)
return
final_link = resolved_link or link
final_link = normalize_resolved_stream_url(final_link, source_url=link)
err = _resolveurl_last_error()
if _is_cloudflare_challenge_error(err) and final_link.strip() == link.strip():
_log(f"ResolveURL Cloudflare-Challenge (unresolved): {err}", xbmc.LOGWARNING)
xbmcgui.Dialog().notification(
"Wiedergabe",
"Hoster durch Cloudflare geschuetzt. Bitte spaeter erneut probieren.",
xbmcgui.NOTIFICATION_INFO,
4500,
)
return
finally:
if restore_hosters is not None and callable(preferred_setter):
preferred_setter(restore_hosters)