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

@@ -1,5 +1,129 @@
# Changelog (Dev)
## 0.1.69-dev - 2026-03-01
### Trakt: Neue Features
- **Weiterschauen:** Neuer Hauptmenüpunkt zeigt die nächste ungesehene Folge je Serie
basierend auf der Trakt-History. Auto-Matching sucht den Titel automatisch in allen
aktiven Plugins und verlinkt direkt zur richtigen Staffel.
- **Trakt Upcoming:** Neuer Hauptmenüpunkt zeigt anstehende Episoden der Watchlist-Serien
(Trakt-Kalender, 14 Tage voraus) mit Ausstrahlungsdatum und TMDB-Poster.
Auto-Matching wie bei „Weiterschauen".
- **Watched-Status in Episodenlisten:** Bereits bei Trakt als gesehen markierte Episoden
werden in Staffelansichten mit Häkchen (Kodi `playcount=1`) markiert.
Ergebnis wird 5 Minuten gecacht um API-Aufrufe zu minimieren.
- **`core/trakt.py`:** Neuer `TraktCalendarItem`-Dataclass und `get_calendar()`-Methode
(Trakt Calendar API: `/calendars/my/shows/{start}/{days}`).
### Python 3.8 Kompatibilität (Windows/Kodi)
- **`from __future__ import annotations`** in allen Modulen ergänzt, die noch kein
deferred-evaluation hatten (`core/router.py`, `core/metadata.py`, `core/playstate.py`,
`core/gui.py`, `regex_patterns.py`). Behebt `TypeError: 'type' object is not subscriptable`
auf Kodi-Installationen mit Python 3.8 (Windows).
### Bugfixes
- **`dokustreams_plugin.py`:** Regex `r"(\\d+)"``r"(\d+)"` Seitennavigation hat
nie Seitenzahlen gefunden (falsch-escaped in Raw-String).
- **`serienstream_plugin.py`:** Dedup-Key verwendete `\\t` (Backslash+t) statt echtem
Tab-Zeichen inkonsistent mit `aniworld_plugin.py`.
- **Menübereinigung:** Doppelter Menüpunkt „Neue Titel" (`new_plugin_titles`) entfernt
identisch mit „Neuste Titel" (`latest_titles`).
---
## 0.1.67-dev - 2026-02-27
### Stabilitäts- und Sicherheits-Fixes
- **Sicherheit (updater.py):** ZIP-Extraktion prüft jetzt jeden Eintrag auf Path-Traversal.
Bösartige Pfade (z. B. `../../`) werden abgelehnt und der Update-Vorgang abgebrochen
(war: still ignoriert mit `continue`).
- **Silent-Failure-Fix (metadata.py):** Neues `_initialized`-Flag und `_require_init()`-Guard
wenn `init()` nicht aufgerufen wurde, erscheint jetzt eine Warnung im Log statt lautlosem No-Op.
- **Thread-Safety (default.py):** Neue Locks `_PLUGIN_CACHE_LOCK` und `_GENRE_TITLES_CACHE_LOCK`
schützen alle Cache-Zugriffe auf Plugin-Instanzen und Genre-Titel-Caches.
- **Memory-Leak-Fix (default.py):** Alle internen Caches haben jetzt ein Größenlimit
(`_CACHE_MAXSIZE = 500`) mit LRU-artigem Eviction-Mechanismus.
- **Code-Qualität (default.py):** ~300 Zeilen Duplicate-Code durch `_show_paged_title_list()`
Hilfsfunktion ersetzt alle paginierten Titellisten (Genres, Kategorien, A-Z) nutzen jetzt
dieselbe Logik.
- **Syntax-Fix (default.py):** Fremd-Text in Zeile 3517 entfernt, der einen latenten Syntax-
Fehler verursachte.
### Neues Plugin-Interface
Neue optionale Methoden in `BasisPlugin` (plugin_interface.py):
| Methode | Beschreibung |
|---------|-------------|
| `latest_titles(page)` | Neuerscheinungen / neu hinzugefügte Titel |
| `years_available()` | Verfügbare Erscheinungsjahre für Filter |
| `titles_for_year(year, page)` | Titel nach Jahr gefiltert |
| `countries_available()` | Verfügbare Länder für Filter |
| `titles_for_country(country, page)` | Titel nach Herkunftsland gefiltert |
| `collections()` | Filmreihen / Sammlungen |
| `titles_for_collection(collection, page)` | Titel einer Sammlung |
| `tags()` | Schlagworte / Tags |
| `titles_for_tag(tag, page)` | Titel nach Schlagwort |
| `random_title()` | Zufälliger Titel |
Neue Capability-Strings: `latest_titles`, `year_filter`, `country_filter`, `collections`, `tags`, `random`
### Neue Menüeinträge in default.py
Plugins die die neuen Capabilities melden, erhalten automatisch folgende Menüpunkte:
- **"Neue Titel"** für Plugins mit `latest_titles`
- **"Nach Jahr"** für Plugins mit `year_filter`
- **"Nach Land"** für Plugins mit `country_filter`
- **"Sammlungen"** für Plugins mit `collections`
- **"Schlagworte"** für Plugins mit `tags`
- **"Zufälliger Titel"** für Plugins mit `random`
### Plugin-Erweiterungen
**Filmpalast** (`filmpalast_plugin.py`):
- `popular_series()` scrapt Top-Filme von `/movies/top`
- `latest_titles(page)` scrapt Neuerscheinungen von `/movies/new` mit Pagination
- IMDb-Rating in `metadata_for()` integriert (`info_labels["rating"]`)
- Neue Capabilities: `popular_series`, `latest_titles`
**Doku-Streams** (`dokustreams_plugin.py`):
- `tags()` scrapt alle Schlagworte von der Startseite
- `titles_for_tag(tag, page)` Titelliste pro Schlagwort mit Pagination
- `random_title()` folgt dem Redirect von `/zufaellige-doku/`
- `resolve_stream_link(link)` ResolveURL + HTTP-Redirect-Fallback
- Neue Capabilities: `tags`, `random`
**AniWorld** (`aniworld_plugin.py`):
- `titles_for_genre_page(genre, page)` paginierte Genre-Titellisten via `/genre/[slug]?page=[n]`
- `genre_page_count(genre)` letzte Seitennummer aus Pagination extrahiert
- `latest_titles(page)` neue Anime-Releases via `/animekalender`
- Neue Capability: `latest_titles`
**SerienStream** (`serienstream_plugin.py`):
- `latest_titles(page)` neue Serien via JSON-Kalender-API (`/api/calendar`) mit wochenweiser Rückwärts-Paginierung
- `genre_page_count(genre)` Gesamtanzahl der Genre-Seiten aus Pagination-Links extrahiert
- `alpha_index()` gibt A-Z-Buchstaben + `0-9` zurück
- `titles_for_alpha_page(letter, page)` Serien alphabetisch abrufen via `/serien/alle?buchstabe={letter}`
- Neue Capabilities: `latest_titles`, `alpha`
**TopStreamFilm** (`topstreamfilm_plugin.py`):
- `years_available()` statische Liste vom aktuellen Jahr bis 1980
- `titles_for_year(year, page)` Titel nach Erscheinungsjahr via `/xfsearch/{year}/page/{n}/`
- `latest_titles(page)` neue Filme via `/neueste-filme/page/{n}/`
- Neue Capabilities: `year_filter`, `latest_titles`
**Einschalten** (`einschalten_plugin.py`):
- `popular_series()` Top-50 Filme sortiert nach `voteAverage` (absteigend)
- `latest_titles(page)` neue Filme (Alias zu `new_titles_page(page)`)
- Neue Capabilities: `popular_series`, `latest_titles`
- Hinweis: Ratings (`voteAverage`, `voteCount`) waren bereits in `metadata_for()` enthalten
---
## 0.1.66-dev - 2026-02-25
- Serienstream HTTP-Fetches robuster gemacht: Retry bei kurzzeitigen Verbindungsabbruechen inkl. Session-Reset.