From 4b9ba6a01aa6e8fa06e989935912047eb2e0da9c Mon Sep 17 00:00:00 2001 From: "itdrui.de" Date: Fri, 13 Mar 2026 19:50:57 +0100 Subject: [PATCH] dev: YouTube: yt-dlp ZIP-Installation von GitHub, kein yesno-Dialog --- CHANGELOG-DEV.md | 4 +++ addon/addon.xml | 2 +- addon/default.py | 63 +++++++++++++++++++++++++++++++-- addon/plugins/youtube_plugin.py | 9 +++-- 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/CHANGELOG-DEV.md b/CHANGELOG-DEV.md index 255c340..7b4826c 100644 --- a/CHANGELOG-DEV.md +++ b/CHANGELOG-DEV.md @@ -1,3 +1,7 @@ +## 0.1.80.0-dev - 2026-03-13 + +- dev: YouTube-Plugin: yt-dlp Suche, Bug-Fix Any-Import + ## 0.1.79.5-dev - 2026-03-11 - dev: Changelog-Hook auf prepare-commit-msg umgestellt diff --git a/addon/addon.xml b/addon/addon.xml index 7075f3f..e451752 100644 --- a/addon/addon.xml +++ b/addon/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/addon/default.py b/addon/default.py index 3c1384b..9faf85c 100644 --- a/addon/default.py +++ b/addon/default.py @@ -1698,13 +1698,70 @@ def _sync_ytdlp_status_setting() -> None: _set_setting_string("ytdlp_status", status) +def _fetch_ytdlp_zip_url() -> str: + """Ermittelt die aktuellste ZIP-URL fuer script.module.yt-dlp von GitHub.""" + api_url = "https://api.github.com/repos/lekma/script.module.yt-dlp/releases/latest" + try: + data = json.loads(_read_binary_url(api_url, timeout=10).decode("utf-8")) + for asset in data.get("assets", []): + url = asset.get("browser_download_url", "") + if url.endswith(".zip"): + return url + except Exception as exc: + _log(f"yt-dlp Release-URL nicht ermittelbar: {exc}", xbmc.LOGWARNING) + return "" + + +def _install_ytdlp_from_zip(zip_url: str) -> bool: + """Laedt script.module.yt-dlp ZIP von GitHub und entpackt es in den Addons-Ordner.""" + try: + zip_bytes = _read_binary_url(zip_url, timeout=60) + except Exception as exc: + _log(f"yt-dlp ZIP-Download fehlgeschlagen: {exc}", xbmc.LOGWARNING) + return False + if xbmcvfs is None: + return False + addons_root = xbmcvfs.translatePath("special://home/addons") + addons_root_real = os.path.realpath(addons_root) + try: + with zipfile.ZipFile(io.BytesIO(zip_bytes)) as archive: + for member in archive.infolist(): + name = str(member.filename or "") + if not name or name.endswith("/"): + continue + target = os.path.realpath(os.path.join(addons_root, name)) + if not target.startswith(addons_root_real + os.sep): + continue + os.makedirs(os.path.dirname(target), exist_ok=True) + with archive.open(member, "r") as src, open(target, "wb") as dst: + dst.write(src.read()) + except Exception as exc: + _log(f"yt-dlp Entpacken fehlgeschlagen: {exc}", xbmc.LOGWARNING) + return False + builtin = getattr(xbmc, "executebuiltin", None) + if callable(builtin): + builtin("UpdateLocalAddons") + return _is_addon_installed(YTDLP_ADDON_ID) + + def _ensure_ytdlp_installed(*, force: bool, silent: bool) -> bool: if _is_addon_installed(YTDLP_ADDON_ID): _sync_ytdlp_status_setting() return True - wait_seconds = 20 if force else 0 - ok = _install_kodi_addon(YTDLP_ADDON_ID, wait_seconds=wait_seconds) + zip_url = _fetch_ytdlp_zip_url() + if not zip_url: + _sync_ytdlp_status_setting() + if not silent: + xbmcgui.Dialog().notification( + "yt-dlp", + "Aktuelle Version nicht ermittelbar (GitHub nicht erreichbar?).", + xbmcgui.NOTIFICATION_ERROR, + 5000, + ) + return False + + ok = _install_ytdlp_from_zip(zip_url) _sync_ytdlp_status_setting() if not silent: @@ -1718,7 +1775,7 @@ def _ensure_ytdlp_installed(*, force: bool, silent: bool) -> bool: else: xbmcgui.Dialog().notification( "yt-dlp", - "Installation fehlgeschlagen. Bitte Repository/Netzwerk pruefen.", + "Installation fehlgeschlagen.", xbmcgui.NOTIFICATION_ERROR, 5000, ) diff --git a/addon/plugins/youtube_plugin.py b/addon/plugins/youtube_plugin.py index e60edb8..5c9be29 100644 --- a/addon/plugins/youtube_plugin.py +++ b/addon/plugins/youtube_plugin.py @@ -172,14 +172,13 @@ def _resolve_with_ytdlp(video_id: str) -> Optional[str]: except ImportError: log_error("[YouTube] yt-dlp nicht verfuegbar (script.module.yt-dlp fehlt)") try: - import xbmc import xbmcgui - yes = xbmcgui.Dialog().yesno( + xbmcgui.Dialog().notification( "yt-dlp fehlt", - "script.module.yt-dlp ist nicht installiert.\nJetzt installieren?", + "Bitte yt-dlp in den ViewIT-Einstellungen installieren.", + xbmcgui.NOTIFICATION_ERROR, + 5000, ) - if yes: - xbmc.executebuiltin("RunPlugin(plugin://plugin.video.viewit/?action=install_ytdlp)") except Exception: pass return None