Files
ViewIT/addon/plugin_interface.py
itdrui.de 7b60b00c8b 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)
2026-03-01 18:39:05 +01:00

154 lines
5.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""Gemeinsame Schnittstelle fuer Kodi-Plugins."""
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any, Callable, Dict, List, Optional, Set, Tuple
class BasisPlugin(ABC):
"""Abstrakte Basisklasse fuer alle Integrationen."""
name: str
version: str = "0.0.0"
prefer_source_metadata: bool = False
@abstractmethod
async def search_titles(
self,
query: str,
progress_callback: Optional[Callable[[str, Optional[int]], Any]] = None,
) -> List[str]:
"""Liefert eine Liste aller Treffer fuer die Suche."""
@abstractmethod
def seasons_for(self, title: str) -> List[str]:
"""Liefert alle Staffeln zu einem Titel."""
@abstractmethod
def episodes_for(self, title: str, season: str) -> List[str]:
"""Liefert alle Folgen zu einer Staffel."""
def stream_link_for(self, title: str, season: str, episode: str) -> Optional[str]:
"""Optional: Liefert den Stream-Link fuer eine konkrete Folge."""
return None
def metadata_for(self, title: str) -> Tuple[Dict[str, str], Dict[str, str], Optional[List[Any]]]:
"""Optional: Liefert Info-Labels, Art und Cast fuer einen Titel."""
return {}, {}, None
def resolve_stream_link(self, link: str) -> Optional[str]:
"""Optional: Folgt einem Stream-Link und liefert die finale URL."""
return None
def genres(self) -> List[str]:
"""Optional: Liefert eine Liste an Genres (falls verfügbar)."""
return []
def titles_for_genre(self, genre: str) -> List[str]:
"""Optional: Liefert alle Serientitel zu einem Genre."""
return []
def capabilities(self) -> Set[str]:
"""Optional: Liefert eine Menge an Features/Capabilities dieses Plugins.
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()
def popular_series(self) -> List[str]:
"""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