diff --git a/core/videolibrarytools.py b/core/videolibrarytools.py index 736ced36..096cb755 100644 --- a/core/videolibrarytools.py +++ b/core/videolibrarytools.py @@ -192,7 +192,7 @@ def save_movie(item, silent=False): headers = {} if item.headers: headers = item.headers - channel = generictools.verify_channel(item.channel) + channel = item.channel if config.get_setting("emergency_urls", channel) in [1, 3]: item = emergency_urls(item, None, json_path, headers=headers) if item_nfo.emergency_urls and not isinstance(item_nfo.emergency_urls, dict): @@ -602,12 +602,12 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True): p_dialog = platformtools.dialog_progress(config.get_localized_string(20000), config.get_localized_string(60064)) p_dialog.update(0, config.get_localized_string(60065)) - channel_alt = generictools.verify_channel(serie.channel) # We prepare to add the emergency urls + channel_alt = serie.channels # We prepare to add the emergency urls emergency_urls_stat = config.get_setting("emergency_urls", channel_alt) # Does the channel want emergency urls? emergency_urls_succ = False try: channel = __import__('specials.%s' % channel_alt, fromlist=["specials.%s" % channel_alt]) except: channel = __import__('channels.%s' % channel_alt, fromlist=["channels.%s" % channel_alt]) - if serie.torrent_caching_fail: # If the conversion process has failed, they are not cached + if serie.torrent_caching_fail: # If the conversion process has failed, they are not cached emergency_urls_stat = 0 del serie.torrent_caching_fail @@ -1066,7 +1066,7 @@ def emergency_urls(item, channel=None, path=None, headers={}): # we launched a "lookup" in the "findvideos" of the channel to obtain the emergency links try: if channel == None: # If the caller has not provided the channel structure, it is created - channel = generictools.verify_channel(item.channel) # It is verified if it is a clone, which returns "newpct1" + channel = item.channel # It is verified if it is a clone, which returns "newpct1" #channel = __import__('channels.%s' % channel, fromlist=["channels.%s" % channel]) channel = __import__('specials.%s' % channel_alt, fromlist=["specials.%s" % channel_alt]) if hasattr(channel, 'findvideos'): # If the channel has "findvideos" ... @@ -1099,7 +1099,7 @@ def emergency_urls(item, channel=None, path=None, headers={}): try: referer = None post = None - channel_bis = generictools.verify_channel(item.channel) + channel_bis =item.channel if config.get_setting("emergency_urls_torrents", channel_bis) and item_res.emergency_urls and path != None: videolibrary_path = config.get_videolibrary_path() # we detect the absolute path of the title movies = config.get_setting("folder_movies") diff --git a/lib/generictools.py b/lib/generictools.py index ada6f0d9..ffe77898 100644 --- a/lib/generictools.py +++ b/lib/generictools.py @@ -257,7 +257,7 @@ def post_tmdb_listado(item, itemlist): from lib import generictools item, itemlist = generictools.post_tmdb_listado (item, itemlist) """ - #logger.debug(item) + # logger.debug(item) # We delete values ​​if there has been a fail-over channel_alt = '' @@ -273,9 +273,9 @@ def post_tmdb_listado(item, itemlist): for item_local in itemlist: # We go through the Itemlist generated by the channel item_local.title = re.sub(r'(?i)online|descarga|downloads|trailer|videoteca|gb|autoplay', '', item_local.title).strip() - #item_local.title = re.sub(r'online|descarga|downloads|trailer|videoteca|gb|autoplay', '', item_local.title, flags=re.IGNORECASE).strip() + # item_local.title = re.sub(r'online|descarga|downloads|trailer|videoteca|gb|autoplay', '', item_local.title, flags=re.IGNORECASE).strip() title = item_local.title - #logger.debug(item_local) + # logger.debug(item_local) item_local.last_page = 0 del item_local.last_page # We delete traces of pagination @@ -297,7 +297,7 @@ def post_tmdb_listado(item, itemlist): # We adjust the category name if item_local.channel == channel_py: - item_local.category = scrapertools.find_single_match(item_local.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() + item_local.category = scrapertools.find_single_match(item_local.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() # We restore the additional info saved in the title_subs list, and delete it from Item title_add = ' ' @@ -336,7 +336,7 @@ def post_tmdb_listado(item, itemlist): # If it brought the TMDB-ID, but it did not work, we reset it and tried again if item_local.infoLabels['tmdb_id'] and not item_local.infoLabels['originaltitle']: - logger.error("*** TMDB-ID erroneo, reseteamos y reintentamos ***") + logger.error("*** Wrong TMDB-ID, reset and retry ***") logger.error(item_local) del item_local.infoLabels['tmdb_id'] # you can bring a wrong TMDB-ID try: @@ -404,14 +404,14 @@ def post_tmdb_listado(item, itemlist): if not item_local.contentSeason or not item_local.contentEpisodeNumber: if "Episodio" in title_add: - item_local.contentSeason, item_local.contentEpisodeNumber = scrapertools.find_single_match(title_add, 'Episodio (\d+)x(\d+)') + item_local.contentSeason, item_local.contentEpisodeNumber = scrapertools.find_single_match(title_add, r'Episodio (\d+)x(\d+)') title = '%s [%s] [%s]' % (title, item_local.infoLabels['year'], rating) elif item_local.contentType == "season": if not item_local.contentSeason: - item_local.contentSeason = scrapertools.find_single_match(item_local.url, '-(\d+)x') + item_local.contentSeason = scrapertools.find_single_match(item_local.url, r'-(\d+)x') if not item_local.contentSeason: - item_local.contentSeason = scrapertools.find_single_match(item_local.url, '-temporadas?-(\d+)') + item_local.contentSeason = scrapertools.find_single_match(item_local.url, r'-temporadas?-(\d+)') if item_local.contentSeason: title = '%s -Temporada %s' % (title, str(item_local.contentSeason)) if not item_local.contentSeason_save: # We restore the num. seasonal @@ -455,7 +455,7 @@ def post_tmdb_listado(item, itemlist): item_local.contentTitle += ' -%s-' % item_local.channel.capitalize() elif "Episodio " in title: if not item_local.contentSeason or not item_local.contentEpisodeNumber: - item_local.contentSeason, item_local.contentEpisodeNumber = scrapertools.find_single_match(title_add, 'Episodio (\d+)x(\d+)') + item_local.contentSeason, item_local.contentEpisodeNumber = scrapertools.find_single_match(title_add, r'Episodio (\d+)x(\d+)') item_local.title = title @@ -689,7 +689,7 @@ def post_tmdb_episodios(item, itemlist): # We adjust the category name if item.channel == channel_py: - item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() + item.category = scrapertools.find_single_match(item.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() # We restore values ​​if there has been a fail-over channel_alt = '' @@ -804,14 +804,14 @@ def post_tmdb_episodios(item, itemlist): if item_local.infoLabels['number_of_seasons']: # If the season num is out of control, it gets 0, and itemlist is reclassified if item_local.contentSeason > item_local.infoLabels['number_of_seasons'] + 1: - logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(item_local.contentSeason) + " / " + str(item_local.contentEpisodeNumber) + " / MAX_TEMPORADAS: " + str(item_local.infoLabels['number_of_seasons']) + " / LISTA_TEMPORADAS: " + str(num_episodios_lista)) + logger.error("ERROR 07: EPISODES: Season number out of range " + " / SEASON: " + str(item_local.contentSeason) + " / " + str(item_local.contentEpisodeNumber) + " / MAX_SEASONS: " + str(item_local.infoLabels['number_of_seasons']) + " / SEASON_LIST: " + str(num_episodios_lista)) item_local.contentSeason = 0 itemlist = sorted(itemlist, key=lambda it: (int(it.contentSeason), int(it.contentEpisodeNumber))) else: num_temporada_max = item_local.infoLabels['number_of_seasons'] else: if item_local.contentSeason > num_temporada_max + 1: - logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(item_local.contentSeason) + " / " + str(item_local.contentEpisodeNumber) + " / MAX_TEMPORADAS: " + str(num_temporada_max) + " / LISTA_TEMPORADAS: " + str(num_episodios_lista)) + logger.error("ERROR 07: EPISODES: Season number out of range " + " / SEASON: " + str(item_local.contentSeason) + " / " + str(item_local.contentEpisodeNumber) + " / MAX_SEASONS: " + str(num_temporada_max) + " / SEASON_LIST: " + str(num_episodios_lista)) item_local.contentSeason = 0 itemlist = sorted(itemlist, key=lambda it: (int(it.contentSeason), int(it.contentEpisodeNumber))) @@ -904,7 +904,7 @@ def post_tmdb_episodios(item, itemlist): # If you are updating video library of a NewPct1 series, we restore the channel with the name of the clone if item.channel == channel_py and (item.library_playcounts or item.add_videolibrary): - item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.channel = scrapertools.find_single_match(item.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') # After reviewing each episode, we close with the footer # First we update all episodes with their maximum number of episodes per season @@ -913,11 +913,11 @@ def post_tmdb_episodios(item, itemlist): for item_local in itemlist: item_local.infoLabels['temporada_num_episodios'] = int(num_episodios_lista[item_local.contentSeason]) except: - logger.error("ERROR 07: EPISODIOS: Num de Temporada fuera de rango " + " / TEMPORADA: " + str(item_local.contentSeason) + " / " + str(item_local.contentEpisodeNumber) + " / MAX_TEMPORADAS: " + str(num_temporada_max) + " / LISTA_TEMPORADAS: " + str(num_episodios_lista)) + logger.error("ERROR 07: EPISODES: Season number out of range" + " / SEASON: " + str(item_local.contentSeason) + " / " + str(item_local.contentEpisodeNumber) + " / MAX_SEASONS: " + str(num_temporada_max) + " / SEASON_LIST: " + str(num_episodios_lista)) logger.error(traceback.format_exc()) # We allow the updating of titles, either for immediate use, or to add to the video library - itemlist.append(item.clone(title="** [COLOR yelow]Actualizar Títulos - vista previa videoteca[/COLOR] **", action="actualizar_titulos", tmdb_stat=False, from_action=item.action, from_title_tmdb=item.title, from_update=True)) + itemlist.append(item.clone(title="** Update Titles - video library preview **", action="actualizar_titulos", tmdb_stat=False, from_action=item.action, from_title_tmdb=item.title, from_update=True)) # Delete num. Season if you do not come from the Add to Video Library menu and you are not updating the Video Library if not item.library_playcounts: # if you are not updating the Video Library @@ -952,34 +952,34 @@ def post_tmdb_episodios(item, itemlist): itemlist_fake = [] # An empty Itemlist is created to update only the .nfo videolibrarytools.save_tvshow(item, itemlist_fake) # The .nfo is updated except: - logger.error("ERROR 08: EPISODIOS: No se ha podido actualizar la URL a la nueva Temporada") + logger.error("ERROR 08: EPISODES: Unable to update the URL to the new Season") logger.error(traceback.format_exc()) - itemlist.append(item.clone(title="[COLOR yellow]Añadir esta Serie a Videoteca-[/COLOR]" + title, action="add_serie_to_library")) + itemlist.append(item.clone(title="[COLOR yellow]Add this Series to Video Library-[/COLOR]" + title, action="add_serie_to_library")) elif modo_serie_temp == 1: # if it is Series we give the option to save the last season or the complete series - itemlist.append(item.clone(title="[COLOR yellow]Añadir última Temp. a Videoteca-[/COLOR]" + title, action="add_serie_to_library", contentType="season", contentSeason=contentSeason, url=item_local.url, add_menu=True)) - itemlist.append(item.clone(title="[COLOR yellow]Añadir esta Serie a Videoteca-[/COLOR]" + title, action="add_serie_to_library", contentType="tvshow", add_menu=True)) + itemlist.append(item.clone(title="[COLOR yellow]Add last Temp. to Video Library-[/COLOR]" + title, action="add_serie_to_library", contentType="season", contentSeason=contentSeason, url=item_local.url, add_menu=True)) + itemlist.append(item.clone(title="[COLOR yellow]Add this Series to Video Library-[/COLOR]" + title, action="add_serie_to_library", contentType="tvshow", add_menu=True)) else: # if not, we give the option to save the current season or the complete series - itemlist.append(item.clone(title="[COLOR yellow]Añadir esta Serie a Videoteca-[/COLOR]" + title, action="add_serie_to_library", contentType="tvshow", add_menu=True)) + itemlist.append(item.clone(title="[COLOR yellow]Add this Series to Video Library-[/COLOR]" + title, action="add_serie_to_library", contentType="tvshow", add_menu=True)) if item.add_videolibrary and not item.add_menu: item.contentSeason = contentSeason - itemlist.append(item.clone(title="[COLOR yellow]Añadir esta Temp. a Videoteca-[/COLOR]" + title, action="add_serie_to_library", contentType="season", contentSeason=contentSeason, add_menu=True)) + itemlist.append(item.clone(title="[COLOR yellow]Aadd this Temp. to Video Library-[/COLOR]" + title, action="add_serie_to_library", contentType="season", contentSeason=contentSeason, add_menu=True)) else: # It is a standard channel, just a line of Add to Video Library - itemlist.append(item.clone(title="[COLOR yellow]Añadir esta serie a videoteca-[/COLOR]" + title, action="add_serie_to_library", extra="episodios", add_menu=True)) + itemlist.append(item.clone(title="[COLOR yellow]Add this series to video library-[/COLOR]" + title, action="add_serie_to_library", extra="episodios", add_menu=True)) # If judicial intervention, I warn !!! if item.intervencion: for clone_inter, autoridad in item.intervencion: thumb_intervenido = get_thumb(autoridad) - itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + clone_inter.capitalize() + ': [/COLOR]' + intervenido_judicial + '. Reportar el problema en el foro', thumbnail=thumb_intervenido)) + itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + clone_inter.capitalize() + ': [/COLOR]' + intervenido_judicial + '. Report the problem in the forum', thumbnail=thumb_intervenido)) del item.intervencion # If there has been a fail-over, I will comment if channel_alt: - itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + channel_alt.capitalize() + '[/COLOR] [ALT ] en uso')) - itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + item.category.capitalize() + '[/COLOR] inaccesible')) + itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + channel_alt.capitalize() + '[/COLOR] [ALT ] In use')) + itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + item.category.capitalize() + '[/COLOR] Inaccessible')) if len(itemlist_fo) > 0: itemlist = itemlist_fo + itemlist @@ -1064,7 +1064,7 @@ def post_tmdb_findvideos(item, itemlist): item.category = category if item.armagedon: #Es una situación catastrófica? - itemlist.append(item.clone(action='', title=item.category + ': [COLOR hotpink]Usando enlaces de emergencia[/COLOR]')) + itemlist.append(item.clone(action='', title=item.category + ': [COLOR hotpink]Using emergency links[/COLOR]')) # We remove the category or title name, if you have it if item.contentTitle: @@ -1128,7 +1128,7 @@ def post_tmdb_findvideos(item, itemlist): tiempo_final = tiempo_final / 60 # I transform it into minutes horas = tiempo_final / 60 # I transform it into hours resto = tiempo_final - (horas * 60) # I keep the remaining minutes of the hour - if not scrapertools.find_single_match(item.quality, '(\[\d+:\d+)'): # if it already has the duration, we pass + if not scrapertools.find_single_match(item.quality, r'(\[\d+:\d+)'): # if it already has the duration, we pass item.quality += ' [/COLOR][COLOR white][%s:%s h]' % (str(horas).zfill(2), str(resto).zfill(2)) # I add it to Server Quality except: logger.error(traceback.format_exc()) @@ -1214,195 +1214,18 @@ def post_tmdb_findvideos(item, itemlist): return (item, itemlist) -def get_torrent_size(url, referer=None, post=None, torrents_path=None, data_torrent=False, \ - timeout=5, file_list=False, lookup=True, local_torr=None, headers={}, short_pad=False): - logger.info() - from servers import torrent - - """ - - Module extracted from the old ZenTorrent channel - - Calculate the size of files containing a .torrent. Download the .torrent file in a folder, - read and decode it. If it contains multiple files, add the size of all of them - - Call: generictools.get_torrent_size (url, data_torrent = False) - Entry: url: url of the .torrent file - Entry: referer: url of referer in case of call with post - Entry: post: content of the post in case of call with post - Entry: data_torrent: Flag in case you want the contents of the .torretn back - Output: size: str with the size and type of measurement (MB, GB, etc) - Output: torrent_f: dict () with the content of the .torrent (optional) - Output: files: dict () with the names of the torrent files and their size (optional) - - """ - - def convert_size(size): - import math - if (size == 0): - return '0B' - size_name = ("B", "KB", "M·B", "G·B", "TB", "PB", "EB", "ZB", "YB") - i = int(math.floor(math.log(size, 1024))) - p = math.pow(1024, i) - #s = round(size / p, 2) - s = round(old_div(size, p), 2) - return '%s %s' % (s, size_name[i]) - - def decode(text): - try: - src = tokenize(text) - if not PY3: - data = decode_item(src.next, src.next()) #Py2 - else: - data = decode_item(src.__next__, next(src)) #Py3 - for token in src: # look for more tokens - raise SyntaxError("trailing junk") - except (AttributeError, ValueError, StopIteration): - try: - data = data - except: - data = src - - return data - - def tokenize(text, match=re.compile("([idel])|(\d+):|(-?\d+)").match): - i = 0 - while i < len(text): - m = match(text, i) - s = m.group(m.lastindex) - i = m.end() - if m.lastindex == 2: - yield "s" - yield text[i:i + int(s)] - i = i + int(s) - else: - yield s - - def decode_item(next, token): - if token == "i": - # integer: "i" value "e" - data = int(next()) - if next() != "e": - raise ValueError - elif token == "s": - # string: "s" value (virtual tokens) - data = next() - elif token == "l" or token == "d": - # container: "l" (or "d") values "e" - data = [] - tok = next() - while tok != "e": - data.append(decode_item(next, tok)) - tok = next() - if token == "d": - #data = dict(zip(data[0::2], data[1::2])) - data = dict(list(zip(data[0::2], data[1::2]))) - else: - raise ValueError - return data - - - #Móludo principal - size = '' - torrent_f = '' - torrent_file = '' - files = {} - try: - #torrents_path = config.get_videolibrary_path() + '/torrents' #path para dejar el .torrent - - #if not os.path.exists(torrents_path): - # os.mkdir(torrents_path) #si no está la carpeta la creamos - - #urllib.URLopener.version = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0' - #urllib.urlretrieve(url, torrents_path + "/generictools.torrent") #desacargamos el .torrent a la carpeta - #torrent_file = open(torrents_path + "/generictools.torrent", "rb").read() #leemos el .torrent - - if ((url and not local_torr) or url.startswith('magnet')): - torrents_path, torrent_file = torrent.caching_torrents(url, \ - referer=referer, post=post, torrents_path=torrents_path, \ - timeout=timeout, lookup=lookup, data_torrent=True, headers=headers) - elif local_torr: - torrent_file = filetools.read(local_torr) - if not torrent_file: - if not lookup: - return (size, torrents_path, torrent_f, files) - elif file_list and data_torrent: - return (size, torrent_f, files) - elif file_list: - return (size, files) - elif data_torrent: - return (size, torrent_f) - return size #Si hay un error, devolvemos el "size" y "torrent" vacíos - - torrent_f = decode(torrent_file) #decodificamos el .torrent - - #si sólo tiene un archivo, tomamos la longitud y la convertimos a una unidad legible, si no dará error - try: - sizet = torrent_f["info"]['length'] - size = convert_size(sizet) - - files = torrent_f["info"].copy() - if 'path' not in files: files.update({'path': ['']}) - if 'piece length' in files: del files['piece length'] - if 'pieces' in files: del files['pieces'] - if 'name' in files: del files['name'] - files = [files] - files.append({"__name": torrent_f["info"]["name"], 'length': 0}) - except: - pass - - #si tiene múltiples archivos sumamos la longitud de todos - if not size: - try: - check_video = scrapertools.find_multiple_matches(str(torrent_f["info"]["files"]), "'length': (\d+).*?}") - sizet = sum([int(i) for i in check_video]) - size = convert_size(sizet) - - files = torrent_f["info"]["files"][:] - files.append({"__name": torrent_f["info"]["name"], 'length': 0}) - - except: - size = 'ERROR' - - except: - size = 'ERROR' - logger.error('ERROR al buscar el tamaño de un .Torrent: ' + str(url)) - logger.error(traceback.format_exc()) - - #try: - # os.remove(torrents_path + "/generictools.torrent") #borramos el .torrent - #except: - # pass - - if '.rar' in str(files): - size = '[COLOR magenta][B]RAR-[/B][/COLOR]%s' % size - - #logger.debug(str(url)) - logger.info(str(size)) - - if not lookup: - return (size, torrents_path, torrent_f, files) - elif file_list and data_torrent: - return (size, torrent_f, files) - elif file_list: - return (size, files) - elif data_torrent: - return (size, torrent_f) - return size - - def get_field_from_kodi_DB(item, from_fields='*', files='file'): logger.info() """ - Llamada para leer de la DB de Kodi los campos que se reciben de entrada (from_fields, por defecto "*") del vídeo señalado en Item - Obviamente esto solo funciona con Kodi y si la película o serie está catalogada en las Videotecas de Alfa y Kodi - Se puede pedir que la búdqueda se haga por archivos (defecto), o por carpeta (series) + Call to read from the Kodi DB the input fields received (from_fields, by default "*") of the video indicated in Item + Obviously this only works with Kodi and if the movie or series is listed in the Alpha and Kodi Video Libraries. + You can request that the search be done by files (default), or by folder (series) - La llamada es: - nun_records, records = generictools.get_field_from_kodi_DB(item, from_fields='cXX[, cYY,...]'[, files = 'file|folder']) + The call is: + nun_records, records = generictools.get_field_from_kodi_DB (item, from_fields = 'cXX [, cYY, ...]' [, files = 'file | folder']) - Devuelve el num de registros encontrados y los registros. Es importante que el llamador verifique que "nun_records > 0" antes de tratar "records" + Returns the num of records found and the records. It is important for the caller to verify that "nun_records> 0" before processing "records" """ @@ -1411,7 +1234,7 @@ def get_field_from_kodi_DB(item, from_fields='*', files='file'): VIDEOLIBRARY_PATH = config.get_videolibrary_config_path() VIDEOLIBRARY_REAL_PATH = config.get_videolibrary_path() - if item.contentType == 'movie': #Agrego la carpeta correspondiente al path de la Videoteca + if item.contentType == 'movie': # I add the folder corresponding to the path of the Video Library path = filetools.join(VIDEOLIBRARY_REAL_PATH, FOLDER_MOVIES) path2 = filetools.join(VIDEOLIBRARY_PATH, FOLDER_MOVIES) folder = FOLDER_MOVIES @@ -1420,49 +1243,49 @@ def get_field_from_kodi_DB(item, from_fields='*', files='file'): path2 = filetools.join(VIDEOLIBRARY_PATH, FOLDER_TVSHOWS) folder = FOLDER_TVSHOWS - raiz, carpetas, ficheros = filetools.walk(path).next() #listo las series o películas en la Videoteca - carpetas = [filetools.join(path, f) for f in carpetas] #agrego la carpeta del contenido al path - for carpeta in carpetas: #busco el contenido seleccionado en la lista de carpetas - if item.contentType == 'movie' and (item.contentTitle.lower() in carpeta or item.contentTitle in carpeta): #Películas? - path = carpeta #Almacenamos la carpeta en el path + raiz, carpetas, ficheros = filetools.walk(path).next() # ready the series or movies in the Video Library + carpetas = [filetools.join(path, f) for f in carpetas] # I add the content folder to the path + for carpeta in carpetas: # I search the selected content in the folder list + if item.contentType == 'movie' and (item.contentTitle.lower() in carpeta or item.contentTitle in carpeta): # Films? + path = carpeta # We store the folder in the path break - elif item.contentType in ['tvshow', 'season', 'episode'] and (item.contentSerieName.lower() in carpeta or item.contentSerieName in carpeta): #Series? + elif item.contentType in ['tvshow', 'season', 'episode'] and (item.contentSerieName.lower() in carpeta or item.contentSerieName in carpeta): # Series? path = carpeta #Almacenamos la carpeta en el path break - path2 += '/%s/' % scrapertools.find_single_match(path, '%s.(.*?\s\[.*?\])' % folder) #Agregamos la carpeta de la Serie o Películas, formato Android - file_search = '%' #Por defecto busca todos los archivos de la carpeta - if files == 'file': #Si se ha pedido son un archivo (defecto), se busca - if item.contentType == 'episode': #Si es episodio, se pone el nombre, si no de deja % - file_search = '%sx%s.strm' % (item.contentSeason, str(item.contentEpisodeNumber).zfill(2)) #Nombre para episodios + path2 += '/%s/' % scrapertools.find_single_match(path, r'%s.(.*?\s\[.*?\])' % folder) # We add the Series or Movies folder, Android format + file_search = '%' # By default it looks for all the files in the folder + if files == 'file': # If a file is requested (default), it is searched + if item.contentType == 'episode': # If it is an episode, put the name, if not leave% + file_search = '%sx%s.strm' % (item.contentSeason, str(item.contentEpisodeNumber).zfill(2)) # Name for episodes - if "\\" in path: #Ajustamos los / en función de la plataforma + if "\\" in path: # We adjust the / depending on the platform path = path.replace("/", "\\") - path += "\\" #Terminamos el path con un / + path += "\\" # We end the path with a / else: path += "/" - if FOLDER_TVSHOWS in path: #Compruebo si es CINE o SERIE - contentType = "episode_view" #Marco la tabla de BBDD de Kodi Video + if FOLDER_TVSHOWS in path: # I check if it is CINEMA or SERIES + contentType = "episode_view" # I mark the Kodi Video BBDD table else: - contentType = "movie_view" #Marco la tabla de BBDD de Kodi Video - path1 = path.replace("\\\\", "\\") #para la SQL solo necesito la carpeta - path2 = path2.replace("\\", "/") #Formato no Windows + contentType = "movie_view" # I mark the Kodi Video BBDD table + path1 = path.replace("\\\\", "\\") # for SQL I just need the folder + path2 = path2.replace("\\", "/") # Format no Windows - #Ejecutmos la sentencia SQL + # Let's execute the SQL statement if not from_fields: from_fields = '*' else: - from_fields = 'strFileName, %s' % from_fields #al menos dos campos, porque uno solo genera cosas raras + from_fields = 'strFileName, %s' % from_fields # at least two fields, because one only generates strange things sql = 'select %s from %s where (strPath like "%s" or strPath like "%s") and strFileName like "%s"' % (from_fields, contentType, path1, path2, file_search) nun_records = 0 records = None try: if config.is_xbmc(): from platformcode import xbmc_videolibrary - nun_records, records = xbmc_videolibrary.execute_sql_kodi(sql) #ejecución de la SQL - if nun_records == 0: #hay error? - logger.error("Error en la SQL: " + sql + ": 0 registros") #No estará catalogada o hay un error en el SQL + nun_records, records = xbmc_videolibrary.execute_sql_kodi(sql) # SQL execution + if nun_records == 0: # is there an error? + logger.error("SQL error: " + sql + ": 0 records") # It will not be listed or there is an error in the SQL except: logger.error(traceback.format_exc()) @@ -1475,97 +1298,97 @@ def fail_over_newpct1(item, patron, patron2=None, timeout=None): """ - Llamada para encontrar una web alternativa a un canal caído, clone de NewPct1 + Call to find an alternative website to a downed channel, clone of NewPct1 - Creamos una array con los datos de los canales alternativos. Los datos de la tupla son: + We create an array with the data of the alternative channels. The tuple data is: - - active = 0,1 Indica si el canal no está activo o sí lo está - - channel nombre del canal alternativo - - channel_host host del canal alternativo, utilizado para el reemplazo de parte de la url - - contentType indica que tipo de contenido que soporta el nuevo canal en fail-overs - - action_excluded lista las acciones que está excluidas para ese canal + - active = 0.1 Indicates if the channel is not active or if it is + - channel name of the alternative channel + - channel_host host of the alternative channel, used to replace part of the url + - contentType indicates what type of content the new channel supports in fail-overs + - action_excluded lists the actions that are excluded for that channel - La llamada al método desde el principio de Submenu, Listado_Búsqueda, Episodios y Findvideos, es: + The method call from the beginning of Submenu, Search_List, Episodes and Findvideos, is: from lib import generictools - item, data = generictools.fail_over_newpct1(item, patron[, patron2=][, timeout=]) + item, data = generictools.fail_over_newpct1 (item, pattern [, pattern2 =] [, timeout =]) - - Entrada: patron: con este patron permite verificar si los datos de la nueva web son buenos - - Entrada (opcional): patron2: segundo patron opcional - - Entrada (opcional): timeout: valor de espera máximo en download de página. Por defecto 3 - - Entrada (opcional): patron=True: pide que sólo verifique si el canal en uso está activo, si no, ofrece otro - - Salida: data: devuelve los datos del la nueva web. Si vuelve vacía es que no se ha encontrado alternativa + - Entry: pattern: with this pattern it is possible to verify if the data of the new website is good + - Input (optional): pattern 2: optional second pattern + - Entry (optional): timeout: maximum wait value in page download. Default 3 + - Input (optional): pattern = True: asks to only verify if the channel in use is active, if not, offers another + - Output: data: returns the data of the new website. If it returns empty it is that no alternative was found """ - #logger.debug(item) + # logger.debug(item) if timeout == None: - timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage + timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) # Timeout downloadpage if timeout == 0: timeout = None - if item.action == "search" or item.action == "listado_busqueda": timeout = timeout * 2 #Mas tiempo para búsquedas + if item.action == "search" or item.action == "listado_busqueda": timeout = timeout * 2 # More time for searches data = '' channel_failed = '' url_alt = [] - item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() + item.category = scrapertools.find_single_match(item.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() if not item.extra2: item.extra2 = 'z9z8z7z6z5' patron_alt = '' verify_torrent = '' - if patron is not True and '|' in patron: #Comprobamos si hay dos patrones alternativos + if patron is not True and '|' in patron: # We check if there are two alternative patterns try: - verify_torrent, patron1, patron_alt = patron.split('|') #Si es así, los separamos y los tratamos + verify_torrent, patron1, patron_alt = patron.split('|') # If so, we separate them and treat them patron = patron1 except: logger.error(traceback.format_exc()) - #Array con los datos de los canales alternativos - #Cargamos en .json del canal para ver las listas de valores en settings + # Array with the data of the alternative channels + # We load in .json of the channel to see the lists of values ​​in settings fail_over = channeltools.get_channel_json(channel_py) - for settings in fail_over['settings']: #Se recorren todos los settings - if settings['id'] == "clonenewpct1_channels_list": #Encontramos en setting - fail_over = settings['default'] #Carga lista de clones + for settings in fail_over['settings']: # All settings are scrolled + if settings['id'] == "clonenewpct1_channels_list": # We found in setting + fail_over = settings['default'] # Load list of clones break fail_over_list = ast.literal_eval(fail_over) - #logger.debug(str(fail_over_list)) + # logger.debug(str(fail_over_list)) if item.from_channel and item.from_channel != 'videolibrary': #Desde search puede venir con el nombre de canal equivocado item.channel = item.from_channel - #Recorremos el Array identificando el canal que falla + # We walk the Array identifying the channel that fails for active, channel, channel_host, contentType, action_excluded in fail_over_list: if item.channel == channel_py: - if channel != item.category.lower(): #es el canal/categoría que falla? + if channel != item.category.lower(): # is the channel / category failing? continue else: - if channel != item.channel: #es el canal que falla? + if channel != item.channel: # is the channel failing? continue - channel_failed = channel #salvamos el nombre del canal o categoría - channel_host_failed = channel_host #salvamos el nombre del host - channel_url_failed = item.url #salvamos la url + channel_failed = channel # we save the name of the channel or category + channel_host_failed = channel_host # we save the hostname + channel_url_failed = item.url # we save the url #logger.debug(channel_failed + ' / ' + channel_host_failed) - if patron == True and active == '1': #solo nos han pedido verificar el clone - return (item, data) #nos vamos, con el mismo clone, si está activo - if (item.action == 'episodios' or item.action == "update_tvshow" or item.action == "get_seasons" or item.action == 'findvideos') and item.contentType not in contentType: #soporta el fail_over de este contenido? - logger.error("ERROR 99: " + item.action.upper() + ": Acción no soportada para Fail-Over en canal: " + item.url) - return (item, data) #no soporta el fail_over de este contenido, no podemos hacer nada + if patron == True and active == '1': # we have only been asked to verify the clone + return (item, data) # we leave, with the same clone, if it is active + if (item.action == 'episodios' or item.action == "update_tvshow" or item.action == "get_seasons" or item.action == 'findvideos') and item.contentType not in contentType: # supports fail_over of this content? + logger.error("ERROR 99: " + item.action.upper() + ": Unsupported Action for Channel Fail-Over: " + item.url) + return (item, data) # does not support fail_over of this content, we can not do anything break if not channel_failed: - logger.error('Patrón: ' + str(patron) + ' / fail_over_list: ' + str(fail_over_list)) + logger.error('Pattern: ' + str(patron) + ' / fail_over_list: ' + str(fail_over_list)) logger.error(item) - return (item, data) #Algo no ha funcionado, no podemos hacer nada + return (item, data) # Something has not worked, we can not do anything - #Recorremos el Array identificando canales activos que funcionen, distintos del caído, que soporten el contenido + # We go through the Array identifying active channels that work, other than the fallen one, that support the content for active, channel, channel_host, contentType, action_excluded in fail_over_list: data_alt = '' - if channel == channel_failed or active == '0' or item.action in action_excluded or item.extra2 in action_excluded: #es válido el nuevo canal? + if channel == channel_failed or active == '0' or item.action in action_excluded or item.extra2 in action_excluded: # is the new channel valid? continue - if (item.action == 'episodios' or item.action == "update_tvshow" or item.action == "get_seasons" or item.action == 'findvideos') and item.contentType not in contentType: #soporta el contenido? + if (item.action == 'episodios' or item.action == "update_tvshow" or item.action == "get_seasons" or item.action == 'findvideos') and item.contentType not in contentType: # does it support content? continue - #Hacemos el cambio de nombre de canal y url, conservando las anteriores como ALT + # We make the channel and url name change, keeping the previous ones as ALT item.channel_alt = channel_failed if item.channel != channel_py: item.channel = channel @@ -1576,36 +1399,36 @@ def fail_over_newpct1(item, patron, patron2=None, timeout=None): channel_host_failed_bis = re.sub(r'(?i)http.*://', '', channel_host_failed) item.url = item.url.replace(channel_host_failed_bis, channel_host_bis) - url_alt += [item.url] #salvamos la url para el bucle + url_alt += [item.url] # we save the url for the loop item.channel_host = channel_host - #logger.debug(str(url_alt)) + # logger.debug(str(url_alt)) - #quitamos el código de series, porque puede variar entre webs + # We remove the series code, because it can vary between websites if item.action == "episodios" or item.action == "get_seasons" or item.action == "update_tvshow": - item.url = re.sub(r'\/\d+\/?$', '', item.url) #parece que con el título solo ecuentra la serie, normalmente... - url_alt = [item.url] #salvamos la url para el bucle, pero de momento ignoramos la inicial con código de serie + item.url = re.sub(r'\/\d+\/?$', '', item.url) # it seems that with the title only finds the series, usually ... + url_alt = [item.url] # we save the url for the loop, but for now we ignore the initial with serial code - #si es un episodio, generalizamos la url para que se pueda encontrar en otro clone. Quitamos la calidad del final de la url + # if it is an episode, we generalize the url so that it can be found in another clone. We remove the quality from the end of the url elif item.action == "findvideos" and item.contentType == "episode": try: - #quitamos el 0 a la izquierda del episodio. Algunos clones no lo aceptan - inter1, inter2, inter3 = scrapertools.find_single_match(item.url, '(http.*?\/temporada-\d+.*?\/capitulo.?-)(\d+)(.*?\/)') + # We remove the 0 to the left of the episode. Some clones do not accept it + inter1, inter2, inter3 = scrapertools.find_single_match(item.url, r'(http.*?\/temporada-\d+.*?\/capitulo.?-)(\d+)(.*?\/)') inter2 = re.sub(r'^0', '', inter2) if inter1 + inter2 + inter3 not in url_alt: url_alt += [inter1 + inter2 + inter3] - #en este formato solo quitamos la calidad del final de la url - if scrapertools.find_single_match(item.url, 'http.*?\/temporada-\d+.*?\/capitulo.?-\d+.*?\/') not in url_alt: - url_alt += [scrapertools.find_single_match(item.url, 'http.*?\/temporada-\d+.*?\/capitulo.?-\d+.*?\/')] + # in this format we only remove the quality from the end of the url + if scrapertools.find_single_match(item.url, r'http.*?\/temporada-\d+.*?\/capitulo.?-\d+.*?\/') not in url_alt: + url_alt += [scrapertools.find_single_match(item.url, r'http.*?\/temporada-\d+.*?\/capitulo.?-\d+.*?\/')] except: - logger.error("ERROR 88: " + item.action + ": Error al convertir la url: " + item.url) + logger.error("ERROR 88: " + item.action + ": Error converting url: " + item.url) logger.error(traceback.format_exc()) - logger.debug('URLs convertidas: ' + str(url_alt)) + logger.debug('Converted URLs: ' + str(url_alt)) - if patron == True: #solo nos han pedido verificar el clone - return (item, data) #nos vamos, con un nuevo clone + if patron == True: # we have only been asked to verify the clone + return (item, data) # we leave, with a new clone - #Leemos la nueva url.. Puede haber varias alternativas a la url original + # We read the new url .. There may be several alternatives to the original url for url in url_alt: try: if item.post: @@ -1616,12 +1439,12 @@ def fail_over_newpct1(item, patron, patron2=None, timeout=None): except: data = '' logger.error(traceback.format_exc()) - if not data: #no ha habido suerte, probamos con la siguiente url - logger.error("ERROR 01: " + item.action + ": La Web no responde o la URL es erronea: " + url) + if not data: # no luck, we try the following url + logger.error("ERROR 01: " + item.action + ": The Web does not respond or the URL is wrong: " + url) continue - #Hemos logrado leer la web, validamos si encontramos un línk válido en esta estructura - #Evitar páginas engañosas que puede meter al canal en un loop infinito + # We have managed to read the web, we validate if we find a valid link in this structure + # Avoid misleading pages that can put the channel in an infinite loop if (not ".com/images/no_imagen.jpg" in data and not ".com/images/imagen-no-disponible.jpg" in data) or item.action != "episodios": if patron: data_alt = scrapertools.find_single_match(data, patron) @@ -1633,38 +1456,25 @@ def fail_over_newpct1(item, patron, patron2=None, timeout=None): data_alt = scrapertools.find_single_match(data_comillas, patron_alt) if patron2 != None: data_alt = scrapertools.find_single_match(data_alt, patron2) - if not data_alt: #no ha habido suerte, probamos con el siguiente canal - logger.error("ERROR 02: " + item.action + ": Ha cambiado la estructura de la Web: " + url + " / Patron: " + patron + " / " +patron_alt) + if not data_alt: # no luck, we tried the next channel + logger.error("ERROR 02: " + item.action + ": The structure of the Web has changed: " + url + " / Patron: " + patron + " / " +patron_alt) web_intervenida(item, data) data = '' continue - else: - #Función especial para encontrar en otro clone un .torrent válido - if verify_torrent == 'torrent:check:status': - from core import videolibrarytools - if not data_alt.startswith("http"): #Si le falta el http.: lo ponemos - data_alt = scrapertools.find_single_match(item.channel_host, '(\w+:)//') + data_alt - if videolibrarytools.verify_url_torrent(data_alt): #verificamos si el .torrent existe - item.url = url #guardamos la url que funciona - break #nos vamos, con la nueva url del .torrent verificada - data = '' - continue #no vale el .torrent, continuamos - item.url = url #guardamos la url que funciona, sin verificar - break #por fin !!! Este canal parece que funciona else: - logger.error("ERROR 02: " + item.action + ": Ha cambiado la estructura de la Web: " + url + " / Patron: " + patron + " / " +patron_alt) + logger.error("ERROR 02: " + item.action + ": The structure of the Web has changed: " + url + " / Patron: " + patron + " / " +patron_alt) web_intervenida(item, data) data = '' continue - if not data: #no ha habido suerte, probamos con el siguiente clone + if not data: # no luck, we tried the following clone url_alt = [] continue else: break - del item.extra2 #Borramos acción temporal excluyente - if not data: #Si no ha logrado encontrar nada, salimos limpiando variables + del item.extra2 # We delete exclusive temporary action + if not data: # If you have not found anything, we leave cleaning variables if item.channel == channel_py: if item.channel_alt: item.category = item.channel_alt.capitalize() @@ -1678,723 +1488,132 @@ def fail_over_newpct1(item, patron, patron2=None, timeout=None): del item.url_alt item.channel_host = channel_host_failed - #logger.debug(item) + # logger.debug(item) return (item, data) -def verify_channel(channel): - return channel - #Lista con los datos de los canales alternativos - #Cargamos en .json del canal para ver las listas de valores en settings - # clones = channeltools.get_channel_json(channel_py) - # for settings in clones['settings']: #Se recorren todos los settings - # if settings['id'] == "clonenewpct1_channels_list": #Encontramos en setting - # clones = settings['default'] #Carga lista de clones - # channel_alt = "'%s'" % channel - # if channel_alt in clones: #Si es un clon se pone como canal newpct1, si no se deja - # channel = channel_py - # return channel - - def web_intervenida(item, data, desactivar=True): logger.info() """ - Llamada para verificar si la caída de un clone de Newpct1 es debido a una intervención judicial + Call to verify if the crash of a Newpct1 clone is due to judicial intervention - La llamada al método desde es: + The method call from is: from lib import generictools - item = generictools.web_intervenida(item, data[, desactivar=True]) + item = generictools.web_intervened (item, data [, disable = True]) - - Entrada: data: resultado de la descarga. Nos permite analizar si se trata de una intervención - - Entrada: desactivar=True: indica que desactiva el canal o clone en caso de intervención judicial - - Salida: item.intervencion: devuele un array con el nombre del clone intervenido y el thumb de la autoridad que interviene. El canal puede anunciarlo. - - Salida: Si es un clone de Newpct1, se desactiva el clone en el .json del Canal. Si es otro canal, se desactiva el canal en su .json. + - Entry: data: result of the download. It allows us to analyze if it is an intervention + - Input: disable = True: indicates that you disable the channel or clone in case of judicial intervention + - Output: item.intervention: return an array with the name of the intervened clone and the thumb of the intervening authority. The channel can announce it. + - Output: If it is a clone of Newpct1, the clone is disabled in the Channel's .json. If it's another channel, the channel in your .json is disabled. """ intervencion = () judicial = '' - #Verificamos que sea una intervención judicial + # We verify that it is a judicial intervention if intervenido_policia in data or intervenido_guardia in data or intervenido_sucuri in data: if intervenido_guardia in data: - judicial = 'intervenido_gc.png' #thumb de la Benemérita + judicial = 'intervenido_gc.png' # thumb of the Benemérita if intervenido_policia in data: - judicial = 'intervenido_pn.jpeg' #thumb de la Policia Nacional + judicial = 'intervenido_pn.jpeg' # thumb of the National Police if intervenido_sucuri in data: - judicial = 'intervenido_sucuri.png' #thumb de Sucuri + judicial = 'intervenido_sucuri.png' # thumb of Juices category = item.category if not item.category: category = item.channel - intervencion = (category, judicial) #Guardamos el nombre canal/categoría y el thumb judicial + intervencion = (category, judicial) # We keep the channel / category name and the judicial thumb if not item.intervencion: - item.intervencion = [] #Si no existe el array, lo creamos - item.intervencion += [intervencion] #Añadimos esta intervención al array + item.intervencion = [] # If the array does not exist, we create it + item.intervencion += [intervencion] # We add this intervention to the array - logger.error("ERROR 99: " + category + ": " + judicial + ": " + item.url + ": DESACTIVADO=" + str(desactivar) + " / DATA: " + data) + logger.error("ERROR 99: " + category + ": " + judicial + ": " + item.url + ": DISABLED=" + str(desactivar) + " / DATA: " + data) - if desactivar == False: #Si no queremos desactivar el canal, nos vamos + if desactivar == False: # If we don't want to disable the channel, we go return item - #Cargamos en .json del canal para ver las listas de valores en settings. Carga las claves desordenadas !!! + # We load in .json of the channel to see the lists of values ​​in settings. Load the cluttered keys !!! from core import filetools import json json_data = channeltools.get_channel_json(item.channel) - if item.channel == channel_py: #Si es un clone de Newpct1, lo desactivamos - for settings in json_data['settings']: #Se recorren todos los settings - if settings['id'] == "clonenewpct1_channels_list": #Encontramos en setting - action_excluded = scrapertools.find_single_match(settings['default'], "\('\d', '%s', '[^']+', '[^']*', '([^']*)'\)" % item.category.lower()) #extraemos el valor de action_excluded + if item.channel == channel_py: # If it's a clone of Newpct1, we disable it + for settings in json_data['settings']: # All settings are scrolled + if settings['id'] == "clonenewpct1_channels_list": # We found in setting + action_excluded = scrapertools.find_single_match(settings['default'], r"\('\d', '%s', '[^']+', '[^']*', '([^']*)'\)" % item.category.lower()) #extraemos el valor de action_excluded if action_excluded: if "intervenido" not in action_excluded: - action_excluded += ', %s' % judicial #Agregamos el thumb de la autoridad judicial + action_excluded += ', %s' % judicial # We add the thumb of the judicial authority else: action_excluded = '%s' % judicial - #Reemplazamos el estado a desactivado y agregamos el thumb de la autoridad judicial + # We replace the status to disabled and add the thumb of the judicial authority settings['default'] = re.sub(r"\('\d', '%s', ('[^']+', '[^']*'), '[^']*'\)" % item.category.lower(), r"('0', '%s', \1, '%s')" % (item.category.lower(), action_excluded), settings['default']) break else: - #json_data['active'] = False #Se desactiva el canal - json_data['thumbnail'] = ', thumb_%s' % judicial #Guardamos el thumb de la autoridad judicial + # json_data['active'] = False # Channel is disabled + json_data['thumbnail'] = ', thumb_%s' % judicial # We keep the thumb of the judicial authority - #Guardamos los cambios hechos en el .json + # We save the changes made in the .json try: if item.channel != channel_py: - disabled = config.set_setting('enabled', False, item.channel) #Desactivamos el canal - disabled = config.set_setting('include_in_global_search', False, item.channel) #Lo sacamos de las búquedas globales + disabled = config.set_setting('enabled', False, item.channel) # We deactivate the channel + disabled = config.set_setting('include_in_global_search', False, item.channel) # We get it out of global searches channel_path = filetools.join(config.get_runtime_path(), "channels", item.channel + ".json") - with open(channel_path, 'w') as outfile: #Grabamos el .json actualizado + with open(channel_path, 'w') as outfile: # We record the updated .json json.dump(json_data, outfile, sort_keys = True, indent = 2, ensure_ascii = False) except: - logger.error("ERROR 98 al salvar el archivo: %s" % channel_path) + logger.error("ERROR 98 when saving the file: %s" % channel_path) logger.error(traceback.format_exc()) - #logger.debug(item) + # logger.debug(item) return item -def redirect_clone_newpct1(item, head_nfo=None, it=None, path=False, overwrite=False, lookup=False): - # logger.info() - # - # """ - # - # Llamada para redirigir cualquier llamada a un clone de NewPct1 a NewPct1.py, o de una url de un canal caido a una alternativa - # Incluye las llamadas estándar del canal y la llamadas externas: - # - Play fron Library - # - Videolibrary Update - # - # La lógica es reemplazar item.channel por "newpct1" y dejar el nombre del clone en item.category. - # De esta forma utiliza siempre el código de NewPct1.py, aunque con las urls y apariencia del clone seleccionado por el usuario. - # - # En el caso de un canal/clone caído o intervenido judicialmente, puede reemplazar el canal en item.channel, o el clone en item.category, y la parte de item.url que se introduzca en una tabla. Esta conversión sólo se realiza si el canal original está inactivo, pero lo realiza siempre para los clones, o si el canal de origen y destino son los mismos. - # - # Este método interroga el .json de NewPct1 para extraer la lista de canales clones. Si item.channel es un clone de NewPct1 y está en esa lista, actualiza item.channel='newpct1' - # - # También en este .json está la tabla para la conversión de canales y urls: - # - activo: está o no activa esta entrada - # - canal_org: canal o clone de origen - # - canal_des: canal o clone de destino (puede ser el mismo) - # - url_org: parte de la url a sustituir de canal o clone de origen - # - url_des: parte de la url a sustituir de canal o clone de destino - # - patron1: expresión Regex aplicable a la url (opcional) - # - patron2: expresión Regex aplicable a la url (opcional) - # - patron3: expresión Regex aplicable a la url (opcional) - # - patron4: expresión Regex aplicable a la url (opcional) - # - patron5: expresión Regex aplicable a la url (opcional) - # - content_inc: contenido al que aplica esta entrada, o * (item.contentType o item.extra) - # - content_exc: contenido que se excluye de esta entrada (item.contentType) (opcional). opción para 'emerg' - # - ow_force: indicador para la acción de "service.py". Puede crear la variable item.ow_force: - # - force: indica al canal que analize toda la serie y que service la reescriba - # - auto: indica a service que la reescriba - # - no: no acción para service, solo redirige en visionado de videolibrary - # - del: borra las estrucuturas de un determinado canal en service, quizás creadas por errores de un canal - # - emerg: funcionalidad muy similar a la de "del". se general dinámicamente cada vez que entra un canal con el estado activado en el .json de "emergency_urls". Permite cargar las urls de emergencia en todos los elementos existentes de la Videoteca para canal afectado - # ejemplos: - # ('1', 'mejortorrent', 'mejortorrent1', 'http://www.mejortorrent.com/', 'https://mejortorrent1.com/', '(http.?:\/\/.*?\/)', 'http.?:\/\/.*?\/.*?-torrent.?-[^-]+-(?:[^-]+-)([^0-9]+-)', 'http.?:\/\/.*?\/.*?-torrent.?-[^-]+-(?:[^-]+-)[^0-9]+-\\d+-(Temporada-).html', 'http.?:\/\/.*?\/.*?-torrent.?-[^-]+-(?:[^-]+-)[^0-9]+-(\\d+)-', '', 'tvshow, season', '', 'force'), - # ('1', 'mejortorrent', 'mejortorrent1', 'http://www.mejortorrent.com/', 'https://mejortorrent1.com/', '(http.?:\/\/.*?\/)', 'http.?:\/\/.*?\/.*?-torrent.?-[^-]+-([^.]+).html', '', '', '', 'movie', '', 'force')", - # ('1', 'torrentrapid', 'torrentlocura', 'http://torrentrapid.com/', 'http://torrentlocura.com/', '', '', '', '', '', '*', '', 'no'), - # ('1', 'newpct1', '', '', '', '', '', '', '', '', '*', '', 'del'), - # ('1', 'torrentrapid', 'torrentrapid', '', '', '', '', '', '', '', '*', '1 ó 2', 'emerg'), - # - # La llamada recibe el parámetro Item, el .nfo y los devuleve actualizados, así como opcionalmente el parámetro "overwrite· que puede forzar la reescritura de todos los archivos de la serie, y el parámetro "path" si viene de service. Por último, recibe opcionalmente el parámetro "lookup" si se quiere solo averigurar si habrá migración para ese título, pero sin realizarla. - # - # """ - # #logger.debug(item) - # #if it != None: logger.debug(it) - # if not it: - # it = Item() - # item_back = item.clone() - # it_back = item.clone() - # ow_force_param = True - # update_stat = 0 - # delete_stat = 0 - # canal_org_des_list = [] - # json_path_list = [] - # emergency_urls_force = False - # status_migration = False - # - # #if item.ow_force == '1': #Ha podido qudar activado de una pasada anteriores - # # del item.ow_force - # # logger.error('** item.ow_force: ' + item.path) #aviso que ha habido una incidencia - # if it.ow_force == '1': #Ha podido quedar activado de una pasada anterior - # del it.ow_force - # if path and it.infoLabels['mediatype'] == 'tvshow': - # try: - # nfo = filetools.join(path, '/tvshow.nfo') - # filetools.write(nfo, head_nfo + it.tojson()) #escribo el .nfo de la peli por si aborta update - # logger.error('** .nfo ACTUALIZADO: it.ow_force: ' + nfo) #aviso que ha habido una incidencia - # except: - # logger.error('** .nfo ERROR actualizar: it.ow_force: ' + nfo) #aviso que ha habido una incidencia - # logger.error(traceback.format_exc()) - # - # #Array con los datos de los canales alternativos - # #Cargamos en .json de Newpct1 para ver las listas de valores en settings - # fail_over_list = channeltools.get_channel_json(channel_py) - # for settings in fail_over_list['settings']: #Se recorren todos los settings - # if settings['id'] == "clonenewpct1_channels_list": #Encontramos en setting - # fail_over_list = settings['default'] #Carga lista de clones - # if settings['id'] == "intervenidos_channels_list": #Encontramos en setting - # intervencion = settings['default'] #Carga lista de clones y canales intervenidos - # - # #primero tratamos los clones de Newpct1 - # channel_alt = item.channel - # #if item.url and not it.library_urls: - # # channel_alt = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').lower() #Salvamos en nombre del canal o clone - # # if not channel_alt: - # # channel_alt = item.channel - # channel = "'%s'" % channel_alt - # category = '' - # if channel_alt != 'videolibrary': - # item.category = channel_alt.capitalize() - # category = "'%s'" % channel_alt - # channel_py_alt = 'xyz123' - # if channel in fail_over_list : #Si es un clone de Newpct1, se actualiza el canal y la categoría - # item.channel = channel_py - # channel_py_alt = "'%s'" % channel_py - # if item.channel_host: #y se borran resto de pasadas anteriores - # del item.channel_host - # - # if it.emergency_urls: - # item.emergency_urls = it.emergency_urls #Refrescar desde el .nfo - # - # #Analizamos si hay series o películas que migrar, debido a que se ha activado en el .json del canal la opción "guardar" - # #"emergency_urls = 1", y hay que calcularla para todos los episodios y película existentes en la Videoteca. - # #Si "emergency_urls" está activada para uno o más canales, se verifica en el .nfo del vídeo si ya se ha realizado - # #la carga de las urls de emergencia. Sí se ha hecho, se ignora el proceso de conversión. Si no, se convierte por el - # #canal en curso cuando hay item.url, o para todos los canales en item.library_urls si no hay un canal específico en curso. - # #El mecanismo consiste en generar una regla temporal de migración para cada canal activado. Esta regla actua borrando - # #todos los .json de la serie/película. En el caso de la serie, el proceso de actualización de la videoteca los regenerará - # #automáticamente. En el caso de peliculas, se general aquí el json actualizado y se marca el .nfo como actualizado. - # #Cuando en el .json se activa "Borrar", "emergency_urls = 2", se borran todos los enlaces existentes - # #Cuando en el .json se activa "Actualizar", "emergency_urls = 3", se actualizan todos los enlaces existentes - # - # """ - # status_migration = regenerate_clones() #TEMPORAL: Reparación de Videoteca con Newpct1 - # - # verify_cached_torrents() #TEMPORAL: verificamos si los .torrents son correctos - # try: #Si ha habido errores, vemos la lista y los reparamos - # json_error_path = filetools.join(config.get_runtime_path(), 'error_cached_torrents.json') - # if filetools.exists(json_error_path): #hay erroer que hay que reparar? - # from core import jsontools - # json_error_file = jsontools.load(filetools.read(json_error_path)) #Leemos la lista de errores - # if not json_error_file: - # filetools.remove(json_error_path) #si ya no quedan errores, borramos el .json - # elif path in json_error_file: #está este títu,o en la lista de errores? - # json_error_file.pop(path) #sí. Lo quitamos - # if not json_error_file: - # filetools.remove(json_error_path) #si ya no quedan errores, borramos el .json - # else: - # filetools.write(json_error_path, jsontools.dump(json_error_file)) #si quedan, actualizamos el .json - # if item.contentType == 'movie': #si es una pelicula, forzamos su actualización - # emergency_urls_force = True - # else: #si es una serie, que regenere los episodios que faltan (en error) - # item.ow_force = '1' #... de todas las temporadas - # except: - # logger.error('Error en el proceso de REPARACION de vídeos con .torrents dañados') - # logger.error(traceback.format_exc()) - # - # #Arreglo temporal para Newpct1 - # try: - # if channel in fail_over_list or channel_alt == 'videolibrary': - # channel_bis = channel_py - # if not item.url and it.library_urls and channel_alt == 'videolibrary': - # for canal_vid, url_vid in it.library_urls.items(): #Se recorre "item.library_urls" para buscar canales candidatos - # canal_vid_alt = "'%s'" % canal_vid - # if canal_vid_alt in fail_over_list: #Se busca si es un clone de newpct1 - # channel_bis = channel_py - # channel_alt = canal_vid - # channel = "'%s'" % channel_alt - # break - # else: - # channel_bis = canal_vid - # if channel_bis == channel_py and config.get_setting("emergency_urls", channel_bis) == 1 and config.get_setting("emergency_urls_torrents", channel_bis) and item.emergency_urls and item.emergency_urls.get(channel_alt, False): - # raiz, carpetas_series, ficheros = filetools.walk(path).next() - # objetivo = '[%s]_01.torrent' % channel_alt - # encontrado = False - # for fichero in ficheros: - # if objetivo in fichero: - # encontrado = True - # break - # if not encontrado: - # logger.error('REGENERANDO: ' + str(item.emergency_urls)) - # item.emergency_urls.pop(channel_alt, None) - # except: - # logger.error('Error en el proceso de RECARGA de URLs de Emergencia') - # logger.error(traceback.format_exc()) - # """ - # - # try: - # if item.url and not channel_py in item.url and it.emergency_urls: #Viene de actualización de videoteca de series - # #Analizamos si el canal ya tiene las urls de emergencia: guardar o borrar - # if (config.get_setting("emergency_urls", item.channel) == 1 and (not item.emergency_urls or (item.emergency_urls and not item.emergency_urls.get(channel_alt, False)))) or (config.get_setting("emergency_urls", item.channel) == 2 and item.emergency_urls.get(channel_alt, False)) or config.get_setting("emergency_urls", item.channel) == 3 or emergency_urls_force: - # intervencion += ", ('1', '%s', '%s', '', '', '', '', '', '', '', '*', '%s', 'emerg')" % (channel_alt, channel_alt, config.get_setting("emergency_urls", item.channel)) - # - # elif it.library_urls: #Viene de "listar peliculas´" - # for canal_vid, url_vid in it.library_urls.items(): #Se recorre "item.library_urls" para buscar canales candidatos - # if canal_vid == channel_py: #Si tiene Newcpt1 en canal, es un error - # continue - # canal_vid_alt = "'%s'" % canal_vid - # if canal_vid_alt in fail_over_list: #Se busca si es un clone de newpct1 - # channel_bis = channel_py - # else: - # channel_bis = canal_vid - # #Analizamos si el canal ya tiene las urls de emergencia: guardar o borrar - # if (config.get_setting("emergency_urls", channel_bis) == 1 and (not it.emergency_urls or (it.emergency_urls and not it.emergency_urls.get(canal_vid, False)))) or (config.get_setting("emergency_urls", channel_bis) == 2 and it.emergency_urls.get(canal_vid, False)) or config.get_setting("emergency_urls", channel_bis) == 3 or emergency_urls_force: - # intervencion += ", ('1', '%s', '%s', '', '', '', '', '', '', '', '*', '%s', 'emerg')" % (canal_vid, canal_vid, config.get_setting("emergency_urls", channel_bis)) - # except: - # logger.error('Error en el proceso de ALMACENAMIENTO de URLs de Emergencia') - # logger.error(traceback.format_exc()) - # - # #Ahora tratamos las webs intervenidas, tranformamos la url, el nfo y borramos los archivos obsoletos de la serie - # if (channel not in intervencion and channel_py_alt not in intervencion and category not in intervencion and channel_alt != 'videolibrary') or not item.infoLabels or status_migration: #lookup o migración - # return (item, it, overwrite) #... el canal/clone está listado - # - # import ast - # intervencion_list = ast.literal_eval(intervencion) #Convertir a Array el string - # #logger.debug(intervencion_list) - # - # if lookup == True: - # overwrite = False #Solo avisamos si hay cambios - # i = 0 - # for activo, canal_org, canal_des, url_org, url_des, patron1, patron2, patron3, patron4, patron5, content_inc, content_exc, ow_force in intervencion_list: - # i += 1 - # opt = '' - # #Es esta nuestra entrada? - # if activo == '1' and (canal_org == channel_alt or canal_org == item.category.lower() or channel_alt == 'videolibrary' or ow_force == 'del' or ow_force == 'emerg'): - # - # if item.url: - # logger.debug('INTERV. LIST: ' + str(intervencion_list[i-1]) + ' / CHANNEL: ' + str(channel_alt) + ' / URL: ' + str(item.url)) - # - # if ow_force == 'del' or ow_force == 'emerg': #Si es un borrado de estructuras erroneas, hacemos un proceso aparte - # canal_des_def = canal_des #Si hay canal de sustitución para item.library_urls, lo usamos - # if not canal_des_def and canal_org in item.library_urls and len(item.library_urls) == 1: #Si no, lo extraemos de la url - # canal_des_def = scrapertools.find_single_match(item.library_urls[canal_org], 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').lower() #salvamos la url actual de la estructura a borrar - # url_total = '' - # if item.url: - # url_total = item.url #Si existe item.url, lo salvamos para futuro uso - # if item.library_urls and canal_org in item.library_urls: #Si existe una entrada con el canal a borrar, lo procesamos - # if lookup == True: #Queremos que el canal solo visualice sin migración? - # overwrite = True #Avisamos que hay cambios - # continue - # logger.error('** REGLA: ' + canal_org + ', ' + canal_des+ ', ' + ow_force) - # logger.error('item.library_urls PREVIA: ' + str(item.library_urls)) - # url_total = item.library_urls[canal_org] #salvamos la url actual de la estructura a borrar - # url_total_status = False - # if len(item.library_urls) == 1 or canal_des: #si el nuevo canal no existe ya... - # item.library_urls.update({canal_des_def: url_total}) #restauramos la url con el nuevo canal - # url_total_status = True #marcamos esta url como válida - # overwrite = True #Le decimos que sobreescriba todos los .jsons - # item.ow_force = '1' #Le decimos que revise todas las temporadas - # if len(item.library_urls) > 1 and ow_force == 'del': - # item.library_urls.pop(canal_org, None) #borramos la url del canal a borrar - # overwrite = True #Le decimos que sobreescriba todos los .jsons - # item.ow_force = '1' #Le decimos que revise todas las temporadas - # if it.library_urls: - # it.library_urls = item.library_urls #lo salvamos en el .nfo, si lo hay - # - # if item.url and item.url == url_total and url_total_status == False: #si la url es la del canal borrado... - # for canal_vid, url_vid in item.library_urls.items(): - # canal_vid_alt = "'%s'" % canal_vid - # if canal_vid_alt not in intervencion: #... la sustituimos por la primera válida - # item.url = url_vid - # break - # if canal_vid_alt in fail_over_list: #Si es un clone de Newpct1, salvamos la nueva categoría - # item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').lower() #Salvamos categoría - # else: - # item.category = canal_vid.capitalize() #si no, salvamos nueva categoría - # logger.error('item.library_urls ACTUALIZADA: ' + str(item.library_urls)) - # - # if lookup == False: #si es migración completa... - # delete_stat += 1 #Ya hemos actualizado algo, o habrá que hacerlo... - # if ow_force == 'emerg': opt = content_exc #Salvamos la opción de Guardar o Borrar enlaces - # canal_org_des_list += [(canal_org, canal_des, url_total, opt, ow_force)] #salvamos el resultado para su proceso - # - # else: - # if channel_alt == 'videolibrary': #Viene de videolibrary.list_movies: IMPRESCINDIBLE - # for canal_vid, url_vid in item.library_urls.items(): - # if canal_org != canal_vid: #Miramos si canal_org de la regla está en item.library_urls - # continue - # else: - # channel_alt = canal_org #Sí, ponermos el nombre del canal de origen - # channel_b = "'%s'" % canal_org - # if channel_b in fail_over_list: #Si es un clone de Newpct1, se actualiza a newpct1 - # channel_alt = channel_py - # if channel_alt == 'videolibrary': - # continue - # if item.contentType == "list": #Si viene de Videolibrary, le cambiamos ya el canal - # if item.channel != channel_py: - # item.channel = canal_des #Cambiamos el canal. Si es clone, lo hace el canal - # continue #Salimos sin hacer nada más. item está casi vacío - # if item.contentType not in content_inc and "*" not in content_inc: #Está el contenido el la lista de incluidos - # continue - # if item.contentType in content_exc: #Está el contenido excluido? - # continue - # channel_enabled = 0 - # channel_enabled_alt = 1 - # if item.channel != channel_py: - # try: - # if channeltools.is_enabled(channel_alt): channel_enabled = 1 #Verificamos que el canal esté inactivo - # if config.get_setting('enabled', channel_alt) == False: channel_enabled_alt = 0 - # channel_enabled = channel_enabled * channel_enabled_alt #Si está inactivo en algún sitio, tomamos eso - # except: - # pass - # if channel_enabled == 1 and canal_org != canal_des: #Si el canal está activo, puede ser solo... - # continue #... una intervención que afecte solo a una región - # if ow_force == 'no' and it.library_urls: #Esta regla solo vale para findvideos... - # continue #... salidmos si estamos actualizando - # if lookup == True: #Queremos que el canal solo visualice sin migración? - # if ow_force != 'no': - # overwrite = True #Avisamos que hay cambios - # continue #Salimos sin tocar archivos - # url_total = '' - # if item.url: - # url_total = item.url - # elif not item.url and item.library_urls: - # url_total = item.library_urls[canal_org] - # url_total = url_total.replace(url_org, url_des) #reemplazamos una parte de url - # url = '' - # if patron1: #Hay expresión regex? - # url += scrapertools.find_single_match(url_total, patron1) #La aplicamos a url - # if patron2: #Hay más expresión regex? - # url += scrapertools.find_single_match(url_total, patron2) #La aplicamos a url - # if patron3: #Hay más expresión regex? - # url += scrapertools.find_single_match(url_total, patron3) #La aplicamos a url - # if patron4: #Hay más expresión regex? - # url += scrapertools.find_single_match(url_total, patron4) #La aplicamos a url - # if patron5: #Hay más expresión regex? - # url += scrapertools.find_single_match(url_total, patron5) #La aplicamos a url - # if url: - # url_total = url #Guardamos la suma de los resultados intermedios - # if item.channel == channel_py or channel in fail_over_list: #Si es Newpct1... - # if item.contentType == "tvshow": - # url_total = re.sub(r'\/\d+\/?$', '', url_total) #parece que con el título encuentra la serie, normalmente... - # update_stat += 1 #Ya hemos actualizado algo - # canal_org_des_list += [(canal_org, canal_des, url_total, opt, ow_force)] #salvamos el resultado para su proceso - # - # if update_stat > 0 or delete_stat > 0: #Ha habido alguna actualización o borrado? Entonces salvamos - # if (update_stat > 0 and path != False) or item.ow_force == '1': - # logger.error('** Lista de Actualizaciones a realizar: ' + str(canal_org_des_list)) - # for canal_org_def, canal_des_def, url_total, opt_def, ow_force_def in canal_org_des_list: #pasamos por todas las "parejas" cambiadas - # url_total_def = url_total - # if ow_force_def != 'del' and ow_force_def != 'emerg': - # if item.url: - # item.url = url_total #Salvamos la url convertida - # if item.library_urls: - # item.library_urls.pop(canal_org_def, None) - # item.library_urls.update({canal_des_def: url_total}) - # it.library_urls = item.library_urls - # if item.channel != channel_py and item.channel != 'videolibrary': - # item.channel = canal_des_def #Cambiamos el canal. Si es clone, lo hace el canal - # if channel_alt == item.category.lower(): #Actualizamos la Categoría y si la tenía - # item.category = item.channel.capitalize() - # if ow_force_def == 'force' and item.contentType != 'movie': #Queremos que el canal revise la serie entera? - # item.ow_force = '1' #Se lo decimos - # if ow_force_def in ['force', 'auto']: #Sobreescribir la series? - # overwrite = True #Sí, lo marcamos - # - # if it.library_urls and path != False and ow_force_def != 'no': #Continuamos si hay .nfo, path, y queremos actualizarlo - # item.update_next = '1' - # del item.update_next #Borramos estos campos para forzar la actualización ya - # it.update_next = '1' - # del it.update_next - # - # #Verificamos que las webs de los canales estén activas antes de borrar los .json, para asegurar que se pueden regenerar - # i = 0 - # canal_org_des_list_ALT = [] #Creamos esta lista para salvar las parejas - # canal_org_des_list_ALT.extend(canal_org_des_list) #... y borrar de la original las web caidas - # for canal_org_def, canal_des_def, url_total, opt_def, ow_force_def in canal_org_des_list_ALT: #pasamos por las "parejas" a borrar - # if "magnet:" in url_total or type(url_total) != str: #Si la url es un Magnet, o es una lista, pasamos - # i += 1 - # continue - # try: - # response = httptools.downloadpage(url_total) - # except: - # logger.error(traceback.format_exc()) - # logger.error('Web ' + canal_des_def.upper() + ' ERROR. Regla no procesada: ' + str(canal_org_des_list[i])) - # del canal_org_des_list[i] #Borro regla - # continue #... y paso a la siguiente - # if not response: - # logger.error('Web ' + canal_des_def.upper() + ' INACTIVA. Regla no procesada: ' + str(canal_org_des_list[i])) - # del canal_org_des_list[i] #Borro regla - # continue #... y paso a la siguiente - # i += 1 - # if i == 0: - # item = item_back.clone() #Restauro las imágenes inciales - # it = it_back.clone() - # item.torrent_caching_fail = True #Marcamos el proceso como fallido - # return (item, it, False) - # - # # Listamos todos los ficheros de la serie, asi evitamos tener que comprobar si existe uno por uno - # canal_erase_list = [] - # from core import videolibrarytools - # raiz, carpetas_series, ficheros = filetools.walk(path).next() - # ficheros = [filetools.join(path, f) for f in ficheros] #Almacenamos la lista de archivos de la carpeta - # #logger.error(ficheros) - # for archivo in ficheros: - # for canal_org_def, canal_des_def, url_total, opt_def, ow_force_def in canal_org_des_list: #pasamos por las "parejas" a borrar - # canal_erase = '[%s]' % canal_org_def - # canal_erase_alt = "'%s'" % canal_org_def - # canal_new = '[%s]' % canal_des_def - # archivo_alt = "'%s'" % scrapertools.find_single_match(archivo, '\[(\w+)\].json') - # if archivo_alt == "''": archivo_alt = "'xyz123'" - # #logger.error(canal_erase + canal_new + archivo + archivo_alt) - # #Borramos los .json que sean de los canal afectados, incluidos todos los de los clones de newpct1 si éste es el canal - # if canal_erase in archivo or (ow_force_def == 'emerg' and canal_erase_alt in fail_over_list and archivo_alt in fail_over_list and it.contentType != 'movie'): - # if canal_des_def and it.contentType == 'movie' and not '.torrent' in archivo: #Si es película ... - # item_json = '' - # item_json = Item().fromjson(filetools.read(archivo)) #leemos el .json ante de borrarlo para salvar... - # if not item_json: #error al leer el .json. Algo no funciona... - # continue - # title = item_json.title #... el título con su formato - # language = item_json.language #... los idiomas, que no están en el .nfo - # wanted = item_json.wanted #... y wanted con el título original - # json_path = archivo.replace(canal_erase, canal_new) #Salvamos el path del .json para luego crearlo - # json_path_list += [(canal_org_def, canal_des_def, url_total, json_path, title, language, wanted, ow_force_def, opt_def, archivo)] - # filetools.remove(archivo) #Borramos el .json y el .torrent - # logger.error('** BORRAMOS: ' + str(archivo)) - # if ow_force_def == 'del' or ow_force_def == 'emerg': #Si la función es 'del' or 'emerg' ... - # overwrite = True #Le decimos que sobreescriba todos los .jsons - # item.ow_force = '1' #Le decimos que revise todas las temporadas - # - # #Si se ha cambiado algo, se actualizan los .nfo - # if it.nfo: del it.nfo #Borramos variables innecesarias - # if it.path: del it.path #Borramos variables innecesarias - # if it.text_color: del it.text_color #Borramos variables innecesarias - # if item.contentType == "movie" and ".nfo" in archivo: #Para películas - # archivo_nfo = archivo #Guardamos el path del .nfo para futuro uso - # if it.ow_force: del it.ow_force - # filetools.write(archivo, head_nfo + it.tojson()) #escribo el .nfo de la peli - # if item.contentType != "movie" and "tvshow.nfo" in archivo: - # archivo_nfo = archivo #Guardamos el path del .nfo para futuro uso - # filetools.write(archivo, head_nfo + it.tojson()) #escribo el tvshow.nfo por si aborta update - # - # #Aquí convertimos las películas. Después de borrado el .json, dejamos que videolibrarytools lo regenere - # if item.contentType == "movie": #Dejamos que regenere el archivo .json - # item_movie = item.clone() - # if item_movie.ow_force: del item_movie.ow_force - # item_movie.update_last = '1' - # if item_movie.update_last: del item_movie.update_last - # if item_movie.library_playcounts: del item_movie.library_playcounts #Borramos lo que no es necesario en el .json - # if item_movie.library_urls: del item_movie.library_urls - # if item_movie.nfo: del item_movie.nfo - # if item_movie.path: del item_movie.path - # if item_movie.strm_path: del item_movie.strm_path - # if item_movie.text_color: del item_movie.text_color - # if item_movie.channel_host: del item_movie.channel_host - # if not item_movie.context: item_movie.context = "['buscar_trailer']" - # if not item_movie.extra: item_movie.extra = "peliculas" - # - # if json_path_list: - # logger.error('** .json LIST: ' + str(json_path_list)) - # for canal_org_def, canal_des_def, url_total, json_path, title, language, wanted, ow_force_def, opt_def, archivo in json_path_list: #pasamos por todos canales - # logger.error('** ESCRIBIMOS: ' + json_path) - # item_movie.emergency_urls = False - # del item_movie.emergency_urls - # item_movie.channel = canal_des_def #mombre del canal migrado - # if not item_movie.category: item_movie.category = canal_des_def.capitalize() #categoría - # item_movie.url = url_total #url migrada - # if title: item_movie.title = title #restaurmos el título con formato - # if language: item_movie.language = language #restaurmos los idiomas - # if wanted: item_movie.wanted = wanted #restaurmos wanted - # item_movie.added_replacing = canal_org_def #guardamos la traza del canal reemplazado - # - # if ow_force_def == 'emerg' and opt_def in ['1', '3']: #Si era una op. para añadir/actualizar urls de emergencia ... - # item_movie = videolibrarytools.emergency_urls(item_movie, None, archivo) #... ejecutamos "findvideos" del canal para obtenerlas - # if item_movie.channel_host: del item_movie.channel_host - # if item_movie.unify: del item_movie.unify - # if item_movie.extra2: del item_movie.extra2 - # if item_movie.emergency_urls: #... si las hay ... - # if it.emergency_urls and not isinstance(it.emergency_urls, dict): - # del it.emergency_urls - # if not it.emergency_urls: #... lo actualizamos en el .nfo - # it.emergency_urls = dict() #... iniciamos la variable si no existe - # it.emergency_urls.update({canal_des_def: True}) #... se marca como activo - # if it.ow_force: del it.ow_force - # filetools.write(archivo_nfo, head_nfo + it.tojson()) #actualizo el .nfo de la peli - # else: - # logger.error('Error en FINDVIDEOS: ' + archivo + ' / Regla: ' + canal_org_def + ', ' + opt_def + ', ' + ow_force_def) - # - # if ow_force_def == 'emerg' and opt_def == '2': #Si era una operación para borrar urls de emergencia ... - # if it.emergency_urls and not isinstance(it.emergency_urls, dict): - # del it.emergency_urls - # if it.emergency_urls and it.emergency_urls.get(item_movie.channel, False): - # it.emergency_urls.pop(item_movie.channel, None) #borramos la entrada del .nfo - # if it.ow_force: del it.ow_force - # filetools.write(archivo_nfo, head_nfo + it.tojson()) #actualizo el .nfo de la peli - # - # filetools.write(json_path, item_movie.tojson()) #Salvamos el nuevo .json de la película - # - # if (update_stat > 0 and path != False and ow_force_def in ['force', 'auto']) or item.ow_force == '1' or len(json_path_list) > 0: - # logger.error('ITEM cambiado') - # if it.emergency_urls: - # logger.error(it.emergency_urls) - # logger.error(item) - # - # return (item, it, overwrite) - return item, item, False - - -def verify_cached_torrents(): - logger.info() - import json - - """ - Verifica que todos los archivos .torrent estén descomprimidos. Si no lo están, los descomprime y regraba - - Método para uso temporal y controlado - - Deja el archivo verify_cached_torrents.json como marca de que se ha ejecutado para esa versión de Alfa - """ - - try: - #Localiza los paths donde dejar el archivo .json de control, y de la Videoteca - json_path = filetools.exists(filetools.join(config.get_runtime_path(), 'verify_cached_torrents.json')) - if json_path: - logger.info('Torrents verificados anteriormente: NOS VAMOS') - return - json_path = filetools.join(config.get_runtime_path(), 'verify_cached_torrents.json') - json_error_path = filetools.join(config.get_runtime_path(), 'error_cached_torrents.json') - json_error_path_BK = filetools.join(config.get_runtime_path(), 'error_cached_torrents_BK.json') - - videolibrary_path = config.get_videolibrary_path() #Calculamos el path absoluto a partir de la Videoteca - movies = config.get_setting("folder_movies") - series = config.get_setting("folder_tvshows") - torrents_movies = filetools.join(videolibrary_path, config.get_setting("folder_movies")) #path de CINE - torrents_series = filetools.join(videolibrary_path, config.get_setting("folder_tvshows")) #path de SERIES - - #Inicializa variables - torren_list = [] - torren_list.append(torrents_movies) - torren_list.append(torrents_series) - i = 0 - j = 0 - k = 0 - descomprimidos = [] - errores = [] - json_data = dict() - - #Recorre las carpetas de CINE y SERIES de la Videoteca, leyendo, descomprimiendo y regrabando los archivos .torrent - for contentType in torren_list: - for root, folders, files in filetools.walk(contentType): - for file in files: - if not '.torrent' in file: - continue - i += 1 - torrent_file = '' - torrent_path = filetools.join(root, file) - torrent_file = filetools.read(torrent_path) - if not scrapertools.find_single_match(torrent_file, '^d\d+:\w+\d+:'): - logger.debug('Torrent comprimido: DESCOMPRIMIENDO: ' + str(torrent_path)) - try: - torrent_file_deco = '' - import zlib - torrent_file_deco = zlib.decompressobj(16 + zlib.MAX_WBITS).decompress(torrent_file) - except: - k += 1 - errores += [torrent_path] - logger.error(traceback.format_exc()) - logger.error('No es un archivo TORRENT. Archivo borrado: ' + str(torrent_path)) - if not json_data.get(root, False): - json_data[root] = 'ERROR' - if scrapertools.find_single_match(file, '^\d+x\d+'): - torrent_json = re.sub(r'\]_\d+.torrent$', '].json', torrent_path) - filetools.remove(torrent_json) - filetools.remove(torrent_path) - continue - - if not scrapertools.find_single_match(torrent_file_deco, '^d\d+:\w+\d+:'): - logger.error('Error de DESCOMPRESIÓN: ' + str(torrent_path)) - k += 1 - errores += [torrent_path] - else: - filetools.write(torrent_path, torrent_file_deco) - j += 1 - descomprimidos += [torrent_path] - else: - #logger.info('Torrent OK. No hace falta descompresión: ' + str(torrent_path)) - h = 0 - - if json_data: - filetools.write(json_error_path, json.dumps(json_data)) - filetools.write(json_error_path_BK, json.dumps(json_data)) - filetools.write(json_path, json.dumps({"torrent_verify": True})) - except: - logger.error('Error en el proceso de VERIFICACIÓN de los .torrents') - logger.error(traceback.format_exc()) - - logger.error(str(i) + ' archivos .torrent revisados. / ' + str(j) + ' descomporimidos / ' + str(k) + ' errores') - if descomprimidos: - logger.error('Lista de .torrents DESCOMPRIMIDOS: ' + str(descomprimidos)) - if errores: - logger.error('Lista de .torrents en ERROR: ' + str(errores)) - - def regenerate_clones(): logger.info() import json from core import videolibrarytools """ - Regenera los archivos .json que ha sido machacado con la migración. También borrar los archivos tvshow.nfo en - películas. + Regenerate .json files that have been crushed with migration. Also delete tvshow.nfo files in films. - Método para uso temporal y controlado + Temporary and controlled use method """ try: - #Localiza los paths donde dejar el archivo .json de control, y de la Videoteca + # Find the paths where to leave the control .json file, and the Video Library json_path = filetools.exists(filetools.join(config.get_runtime_path(), 'verify_cached_torrents.json')) if json_path: - logger.info('Videoteca reparada anteriormente: NOS VAMOS') + logger.info('Previously repaired video library: WE ARE GOING') return False json_path = filetools.join(config.get_runtime_path(), 'verify_cached_torrents.json') - filetools.write(json_path, json.dumps({"CINE_verify": True})) #Evita que se lance otro proceso simultaneo + filetools.write(json_path, json.dumps({"CINE_verify": True})) # Prevents another simultaneous process from being launched json_error_path = filetools.join(config.get_runtime_path(), 'error_cached_torrents.json') json_error_path_BK = filetools.join(config.get_runtime_path(), 'error_cached_torrents_BK.json') - videolibrary_path = config.get_videolibrary_path() #Calculamos el path absoluto a partir de la Videoteca + videolibrary_path = config.get_videolibrary_path() # We calculate the absolute path from the Video Library movies = config.get_setting("folder_movies") series = config.get_setting("folder_tvshows") - torrents_movies = filetools.join(videolibrary_path, config.get_setting("folder_movies")) #path de CINE - torrents_series = filetools.join(videolibrary_path, config.get_setting("folder_tvshows")) #path de SERIES + torrents_movies = filetools.join(videolibrary_path, config.get_setting("folder_movies")) # path of CINE + torrents_series = filetools.join(videolibrary_path, config.get_setting("folder_tvshows")) # path the SERIES - #Cargamos en .json de Newpct1 para ver las listas de valores en settings + # We load in .json from Newpct1 to see the lists of values ​​in settings fail_over_list = channeltools.get_channel_json(channel_py) - for settings in fail_over_list['settings']: #Se recorren todos los settings - if settings['id'] == "clonenewpct1_channels_list": #Encontramos en setting - fail_over_list = settings['default'] #Carga lista de clones + for settings in fail_over_list['settings']: # All settings are scrolled + if settings['id'] == "clonenewpct1_channels_list": # We found in setting + fail_over_list = settings['default'] # Load list of clones #Inicializa variables torren_list = [] torren_list.append(torrents_movies) - #torren_list.append(torrents_series) + # torren_list.append(torrents_series) i = 0 j = 0 k = 0 @@ -2402,7 +1621,7 @@ def regenerate_clones(): errores = [] json_data = dict() - #Recorre las carpetas de CINE y SERIES de la Videoteca, leyendo, descomprimiendo y regrabando los archivos .torrent + # Browse the FILM and SERIES folders of the Video Library, reading, unzipping and rewriting the .torrent files for contentType in torren_list: for root, folders, files in filetools.walk(contentType): nfo = '' @@ -2410,9 +1629,9 @@ def regenerate_clones(): file_list = str(files) logger.error(file_list) - #Borra los archivos Tvshow.nfo y verifica si el .nfo tiene más de un canal y uno es clone Newpct1 + # Delete the Tvshow.nfo files and check if the .nfo has more than one channel and one is clone Newpct1 for file in files: - #logger.info('file - nfos: ' + file) + # logger.info('file - nfos: ' + file) if 'tvshow.nfo' in file: file_path = filetools.join(root, 'tvshow.nfo') filetools.remove(file_path) @@ -2424,97 +1643,97 @@ def regenerate_clones(): try: head_nfo, nfo = videolibrarytools.read_nfo(filetools.join(root, file)) except: - logger.error('** NFO: error de lectura en: ' + file) + logger.error('** NFO: read error in: ' + file) break if not nfo: - logger.error('** NFO: error de lectura en: ' + file) + logger.error('** NFO: read error in: ' + file) break - if nfo.ow_force: #Si tiene ow_force lo quitamos para evitar futuros problemas + if nfo.ow_force: # If you have ow_force we remove it to avoid future problems del nfo.ow_force try: - filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) #actualizo el .nfo + filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) # I update the .nfo except: - logger.error('** NFO: error de escritura en: ' + file) + logger.error('** NFO: typing error in: ' + file) break if '.torrent' not in file_list and nfo.emergency_urls: - del nfo.emergency_urls #Si tiene emergency_urls, lo reseteamos + del nfo.emergency_urls # If you have emergency_urls, we reset it try: - filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) #actualizo el .nfo + filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) # I update the .nfo except: - logger.error('** NFO: error de escritura en: ' + file) + logger.error('** NFO: typing error in: ' + file) break - newpct1 = True #marcamos par a resetar los .jsons + newpct1 = True # we set to reset the .jsons - if len(nfo.library_urls) > 1: #Tiene más de un canal? + if len(nfo.library_urls) > 1: # Do you have more than one channel? for canal, url in nfo.library_urls.items(): canal_json = "[%s].json" % canal - if canal_json not in file_list: #Canal zomby, lo borramos + if canal_json not in file_list: # Zombie channel, we delete it logger.error('pop: ' + canal) nfo.library_urls.pop(canal, None) if nfo.emergency_urls: - del nfo.emergency_urls #Si tiene emergency_urls, lo reseteamos + del nfo.emergency_urls # If you have emergency_urls, we reset it try: - filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) #actualizo el .nfo + filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) # I update the .nfo except: - logger.error('** NFO: error de escritura en: ' + file) + logger.error('** NFO: typing error in: ' + file) break - newpct1 = True #marcamos par a resetar los .jsons + newpct1 = True # we set to reset the .jsons canal_nwepct1 = "'%s'" % canal - if canal_nwepct1 in fail_over_list: #Algún canal es clone de Newpct1 - newpct1 = True #Si es que sí, lo marcamos + if canal_nwepct1 in fail_over_list: # Some channel is clone of Newpct1 + newpct1 = True # If yes, we mark it if nfo.emergency_urls: - del nfo.emergency_urls #Si tiene emergency_urls, lo reseteamos + del nfo.emergency_urls # If you have emergency_urls, we reset it try: - filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) #actualizo el .nfo + filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) # I update the .nfo except: - logger.error('** NFO: error de escritura en: ' + file) + logger.error('** NFO: typing error in: ' + file) break - #Zona para arrelgar los archivos .json + # Area to fill the .json files if not newpct1: continue for file in files: file_path = filetools.join(root, file) if '.json' in file: logger.info('** file: ' + file) - canal_json = scrapertools.find_single_match(file, '\[(\w+)\].json') + canal_json = scrapertools.find_single_match(file, r'\[(\w+)\].json') if canal_json not in nfo.library_urls: - filetools.remove(file_path) #borramos el .json es un zomby + filetools.remove(file_path) # we delete the .json is a zombie item_movie = '' try: - item_movie = Item().fromjson(filetools.read(file_path)) #leemos el .json + item_movie = Item().fromjson(filetools.read(file_path)) # we read the .json except: - logger.error('** JSON: error de lectura en: ' + file) + logger.error('** JSON: read error in: ' + file) continue if not item_movie: - logger.error('** JSON: error de lectura en: ' + file) + logger.error('** JSON: read error in: ' + file) continue if item_movie.emergency_urls: del item_movie.emergency_urls - item_movie.channel = canal_json #mombre del canal - item_movie.category = canal_json.capitalize() #categoría - item_movie.url = nfo.library_urls[canal_json] #url - if scrapertools.find_single_match(item_movie.title, '(.*?)\[\d+.\d+\s*.\s*B\]'): - item_movie.title = scrapertools.find_single_match(item_movie.title, '(.*?)\[\d+.\d+\s*.\s*B\]').strip() #quitamos Size - if item_movie.added_replacing: del item_movie.added_replacing #quitamos traza del canal reemplazado + item_movie.channel = canal_json # channel name + item_movie.category = canal_json.capitalize() # category + item_movie.url = nfo.library_urls[canal_json] # url + if scrapertools.find_single_match(item_movie.title, r'(.*?)\[\d+.\d+\s*.\s*B\]'): + item_movie.title = scrapertools.find_single_match(item_movie.title, r'(.*?)\[\d+.\d+\s*.\s*B\]').strip() # we remove Size + if item_movie.added_replacing: del item_movie.added_replacing # remove trace from the replaced channel try: - filetools.write(file_path, item_movie.tojson()) #Salvamos el nuevo .json de la película + filetools.write(file_path, item_movie.tojson()) # We save the new .json from the movie except: - logger.error('** JSON: error de escritura en: ' + file) + logger.error('** JSON: typing error in: ' + file) else: errores += [file] if '.torrent' in file: - filetools.remove(file_path) #borramos los .torrent salvados + filetools.remove(file_path) # we delete the saved .torrent - logger.error('** Lista de peliculas reparadas: ' + str(errores)) + logger.error('** List of movies repaireds: ' + str(errores)) filetools.write(json_error_path, json.dumps(json_data)) filetools.write(json_error_path_BK, json.dumps(json_data)) filetools.write(json_path, json.dumps({"CINE_verify": True})) except: - filetools.remove(json_path) #borramos el bloqueo para que se pueda lanzar de nuevo - logger.error('Error en el proceso de REPARACIÓN de Videoteca de CINE') + filetools.remove(json_path) # we delete the lock so that it can be launched again + logger.error('CINEMA Video Library REPAIR process error') logger.error(traceback.format_exc()) return True @@ -2522,12 +1741,12 @@ def regenerate_clones(): def dejuice(data): logger.info() - # Metodo para desobfuscar datos de JuicyCodes + # Method to unobtrusive JuicyCodes data import base64 from lib import jsunpack - juiced = scrapertools.find_single_match(data, 'JuicyCodes.Run\((.*?)\);') + juiced = scrapertools.find_single_match(data, r'JuicyCodes.Run\((.*?)\);') b64_data = juiced.replace('+', '').replace('"', '') b64_decode = base64.b64decode(b64_data) dejuiced = jsunpack.unpack(b64_decode) @@ -2539,10 +1758,10 @@ def privatedecrypt(url, headers=None): data = httptools.downloadpage(url, headers=headers, follow_redirects=False).data data = re.sub(r'\n|\r|\t| |
|\s{2,}', "", data) - packed = scrapertools.find_single_match(data, '(eval\(.*?);var') + packed = scrapertools.find_single_match(data, r'(eval\(.*?);var') unpacked = jsunpack.unpack(packed) - server = scrapertools.find_single_match(unpacked, "src:.'(http://\D+)/") - id = scrapertools.find_single_match(unpacked, "src:.'http://\D+/.*?description:.'(.*?).'") + server = scrapertools.find_single_match(unpacked, r"src:.'(http://\D+)/") + id = scrapertools.find_single_match(unpacked, r"src:.'http://\D+/.*?description:.'(.*?).'") if server == '': if 'powvideo' in unpacked: id = scrapertools.find_single_match(unpacked, ",description:.'(.*?).'") diff --git a/specials/videolibrary.py b/specials/videolibrary.py index 12dbb46c..c9f8c192 100644 --- a/specials/videolibrary.py +++ b/specials/videolibrary.py @@ -83,7 +83,7 @@ def list_movies(item, silent=False): # Verify the existence of the channels. If the channel does not exist, ask yourself if you want to remove the links from that channel. for canal_org in new_item.library_urls: - canal = generictools.verify_channel(canal_org) + canal = canal_org try: if canal in ['community', 'downloads']: channel_verify = __import__('specials.%s' % canal, fromlist=["channels.%s" % canal]) @@ -207,7 +207,6 @@ def list_tvshows(item): # Verify the existence of the channels. If the channel does not exist, ask yourself if you want to remove the links from that channel. 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])