dev: umfangreiches Refactoring, Trakt-Integration und Code-Review-Fixes (0.1.69-dev)

Core & Architektur:
- Neues Verzeichnis addon/core/ mit router.py, trakt.py, metadata.py,
  gui.py, playstate.py, plugin_manager.py, updater.py
- Tests-Verzeichnis hinzugefügt (24 Tests, pytest + Coverage)

Trakt-Integration:
- OAuth Device Flow, Scrobbling, Watchlist, History, Calendar
- Upcoming Episodes, Weiterschauen (Continue Watching)
- Watched-Status in Episodenlisten
- _trakt_find_in_plugins() mit 5-Min-Cache

Serienstream-Suche:
- API-Ergebnisse werden immer mit Katalog-Cache ergänzt (serverseitiges 10-Treffer-Limit)
- Katalog-Cache wird beim Addon-Start im Daemon-Thread vorgewärmt
- Notification nach Cache-Load via xbmc.executebuiltin() (thread-sicher)

Bugfixes (Code-Review):
- Race Condition auf _TRAKT_WATCHED_CACHE: _TRAKT_WATCHED_CACHE_LOCK hinzugefügt
- GUI-Dialog aus Daemon-Thread: xbmcgui -> xbmc.executebuiltin()
- ValueError in Trakt-Watchlist-Routen abgesichert
- Token expires_at==0 Check korrigiert
- get_setting_bool() Kontrollfluss in gui.py bereinigt
- topstreamfilm_plugin: try-finally um xbmcvfs.File.close()

Cleanup:
- default.py.bak und refactor_router.py entfernt
- .gitignore: /tests/ Eintrag entfernt
- Type-Hints vereinheitlicht (Dict/List/Tuple -> dict/list/tuple)
This commit is contained in:
2026-03-01 18:23:45 +01:00
parent 73f07d20b4
commit 7b60b00c8b
36 changed files with 4765 additions and 672 deletions

View File

@@ -53,8 +53,14 @@ class BasisPlugin(ABC):
def capabilities(self) -> Set[str]:
"""Optional: Liefert eine Menge an Features/Capabilities dieses Plugins.
Beispiele:
- `popular_series`: Plugin kann eine Liste beliebter Serien liefern.
Bekannte Werte:
- 'popular_series' Plugin hat beliebte Serien/Filme
- 'latest_titles' Plugin hat neu hinzugefuegte Titel
- 'year_filter' Plugin unterstuetzt Jahr-Filter
- 'country_filter' Plugin unterstuetzt Land-Filter
- 'collections' Plugin hat Sammlungen/Filmreihen
- 'tags' Plugin hat Tag/Schlagwort-Suche
- 'random' Plugin kann einen zufaelligen Titel liefern
"""
return set()
@@ -63,3 +69,85 @@ class BasisPlugin(ABC):
"""Optional: Liefert eine Liste beliebter Serien (als Titel-Strings)."""
return []
# ------------------------------------------------------------------
# Neue Felder fuer "Neue Titel"-Menü
# ------------------------------------------------------------------
def latest_titles(self, page: int = 1) -> List[str]:
"""Optional: Liefert neu hinzugefuegte Titel (Filme oder Serien).
Capability: 'latest_titles'
"""
return []
# ------------------------------------------------------------------
# Jahr-Filter
# ------------------------------------------------------------------
def years_available(self) -> List[str]:
"""Optional: Liefert verfuegbare Erscheinungsjahre (z.B. ['2026', '2025', ...]).
Capability: 'year_filter'
"""
return []
def titles_for_year(self, year: str, page: int = 1) -> List[str]:
"""Optional: Liefert Titel fuer ein bestimmtes Erscheinungsjahr."""
return []
# ------------------------------------------------------------------
# Land-Filter
# ------------------------------------------------------------------
def countries_available(self) -> List[str]:
"""Optional: Liefert verfuegbare Produktionslaender.
Capability: 'country_filter'
"""
return []
def titles_for_country(self, country: str, page: int = 1) -> List[str]:
"""Optional: Liefert Titel fuer ein bestimmtes Produktionsland."""
return []
# ------------------------------------------------------------------
# Sammlungen / Collections
# ------------------------------------------------------------------
def collections(self) -> List[str]:
"""Optional: Liefert verfuegbare Sammlungen/Filmreihen.
Capability: 'collections'
"""
return []
def titles_for_collection(self, collection: str, page: int = 1) -> List[str]:
"""Optional: Liefert Titel einer Sammlung/Filmreihe."""
return []
# ------------------------------------------------------------------
# Tags / Schlagworte
# ------------------------------------------------------------------
def tags(self) -> List[str]:
"""Optional: Liefert verfuegbare Schlagworte/Tags.
Capability: 'tags'
"""
return []
def titles_for_tag(self, tag: str, page: int = 1) -> List[str]:
"""Optional: Liefert Titel zu einem Schlagwort/Tag."""
return []
# ------------------------------------------------------------------
# Zufaelliger Titel
# ------------------------------------------------------------------
def random_title(self) -> Optional[str]:
"""Optional: Liefert einen zufaelligen Titel.
Capability: 'random'
"""
return None