Files
ViewIT/addon/plugin_helpers.py
itdrui.de ee275bee47 Implement ViewIt Plugin System Documentation and Update Project Notes
- Added comprehensive documentation for the ViewIt Plugin System, detailing the plugin loading process, required methods, optional features, and community extension workflow.
- Updated project notes to reflect the current structure, build process, search logic, and known issues.
- Introduced new build scripts for installing the add-on and creating ZIP packages.
- Added test scripts for TMDB API integration, including argument parsing and logging functionality.
- Enhanced existing plugins with improved search logic and error handling.
2026-02-01 17:55:30 +01:00

129 lines
3.9 KiB
Python

#!/usr/bin/env python3
"""Shared helpers for ViewIt plugins.
Focus:
- Kodi addon settings access (string/bool)
- Optional URL notifications
- Optional URL logging
- Optional HTML response dumps
Designed to work both in Kodi and outside Kodi (for linting/tests).
"""
from __future__ import annotations
from datetime import datetime
import hashlib
import os
from typing import Optional
try: # pragma: no cover - Kodi runtime
import xbmcaddon # type: ignore[import-not-found]
import xbmcvfs # type: ignore[import-not-found]
import xbmcgui # type: ignore[import-not-found]
except ImportError: # pragma: no cover - allow importing outside Kodi
xbmcaddon = None
xbmcvfs = None
xbmcgui = None
def get_setting_string(addon_id: str, setting_id: str, *, default: str = "") -> str:
if xbmcaddon is None:
return default
try:
addon = xbmcaddon.Addon(addon_id)
getter = getattr(addon, "getSettingString", None)
if getter is not None:
return str(getter(setting_id) or "").strip()
return str(addon.getSetting(setting_id) or "").strip()
except Exception:
return default
def get_setting_bool(addon_id: str, setting_id: str, *, default: bool = False) -> bool:
if xbmcaddon is None:
return default
try:
addon = xbmcaddon.Addon(addon_id)
getter = getattr(addon, "getSettingBool", None)
if getter is not None:
return bool(getter(setting_id))
raw = addon.getSetting(setting_id)
return str(raw).strip().lower() in {"1", "true", "yes", "on"}
except Exception:
return default
def notify_url(addon_id: str, *, heading: str, url: str, enabled_setting_id: str) -> None:
if xbmcgui is None:
return
if not get_setting_bool(addon_id, enabled_setting_id, default=False):
return
try:
xbmcgui.Dialog().notification(heading, url, xbmcgui.NOTIFICATION_INFO, 3000)
except Exception:
return
def _profile_logs_dir(addon_id: str) -> Optional[str]:
if xbmcaddon is None or xbmcvfs is None:
return None
try:
addon = xbmcaddon.Addon(addon_id)
profile = xbmcvfs.translatePath(addon.getAddonInfo("profile"))
log_dir = os.path.join(profile, "logs")
if not xbmcvfs.exists(log_dir):
xbmcvfs.mkdirs(log_dir)
return log_dir
except Exception:
return None
def _append_text_file(path: str, content: str) -> None:
try:
with open(path, "a", encoding="utf-8") as handle:
handle.write(content)
return
except Exception:
pass
if xbmcvfs is None:
return
try:
handle = xbmcvfs.File(path, "a")
handle.write(content)
handle.close()
except Exception:
return
def log_url(addon_id: str, *, enabled_setting_id: str, log_filename: str, url: str, kind: str = "VISIT") -> None:
if not get_setting_bool(addon_id, enabled_setting_id, default=False):
return
timestamp = datetime.utcnow().isoformat(timespec="seconds") + "Z"
line = f"{timestamp}\t{kind}\t{url}\n"
log_dir = _profile_logs_dir(addon_id)
if log_dir:
_append_text_file(os.path.join(log_dir, log_filename), line)
return
_append_text_file(os.path.join(os.path.dirname(__file__), log_filename), line)
def dump_response_html(
addon_id: str,
*,
enabled_setting_id: str,
url: str,
body: str,
filename_prefix: str,
) -> None:
if not get_setting_bool(addon_id, enabled_setting_id, default=False):
return
timestamp = datetime.utcnow().strftime("%Y%m%d_%H%M%S_%f")
digest = hashlib.md5(url.encode("utf-8")).hexdigest() # nosec - filename only
filename = f"{filename_prefix}_{timestamp}_{digest}.html"
log_dir = _profile_logs_dir(addon_id)
path = os.path.join(log_dir, filename) if log_dir else os.path.join(os.path.dirname(__file__), filename)
content = f"<!-- {url} -->\n{body or ''}"
_append_text_file(path, content)