Analysiert und dokumentiert: - plugin.video.xstream: Startup-Sequenz, URL-Routing, Site-Plugin-Konvention, Browsing- und Hoster-Auflösungsflow, globale Suche - script.module.xstreamscraper: automatische TMDB-basierte Stream-Suche - HTTP-Request-Handler: Caching, Cookie-Verwaltung, Anti-Bot-Mechanismen - Plugin-Handler, GUI-Schicht, Einstellungsreferenz, Abhängigkeiten Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
432 lines
18 KiB
Markdown
432 lines
18 KiB
Markdown
# xStream – Technische Dokumentation
|
||
|
||
Version: `plugin.video.xstream 2026.02.11` / `script.module.xstreamscraper 2025.08.14`
|
||
Erstellt: 2026-08-17
|
||
|
||
---
|
||
|
||
## 1. Übersicht
|
||
|
||
Das Projekt besteht aus zwei voneinander abhängigen Kodi-Addons:
|
||
|
||
| Addon | Zweck |
|
||
|---|---|
|
||
| `plugin.video.xstream` | Vollständiges Video-Plugin: Browser-GUI, Site-Plugins, Hoster-Auflösung, Download |
|
||
| `script.module.xstreamscraper` | Companion-Modul: automatische Suche und Stream-Auflösung via TMDB-ID, für externe Aufrufer |
|
||
|
||
**Zusammenfassung der Funktion:** xStream ist eine Kodi-Suchmaschine für Filme und Serien. Es lädt Inhalte von verschiedenen Streaming-Webseiten (sogenannte „Site-Plugins"), löst die gefundenen Hoster-Links über das `resolveurl`-Addon auf und spielt den Stream in Kodi ab. Das Scraper-Modul ergänzt dies um eine vollautomatische Suche, die auf TMDB-IDs basiert.
|
||
|
||
---
|
||
|
||
## 2. Komponentenstruktur
|
||
|
||
```
|
||
Xstream-Standalone/
|
||
├── plugin.video.xstream/
|
||
│ ├── addon.xml # Addon-Metadaten und Abhängigkeiten
|
||
│ ├── default.py # Einstiegspunkt (Kodi ruft dies auf)
|
||
│ ├── service.py # Kodi-Service (läuft beim Kodi-Start)
|
||
│ ├── xstream.py # URL-Router und Hauptlogik
|
||
│ ├── sites/ # Site-Plugins (eine Datei pro Webseite)
|
||
│ │ ├── kinox.py
|
||
│ │ ├── aniworld.py
|
||
│ │ ├── burningseries.py
|
||
│ │ └── ...
|
||
│ └── resources/
|
||
│ └── lib/
|
||
│ ├── config.py # Addon-Einstellungen (Wrapper um xbmcaddon)
|
||
│ ├── tools.py # Logger, Parser, Cache-Hilfsfunktionen
|
||
│ ├── gui/
|
||
│ │ ├── gui.py # Kodi-GUI-Abstraktion (Listeneinträge, Ansichten)
|
||
│ │ ├── guiElement.py # Einzelner Listeneintrag (Titel, Thumbnail, Metadaten)
|
||
│ │ ├── hoster.py # Hoster-GUI: Abspielen, Download, Weiterleiten
|
||
│ │ └── contextElement.py# Kontextmenü-Einträge
|
||
│ └── handler/
|
||
│ ├── pluginHandler.py # Erkennung und Verwaltung der Site-Plugins
|
||
│ ├── requestHandler.py# HTTP-Client mit Cache, Cookies, Anti-Bot
|
||
│ ├── ParameterHandler.py # URL-Parameter lesen/schreiben
|
||
│ ├── jdownloaderHandler.py
|
||
│ ├── jdownloader2Handler.py
|
||
│ ├── myjdownloaderHandler.py
|
||
│ └── pyLoadHandler.py
|
||
└── script.module.xstreamscraper/
|
||
├── addon.xml
|
||
├── main.py # Einstiegspunkt des Scraper-Moduls
|
||
├── service.py # Service des Scraper-Moduls
|
||
└── resources/lib/
|
||
├── scraper.py # Kernlogik: Suche, Hoster-Auflösung, Wiedergabe
|
||
├── settings.py # Globaler Zustand (collectMode, aDirectory)
|
||
├── tools.py
|
||
├── gui/ # GUI-Klassen (Subset von plugin.video.xstream)
|
||
└── handler/ # Request- und Parameter-Handler (Subset)
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Ablauf: plugin.video.xstream
|
||
|
||
### 3.1 Startup-Sequenz (Service)
|
||
|
||
`service.py` wird von Kodi beim Start als separater Service-Prozess ausgeführt.
|
||
|
||
```
|
||
Kodi-Start
|
||
└─► service.py: main()
|
||
1. cCache: setze '{addon_id}_main' = 'running'
|
||
2. Resolver-Update von GitHub prüfen/ausführen (updateManager.resolverUpdate)
|
||
3. Abhängigkeiten prüfen (checkDependence) – fehlende Addons installieren
|
||
4. Domain-Prüfung aller Site-Plugins parallel (cPluginHandler.checkDomain)
|
||
→ HTTP-Request an domain des jeweiligen Site-Plugins
|
||
→ Status 200/3xx: Domain aktiv, globale Suche aktiviert
|
||
→ Status 403–503: globale Suche deaktiviert, Link gesperrt
|
||
5. PluginDB aktualisieren (falls neue Einstellungen vorhanden)
|
||
6. cCache: setze '{addon_id}_main' = 'finished'
|
||
7. Changelog-Popup anzeigen (falls konfiguriert)
|
||
8. Alten HTML-Cache löschen (alle N Tage, konfigurierbar)
|
||
```
|
||
|
||
`showMainMenu()` in `xstream.py` wartet aktiv (max. 60 Sekunden / 0,5-Sekunden-Schleifen) auf das Signal `'finished'`, bevor das Hauptmenü aufgebaut wird.
|
||
|
||
---
|
||
|
||
### 3.2 Browsing-Flow (Plugin-Aufruf)
|
||
|
||
Kodi ruft `default.py` mit einer Plugin-URL der Form
|
||
`plugin://plugin.video.xstream/?site=kinox&function=showMovieMenu&...` auf.
|
||
|
||
```
|
||
default.py: main()
|
||
└─► Systempfade einrichten (sites/, lib/, art/sites/)
|
||
└─► xstream.py: parseUrl()
|
||
├── ParameterHandler: URL-Parameter lesen
|
||
├── Sonderfunktionen: clearCache, viewInfo, searchAlter, searchTMDB, ...
|
||
├── Kein 'site'-Parameter → showMainMenu()
|
||
│ └── alle aktivierten Site-Plugins als Listeneinträge hinzufügen
|
||
├── site = 'cHosterGui' → showHosterGui()
|
||
├── site = 'globalSearch' → searchGlobal()
|
||
├── site = 'xStream' → xStream-Einstellungen öffnen
|
||
├── site = 'resolver' → Resolver-Einstellungen öffnen
|
||
└── site = '<plugin-name>'
|
||
└── plugin = __import__('<plugin-name>')
|
||
└── function = getattr(plugin, sFunction)
|
||
└── function() ← Site-Plugin übernimmt
|
||
```
|
||
|
||
---
|
||
|
||
### 3.3 Site-Plugin-Konvention
|
||
|
||
Jede Datei in `sites/` ist ein eigenständiges Python-Modul. Es muss folgende Modul-Variablen und Funktionen bereitstellen:
|
||
|
||
| Name | Pflicht | Beschreibung |
|
||
|---|---|---|
|
||
| `SITE_IDENTIFIER` | Ja | Eindeutiger Bezeichner (= Dateiname ohne `.py`) |
|
||
| `SITE_NAME` | Ja | Anzeigename im Menü |
|
||
| `SITE_ICON` | Nein | Dateiname des Icons in `resources/art/sites/` |
|
||
| `DOMAIN` | Nein | Standarddomain; kann per Einstellung überschrieben werden |
|
||
| `SITE_GLOBAL_SEARCH` | Nein | `True`/`False`; steuert globale Suche |
|
||
| `load()` | Ja | Einstiegspunkt – baut Hauptmenü des Sites auf |
|
||
| `_search(oGui, sSearchText)` | Nein | Globale Suche; befüllt `oGui` mit Ergebnissen |
|
||
| `showHosters()` | Typisch | Gibt Hoster-Liste zurück (list of dicts + Funktionsname am Ende) |
|
||
| `getHosterUrl(sUrl)` | Typisch | Löst einen Hoster-Link zur Stream-URL auf |
|
||
|
||
**Beispiel (kinox.py, vereinfacht):**
|
||
```python
|
||
SITE_IDENTIFIER = 'kinox'
|
||
SITE_NAME = 'KinoX'
|
||
DOMAIN = 'ww22.kinoz.to'
|
||
|
||
def load(): # Hauptmenü: News, Filme, Serien, Dokumentationen, Suche
|
||
def showMovieMenu(): # Untermenü: Kino, A-Z, Genre, Beliebt, Neu
|
||
def showHosters(): # Gibt Liste der Hoster-Dicts + 'getHosterUrl' zurück
|
||
def getHosterUrl(): # Löst Hoster-URL auf, gibt {'streamUrl':..., 'resolved':...} zurück
|
||
def _search(oGui, sSearchText): # Globale Suche, befüllt oGui
|
||
```
|
||
|
||
---
|
||
|
||
### 3.4 Hoster-Auflösungsflow
|
||
|
||
```
|
||
User klickt auf Film/Episode
|
||
└─► xstream.py: parseUrl() erkennt 'playMode'
|
||
├── hosterSelect = 'Auto' → cHosterGui.streamAuto()
|
||
└── sonst → cHosterGui.stream()
|
||
|
||
cHosterGui.stream(playMode, siteName, function):
|
||
1. Site-Plugin laden, Hoster-Funktion aufrufen → Hoster-Liste
|
||
2. Hoster nach Priorität sortieren (__getPriorities)
|
||
→ resolveurl.HostedMediaFile(url=...).get_resolvers()
|
||
→ Priorität nach Resolver-Ranking + Qualität + Sprache
|
||
3. Auswahl:
|
||
├── hosterSelect = 'List' → Hoster als Ordner anzeigen (showHosterFolder)
|
||
├── Mehrere Hoster → Dialog zur Auswahl (_chooseHoster)
|
||
└── Genau ein Hoster → direkt weiter
|
||
4. getHosterUrl(hoster['link']) aufrufen → {'streamUrl': ..., 'resolved': bool}
|
||
5. cHosterGui.play / download / addToPlaylist / sendToJD / ...
|
||
|
||
cHosterGui.play(siteResult):
|
||
1. resolveurl.resolve(streamUrl) → direkter Stream-Link
|
||
2. xbmcgui.ListItem mit Link erstellen
|
||
3. m3u8/mpd → inputstream.adaptive aktivieren
|
||
4. xbmcplugin.setResolvedUrl(handle, True, listItem)
|
||
```
|
||
|
||
---
|
||
|
||
### 3.5 Globale Suche
|
||
|
||
```
|
||
searchGlobal(sSearchText):
|
||
1. cGui im collectMode = True (Ergebnisse werden im Speicher gesammelt)
|
||
2. ThreadPoolExecutor (max. 10 Workers):
|
||
→ alle aktivierten Plugins mit globalsearch != 'false'
|
||
→ plugin._search(oGui, sSearchText) parallel aufrufen
|
||
3. Fortschrittsdialog aktualisieren (0–50 %)
|
||
4. collectMode = False
|
||
5. Ergebnisse nach Site-Name sortiert als Listeneinträge hinzufügen (50–100 %)
|
||
|
||
searchAlter (Kontextmenü „Weitere Quellen"):
|
||
- Wie searchGlobal, aber mit Titel-Normalisierung (Jahr, Staffelkennung entfernen)
|
||
- Ergebnisse werden nach Titel, Jahr und IMDB-ID gefiltert
|
||
|
||
searchTMDB (aus TMDB-Kontext aufgerufen):
|
||
- Wie searchGlobal, ohne zusätzliche Filterung
|
||
```
|
||
|
||
---
|
||
|
||
## 4. HTTP-Request-Handler (`requestHandler.py`)
|
||
|
||
`cRequestHandler` ist der zentrale HTTP-Client des Plugins.
|
||
|
||
### Initialisierung (wichtige Parameter)
|
||
|
||
| Parameter | Standard | Bedeutung |
|
||
|---|---|---|
|
||
| `caching` | `True` | HTML-Cache aktivieren |
|
||
| `ignoreErrors` | `False` | HTTP-Fehler still ignorieren |
|
||
| `method` | `'GET'` | HTTP-Methode |
|
||
| `compression` | `True` | gzip/deflate anfordern |
|
||
| `bypass_dns` | `False` | DNS-over-HTTPS verwenden |
|
||
|
||
### Caching
|
||
|
||
Zwei Cache-Ebenen, konfigurierbar per Einstellung:
|
||
|
||
| Ebene | Speicherort | Aktivierung |
|
||
|---|---|---|
|
||
| Persistent | `{profile}/htmlcache/{md5(url)}` | Standard |
|
||
| Volatil (In-Memory) | `cCache` (Wörterbuch) | Einstellung `volatileHtmlCache = true` |
|
||
|
||
Cache-Lebensdauer: konfigurierbar, Standard 6 Stunden (360 min × 60 s).
|
||
|
||
### Anti-Bot-Mechanismen
|
||
|
||
| Schutzmechanismus | Erkennung | Behandlung |
|
||
|---|---|---|
|
||
| Cloudflare | `cloudflare` im Response-Header | Fehlermeldung an Nutzer, kein Retry |
|
||
| DDOS-Guard | `DDOS-GUARD` im Response-Body | Automatischer Cookie-Challenge via `check.ddos-guard.net` |
|
||
| Blazingfast | `lazingfast` im Response-Body | AES-Entschlüsselung via pyaes, Cookie-Setzung |
|
||
| DNS-Sperre (CUII) | Redirect zu `notice.cuii.info` | Fehlerdialog; Bypass via DoH (Cloudflare) wenn aktiviert |
|
||
|
||
### DNS-over-HTTPS (DoH)
|
||
|
||
Wenn `bypass_dns = True` und Einstellung `bypassDNSlock = true`:
|
||
→ DNS-Auflösung via `https://cloudflare-dns.com/dns-query` statt System-DNS
|
||
→ IP-Adresse wird direkt für TCP-Verbindung genutzt; SNI-Header enthält weiterhin den Hostnamen
|
||
→ IP-Ergebnis wird im volatilen Cache gespeichert
|
||
|
||
### Cookie-Verwaltung
|
||
|
||
Pro Domain wird eine eigene Cookie-Datei im LWP-Format gespeichert:
|
||
`{profile}/cookies/{domain_mit_unterstrichen}.txt`
|
||
|
||
---
|
||
|
||
## 5. Plugin-Handler (`pluginHandler.py`)
|
||
|
||
Verwaltet die Erkennung und den Zustand der Site-Plugins.
|
||
|
||
### PluginDB
|
||
|
||
Eine JSON-Datei unter `{profile}/pluginDB`. Sie enthält für jedes Site-Plugin:
|
||
|
||
```json
|
||
{
|
||
"kinox": {
|
||
"name": "KinoX",
|
||
"identifier": "kinox",
|
||
"icon": "kinox.png",
|
||
"domain": "ww22.kinoz.to",
|
||
"globalsearch": "true",
|
||
"modified": 1700000000.0
|
||
}
|
||
}
|
||
```
|
||
|
||
Die DB wird aktualisiert, wenn:
|
||
- Eine neue `.py`-Datei im `sites/`-Ordner gefunden wird
|
||
- Eine vorhandene Datei seit dem letzten Einlesen geändert wurde
|
||
- Die globale Sucheinstellung für ein Plugin geändert wurde
|
||
|
||
### Domain-Prüfung (`checkDomain`)
|
||
|
||
Wird beim Kodi-Start vom Service aufgerufen. Für jedes aktivierte Plugin:
|
||
1. HTTP-Request an `http://{domain}/`
|
||
2. Status-Code wird in der Einstellung `plugin_{id}_status` gespeichert
|
||
3. Bei Redirect (3xx): neue Domain aus dem `Location`-Header übernehmen
|
||
4. Bei 403–503: globale Suche für das Plugin deaktivieren
|
||
|
||
---
|
||
|
||
## 6. GUI-Schicht (`gui.py`, `guiElement.py`)
|
||
|
||
### `cGui`
|
||
|
||
Abstraktion über Kodis `xbmcplugin`-API. Wesentliche Konzepte:
|
||
|
||
**collectMode**: Wenn `True`, werden Listeneinträge nicht an Kodi gesendet, sondern in `self.searchResults` gesammelt. Wird für die globale Suche verwendet, damit alle Plugins ihre Ergebnisse in eine gemeinsame Liste schreiben können.
|
||
|
||
**TMDB-Metadaten**: Wenn die Einstellung `TMDBMETA = true`, wird für jeden Eintrag automatisch `guiElement.getMeta()` aufgerufen (via TMDB-API), bevor er angezeigt wird.
|
||
|
||
**Kontext-Menü-Einträge** (automatisch für alle Einträge):
|
||
- Trailer (wenn Addon `script.module.xstream.trailer` installiert)
|
||
- Erweiterte Info (TMDB-Infobox)
|
||
- Weitere Quellen (searchAlter)
|
||
- Playlist hinzufügen
|
||
- Download
|
||
- An JDownloader / JDownloader2 / My.JDownloader / pyLoad senden
|
||
- Manueller Hoster-Auswahldialog (wenn Auto-Modus aktiv)
|
||
|
||
### `cGuiElement`
|
||
|
||
Repräsentiert einen einzelnen Listeneintrag. Wesentliche Felder:
|
||
|
||
| Feld | Methode | Beschreibung |
|
||
|---|---|---|
|
||
| Titel | `setTitle` | Anzeigename |
|
||
| Site-Name | `setSiteName` | Zugehöriges Site-Plugin |
|
||
| Funktion | `setFunction` | Aufzurufende Funktion beim Klick |
|
||
| Thumbnail | `setThumbnail` | Vorschaubild-URL |
|
||
| Fanart | `setFanart` | Hintergrundbild-URL |
|
||
| Medientyp | `setMediaType` | `movie`, `tvshow`, `season`, `episode` |
|
||
| Sprache | `setLanguage` | Sprach-Code (z. B. `DE`, `EN`) |
|
||
| Qualität | `setQuality` | z. B. `1080p`, `720p` |
|
||
| Jahr | `setYear` | Erscheinungsjahr |
|
||
| Staffel/Episode | `setSeason`/`setEpisode` | Serieninformationen |
|
||
|
||
---
|
||
|
||
## 7. script.module.xstreamscraper
|
||
|
||
Das Scraper-Modul ist für den Fall gedacht, dass externe Tools (z. B. über Kodi-Addons, die TMDB-IDs kennen) einen Film oder eine Serie automatisch abspielen wollen, ohne durch das xStream-Menü navigieren zu müssen.
|
||
|
||
### Haupt-API: `scraper.play(_type, _id, season, episode)`
|
||
|
||
```
|
||
play("movie", "123456", None, None)
|
||
play("tv", "78910", "2", "5") # Staffel 2, Episode 5
|
||
```
|
||
|
||
**Ablauf:**
|
||
|
||
```
|
||
play(_type, _id, season, episode):
|
||
1. TMDB-API: Film-/Seriendaten laden (Name, Erscheinungsdatum, alternative Titel)
|
||
2. Optional: vavoo-Integration prüfen (direkter Stream ohne Scraping)
|
||
3. searchGlobal(name, searchtitles, isSerie, ...) aufrufen
|
||
→ alle aktivierten Site-Plugins parallel durchsuchen (ThreadPoolExecutor)
|
||
→ Ergebnisse filtern:
|
||
- Sprache muss Deutsch sein
|
||
- Medientyp muss passen (Film ≠ Serie)
|
||
- Bei Serien: Staffelnummer prüfen
|
||
- Jahresabgleich (±0 bei Filmen)
|
||
- Titelabgleich (normalisiert: Sonderzeichen entfernt)
|
||
4. get_hosters(sources, isSerie, season, episode) aufrufen
|
||
→ Bei Serien: get_episodes() navigiert zu korrekter Episode
|
||
→ site-plugin.getHosterUrl() für jeden Treffer
|
||
5. Jeden Hoster der Reihe nach testen:
|
||
→ resolveurl.resolve(streamUrl) aufrufen
|
||
→ HTTP-HEAD-Request prüfen (Content-Type muss Video sein)
|
||
→ Erster gültiger Link → _play(url)
|
||
6. _play(url):
|
||
→ xbmcgui.ListItem mit URL
|
||
→ m3u8 → inputstream.adaptive
|
||
→ xbmcplugin.setResolvedUrl()
|
||
```
|
||
|
||
### Unterschied zur manuellen Nutzung via plugin.video.xstream
|
||
|
||
| Aspekt | plugin.video.xstream | script.module.xstreamscraper |
|
||
|---|---|---|
|
||
| Einstieg | Nutzer-Navigation | TMDB-ID als Parameter |
|
||
| Hoster-Auswahl | Manuell oder nach Priorität | Vollautomatisch, erster funktionierender |
|
||
| Stream-Validierung | Keiner | HTTP-HEAD-Request vor Wiedergabe |
|
||
| Sprach-/Jahresfilter | Keine automatische Filterung | Automatisch (nur Deutsch, korrektes Jahr) |
|
||
| Zielgruppe | Endnutzer in Kodi-GUI | Andere Addons / Automatisierung |
|
||
|
||
---
|
||
|
||
## 8. Einstellungen (Auszug)
|
||
|
||
Alle Einstellungen befinden sich in `resources/settings.xml` und werden über `cConfig` gelesen.
|
||
|
||
| Einstellung | Bedeutung |
|
||
|---|---|
|
||
| `plugin_{id}` | Site-Plugin aktiviert (`true`/`false`) |
|
||
| `plugin_{id}.domain` | Überschreibt Standard-Domain des Plugins |
|
||
| `plugin_{id}_status` | Letzter HTTP-Status-Code der Domain |
|
||
| `plugin_{id}_checkdomain` | Domain-Prüfung für dieses Plugin aktiviert |
|
||
| `global_search_{id}` | Globale Suche für dieses Plugin aktiviert |
|
||
| `hosterSelect` | `Auto` (automatisch) oder `List` (manuelle Auswahl) |
|
||
| `cacheTime` | HTML-Cache-Lebensdauer in Minuten (Standard: 360) |
|
||
| `requestTimeout` | HTTP-Timeout in Sekunden (Standard: 10) |
|
||
| `volatileHtmlCache` | In-Memory-Cache aktivieren |
|
||
| `bypassDNSlock` | DNS-over-HTTPS für gesperrte Domains |
|
||
| `TMDBMETA` | TMDB-Metadaten für Listeneinträge laden |
|
||
| `metaOverwrite` | TMDB-Daten ersetzen statt ergänzen |
|
||
| `prefLanguage` | Bevorzugte Sprache (`1` = Deutsch, `2` = Englisch) |
|
||
| `preferedQuality` | Bevorzugte Videoqualität für Hoster-Sortierung |
|
||
| `presortHoster` | Hoster nach Resolver-Priorität vorsortieren |
|
||
| `maxHoster` | Maximale Anzahl Hoster in der Liste |
|
||
| `jd_enabled` / `jd2_enabled` / `myjd_enabled` / `pyload_enabled` | Download-Manager aktivieren |
|
||
| `githubUpdateResolver` | Resolver bei Kodi-Start aktualisieren |
|
||
| `cacheDeltaDay` | HTML-Cache alle N Tage beim Start löschen |
|
||
| `popup.update.notification` | Changelog-Popup beim Start anzeigen |
|
||
|
||
---
|
||
|
||
## 9. Abhängigkeiten
|
||
|
||
### plugin.video.xstream
|
||
|
||
| Addon | Pflicht | Zweck |
|
||
|---|---|---|
|
||
| `script.module.requests` | Ja | HTTP (via scraper-Modul) |
|
||
| `script.module.resolveurl` ≥ 5.1.173 | Ja | Hoster-Auflösung |
|
||
| `script.module.six` ≥ 1.11.0 | Ja | Python-2/3-Kompatibilität |
|
||
| `script.module.pyaes` | Ja | AES-Entschlüsselung (Blazingfast-Bypass) |
|
||
| `script.module.inputstreamhelper` ≥ 0.3.3 | Optional | HLS/DASH über inputstream.adaptive |
|
||
| `repository.resolveurl` | Optional | Resolver-Repository |
|
||
| `script.module.pydevd` / `script.module.web-pdb` | Optional | Debugging |
|
||
|
||
### script.module.xstreamscraper
|
||
|
||
Zusätzlich zu den obigen:
|
||
|
||
| Addon | Pflicht | Zweck |
|
||
|---|---|---|
|
||
| `plugin.video.xstream` | Ja | Nutzt dessen Site-Plugins direkt |
|
||
| `plugin.video.vavooto` | Ja | Vavoo-Stream-Integration |
|
||
|
||
---
|
||
|
||
## 10. Bekannte Einschränkungen
|
||
|
||
- **Cloudflare**: Seiten mit aktivem Cloudflare-Schutz werden nicht automatisch umgangen. Der Nutzer erhält eine Fehlermeldung.
|
||
- **Domain-Wechsel**: Wenn eine Streaming-Seite ihre Domain ändert, muss entweder der Kodi-Start abgewartet werden (Domain-Prüfung aktualisiert die Einstellung automatisch via Redirect-Erkennung) oder die Domain muss manuell in den xStream-Einstellungen angepasst werden.
|
||
- **Thread-Safety in Global Search**: Die Site-Plugins werden parallel in Threads ausgeführt. Plugins, die globalen Zustand modifizieren, können Race-Conditions verursachen.
|
||
- **scraper.py `plugin_` Funktion**: Der Scraper importiert Site-Plugins dynamisch und setzt `settings.urlparams` als globalen Zustand – dies ist nicht thread-sicher und kann bei paralleler Nutzung zu Problemen führen.
|
||
- **Kodi-Version**: Der Code enthält explizite Versionsprüfungen (`kodi_version[:2] < '20'` usw.). Unter Kodi 19 wird `setInfo` statt `getVideoInfoTag()` verwendet.
|