# -*- coding: utf-8 -*- #from builtins import str import sys from core.support import typo PY3 = False if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int import xbmc, os, traceback from channelselector import get_thumb, thumb from core import filetools from core import scrapertools from core import videolibrarytools from core.item import Item from platformcode import config, logger from platformcode import platformtools from lib import generictools from distutils import dir_util def mainlist(item): logger.info() itemlist = list() itemlist.append(Item(channel=item.channel, action="list_movies", title=config.get_localized_string(60509), category=config.get_localized_string(70270), thumbnail=get_thumb("videolibrary_movie.png"))) itemlist.append(Item(channel=item.channel, action="list_tvshows", title=config.get_localized_string(60600), category=config.get_localized_string(70271), thumbnail=get_thumb("videolibrary_tvshow.png"))) itemlist.append(Item(channel='shortcuts', action="SettingOnPosition", category=2, setting=1, title=typo(config.get_localized_string(70287),'bold color kod'), thumbnail = get_thumb("setting_0.png"))) return itemlist def channel_config(item): return platformtools.show_channel_settings(channelpath=os.path.join(config.get_runtime_path(), "channels", item.channel), caption=config.get_localized_string(60598)) def list_movies(item, silent=False): logger.info() itemlist = [] dead_list = [] zombie_list = [] for raiz, subcarpetas, ficheros in filetools.walk(videolibrarytools.MOVIES_PATH): for s in subcarpetas: nfo_path = filetools.join(raiz, s, s + ".nfo") logger.debug(nfo_path) local_movie = False for f in filetools.listdir(filetools.join(raiz, s)): if f.split('.')[-1] not in ['nfo','json','strm']: local_movie = True break if filetools.exists(nfo_path): #Sincronizamos las películas vistas desde la videoteca de Kodi con la de Alfa try: if config.is_xbmc(): #Si es Kodi, lo hacemos from platformcode import xbmc_videolibrary xbmc_videolibrary.mark_content_as_watched_on_alfa(nfo_path) except: logger.error(traceback.format_exc()) head_nfo, new_item = videolibrarytools.read_nfo(nfo_path) if not new_item: #Si no ha leído bien el .nfo, pasamos a la siguiente logger.error('.nfo erroneo en ' + str(nfo_path)) continue if len(new_item.library_urls) > 1: multicanal = True else: multicanal = False ## verifica la existencia de los canales, en caso de no existir el canal se pregunta si se quieren ## eliminar los enlaces de dicho canal for canal_org in new_item.library_urls: canal = generictools.verify_channel(canal_org) try: if canal in ['community', 'downloads']: channel_verify = __import__('specials.%s' % canal, fromlist=["channels.%s" % canal]) else: channel_verify = __import__('channels.%s' % canal, fromlist=["channels.%s" % canal]) logger.debug('Channel %s seems correct' % channel_verify) except: dead_item = Item(multicanal=multicanal, contentType='movie', dead=canal, path=filetools.join(raiz, s), nfo=nfo_path, library_urls=new_item.library_urls, infoLabels={'title': new_item.contentTitle}) if canal not in dead_list and canal not in zombie_list: confirm = platformtools.dialog_yesno(config.get_localized_string(30131), config.get_localized_string(30132) % canal.upper(), config.get_localized_string(30133)) elif canal in zombie_list: confirm = False else: confirm = True if confirm: delete(dead_item) if canal not in dead_list: dead_list.append(canal) continue else: if canal not in zombie_list: zombie_list.append(canal) if len(dead_list) > 0: for canal in dead_list: if canal in new_item.library_urls: del new_item.library_urls[canal] new_item.nfo = nfo_path new_item.path = filetools.join(raiz, s) new_item.thumbnail = new_item.contentThumbnail new_item.extra = filetools.join(config.get_setting("videolibrarypath"), config.get_setting("folder_movies"), s) # new_item.text_color = "blue" strm_path = new_item.strm_path.replace("\\", "/").rstrip("/") if '/' in new_item.path: new_item.strm_path = strm_path logger.info('EXIST'+ str(local_movie)) if not filetools.exists(filetools.join(new_item.path, filetools.basename(strm_path))) and local_movie == False: # Si se ha eliminado el strm desde la bilbioteca de kodi, no mostrarlo continue # Menu contextual: Marcar como visto/no visto visto = new_item.library_playcounts.get(os.path.splitext(f)[0], 0) new_item.infoLabels["playcount"] = visto if visto > 0: texto_visto = config.get_localized_string(60016) contador = 0 else: texto_visto = config.get_localized_string(60017) contador = 1 # Menu contextual: Eliminar serie/canal num_canales = len(new_item.library_urls) if "downloads" in new_item.library_urls: num_canales -= 1 if num_canales > 1: texto_eliminar = config.get_localized_string(60018) else: texto_eliminar = config.get_localized_string(60019) new_item.context = [{"title": texto_visto, "action": "mark_content_as_watched", "channel": "videolibrary", "playcount": contador}, {"title": texto_eliminar, "action": "delete", "channel": "videolibrary", "multicanal": multicanal}] # ,{"title": "Cambiar contenido (PENDIENTE)", # "action": "", # "channel": "videolibrary"}] # logger.debug("new_item: " + new_item.tostring('\n')) itemlist.append(new_item) if silent == False: return sorted(itemlist, key=lambda it: it.title.lower()) else: return def list_tvshows(item): logger.info() itemlist = [] dead_list = [] zombie_list = [] # Obtenemos todos los tvshow.nfo de la videoteca de SERIES recursivamente for raiz, subcarpetas, ficheros in filetools.walk(videolibrarytools.TVSHOWS_PATH): for s in subcarpetas: tvshow_path = filetools.join(raiz, s, "tvshow.nfo") logger.debug(tvshow_path) if filetools.exists(tvshow_path): #Sincronizamos los episodios vistos desde la videoteca de Kodi con la de Alfa try: if config.is_xbmc(): #Si es Kodi, lo hacemos from platformcode import xbmc_videolibrary xbmc_videolibrary.mark_content_as_watched_on_alfa(tvshow_path) except: logger.error(traceback.format_exc()) head_nfo, item_tvshow = videolibrarytools.read_nfo(tvshow_path) if not item_tvshow: #Si no ha leído bien el .nfo, pasamos a la siguiente logger.error('.nfo erroneo en ' + str(tvshow_path)) continue if len(item_tvshow.library_urls) > 1: multicanal = True else: multicanal = False ## verifica la existencia de los canales, en caso de no existir el canal se pregunta si se quieren ## eliminar los enlaces de dicho canal for canal in item_tvshow.library_urls: canal = generictools.verify_channel(canal) try: if canal in ['community', 'downloads']: channel_verify = __import__('specials.%s' % canal, fromlist=["channels.%s" % canal]) else: channel_verify = __import__('channels.%s' % canal, fromlist=["channels.%s" % canal]) logger.debug('El canal %s parece correcto' % channel_verify) except: dead_item = Item(multicanal=multicanal, contentType='tvshow', dead=canal, path=filetools.join(raiz, s), nfo=tvshow_path, library_urls=item_tvshow.library_urls, infoLabels={'title': item_tvshow.contentTitle}) if canal not in dead_list and canal not in zombie_list: confirm = platformtools.dialog_yesno(config.get_localized_string(30131), config.get_localized_string(30132) % canal.upper(), config.get_localized_string(30133)) elif canal in zombie_list: confirm = False else: confirm = True if confirm: delete(dead_item) if canal not in dead_list: dead_list.append(canal) continue else: if canal not in zombie_list: zombie_list.append(canal) if len(dead_list) > 0: for canal in dead_list: if canal in item_tvshow.library_urls: del item_tvshow.library_urls[canal] ### continua la carga de los elementos de la videoteca try: #A veces da errores aleatorios, por no encontrar el .nfo. Probablemente problemas de timing item_tvshow.title = item_tvshow.contentTitle item_tvshow.path = filetools.join(raiz, s) item_tvshow.nfo = tvshow_path item_tvshow.extra = filetools.join(config.get_setting("videolibrarypath"), config.get_setting("folder_tvshows"), s) # Menu contextual: Marcar como visto/no visto visto = item_tvshow.library_playcounts.get(item_tvshow.contentTitle, 0) item_tvshow.infoLabels["playcount"] = visto if visto > 0: texto_visto = config.get_localized_string(60020) contador = 0 else: texto_visto = config.get_localized_string(60021) contador = 1 except: logger.error('Not find: ' + str(tvshow_path)) logger.error(traceback.format_exc()) continue # Menu contextual: Buscar automáticamente nuevos episodios o no if item_tvshow.active and int(item_tvshow.active) > 0: texto_update = config.get_localized_string(60022) value = 0 # item_tvshow.text_color = "green" else: texto_update = config.get_localized_string(60023) value = 1 # item_tvshow.text_color = "0xFFDF7401" # Menu contextual: Eliminar serie/canal num_canales = len(item_tvshow.library_urls) if "downloads" in item_tvshow.library_urls: num_canales -= 1 if num_canales > 1: texto_eliminar = config.get_localized_string(60024) else: texto_eliminar = config.get_localized_string(60025) item_tvshow.context = [{"title": texto_visto, "action": "mark_content_as_watched", "channel": "videolibrary", "playcount": contador}, {"title": texto_update, "action": "mark_tvshow_as_updatable", "channel": "videolibrary", "active": value}, {"title": texto_eliminar, "action": "delete", "channel": "videolibrary", "multicanal": multicanal}, {"title": config.get_localized_string(70269), "action": "update_tvshow", "channel": "videolibrary"}] # ,{"title": "Cambiar contenido (PENDIENTE)", # "action": "", # "channel": "videolibrary"}] # logger.debug("item_tvshow:\n" + item_tvshow.tostring('\n')) ## verifica la existencia de los canales ## if len(item_tvshow.library_urls) > 0: itemlist.append(item_tvshow) if itemlist: itemlist = sorted(itemlist, key=lambda it: it.title.lower()) itemlist.append(Item(channel=item.channel, action="update_videolibrary", thumbnail=item.thumbnail, title=config.get_localized_string(60026), folder=False)) return itemlist def get_seasons(item): logger.info() # logger.debug("item:\n" + item.tostring('\n')) itemlist = [] dict_temp = {} videolibrarytools.check_renumber_options(item) raiz, carpetas_series, ficheros = next(filetools.walk(item.path)) # Menu contextual: Releer tvshow.nfo head_nfo, item_nfo = videolibrarytools.read_nfo(item.nfo) if config.get_setting("no_pile_on_seasons", "videolibrary") == 2: # Siempre return get_episodes(item) for f in ficheros: if f.endswith('.json'): season = f.split('x')[0] dict_temp[season] = config.get_localized_string(60027) % season if config.get_setting("no_pile_on_seasons", "videolibrary") == 1 and len( dict_temp) == 1: # Sólo si hay una temporada return get_episodes(item) else: # TODO mostrar los episodios de la unica temporada "no vista", en vez de mostrar el Item "temporada X" previo # si está marcado "ocultar los vistos" en el skin, se ejecutaria esto # se comprueba cada temporada en dict_temp si está visto. # si hay una sola temporada y no_pile_on_seasons == 1, se devuelve get(episodios) # si está todo visto, hacemos como actualmente <-- el else no se hace nada.. CREO # if config.get_setting("no_pile_on_seasons", "videolibrary") == 1 and len(dict_temp_Visible) == 1: # Sólo si hay una temporada # Creamos un item por cada temporada for season, title in list(dict_temp.items()): new_item = item.clone(action="get_episodes", title=title, contentSeason=season, filtrar_season=True, channel='videolibrary') # Menu contextual: Marcar la temporada como vista o no visto = item_nfo.library_playcounts.get("season %s" % season, 0) new_item.infoLabels["playcount"] = visto if visto > 0: texto = config.get_localized_string(60028) value = 0 else: texto = config.get_localized_string(60029) value = 1 new_item.context = [{"title": texto, "action": "mark_season_as_watched", "channel": "videolibrary", "playcount": value}] # logger.debug("new_item:\n" + new_item.tostring('\n')) itemlist.append(new_item) if len(itemlist) > 1: itemlist = sorted(itemlist, key=lambda it: int(it.contentSeason)) if config.get_setting("show_all_seasons", "videolibrary"): new_item = item.clone(action="get_episodes", title=config.get_localized_string(60030)) new_item.infoLabels["playcount"] = 0 itemlist.insert(0, new_item) add_download_items(item, itemlist) return itemlist def get_episodes(item): logger.info() # logger.debug("item:\n" + item.tostring('\n')) itemlist = [] # Obtenemos los archivos de los episodios raiz, carpetas_series, ficheros = next(filetools.walk(item.path)) # Menu contextual: Releer tvshow.nfo head_nfo, item_nfo = videolibrarytools.read_nfo(item.nfo) # Crear un item en la lista para cada strm encontrado for i in ficheros: ext = i.split('.')[-1] if ext not in ['json','nfo']: #i.endswith('.strm'): season_episode = scrapertools.get_season_and_episode(i) if not season_episode: # El fichero no incluye el numero de temporada y episodio continue season, episode = season_episode.split("x") # Si hay q filtrar por temporada, ignoramos los capitulos de otras temporadas if item.filtrar_season and int(season) != int(item.contentSeason): continue # Obtener los datos del season_episode.nfo nfo_path = filetools.join(raiz, '%sx%s.nfo' % (season, episode))#.replace('.strm', '.nfo') if filetools.isfile(nfo_path): head_nfo, epi = videolibrarytools.read_nfo(nfo_path) # Fijar el titulo del capitulo si es posible if epi.contentTitle: title_episodie = epi.contentTitle.strip() else: title_episodie = config.get_localized_string(60031) % \ (epi.contentSeason, str(epi.contentEpisodeNumber).zfill(2)) epi.contentTitle = "%sx%s" % (epi.contentSeason, str(epi.contentEpisodeNumber).zfill(2)) epi.title = "%sx%s - %s" % (epi.contentSeason, str(epi.contentEpisodeNumber).zfill(2), title_episodie) if item_nfo.library_filter_show: epi.library_filter_show = item_nfo.library_filter_show # Menu contextual: Marcar episodio como visto o no visto = item_nfo.library_playcounts.get(season_episode, 0) epi.infoLabels["playcount"] = visto if visto > 0: texto = config.get_localized_string(60032) value = 0 else: texto = config.get_localized_string(60033) value = 1 epi.context = [{"title": texto, "action": "mark_content_as_watched", "channel": "videolibrary", "playcount": value, "nfo": item.nfo}] if ext != 'strm': epi.local = True itemlist.append(epi) itemlist = sorted(itemlist, key=lambda it: (int(it.contentSeason), int(it.contentEpisodeNumber))) add_download_items(item, itemlist) return itemlist def findvideos(item): from specials import autoplay logger.info() # logger.debug("item:\n" + item.tostring('\n')) videolibrarytools.check_renumber_options(item) itemlist = [] list_canales = {} item_local = None # Desactiva autoplay autoplay.set_status(False) if not item.contentTitle or not item.strm_path: logger.debug("Unable to search for videos due to lack of parameters") return [] #content_title = [c for c in item.contentTitle.strip().lower() if c not in ":*?<>|\/"] content_title = str(item.contentSeason) + 'x' + (str(item.contentEpisodeNumber) if item.contentEpisodeNumber > 9 \ else '0' + str(item.contentEpisodeNumber)) if item.contentType == 'movie': item.strm_path = filetools.join(videolibrarytools.MOVIES_PATH, item.strm_path) path_dir = filetools.dirname(item.strm_path) item.nfo = filetools.join(path_dir, filetools.basename(path_dir) + ".nfo") else: item.strm_path = filetools.join(videolibrarytools.TVSHOWS_PATH, item.strm_path) path_dir = filetools.dirname(item.strm_path) item.nfo = filetools.join(path_dir, 'tvshow.nfo') for fd in filetools.listdir(path_dir): if fd.endswith('.json'): contenido, nom_canal = fd[:-6].split('[') if (contenido.startswith(content_title) or item.contentType == 'movie') and nom_canal not in \ list(list_canales.keys()): list_canales[nom_canal] = filetools.join(path_dir, fd) num_canales = len(list_canales) if 'downloads' in list_canales: json_path = list_canales['downloads'] item_json = Item().fromjson(filetools.read(json_path)) ###### Redirección al canal NewPct1.py si es un clone, o a otro canal y url si ha intervención judicial try: if item_json: item_json, it, overwrite = generictools.redirect_clone_newpct1(item_json) except: logger.error(traceback.format_exc()) item_json.contentChannel = "local" # Soporte para rutas relativas en descargas if filetools.is_relative(item_json.url): item_json.url = filetools.join(videolibrarytools.VIDEOLIBRARY_PATH, item_json.url) del list_canales['downloads'] # Comprobar q el video no haya sido borrado if filetools.exists(item_json.url): item_local = item_json.clone(action='play') itemlist.append(item_local) else: num_canales -= 1 filtro_canal = '' if num_canales > 1 and config.get_setting("ask_channel", "videolibrary"): opciones = [config.get_localized_string(70089) % k.capitalize() for k in list(list_canales.keys())] opciones.insert(0, config.get_localized_string(70083)) if item_local: opciones.append(item_local.title) from platformcode import platformtools index = platformtools.dialog_select(config.get_localized_string(30163), opciones) if index < 0: return [] elif item_local and index == len(opciones) - 1: filtro_canal = 'downloads' platformtools.play_video(item_local) elif index > 0: filtro_canal = opciones[index].replace(config.get_localized_string(70078), "").strip() itemlist = [] for nom_canal, json_path in list(list_canales.items()): if filtro_canal and filtro_canal != nom_canal.capitalize(): continue item_canal = Item() item_canal.channel = nom_canal ###### Redirección al canal NewPct1.py si es un clone, o a otro canal y url si ha intervención judicial try: item_canal, it, overwrite = generictools.redirect_clone_newpct1(item_canal) except: logger.error(traceback.format_exc()) nom_canal = item_canal.channel # Importamos el canal de la parte seleccionada try: if nom_canal == 'community': channel = __import__('specials.%s' % nom_canal, fromlist=["channels.%s" % nom_canal]) else: channel = __import__('channels.%s' % nom_canal, fromlist=["channels.%s" % nom_canal]) except ImportError: exec("import channels." + nom_canal + " as channel") item_json = Item().fromjson(filetools.read(json_path)) ###### Redirección al canal NewPct1.py si es un clone, o a otro canal y url si ha intervención judicial try: if item_json: item_json, it, overwrite = generictools.redirect_clone_newpct1(item_json) except: logger.error(traceback.format_exc()) list_servers = [] try: # FILTERTOOLS # si el canal tiene filtro se le pasa el nombre que tiene guardado para que filtre correctamente. if "list_language" in item_json: # si se viene desde la videoteca del addon if "library_filter_show" in item: item_json.show = item.library_filter_show.get(nom_canal, "") # Ejecutamos find_videos, del canal o común item_json.contentChannel = 'videolibrary' if hasattr(channel, 'findvideos'): from core import servertools if item_json.videolibray_emergency_urls: del item_json.videolibray_emergency_urls list_servers = getattr(channel, 'findvideos')(item_json) list_servers = servertools.filter_servers(list_servers) elif item_json.action == 'play': from platformcode import platformtools autoplay.set_status(True) item_json.contentChannel = item_json.channel item_json.channel = "videolibrary" platformtools.play_video(item_json) return '' else: from core import servertools list_servers = servertools.find_video_items(item_json) except Exception as ex: logger.error("The findvideos function for the channel %s failed" % nom_canal) template = "An exception of type %s occured. Arguments:\n%r" message = template % (type(ex).__name__, ex.args) logger.error(message) logger.error(traceback.format_exc()) # Cambiarle el titulo a los servers añadiendoles el nombre del canal delante y # las infoLabels y las imagenes del item si el server no tiene for server in list_servers: #if not server.action: # Ignorar/PERMITIR las etiquetas # continue server.contentChannel = server.channel server.channel = "videolibrary" server.nfo = item.nfo server.strm_path = item.strm_path server.play_from = item.play_from #### Compatibilidad con Kodi 18: evita que se quede la ruedecedita dando vueltas en enlaces Directos if server.action == 'play': server.folder = False # Se añade el nombre del canal si se desea if config.get_setting("quit_channel_name", "videolibrary") == 0: server.title = "%s: %s" % (nom_canal.capitalize(), server.title) #server.infoLabels = item_json.infoLabels if not server.thumbnail: server.thumbnail = item.thumbnail # logger.debug("server:\n%s" % server.tostring('\n')) itemlist.append(server) # return sorted(itemlist, key=lambda it: it.title.lower()) autoplay.play_multi_channel(item, itemlist) from inspect import stack from specials import nextep if nextep.check(item) and stack()[1][3] == 'run': nextep.videolibrary(item) add_download_items(item, itemlist) return itemlist def play(item): logger.info() # logger.debug("item:\n" + item.tostring('\n')) if not item.contentChannel == "local": if item.contentChannel == 'community': channel = __import__('specials.%s' % item.contentChannel, fromlist=["channels.%s" % item.contentChannel]) else: channel = __import__('channels.%s' % item.contentChannel, fromlist=["channels.%s" % item.contentChannel]) if hasattr(channel, "play"): itemlist = getattr(channel, "play")(item) else: itemlist = [item.clone()] else: itemlist = [item.clone(url=item.url, server="local")] # Para enlaces directo en formato lista if isinstance(itemlist[0], list): item.video_urls = itemlist itemlist = [item] # Esto es necesario por si el play del canal elimina los datos for v in itemlist: if isinstance(v, Item): v.nfo = item.nfo v.strm_path = item.strm_path v.infoLabels = item.infoLabels if item.contentTitle: v.title = item.contentTitle else: if item.contentType == "episode": v.title = config.get_localized_string(60036) % item.contentEpisodeNumber v.thumbnail = item.thumbnail v.contentThumbnail = item.thumbnail v.contentChannel = item.contentChannel return itemlist def update_videolibrary(item): logger.info() # Actualizar las series activas sobreescribiendo import service service.check_for_update(overwrite=True) # Eliminar las carpetas de peliculas que no contengan archivo strm for raiz, subcarpetas, ficheros in filetools.walk(videolibrarytools.MOVIES_PATH): strm = False for f in ficheros: if f.endswith(".strm"): strm = True break if ficheros and not strm: logger.debug("Deleting deleted movie folder: %s" % raiz) filetools.rmdirtree(raiz) def move_videolibrary(current_path, new_path, current_movies_folder, new_movies_folder, current_tvshows_folder, new_tvshows_folder): logger.info() backup_current_path = current_path backup_new_path = new_path notify = False progress = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(80011)) current_path = xbmc.translatePath(current_path) new_path = xbmc.translatePath(new_path) current_movies_path = filetools.join(current_path, current_movies_folder) new_movies_path = filetools.join(new_path, new_movies_folder) current_tvshows_path = os.path.join(current_path, current_tvshows_folder) new_tvshows_path = os.path.join(new_path, new_tvshows_folder) from platformcode import xbmc_videolibrary movies_path, tvshows_path = xbmc_videolibrary.check_sources(new_movies_path, new_tvshows_path) if movies_path or tvshows_path: if not movies_path: filetools.rmdir(new_movies_path) if not tvshows_path: filetools.rmdir(new_tvshows_path) config.set_setting("videolibrarypath", backup_current_path) config.set_setting("folder_movies", current_movies_folder) config.set_setting("folder_tvshows", current_tvshows_folder) xbmc_videolibrary.update_sources(backup_current_path, backup_new_path) progress.update(100) xbmc.sleep(1000) progress.close() platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(80028)) return config.verify_directories_created() progress.update(10, config.get_localized_string(20000), config.get_localized_string(80012)) if current_movies_path != new_movies_path: if filetools.listdir(current_movies_path): dir_util.copy_tree(current_movies_path, new_movies_path) notify = True filetools.rmdirtree(current_movies_path) progress.update(40) if current_tvshows_path != new_tvshows_path: if filetools.listdir(current_tvshows_path): dir_util.copy_tree(current_tvshows_path, new_tvshows_path) notify = True filetools.rmdirtree(current_tvshows_path) progress.update(70) if current_path != new_path and not filetools.listdir(current_path) and not "plugin.video.kod\\videolibrary" in current_path: filetools.rmdirtree(current_path) xbmc_videolibrary.update_sources(backup_new_path, backup_current_path) if config.is_xbmc() and config.get_setting("videolibrary_kodi"): xbmc_videolibrary.update_db(backup_current_path, backup_new_path, current_movies_folder, new_movies_folder, current_tvshows_folder, new_tvshows_folder, progress) else: progress.update(100) xbmc.sleep(1000) progress.close() if notify: platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(80014), time=5000, sound=False) def delete_videolibrary(item): logger.info() if not platformtools.dialog_yesno(config.get_localized_string(20000), config.get_localized_string(80037)): return p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(80038)) p_dialog.update(0) filetools.rmdirtree(videolibrarytools.MOVIES_PATH) p_dialog.update(40) filetools.rmdirtree(videolibrarytools.TVSHOWS_PATH) p_dialog.update(80) if config.is_xbmc() and config.get_setting("videolibrary_kodi"): from platformcode import xbmc_videolibrary strm_list = [] strm_list.append(config.get_setting('videolibrarypath')) xbmc_videolibrary.clean(strm_list) p_dialog.update(90) config.verify_directories_created() p_dialog.update(100) xbmc.sleep(1000) p_dialog.close() platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(80039), time=5000, sound=False) # metodos de menu contextual def update_tvshow(item): logger.info() # logger.debug("item:\n" + item.tostring('\n')) heading = config.get_localized_string(60037) p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), heading) p_dialog.update(0, heading, item.contentSerieName) import service if service.update(item.path, p_dialog, 1, 1, item, False) and config.is_xbmc() and config.get_setting("videolibrary_kodi"): from platformcode import xbmc_videolibrary xbmc_videolibrary.update(folder=filetools.basename(item.path)) p_dialog.close() def verify_playcount_series(item, path): logger.info() """ Este método revisa y repara el PlayCount de una serie que se haya desincronizado de la lista real de episodios en su carpeta. Las entradas de episodios, temporadas o serie que falten, son creado con la marca de "no visto". Posteriormente se envia a verificar los contadores de Temporadas y Serie En el retorno envía de estado de True si se actualizado o False si no, normalmente por error. Con este estado, el caller puede actualizar el estado de la opción "verify_playcount" en "videolibrary.py". La intención de este método es la de dar una pasada que repare todos los errores y luego desactivarse. Se puede volver a activar en el menú de Videoteca de Alfa. """ #logger.debug("item:\n" + item.tostring('\n')) #Si no ha hecho nunca la verificación, lo forzamos estado = config.get_setting("verify_playcount", "videolibrary") if not estado or estado == False: estado = True #Si no ha hecho nunca la verificación, lo forzamos else: estado = False if item.contentType == 'movie': #Esto es solo para Series return (item, False) if filetools.exists(path): nfo_path = filetools.join(path, "tvshow.nfo") head_nfo, it = videolibrarytools.read_nfo(nfo_path) #Obtenemos el .nfo de la Serie if not hasattr(it, 'library_playcounts') or not it.library_playcounts: #Si el .nfo no tiene library_playcounts se lo creamos logger.error('** It does not have PlayCount') it.library_playcounts = {} # Obtenemos los archivos de los episodios raiz, carpetas_series, ficheros = next(filetools.walk(path)) # Crear un item en la lista para cada strm encontrado estado_update = False for i in ficheros: if i.endswith('.strm'): season_episode = scrapertools.get_season_and_episode(i) if not season_episode: # El fichero no incluye el numero de temporada y episodio continue season, episode = season_episode.split("x") if season_episode not in it.library_playcounts: #No está incluido el episodio it.library_playcounts.update({season_episode: 0}) #actualizamos el playCount del .nfo estado_update = True #Marcamos que hemos actualizado algo if 'season %s' % season not in it.library_playcounts: #No está incluida la Temporada it.library_playcounts.update({'season %s' % season: 0}) #actualizamos el playCount del .nfo estado_update = True #Marcamos que hemos actualizado algo if it.contentSerieName not in it.library_playcounts: #No está incluida la Serie it.library_playcounts.update({item.contentSerieName: 0}) #actualizamos el playCount del .nfo estado_update = True #Marcamos que hemos actualizado algo if estado_update: logger.error('** Estado de actualización: ' + str(estado) + ' / PlayCount: ' + str(it.library_playcounts)) estado = estado_update # se comprueba que si todos los episodios de una temporada están marcados, se marque tb la temporada for key, value in it.library_playcounts.items(): if key.startswith("season"): season = scrapertools.find_single_match(key, 'season (\d+)') #Obtenemos en núm. de Temporada it = check_season_playcount(it, season) # Guardamos los cambios en item.nfo if filetools.write(nfo_path, head_nfo + it.tojson()): return (it, estado) return (item, False) def mark_content_as_watched2(item): logger.info() # logger.debug("item:\n" + item.tostring('\n')) if filetools.exists(item.nfo): head_nfo, it = videolibrarytools.read_nfo(item.nfo) #logger.debug(it) name_file = "" if item.contentType == 'movie' or item.contentType == 'tvshow': name_file = os.path.splitext(filetools.basename(item.nfo))[0] if name_file != 'tvshow' : it.library_playcounts.update({name_file: item.playcount}) if item.contentType == 'episode' or item.contentType == 'tvshow' or item.contentType == 'list' or name_file == 'tvshow': # elif item.contentType == 'episode': name_file = os.path.splitext(filetools.basename(item.strm_path))[0] num_season = name_file [0] item.__setattr__('contentType', 'episode') item.__setattr__('contentSeason', num_season) #logger.debug(name_file) else: name_file = item.contentTitle # logger.debug(name_file) if not hasattr(it, 'library_playcounts'): it.library_playcounts = {} it.library_playcounts.update({name_file: item.playcount}) # se comprueba que si todos los episodios de una temporada están marcados, se marque tb la temporada if item.contentType != 'movie': it = check_season_playcount(it, item.contentSeason) #logger.debug(it) # Guardamos los cambios en item.nfo if filetools.write(item.nfo, head_nfo + it.tojson()): item.infoLabels['playcount'] = item.playcount #logger.debug(item.playcount) # if item.contentType == 'episodesss': # Actualizar toda la serie #new_item = item.clone(contentSeason=-1) #mark_season_as_watched(new_item) if config.is_xbmc(): from platformcode import xbmc_videolibrary xbmc_videolibrary.mark_content_as_watched_on_kodi(item , item.playcount) # logger.debug(item) platformtools.itemlist_refresh() def mark_content_as_watched(item): logger.info() #logger.debug("item:\n" + item.tostring('\n')) if filetools.exists(item.nfo): head_nfo, it = videolibrarytools.read_nfo(item.nfo) if item.contentType == 'movie': name_file = os.path.splitext(filetools.basename(item.nfo))[0] elif item.contentType == 'episode': name_file = "%sx%s" % (item.contentSeason, str(item.contentEpisodeNumber).zfill(2)) else: name_file = item.contentTitle if not hasattr(it, 'library_playcounts'): it.library_playcounts = {} it.library_playcounts.update({name_file: item.playcount}) # se comprueba que si todos los episodios de una temporada están marcados, se marque tb la temporada if item.contentType != 'movie': it = check_season_playcount(it, item.contentSeason) # Guardamos los cambios en item.nfo if filetools.write(item.nfo, head_nfo + it.tojson()): item.infoLabels['playcount'] = item.playcount if item.contentType == 'tvshow' and item.type != 'episode' : # Actualizar toda la serie new_item = item.clone(contentSeason=-1) mark_season_as_watched(new_item) if config.is_xbmc(): #and item.contentType == 'episode': from platformcode import xbmc_videolibrary xbmc_videolibrary.mark_content_as_watched_on_kodi(item, item.playcount) platformtools.itemlist_refresh() def mark_season_as_watched(item): logger.info() # logger.debug("item:\n" + item.tostring('\n')) # Obtener el diccionario de episodios marcados f = filetools.join(item.path, 'tvshow.nfo') head_nfo, it = videolibrarytools.read_nfo(f) if not hasattr(it, 'library_playcounts'): it.library_playcounts = {} # Obtenemos los archivos de los episodios raiz, carpetas_series, ficheros = next(filetools.walk(item.path)) # Marcamos cada uno de los episodios encontrados de esta temporada episodios_marcados = 0 for i in ficheros: if i.endswith(".strm"): season_episode = scrapertools.get_season_and_episode(i) if not season_episode: # El fichero no incluye el numero de temporada y episodio continue season, episode = season_episode.split("x") if int(item.contentSeason) == -1 or int(season) == int(item.contentSeason): name_file = os.path.splitext(filetools.basename(i))[0] it.library_playcounts[name_file] = item.playcount episodios_marcados += 1 if episodios_marcados: if int(item.contentSeason) == -1: # Añadimos todas las temporadas al diccionario item.library_playcounts for k in list(it.library_playcounts.keys()): if k.startswith("season"): it.library_playcounts[k] = item.playcount else: # Añadimos la temporada al diccionario item.library_playcounts it.library_playcounts["season %s" % item.contentSeason] = item.playcount # se comprueba que si todas las temporadas están vistas, se marque la serie como vista it = check_tvshow_playcount(it, item.contentSeason) # Guardamos los cambios en tvshow.nfo filetools.write(f, head_nfo + it.tojson()) item.infoLabels['playcount'] = item.playcount if config.is_xbmc(): # Actualizamos la BBDD de Kodi from platformcode import xbmc_videolibrary xbmc_videolibrary.mark_season_as_watched_on_kodi(item, item.playcount) platformtools.itemlist_refresh() def mark_tvshow_as_updatable(item): logger.info() head_nfo, it = videolibrarytools.read_nfo(item.nfo) it.active = item.active filetools.write(item.nfo, head_nfo + it.tojson()) platformtools.itemlist_refresh() def delete(item): def delete_all(_item): for file in filetools.listdir(_item.path): if file.endswith(".strm") or file.endswith(".nfo") or file.endswith(".json")or file.endswith(".torrent"): filetools.remove(filetools.join(_item.path, file)) raiz, carpeta_serie, ficheros = next(filetools.walk(_item.path)) if ficheros == []: filetools.rmdir(_item.path) else: if _item.contentType == 'movie': heading = config.get_localized_string(70084) else: heading = config.get_localized_string(70085) if platformtools.dialog_yesno(heading, config.get_localized_string(70081)): filetools.rmdirtree(_item.path) if config.is_xbmc() and config.get_setting("videolibrary_kodi"): from platformcode import xbmc_videolibrary strm_list = [] strm_list.append(_item.extra) xbmc_videolibrary.clean(strm_list) logger.info("All links removed") xbmc.sleep(1000) platformtools.itemlist_refresh() # logger.info(item.contentTitle) # logger.debug(item.tostring('\n')) if item.contentType == 'movie': heading = config.get_localized_string(70084) else: heading = config.get_localized_string(70085) if item.multicanal: # Obtener listado de canales if item.dead == '': opciones = [] channels = [] for k in list(item.library_urls.keys()): if k != "downloads": opciones.append(config.get_localized_string(70086) % k.capitalize()) channels.append(k) opciones.insert(0, heading) index = platformtools.dialog_select(config.get_localized_string(30163), opciones) if index == 0: # Seleccionado Eliminar pelicula/serie canal = None delete_all(item) elif index > 0: # Seleccionado Eliminar canal X canal = opciones[index].replace(config.get_localized_string(70079), "").lower() channels.remove(canal) else: return else: canal = item.dead if canal: num_enlaces = 0 strm_list = [] for fd in filetools.listdir(item.path): if fd.endswith(canal + '].json') or scrapertools.find_single_match(fd, '%s]_\d+.torrent' % canal): if filetools.remove(filetools.join(item.path, fd)): num_enlaces += 1 # Remove strm and nfo if no other channel episode = fd.replace(' [' + canal + '].json', '') found_ch = False for ch in channels: if filetools.exists(filetools.join(item.path, episode + ' [' + ch + '].json')): found_ch = True break if found_ch == False: filetools.remove(filetools.join(item.path, episode + '.nfo')) filetools.remove(filetools.join(item.path, episode + '.strm')) strm_list.append(filetools.join(item.extra, episode + '.strm')) if config.is_xbmc() and config.get_setting("videolibrary_kodi") and strm_list: from platformcode import xbmc_videolibrary xbmc_videolibrary.clean(strm_list) if num_enlaces > 0: # Actualizar .nfo head_nfo, item_nfo = videolibrarytools.read_nfo(item.nfo) del item_nfo.library_urls[canal] if item_nfo.emergency_urls and item_nfo.emergency_urls.get(canal, False): del item_nfo.emergency_urls[canal] filetools.write(item.nfo, head_nfo + item_nfo.tojson()) msg_txt = config.get_localized_string(70087) % (num_enlaces, canal) logger.info(msg_txt) platformtools.dialog_notification(heading, msg_txt) platformtools.itemlist_refresh() else: if platformtools.dialog_yesno(heading, config.get_localized_string(70088) % item.infoLabels['title']): delete_all(item) def check_season_playcount(item, season): logger.info() if season: episodios_temporada = 0 episodios_vistos_temporada = 0 for key, value in item.library_playcounts.items(): if key.startswith("%sx" % season): episodios_temporada += 1 if value > 0: episodios_vistos_temporada += 1 if episodios_temporada == episodios_vistos_temporada: # se comprueba que si todas las temporadas están vistas, se marque la serie como vista item.library_playcounts.update({"season %s" % season: 1}) else: # se comprueba que si todas las temporadas están vistas, se marque la serie como vista item.library_playcounts.update({"season %s" % season: 0}) return check_tvshow_playcount(item, season) def check_tvshow_playcount(item, season): logger.info() if season: temporadas_serie = 0 temporadas_vistas_serie = 0 for key, value in item.library_playcounts.items(): #if key.startswith("season %s" % season): if key.startswith("season" ): temporadas_serie += 1 if value > 0: temporadas_vistas_serie += 1 #logger.debug(temporadas_serie) if temporadas_serie == temporadas_vistas_serie: item.library_playcounts.update({item.title: 1}) else: item.library_playcounts.update({item.title: 0}) else: playcount = item.library_playcounts.get(item.title, 0) item.library_playcounts.update({item.title: playcount}) return item def add_download_items(item, itemlist): if config.get_setting('downloadenabled'): localOnly = True for i in itemlist: if i.contentChannel != 'local': localOnly = False break if not item.fromLibrary and not localOnly: downloadItem = Item(channel='downloads', from_channel=item.channel, title=typo(config.get_localized_string(60355), "color kod bold"), fulltitle=item.fulltitle, show=item.fulltitle, contentType=item.contentType, contentSerieName=item.contentSerieName, url=item.url, action='save_download', from_action="findvideos", contentTitle=item.contentTitle, path=item.path, thumbnail=thumb(thumb='downloads.png'), parent=item.tourl()) if item.action == 'findvideos': if item.contentType == 'episode': downloadItem.title = typo(config.get_localized_string(60356), "color kod bold") else: # film downloadItem.title = typo(config.get_localized_string(60354), "color kod bold") downloadItem.downloadItemlist = [i.tourl() for i in itemlist] itemlist.append(downloadItem) else: if item.contentSeason: # season downloadItem.title = typo(config.get_localized_string(60357), "color kod bold") itemlist.append(downloadItem) else: # tvshow + not seen itemlist.append(downloadItem) itemlist.append(downloadItem.clone(title=typo(config.get_localized_string(60003), "color kod bold"), unseen=True))