dev: harden resolver bootstrap and simplify update settings
This commit is contained in:
182
addon/default.py
182
addon/default.py
@@ -954,12 +954,6 @@ def _add_directory_item(
|
||||
xbmcplugin.addDirectoryItem(handle=handle, url=url, listitem=item, isFolder=is_folder)
|
||||
|
||||
|
||||
def _plugin_version(plugin: BasisPlugin) -> str:
|
||||
raw = getattr(plugin, "version", "0.0.0")
|
||||
text = str(raw or "").strip()
|
||||
return text or "0.0.0"
|
||||
|
||||
|
||||
def _normalize_update_info_url(raw: str) -> str:
|
||||
value = str(raw or "").strip()
|
||||
default = "http://127.0.0.1:8080/repo/addons.xml"
|
||||
@@ -976,6 +970,8 @@ UPDATE_CHANNEL_CUSTOM = 2
|
||||
AUTO_UPDATE_INTERVAL_SEC = 6 * 60 * 60
|
||||
UPDATE_HTTP_TIMEOUT_SEC = 8
|
||||
UPDATE_ADDON_ID = "plugin.video.viewit"
|
||||
RESOLVEURL_ADDON_ID = "script.module.resolveurl"
|
||||
RESOLVEURL_AUTO_INSTALL_INTERVAL_SEC = 6 * 60 * 60
|
||||
|
||||
|
||||
def _selected_update_channel() -> int:
|
||||
@@ -1030,10 +1026,7 @@ def _resolve_update_info_url() -> str:
|
||||
raw = _get_setting_string("update_repo_url")
|
||||
else:
|
||||
raw = _get_setting_string("update_repo_url_main")
|
||||
info_url = _normalize_update_info_url(raw)
|
||||
# Legacy-Setting beibehalten, damit bestehende Installationen und alte Builds weiterlaufen.
|
||||
_set_setting_string("update_repo_url", info_url)
|
||||
return info_url
|
||||
return _normalize_update_info_url(raw)
|
||||
|
||||
|
||||
def _read_text_url(url: str, *, timeout: int = UPDATE_HTTP_TIMEOUT_SEC) -> str:
|
||||
@@ -1247,25 +1240,10 @@ def _install_addon_version(info_url: str, version: str) -> bool:
|
||||
|
||||
def _sync_update_channel_status_settings() -> None:
|
||||
channel = _selected_update_channel()
|
||||
channel_label = _channel_label(channel)
|
||||
|
||||
selected_info_url = _resolve_update_info_url()
|
||||
main_info_url = _normalize_update_info_url(_get_setting_string("update_repo_url_main"))
|
||||
nightly_info_url = _normalize_update_info_url(_get_setting_string("update_repo_url_nightly"))
|
||||
|
||||
available_main = _fetch_repo_addon_version(main_info_url)
|
||||
available_nightly = _fetch_repo_addon_version(nightly_info_url)
|
||||
if channel == UPDATE_CHANNEL_MAIN:
|
||||
available_selected = available_main
|
||||
elif channel == UPDATE_CHANNEL_NIGHTLY:
|
||||
available_selected = available_nightly
|
||||
else:
|
||||
available_selected = _fetch_repo_addon_version(selected_info_url)
|
||||
|
||||
_set_setting_string("update_active_channel", channel_label)
|
||||
available_selected = _fetch_repo_addon_version(selected_info_url)
|
||||
_set_setting_string("update_active_channel", _channel_label(channel))
|
||||
_set_setting_string("update_active_repo_url", selected_info_url)
|
||||
_set_setting_string("update_available_main", available_main)
|
||||
_set_setting_string("update_available_nightly", available_nightly)
|
||||
_set_setting_string("update_available_selected", available_selected)
|
||||
|
||||
|
||||
@@ -1306,11 +1284,6 @@ def _update_repository_source(info_url: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def _settings_key_for_plugin(name: str) -> str:
|
||||
safe = re.sub(r"[^a-z0-9]+", "_", (name or "").strip().casefold()).strip("_")
|
||||
return f"update_version_{safe}" if safe else "update_version_unknown"
|
||||
|
||||
|
||||
def _installed_addon_version_from_disk() -> str:
|
||||
if xbmcvfs is None:
|
||||
return "0.0.0"
|
||||
@@ -1328,6 +1301,96 @@ def _installed_addon_version_from_disk() -> str:
|
||||
return "0.0.0"
|
||||
|
||||
|
||||
def _is_addon_installed(addon_id: str) -> bool:
|
||||
addon_id = str(addon_id or "").strip()
|
||||
if not addon_id:
|
||||
return False
|
||||
has_addon = getattr(xbmc, "getCondVisibility", None)
|
||||
if callable(has_addon):
|
||||
try:
|
||||
return bool(has_addon(f"System.HasAddon({addon_id})"))
|
||||
except Exception:
|
||||
pass
|
||||
if xbmcvfs is None:
|
||||
return False
|
||||
try:
|
||||
addon_xml = xbmcvfs.translatePath(f"special://home/addons/{addon_id}/addon.xml")
|
||||
except Exception:
|
||||
return False
|
||||
return bool(addon_xml and os.path.exists(addon_xml))
|
||||
|
||||
|
||||
def _sync_resolveurl_status_setting() -> None:
|
||||
status = "Installiert" if _is_addon_installed(RESOLVEURL_ADDON_ID) else "Fehlt"
|
||||
_set_setting_string("resolveurl_status", status)
|
||||
|
||||
|
||||
def _install_kodi_addon(addon_id: str, *, wait_seconds: int) -> bool:
|
||||
if _is_addon_installed(addon_id):
|
||||
return True
|
||||
builtin = getattr(xbmc, "executebuiltin", None)
|
||||
if not callable(builtin):
|
||||
return False
|
||||
try:
|
||||
builtin(f"InstallAddon({addon_id})")
|
||||
builtin("UpdateLocalAddons")
|
||||
except Exception as exc:
|
||||
_log(f"InstallAddon fehlgeschlagen ({addon_id}): {exc}", xbmc.LOGWARNING)
|
||||
return False
|
||||
|
||||
if wait_seconds <= 0:
|
||||
return _is_addon_installed(addon_id)
|
||||
deadline = time.time() + max(1, int(wait_seconds))
|
||||
while time.time() < deadline:
|
||||
if _is_addon_installed(addon_id):
|
||||
return True
|
||||
time.sleep(1)
|
||||
return _is_addon_installed(addon_id)
|
||||
|
||||
|
||||
def _ensure_resolveurl_installed(*, force: bool, silent: bool) -> bool:
|
||||
if _is_addon_installed(RESOLVEURL_ADDON_ID):
|
||||
_sync_resolveurl_status_setting()
|
||||
return True
|
||||
if not force and not _get_setting_bool("resolveurl_auto_install", default=True):
|
||||
_sync_resolveurl_status_setting()
|
||||
return False
|
||||
|
||||
now = int(time.time())
|
||||
if not force:
|
||||
last_try = _get_setting_int("resolveurl_last_ts", default=0)
|
||||
if last_try > 0 and (now - last_try) < RESOLVEURL_AUTO_INSTALL_INTERVAL_SEC:
|
||||
return False
|
||||
_set_setting_string("resolveurl_last_ts", str(now))
|
||||
|
||||
wait_seconds = 20 if force else 0
|
||||
ok = _install_kodi_addon(RESOLVEURL_ADDON_ID, wait_seconds=wait_seconds)
|
||||
_sync_resolveurl_status_setting()
|
||||
|
||||
if not silent:
|
||||
if ok:
|
||||
xbmcgui.Dialog().notification(
|
||||
"ResolveURL",
|
||||
"script.module.resolveurl ist installiert.",
|
||||
xbmcgui.NOTIFICATION_INFO,
|
||||
4000,
|
||||
)
|
||||
else:
|
||||
xbmcgui.Dialog().notification(
|
||||
"ResolveURL",
|
||||
"Installation fehlgeschlagen. Bitte Repository/Netzwerk pruefen.",
|
||||
xbmcgui.NOTIFICATION_ERROR,
|
||||
5000,
|
||||
)
|
||||
return ok
|
||||
|
||||
|
||||
def _maybe_auto_install_resolveurl(action: str | None) -> None:
|
||||
if (action or "").strip():
|
||||
return
|
||||
_ensure_resolveurl_installed(force=False, silent=True)
|
||||
|
||||
|
||||
def _sync_update_version_settings() -> None:
|
||||
addon_version = _installed_addon_version_from_disk()
|
||||
if addon_version == "0.0.0":
|
||||
@@ -1337,24 +1400,8 @@ def _sync_update_version_settings() -> None:
|
||||
addon_version = str(addon.getAddonInfo("version") or "0.0.0")
|
||||
except Exception:
|
||||
addon_version = "0.0.0"
|
||||
_set_setting_string("update_version_addon", addon_version)
|
||||
_set_setting_string("update_installed_version", addon_version)
|
||||
|
||||
versions = {
|
||||
"update_version_serienstream": "-",
|
||||
"update_version_aniworld": "-",
|
||||
"update_version_einschalten": "-",
|
||||
"update_version_topstreamfilm": "-",
|
||||
"update_version_filmpalast": "-",
|
||||
"update_version_doku_streams": "-",
|
||||
}
|
||||
for plugin in _discover_plugins().values():
|
||||
key = _settings_key_for_plugin(str(plugin.name))
|
||||
if key in versions:
|
||||
versions[key] = _plugin_version(plugin)
|
||||
for key, value in versions.items():
|
||||
_set_setting_string(key, value)
|
||||
|
||||
_sync_resolveurl_status_setting()
|
||||
_sync_update_channel_status_settings()
|
||||
|
||||
|
||||
@@ -3543,14 +3590,18 @@ def _show_version_selector() -> None:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
confirm_choice = xbmcgui.Dialog().select(
|
||||
"Version installieren",
|
||||
[
|
||||
f"Installieren: {version}",
|
||||
"Abbrechen",
|
||||
],
|
||||
)
|
||||
if confirm_choice != 0:
|
||||
dialog = xbmcgui.Dialog()
|
||||
try:
|
||||
confirmed = dialog.yesno(
|
||||
"Version installieren",
|
||||
f"Installiert: {installed}",
|
||||
f"Ausgewaehlt: {version}",
|
||||
yeslabel="Installieren",
|
||||
nolabel="Abbrechen",
|
||||
)
|
||||
except TypeError:
|
||||
confirmed = dialog.yesno("Version installieren", f"Installiert: {installed}", f"Ausgewaehlt: {version}")
|
||||
if not confirmed:
|
||||
return
|
||||
|
||||
xbmcgui.Dialog().notification("Updates", f"Installation gestartet: {version}", xbmcgui.NOTIFICATION_INFO, 2500)
|
||||
@@ -3609,6 +3660,10 @@ def _is_cloudflare_challenge_error(message: str) -> bool:
|
||||
return "cloudflare" in text or "challenge" in text or "attention required" in text
|
||||
|
||||
|
||||
def _is_resolveurl_missing_error(message: str) -> bool:
|
||||
return str(message or "").strip().casefold() == "resolveurl missing"
|
||||
|
||||
|
||||
def _play_final_link(
|
||||
link: str,
|
||||
*,
|
||||
@@ -3743,6 +3798,11 @@ def _play_episode(
|
||||
resolved_link = plugin.resolve_stream_link(link)
|
||||
if not resolved_link:
|
||||
err = _resolveurl_last_error()
|
||||
if _is_resolveurl_missing_error(err):
|
||||
_log("ResolveURL fehlt: versuche Auto-Installation.", xbmc.LOGWARNING)
|
||||
_ensure_resolveurl_installed(force=True, silent=True)
|
||||
resolved_link = plugin.resolve_stream_link(link)
|
||||
err = _resolveurl_last_error()
|
||||
if _is_cloudflare_challenge_error(err):
|
||||
_log(f"ResolveURL Cloudflare-Challenge: {err}", xbmc.LOGWARNING)
|
||||
xbmcgui.Dialog().notification(
|
||||
@@ -3853,6 +3913,11 @@ def _play_episode_url(
|
||||
resolved_link = plugin.resolve_stream_link(link)
|
||||
if not resolved_link:
|
||||
err = _resolveurl_last_error()
|
||||
if _is_resolveurl_missing_error(err):
|
||||
_log("ResolveURL fehlt: versuche Auto-Installation.", xbmc.LOGWARNING)
|
||||
_ensure_resolveurl_installed(force=True, silent=True)
|
||||
resolved_link = plugin.resolve_stream_link(link)
|
||||
err = _resolveurl_last_error()
|
||||
if _is_cloudflare_challenge_error(err):
|
||||
_log(f"ResolveURL Cloudflare-Challenge: {err}", xbmc.LOGWARNING)
|
||||
xbmcgui.Dialog().notification(
|
||||
@@ -3914,6 +3979,7 @@ def run() -> None:
|
||||
action = params.get("action")
|
||||
_log(f"Action: {action}", xbmc.LOGDEBUG)
|
||||
_maybe_run_auto_update_check(action)
|
||||
_maybe_auto_install_resolveurl(action)
|
||||
if action == "search":
|
||||
_show_search()
|
||||
elif action == "plugin_menu":
|
||||
@@ -3991,6 +4057,8 @@ def run() -> None:
|
||||
_apply_update_channel()
|
||||
elif action == "select_update_version":
|
||||
_show_version_selector()
|
||||
elif action == "install_resolveurl":
|
||||
_ensure_resolveurl_installed(force=True, silent=False)
|
||||
elif action == "seasons":
|
||||
_show_seasons(params.get("plugin", ""), params.get("title", ""), params.get("series_url", ""))
|
||||
elif action == "episodes":
|
||||
|
||||
Reference in New Issue
Block a user