From 2395f1c0b779f45284c36f01d1a18ada9fb923f9 Mon Sep 17 00:00:00 2001 From: Paperclip Date: Wed, 26 Aug 2026 19:32:42 +0200 Subject: [PATCH] Use API All domains as search sources Co-Authored-By: Paperclip --- plugin.video.xstream/sites/api_all.py | 68 ++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/plugin.video.xstream/sites/api_all.py b/plugin.video.xstream/sites/api_all.py index d8a5a13..8fb9453 100644 --- a/plugin.video.xstream/sites/api_all.py +++ b/plugin.video.xstream/sites/api_all.py @@ -8,6 +8,7 @@ import re import xbmcgui +from concurrent.futures import ThreadPoolExecutor, as_completed from urllib.parse import urlparse from resources.lib.handler.ParameterHandler import ParameterHandler @@ -60,6 +61,42 @@ def _get_configured_domain(): return _get_default_domain() + +def _get_search_domains(): + domains = [] + configured = _get_configured_domain() + if configured: + domains.append(configured) + + for entry in API_ALL_DOMAINS: + domain = entry['domain'] + if domain not in domains: + domains.append(domain) + + return domains + + +def _fetch_movies_for_domain(domain, sLang): + oRequest = cRequestHandler( + 'https://' + domain + '/data/browse/?lang=%s&order_by=%s&page=%s&limit=0' % (sLang, 'new', '1'), + caching=True + ) + oRequest.addHeaderEntry('Referer', 'https://' + domain + '/') + oRequest.addHeaderEntry('Origin', 'https://' + domain + '/') + oRequest.cacheTime = 60 * 60 * 48 + sJson = oRequest.request() + aJson = loads(sJson) + movies = aJson.get('movies', []) + return movies if isinstance(movies, list) else [] + + +def _movie_signature(movie): + return ( + str(movie.get('_id', '')).strip(), + str(movie.get('title', '')).strip().lower(), + str(movie.get('year', '')).strip(), + ) + SITE_NAME = 'API Suchmaschine' SITE_ICON = 'api.png' SITE_IDENTIFIER = 'api_all' @@ -623,13 +660,30 @@ def loadMoviesData(): sLang = '3' try: - oRequest = cRequestHandler(URL_SEARCH % (sLang, 'new', '1'), caching=True) - oRequest.addHeaderEntry('Referer', REFERER) - oRequest.addHeaderEntry('Origin', ORIGIN) - oRequest.cacheTime = 60 * 60 * 48 # HTML Cache Zeit 2 Tage - sJson = oRequest.request() - apiJson = loads(sJson) - logger.info('API-Daten erfolgreich geladen') + merged_movies = {} + domains = _get_search_domains() + + with ThreadPoolExecutor(max_workers=min(8, len(domains) or 1)) as executor: + futures = { + executor.submit(_fetch_movies_for_domain, domain, sLang): domain + for domain in domains + } + + for future in as_completed(futures): + domain = futures[future] + try: + movies = future.result() + except Exception: + logger.info('API-Daten konnten von %s nicht geladen werden' % domain) + continue + + for movie in movies: + if not isinstance(movie, dict) or '_id' not in movie: + continue + merged_movies.setdefault(_movie_signature(movie), movie) + + apiJson = {'movies': list(merged_movies.values())} + logger.info('API-Daten erfolgreich aus %d Domains geladen' % len(domains)) except: logger.error('Fehler beim Laden der API-Daten') apiJson = {'movies': []}