From 537f0e23e164967001591caf841c4720cd89b4b3 Mon Sep 17 00:00:00 2001 From: "itdrui.de" Date: Sun, 8 Feb 2026 22:33:07 +0100 Subject: [PATCH] nightly: per-plugin metadata source option --- addon/addon.xml | 2 +- addon/default.py | 638 ++++++++++++++++++++--------------- addon/resources/settings.xml | 6 + 3 files changed, 381 insertions(+), 265 deletions(-) diff --git a/addon/addon.xml b/addon/addon.xml index 6f5c34c..479247e 100644 --- a/addon/addon.xml +++ b/addon/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/addon/default.py b/addon/default.py index 8f1bbe2..d488981 100644 --- a/addon/default.py +++ b/addon/default.py @@ -402,6 +402,81 @@ def _get_setting_bool(setting_id: str, *, default: bool = False) -> bool: return default +def _get_setting_int(setting_id: str, *, default: int = 0) -> int: + if xbmcaddon is None: + return default + addon = _get_addon() + if addon is None: + return default + getter = getattr(addon, "getSettingInt", None) + if callable(getter): + raw_getter = getattr(addon, "getSetting", None) + if callable(raw_getter): + try: + raw = str(raw_getter(setting_id) or "").strip() + except TypeError: + raw = "" + if raw == "": + return default + try: + return int(getter(setting_id)) + except TypeError: + return default + getter = getattr(addon, "getSetting", None) + if callable(getter): + try: + raw = str(getter(setting_id) or "").strip() + except TypeError: + return default + if raw == "": + return default + try: + return int(raw) + except ValueError: + return default + return default + + +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, +) -> tuple[bool, bool, bool]: + 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 _tmdb_list_enabled() -> bool: + return _tmdb_enabled() and _get_setting_bool("tmdb_genre_metadata", default=False) + + def _set_setting_string(setting_id: str, value: str) -> None: if xbmcaddon is None: return @@ -1124,14 +1199,15 @@ def _show_plugin_search_results(plugin_name: str, query: str) -> None: results = [str(t).strip() for t in (results or []) if t and str(t).strip()] results.sort(key=lambda value: value.casefold()) - plugin_meta = _collect_plugin_metadata(plugin, results) + use_source, show_tmdb, prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_enabled() + ) + plugin_meta = _collect_plugin_metadata(plugin, results) if use_source else {} tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {} - show_tmdb = _tmdb_enabled() show_plot = _get_setting_bool("tmdb_show_plot", default=True) show_art = _get_setting_bool("tmdb_show_art", default=True) - prefer_source = bool(getattr(plugin, "prefer_source_metadata", False)) - tmdb_titles = list(results) - if show_tmdb and prefer_source: + tmdb_titles = list(results) if show_tmdb else [] + if show_tmdb and prefer_source and use_source: tmdb_titles = [] for title in results: meta = plugin_meta.get(title) @@ -1334,14 +1410,15 @@ def _show_search_results(query: str) -> None: continue results = [str(t).strip() for t in (results or []) if t and str(t).strip()] _log(f"Treffer ({plugin_name}): {len(results)}", xbmc.LOGDEBUG) - plugin_meta = _collect_plugin_metadata(plugin, results) + use_source, show_tmdb, prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_enabled() + ) + plugin_meta = _collect_plugin_metadata(plugin, results) if use_source else {} tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {} - show_tmdb = _tmdb_enabled() show_plot = _get_setting_bool("tmdb_show_plot", default=True) show_art = _get_setting_bool("tmdb_show_art", default=True) - prefer_source = bool(getattr(plugin, "prefer_source_metadata", False)) - tmdb_titles = list(results) - if show_tmdb and prefer_source: + tmdb_titles = list(results) if show_tmdb else [] + if show_tmdb and prefer_source and use_source: tmdb_titles = [] for title in results: meta = plugin_meta.get(title) @@ -1485,11 +1562,14 @@ def _show_seasons(plugin_name: str, title: str, series_url: str = "") -> None: except Exception: pass + use_source, show_tmdb, _prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_enabled() + ) title_info_labels: dict[str, str] | None = None title_art: dict[str, str] | None = None title_cast: list[TmdbCastMember] | None = None meta_getter = getattr(plugin, "metadata_for", None) - if callable(meta_getter): + if use_source and callable(meta_getter): try: with _busy_dialog(): meta_labels, meta_art, meta_cast = meta_getter(title) @@ -1516,8 +1596,9 @@ def _show_seasons(plugin_name: str, title: str, series_url: str = "") -> None: xbmcplugin.setPluginCategory(handle, f"{title} ({count} {suffix})") _set_content(handle, "seasons") # Staffel-Metadaten (Plot/Poster) optional via TMDB. - _tmdb_labels_and_art(title) - api_key = _get_setting_string("tmdb_api_key").strip() + if show_tmdb: + _tmdb_labels_and_art(title) + api_key = _get_setting_string("tmdb_api_key").strip() if show_tmdb else "" language = _get_setting_string("tmdb_language").strip() or "de-DE" show_plot = _get_setting_bool("tmdb_show_plot", default=True) show_art = _get_setting_bool("tmdb_show_art", default=True) @@ -1606,13 +1687,40 @@ def _show_episodes(plugin_name: str, title: str, season: str, series_url: str = episodes = list(plugin.episodes_for(title, season)) if episodes: - show_info, show_art, show_cast = _tmdb_labels_and_art(title) + use_source, show_tmdb, _prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_enabled() + ) + show_info: dict[str, str] = {} + show_art: dict[str, str] = {} + show_cast: list[TmdbCastMember] | None = None + if show_tmdb: + show_info, show_art, show_cast = _tmdb_labels_and_art(title) + elif use_source: + meta_getter = getattr(plugin, "metadata_for", None) + if callable(meta_getter): + try: + with _busy_dialog(): + meta_labels, meta_art, meta_cast = meta_getter(title) + if isinstance(meta_labels, dict): + show_info = {str(k): str(v) for k, v in meta_labels.items() if v} + if isinstance(meta_art, dict): + show_art = {str(k): str(v) for k, v in meta_art.items() if v} + if isinstance(meta_cast, list): + show_cast = meta_cast # noqa: PGH003 + except Exception: + pass + show_fanart = (show_art or {}).get("fanart") if isinstance(show_art, dict) else "" show_poster = (show_art or {}).get("poster") if isinstance(show_art, dict) else "" with _busy_dialog(): for episode in episodes: - info_labels, art = _tmdb_episode_labels_and_art(title=title, season_label=season, episode_label=episode) - episode_cast = _tmdb_episode_cast(title=title, season_label=season, episode_label=episode) + if show_tmdb: + info_labels, art = _tmdb_episode_labels_and_art( + title=title, season_label=season, episode_label=episode + ) + episode_cast = _tmdb_episode_cast(title=title, season_label=season, episode_label=episode) + else: + info_labels, art, episode_cast = {}, {}, [] merged_info = dict(show_info or {}) merged_info.update(dict(info_labels or {})) merged_art: dict[str, str] = {} @@ -1803,16 +1911,16 @@ def _show_category_titles_page(plugin_name: str, category: str, page: int = 1) - titles = [str(t).strip() for t in titles if t and str(t).strip()] titles.sort(key=lambda value: value.casefold()) - show_tmdb = _get_setting_bool("tmdb_genre_metadata", default=False) if titles: - plugin_meta = _collect_plugin_metadata(plugin, titles) - show_tmdb = _tmdb_enabled() + use_source, show_tmdb, prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_list_enabled() + ) + plugin_meta = _collect_plugin_metadata(plugin, titles) if use_source else {} show_plot = _get_setting_bool("tmdb_show_plot", default=True) show_art = _get_setting_bool("tmdb_show_art", default=True) - prefer_source = bool(getattr(plugin, "prefer_source_metadata", False)) tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {} - tmdb_titles = list(titles) - if show_tmdb and prefer_source: + tmdb_titles = list(titles) if show_tmdb else [] + if show_tmdb and prefer_source and use_source: tmdb_titles = [] for title in titles: meta = plugin_meta.get(title) @@ -1823,51 +1931,31 @@ def _show_category_titles_page(plugin_name: str, category: str, page: int = 1) - if show_tmdb and tmdb_titles: with _busy_dialog(): tmdb_prefetched = _tmdb_labels_and_art_bulk(tmdb_titles) - if show_tmdb: - for title in titles: - tmdb_info, tmdb_art, tmdb_cast = tmdb_prefetched.get(title, ({}, {}, [])) - meta = plugin_meta.get(title) - info_labels, art, cast = _merge_metadata(title, tmdb_info, tmdb_art, tmdb_cast, meta) - info_labels.setdefault("mediatype", "tvshow") - if (info_labels.get("mediatype") or "").strip().casefold() == "tvshow": - info_labels.setdefault("tvshowtitle", title) - playstate = _title_playstate(plugin_name, title) - info_labels = _apply_playstate_to_info(dict(info_labels), playstate) - display_label = _label_with_duration(title, info_labels) - display_label = _label_with_playstate(display_label, playstate) - direct_play = bool( - plugin_name.casefold() == "einschalten" - and _get_setting_bool("einschalten_enable_playback", default=False) - ) - _add_directory_item( - handle, - display_label, - "play_movie" if direct_play else "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=not direct_play, - info_labels=info_labels, - art=art, - cast=cast, - ) - else: - for title in titles: - playstate = _title_playstate(plugin_name, title) - meta = plugin_meta.get(title) - info_labels, art, cast = _merge_metadata(title, {}, {}, None, meta) - direct_play = bool( - plugin_name.casefold() == "einschalten" - and _get_setting_bool("einschalten_enable_playback", default=False) - ) - _add_directory_item( - handle, - _label_with_playstate(title, playstate), - "play_movie" if direct_play else "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=not direct_play, - info_labels=_apply_playstate_to_info(info_labels, playstate), - art=art, - cast=cast, - ) + for title in titles: + tmdb_info, tmdb_art, tmdb_cast = tmdb_prefetched.get(title, ({}, {}, [])) if show_tmdb else ({}, {}, []) + meta = plugin_meta.get(title) + info_labels, art, cast = _merge_metadata(title, tmdb_info, tmdb_art, tmdb_cast, meta) + info_labels.setdefault("mediatype", "tvshow") + if (info_labels.get("mediatype") or "").strip().casefold() == "tvshow": + info_labels.setdefault("tvshowtitle", title) + playstate = _title_playstate(plugin_name, title) + info_labels = _apply_playstate_to_info(dict(info_labels), playstate) + display_label = _label_with_duration(title, info_labels) + display_label = _label_with_playstate(display_label, playstate) + direct_play = bool( + plugin_name.casefold() == "einschalten" + and _get_setting_bool("einschalten_enable_playback", default=False) + ) + _add_directory_item( + handle, + display_label, + "play_movie" if direct_play else "seasons", + {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, + is_folder=not direct_play, + info_labels=info_labels, + art=art, + cast=cast, + ) show_next = False if total_pages is not None: @@ -1939,16 +2027,16 @@ def _show_genre_titles_page(plugin_name: str, genre: str, page: int = 1) -> None titles = [str(t).strip() for t in titles if t and str(t).strip()] titles.sort(key=lambda value: value.casefold()) - show_tmdb = _get_setting_bool("tmdb_genre_metadata", default=False) if titles: - plugin_meta = _collect_plugin_metadata(plugin, titles) - show_tmdb = show_tmdb and _tmdb_enabled() + use_source, show_tmdb, prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_list_enabled() + ) + plugin_meta = _collect_plugin_metadata(plugin, titles) if use_source else {} show_plot = _get_setting_bool("tmdb_show_plot", default=True) show_art = _get_setting_bool("tmdb_show_art", default=True) - prefer_source = bool(getattr(plugin, "prefer_source_metadata", False)) tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {} - tmdb_titles = list(titles) - if show_tmdb and prefer_source: + tmdb_titles = list(titles) if show_tmdb else [] + if show_tmdb and prefer_source and use_source: tmdb_titles = [] for title in titles: meta = plugin_meta.get(title) @@ -2090,50 +2178,52 @@ def _show_alpha_titles_page(plugin_name: str, letter: str, page: int = 1) -> Non titles = [str(t).strip() for t in titles if t and str(t).strip()] titles.sort(key=lambda value: value.casefold()) - show_tmdb = _get_setting_bool("tmdb_genre_metadata", default=False) if titles: - if show_tmdb: - with _busy_dialog(): - tmdb_prefetched = _tmdb_labels_and_art_bulk(titles) - for title in titles: - info_labels, art, cast = tmdb_prefetched.get(title, _tmdb_labels_and_art(title)) - info_labels = dict(info_labels or {}) - info_labels.setdefault("mediatype", "tvshow") - if (info_labels.get("mediatype") or "").strip().casefold() == "tvshow": - info_labels.setdefault("tvshowtitle", title) - playstate = _title_playstate(plugin_name, title) - info_labels = _apply_playstate_to_info(dict(info_labels), playstate) - display_label = _label_with_duration(title, info_labels) - display_label = _label_with_playstate(display_label, playstate) - direct_play = bool( - plugin_name.casefold() == "einschalten" - and _get_setting_bool("einschalten_enable_playback", default=False) - ) - _add_directory_item( - handle, - display_label, - "play_movie" if direct_play else "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=not direct_play, - info_labels=info_labels, - art=art, - cast=cast, - ) - else: + use_source, show_tmdb, prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_list_enabled() + ) + plugin_meta = _collect_plugin_metadata(plugin, titles) if use_source else {} + show_plot = _get_setting_bool("tmdb_show_plot", default=True) + show_art = _get_setting_bool("tmdb_show_art", default=True) + tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {} + tmdb_titles = list(titles) if show_tmdb else [] + if show_tmdb and prefer_source and use_source: + tmdb_titles = [] for title in titles: - playstate = _title_playstate(plugin_name, title) - direct_play = bool( - plugin_name.casefold() == "einschalten" - and _get_setting_bool("einschalten_enable_playback", default=False) - ) - _add_directory_item( - handle, - _label_with_playstate(title, playstate), - "play_movie" if direct_play else "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=not direct_play, - info_labels=_apply_playstate_to_info({"title": title}, playstate), - ) + meta = plugin_meta.get(title) + meta_labels = meta[0] if meta else {} + meta_art = meta[1] if meta else {} + if _needs_tmdb(meta_labels, meta_art, want_plot=show_plot, want_art=show_art): + tmdb_titles.append(title) + if show_tmdb and tmdb_titles: + with _busy_dialog(): + tmdb_prefetched = _tmdb_labels_and_art_bulk(tmdb_titles) + for title in titles: + tmdb_info, tmdb_art, tmdb_cast = tmdb_prefetched.get(title, ({}, {}, [])) if show_tmdb else ({}, {}, []) + meta = plugin_meta.get(title) + info_labels, art, cast = _merge_metadata(title, tmdb_info, tmdb_art, tmdb_cast, meta) + info_labels = dict(info_labels or {}) + info_labels.setdefault("mediatype", "tvshow") + if (info_labels.get("mediatype") or "").strip().casefold() == "tvshow": + info_labels.setdefault("tvshowtitle", title) + playstate = _title_playstate(plugin_name, title) + info_labels = _apply_playstate_to_info(dict(info_labels), playstate) + display_label = _label_with_duration(title, info_labels) + display_label = _label_with_playstate(display_label, playstate) + direct_play = bool( + plugin_name.casefold() == "einschalten" + and _get_setting_bool("einschalten_enable_playback", default=False) + ) + _add_directory_item( + handle, + display_label, + "play_movie" if direct_play else "seasons", + {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, + is_folder=not direct_play, + info_labels=info_labels, + art=art, + cast=cast, + ) show_next = False if total_pages is not None: @@ -2200,42 +2290,48 @@ def _show_series_catalog(plugin_name: str, page: int = 1) -> None: titles = [str(t).strip() for t in titles if t and str(t).strip()] titles.sort(key=lambda value: value.casefold()) - show_tmdb = _get_setting_bool("tmdb_genre_metadata", default=False) if titles: - if show_tmdb: - with _busy_dialog(): - tmdb_prefetched = _tmdb_labels_and_art_bulk(titles) - for title in titles: - info_labels, art, cast = tmdb_prefetched.get(title, _tmdb_labels_and_art(title)) - info_labels = dict(info_labels or {}) - info_labels.setdefault("mediatype", "tvshow") - if (info_labels.get("mediatype") or "").strip().casefold() == "tvshow": - info_labels.setdefault("tvshowtitle", title) - playstate = _title_playstate(plugin_name, title) - info_labels = _apply_playstate_to_info(dict(info_labels), playstate) - display_label = _label_with_duration(title, info_labels) - display_label = _label_with_playstate(display_label, playstate) - _add_directory_item( - handle, - display_label, - "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=True, - info_labels=info_labels, - art=art, - cast=cast, - ) - else: + use_source, show_tmdb, prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_list_enabled() + ) + plugin_meta = _collect_plugin_metadata(plugin, titles) if use_source else {} + show_plot = _get_setting_bool("tmdb_show_plot", default=True) + show_art = _get_setting_bool("tmdb_show_art", default=True) + tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {} + tmdb_titles = list(titles) if show_tmdb else [] + if show_tmdb and prefer_source and use_source: + tmdb_titles = [] for title in titles: - playstate = _title_playstate(plugin_name, title) - _add_directory_item( - handle, - _label_with_playstate(title, playstate), - "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=True, - info_labels=_apply_playstate_to_info({"title": title}, playstate), - ) + meta = plugin_meta.get(title) + meta_labels = meta[0] if meta else {} + meta_art = meta[1] if meta else {} + if _needs_tmdb(meta_labels, meta_art, want_plot=show_plot, want_art=show_art): + tmdb_titles.append(title) + if show_tmdb and tmdb_titles: + with _busy_dialog(): + tmdb_prefetched = _tmdb_labels_and_art_bulk(tmdb_titles) + for title in titles: + tmdb_info, tmdb_art, tmdb_cast = tmdb_prefetched.get(title, ({}, {}, [])) if show_tmdb else ({}, {}, []) + meta = plugin_meta.get(title) + info_labels, art, cast = _merge_metadata(title, tmdb_info, tmdb_art, tmdb_cast, meta) + info_labels = dict(info_labels or {}) + info_labels.setdefault("mediatype", "tvshow") + if (info_labels.get("mediatype") or "").strip().casefold() == "tvshow": + info_labels.setdefault("tvshowtitle", title) + playstate = _title_playstate(plugin_name, title) + info_labels = _apply_playstate_to_info(dict(info_labels), playstate) + display_label = _label_with_duration(title, info_labels) + display_label = _label_with_playstate(display_label, playstate) + _add_directory_item( + handle, + display_label, + "seasons", + {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, + is_folder=True, + info_labels=info_labels, + art=art, + cast=cast, + ) show_next = False if total_pages is not None: @@ -2429,16 +2525,16 @@ def _show_popular(plugin_name: str | None = None, page: int = 1) -> None: end = start + page_size page_items = titles[start:end] - show_tmdb = _get_setting_bool("tmdb_genre_metadata", default=False) if page_items: - plugin_meta = _collect_plugin_metadata(plugin, page_items) - show_tmdb = show_tmdb and _tmdb_enabled() + use_source, show_tmdb, prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_list_enabled() + ) + plugin_meta = _collect_plugin_metadata(plugin, page_items) if use_source else {} show_plot = _get_setting_bool("tmdb_show_plot", default=True) show_art = _get_setting_bool("tmdb_show_art", default=True) - prefer_source = bool(getattr(plugin, "prefer_source_metadata", False)) tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {} - tmdb_titles = list(page_items) - if show_tmdb and prefer_source: + tmdb_titles = list(page_items) if show_tmdb else [] + if show_tmdb and prefer_source and use_source: tmdb_titles = [] for title in page_items: meta = plugin_meta.get(title) @@ -2450,7 +2546,7 @@ def _show_popular(plugin_name: str | None = None, page: int = 1) -> None: with _busy_dialog(): tmdb_prefetched = _tmdb_labels_and_art_bulk(tmdb_titles) for title in page_items: - tmdb_info, tmdb_art, tmdb_cast = tmdb_prefetched.get(title, ({}, {}, [])) + tmdb_info, tmdb_art, tmdb_cast = tmdb_prefetched.get(title, ({}, {}, [])) if show_tmdb else ({}, {}, []) meta = plugin_meta.get(title) info_labels, art, cast = _merge_metadata(title, tmdb_info, tmdb_art, tmdb_cast, meta) info_labels.setdefault("mediatype", "tvshow") @@ -2577,48 +2673,50 @@ def _show_new_titles(plugin_name: str, page: int = 1) -> None: start = (page - 1) * page_size end = start + page_size page_items = titles[start:end] - show_tmdb = _get_setting_bool("tmdb_genre_metadata", default=False) if page_items: - if show_tmdb: - with _busy_dialog(): - tmdb_prefetched = _tmdb_labels_and_art_bulk(page_items) - for title in page_items: - info_labels, art, cast = tmdb_prefetched.get(title, _tmdb_labels_and_art(title)) - info_labels = dict(info_labels or {}) - info_labels.setdefault("mediatype", "movie") - playstate = _title_playstate(plugin_name, title) - info_labels = _apply_playstate_to_info(dict(info_labels), playstate) - display_label = _label_with_duration(title, info_labels) - display_label = _label_with_playstate(display_label, playstate) - direct_play = bool( - plugin_name.casefold() == "einschalten" - and _get_setting_bool("einschalten_enable_playback", default=False) - ) - _add_directory_item( - handle, - display_label, - "play_movie" if direct_play else "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=not direct_play, - info_labels=info_labels, - art=art, - cast=cast, - ) - else: + use_source, show_tmdb, prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_list_enabled() + ) + plugin_meta = _collect_plugin_metadata(plugin, page_items) if use_source else {} + show_plot = _get_setting_bool("tmdb_show_plot", default=True) + show_art = _get_setting_bool("tmdb_show_art", default=True) + tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {} + tmdb_titles = list(page_items) if show_tmdb else [] + if show_tmdb and prefer_source and use_source: + tmdb_titles = [] for title in page_items: - playstate = _title_playstate(plugin_name, title) - direct_play = bool( - plugin_name.casefold() == "einschalten" - and _get_setting_bool("einschalten_enable_playback", default=False) - ) - _add_directory_item( - handle, - _label_with_playstate(title, playstate), - "play_movie" if direct_play else "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=not direct_play, - info_labels=_apply_playstate_to_info({"title": title}, playstate), - ) + meta = plugin_meta.get(title) + meta_labels = meta[0] if meta else {} + meta_art = meta[1] if meta else {} + if _needs_tmdb(meta_labels, meta_art, want_plot=show_plot, want_art=show_art): + tmdb_titles.append(title) + if show_tmdb and tmdb_titles: + with _busy_dialog(): + tmdb_prefetched = _tmdb_labels_and_art_bulk(tmdb_titles) + for title in page_items: + tmdb_info, tmdb_art, tmdb_cast = tmdb_prefetched.get(title, ({}, {}, [])) if show_tmdb else ({}, {}, []) + meta = plugin_meta.get(title) + info_labels, art, cast = _merge_metadata(title, tmdb_info, tmdb_art, tmdb_cast, meta) + info_labels = dict(info_labels or {}) + info_labels.setdefault("mediatype", "movie") + playstate = _title_playstate(plugin_name, title) + info_labels = _apply_playstate_to_info(dict(info_labels), playstate) + display_label = _label_with_duration(title, info_labels) + display_label = _label_with_playstate(display_label, playstate) + direct_play = bool( + plugin_name.casefold() == "einschalten" + and _get_setting_bool("einschalten_enable_playback", default=False) + ) + _add_directory_item( + handle, + display_label, + "play_movie" if direct_play else "seasons", + {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, + is_folder=not direct_play, + info_labels=info_labels, + art=art, + cast=cast, + ) show_next = False if callable(paging_getter) and callable(has_more_getter): @@ -2738,7 +2836,9 @@ def _show_genre_series_group(plugin_name: str, genre: str, group_code: str, page return xbmcplugin.setPluginCategory(handle, f"{genre} [{group_code}] ({page})") - show_tmdb = _get_setting_bool("tmdb_genre_metadata", default=False) + use_source, show_tmdb, prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_list_enabled() + ) if page > 1: _add_directory_item( handle, @@ -2748,40 +2848,44 @@ def _show_genre_series_group(plugin_name: str, genre: str, group_code: str, page is_folder=True, ) if page_items: - if show_tmdb: - with _busy_dialog(): - tmdb_prefetched = _tmdb_labels_and_art_bulk(page_items) - for title in page_items: - info_labels, art, cast = tmdb_prefetched.get(title, _tmdb_labels_and_art(title)) - info_labels = dict(info_labels or {}) - info_labels.setdefault("mediatype", "tvshow") - if (info_labels.get("mediatype") or "").strip().casefold() == "tvshow": - info_labels.setdefault("tvshowtitle", title) - playstate = _title_playstate(plugin_name, title) - info_labels = _apply_playstate_to_info(dict(info_labels), playstate) - display_label = _label_with_duration(title, info_labels) - display_label = _label_with_playstate(display_label, playstate) - _add_directory_item( - handle, - display_label, - "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=True, - info_labels=info_labels, - art=art, - cast=cast, - ) - else: + plugin_meta = _collect_plugin_metadata(plugin, page_items) if use_source else {} + show_plot = _get_setting_bool("tmdb_show_plot", default=True) + show_art = _get_setting_bool("tmdb_show_art", default=True) + tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {} + tmdb_titles = list(page_items) if show_tmdb else [] + if show_tmdb and prefer_source and use_source: + tmdb_titles = [] for title in page_items: - playstate = _title_playstate(plugin_name, title) - _add_directory_item( - handle, - _label_with_playstate(title, playstate), - "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=True, - info_labels=_apply_playstate_to_info({"title": title}, playstate), - ) + meta = plugin_meta.get(title) + meta_labels = meta[0] if meta else {} + meta_art = meta[1] if meta else {} + if _needs_tmdb(meta_labels, meta_art, want_plot=show_plot, want_art=show_art): + tmdb_titles.append(title) + if show_tmdb and tmdb_titles: + with _busy_dialog(): + tmdb_prefetched = _tmdb_labels_and_art_bulk(tmdb_titles) + for title in page_items: + tmdb_info, tmdb_art, tmdb_cast = tmdb_prefetched.get(title, ({}, {}, [])) if show_tmdb else ({}, {}, []) + meta = plugin_meta.get(title) + info_labels, art, cast = _merge_metadata(title, tmdb_info, tmdb_art, tmdb_cast, meta) + info_labels = dict(info_labels or {}) + info_labels.setdefault("mediatype", "tvshow") + if (info_labels.get("mediatype") or "").strip().casefold() == "tvshow": + info_labels.setdefault("tvshowtitle", title) + playstate = _title_playstate(plugin_name, title) + info_labels = _apply_playstate_to_info(dict(info_labels), playstate) + display_label = _label_with_duration(title, info_labels) + display_label = _label_with_playstate(display_label, playstate) + _add_directory_item( + handle, + display_label, + "seasons", + {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, + is_folder=True, + info_labels=info_labels, + art=art, + cast=cast, + ) show_next = False if callable(grouped_has_more): try: @@ -2827,43 +2931,49 @@ def _show_genre_series_group(plugin_name: str, genre: str, group_code: str, page start = (page - 1) * page_size end = start + page_size page_items = filtered[start:end] - show_tmdb = _get_setting_bool("tmdb_genre_metadata", default=False) + use_source, show_tmdb, prefer_source = _metadata_policy( + plugin_name, plugin, allow_tmdb=_tmdb_list_enabled() + ) if page_items: - if show_tmdb: - with _busy_dialog(): - tmdb_prefetched = _tmdb_labels_and_art_bulk(page_items) - for title in page_items: - info_labels, art, cast = tmdb_prefetched.get(title, _tmdb_labels_and_art(title)) - info_labels = dict(info_labels or {}) - info_labels.setdefault("mediatype", "tvshow") - if (info_labels.get("mediatype") or "").strip().casefold() == "tvshow": - info_labels.setdefault("tvshowtitle", title) - playstate = _title_playstate(plugin_name, title) - info_labels = _apply_playstate_to_info(dict(info_labels), playstate) - display_label = _label_with_duration(title, info_labels) - display_label = _label_with_playstate(display_label, playstate) - _add_directory_item( - handle, - display_label, - "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=True, - info_labels=info_labels, - art=art, - cast=cast, - ) - else: + plugin_meta = _collect_plugin_metadata(plugin, page_items) if use_source else {} + show_plot = _get_setting_bool("tmdb_show_plot", default=True) + show_art = _get_setting_bool("tmdb_show_art", default=True) + tmdb_prefetched: dict[str, tuple[dict[str, str], dict[str, str], list[TmdbCastMember]]] = {} + tmdb_titles = list(page_items) if show_tmdb else [] + if show_tmdb and prefer_source and use_source: + tmdb_titles = [] for title in page_items: - playstate = _title_playstate(plugin_name, title) - _add_directory_item( - handle, - _label_with_playstate(title, playstate), - "seasons", - {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, - is_folder=True, - info_labels=_apply_playstate_to_info({"title": title}, playstate), - ) + meta = plugin_meta.get(title) + meta_labels = meta[0] if meta else {} + meta_art = meta[1] if meta else {} + if _needs_tmdb(meta_labels, meta_art, want_plot=show_plot, want_art=show_art): + tmdb_titles.append(title) + if show_tmdb and tmdb_titles: + with _busy_dialog(): + tmdb_prefetched = _tmdb_labels_and_art_bulk(tmdb_titles) + for title in page_items: + tmdb_info, tmdb_art, tmdb_cast = tmdb_prefetched.get(title, ({}, {}, [])) if show_tmdb else ({}, {}, []) + meta = plugin_meta.get(title) + info_labels, art, cast = _merge_metadata(title, tmdb_info, tmdb_art, tmdb_cast, meta) + info_labels = dict(info_labels or {}) + info_labels.setdefault("mediatype", "tvshow") + if (info_labels.get("mediatype") or "").strip().casefold() == "tvshow": + info_labels.setdefault("tvshowtitle", title) + playstate = _title_playstate(plugin_name, title) + info_labels = _apply_playstate_to_info(dict(info_labels), playstate) + display_label = _label_with_duration(title, info_labels) + display_label = _label_with_playstate(display_label, playstate) + _add_directory_item( + handle, + display_label, + "seasons", + {"plugin": plugin_name, "title": title, **_series_url_params(plugin, title)}, + is_folder=True, + info_labels=info_labels, + art=art, + cast=cast, + ) if total_pages > 1 and page < total_pages: _add_directory_item( diff --git a/addon/resources/settings.xml b/addon/resources/settings.xml index d9f7c76..f9e466c 100644 --- a/addon/resources/settings.xml +++ b/addon/resources/settings.xml @@ -31,22 +31,28 @@ + + + + + +