Files
ViewIT/addon/resolveurl_backend.py

115 lines
3.6 KiB
Python

"""Optionales ResolveURL-Backend für das Kodi-Addon.
Wenn `script.module.resolveurl` installiert ist, kann damit eine Hoster-URL
zu einer abspielbaren Media-URL (inkl. evtl. Header-Suffix) aufgelöst werden.
"""
from __future__ import annotations
import importlib
import os
import sys
from typing import Optional
_LAST_RESOLVE_ERROR = ""
def _debug_log(message: str) -> None:
line = f"[ViewIt][ResolveURL] {message}"
try:
import xbmc # type: ignore
xbmc.log(line, xbmc.LOGDEBUG)
except Exception:
return
def _append_addon_lib_path(addon_id: str) -> bool:
try:
import xbmcaddon # type: ignore
import xbmcvfs # type: ignore
addon = xbmcaddon.Addon(addon_id)
addon_path = addon.getAddonInfo("path")
lib_path = xbmcvfs.translatePath(os.path.join(addon_path, "lib"))
if lib_path and lib_path not in sys.path:
sys.path.append(lib_path)
return bool(lib_path)
except Exception:
return False
def get_last_error() -> str:
return str(_LAST_RESOLVE_ERROR or "")
def _import_resolveurl():
try:
return importlib.import_module("resolveurl")
except Exception as exc:
_debug_log(f"import resolveurl failed (direct): {exc}")
# Kodi should load transitive deps, but some runtimes miss sys.path entries.
_append_addon_lib_path("script.module.resolveurl")
_append_addon_lib_path("script.module.kodi-six")
_append_addon_lib_path("script.module.six")
try:
return importlib.import_module("resolveurl")
except Exception as exc:
_debug_log(f"import resolveurl failed (with addon lib paths): {exc}")
return None
def resolve(url: str) -> Optional[str]:
global _LAST_RESOLVE_ERROR
_LAST_RESOLVE_ERROR = ""
if not url:
_debug_log("resolve() skipped (empty url)")
return None
_debug_log(f"input: {url}")
resolveurl = _import_resolveurl()
if resolveurl is None:
_LAST_RESOLVE_ERROR = "resolveurl missing"
_debug_log("result: <none> (resolveurl missing)")
return None
try:
hosted = getattr(resolveurl, "HostedMediaFile", None)
if callable(hosted):
hmf = hosted(url)
valid = getattr(hmf, "valid_url", None)
if callable(valid) and not valid():
_LAST_RESOLVE_ERROR = "invalid url"
_debug_log("result: <none> (invalid url for HostedMediaFile)")
return None
resolver = getattr(hmf, "resolve", None)
if callable(resolver):
result = resolver()
if result:
_debug_log(f"result: {result}")
return str(result)
_LAST_RESOLVE_ERROR = "unresolved"
_debug_log("result: <none> (HostedMediaFile unresolved)")
return None
except Exception as exc:
_LAST_RESOLVE_ERROR = str(exc or "")
_debug_log(f"HostedMediaFile error: {_LAST_RESOLVE_ERROR}")
try:
resolve_fn = getattr(resolveurl, "resolve", None)
if callable(resolve_fn):
result = resolve_fn(url)
if result:
_debug_log(f"result: {result}")
return str(result)
_LAST_RESOLVE_ERROR = "unresolved"
_debug_log("result: <none> (resolve() unresolved)")
return None
except Exception as exc:
_LAST_RESOLVE_ERROR = str(exc or "")
_debug_log(f"resolve() error: {_LAST_RESOLVE_ERROR}")
return None
_debug_log("result: <none> (no resolver path)")
return None