Nightly: refactor readability, progress callbacks, and resource handling
This commit is contained in:
93
addon/metadata_utils.py
Normal file
93
addon/metadata_utils.py
Normal file
@@ -0,0 +1,93 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
from plugin_interface import BasisPlugin
|
||||
from tmdb import TmdbCastMember
|
||||
|
||||
METADATA_MODE_AUTO = 0
|
||||
METADATA_MODE_SOURCE = 1
|
||||
METADATA_MODE_TMDB = 2
|
||||
METADATA_MODE_MIX = 3
|
||||
|
||||
|
||||
def metadata_setting_id(plugin_name: str) -> str:
|
||||
safe = re.sub(r"[^a-z0-9]+", "_", (plugin_name or "").strip().casefold()).strip("_")
|
||||
return f"{safe}_metadata_source" if safe else "metadata_source"
|
||||
|
||||
|
||||
def plugin_supports_metadata(plugin: BasisPlugin) -> bool:
|
||||
try:
|
||||
return plugin.__class__.metadata_for is not BasisPlugin.metadata_for
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def metadata_policy(
|
||||
plugin_name: str,
|
||||
plugin: BasisPlugin,
|
||||
*,
|
||||
allow_tmdb: bool,
|
||||
get_setting_int=None,
|
||||
) -> tuple[bool, bool, bool]:
|
||||
if not callable(get_setting_int):
|
||||
return plugin_supports_metadata(plugin), allow_tmdb, bool(getattr(plugin, "prefer_source_metadata", False))
|
||||
mode = get_setting_int(metadata_setting_id(plugin_name), default=METADATA_MODE_AUTO)
|
||||
supports_source = plugin_supports_metadata(plugin)
|
||||
if mode == METADATA_MODE_SOURCE:
|
||||
return supports_source, False, True
|
||||
if mode == METADATA_MODE_TMDB:
|
||||
return False, allow_tmdb, False
|
||||
if mode == METADATA_MODE_MIX:
|
||||
return supports_source, allow_tmdb, True
|
||||
prefer_source = bool(getattr(plugin, "prefer_source_metadata", False))
|
||||
return supports_source, allow_tmdb, prefer_source
|
||||
|
||||
|
||||
def collect_plugin_metadata(
|
||||
plugin: BasisPlugin,
|
||||
titles: list[str],
|
||||
) -> dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember] | None]]:
|
||||
getter = getattr(plugin, "metadata_for", None)
|
||||
if not callable(getter):
|
||||
return {}
|
||||
collected: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember] | None]] = {}
|
||||
for title in titles:
|
||||
try:
|
||||
labels, art, cast = getter(title)
|
||||
except Exception:
|
||||
continue
|
||||
if isinstance(labels, dict) or isinstance(art, dict) or cast:
|
||||
label_map = {str(k): str(v) for k, v in dict(labels or {}).items() if v}
|
||||
art_map = {str(k): str(v) for k, v in dict(art or {}).items() if v}
|
||||
collected[title] = (label_map, art_map, cast if isinstance(cast, list) else None)
|
||||
return collected
|
||||
|
||||
|
||||
def needs_tmdb(labels: dict[str, str], art: dict[str, str], *, want_plot: bool, want_art: bool) -> bool:
|
||||
if want_plot and not labels.get("plot"):
|
||||
return True
|
||||
if want_art and not (art.get("thumb") or art.get("poster") or art.get("fanart") or art.get("landscape")):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def merge_metadata(
|
||||
title: str,
|
||||
tmdb_labels: dict[str, str] | None,
|
||||
tmdb_art: dict[str, str] | None,
|
||||
tmdb_cast: list[TmdbCastMember] | None,
|
||||
plugin_meta: tuple[dict[str, str], dict[str, str], list[TmdbCastMember] | None] | None,
|
||||
) -> tuple[dict[str, str], dict[str, str], list[TmdbCastMember] | None]:
|
||||
labels = dict(tmdb_labels or {})
|
||||
art = dict(tmdb_art or {})
|
||||
cast = tmdb_cast
|
||||
if plugin_meta is not None:
|
||||
meta_labels, meta_art, meta_cast = plugin_meta
|
||||
labels.update({k: str(v) for k, v in dict(meta_labels or {}).items() if v})
|
||||
art.update({k: str(v) for k, v in dict(meta_art or {}).items() if v})
|
||||
if meta_cast is not None:
|
||||
cast = meta_cast
|
||||
if "title" not in labels:
|
||||
labels["title"] = title
|
||||
return labels, art, cast
|
||||
Reference in New Issue
Block a user