From 5564851d35a1885f47fc3d0ef1952c32de2ca330 Mon Sep 17 00:00:00 2001 From: "itdrui.de" Date: Tue, 10 Mar 2026 10:41:37 +0100 Subject: [PATCH] =?UTF-8?q?dev:=20bump=20to=200.1.74-dev=20=E2=80=93=20Bur?= =?UTF-8?q?ningSeries=20entfernt,=20Paging-Fix=20Neuste=20Titel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG-DEV.md | 4 + addon/addon.xml | 2 +- addon/default.py | 261 +++++++------------------- addon/plugins/_template_plugin.py | 4 +- addon/plugins/aniworld_plugin.py | 7 +- addon/plugins/einschalten_plugin.py | 10 +- addon/plugins/filmpalast_plugin.py | 7 +- addon/plugins/netzkino_plugin.py | 7 +- addon/plugins/topstreamfilm_plugin.py | 7 +- scripts/hooks/commit-msg | 13 +- 10 files changed, 109 insertions(+), 213 deletions(-) diff --git a/CHANGELOG-DEV.md b/CHANGELOG-DEV.md index 6c1f520..7f23348 100644 --- a/CHANGELOG-DEV.md +++ b/CHANGELOG-DEV.md @@ -1,3 +1,7 @@ +## 0.1.73-dev - 2026-03-07 + +- dev: bump to 0.1.73-dev – Autoplay-Setting, Moflix Hoster-Dialog, Update-Hinweis im Hauptmenue + # Changelog (Dev) ## 0.1.71-dev - 2026-03-01 diff --git a/addon/addon.xml b/addon/addon.xml index 752ec06..14a66b2 100644 --- a/addon/addon.xml +++ b/addon/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/addon/default.py b/addon/default.py index 7d5ed2c..03e8b37 100644 --- a/addon/default.py +++ b/addon/default.py @@ -1203,6 +1203,7 @@ def _normalize_update_info_url(raw: str) -> str: UPDATE_CHANNEL_MAIN = 0 UPDATE_CHANNEL_NIGHTLY = 1 UPDATE_CHANNEL_CUSTOM = 2 +UPDATE_CHANNEL_DEV = 3 _AUTO_UPDATE_INTERVALS = [1 * 60 * 60, 6 * 60 * 60, 24 * 60 * 60] # 1h, 6h, 24h UPDATE_HTTP_TIMEOUT_SEC = 8 UPDATE_ADDON_ID = "plugin.video.viewit" @@ -1212,7 +1213,7 @@ RESOLVEURL_AUTO_INSTALL_INTERVAL_SEC = 6 * 60 * 60 def _selected_update_channel() -> int: channel = _get_setting_int("update_channel", default=UPDATE_CHANNEL_MAIN) - if channel not in {UPDATE_CHANNEL_MAIN, UPDATE_CHANNEL_NIGHTLY, UPDATE_CHANNEL_CUSTOM}: + if channel not in {UPDATE_CHANNEL_MAIN, UPDATE_CHANNEL_NIGHTLY, UPDATE_CHANNEL_CUSTOM, UPDATE_CHANNEL_DEV}: return UPDATE_CHANNEL_MAIN return channel @@ -1222,6 +1223,8 @@ def _channel_label(channel: int) -> str: return "Nightly" if channel == UPDATE_CHANNEL_CUSTOM: return "Custom" + if channel == UPDATE_CHANNEL_DEV: + return "Dev" return "Main" @@ -1246,11 +1249,17 @@ def _is_nightly_version(version: str) -> bool: return bool(re.match(r"^\d+\.\d+\.\d+-nightly$", str(version or "").strip())) +def _is_dev_version(version: str) -> bool: + return bool(re.match(r"^\d+\.\d+\.\d+-dev$", str(version or "").strip())) + + def _filter_versions_for_channel(channel: int, versions: list[str]) -> list[str]: if channel == UPDATE_CHANNEL_MAIN: return [v for v in versions if _is_stable_version(v)] if channel == UPDATE_CHANNEL_NIGHTLY: return [v for v in versions if _is_nightly_version(v)] + if channel == UPDATE_CHANNEL_DEV: + return [v for v in versions if _is_dev_version(v)] return list(versions) @@ -1260,6 +1269,8 @@ def _resolve_update_info_url() -> str: raw = _get_setting_string("update_repo_url_nightly") elif channel == UPDATE_CHANNEL_CUSTOM: raw = _get_setting_string("update_repo_url") + elif channel == UPDATE_CHANNEL_DEV: + raw = _get_setting_string("update_repo_url_dev") else: raw = _get_setting_string("update_repo_url_main") return _normalize_update_info_url(raw) @@ -1661,24 +1672,6 @@ def _show_root_menu() -> None: for plugin_name in sorted(plugins.keys(), key=lambda value: value.casefold()): _add_directory_item(handle, plugin_name, "plugin_menu", {"plugin": plugin_name}, is_folder=True) - # Katalog-Caches im Hintergrund vorwaermen (fire-and-forget) - for _pname, _plugin in plugins.items(): - _warmer = getattr(_plugin, "warm_catalog_cache", None) - if callable(_warmer): - def _warm_and_notify(_fn=_warmer, _name=_pname): - try: - loaded = _fn() - except Exception: - loaded = False - if loaded: - # executebuiltin ist thread-sicher; xbmcgui.Dialog() darf nicht - # aus Daemon-Threads aufgerufen werden (Kodi-Absturzgefahr). - safe_name = _name.replace('"', "") - xbmc.executebuiltin( - f'Notification("{safe_name}", "Suchindex geladen", 3000, "")' - ) - threading.Thread(target=_warm_and_notify, daemon=True, name=f"viewit-warmup-{_pname}").start() - # Trakt-Menue (nur wenn aktiviert) if _get_setting_bool("trakt_enabled", default=False): if _trakt_load_token(): @@ -1704,7 +1697,8 @@ def _show_plugin_menu(plugin_name: str) -> None: xbmcplugin.setPluginCategory(handle, plugin_name) - _add_directory_item(handle, "Suche", "plugin_search", {"plugin": plugin_name}, is_folder=True) + if callable(getattr(plugin, "search_titles", None)): + _add_directory_item(handle, "Suche", "plugin_search", {"plugin": plugin_name}, is_folder=True) if _plugin_has_capability(plugin, "new_titles") or _plugin_has_capability(plugin, "latest_episodes"): _add_directory_item(handle, LATEST_MENU_LABEL, "latest_titles", {"plugin": plugin_name, "page": "1"}, is_folder=True) @@ -2527,34 +2521,6 @@ def _show_episodes(plugin_name: str, title: str, season: str, series_url: str = xbmcplugin.endOfDirectory(handle) -def _show_genre_sources() -> None: - handle = _get_handle() - _log("Genre-Quellen laden.") - plugins = _discover_plugins() - sources: list[tuple[str, BasisPlugin]] = [] - for plugin_name, plugin in plugins.items(): - if plugin.__class__.genres is BasisPlugin.genres: - continue - if plugin.__class__.titles_for_genre is BasisPlugin.titles_for_genre: - continue - sources.append((plugin_name, plugin)) - - if not sources: - xbmcgui.Dialog().notification("Genres", "Keine Quellen mit Genres gefunden.", xbmcgui.NOTIFICATION_INFO, 3000) - xbmcplugin.endOfDirectory(handle) - return - - for plugin_name, plugin in sources: - _add_directory_item( - handle, - f"Genres [{plugin_name}]", - "genres", - {"plugin": plugin_name}, - is_folder=True, - ) - xbmcplugin.endOfDirectory(handle) - - def _show_genres(plugin_name: str) -> None: handle = _get_handle() _log(f"Genres laden: {plugin_name}") @@ -2596,44 +2562,6 @@ def _show_genres(plugin_name: str) -> None: xbmcplugin.endOfDirectory(handle) -def _show_categories(plugin_name: str) -> None: - handle = _get_handle() - _log(f"Kategorien laden: {plugin_name}") - plugin = _discover_plugins().get(plugin_name) - if plugin is None: - xbmcgui.Dialog().notification("Kategorien", "Quelle nicht gefunden.", xbmcgui.NOTIFICATION_INFO, 3000) - xbmcplugin.endOfDirectory(handle) - return - getter = getattr(plugin, "categories", None) - if not callable(getter): - xbmcgui.Dialog().notification("Kategorien", "Kategorien nicht verfuegbar.", xbmcgui.NOTIFICATION_INFO, 3000) - xbmcplugin.endOfDirectory(handle) - return - try: - categories = _run_with_progress( - "Kategorien", - f"{plugin_name}: Kategorien werden geladen...", - lambda: list(getter() or []), - ) - except Exception as exc: - _log(f"Kategorien konnten nicht geladen werden ({plugin_name}): {exc}", xbmc.LOGWARNING) - xbmcgui.Dialog().notification("Kategorien", "Kategorien konnten nicht geladen werden.", xbmcgui.NOTIFICATION_INFO, 3000) - xbmcplugin.endOfDirectory(handle) - return - for category in categories: - category = str(category).strip() - if not category: - continue - _add_directory_item( - handle, - category, - "category_titles_page", - {"plugin": plugin_name, "category": category, "page": "1"}, - is_folder=True, - ) - xbmcplugin.endOfDirectory(handle) - - def _show_paged_title_list( plugin_name: str, filter_value: str, @@ -2767,18 +2695,6 @@ def _show_paged_title_list( xbmcplugin.endOfDirectory(handle) -def _show_category_titles_page(plugin_name: str, category: str, page: int = 1) -> None: - _show_paged_title_list( - plugin_name, category, page, - dialog_label="Kategorien", - page_action="category_titles_page", - filter_param="category", - paging_method="titles_for_genre_page", - count_method="genre_page_count", - has_more_method="genre_has_more", - ) - - def _show_genre_titles_page(plugin_name: str, genre: str, page: int = 1) -> None: _show_paged_title_list( plugin_name, genre, page, @@ -3351,6 +3267,8 @@ def _show_new_titles(plugin_name: str, page: int = 1, *, action_name: str = "new show_next = bool(has_more_getter(page)) except Exception: show_next = False + elif callable(paging_getter) and page_items: + show_next = True elif "total_pages" in locals(): show_next = bool(total_pages > 1 and page < total_pages) # type: ignore[name-defined] @@ -3445,7 +3363,12 @@ def _show_latest_episodes(plugin_name: str, page: int = 1) -> None: info_labels=info_labels, ) - if entries: + has_more_fn = getattr(plugin, "latest_episodes_has_more", None) + if callable(has_more_fn): + show_next = bool(has_more_fn(page)) + else: + show_next = False + if show_next: _add_directory_item(handle, "Naechste Seite", "latest_titles", {"plugin": plugin_name, "page": str(page + 1)}, is_folder=True) @@ -3842,6 +3765,51 @@ def _is_resolveurl_missing_error(message: str) -> bool: return str(message or "").strip().casefold() == "resolveurl missing" +def _resolve_stream_with_retry(plugin: BasisPlugin, link: str) -> str | None: + """Löst einen Stream-Link auf mit ResolveURL-Auto-Install und CF-Check. + + Gibt den finalen Link zurück oder None (mit Kodi-Notification bei Fehler). + """ + 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( + "Wiedergabe", + "Hoster durch Cloudflare geschuetzt. Bitte spaeter erneut probieren.", + xbmcgui.NOTIFICATION_INFO, + 4500, + ) + return None + if not resolved_link: + _log("Stream konnte nicht aufgeloest werden.", xbmc.LOGWARNING) + xbmcgui.Dialog().notification( + "Wiedergabe", + "Stream konnte nicht aufgeloest werden.", + xbmcgui.NOTIFICATION_INFO, + 3000, + ) + return None + final_link = normalize_resolved_stream_url(resolved_link, source_url=link) + err = _resolveurl_last_error() + if _is_cloudflare_challenge_error(err) and final_link.strip() == link.strip(): + _log(f"ResolveURL Cloudflare-Challenge (unresolved): {err}", xbmc.LOGWARNING) + xbmcgui.Dialog().notification( + "Wiedergabe", + "Hoster durch Cloudflare geschuetzt. Bitte spaeter erneut probieren.", + xbmcgui.NOTIFICATION_INFO, + 4500, + ) + return None + return final_link + + def _play_final_link( link: str, *, @@ -4086,43 +4054,8 @@ def _play_episode( xbmcgui.Dialog().notification("Wiedergabe", "Kein Stream gefunden.", xbmcgui.NOTIFICATION_INFO, 3000) return _log(f"Stream-Link: {link}", xbmc.LOGDEBUG) - 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( - "Wiedergabe", - "Hoster durch Cloudflare geschuetzt. Bitte spaeter erneut probieren.", - xbmcgui.NOTIFICATION_INFO, - 4500, - ) - return - if not resolved_link: - _log("Stream konnte nicht aufgeloest werden.", xbmc.LOGWARNING) - xbmcgui.Dialog().notification( - "Wiedergabe", - "Stream konnte nicht aufgeloest werden.", - xbmcgui.NOTIFICATION_INFO, - 3000, - ) - return - final_link = resolved_link - final_link = normalize_resolved_stream_url(final_link, source_url=link) - err = _resolveurl_last_error() - if _is_cloudflare_challenge_error(err) and final_link.strip() == link.strip(): - _log(f"ResolveURL Cloudflare-Challenge (unresolved): {err}", xbmc.LOGWARNING) - xbmcgui.Dialog().notification( - "Wiedergabe", - "Hoster durch Cloudflare geschuetzt. Bitte spaeter erneut probieren.", - xbmcgui.NOTIFICATION_INFO, - 4500, - ) + final_link = _resolve_stream_with_retry(plugin, link) + if not final_link: return finally: if restore_hosters is not None and callable(preferred_setter): @@ -4237,43 +4170,8 @@ def _play_episode_url( xbmcgui.Dialog().notification("Wiedergabe", "Kein Stream gefunden.", xbmcgui.NOTIFICATION_INFO, 3000) return _log(f"Stream-Link: {link}", xbmc.LOGDEBUG) - 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( - "Wiedergabe", - "Hoster durch Cloudflare geschuetzt. Bitte spaeter erneut probieren.", - xbmcgui.NOTIFICATION_INFO, - 4500, - ) - return - if not resolved_link: - _log("Stream konnte nicht aufgeloest werden.", xbmc.LOGWARNING) - xbmcgui.Dialog().notification( - "Wiedergabe", - "Stream konnte nicht aufgeloest werden.", - xbmcgui.NOTIFICATION_INFO, - 3000, - ) - return - final_link = resolved_link - final_link = normalize_resolved_stream_url(final_link, source_url=link) - err = _resolveurl_last_error() - if _is_cloudflare_challenge_error(err) and final_link.strip() == link.strip(): - _log(f"ResolveURL Cloudflare-Challenge (unresolved): {err}", xbmc.LOGWARNING) - xbmcgui.Dialog().notification( - "Wiedergabe", - "Hoster durch Cloudflare geschuetzt. Bitte spaeter erneut probieren.", - xbmcgui.NOTIFICATION_INFO, - 4500, - ) + final_link = _resolve_stream_with_retry(plugin, link) + if not final_link: return finally: if restore_hosters is not None and callable(preferred_setter): @@ -4945,21 +4843,11 @@ def _route_plugin_search(params: dict[str, str]) -> None: _show_plugin_search(params.get("plugin", "")) -@_router.route("genre_sources") -def _route_genre_sources(params: dict[str, str]) -> None: - _show_genre_sources() - - @_router.route("genres") def _route_genres(params: dict[str, str]) -> None: _show_genres(params.get("plugin", "")) -@_router.route("categories") -def _route_categories(params: dict[str, str]) -> None: - _show_categories(params.get("plugin", "")) - - @_router.route("latest_titles") def _route_latest_titles(params: dict[str, str]) -> None: _show_latest_titles(params.get("plugin", ""), _parse_positive_int(params.get("page", "1"), default=1)) @@ -4988,13 +4876,6 @@ def _route_genre_titles_page(params: dict[str, str]) -> None: ) -@_router.route("category_titles_page") -def _route_category_titles_page(params: dict[str, str]) -> None: - _show_category_titles_page( - params.get("plugin", ""), params.get("category", ""), - _parse_positive_int(params.get("page", "1"), default=1), - ) - @_router.route("alpha_index") def _route_alpha_index(params: dict[str, str]) -> None: diff --git a/addon/plugins/_template_plugin.py b/addon/plugins/_template_plugin.py index d923831..55477f9 100644 --- a/addon/plugins/_template_plugin.py +++ b/addon/plugins/_template_plugin.py @@ -9,7 +9,7 @@ Vorgehen fuer ein neues Plugin: 3. `search_titles`, `seasons_for`, `episodes_for` gemaess Zielseite implementieren 4. Optional weitere Methoden implementieren – capabilities deklarieren und Methoden ueberschreiben: - `popular_series()` + capability 'popular_series' - - `latest_titles(page)` + capability 'latest_titles' + - `new_titles()` + `new_titles_page(page)` + capability 'new_titles' - `genres()` + `titles_for_genre(genre)` + `titles_for_genre_page(genre, page)` - `alpha_index()` + `titles_for_alpha_page(letter, page)` - `years_available()` + `titles_for_year(year, page)` + capability 'year_filter' @@ -169,7 +169,7 @@ class TemplatePlugin(BasisPlugin): Bekannte Werte (aus plugin_interface.py): - 'popular_series' – Plugin hat beliebte Serien/Filme - - 'latest_titles' – Plugin hat neu hinzugefuegte Titel + - 'new_titles' – Plugin hat neu hinzugefuegte Titel - 'year_filter' – Plugin unterstuetzt Jahr-Filter - 'country_filter' – Plugin unterstuetzt Land-Filter - 'collections' – Plugin hat Sammlungen/Filmreihen diff --git a/addon/plugins/aniworld_plugin.py b/addon/plugins/aniworld_plugin.py index 35c2710..150518e 100644 --- a/addon/plugins/aniworld_plugin.py +++ b/addon/plugins/aniworld_plugin.py @@ -1025,7 +1025,7 @@ class AniworldPlugin(BasisPlugin): _session_cache_set(self._season_episodes_cache_name(season_url), payload) def capabilities(self) -> set[str]: - return {"popular_series", "genres", "latest_episodes", "latest_titles"} + return {"popular_series", "genres", "latest_episodes", "new_titles"} def _find_series_by_title(self, title: str) -> Optional[SeriesResult]: title = (title or "").strip() @@ -1345,7 +1345,7 @@ class AniworldPlugin(BasisPlugin): except Exception: return 1 - def latest_titles(self, page: int = 1) -> List[str]: + def new_titles_page(self, page: int = 1) -> List[str]: """Liefert neu hinzugefuegte Anime vom Animekalender.""" if not self._requests_available: return [] @@ -1372,6 +1372,9 @@ class AniworldPlugin(BasisPlugin): except Exception: return [] + def new_titles(self) -> List[str]: + return self.new_titles_page(1) + def _season_label(self, number: int) -> str: return f"Staffel {number}" diff --git a/addon/plugins/einschalten_plugin.py b/addon/plugins/einschalten_plugin.py index 932df4e..008c162 100644 --- a/addon/plugins/einschalten_plugin.py +++ b/addon/plugins/einschalten_plugin.py @@ -1019,7 +1019,7 @@ class EinschaltenPlugin(BasisPlugin): return resolve_via_resolveurl(link, fallback_to_link=True) def capabilities(self) -> Set[str]: - return {"new_titles", "genres", "popular_series", "latest_titles"} + return {"new_titles", "genres", "popular_series"} def popular_series(self) -> List[str]: """Liefert die am besten bewerteten Filme (nach voteAverage sortiert).""" @@ -1042,14 +1042,6 @@ class EinschaltenPlugin(BasisPlugin): titles.append(movie.title) return titles - def latest_titles(self, page: int = 1) -> List[str]: - """Liefert neu hinzugefügte Filme (Alias zu new_titles_page).""" - if not REQUESTS_AVAILABLE: - return [] - if not self._get_base_url(): - return [] - return self.new_titles_page(max(1, int(page or 1))) - def new_titles(self) -> List[str]: if not REQUESTS_AVAILABLE: return [] diff --git a/addon/plugins/filmpalast_plugin.py b/addon/plugins/filmpalast_plugin.py index 60b35d9..967b4f6 100644 --- a/addon/plugins/filmpalast_plugin.py +++ b/addon/plugins/filmpalast_plugin.py @@ -525,7 +525,7 @@ class FilmpalastPlugin(BasisPlugin): return max_page def capabilities(self) -> set[str]: - return {"genres", "alpha", "series_catalog", "popular_series", "latest_titles"} + return {"genres", "alpha", "series_catalog", "popular_series", "new_titles"} def _parse_alpha_links(self, soup: BeautifulSoupT) -> Dict[str, str]: alpha: Dict[str, str] = {} @@ -1057,7 +1057,7 @@ class FilmpalastPlugin(BasisPlugin): except Exception: return [] - def latest_titles(self, page: int = 1) -> List[str]: + def new_titles_page(self, page: int = 1) -> List[str]: """Liefert neu hinzugefuegte Titel von /movies/new.""" if not self._requests_available: return [] @@ -1071,6 +1071,9 @@ class FilmpalastPlugin(BasisPlugin): except Exception: return [] + def new_titles(self) -> List[str]: + return self.new_titles_page(1) + def resolve_stream_link(self, link: str) -> Optional[str]: if not link: return None diff --git a/addon/plugins/netzkino_plugin.py b/addon/plugins/netzkino_plugin.py index f2639e3..e52f1a2 100644 --- a/addon/plugins/netzkino_plugin.py +++ b/addon/plugins/netzkino_plugin.py @@ -231,10 +231,13 @@ class NetzkinoPlugin(BasisPlugin): # Browsing # ------------------------------------------------------------------ - def latest_titles(self, page: int = 1) -> List[str]: + def new_titles_page(self, page: int = 1) -> List[str]: url = _URL_CATEGORY.format(slug="neue-filme") return self._load_posts(url) + def new_titles(self) -> List[str]: + return self.new_titles_page(1) + def genres(self) -> List[str]: # Gibt die Anzeigenamen zurück (sortiert, Browsing-Kategorien) return sorted(CATEGORIES.values()) @@ -248,4 +251,4 @@ class NetzkinoPlugin(BasisPlugin): return self._load_posts(url) def capabilities(self) -> set[str]: - return {"latest_titles", "genres"} + return {"new_titles", "genres"} diff --git a/addon/plugins/topstreamfilm_plugin.py b/addon/plugins/topstreamfilm_plugin.py index 1281c9e..bafddbe 100644 --- a/addon/plugins/topstreamfilm_plugin.py +++ b/addon/plugins/topstreamfilm_plugin.py @@ -1167,7 +1167,7 @@ class TopstreamfilmPlugin(BasisPlugin): return resolve_via_resolveurl(link, fallback_to_link=True) def capabilities(self) -> set[str]: - return {"genres", "popular_series", "year_filter", "latest_titles"} + return {"genres", "popular_series", "year_filter", "new_titles"} def years_available(self) -> List[str]: """Liefert verfügbare Erscheinungsjahre (aktuelles Jahr bis 1980).""" @@ -1207,7 +1207,7 @@ class TopstreamfilmPlugin(BasisPlugin): self._save_title_url_cache() return titles - def latest_titles(self, page: int = 1) -> List[str]: + def new_titles_page(self, page: int = 1) -> List[str]: """Liefert neu hinzugefügte Filme. URL-Muster: /neueste-filme/ oder /neueste-filme/page/{n}/ @@ -1238,6 +1238,9 @@ class TopstreamfilmPlugin(BasisPlugin): self._save_title_url_cache() return titles + def new_titles(self) -> List[str]: + return self.new_titles_page(1) + # Alias für die automatische Plugin-Erkennung. Plugin = TopstreamfilmPlugin diff --git a/scripts/hooks/commit-msg b/scripts/hooks/commit-msg index 2d3383e..b776d73 100755 --- a/scripts/hooks/commit-msg +++ b/scripts/hooks/commit-msg @@ -1,5 +1,5 @@ #!/bin/bash -# commit-msg: Commit-Message als Changelog-Eintrag in CHANGELOG-DEV.md prependen (nur dev-Branch) +# commit-msg: Version in Commit-Message aktualisieren und Changelog-Eintrag prependen (nur dev-Branch) branch=$(git symbolic-ref --short HEAD 2>/dev/null) [[ "$branch" != "dev" ]] && exit 0 @@ -7,8 +7,15 @@ branch=$(git symbolic-ref --short HEAD 2>/dev/null) root=$(git rev-parse --show-toplevel) cd "$root" -msg=$(cat "$1") +# Aktuelle Version aus addon.xml (bereits vom pre-commit Hook hochgezählt) version=$(grep -oP 'version="\K[0-9]+\.[0-9]+\.[0-9]+[^"]*' addon/addon.xml | head -1) + +# Commit-Message: alte Versionsnummern durch aktuelle ersetzen +# z.B. "dev: bump to 0.1.72-dev – ..." → "dev: bump to 0.1.73-dev – ..." +msg=$(cat "$1") +updated_msg=$(echo "$msg" | sed -E "s/bump to [0-9]+\.[0-9]+\.[0-9]+[^ ]*/bump to ${version}/g") +echo "$updated_msg" > "$1" + today=$(date +%Y-%m-%d) # Changelog-Eintrag aufbauen @@ -19,7 +26,7 @@ today=$(date +%Y-%m-%d) while IFS= read -r line; do [[ -z "$line" ]] && continue echo "- ${line}" - done <<< "$msg" + done <<< "$updated_msg" echo "" cat CHANGELOG-DEV.md } > /tmp/changelog_new.md