diff --git a/.gitignore b/.gitignore index e43b0f9..9f2e848 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .DS_Store +__pycache__/ diff --git a/galdPl.py b/galdPl.py index 38f1e9a..0652c2e 100644 --- a/galdPl.py +++ b/galdPl.py @@ -6,6 +6,7 @@ import io import os import sys +import time import xbmc import xbmcgui import xbmcplugin @@ -667,58 +668,82 @@ def mojedb(params): try: import urllib.request import re - + def get_json_files_from_folder(folder): base_url = "https://git.gald.site/gald/galdistream/src/branch/main/resources/" url = base_url + folder - + req = urllib.request.Request(url) req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36') - + with urllib.request.urlopen(req, timeout=10) as response: html_content = response.read().decode('utf-8') - + json_pattern = r'href="(/gald/galdistream/src/branch/main/resources/[^"]*\.json)"' matches = re.findall(json_pattern, html_content) - + files = [] for match in matches: file_name = match.split("/")[-1] files.append(file_name) return files - + base_url_raw = "https://git.gald.site/gald/galdistream/raw/branch/main/resources/" folders = ["movies", "series"] all_files = [] - + for folder in folders: try: files = get_json_files_from_folder(folder) all_files += [f"{folder}/{file}" for file in files] except Exception as e: xbmc.log(f"Chyba při získávání souborů ze složky {folder}: {e}", xbmc.LOGERROR) - + + downloads = 0 for file in all_files: url = base_url_raw + file local_path = os.path.join(_addon.getAddonInfo('path'), 'resources', file) try: req = urllib.request.Request(url) req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36') - + with urllib.request.urlopen(req, timeout=10) as response: content = response.read() - + os.makedirs(os.path.dirname(local_path), exist_ok=True) with open(local_path, "wb") as f: f.write(content) + downloads += 1 xbmc.log(f"Staženo: {file}", xbmc.LOGDEBUG) except Exception as e: xbmc.log(f"Chyba při stahování {file}: {e}", xbmc.LOGERROR) + + xbmc.log(f"Debug: Stažených JSON souborů: {downloads}", xbmc.LOGDEBUG) + return True except Exception as e: xbmc.log(f"Chyba při stahování JSON souborů: {e}", xbmc.LOGERROR) - - # Stáhni aktuální JSON soubory z GITu - update_json_db() + return False + + def should_update_json_db(max_age_hours=12): + try: + last_sync = float(_addon.getSetting('json_db_last_sync') or 0) + except ValueError: + last_sync = 0 + + if last_sync <= 0: + return True + + age_seconds = time.time() - last_sync + return age_seconds >= max_age_hours * 3600 + + # Stáhni aktuální JSON soubory z GITu pouze pokud je to nutné + if should_update_json_db(): + if update_json_db(): + _addon.setSetting('json_db_last_sync', str(int(time.time()))) + else: + xbmc.log("Debug: Aktualizace JSON databáze selhala", xbmc.LOGDEBUG) + else: + xbmc.log("Debug: Přeskakuji aktualizaci JSON databáze, používám cache", xbmc.LOGDEBUG) xbmcplugin.setPluginCategory(_handle, _addon.getAddonInfo('name') + " \\ " + _addon.getLocalizedString(30220)) token = revalidate() @@ -752,6 +777,8 @@ def mojedb(params): except Exception as e: xbmc.log(f"Debug: Chyba při načítání složky {series_dir}: {str(e)}", xbmc.LOGDEBUG) + series_files.sort(key=lambda name: name.lower()) + xbmc.log(f"Debug: Nalezeno {len(series_files)} JSON souborů seriálů", xbmc.LOGDEBUG) for file in series_files: xbmc.log(f"Debug: Seriál soubor: {file}", xbmc.LOGDEBUG) @@ -772,6 +799,8 @@ def mojedb(params): except Exception as e: xbmc.log(f"Debug: Chyba při načítání složky {movies_dir}: {str(e)}", xbmc.LOGDEBUG) + movies_files.sort(key=lambda name: name.lower()) + xbmc.log(f"Debug: Nalezeno {len(movies_files)} JSON souborů filmů", xbmc.LOGDEBUG) for file in movies_files: try: @@ -785,6 +814,8 @@ def mojedb(params): except Exception as e: xbmc.log(f"Chyba při načítání filmového souboru {file}: {str(e)}", xbmc.LOGERROR) + movies_collections.sort(key=lambda item: (item['data'].get('title') or item['file']).lower()) + except Exception as e: xbmc.log(f"Chyba při načítání databáze: {str(e)}", xbmc.LOGERROR) popinfo(f"Chyba při načítání databáze: {str(e)}", icon=xbmcgui.NOTIFICATION_ERROR, sound=True) @@ -804,37 +835,44 @@ def mojedb(params): # Výpis seriálů elif params.get('type') == 'series' and not params.get('series_idx'): + xbmcplugin.setContent(_handle, 'tvshows') xbmc.log(f"Debug: Zobrazuji seriály, nalezeno {len(series_files)} souborů", xbmc.LOGDEBUG) + series_entries = [] for idx, file in enumerate(series_files): try: xbmc.log(f"Debug: Načítám seriál: {file}", xbmc.LOGDEBUG) - # Načti data seriálu z JSON souboru series_path = xbmcvfs.translatePath(os.path.join(_addon.getAddonInfo('path'), 'resources', 'series', file)) xbmc.log(f"Debug: Cesta k souboru: {series_path}", xbmc.LOGDEBUG) with xbmcvfs.File(series_path, 'r') as f: content = f.read() xbmc.log(f"Debug: Přečteno {len(content)} znaků", xbmc.LOGDEBUG) serie_data = json.loads(content) - - # Vytvoř název seriálu z názvu souboru + series_name = file.replace('.json', '').replace('-', ' ').title() if 'title' in serie_data: series_name = serie_data['title'] - - xbmc.log(f"Debug: Vytvářím položku pro seriál: {series_name}", xbmc.LOGDEBUG) - # Použijeme číselný index místo názvu souboru - url = get_url(action='mojedb', type='series', series_idx=idx) - xbmc.log(f"Debug: URL pro seriál: {url}", xbmc.LOGDEBUG) - listitem = xbmcgui.ListItem(label=series_name) - listitem.setArt({'icon': serie_data.get('icon', 'DefaultTVShows.png')}) - xbmcplugin.addDirectoryItem(_handle, url, listitem, True) - xbmc.log(f"Debug: Přidána položka pro seriál: {series_name}", xbmc.LOGDEBUG) + + series_entries.append({ + 'index': idx, + 'name': series_name, + 'icon': serie_data.get('icon') or 'DefaultTVShows.png' + }) + xbmc.log(f"Debug: Připravená položka pro seriál: {series_name}", xbmc.LOGDEBUG) except Exception as e: xbmc.log(f"Chyba při načítání seriálu {file}: {str(e)}", xbmc.LOGERROR) popinfo(f"Chyba při načítání seriálu {file}: {str(e)}", icon=xbmcgui.NOTIFICATION_ERROR) + series_entries.sort(key=lambda item: item['name'].lower()) + for entry in series_entries: + url = get_url(action='mojedb', type='series', series_idx=entry['index']) + listitem = xbmcgui.ListItem(label=entry['name']) + listitem.setArt({'icon': entry['icon']}) + xbmcplugin.addDirectoryItem(_handle, url, listitem, True) + xbmc.log(f"Debug: Přidána položka pro seriál: {entry['name']}", xbmc.LOGDEBUG) + # Výpis sezón daného seriálu elif params.get('type') == 'series' and params.get('series_idx') is not None and not params.get('season_idx'): + xbmcplugin.setContent(_handle, 'seasons') try: series_idx = int(params['series_idx']) series_file = series_files[series_idx] @@ -844,17 +882,25 @@ def mojedb(params): with xbmcvfs.File(series_path, 'r') as f: content = f.read() serie_data = json.loads(content) - - for idx, season in enumerate(serie_data.get('seasons', [])): - label = f"{serie_data['title']} - Sezóna {season['season']}" + + series_title = serie_data.get('title') or series_file.replace('.json', '').replace('-', ' ').title() + series_icon = serie_data.get('icon') or 'DefaultTVShows.png' + + seasons_with_index = list(enumerate(serie_data.get('seasons', []))) + sorted_seasons = sorted(seasons_with_index, key=lambda item: item[1].get('season', item[0])) + + for original_idx, season in sorted_seasons: + season_number = season.get('season', original_idx + 1) + label = f"{series_title} - Sezóna {season_number}" listitem = xbmcgui.ListItem(label=label) - listitem.setArt({'icon': serie_data.get('icon', 'DefaultTVShows.png')}) - xbmcplugin.addDirectoryItem(_handle, get_url(action='mojedb', type='series', series_idx=series_idx, season_idx=idx), listitem, True) + listitem.setArt({'icon': series_icon}) + xbmcplugin.addDirectoryItem(_handle, get_url(action='mojedb', type='series', series_idx=series_idx, season_idx=original_idx), listitem, True) except Exception as e: popinfo(f"Chyba při zpracování sezón: {str(e)}", icon=xbmcgui.NOTIFICATION_ERROR, sound=True) # Výpis epizod dané sezóny elif params.get('type') == 'series' and params.get('series_idx') is not None and params.get('season_idx') is not None and not params.get('episode_idx'): + xbmcplugin.setContent(_handle, 'episodes') xbmc.log("Debug: Zpracovávám seznam epizod", xbmc.LOGDEBUG) try: series_idx = int(params['series_idx']) @@ -866,15 +912,21 @@ def mojedb(params): with xbmcvfs.File(series_path, 'r') as f: content = f.read() serie_data = json.loads(content) - + season = serie_data['seasons'][season_idx] - xbmc.log(f"Debug: Sezóna {season['season']}, {len(season.get('episodes', []))} epizod", xbmc.LOGDEBUG) - popinfo(f"Debug: Sezóna {season['season']}, {len(season.get('episodes', []))} epizod") - for idx, episode in enumerate(season.get('episodes', [])): - listitem = xbmcgui.ListItem(label=episode['title']) - listitem.setArt({'icon': serie_data.get('icon', 'DefaultTVShows.png')}) - xbmcplugin.addDirectoryItem(_handle, get_url(action='mojedb', type='series', series_idx=series_idx, season_idx=params['season_idx'], episode_idx=idx), listitem, True) - popinfo(f"Debug: Přidáno {len(season.get('episodes', []))} epizod") + series_icon = serie_data.get('icon') or 'DefaultTVShows.png' + season_number = season.get('season', season_idx + 1) + episodes_with_index = list(enumerate(season.get('episodes', []))) + episode_count = len(episodes_with_index) + xbmc.log(f"Debug: Sezóna {season_number}, {episode_count} epizod", xbmc.LOGDEBUG) + sorted_episodes = sorted(episodes_with_index, key=lambda item: (item[1].get('title') or '').lower()) + + for original_idx, episode in sorted_episodes: + episode_title = episode.get('title') or f"Epizoda {original_idx + 1}" + listitem = xbmcgui.ListItem(label=episode_title) + listitem.setArt({'icon': series_icon}) + xbmcplugin.addDirectoryItem(_handle, get_url(action='mojedb', type='series', series_idx=series_idx, season_idx=params['season_idx'], episode_idx=original_idx), listitem, True) + xbmc.log(f"Debug: Přidáno {episode_count} epizod", xbmc.LOGDEBUG) except Exception as e: xbmc.log(f"Chyba při zpracování epizod: {str(e)}", xbmc.LOGERROR) popinfo(f"Chyba při zpracování epizod: {str(e)}", icon=xbmcgui.NOTIFICATION_ERROR, sound=True) @@ -935,28 +987,34 @@ def mojedb(params): # Přehled filmových kolekcí elif params.get('type') == 'movies' and params.get('collection_idx') is None and params.get('movie_idx') is None: + xbmcplugin.setContent(_handle, 'videos') xbmc.log(f"Debug: Zobrazuji filmové kolekce, nalezeno {len(movies_collections)} souborů", xbmc.LOGDEBUG) for idx, collection in enumerate(movies_collections): data = collection['data'] title = data.get('title') or collection['file'].replace('.json', '').replace('-', ' ').title() xbmc.log(f"Debug: Přidávám kolekci filmů: {title}", xbmc.LOGDEBUG) listitem = xbmcgui.ListItem(label=title) - listitem.setArt({'icon': data.get('icon', 'DefaultMovies.png')}) + listitem.setArt({'icon': data.get('icon') or 'DefaultMovies.png'}) xbmcplugin.addDirectoryItem(_handle, get_url(action='mojedb', type='movies', collection_idx=idx), listitem, True) # Výpis filmů v kolekci elif params.get('type') == 'movies' and params.get('collection_idx') is not None and params.get('movie_idx') is None: + xbmcplugin.setContent(_handle, 'movies') try: collection_idx = int(params['collection_idx']) collection = movies_collections[collection_idx] movies = collection['data'].get('movies', []) xbmc.log(f"Debug: Zobrazuji filmy v kolekci {collection['file']} (počet {len(movies)})", xbmc.LOGDEBUG) - for idx, movie in enumerate(movies): - listitem = xbmcgui.ListItem(label=movie.get('title', f'Film {idx + 1}')) - listitem.setArt({'icon': movie.get('icon', 'DefaultMovies.png')}) + movies_with_index = list(enumerate(movies)) + sorted_movies = sorted(movies_with_index, key=lambda item: (item[1].get('title') or f'Film {item[0] + 1}').lower()) + + for original_idx, movie in sorted_movies: + movie_title = movie.get('title') or f'Film {original_idx + 1}' + listitem = xbmcgui.ListItem(label=movie_title) + listitem.setArt({'icon': movie.get('icon') or 'DefaultMovies.png'}) xbmcplugin.addDirectoryItem( _handle, - get_url(action='mojedb', type='movies', collection_idx=collection_idx, movie_idx=idx), + get_url(action='mojedb', type='movies', collection_idx=collection_idx, movie_idx=original_idx), listitem, True ) diff --git a/resources/movies/fantasy.json b/resources/movies/fantasy.json index c9af7f3..6109614 100644 --- a/resources/movies/fantasy.json +++ b/resources/movies/fantasy.json @@ -1,9 +1,13 @@ { - "title": "Top 5 fantasy filmy", + "title": "Fantasy filmy", "icon": "DefaultMovies.png", "movies": [ { "title": "Pán prstenů: Společenstvo prstenu", "icon": "DefaultMovies.png", "search": "pan prstenu spolecenstvo prstenu cz" }, + { "title": "Pán prstenů: Dvě věže", "icon": "DefaultMovies.png", "search": "pan prstenu dve veze cz" }, { "title": "Pán prstenů: Návrat krále", "icon": "DefaultMovies.png", "search": "pan prstenu navrat krale cz" }, + { "title": "Hobit: Neočekávaná cesta", "icon": "DefaultMovies.png", "search": "hobit neocekavana cesta cz" }, + { "title": "Hobit: Šmakova dračí poušť", "icon": "DefaultMovies.png", "search": "hobit smakova draci poust cz" }, + { "title": "Hobit: Bitva pěti armád", "icon": "DefaultMovies.png", "search": "hobit bitva peti armad cz" }, { "title": "Letopisy Narnie: Lev, čarodějnice a skříň", "icon": "DefaultMovies.png", "search": "letopisy narnie lev carodejnice a skrin cz" }, { "title": "Faunův labyrint", "icon": "DefaultMovies.png", "search": "faunuv labyrint cz" }, { "title": "Princezna nevěsta", "icon": "DefaultMovies.png", "search": "princezna nevesta cz" } diff --git a/resources/movies/pohadky.json b/resources/movies/pohadky.json new file mode 100644 index 0000000..50fc392 --- /dev/null +++ b/resources/movies/pohadky.json @@ -0,0 +1,32 @@ +{ + "title": "Pohádky a rodinné filmy", + "icon": "DefaultMovies.png", + "movies": [ + { "title": "Asterix a Obelix proti Caesarovi", "icon": "DefaultMovies.png", "search": "asterix a obelix proti cezarovi cz" }, + { "title": "Asterix a Obelix: Mise Kleopatra", "icon": "DefaultMovies.png", "search": "asterix a obelix mise kleopatra cz" }, + { "title": "Asterix a Obelix: Olympijské hry", "icon": "DefaultMovies.png", "search": "asterix a obelix olympijske hry cz" }, + { "title": "Asterix a Obelix ve službách jejího veličenstva", "icon": "DefaultMovies.png", "search": "asterix a obelix ve sluzbach jejiho velicenstva cz" }, + { "title": "Asterix a Obelix: Říše středu", "icon": "DefaultMovies.png", "search": "asterix a obelix rise stredu cz" }, + { "title": "Asterix: Sídliště bohů", "icon": "DefaultMovies.png", "search": "asterix sidliste bohu cz" }, + { "title": "Asterix: Tajemství kouzelného lektvaru", "icon": "DefaultMovies.png", "search": "asterix tajemstvi kouzelneho lektvaru cz" }, + { "title": "Asterix dobývá Ameriku", "icon": "DefaultMovies.png", "search": "asterix dobyva ameriku cz" }, + { "title": "Asterix a Vikingové", "icon": "DefaultMovies.png", "search": "asterix a vikingove cz" }, + { "title": "Doba ledová", "icon": "DefaultMovies.png", "search": "doba ledova 1 cz" }, + { "title": "Doba ledová 2: Obleva", "icon": "DefaultMovies.png", "search": "doba ledova 2 obleva cz" }, + { "title": "Doba ledová 3: Úsvit dinosaurů", "icon": "DefaultMovies.png", "search": "doba ledova 3 usvit dinosauru cz" }, + { "title": "Doba ledová 4: Země v pohybu", "icon": "DefaultMovies.png", "search": "doba ledova 4 zeme v pohybu cz" }, + { "title": "Doba ledová: Mamutí drcnutí", "icon": "DefaultMovies.png", "search": "doba ledova mamuti drcnuti cz" }, + { "title": "Madagaskar", "icon": "DefaultMovies.png", "search": "madagaskar 1 cz" }, + { "title": "Madagaskar 2: Útěk do Afriky", "icon": "DefaultMovies.png", "search": "madagaskar 2 utek do afriky cz" }, + { "title": "Madagaskar 3: Evropské šílenství", "icon": "DefaultMovies.png", "search": "madagaskar 3 evropske silenstvi cz" }, + { "title": "Tučňáci z Madagaskaru", "icon": "DefaultMovies.png", "search": "tucnaci z madagaskaru film cz" }, + { "title": "Tři oříšky pro Popelku", "icon": "DefaultMovies.png", "search": "tri orisky pro popelku cz" }, + { "title": "Pyšná princezna", "icon": "DefaultMovies.png", "search": "pysna princezna cz" }, + { "title": "S čerty nejsou žerty", "icon": "DefaultMovies.png", "search": "s certy nejsou zerty cz" }, + { "title": "Anděl Páně", "icon": "DefaultMovies.png", "search": "andel pane cz" }, + { "title": "Anděl Páně 2", "icon": "DefaultMovies.png", "search": "andel pane 2 cz" }, + { "title": "Princezna ze mlejna", "icon": "DefaultMovies.png", "search": "princezna ze mlejna cz" }, + { "title": "Princezna se zlatou hvězdou", "icon": "DefaultMovies.png", "search": "princezna se zlatou hvezdou cz" }, + { "title": "Ať žijí duchové!", "icon": "DefaultMovies.png", "search": "at ziji duchove cz" } + ] +}