diff --git a/plugin.video.alfa/channels/descargas2020.py b/plugin.video.alfa/channels/descargas2020.py index 01aed6bb..98e005c6 100644 --- a/plugin.video.alfa/channels/descargas2020.py +++ b/plugin.video.alfa/channels/descargas2020.py @@ -5,6 +5,7 @@ import sys import urllib import urlparse import datetime +import ast from channelselector import get_thumb from core import httptools @@ -17,15 +18,34 @@ from lib import generictools host = 'http://descargas2020.com/' +#Código para permitir usar un único canal para todas las webs clones de NewPct1 +clone_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte a lista de tuplas +host_index = 0 +host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto +i = 0 +for active_clone, channel_clone, host_clone, contentType_clone, info_clone in clone_list: + if i == host_index: + #channel_clone_name = channel_clone #ACTIVAR CUANDO SE PASE A NEWPCT1 + #host = 'http://%s/' % host_clone #ACTIVAR CUANDO SE PASE A NEWPCT1 + i += 1 + +#Carga de opciones del canal item = Item() if not item.channel: item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/') +channel_clone_name = scrapertools.find_single_match(host, r'(\w+)\.com\/') #QUITAR CUANDO SE PASE A NEWPCT1 __modo_grafico__ = config.get_setting('modo_grafico', item.channel) modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel) + def mainlist(item): logger.info() + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] thumb_pelis = get_thumb("channels_movie.png") @@ -64,20 +84,40 @@ def settingCanal(item): def submenu(item): logger.info() itemlist = [] - + try: data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) except: - logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) - return itemlist #Algo no funciona, pintamos lo que tenemos - data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") - data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com - + pass + + host_alt = host host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") patron = '
  • .*?(.*?)' - if "pelisyseries.com" in host and item.extra == "varios": #compatibilidad con mispelisy.series.com - data = ' Documentales' + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú + item, data = generictools.fail_over_newpct1(item, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + elif item.channel_alt: #Si ha habido fail-over, lo comento + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] caído')) + + host_alt = host.replace(item.channel_alt, item.channel) + del item.channel_alt + if item.url_alt: del item.url_alt + + #data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + #data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + + host_dom = host_alt.replace("https://", "").replace("http://", "").replace("www.", "") + patron = '
  • .*?(.*?)' + if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = ' Documentales' else: if data: data = scrapertools.get_match(data, patron) @@ -104,10 +144,10 @@ def submenu(item): Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra)) if item.extra == "peliculas": - itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host + "peliculas-hd/4kultrahd/", extra=item.extra)) + itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) itemlist.append( - Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host + "peliculas-hd/4kultrahd/", extra=item.extra)) - + Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) + return itemlist @@ -203,7 +243,8 @@ def listado(item): #logger.debug("patron: " + patron + " / fichas: " + fichas) # Identifico la página actual y el total de páginas para el pie de página - total_pag = scrapertools.find_single_match(data,'Last<\/a><\/li>') + patron_last_page = 'Last<\/a><\/li>' + total_pag = scrapertools.find_single_match(data, patron_last_page) if not item.post_num: post_num = 1 @@ -419,6 +460,9 @@ def listado(item): def listado_busqueda(item): logger.info() + + host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/') + itemlist = [] cnt_tot = 40 # Poner el num. máximo de items por página. Dejamos que la web lo controle cnt_title = 0 # Contador de líneas insertadas en Itemlist @@ -449,17 +493,24 @@ def listado_busqueda(item): #Máximo num. de líneas permitidas por TMDB. Máx de 5 páginas por Itemlist para no degradar el rendimiento while cnt_title <= cnt_tot and cnt_next < 5: + pattern = '' % item.pattern #seleccionamos el bloque que nos interesa try: data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data) except: - logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) - return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos - cnt_next += 1 - if not data: #Si la web está caída salimos sin dar error - logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) + pass + + cnt_next += 1 + if not data or not scrapertools.find_single_match(data, pattern): + logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data) + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú + item, data = generictools.fail_over_newpct1(item, pattern) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + elif item.channel_alt: #Si ha habido fail-over, lo comento + host = host.replace(item.channel_alt, item.channel) #Obtiene la dirección de la próxima página, si la hay try: @@ -824,6 +875,11 @@ def listado_busqueda(item): def findvideos(item): from core import channeltools logger.info() + + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] # Cualquiera de las tres opciones son válidas @@ -934,9 +990,20 @@ def findvideos(item): try: data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) except: + pass + + patron = 'class="btn-torrent">.*?window.location.href = "(.*?)";' #Patron para .torrent + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data or not scrapertools.find_single_match(data, patron): logger.error("ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url + " / DATA: " + data) + + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el vídeo + item, data = generictools.fail_over_newpct1(item, patron) + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("$!", "#!").replace("'", "\"").replace("ñ", "ñ").replace("//pictures", "/pictures") @@ -948,6 +1015,8 @@ def findvideos(item): else: item.title = re.sub(r'\s\[\d+,?\d*?\s\w[b|B]\]', '', item.title) #Quitamos size de título, si lo traía item.title = '%s [%s]' % (item.title, size) #Agregamos size al final del título + if size: + size = size.replace('GB', 'G B').replace('Gb', 'G b').replace('MB', 'M B').replace('Mb', 'M b') item.quality = re.sub(r'\s\[\d+,?\d*?\s\w[b|B]\]', '', item.quality) #Quitamos size de calidad, si lo traía #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB @@ -957,7 +1026,6 @@ def findvideos(item): item_local = item.clone() # obtenemos la url torrent - patron = 'class="btn-torrent">.*?window.location.href = "(.*?)";' item_local.url = scrapertools.find_single_match(data, patron) if not item_local.url: #error logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) @@ -969,17 +1037,17 @@ def findvideos(item): #Ahora pintamos el link del Torrent, si lo hay if item_local.url: # Hay Torrent ? - item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.quality, str(item_local.language)) #Preparamos título de Torrent + if size: + quality = '%s [%s]' % (item_local.quality, size) #Agregamos size al final del título + else: + quality = item_local.quality + item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (quality, str(item_local.language)) #Preparamos título de Torrent item_local.title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', item_local.title).strip() #Quitamos etiquetas vacías item_local.title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', item_local.title).strip() #Quitamos colores vacíos item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Servidor - if size: - quality = '%s [%s]' % (item_local.quality, size) #Agregamos size al final del título - else: - quality = item_local.quality - + itemlist.append(item_local.clone(quality=quality)) #Pintar pantalla logger.debug("TORRENT: " + item_local.url + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / tamaño: " + size + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) @@ -1163,9 +1231,20 @@ def findvideos(item): def episodios(item): logger.info() + + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] + # Obtener la información actualizada de la Serie. TMDB es imprescindible para Videoteca + if not item.infoLabels['tmdb_id']: + tmdb.set_infoLabels(item, True) + max_temp = 1 + if item.infoLabels['number_of_seasons']: + max_temp = item.infoLabels['number_of_seasons'] y = [] if modo_ultima_temp and item.library_playcounts: #Averiguar cuantas temporadas hay en Videoteca patron = 'season (\d+)' @@ -1173,16 +1252,30 @@ def episodios(item): for x in matches: y += [int(x)] max_temp = max(y) - - # Obtener la información actualizada de la Serie. TMDB es imprescindible para Videoteca - if not item.infoLabels['tmdb_id']: - tmdb.set_infoLabels(item, True) - + data = '' try: data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) - except: #Algún error de proceso, salimos - logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea" + item.url) + patron = '' % "buscar-list" # item.pattern + data_alt = '' + if data: data_alt = scrapertools.get_match(data, patron) + except: #Algún error de proceso + pass + + if "pelisyseries.com" in item.url: + pattern = ']*>
    ]+>(?P.*?)?<\/h3>.*?<\/li>' + else: + pattern = ']*>]+>(?P.*?)?<\/h2>' + + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data_alt or not scrapertools.find_single_match(data_alt, pattern): + logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea: " + item.url) + + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el vídeo + item, data = generictools.fail_over_newpct1(item, patron, pattern) + + if not data: #No se ha encontrado ningún canal activo para este vídeo + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) return itemlist @@ -1209,7 +1302,8 @@ def episodios(item): list_pages = [item.url] season = max_temp - if item.library_playcounts or item.tmdb_stat: #Comprobamos si realmente sabemos el num. máximo de temporadas + #Comprobamos si realmente sabemos el num. máximo de temporadas + if item.library_playcounts or (item.infoLabels['number_of_seasons'] and item.tmdb_stat): num_temporadas_flag = True else: num_temporadas_flag = False @@ -1226,11 +1320,11 @@ def episodios(item): if not data: raise except: - logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + data) + logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + str(data)) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos - if "pelisyseries.com" in host: + if "pelisyseries.com" in item.url: pattern = ']*>
    ]+>(?P.*?)?<\/h3>.*?<\/li>' else: pattern = ']*>]+>(?P.*?)?<\/h2>' @@ -1245,7 +1339,7 @@ def episodios(item): #Empezamos a generar cada episodio for url, thumb, info in matches: - if "pelisyseries.com" in host: #En esta web están en diferente orden + if "pelisyseries.com" in item.url: #En esta web están en diferente orden interm = url url = thumb thumb = interm @@ -1273,6 +1367,10 @@ def episodios(item): if scrapertools.find_single_match(info, '\[\d{3}\]'): info = re.sub(r'\[(\d{3}\])', r'[Cap.\1', info) + elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?[c|C]ap.*?\.(?P\d+)?.*?(?:(?P\d+))\]?\[(?P\w+)?(?P\w+)\]?'): + pattern = 'Temp.*?(?P\d+).*?[c|C]ap.*?\.(?P\d+)?.*?(?:(?P\d+))\]?\[(?P\w+)?(?P\w+)\]?' + elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?(?P\d{2})?(?:.*?(?P\d{2}))?.*?(?P\[\w+.*)\[.*?\]?'): + pattern = 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?(?P\d{2})?(?:.*?(?P\d{2}))?.*?(?P\[\w+.*)\[.*?\]?' elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?Cap\w?\.\s\d?(?P\d{2})(?:.*?(?P\d{2}))?.*?\[(?P\w+)\]?'): pattern = 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?Cap\w?\.\s\d?(?P\d{2})(?:.*?(?P\d{2}))?.*?\[(?P\w+)\]?' elif scrapertools.find_single_match(info, '\[Cap.\d{2}_\d{2}\]'): @@ -1312,11 +1410,9 @@ def episodios(item): except: logger.error("ERROR 07: EPISODIOS: Error en número de Temporada o Episodio: " + " / TEMPORADA/EPISODIO: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / MATCHES: " + str(matches)) - #logger.error("TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / " + str(match['episode2']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern) if num_temporadas_flag and match['season'] != season and match['season'] > max_temp + 1: #Si el num de temporada está fuera de control, se trata pone en num. de temporada actual - #logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern + " / MATCHES: " + str(matches)) - #logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern) + logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern + " / MATCHES: " + str(matches)) match['season'] = season item_local.contentSeason = season else: @@ -1331,11 +1427,11 @@ def episodios(item): item_local.quality = match['quality'] #Si hay quality se coge, si no, la de la serie item_local.quality = item_local.quality.replace("ALTA DEFINICION", "HDTV") - if match['lang'] and estado == False: - match['lang'] = match['lang'].replace("- ", "") + if match['lang'] and (estado == False or "especia" in str(match['lang']).lower()): + match['lang'] = match['lang'].replace("- ", "").replace("[", "").replace("]", "") item_local.infoLabels['episodio_titulo'] = match['lang'] item_local.infoLabels['title'] = item_local.infoLabels['episodio_titulo'] - + item_local.contentEpisodeNumber = match['episode'] if match['episode'] == 0: match['episode'] = 1 #Evitar errores en Videoteca @@ -1381,6 +1477,8 @@ def episodios(item): # Pasada por TMDB y clasificación de lista por temporada y episodio tmdb.set_infoLabels(itemlist, True) + + #logger.debug(item) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_episodios(item, itemlist) @@ -1395,7 +1493,7 @@ def actualizar_titulos(item): from platformcode import launcher item = generictools.update_title(item) #Llamamos al método que actualiza el título con tmdb.find_and_set_infoLabels - + #Volvemos a la siguiente acción en el canal return launcher.run(item) @@ -1403,6 +1501,9 @@ def actualizar_titulos(item): def search(item, texto): logger.info("search:" + texto) # texto = texto.replace(" ", "+") + + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() try: item.post = "q=%s" % texto diff --git a/plugin.video.alfa/channels/elitetorrent.py b/plugin.video.alfa/channels/elitetorrent.py index 42e69560..235a7c40 100644 --- a/plugin.video.alfa/channels/elitetorrent.py +++ b/plugin.video.alfa/channels/elitetorrent.py @@ -12,6 +12,7 @@ from core import servertools from core.item import Item from platformcode import config, logger from core import tmdb +from lib import generictools host = 'http://www.elitetorrent.biz' @@ -39,7 +40,12 @@ def submenu(item): logger.info() itemlist = [] - data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) + try: + data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) + except: + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #Algo no funciona, pintamos lo que tenemos patron = '
    .*?<\/div>' #Menú principal data1 = scrapertools.get_match(data, patron) @@ -48,6 +54,10 @@ def submenu(item): patron = ')", "", httptools.downloadpage(item.url).data) - + try: + data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) + except: + logger.error("ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + if not data: #Si la web está caída salimos sin dar error + logger.error("ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + patron = '
    .*?<\/nav><\/div><\/div>' data = scrapertools.find_single_match(data, patron) @@ -90,6 +109,11 @@ def listado(item): patron += '="dig2">(.*?)<\/span><\/div>' #tipo tamaño matches = re.compile(patron, re.DOTALL).findall(data) + if not matches and not '503 Backend fetch failed' in data: #error + logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) @@ -102,7 +126,7 @@ def listado(item): item_local.url = urlparse.urljoin(host, scrapedurl) item_local.thumbnail = urlparse.urljoin(host, scrapedthumbnail) - if "---" in scrapedcalidad: #Scrapeamos y limpiamos calidades + if "---" in scrapedcalidad: #limpiamos calidades scrapedcalidad = '' if "microhd" in title.lower(): item_local.quality = "microHD" @@ -137,13 +161,18 @@ def listado(item): if item_local.extra == "peliculas": #preparamos Item para películas if "/serie" in scrapedurl or "/serie" in item.url: continue + if not "/serie" in scrapedurl and not "/serie" in item.url: item_local.contentType = "movie" - item_local.contentTitle = title.strip() - else: #preparamos Item para series + item_local.contentTitle = title + item_local.extra = "peliculas" + + if item_local.extra == "series": #preparamos Item para series if not "/serie" in scrapedurl and not "/serie" in item.url: continue + if "/serie" in scrapedurl or "/serie" in item.url: item_local.contentType = "episode" - epi_mult = scrapertools.find_single_match(item_local.url, r'cap.*?-\d+-(al-\d+)') + item_local.extra = "series" + epi_mult = scrapertools.find_single_match(item_local.url, r'cap.*?-\d+-al-(\d+)') item_local.contentSeason = scrapertools.find_single_match(item_local.url, r'temp.*?-(\d+)') item_local.contentEpisodeNumber = scrapertools.find_single_match(item_local.url, r'cap.*?-(\d+)') if not item_local.contentSeason: @@ -154,87 +183,35 @@ def listado(item): item_local.contentSeason = 1 if item_local.contentEpisodeNumber < 1: item_local.contentEpisodeNumber = 1 - item_local.contentSerieName = title.strip() + item_local.contentSerieName = title if epi_mult: - title = '%s, %s' % (epi_mult.replace("-", " "), title) + title = "%sx%s al %s -" % (item_local.contentSeason, str(item_local.contentEpisodeNumber).zfill(2), str(epi_mult).zfill(2)) #Creamos un título con el rango de episodios + else: + title = '%sx%s ' % (str(item_local.contentSeason), str(item_local.contentEpisodeNumber).zfill(2)) item_local.action = "findvideos" item_local.title = title.strip() item_local.infoLabels['year'] = "-" + #Pasamos a TMDB cada Item, para evitar el efecto memoria de tmdb + if item.category: #Si este campo no existe es que viene de la primera pasada de una búsqueda global, pasamos + tmdb.set_infoLabels(item_local, True) + itemlist.append(item_local.clone()) #Pintar pantalla + #if not item.category: #Si este campo no existe es que viene de la primera pasada de una búsqueda global + # return itemlist #Retornamos sin pasar por la fase de maquillaje para ahorra tiempo + #Pasamos a TMDB la lista completa Itemlist - tmdb.set_infoLabels(itemlist, True) + #tmdb.set_infoLabels(itemlist, True) - # Pasada para maquillaje de los títulos obtenidos desde TMDB - for item_local in itemlist: - title = item_local.title - - # Si TMDB no ha encontrado el vídeo limpiamos el año - if item_local.infoLabels['year'] == "-": - item_local.infoLabels['year'] = '' - item_local.infoLabels['aired'] = '' - - # Preparamos el título para series, con los núm. de temporadas, si las hay - if item_local.contentType == "season" or item_local.contentType == "tvshow": - item_local.contentTitle= '' - if item_local.contentType == "episode": - if scrapertools.find_single_match(title, r'(al\s\d+)'): - item_local.infoLabels['episodio_titulo'] = scrapertools.find_single_match(title, r'(al\s\d+)') - if scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})'): - item_local.infoLabels['year'] = scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})') - - rating = '' - if item_local.infoLabels['rating'] and item_local.infoLabels['rating'] != '0.0': - rating = float(item_local.infoLabels['rating']) - rating = round(rating, 1) - - #Ahora maquillamos un poco los titulos dependiendo de si se han seleccionado títulos inteleigentes o no - if not config.get_setting("unify"): #Si Titulos Inteligentes NO seleccionados: - if item_local.contentType == "episode": - if item_local.infoLabels['episodio_titulo']: - title = '%sx%s %s, %s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (str(item_local.contentSeason), str(item_local.contentEpisodeNumber).zfill(2), item_local.infoLabels['episodio_titulo'], item_local.contentSerieName, item_local.infoLabels['year'], rating, item_local.quality, str(item_local.language)) - else: - title = '%sx%s %s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (str(item_local.contentSeason), str(item_local.contentEpisodeNumber).zfill(2), item_local.contentSerieName, item_local.infoLabels['year'], rating, item_local.quality, str(item_local.language)) - item_local.infoLabels['title'] = item_local.contentSerieName - - elif item_local.contentType == "season" or item_local.contentType == "tvshow": - if item_local.extra == "series": - title = '%s - Temporada %s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.contentSerieName, item_local.contentSeason, item_local.infoLabels['year'], rating, item_local.quality, str(item_local.language)) - else: - title = '%s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.contentSerieName, item_local.infoLabels['year'], rating, item_local.quality, str(item_local.language)) - - elif item_local.contentType == "movie": - title = '%s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (title, str(item_local.infoLabels['year']), rating, item_local.quality, str(item_local.language)) - - if config.get_setting("unify"): #Si Titulos Inteligentes SÍ seleccionados: - if item_local.contentType == "episode": - if item_local.infoLabels['episodio_titulo']: - item_local.infoLabels['episodio_titulo'] = '%s, %s [%s] [%s]' % (item_local.infoLabels['episodio_titulo'], item_local.contentSerieName, item_local.infoLabels['year'], rating) - else: - item_local.infoLabels['episodio_titulo'] = '%s [%s] [%s]' % (item_local.contentSerieName, item_local.infoLabels['year'], rating) - item_local.infoLabels['title'] = item_local.contentSerieName - - elif item_local.contentType == "season" or item_local.contentType == "tvshow": - if item_local.extra == "series": - title = '%s - Temporada %s [%s] [%s]' % (item_local.contentSerieName, item_local.contentSeason, item_local.infoLabels['year'], rating) - else: - title = '%s' % (item_local.contentSerieName) - - item_local.infoLabels['episodio_titulo'] = item_local.infoLabels['episodio_titulo'].replace("--", "").replace("[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() - title = title.replace("--", "").replace("[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() - title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', title).strip() - title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', title).strip() - - item_local.title = title - - logger.debug("url: " + item_local.url + " / title: " + item_local.title + " / content title: " + item_local.contentTitle + "/" + item_local.contentSerieName + " / calidad: " + item_local.quality + " / year: " + str(item_local.infoLabels['year'])) + #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB + item, itemlist = generictools.post_tmdb_listado(item, itemlist) # Extrae el paginador patron = '
    .*?)", "", httptools.downloadpage(item.url).data) - - patron = '
    .*?<\/nav><\/div><\/div>' - data = scrapertools.find_single_match(data, patron) - - patron = '
  • .*?)", "", httptools.downloadpage(item.url).data) + #Bajamos los datos de la página + try: + data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) + except: + logger.error("ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #data = unicode(data, "utf-8", errors="replace") #Añadimos el tamaño para todos size = scrapertools.find_single_match(item.quality, '\s\[(\d+,?\d*?\s\w[b|B]s)\]') - item.quality = re.sub('\s\[\d+,?\d*?\s\w[b|B]s\]', '', item.quality) #Quitamos size de calidad, si lo traía if size: item.title = re.sub('\s\[\d+,?\d*?\s\w[b|B]s\]', '', item.title) #Quitamos size de título, si lo traía item.title = '%s [%s]' % (item.title, size) #Agregamos size al final del título + item.quality = re.sub('\s\[\d+,?\d*?\s\w[b|B]s\]', '', item.quality) #Quitamos size de calidad, si lo traía + item.quality = '%s [%s]' % (item.quality, size) #Agregamos size al final de calidad + item.quality = item.quality.replace("G", "G ").replace("M", "M ") #Se evita la palabra reservada en Unify - #Limpiamos de año y rating de episodios - if item.infoLabels['episodio_titulo']: - item.infoLabels['episodio_titulo'] = re.sub(r'\s?\[.*?\]', '', item.infoLabels['episodio_titulo']) - if item.infoLabels['episodio_titulo'] == item.contentSerieName: - item.infoLabels['episodio_titulo'] = '' - if item.infoLabels['aired'] and item.contentType == "episode": - item.infoLabels['year'] = scrapertools.find_single_match(str(item.infoLabels['aired']), r'\/(\d{4})') - - #Generamos una copia de Item para trabajar sobre ella - item_local = item.clone() - - patron = '
    >": itemlist.pop() diff --git a/plugin.video.alfa/channels/grantorrent.py b/plugin.video.alfa/channels/grantorrent.py index f2534bd9..e4e4de76 100644 --- a/plugin.video.alfa/channels/grantorrent.py +++ b/plugin.video.alfa/channels/grantorrent.py @@ -286,20 +286,20 @@ def listado(item): title = title.replace("Dual", "").replace("dual", "").replace("Subtitulada", "").replace("subtitulada", "").replace("Subt", "").replace("subt", "").replace("Sub", "").replace("sub", "").replace("(Reparado)", "").replace("(Proper)", "").replace("(proper)", "").replace("Proper", "").replace("proper", "").replace("(Latino)", "").replace("Latino", "") title = title.replace("- HDRip", "").replace("(HDRip)", "").replace("- Hdrip", "").replace("(microHD)", "").replace("(DVDRip)", "").replace("(HDRip)", "").replace("(BR-LINE)", "").replace("(HDTS-SCREENER)", "").replace("(BDRip)", "").replace("(BR-Screener)", "").replace("(DVDScreener)", "").replace("TS-Screener", "").replace(" TS", "").replace(" Ts", "") - if item_local.extra == "peliculas": #preparamos Item para películas + if item_local.extra == "peliculas": #preparamos Item para películas if "/serie" in scrapedurl or "/serie" in item.url: continue item_local.contentType = "movie" item_local.action = "findvideos" - title = scrapertools.htmlclean(title) #Quitamos html restante + title = scrapertools.htmlclean(title) #Quitamos html restante item_local.contentTitle = title.strip() - else: #preparamos Item para series + else: #preparamos Item para series if not "/serie" in scrapedurl and not "/serie" in item.url: continue - if modo_serie_temp == 1: #si está en modo Serie + if modo_serie_temp == 1: #si está en modo Serie item_local.contentType = "tvshow" item_local.extra = "tvshow" - else: #si no, en modo temporada + else: #si no, en modo temporada item_local.contentType = "season" item_local.extra = "season" item_local.action = "episodios" @@ -378,6 +378,7 @@ def findvideos(item): if item.contentType == "episode": #En Series los campos están en otro orden. No hay size, en su lugar sxe temp_epi = quality quality = size + size = '' contentSeason = '' contentEpisodeNumber = '' try: #obtenemos la temporada y episodio de la página y la comparamos con Item @@ -423,17 +424,11 @@ def findvideos(item): item_local.quality = quality if "temporada" in temp_epi.lower(): item_local.quality = '%s [Temporada]' % item_local.quality - if size and item_local.contentType != "episode": + #if size and item_local.contentType != "episode": + if size: size = size.replace(".", ",").replace("B,", " B").replace("b,", " b") item_local.quality = '%s [%s]' % (item_local.quality, size) - - #Limpiamos de año y rating de episodios - if item.infoLabels['episodio_titulo']: - item.infoLabels['episodio_titulo'] = re.sub(r'\s?\[.*?\]', '', item.infoLabels['episodio_titulo']) - item.infoLabels['episodio_titulo'] = item.infoLabels['episodio_titulo'].replace(item.wanted, '') - if item.infoLabels['aired'] and item.contentType == "episode": - item.infoLabels['year'] = scrapertools.find_single_match(str(item.infoLabels['aired']), r'\/(\d{4})') - + #Salvamos la url del .torrent if scrapedurl: item_local.url = scrapedurl @@ -446,7 +441,7 @@ def findvideos(item): itemlist.append(item_local.clone()) #Pintar pantalla - logger.debug("TORRENT: " + item_local.url + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality) + #logger.debug("TORRENT: " + item_local.url + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality) #logger.debug(item_local) return itemlist @@ -495,14 +490,14 @@ def episodios(item): matches = re.compile(patron, re.DOTALL).findall(str(item.library_playcounts)) max_temp = int(max(matches)) - if not item.library_playcounts: #no viene de Videoteca, se ponen valores de configuración o de la pasada anterior + if not item.library_playcounts: #no viene de Videoteca, se ponen valores de configuración o de la pasada anterior if not item.contentType: if modo_serie_temp == 0: item.contentType = "season" else: item.contentType = "tvshow" if item.contentSeason: - item.contentSeason = 0 + del item.infoLabels['season'] elif max_temp < item.infoLabels["number_of_seasons"]: #Si tenemos en .nfo menos temporadas, Temp. item.contentType = "season" diff --git a/plugin.video.alfa/channels/mejortorrent.py b/plugin.video.alfa/channels/mejortorrent.py index aad82d98..50c29870 100755 --- a/plugin.video.alfa/channels/mejortorrent.py +++ b/plugin.video.alfa/channels/mejortorrent.py @@ -12,6 +12,7 @@ from core import servertools from core.item import Item from platformcode import config, logger from core import tmdb +from lib import generictools host = "http://www.mejortorrent.com" @@ -84,20 +85,29 @@ def alfabeto(item): def listado(item): logger.info() itemlist = [] - url_next_page ='' # Controlde paginación - cnt_tot = 30 # Poner el num. máximo de items por página + url_next_page ='' # Control de paginación + cnt_tot = 30 # Poner el num. máximo de items por página if item.category: del item.category if item.totalItems: del item.totalItems + try: # La url de Películas por orden Alfabético tiene un formato distinto - if item.extra == "peliculas" and item.tipo: - url = item.url.split("?") - data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(url[0], post=url[1]).data) - else: - data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) + if item.extra == "peliculas" and item.tipo: + url = item.url.split("?") + data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(url[0], post=url[1]).data) + else: + data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) + except: + logger.error("ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + if not data: #Si la web está caída salimos sin dar error + logger.error("ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos # En este canal las url's y los títulos tienen diferente formato dependiendo del contenido if item.extra == "peliculas" and item.tipo: #Desde Lista Alfabética @@ -115,6 +125,7 @@ def listado(item): item.action = "findvideos" item.contentType = "movie" pag = True #Sí hay paginación + cnt_tot = 25 # Poner el num. máximo de items por página. Parece que hay 50 elif item.extra == "series" and item.tipo: patron = "()" patron_enlace = "\/serie-descargar-torrent*.-\d+-?\d+-(.*?)\.html" @@ -163,10 +174,35 @@ def listado(item): else: cnt_pag = item.cnt_pag del item.cnt_pag + if not item.cnt_pag_num: + cnt_pag_num = 0 # Número de página actual + else: + cnt_pag_num = item.cnt_pag_num + del item.cnt_pag_num matches = re.compile(patron, re.DOTALL).findall(data) - matches_cnt = len(matches) + if not matches and not 'Se han encontrado 0 resultados.' in data: #error + logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + + #Capturamos el num. de la última página para informala a pié de página. Opción para páginas sin paginación + if pag == False: + item.last_page = (len(matches) / cnt_tot) + 1 + + if not item.last_page and pag: #Capturamos el num. de la última página para informala a pié de página + item.last_page = -1 + patron_next_page = " Siguiente >> <\/a>" + url_next_page = urlparse.urljoin(item.url, scrapertools.find_single_match(data, patron_next_page)) + url_last_page = re.sub(r"\d+$", "9999", url_next_page) + data_last = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(url_last_page).data) + patron_last_page = "(\d+)<\/span>" + if item.extra == "documentales": + item.last_page = int(scrapertools.find_single_match(data_last, patron_last_page)) + else: + item.last_page = int(scrapertools.find_single_match(data_last, patron_last_page)) * (len(matches) / cnt_tot) + if matches_cnt > cnt_tot and item.extra == "documentales" and pag: item.next_page = '' if item.next_page != 'b': @@ -189,10 +225,10 @@ def listado(item): modo = 'next' if item.next_page: del item.next_page - + #logger.debug(data) - #logger.debug("PATRON1: " + patron + " / ") - #logger.debug(matches) + logger.debug("PATRON1: " + patron + " / ") + logger.debug(matches) # Primera pasada # En la primera pasada se obtiene una información básica del título a partir de la url @@ -212,6 +248,10 @@ def listado(item): del item_local.pag if item_local.text_color: del item_local.text_color + if item_local.last_page: + del item_local.last_page + if item_local.cnt_pag_num: + del item_local.cnt_pag_num item_local.title = '' item_local.context = "['buscar_trailer']" @@ -257,13 +297,16 @@ def listado(item): real_title = scrapertools.find_single_match(scrapedurl, patron_title_se) real_title = real_title.replace("-", " ") item_local.contentSeason = scrapertools.find_single_match(scrapedurl, '.*?-(\d{1,2})-Temp.*?\.html') - + item_local.contentSerieName = real_title if not item_local.contentSeason: item_local.contentSeason = 1 else: item_local.contentTitle = item_local.title + if item_local.contentType == "episode": + item_local.title = '%sx%s ' % (item_local.contentSeason, item_local.contentEpisodeNumber) + itemlist.append(item_local.clone()) #logger.debug(item_local) @@ -277,9 +320,10 @@ def listado(item): cnt_pag = 0 else: cnt_pag += cnt_tot + cnt_pag_num += 1 - #logger.debug("PATRON2: " + patron_title) - #logger.debug(matches) + logger.debug("PATRON2: " + patron_title) + logger.debug(matches) cnt = 0 for scrapedtitle, notused, scrapedinfo in matches: item_local = itemlist[cnt] #Vinculamos item_local con la entrada de la lista itemlist (más fácil de leer) @@ -287,8 +331,11 @@ def listado(item): # Limpiamos títulos, Sacamos datos de calidad, audio y lenguaje scrapedtitle = re.sub('\r\n', '', scrapedtitle).decode('iso-8859-1').encode('utf8').strip() title = scrapedtitle + title = title.replace("á", "a").replace("é", "e").replace("í", "i").replace("ó", "o").replace("ú", "u").replace("ü", "u").replace("�", "ñ").replace("ñ", "ñ") - title_subs = "" + title_subs = [] + + #Determinamos y marcamos idiomas distintos del castellano item_local.language = [] if "[subs" in title.lower() or "[vos" in title.lower() or "v.o.s" in title.lower(): item_local.language += ["VOS"] @@ -299,25 +346,25 @@ def listado(item): title = title.replace("Castellano", "").replace("castellano", "").replace("inglés", "").replace("ingles", "").replace("Inglés", "").replace("Ingles", "") if "3d" in title.lower(): #Reservamos info para después de TMDB - title_subs = " 3D" + item_local.quality += " 3D" title = title.replace(" [3d]", "").replace(" 3d", "").replace(" [3D]", "").replace(" 3D", "") - if "temp" in title.lower(): #Reservamos info de Temporada para después de TMDB - title_subs = "[Temp.]" + #if "temp" in title.lower(): #Reservamos info de Temporada para después de TMDB + # title_subs += ["Temporada"] if "audio" in title.lower(): #Reservamos info de audio para después de TMDB - title_subs = '[%s]' % scrapertools.find_single_match(title, r'(\[[a|A]udio.*?\])') + title_subs += ['[%s]' % scrapertools.find_single_match(title, r'(\[[a|A]udio.*?\])')] title = re.sub(r'\[[a|A]udio.*?\]', '', title) if "[dual" in title.lower(): - title_subs = "[Dual]" + item_local.language[0:0] = ["DUAL"] title = title = re.sub(r'\[D|dual.*?\]', '', title) if scrapertools.find_single_match(title, r'-\s[m|M].*?serie'): title = re.sub(r'-\s[m|M].*?serie', '', title) - title_subs += "[Miniserie]" + title_subs += ["Miniserie"] if title.endswith('.'): title = title[:-1] - title = title.replace("á", "a", 1).replace("é", "e", 1).replace("í", "i", 1).replace("ó", "o", 1).replace("ú", "u", 1).replace("ü", "u", 1) + if not title: - title = "dummy" + title = "SIN TÍTULO" title = scrapertools.remove_htmltags(title) info = scrapedinfo.decode('iso-8859-1').encode('utf8') @@ -330,13 +377,13 @@ def listado(item): if item_local.quality: title = re.sub(r'[\[|\(]\d+.*?[\)|\]]', '', title) # Quitar la calidad del título info = "" - item_local.contentSerieName = scrapertools.find_single_match(title, '(.*?) - \d.*?') + item_local.contentSerieName = scrapertools.find_single_match(title, '(.*?) - \d.*?').strip() if not item_local.contentSerieName: - item_local.contentSerieName = title - item_local.infoLabels['tvshowtitle'] = item_local.contentSerieName - item_local.infoLabels['title'] = '' + item_local.contentSerieName = title.strip() + if item_local.infoLabels['title']: + del item_local.infoLabels['title'] if not item_local.contentSerieName: - item_local.contentSerieName = "dummy" + item_local.contentSerieName = "SIN TITULO" if info != "" and not item_local.quality: item_local.quality = info @@ -355,30 +402,28 @@ def listado(item): item_local.quality = "4K" title = title.replace("4k-hdr", "").replace("4K-HDR", "").replace("hdr", "").replace("HDR", "").replace("4k", "").replace("4K", "") title = title.replace("(", "").replace(")", "").replace("[", "").replace("]", "").strip() - item_local.title = title - - if item_local.extra == "peliculas": + if item_local.extra == "peliculas": + item_local.title = title item_local.contentTitle = title + elif item_local.contentType != "episode": + item_local.title = title + item_local.title = '%s ' % item_local.contentSerieName if "saga" in item_local.contentTitle.lower() or "saga" in item_local.contentSerieName.lower(): item_local.contentTitle = item_local.contentTitle.replace("Saga ", "").replace("Saga", "") item_local.contentSerieName = item_local.contentSerieName.replace("Saga ", "").replace("Saga", "") - title_subs = "[Saga]" + title_subs += ["Saga"] if "colecc" in item_local.contentTitle.lower() or "colecc" in item_local.contentSerieName.lower(): item_local.contentTitle = item_local.contentTitle.replace("Coleccion ", "").replace("Coleccion", "") item_local.contentSerieName = item_local.contentSerieName.replace("Coleccion ", "").replace("Coleccion", "") - title_subs = "[Coleccion]" - - if "3D" in title_subs: #Si es 3D lo añadimos a calidad - item_local.quality = item_local.quality + title_subs - title_subs = '' + title_subs += ["Coleccion"] - # Guardamos temporalmente info extra, si lo hay - item_local.extra = item_local.extra + title_subs + #Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB + item_local.title_subs = title_subs #Salvamos y borramos el número de temporadas porque TMDB a veces hace tonterias. Lo pasamos como serie completa if item_local.contentSeason and (item_local.contentType == "season" or item_local.contentType == "tvshow"): - item_local.SeasonBackup = item_local.contentSeason + item_local.contentSeason_save = item_local.contentSeason del item_local.infoLabels['season'] #logger.debug(item_local) @@ -386,91 +431,22 @@ def listado(item): cnt += 1 if cnt == len(itemlist): break - - #Llamamos a TMDB para que complete InfoLabels + + #Llamamos a TMDB para que complete InfoLabels desde itemlist. Mejor desde itemlist porque envía las queries en paralelo tmdb.set_infoLabels(itemlist, __modo_grafico__) - # Pasada para maqullaje de los títulos obtenidos desde TMDB - for item_local in itemlist: - title = item_local.title - title_subs = "" - temporada = "" - title_subs = scrapertools.find_single_match(item_local.extra, r'(\[.*?\])') - if "[Temp.]" in item_local.extra: - temporada = "[Temp.]" - title_subs = "" - if "Audio" in item_local.extra or "audio" in item_local.extra: - title_subs = '[%s]' % scrapertools.find_single_match(item_local.extra, r'\[[a|A]udio (.*?)\]') - item_local.extra = re.sub(r'\[.*?\]', '', item_local.extra) - - # Si TMDB no ha encontrado el vídeo limpiamos el año - if item_local.infoLabels['year'] == "-": - item_local.infoLabels['year'] = '' - item_local.infoLabels['aired'] = '' - - # Preparamos el título para series, con los núm. de temporadas, si las hay - if item_local.contentType == "season" or item_local.contentType == "tvshow": - item_local.contentTitle= '' - - rating = '' - if item_local.infoLabels['rating'] and item_local.infoLabels['rating'] != '0.0': - rating = float(item_local.infoLabels['rating']) - rating = round(rating, 1) - - #Cambiamos el título si son capítulos múltiples - if scrapertools.find_single_match(item_local.url, r'\d+x\d+.*?(\w+.*?\d+x\d+)'): - item_local.infoLabels['episodio_titulo'] = scrapertools.find_single_match(item_local.url, r'\d+x\d+.*?(\w+.*?\d+x\d+)').replace("-", " ") - - #Ahora maquillamos un poco los titulos dependiendo de si se han seleccionado títulos inteleigentes o no - if not config.get_setting("unify"): #Si Titulos Inteligentes NO seleccionados: - if item_local.contentType == "episode": - if item_local.infoLabels['episodio_titulo']: - title = '%sx%s %s, %s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (str(item_local.SeasonBackup), str(item_local.contentEpisodeNumber).zfill(2), item_local.infoLabels['episodio_titulo'], item_local.contentSerieName, scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})'), rating, item_local.quality, str(item_local.language)) - else: - title = '%sx%s %s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (str(item_local.SeasonBackup), str(item_local.contentEpisodeNumber).zfill(2), item_local.contentSerieName, scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})'), rating, item_local.quality, str(item_local.language)) - item_local.infoLabels['title'] = item_local.contentSerieName - - elif item_local.contentType == "season" or item_local.contentType == "tvshow": - if item_local.extra == "series" or temporada == "[Temp.]": - title = '%s - Temporada %s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.contentSerieName, str(item_local.SeasonBackup), scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})'), rating, item_local.quality, str(item_local.language)) - else: - title = '%s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.contentSerieName, scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})'), rating, item_local.quality, str(item_local.language)) - - elif item_local.contentType == "movie": - title = '%s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (title, str(item_local.infoLabels['year']), rating, item_local.quality, str(item_local.language)) - - if config.get_setting("unify"): #Si Titulos Inteligentes SÍ seleccionados: - if item_local.contentType == "episode": - if item_local.infoLabels['episodio_titulo']: - item_local.infoLabels['episodio_titulo'] = '%s, %s [%s]' % (item_local.infoLabels['episodio_titulo'], item_local.contentSerieName, scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})')) - else: - item_local.infoLabels['episodio_titulo'] = '%s [%s]' % (item_local.contentSerieName, scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})')) - item_local.infoLabels['title'] = item_local.contentSerieName - - elif item_local.contentType == "season" or item_local.contentType == "tvshow": - if item_local.extra == "series" or temporada == "[Temp.]": - title = '%s - Temporada %s' % (item_local.contentSerieName, item_local.SeasonBackup) - else: - title = '%s' % (item_local.contentSerieName) - title_subs = title_subs.replace("[", "-").replace("]", "-") - - if item_local.SeasonBackup: - del item_local.SeasonBackup - item_local.infoLabels['episodio_titulo'] = item_local.infoLabels['episodio_titulo'].replace("--", "").replace(" []", "").replace("()", "").replace("(/)", "").replace("[/]", "") - title = title.replace("--", "").replace(" []", "").replace("()", "").replace("(/)", "").replace("[/]", "") - title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', title) - title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', title) - item_local.title = title + title_subs - item_local.contentTitle += title_subs #añadimos info adicional para display - - #logger.debug(item_local) + #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB + item, itemlist = generictools.post_tmdb_listado(item, itemlist) if len(itemlist) == 0: itemlist.append(Item(channel=item.channel, action="mainlist", title="No se ha podido cargar el listado")) else: if url_next_page: + title_foot = str(cnt_pag_num) + if item.last_page > 0: + title_foot += ' de %s' % str(item.last_page) itemlist.append( - Item(channel=item.channel, action="listado", title="[COLOR gold][B]Pagina siguiente >>[/B][/COLOR]", url=url_next_page, next_page=next_page, cnt_pag=cnt_pag, pag=pag, modo=modo, extra=item.extra, tipo=item.tipo)) + Item(channel=item.channel, action="listado", title="[COLOR gold][B]Pagina siguiente >> [/B][/COLOR]" + title_foot, url=url_next_page, next_page=next_page, cnt_pag=cnt_pag, pag=pag, modo=modo, extra=item.extra, tipo=item.tipo, last_page=item.last_page, cnt_pag_num=cnt_pag_num)) #logger.debug(url_next_page + " / " + next_page + " / " + str(matches_cnt) + " / " + str(cnt_pag) + " / " + str(pag) + " / " + modo + " / " + item.extra + " / " + str(item.tipo)) @@ -484,9 +460,17 @@ def listado_busqueda(item): cnt_tot = 30 # Poner el num. máximo de items por página pag = False # No hay paginación en la web category = "" # Guarda la categoria que viene desde una busqueda global - - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data) - #logger.debug(data) + + try: + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data) + except: + logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + if not data: #Si la web está caída salimos sin dar error + logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos # busca series y Novedades patron = "]+>(.*?)<\/a>" @@ -509,6 +493,12 @@ def listado_busqueda(item): patron += "(.*?)<\/td>" patron_enlace = "\/doc-descargar-torrent-\d+-\d+-(.*?)\.html" matches += re.compile(patron, re.DOTALL).findall(data) + matches_cnt = len(matches) + + if not matches and not 'Se han encontrado 0 resultados.' in data: #error + logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #logger.debug("MATCHES: ") #logger.debug(matches) @@ -519,8 +509,15 @@ def listado_busqueda(item): else: cnt_pag = item.cnt_pag del item.cnt_pag + if not item.cnt_pag_num: + cnt_pag_num = 0 # Número de página actual + else: + cnt_pag_num = item.cnt_pag_num + del item.cnt_pag_num - matches_cnt = len(matches) + #Capturamos el num. de la última página para informala a pié de página + last_page = (len(matches) / cnt_tot) + 1 + if item.next_page != 'b': if matches_cnt > cnt_pag + cnt_tot: url_next_page = item.url @@ -546,6 +543,7 @@ def listado_busqueda(item): cnt_pag += cnt_tot else: cnt_pag += matches_cnt + cnt_pag_num += 1 for scrapedurl, scrapedtitle, scrapedinfo in matches: # Creamos "item_local" y lo limpiamos un poco de algunos restos de item @@ -559,8 +557,11 @@ def listado_busqueda(item): del item_local.totalItems if item_local.text_color: del item_local.text_color + if item_local.cnt_pag_num: + del item_local.cnt_pag_num item_local.contentThumbnail = '' item_local.thumbnail = '' + item_local.title = '' item_local.context = "['buscar_trailer']" item_local.infoLabels['year'] = '-' # Al no saber el año, le ponemos "-" y TmDB lo calcula automáticamente @@ -569,11 +570,11 @@ def listado_busqueda(item): title = scrapedtitle title = title.replace("á", "a").replace("é", "e").replace("í", "i").replace("ó", "o").replace("ú", "u").replace("ü", "u").replace("�", "ñ").replace("ñ", "ñ") - title_subs = "" + title_subs = [] #Determinamos y marcamos idiomas distintos del castellano item_local.language = [] - if "[vos" in title.lower() or "v.o.s" in title.lower() or "vo" in title.lower(): + if "[subs" in title.lower() or "[vos" in title.lower() or "v.o.s" in title.lower() or "vo" in title.lower(): item_local.language += ["VOS"] title = title.replace(" [Subs. integrados]", "").replace(" [subs. Integrados]", "").replace(" [VOSE", "").replace(" [VOS", "").replace(" (V.O.S.E)", "").replace(" VO", "") if "latino" in title.lower() or "argentina" in title.lower(): @@ -581,28 +582,29 @@ def listado_busqueda(item): title = title.replace(" Latino", "").replace(" latino", "").replace(" Argentina", "").replace(" argentina", "") title = title.replace("Castellano", "").replace("castellano", "").replace("inglés", "").replace("ingles", "").replace("Inglés", "").replace("Ingles", "") - if "3d" in title or "3D" in title: #Reservamos info de subtítulos para después de TMDB - title_subs = "[3D]" + if "3d" in title or "3D" in title: #Reservamos info para después de TMDB + item_local.quality += " 3D" title = title.replace(" [3d]", "").replace(" 3d", "").replace(" [3D]", "").replace(" 3D", "") - if "Temp" in title or "temp" in title: #Reservamos info de Temporada para después de TMDB - title_subs = "[Temp.]" - if "Audio" in title or "audio" in title: #Reservamos info de subtítulos para después de TMDB - title_subs = '[%s]' % scrapertools.find_single_match(title, r'(\[[a|A]udio.*?\])') + #if "temp" in title.lower(): #Reservamos info de Temporada para después de TMDB + # title_subs += ["Temporada"] + if "audio" in title.lower(): #Reservamos info de audio para después de TMDB + title_subs += ['[%s]' % scrapertools.find_single_match(title, r'(\[[a|A]udio.*?\])')] title = re.sub(r'\[[a|A]udio.*?\]', '', title) - if "[Dual" in title or "[dual" in title: - title_subs = "[Dual]" - title = title = re.sub(r'\[[D|d]ual.*?\]', '', title) + if "[dual" in title.lower(): + item_local.language[0:0] = ["DUAL"] + title = title = re.sub(r'\[D|dual.*?\]', '', title) if scrapertools.find_single_match(title, r'-\s[m|M].*?serie'): title = re.sub(r'-\s[m|M].*?serie', '', title) - title_subs += "[Miniserie]" + title_subs += ["Miniserie"] if title.endswith('.'): title = title[:-1] if not title: - title = "dummy" + title = "SIN TÍTULO" title = scrapertools.remove_htmltags(title) + # Ahora preparamos el título y la calidad tanto para series como para documentales y películas if item.extra == "novedades" and ("/serie-" in scrapedurl or "/doc-" in scrapedurl): item_local.quality = scrapertools.find_single_match(scrapedtitle, r'.*?\[(.*?)\]') else: @@ -621,22 +623,20 @@ def listado_busqueda(item): item_local.contentType = "season" title = re.sub(r'\[\d+.*?\]', '', title) # Quitar la calidad del título - item_local.contentSerieName = scrapertools.find_single_match(title, '(.*?) - \d.*?') + item_local.contentSerieName = scrapertools.find_single_match(title, '(.*?) - \d.*?').strip() if not item_local.contentSerieName: - item_local.contentSerieName = title - if item_local.contentSerieName.endswith(' '): - item_local.contentSerieName = item_local.contentSerieName[:-1] + item_local.contentSerieName = title.strip() + if item_local.infoLabels['title']: + del item_local.infoLabels['title'] title = item_local.contentSerieName item_local.title = title - item_local.infoLabels['tvshowtitle'] = item_local.contentSerieName - item_local.infoLabels['title'] = '' if not item_local.contentSerieName: - item_local.contentSerieName = "dummy" + item_local.contentSerieName = "SIN TITULO" item_local.contentSeason = scrapertools.find_single_match(scrapedurl, '.*?-(\d{1,2})-Temp.*?\.html') if not item_local.contentSeason: item_local.contentSeason = 1 - if "(HDRip" in title or "(BR" in title or "(HDRip" in title or "(VHSRip" in title or "(DVDRip" in title or "(FullB" in title or "(fullb" in title or "(Blu" in title or "(4K" in title or "(4k" in title or "(HEVC" in title or "(IMAX" in title or "Extendida" in title or "[720p]" in title or "[1080p]" in title: + if "(hdrip" in title.lower() or "(br" in title.lower() or "(vhsrip" in title.lower() or "(dvdrip" in title.lower() or "(fullb" in title.lower() or "(blu" in title.lower() or "(4k" in title.lower() or "(hevc" in title.lower() or "(imax" in title.lower() or "extendida" in title.lower() or "[720p]" in title.lower() or "[1080p]" in title.lower(): if not item_local.quality: item_local.quality = scrapertools.find_single_match(title, r'\(.*?\)?\(.*?\)') if not item_local.quality: @@ -644,10 +644,10 @@ def listado_busqueda(item): title = re.sub(r'\(.*?\)?\(.*?\)', '', title) title = re.sub(r'[\[|\(].*?[\)|\]]', '', title) if not item_local.quality: - if "FullBluRay" in title or "fullbluray" in title: + if "fullbluray" in title.lower(): item_local.quality = "FullBluRay" title = title.replace("FullBluRay", "").replace("fullbluray", "") - if "4K" in title or "4k" in title or "HDR" in title or "hdr" in title: + if "4k" in title.lower() or "hdr" in title.lower(): item_local.quality = "4K" title = title.replace("4k-hdr", "").replace("4K-HDR", "").replace("hdr", "").replace("HDR", "").replace("4k", "").replace("4K", "") title = title.replace("(", "").replace(")", "").replace("[", "").replace("]", "").strip() @@ -659,21 +659,21 @@ def listado_busqueda(item): item_local.contentType = "movie" item_local.contentTitle = title - if "Saga" in item_local.contentTitle or "Saga" in item_local.contentSerieName: - item_local.contentTitle = item_local.contentTitle.replace("Saga ", "").replace("Saga", "") - item_local.contentSerieName = item_local.contentSerieName.replace("Saga ", "").replace("Saga", "") - title_subs = "[Saga]" - if "Colecc" in item_local.contentTitle or "Colecc" in item_local.contentSerieName: - item_local.contentTitle = item_local.contentTitle.replace("Coleccion ", "").replace("Coleccion", "") - item_local.contentSerieName = item_local.contentSerieName.replace("Coleccion ", "").replace("Coleccion", "") - title_subs = "[Coleccion]" + if "saga" in item_local.contentTitle.lower() or "saga" in item_local.contentSerieName.lower(): + item_local.contentTitle = item_local.contentTitle.replace("Saga ", "").replace("Saga", "") + item_local.contentSerieName = item_local.contentSerieName.replace("Saga ", "").replace("Saga", "") + title_subs += ["Saga"] + if "colecc" in item_local.contentTitle.lower() or "colecc" in item_local.contentSerieName.lower(): + item_local.contentTitle = item_local.contentTitle.replace("Coleccion ", "").replace("Coleccion", "") + item_local.contentSerieName = item_local.contentSerieName.replace("Coleccion ", "").replace("Coleccion", "") + title_subs += ["Coleccion"] - # Guardamos temporalmente info de subtítulos, si lo hay - item_local.extra = item_local.extra + title_subs + #Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB + item_local.title_subs = title_subs #Salvamos y borramos el número de temporadas porque TMDB a veces hace tonterias. Lo pasamos como serie completa if item_local.contentSeason and (item_local.contentType == "season" or item_local.contentType == "tvshow"): - item_local.SeasonBackup = item_local.contentSeason + item_local.contentSeason_save = item_local.contentSeason del item_local.infoLabels['season'] itemlist.append(item_local.clone()) @@ -686,67 +686,15 @@ def listado_busqueda(item): #Llamamos a TMDB para que complete InfoLabels desde itemlist. Mejor desde itemlist porque envía las queries en paralelo tmdb.set_infoLabels(itemlist, __modo_grafico__) - # Pasada para maqullaje de los títulos obtenidos desde TMDB - for item_local in itemlist: - title = item_local.title - title_subs = "" - temporada = "" - title_subs = scrapertools.find_single_match(item_local.extra, r'(\[.*?\])') - if "[Temp.]" in item_local.extra: - temporada = "[Temp.]" - title_subs = "" - if "Audio" in item_local.extra or "audio" in item_local.extra: - title_subs = '[%s]' % scrapertools.find_single_match(item_local.extra, r'\[[a|A]udio (.*?)\]') - item_local.extra = re.sub(r'\[.*?\]', '', item_local.extra) - - # Si TMDB no ha encontrado el vídeo limpiamos el año - if item_local.infoLabels['year'] == "-": - item_local.infoLabels['year'] = '' - item_local.infoLabels['aired'] = '' - - # Preparamos el título para series, con los núm. de temporadas, si las hay - if item_local.contentType == "season" or item_local.contentType == "tvshow": - item_local.contentTitle= '' - - rating = '' - if item_local.infoLabels['rating'] and item_local.infoLabels['rating'] != '0.0': - rating = float(item_local.infoLabels['rating']) - rating = round(rating, 1) - - # Ahora maquillamos un poco los titulos dependiendo de si se han seleccionado títulos inteleigentes o no - if not config.get_setting("unify"): #Si Titulos Inteligentes NO seleccionados: - if item_local.contentType == "season" or item_local.contentType == "tvshow": - if item_local.extra == "series" or temporada == "[Temp.]": - title = '%s - Temporada %s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.contentSerieName, str(item_local.SeasonBackup), scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})'), rating, item_local.quality, str(item_local.language)) - else: - title = '%s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.contentSerieName, scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})'), rating, item_local.quality, str(item_local.language)) - - elif item_local.contentType == "movie": - title = '%s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (title, str(item_local.infoLabels['year']), rating, item_local.quality, str(item_local.language)) - - if config.get_setting("unify"): #Si Titulos Inteligentes SÍ seleccionados: - if item_local.contentType == "season" or item_local.contentType == "tvshow": - if item_local.extra == "series" or temporada == "[Temp.]": - title = '%s - Temporada %s' % (item_local.contentSerieName, item_local.SeasonBackup) - else: - title = '%s' % (item_local.contentSerieName) - title_subs = title_subs.replace("[", "-").replace("]", "-") - - if item_local.SeasonBackup: - del item_local.SeasonBackup - item_local.infoLabels['episodio_titulo'] = item_local.infoLabels['episodio_titulo'].replace("--", "").replace(" []", "").replace("()", "").replace("(/)", "").replace("[/]", "") - title = title.replace("--", "").replace(" []", "").replace("()", "").replace("(/)", "").replace("[/]", "") - title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', title) - title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', title) - item_local.title = title + title_subs - item_local.contentTitle += title_subs #añadimos info adicional para display - - #logger.debug("title=[" + item_local.title + "], url=[" + item_local.url + "], calidad=[" + item_local.quality + "]") - #logger.debug(item_local) - + #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB + item, itemlist = generictools.post_tmdb_listado(item, itemlist) + if url_next_page: + title_foot = str(cnt_pag_num) + if last_page > 0: + title_foot += ' de %s' % str(last_page) itemlist.append( - Item(channel=item.channel, action="listado_busqueda", title="[COLOR gold][B]Pagina siguiente >>[/B][/COLOR]", url=url_next_page, next_page=next_page, cnt_pag=cnt_pag, pag=pag, modo=modo, extra=item.extra)) + Item(channel=item.channel, action="listado_busqueda", title="[COLOR gold][B]Pagina siguiente >> [/B][/COLOR]" + title_foot, url=url_next_page, next_page=next_page, cnt_pag=cnt_pag, pag=pag, modo=modo, extra=item.extra, cnt_pag_num=cnt_pag_num)) #logger.debug(url_next_page + " / " + next_page + " / " + str(matches_cnt) + " / " + str(cnt_pag) + " / " + str(pag) + " / " + modo + " / " + item.extra )) @@ -757,44 +705,28 @@ def findvideos(item): logger.info() itemlist = [] - # Saber si estamos en una ventana emergente lanzada desde una viñeta del menú principal, - # con la función "play_from_library" - unify_status = False + #Bajamos los datos de la página try: - import xbmc - if xbmc.getCondVisibility('Window.IsMedia') == 1: - unify_status = config.get_setting("unify") + if item.post: #Puede traer datos para una llamada "post". De momento usado para documentales, pero podrían ser series + data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url, post=item.post).data) + data = data.replace('"', "'") + patron = ">Pincha.*?)", "", httptools.downloadpage(item.url).data) + patron = " item.infoLabels['temporada_num_episodios']: - item.infoLabels['temporada_num_episodios'] = num_episodios - - if item.post: #Puede traer datos para una llamada "post". De momento usado para documentales, pero podrían ser series - data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url, post=item.post).data) - data = data.replace('"', "'") - patron = ">Pincha.*?)", "", httptools.downloadpage(item.url).data) - patron = ")", "", httptools.downloadpage(url).data) + try: + torrent_data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(url).data) + except: #error + logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / URL: " + url + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #logger.debug(torrent_data) item_local.url = scrapertools.get_match(torrent_data, ">Pincha.*?)", "", httptools.downloadpage(item.url).data) + try: + data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) + except: #Algún error de proceso, salimos + logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea" + item.url) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) + return itemlist #Datos para crear el Post. Usado para documentales total_capis = scrapertools.find_single_match(data, "") @@ -909,6 +813,10 @@ def episodios(item): patron += " 1: @@ -958,86 +866,30 @@ def episodios(item): itemlist.append(item_local.clone()) - # Llamamos a TMDB para que complete el episodio en InfoLabels - tmdb.set_infoLabels(itemlist, True) if len(itemlist) > 1: - itemlist = sorted(itemlist, key=lambda it: (int(it.contentSeason), int(it.contentEpisodeNumber))) + itemlist = sorted(itemlist, key=lambda it: (int(it.contentSeason), int(it.contentEpisodeNumber))) #clasificamos - # Pasada para maqullaje de los títulos obtenidos desde TMDB - num_episodios = 1 - num_episodios_lista = [0] - num_temporada = 1 - num_episodios_flag = True - for item_local in itemlist: - - # Si no hay datos de TMDB, pongo los datos locales que conozco - if item_local.infoLabels['aired']: - item_local.infoLabels['year'] = scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})') + # Pasada por TMDB y clasificación de lista por temporada y episodio + tmdb.set_infoLabels(itemlist, True) - # Si son episodios múltiples, se toman los datos locales para nombre de episodio - if scrapertools.find_single_match(item_local.title, r'\d+x\d+.*?(\w+.*?\d+x\d+)'): - item_local.infoLabels['episodio_titulo'] = scrapertools.find_single_match(item_local.title, r'\d+x\d+.*?(\w+.*?\d+x\d+)') - item_local.title = '%sx%s - %s' % (str(item_local.contentSeason), str(item_local.contentEpisodeNumber).zfill(2), item_local.infoLabels['episodio_titulo']) - else: - item_local.title = '%sx%s -' % (str(item_local.contentSeason), str(item_local.contentEpisodeNumber).zfill(2)) - - rating = '' - if item_local.infoLabels['rating'] and item_local.infoLabels['rating'] != '0.0': - rating = float(item_local.infoLabels['rating']) - rating = round(rating, 1) - - #Salvamos en número de episodios de la temporada - if num_temporada != item_local.contentSeason: - num_temporada = item_local.contentSeason - num_episodios = 0 - if item_local.infoLabels['temporada_num_episodios']: - num_episodios = item_local.infoLabels['temporada_num_episodios'] - - #Preparamos el título para que sea compatible con Añadir Serie a Videoteca - if item_local.infoLabels['episodio_titulo']: - if "al" in item_local.title: #Si son episodios múltiples, ponemos nombre de serie - item_local.title = '%s - %s' % (item_local.title, item_local.contentSerieName) - item_local.infoLabels['episodio_titulo'] = '%s %s' % (scrapertools.find_single_match(item_local.title, r'(al \d+)'), item_local.contentSerieName) - else: - item_local.title = '%s %s' % (item_local.title, item_local.infoLabels['episodio_titulo']) - if item_local.infoLabels['year']: - item_local.infoLabels['episodio_titulo'] = '%s [%s]' % (item_local.infoLabels['episodio_titulo'], item_local.infoLabels['year']) - if rating: - item_local.infoLabels['episodio_titulo'] = '%s [%s]' % (item_local.infoLabels['episodio_titulo'], rating) - else: - item_local.title = '%s %s' % (item_local.title, item_local.contentSerieName) - item_local.infoLabels['episodio_titulo'] = '%s [%s] [%s]' % (item_local.contentSerieName, item_local.infoLabels['year'], rating) - item_local.infoLabels['title'] = item_local.infoLabels['episodio_titulo'] - - item_local.title = '%s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.title, item_local.infoLabels['year'], rating, item_local.quality, str(item_local.language)) - - #Quitamos campos vacíos - item_local.infoLabels['episodio_titulo'] = item_local.infoLabels['episodio_titulo'].replace(" []", "") - item_local.title = item_local.title.replace(" []", "") - item_local.title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', item_local.title) - item_local.title = re.sub(r'\s\[COLOR \w+\]-\[\/COLOR\]', '', item_local.title) - if num_episodios < item_local.contentEpisodeNumber: - num_episodios = item_local.contentEpisodeNumber - if num_episodios and not item_local.infoLabels['temporada_num_episodios']: - item_local.infoLabels['temporada_num_episodios'] = num_episodios - num_episodios_flag = False - num_episodios_lista[item_local.contentSeason:] = [num_episodios] - - #logger.debug("title=[" + item_local.title + "], url=[" + item_local.url + "], item=[" + str(item_local) + "]") - - if not num_episodios_flag: #Si el num de episodios no está informado, acualizamos episodios de toda la serie - for item_local in itemlist: - item_local.infoLabels['temporada_num_episodios'] = num_episodios_lista[item_local.contentSeason] - - if config.get_videolibrary_support() and len(itemlist) > 0: - title = '' - if item_local.infoLabels['temporada_num_episodios']: - title = ' [Temp. de %s ep.]' % item_local.infoLabels['temporada_num_episodios'] - - itemlist.append(item.clone(title="[COLOR yellow]Añadir esta serie a la videoteca[/COLOR]" + title, action="add_serie_to_library", extra="episodios")) + #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB + item, itemlist = generictools.post_tmdb_episodios(item, itemlist) return itemlist + +def actualizar_titulos(item): + logger.info() + itemlist = [] + + from platformcode import launcher + + item = generictools.update_title(item) #Llamamos al método que actualiza el título con tmdb.find_and_set_infoLabels + + #Volvemos a la siguiente acción en el canal + return launcher.run(item) + + def search(item, texto): itemlist = [] logger.info("search:" + texto) @@ -1054,6 +906,7 @@ def search(item, texto): for line in sys.exc_info(): logger.error("%s" % line) return [] + def newest(categoria): logger.info() diff --git a/plugin.video.alfa/channels/mispelisyseries.py b/plugin.video.alfa/channels/mispelisyseries.py index 33d7a336..0d207a6f 100644 --- a/plugin.video.alfa/channels/mispelisyseries.py +++ b/plugin.video.alfa/channels/mispelisyseries.py @@ -5,6 +5,7 @@ import sys import urllib import urlparse import datetime +import ast from channelselector import get_thumb from core import httptools @@ -17,15 +18,34 @@ from lib import generictools host = 'http://mispelisyseries.com/' +#Código para permitir usar un único canal para todas las webs clones de NewPct1 +clone_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte a lista de tuplas +host_index = 0 +host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto +i = 0 +for active_clone, channel_clone, host_clone, contentType_clone, info_clone in clone_list: + if i == host_index: + #channel_clone_name = channel_clone #ACTIVAR CUANDO SE PASE A NEWPCT1 + #host = 'http://%s/' % host_clone #ACTIVAR CUANDO SE PASE A NEWPCT1 + i += 1 + +#Carga de opciones del canal item = Item() if not item.channel: item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/') +channel_clone_name = scrapertools.find_single_match(host, r'(\w+)\.com\/') #QUITAR CUANDO SE PASE A NEWPCT1 __modo_grafico__ = config.get_setting('modo_grafico', item.channel) modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel) + def mainlist(item): logger.info() + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] thumb_pelis = get_thumb("channels_movie.png") @@ -64,20 +84,40 @@ def settingCanal(item): def submenu(item): logger.info() itemlist = [] - + try: data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) except: - logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) - return itemlist #Algo no funciona, pintamos lo que tenemos - data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") - data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com - + pass + + host_alt = host host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") patron = '
  • .*?(.*?)' - if "pelisyseries.com" in host and item.extra == "varios": #compatibilidad con mispelisy.series.com - data = ' Documentales' + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú + item, data = generictools.fail_over_newpct1(item, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + elif item.channel_alt: #Si ha habido fail-over, lo comento + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] caído')) + + host_alt = host.replace(item.channel_alt, item.channel) + del item.channel_alt + if item.url_alt: del item.url_alt + + #data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + #data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + + host_dom = host_alt.replace("https://", "").replace("http://", "").replace("www.", "") + patron = '
  • .*?(.*?)' + if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = ' Documentales' else: if data: data = scrapertools.get_match(data, patron) @@ -104,10 +144,10 @@ def submenu(item): Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra)) if item.extra == "peliculas": - itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host + "peliculas-hd/4kultrahd/", extra=item.extra)) + itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) itemlist.append( - Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host + "peliculas-hd/4kultrahd/", extra=item.extra)) - + Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) + return itemlist @@ -203,7 +243,8 @@ def listado(item): #logger.debug("patron: " + patron + " / fichas: " + fichas) # Identifico la página actual y el total de páginas para el pie de página - total_pag = scrapertools.find_single_match(data,'Last<\/a><\/li>') + patron_last_page = 'Last<\/a><\/li>' + total_pag = scrapertools.find_single_match(data, patron_last_page) if not item.post_num: post_num = 1 @@ -419,6 +460,9 @@ def listado(item): def listado_busqueda(item): logger.info() + + host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/') + itemlist = [] cnt_tot = 40 # Poner el num. máximo de items por página. Dejamos que la web lo controle cnt_title = 0 # Contador de líneas insertadas en Itemlist @@ -449,17 +493,24 @@ def listado_busqueda(item): #Máximo num. de líneas permitidas por TMDB. Máx de 5 páginas por Itemlist para no degradar el rendimiento while cnt_title <= cnt_tot and cnt_next < 5: + pattern = '' % item.pattern #seleccionamos el bloque que nos interesa try: data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data) except: - logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) - return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos - cnt_next += 1 - if not data: #Si la web está caída salimos sin dar error - logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) + pass + + cnt_next += 1 + if not data or not scrapertools.find_single_match(data, pattern): + logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data) + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú + item, data = generictools.fail_over_newpct1(item, pattern) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + elif item.channel_alt: #Si ha habido fail-over, lo comento + host = host.replace(item.channel_alt, item.channel) #Obtiene la dirección de la próxima página, si la hay try: @@ -824,6 +875,11 @@ def listado_busqueda(item): def findvideos(item): from core import channeltools logger.info() + + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] # Cualquiera de las tres opciones son válidas @@ -934,9 +990,20 @@ def findvideos(item): try: data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) except: + pass + + patron = 'class="btn-torrent">.*?window.location.href = "(.*?)";' #Patron para .torrent + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data or not scrapertools.find_single_match(data, patron): logger.error("ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url + " / DATA: " + data) + + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el vídeo + item, data = generictools.fail_over_newpct1(item, patron) + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("$!", "#!").replace("'", "\"").replace("ñ", "ñ").replace("//pictures", "/pictures") @@ -948,6 +1015,8 @@ def findvideos(item): else: item.title = re.sub(r'\s\[\d+,?\d*?\s\w[b|B]\]', '', item.title) #Quitamos size de título, si lo traía item.title = '%s [%s]' % (item.title, size) #Agregamos size al final del título + if size: + size = size.replace('GB', 'G B').replace('Gb', 'G b').replace('MB', 'M B').replace('Mb', 'M b') item.quality = re.sub(r'\s\[\d+,?\d*?\s\w[b|B]\]', '', item.quality) #Quitamos size de calidad, si lo traía #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB @@ -957,7 +1026,6 @@ def findvideos(item): item_local = item.clone() # obtenemos la url torrent - patron = 'class="btn-torrent">.*?window.location.href = "(.*?)";' item_local.url = scrapertools.find_single_match(data, patron) if not item_local.url: #error logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) @@ -969,17 +1037,17 @@ def findvideos(item): #Ahora pintamos el link del Torrent, si lo hay if item_local.url: # Hay Torrent ? - item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.quality, str(item_local.language)) #Preparamos título de Torrent + if size: + quality = '%s [%s]' % (item_local.quality, size) #Agregamos size al final del título + else: + quality = item_local.quality + item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (quality, str(item_local.language)) #Preparamos título de Torrent item_local.title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', item_local.title).strip() #Quitamos etiquetas vacías item_local.title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', item_local.title).strip() #Quitamos colores vacíos item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Servidor - if size: - quality = '%s [%s]' % (item_local.quality, size) #Agregamos size al final del título - else: - quality = item_local.quality - + itemlist.append(item_local.clone(quality=quality)) #Pintar pantalla logger.debug("TORRENT: " + item_local.url + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / tamaño: " + size + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) @@ -1163,9 +1231,20 @@ def findvideos(item): def episodios(item): logger.info() + + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] + # Obtener la información actualizada de la Serie. TMDB es imprescindible para Videoteca + if not item.infoLabels['tmdb_id']: + tmdb.set_infoLabels(item, True) + max_temp = 1 + if item.infoLabels['number_of_seasons']: + max_temp = item.infoLabels['number_of_seasons'] y = [] if modo_ultima_temp and item.library_playcounts: #Averiguar cuantas temporadas hay en Videoteca patron = 'season (\d+)' @@ -1173,16 +1252,30 @@ def episodios(item): for x in matches: y += [int(x)] max_temp = max(y) - - # Obtener la información actualizada de la Serie. TMDB es imprescindible para Videoteca - if not item.infoLabels['tmdb_id']: - tmdb.set_infoLabels(item, True) - + data = '' try: data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) - except: #Algún error de proceso, salimos - logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea" + item.url) + patron = '' % "buscar-list" # item.pattern + data_alt = '' + if data: data_alt = scrapertools.get_match(data, patron) + except: #Algún error de proceso + pass + + if "pelisyseries.com" in item.url: + pattern = ']*>
    ]+>(?P.*?)?<\/h3>.*?<\/li>' + else: + pattern = ']*>]+>(?P.*?)?<\/h2>' + + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data_alt or not scrapertools.find_single_match(data_alt, pattern): + logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea: " + item.url) + + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el vídeo + item, data = generictools.fail_over_newpct1(item, patron, pattern) + + if not data: #No se ha encontrado ningún canal activo para este vídeo + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) return itemlist @@ -1209,7 +1302,8 @@ def episodios(item): list_pages = [item.url] season = max_temp - if item.library_playcounts or item.tmdb_stat: #Comprobamos si realmente sabemos el num. máximo de temporadas + #Comprobamos si realmente sabemos el num. máximo de temporadas + if item.library_playcounts or (item.infoLabels['number_of_seasons'] and item.tmdb_stat): num_temporadas_flag = True else: num_temporadas_flag = False @@ -1226,11 +1320,11 @@ def episodios(item): if not data: raise except: - logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + data) + logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + str(data)) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos - if "pelisyseries.com" in host: + if "pelisyseries.com" in item.url: pattern = ']*>
    ]+>(?P.*?)?<\/h3>.*?<\/li>' else: pattern = ']*>]+>(?P.*?)?<\/h2>' @@ -1245,7 +1339,7 @@ def episodios(item): #Empezamos a generar cada episodio for url, thumb, info in matches: - if "pelisyseries.com" in host: #En esta web están en diferente orden + if "pelisyseries.com" in item.url: #En esta web están en diferente orden interm = url url = thumb thumb = interm @@ -1273,6 +1367,10 @@ def episodios(item): if scrapertools.find_single_match(info, '\[\d{3}\]'): info = re.sub(r'\[(\d{3}\])', r'[Cap.\1', info) + elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?[c|C]ap.*?\.(?P\d+)?.*?(?:(?P\d+))\]?\[(?P\w+)?(?P\w+)\]?'): + pattern = 'Temp.*?(?P\d+).*?[c|C]ap.*?\.(?P\d+)?.*?(?:(?P\d+))\]?\[(?P\w+)?(?P\w+)\]?' + elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?(?P\d{2})?(?:.*?(?P\d{2}))?.*?(?P\[\w+.*)\[.*?\]?'): + pattern = 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?(?P\d{2})?(?:.*?(?P\d{2}))?.*?(?P\[\w+.*)\[.*?\]?' elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?Cap\w?\.\s\d?(?P\d{2})(?:.*?(?P\d{2}))?.*?\[(?P\w+)\]?'): pattern = 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?Cap\w?\.\s\d?(?P\d{2})(?:.*?(?P\d{2}))?.*?\[(?P\w+)\]?' elif scrapertools.find_single_match(info, '\[Cap.\d{2}_\d{2}\]'): @@ -1312,11 +1410,9 @@ def episodios(item): except: logger.error("ERROR 07: EPISODIOS: Error en número de Temporada o Episodio: " + " / TEMPORADA/EPISODIO: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / MATCHES: " + str(matches)) - #logger.error("TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / " + str(match['episode2']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern) if num_temporadas_flag and match['season'] != season and match['season'] > max_temp + 1: #Si el num de temporada está fuera de control, se trata pone en num. de temporada actual - #logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern + " / MATCHES: " + str(matches)) - #logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern) + logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern + " / MATCHES: " + str(matches)) match['season'] = season item_local.contentSeason = season else: @@ -1331,11 +1427,11 @@ def episodios(item): item_local.quality = match['quality'] #Si hay quality se coge, si no, la de la serie item_local.quality = item_local.quality.replace("ALTA DEFINICION", "HDTV") - if match['lang'] and estado == False: - match['lang'] = match['lang'].replace("- ", "") + if match['lang'] and (estado == False or "especia" in str(match['lang']).lower()): + match['lang'] = match['lang'].replace("- ", "").replace("[", "").replace("]", "") item_local.infoLabels['episodio_titulo'] = match['lang'] item_local.infoLabels['title'] = item_local.infoLabels['episodio_titulo'] - + item_local.contentEpisodeNumber = match['episode'] if match['episode'] == 0: match['episode'] = 1 #Evitar errores en Videoteca @@ -1381,6 +1477,8 @@ def episodios(item): # Pasada por TMDB y clasificación de lista por temporada y episodio tmdb.set_infoLabels(itemlist, True) + + #logger.debug(item) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_episodios(item, itemlist) @@ -1395,7 +1493,7 @@ def actualizar_titulos(item): from platformcode import launcher item = generictools.update_title(item) #Llamamos al método que actualiza el título con tmdb.find_and_set_infoLabels - + #Volvemos a la siguiente acción en el canal return launcher.run(item) @@ -1403,6 +1501,9 @@ def actualizar_titulos(item): def search(item, texto): logger.info("search:" + texto) # texto = texto.replace(" ", "+") + + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() try: item.post = "q=%s" % texto diff --git a/plugin.video.alfa/channels/torrentlocura.py b/plugin.video.alfa/channels/torrentlocura.py index 7de6f82e..5bfd66a9 100755 --- a/plugin.video.alfa/channels/torrentlocura.py +++ b/plugin.video.alfa/channels/torrentlocura.py @@ -5,6 +5,7 @@ import sys import urllib import urlparse import datetime +import ast from channelselector import get_thumb from core import httptools @@ -17,15 +18,34 @@ from lib import generictools host = 'http://torrentlocura.com/' +#Código para permitir usar un único canal para todas las webs clones de NewPct1 +clone_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte a lista de tuplas +host_index = 0 +host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto +i = 0 +for active_clone, channel_clone, host_clone, contentType_clone, info_clone in clone_list: + if i == host_index: + #channel_clone_name = channel_clone #ACTIVAR CUANDO SE PASE A NEWPCT1 + #host = 'http://%s/' % host_clone #ACTIVAR CUANDO SE PASE A NEWPCT1 + i += 1 + +#Carga de opciones del canal item = Item() if not item.channel: item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/') +channel_clone_name = scrapertools.find_single_match(host, r'(\w+)\.com\/') #QUITAR CUANDO SE PASE A NEWPCT1 __modo_grafico__ = config.get_setting('modo_grafico', item.channel) modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel) + def mainlist(item): logger.info() + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] thumb_pelis = get_thumb("channels_movie.png") @@ -64,20 +84,40 @@ def settingCanal(item): def submenu(item): logger.info() itemlist = [] - + try: data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) except: - logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) - return itemlist #Algo no funciona, pintamos lo que tenemos - data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") - data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com - + pass + + host_alt = host host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") patron = '
  • .*?(.*?)' - if "pelisyseries.com" in host and item.extra == "varios": #compatibilidad con mispelisy.series.com - data = ' Documentales' + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú + item, data = generictools.fail_over_newpct1(item, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + elif item.channel_alt: #Si ha habido fail-over, lo comento + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] caído')) + + host_alt = host.replace(item.channel_alt, item.channel) + del item.channel_alt + if item.url_alt: del item.url_alt + + #data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + #data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + + host_dom = host_alt.replace("https://", "").replace("http://", "").replace("www.", "") + patron = '
  • .*?(.*?)' + if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = ' Documentales' else: if data: data = scrapertools.get_match(data, patron) @@ -104,10 +144,10 @@ def submenu(item): Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra)) if item.extra == "peliculas": - itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host + "peliculas-hd/4kultrahd/", extra=item.extra)) + itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) itemlist.append( - Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host + "peliculas-hd/4kultrahd/", extra=item.extra)) - + Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) + return itemlist @@ -203,7 +243,8 @@ def listado(item): #logger.debug("patron: " + patron + " / fichas: " + fichas) # Identifico la página actual y el total de páginas para el pie de página - total_pag = scrapertools.find_single_match(data,'Last<\/a><\/li>') + patron_last_page = 'Last<\/a><\/li>' + total_pag = scrapertools.find_single_match(data, patron_last_page) if not item.post_num: post_num = 1 @@ -419,6 +460,9 @@ def listado(item): def listado_busqueda(item): logger.info() + + host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/') + itemlist = [] cnt_tot = 40 # Poner el num. máximo de items por página. Dejamos que la web lo controle cnt_title = 0 # Contador de líneas insertadas en Itemlist @@ -449,17 +493,24 @@ def listado_busqueda(item): #Máximo num. de líneas permitidas por TMDB. Máx de 5 páginas por Itemlist para no degradar el rendimiento while cnt_title <= cnt_tot and cnt_next < 5: + pattern = '' % item.pattern #seleccionamos el bloque que nos interesa try: data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data) except: - logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) - return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos - cnt_next += 1 - if not data: #Si la web está caída salimos sin dar error - logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) + pass + + cnt_next += 1 + if not data or not scrapertools.find_single_match(data, pattern): + logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data) + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú + item, data = generictools.fail_over_newpct1(item, pattern) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + elif item.channel_alt: #Si ha habido fail-over, lo comento + host = host.replace(item.channel_alt, item.channel) #Obtiene la dirección de la próxima página, si la hay try: @@ -824,6 +875,11 @@ def listado_busqueda(item): def findvideos(item): from core import channeltools logger.info() + + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] # Cualquiera de las tres opciones son válidas @@ -934,9 +990,20 @@ def findvideos(item): try: data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) except: + pass + + patron = 'class="btn-torrent">.*?window.location.href = "(.*?)";' #Patron para .torrent + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data or not scrapertools.find_single_match(data, patron): logger.error("ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url + " / DATA: " + data) + + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el vídeo + item, data = generictools.fail_over_newpct1(item, patron) + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("$!", "#!").replace("'", "\"").replace("ñ", "ñ").replace("//pictures", "/pictures") @@ -948,6 +1015,8 @@ def findvideos(item): else: item.title = re.sub(r'\s\[\d+,?\d*?\s\w[b|B]\]', '', item.title) #Quitamos size de título, si lo traía item.title = '%s [%s]' % (item.title, size) #Agregamos size al final del título + if size: + size = size.replace('GB', 'G B').replace('Gb', 'G b').replace('MB', 'M B').replace('Mb', 'M b') item.quality = re.sub(r'\s\[\d+,?\d*?\s\w[b|B]\]', '', item.quality) #Quitamos size de calidad, si lo traía #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB @@ -957,7 +1026,6 @@ def findvideos(item): item_local = item.clone() # obtenemos la url torrent - patron = 'class="btn-torrent">.*?window.location.href = "(.*?)";' item_local.url = scrapertools.find_single_match(data, patron) if not item_local.url: #error logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) @@ -969,17 +1037,17 @@ def findvideos(item): #Ahora pintamos el link del Torrent, si lo hay if item_local.url: # Hay Torrent ? - item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.quality, str(item_local.language)) #Preparamos título de Torrent + if size: + quality = '%s [%s]' % (item_local.quality, size) #Agregamos size al final del título + else: + quality = item_local.quality + item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (quality, str(item_local.language)) #Preparamos título de Torrent item_local.title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', item_local.title).strip() #Quitamos etiquetas vacías item_local.title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', item_local.title).strip() #Quitamos colores vacíos item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Servidor - if size: - quality = '%s [%s]' % (item_local.quality, size) #Agregamos size al final del título - else: - quality = item_local.quality - + itemlist.append(item_local.clone(quality=quality)) #Pintar pantalla logger.debug("TORRENT: " + item_local.url + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / tamaño: " + size + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) @@ -1163,9 +1231,20 @@ def findvideos(item): def episodios(item): logger.info() + + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] + # Obtener la información actualizada de la Serie. TMDB es imprescindible para Videoteca + if not item.infoLabels['tmdb_id']: + tmdb.set_infoLabels(item, True) + max_temp = 1 + if item.infoLabels['number_of_seasons']: + max_temp = item.infoLabels['number_of_seasons'] y = [] if modo_ultima_temp and item.library_playcounts: #Averiguar cuantas temporadas hay en Videoteca patron = 'season (\d+)' @@ -1173,16 +1252,30 @@ def episodios(item): for x in matches: y += [int(x)] max_temp = max(y) - - # Obtener la información actualizada de la Serie. TMDB es imprescindible para Videoteca - if not item.infoLabels['tmdb_id']: - tmdb.set_infoLabels(item, True) - + data = '' try: data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) - except: #Algún error de proceso, salimos - logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea" + item.url) + patron = '' % "buscar-list" # item.pattern + data_alt = '' + if data: data_alt = scrapertools.get_match(data, patron) + except: #Algún error de proceso + pass + + if "pelisyseries.com" in item.url: + pattern = ']*>
    ]+>(?P.*?)?<\/h3>.*?<\/li>' + else: + pattern = ']*>]+>(?P.*?)?<\/h2>' + + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data_alt or not scrapertools.find_single_match(data_alt, pattern): + logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea: " + item.url) + + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el vídeo + item, data = generictools.fail_over_newpct1(item, patron, pattern) + + if not data: #No se ha encontrado ningún canal activo para este vídeo + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) return itemlist @@ -1209,7 +1302,8 @@ def episodios(item): list_pages = [item.url] season = max_temp - if item.library_playcounts or item.tmdb_stat: #Comprobamos si realmente sabemos el num. máximo de temporadas + #Comprobamos si realmente sabemos el num. máximo de temporadas + if item.library_playcounts or (item.infoLabels['number_of_seasons'] and item.tmdb_stat): num_temporadas_flag = True else: num_temporadas_flag = False @@ -1226,11 +1320,11 @@ def episodios(item): if not data: raise except: - logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + data) + logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + str(data)) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos - if "pelisyseries.com" in host: + if "pelisyseries.com" in item.url: pattern = ']*>
    ]+>(?P.*?)?<\/h3>.*?<\/li>' else: pattern = ']*>]+>(?P.*?)?<\/h2>' @@ -1245,7 +1339,7 @@ def episodios(item): #Empezamos a generar cada episodio for url, thumb, info in matches: - if "pelisyseries.com" in host: #En esta web están en diferente orden + if "pelisyseries.com" in item.url: #En esta web están en diferente orden interm = url url = thumb thumb = interm @@ -1273,6 +1367,10 @@ def episodios(item): if scrapertools.find_single_match(info, '\[\d{3}\]'): info = re.sub(r'\[(\d{3}\])', r'[Cap.\1', info) + elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?[c|C]ap.*?\.(?P\d+)?.*?(?:(?P\d+))\]?\[(?P\w+)?(?P\w+)\]?'): + pattern = 'Temp.*?(?P\d+).*?[c|C]ap.*?\.(?P\d+)?.*?(?:(?P\d+))\]?\[(?P\w+)?(?P\w+)\]?' + elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?(?P\d{2})?(?:.*?(?P\d{2}))?.*?(?P\[\w+.*)\[.*?\]?'): + pattern = 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?(?P\d{2})?(?:.*?(?P\d{2}))?.*?(?P\[\w+.*)\[.*?\]?' elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?Cap\w?\.\s\d?(?P\d{2})(?:.*?(?P\d{2}))?.*?\[(?P\w+)\]?'): pattern = 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?Cap\w?\.\s\d?(?P\d{2})(?:.*?(?P\d{2}))?.*?\[(?P\w+)\]?' elif scrapertools.find_single_match(info, '\[Cap.\d{2}_\d{2}\]'): @@ -1312,11 +1410,9 @@ def episodios(item): except: logger.error("ERROR 07: EPISODIOS: Error en número de Temporada o Episodio: " + " / TEMPORADA/EPISODIO: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / MATCHES: " + str(matches)) - #logger.error("TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / " + str(match['episode2']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern) if num_temporadas_flag and match['season'] != season and match['season'] > max_temp + 1: #Si el num de temporada está fuera de control, se trata pone en num. de temporada actual - #logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern + " / MATCHES: " + str(matches)) - #logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern) + logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern + " / MATCHES: " + str(matches)) match['season'] = season item_local.contentSeason = season else: @@ -1331,11 +1427,11 @@ def episodios(item): item_local.quality = match['quality'] #Si hay quality se coge, si no, la de la serie item_local.quality = item_local.quality.replace("ALTA DEFINICION", "HDTV") - if match['lang'] and estado == False: - match['lang'] = match['lang'].replace("- ", "") + if match['lang'] and (estado == False or "especia" in str(match['lang']).lower()): + match['lang'] = match['lang'].replace("- ", "").replace("[", "").replace("]", "") item_local.infoLabels['episodio_titulo'] = match['lang'] item_local.infoLabels['title'] = item_local.infoLabels['episodio_titulo'] - + item_local.contentEpisodeNumber = match['episode'] if match['episode'] == 0: match['episode'] = 1 #Evitar errores en Videoteca @@ -1381,6 +1477,8 @@ def episodios(item): # Pasada por TMDB y clasificación de lista por temporada y episodio tmdb.set_infoLabels(itemlist, True) + + #logger.debug(item) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_episodios(item, itemlist) @@ -1395,7 +1493,7 @@ def actualizar_titulos(item): from platformcode import launcher item = generictools.update_title(item) #Llamamos al método que actualiza el título con tmdb.find_and_set_infoLabels - + #Volvemos a la siguiente acción en el canal return launcher.run(item) @@ -1403,6 +1501,9 @@ def actualizar_titulos(item): def search(item, texto): logger.info("search:" + texto) # texto = texto.replace(" ", "+") + + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() try: item.post = "q=%s" % texto diff --git a/plugin.video.alfa/channels/torrentrapid.json b/plugin.video.alfa/channels/torrentrapid.json index 99e1d0f9..f9106274 100644 --- a/plugin.video.alfa/channels/torrentrapid.json +++ b/plugin.video.alfa/channels/torrentrapid.json @@ -33,6 +33,30 @@ "enabled": true, "visible": true }, + { + "id": "clonenewpct1_channel_default", + "type": "list", + "label": "Clone de NewPct1 por defecto", + "default": 0, + "enabled": true, + "visible": true, + "lvalues": [ + "Torrentrapid", + "Torrentlocura", + "Tumejortorrent", + "Tvsinpagar", + "Descargas2020", + "Mispelisyseries" + ] + }, + { + "id": "clonenewpct1_channels_list", + "type": "text", + "label": "Lista de clones de NewPct1 y orden de uso", + "default": "('1', 'torrentrapid', 'torrentrapid.com', 'movie, tvshow, season, episode', ''), ('1', 'torrentlocura', 'torrentlocura.com', 'movie, tvshow, season, episode', ''), ('1', 'tumejortorrent', 'tumejortorrent.com', 'movie, tvshow, season, episode', ''), ('1', 'tvsinpagar', 'www.tvsinpagar.com', 'tvshow, season, episode', ''), ('1', 'descargas2020', 'descargas2020.com', 'movie, tvshow, season, episode', ''), ('1', 'mispelisyseries', 'mispelisyseries.com', 'movie, tvshow, season, episode', '')", + "enabled": true, + "visible": false + }, { "id": "seleccionar_ult_temporadda_activa", "type": "bool", diff --git a/plugin.video.alfa/channels/torrentrapid.py b/plugin.video.alfa/channels/torrentrapid.py index 4bd37764..292d7faa 100644 --- a/plugin.video.alfa/channels/torrentrapid.py +++ b/plugin.video.alfa/channels/torrentrapid.py @@ -5,6 +5,7 @@ import sys import urllib import urlparse import datetime +import ast from channelselector import get_thumb from core import httptools @@ -17,15 +18,34 @@ from lib import generictools host = 'http://torrentrapid.com/' +#Código para permitir usar un único canal para todas las webs clones de NewPct1 +clone_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte a lista de tuplas +host_index = 0 +host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto +i = 0 +for active_clone, channel_clone, host_clone, contentType_clone, info_clone in clone_list: + if i == host_index: + #channel_clone_name = channel_clone #ACTIVAR CUANDO SE PASE A NEWPCT1 + #host = 'http://%s/' % host_clone #ACTIVAR CUANDO SE PASE A NEWPCT1 + i += 1 + +#Carga de opciones del canal item = Item() if not item.channel: item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/') +channel_clone_name = scrapertools.find_single_match(host, r'(\w+)\.com\/') #QUITAR CUANDO SE PASE A NEWPCT1 __modo_grafico__ = config.get_setting('modo_grafico', item.channel) modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel) + def mainlist(item): logger.info() + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] thumb_pelis = get_thumb("channels_movie.png") @@ -64,20 +84,40 @@ def settingCanal(item): def submenu(item): logger.info() itemlist = [] - + try: data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) except: - logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) - return itemlist #Algo no funciona, pintamos lo que tenemos - data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") - data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com - + pass + + host_alt = host host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") patron = '
  • .*?(.*?)' - if "pelisyseries.com" in host and item.extra == "varios": #compatibilidad con mispelisy.series.com - data = ' Documentales' + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú + item, data = generictools.fail_over_newpct1(item, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + elif item.channel_alt: #Si ha habido fail-over, lo comento + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] caído')) + + host_alt = host.replace(item.channel_alt, item.channel) + del item.channel_alt + if item.url_alt: del item.url_alt + + #data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + #data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + + host_dom = host_alt.replace("https://", "").replace("http://", "").replace("www.", "") + patron = '
  • .*?(.*?)' + if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = ' Documentales' else: if data: data = scrapertools.get_match(data, patron) @@ -104,10 +144,10 @@ def submenu(item): Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra)) if item.extra == "peliculas": - itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host + "peliculas-hd/4kultrahd/", extra=item.extra)) + itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) itemlist.append( - Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host + "peliculas-hd/4kultrahd/", extra=item.extra)) - + Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) + return itemlist @@ -203,7 +243,8 @@ def listado(item): #logger.debug("patron: " + patron + " / fichas: " + fichas) # Identifico la página actual y el total de páginas para el pie de página - total_pag = scrapertools.find_single_match(data,'Last<\/a><\/li>') + patron_last_page = 'Last<\/a><\/li>' + total_pag = scrapertools.find_single_match(data, patron_last_page) if not item.post_num: post_num = 1 @@ -419,6 +460,9 @@ def listado(item): def listado_busqueda(item): logger.info() + + host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/') + itemlist = [] cnt_tot = 40 # Poner el num. máximo de items por página. Dejamos que la web lo controle cnt_title = 0 # Contador de líneas insertadas en Itemlist @@ -449,17 +493,24 @@ def listado_busqueda(item): #Máximo num. de líneas permitidas por TMDB. Máx de 5 páginas por Itemlist para no degradar el rendimiento while cnt_title <= cnt_tot and cnt_next < 5: + pattern = '' % item.pattern #seleccionamos el bloque que nos interesa try: data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data) except: - logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) - return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos - cnt_next += 1 - if not data: #Si la web está caída salimos sin dar error - logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) + pass + + cnt_next += 1 + if not data or not scrapertools.find_single_match(data, pattern): + logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data) + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú + item, data = generictools.fail_over_newpct1(item, pattern) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + elif item.channel_alt: #Si ha habido fail-over, lo comento + host = host.replace(item.channel_alt, item.channel) #Obtiene la dirección de la próxima página, si la hay try: @@ -824,6 +875,11 @@ def listado_busqueda(item): def findvideos(item): from core import channeltools logger.info() + + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] # Cualquiera de las tres opciones son válidas @@ -934,9 +990,20 @@ def findvideos(item): try: data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) except: + pass + + patron = 'class="btn-torrent">.*?window.location.href = "(.*?)";' #Patron para .torrent + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data or not scrapertools.find_single_match(data, patron): logger.error("ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url + " / DATA: " + data) + + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el vídeo + item, data = generictools.fail_over_newpct1(item, patron) + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("$!", "#!").replace("'", "\"").replace("ñ", "ñ").replace("//pictures", "/pictures") @@ -948,6 +1015,8 @@ def findvideos(item): else: item.title = re.sub(r'\s\[\d+,?\d*?\s\w[b|B]\]', '', item.title) #Quitamos size de título, si lo traía item.title = '%s [%s]' % (item.title, size) #Agregamos size al final del título + if size: + size = size.replace('GB', 'G B').replace('Gb', 'G b').replace('MB', 'M B').replace('Mb', 'M b') item.quality = re.sub(r'\s\[\d+,?\d*?\s\w[b|B]\]', '', item.quality) #Quitamos size de calidad, si lo traía #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB @@ -957,7 +1026,6 @@ def findvideos(item): item_local = item.clone() # obtenemos la url torrent - patron = 'class="btn-torrent">.*?window.location.href = "(.*?)";' item_local.url = scrapertools.find_single_match(data, patron) if not item_local.url: #error logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) @@ -969,17 +1037,17 @@ def findvideos(item): #Ahora pintamos el link del Torrent, si lo hay if item_local.url: # Hay Torrent ? - item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.quality, str(item_local.language)) #Preparamos título de Torrent + if size: + quality = '%s [%s]' % (item_local.quality, size) #Agregamos size al final del título + else: + quality = item_local.quality + item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (quality, str(item_local.language)) #Preparamos título de Torrent item_local.title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', item_local.title).strip() #Quitamos etiquetas vacías item_local.title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', item_local.title).strip() #Quitamos colores vacíos item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Servidor - if size: - quality = '%s [%s]' % (item_local.quality, size) #Agregamos size al final del título - else: - quality = item_local.quality - + itemlist.append(item_local.clone(quality=quality)) #Pintar pantalla logger.debug("TORRENT: " + item_local.url + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / tamaño: " + size + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) @@ -1163,9 +1231,20 @@ def findvideos(item): def episodios(item): logger.info() + + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] + # Obtener la información actualizada de la Serie. TMDB es imprescindible para Videoteca + if not item.infoLabels['tmdb_id']: + tmdb.set_infoLabels(item, True) + max_temp = 1 + if item.infoLabels['number_of_seasons']: + max_temp = item.infoLabels['number_of_seasons'] y = [] if modo_ultima_temp and item.library_playcounts: #Averiguar cuantas temporadas hay en Videoteca patron = 'season (\d+)' @@ -1173,16 +1252,30 @@ def episodios(item): for x in matches: y += [int(x)] max_temp = max(y) - - # Obtener la información actualizada de la Serie. TMDB es imprescindible para Videoteca - if not item.infoLabels['tmdb_id']: - tmdb.set_infoLabels(item, True) - + data = '' try: data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) - except: #Algún error de proceso, salimos - logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea" + item.url) + patron = '' % "buscar-list" # item.pattern + data_alt = '' + if data: data_alt = scrapertools.get_match(data, patron) + except: #Algún error de proceso + pass + + if "pelisyseries.com" in item.url: + pattern = ']*>
    ]+>(?P.*?)?<\/h3>.*?<\/li>' + else: + pattern = ']*>]+>(?P.*?)?<\/h2>' + + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data_alt or not scrapertools.find_single_match(data_alt, pattern): + logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea: " + item.url) + + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el vídeo + item, data = generictools.fail_over_newpct1(item, patron, pattern) + + if not data: #No se ha encontrado ningún canal activo para este vídeo + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) return itemlist @@ -1209,7 +1302,8 @@ def episodios(item): list_pages = [item.url] season = max_temp - if item.library_playcounts or item.tmdb_stat: #Comprobamos si realmente sabemos el num. máximo de temporadas + #Comprobamos si realmente sabemos el num. máximo de temporadas + if item.library_playcounts or (item.infoLabels['number_of_seasons'] and item.tmdb_stat): num_temporadas_flag = True else: num_temporadas_flag = False @@ -1226,11 +1320,11 @@ def episodios(item): if not data: raise except: - logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + data) + logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + str(data)) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos - if "pelisyseries.com" in host: + if "pelisyseries.com" in item.url: pattern = ']*>
    ]+>(?P.*?)?<\/h3>.*?<\/li>' else: pattern = ']*>]+>(?P.*?)?<\/h2>' @@ -1245,7 +1339,7 @@ def episodios(item): #Empezamos a generar cada episodio for url, thumb, info in matches: - if "pelisyseries.com" in host: #En esta web están en diferente orden + if "pelisyseries.com" in item.url: #En esta web están en diferente orden interm = url url = thumb thumb = interm @@ -1273,6 +1367,10 @@ def episodios(item): if scrapertools.find_single_match(info, '\[\d{3}\]'): info = re.sub(r'\[(\d{3}\])', r'[Cap.\1', info) + elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?[c|C]ap.*?\.(?P\d+)?.*?(?:(?P\d+))\]?\[(?P\w+)?(?P\w+)\]?'): + pattern = 'Temp.*?(?P\d+).*?[c|C]ap.*?\.(?P\d+)?.*?(?:(?P\d+))\]?\[(?P\w+)?(?P\w+)\]?' + elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?(?P\d{2})?(?:.*?(?P\d{2}))?.*?(?P\[\w+.*)\[.*?\]?'): + pattern = 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?(?P\d{2})?(?:.*?(?P\d{2}))?.*?(?P\[\w+.*)\[.*?\]?' elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?Cap\w?\.\s\d?(?P\d{2})(?:.*?(?P\d{2}))?.*?\[(?P\w+)\]?'): pattern = 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?Cap\w?\.\s\d?(?P\d{2})(?:.*?(?P\d{2}))?.*?\[(?P\w+)\]?' elif scrapertools.find_single_match(info, '\[Cap.\d{2}_\d{2}\]'): @@ -1312,11 +1410,9 @@ def episodios(item): except: logger.error("ERROR 07: EPISODIOS: Error en número de Temporada o Episodio: " + " / TEMPORADA/EPISODIO: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / MATCHES: " + str(matches)) - #logger.error("TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / " + str(match['episode2']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern) if num_temporadas_flag and match['season'] != season and match['season'] > max_temp + 1: #Si el num de temporada está fuera de control, se trata pone en num. de temporada actual - #logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern + " / MATCHES: " + str(matches)) - #logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern) + logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern + " / MATCHES: " + str(matches)) match['season'] = season item_local.contentSeason = season else: @@ -1331,11 +1427,11 @@ def episodios(item): item_local.quality = match['quality'] #Si hay quality se coge, si no, la de la serie item_local.quality = item_local.quality.replace("ALTA DEFINICION", "HDTV") - if match['lang'] and estado == False: - match['lang'] = match['lang'].replace("- ", "") + if match['lang'] and (estado == False or "especia" in str(match['lang']).lower()): + match['lang'] = match['lang'].replace("- ", "").replace("[", "").replace("]", "") item_local.infoLabels['episodio_titulo'] = match['lang'] item_local.infoLabels['title'] = item_local.infoLabels['episodio_titulo'] - + item_local.contentEpisodeNumber = match['episode'] if match['episode'] == 0: match['episode'] = 1 #Evitar errores en Videoteca @@ -1381,6 +1477,8 @@ def episodios(item): # Pasada por TMDB y clasificación de lista por temporada y episodio tmdb.set_infoLabels(itemlist, True) + + #logger.debug(item) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_episodios(item, itemlist) @@ -1395,7 +1493,7 @@ def actualizar_titulos(item): from platformcode import launcher item = generictools.update_title(item) #Llamamos al método que actualiza el título con tmdb.find_and_set_infoLabels - + #Volvemos a la siguiente acción en el canal return launcher.run(item) @@ -1403,6 +1501,9 @@ def actualizar_titulos(item): def search(item, texto): logger.info("search:" + texto) # texto = texto.replace(" ", "+") + + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() try: item.post = "q=%s" % texto diff --git a/plugin.video.alfa/channels/tumejortorrent.py b/plugin.video.alfa/channels/tumejortorrent.py index a9bff840..105b8cda 100644 --- a/plugin.video.alfa/channels/tumejortorrent.py +++ b/plugin.video.alfa/channels/tumejortorrent.py @@ -5,6 +5,7 @@ import sys import urllib import urlparse import datetime +import ast from channelselector import get_thumb from core import httptools @@ -17,15 +18,34 @@ from lib import generictools host = 'http://tumejortorrent.com/' +#Código para permitir usar un único canal para todas las webs clones de NewPct1 +clone_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte a lista de tuplas +host_index = 0 +host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto +i = 0 +for active_clone, channel_clone, host_clone, contentType_clone, info_clone in clone_list: + if i == host_index: + #channel_clone_name = channel_clone #ACTIVAR CUANDO SE PASE A NEWPCT1 + #host = 'http://%s/' % host_clone #ACTIVAR CUANDO SE PASE A NEWPCT1 + i += 1 + +#Carga de opciones del canal item = Item() if not item.channel: item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/') +channel_clone_name = scrapertools.find_single_match(host, r'(\w+)\.com\/') #QUITAR CUANDO SE PASE A NEWPCT1 __modo_grafico__ = config.get_setting('modo_grafico', item.channel) modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel) + def mainlist(item): logger.info() + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] thumb_pelis = get_thumb("channels_movie.png") @@ -64,20 +84,40 @@ def settingCanal(item): def submenu(item): logger.info() itemlist = [] - + try: data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) except: - logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) - return itemlist #Algo no funciona, pintamos lo que tenemos - data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") - data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com - + pass + + host_alt = host host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") patron = '
  • .*?(.*?)' - if "pelisyseries.com" in host and item.extra == "varios": #compatibilidad con mispelisy.series.com - data = ' Documentales' + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú + item, data = generictools.fail_over_newpct1(item, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + elif item.channel_alt: #Si ha habido fail-over, lo comento + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] caído')) + + host_alt = host.replace(item.channel_alt, item.channel) + del item.channel_alt + if item.url_alt: del item.url_alt + + #data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + #data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + + host_dom = host_alt.replace("https://", "").replace("http://", "").replace("www.", "") + patron = '
  • .*?(.*?)' + if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = ' Documentales' else: if data: data = scrapertools.get_match(data, patron) @@ -104,10 +144,10 @@ def submenu(item): Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra)) if item.extra == "peliculas": - itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host + "peliculas-hd/4kultrahd/", extra=item.extra)) + itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) itemlist.append( - Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host + "peliculas-hd/4kultrahd/", extra=item.extra)) - + Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) + return itemlist @@ -203,7 +243,8 @@ def listado(item): #logger.debug("patron: " + patron + " / fichas: " + fichas) # Identifico la página actual y el total de páginas para el pie de página - total_pag = scrapertools.find_single_match(data,'Last<\/a><\/li>') + patron_last_page = 'Last<\/a><\/li>' + total_pag = scrapertools.find_single_match(data, patron_last_page) if not item.post_num: post_num = 1 @@ -419,6 +460,9 @@ def listado(item): def listado_busqueda(item): logger.info() + + host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/') + itemlist = [] cnt_tot = 40 # Poner el num. máximo de items por página. Dejamos que la web lo controle cnt_title = 0 # Contador de líneas insertadas en Itemlist @@ -449,17 +493,24 @@ def listado_busqueda(item): #Máximo num. de líneas permitidas por TMDB. Máx de 5 páginas por Itemlist para no degradar el rendimiento while cnt_title <= cnt_tot and cnt_next < 5: + pattern = '' % item.pattern #seleccionamos el bloque que nos interesa try: data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data) except: - logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) - return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos - cnt_next += 1 - if not data: #Si la web está caída salimos sin dar error - logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) + pass + + cnt_next += 1 + if not data or not scrapertools.find_single_match(data, pattern): + logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data) + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú + item, data = generictools.fail_over_newpct1(item, pattern) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + elif item.channel_alt: #Si ha habido fail-over, lo comento + host = host.replace(item.channel_alt, item.channel) #Obtiene la dirección de la próxima página, si la hay try: @@ -824,6 +875,11 @@ def listado_busqueda(item): def findvideos(item): from core import channeltools logger.info() + + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] # Cualquiera de las tres opciones son válidas @@ -934,9 +990,20 @@ def findvideos(item): try: data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) except: + pass + + patron = 'class="btn-torrent">.*?window.location.href = "(.*?)";' #Patron para .torrent + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data or not scrapertools.find_single_match(data, patron): logger.error("ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url + " / DATA: " + data) + + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el vídeo + item, data = generictools.fail_over_newpct1(item, patron) + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("$!", "#!").replace("'", "\"").replace("ñ", "ñ").replace("//pictures", "/pictures") @@ -948,6 +1015,8 @@ def findvideos(item): else: item.title = re.sub(r'\s\[\d+,?\d*?\s\w[b|B]\]', '', item.title) #Quitamos size de título, si lo traía item.title = '%s [%s]' % (item.title, size) #Agregamos size al final del título + if size: + size = size.replace('GB', 'G B').replace('Gb', 'G b').replace('MB', 'M B').replace('Mb', 'M b') item.quality = re.sub(r'\s\[\d+,?\d*?\s\w[b|B]\]', '', item.quality) #Quitamos size de calidad, si lo traía #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB @@ -957,7 +1026,6 @@ def findvideos(item): item_local = item.clone() # obtenemos la url torrent - patron = 'class="btn-torrent">.*?window.location.href = "(.*?)";' item_local.url = scrapertools.find_single_match(data, patron) if not item_local.url: #error logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) @@ -969,17 +1037,17 @@ def findvideos(item): #Ahora pintamos el link del Torrent, si lo hay if item_local.url: # Hay Torrent ? - item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.quality, str(item_local.language)) #Preparamos título de Torrent + if size: + quality = '%s [%s]' % (item_local.quality, size) #Agregamos size al final del título + else: + quality = item_local.quality + item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (quality, str(item_local.language)) #Preparamos título de Torrent item_local.title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', item_local.title).strip() #Quitamos etiquetas vacías item_local.title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', item_local.title).strip() #Quitamos colores vacíos item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Servidor - if size: - quality = '%s [%s]' % (item_local.quality, size) #Agregamos size al final del título - else: - quality = item_local.quality - + itemlist.append(item_local.clone(quality=quality)) #Pintar pantalla logger.debug("TORRENT: " + item_local.url + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / tamaño: " + size + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) @@ -1163,9 +1231,20 @@ def findvideos(item): def episodios(item): logger.info() + + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] + # Obtener la información actualizada de la Serie. TMDB es imprescindible para Videoteca + if not item.infoLabels['tmdb_id']: + tmdb.set_infoLabels(item, True) + max_temp = 1 + if item.infoLabels['number_of_seasons']: + max_temp = item.infoLabels['number_of_seasons'] y = [] if modo_ultima_temp and item.library_playcounts: #Averiguar cuantas temporadas hay en Videoteca patron = 'season (\d+)' @@ -1173,16 +1252,30 @@ def episodios(item): for x in matches: y += [int(x)] max_temp = max(y) - - # Obtener la información actualizada de la Serie. TMDB es imprescindible para Videoteca - if not item.infoLabels['tmdb_id']: - tmdb.set_infoLabels(item, True) - + data = '' try: data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) - except: #Algún error de proceso, salimos - logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea" + item.url) + patron = '' % "buscar-list" # item.pattern + data_alt = '' + if data: data_alt = scrapertools.get_match(data, patron) + except: #Algún error de proceso + pass + + if "pelisyseries.com" in item.url: + pattern = ']*>
    ]+>(?P.*?)?<\/h3>.*?<\/li>' + else: + pattern = ']*>]+>(?P.*?)?<\/h2>' + + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data_alt or not scrapertools.find_single_match(data_alt, pattern): + logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea: " + item.url) + + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el vídeo + item, data = generictools.fail_over_newpct1(item, patron, pattern) + + if not data: #No se ha encontrado ningún canal activo para este vídeo + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) return itemlist @@ -1209,7 +1302,8 @@ def episodios(item): list_pages = [item.url] season = max_temp - if item.library_playcounts or item.tmdb_stat: #Comprobamos si realmente sabemos el num. máximo de temporadas + #Comprobamos si realmente sabemos el num. máximo de temporadas + if item.library_playcounts or (item.infoLabels['number_of_seasons'] and item.tmdb_stat): num_temporadas_flag = True else: num_temporadas_flag = False @@ -1226,11 +1320,11 @@ def episodios(item): if not data: raise except: - logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + data) + logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + str(data)) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos - if "pelisyseries.com" in host: + if "pelisyseries.com" in item.url: pattern = ']*>
    ]+>(?P.*?)?<\/h3>.*?<\/li>' else: pattern = ']*>]+>(?P.*?)?<\/h2>' @@ -1245,7 +1339,7 @@ def episodios(item): #Empezamos a generar cada episodio for url, thumb, info in matches: - if "pelisyseries.com" in host: #En esta web están en diferente orden + if "pelisyseries.com" in item.url: #En esta web están en diferente orden interm = url url = thumb thumb = interm @@ -1273,6 +1367,10 @@ def episodios(item): if scrapertools.find_single_match(info, '\[\d{3}\]'): info = re.sub(r'\[(\d{3}\])', r'[Cap.\1', info) + elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?[c|C]ap.*?\.(?P\d+)?.*?(?:(?P\d+))\]?\[(?P\w+)?(?P\w+)\]?'): + pattern = 'Temp.*?(?P\d+).*?[c|C]ap.*?\.(?P\d+)?.*?(?:(?P\d+))\]?\[(?P\w+)?(?P\w+)\]?' + elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?(?P\d{2})?(?:.*?(?P\d{2}))?.*?(?P\[\w+.*)\[.*?\]?'): + pattern = 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?(?P\d{2})?(?:.*?(?P\d{2}))?.*?(?P\[\w+.*)\[.*?\]?' elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?Cap\w?\.\s\d?(?P\d{2})(?:.*?(?P\d{2}))?.*?\[(?P\w+)\]?'): pattern = 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?Cap\w?\.\s\d?(?P\d{2})(?:.*?(?P\d{2}))?.*?\[(?P\w+)\]?' elif scrapertools.find_single_match(info, '\[Cap.\d{2}_\d{2}\]'): @@ -1312,11 +1410,9 @@ def episodios(item): except: logger.error("ERROR 07: EPISODIOS: Error en número de Temporada o Episodio: " + " / TEMPORADA/EPISODIO: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / MATCHES: " + str(matches)) - #logger.error("TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / " + str(match['episode2']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern) if num_temporadas_flag and match['season'] != season and match['season'] > max_temp + 1: #Si el num de temporada está fuera de control, se trata pone en num. de temporada actual - #logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern + " / MATCHES: " + str(matches)) - #logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern) + logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern + " / MATCHES: " + str(matches)) match['season'] = season item_local.contentSeason = season else: @@ -1331,11 +1427,11 @@ def episodios(item): item_local.quality = match['quality'] #Si hay quality se coge, si no, la de la serie item_local.quality = item_local.quality.replace("ALTA DEFINICION", "HDTV") - if match['lang'] and estado == False: - match['lang'] = match['lang'].replace("- ", "") + if match['lang'] and (estado == False or "especia" in str(match['lang']).lower()): + match['lang'] = match['lang'].replace("- ", "").replace("[", "").replace("]", "") item_local.infoLabels['episodio_titulo'] = match['lang'] item_local.infoLabels['title'] = item_local.infoLabels['episodio_titulo'] - + item_local.contentEpisodeNumber = match['episode'] if match['episode'] == 0: match['episode'] = 1 #Evitar errores en Videoteca @@ -1381,6 +1477,8 @@ def episodios(item): # Pasada por TMDB y clasificación de lista por temporada y episodio tmdb.set_infoLabels(itemlist, True) + + #logger.debug(item) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_episodios(item, itemlist) @@ -1395,7 +1493,7 @@ def actualizar_titulos(item): from platformcode import launcher item = generictools.update_title(item) #Llamamos al método que actualiza el título con tmdb.find_and_set_infoLabels - + #Volvemos a la siguiente acción en el canal return launcher.run(item) @@ -1403,6 +1501,9 @@ def actualizar_titulos(item): def search(item, texto): logger.info("search:" + texto) # texto = texto.replace(" ", "+") + + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() try: item.post = "q=%s" % texto diff --git a/plugin.video.alfa/channels/tvsinpagar.py b/plugin.video.alfa/channels/tvsinpagar.py index 2641d04e..8a0ef203 100644 --- a/plugin.video.alfa/channels/tvsinpagar.py +++ b/plugin.video.alfa/channels/tvsinpagar.py @@ -5,6 +5,7 @@ import sys import urllib import urlparse import datetime +import ast from channelselector import get_thumb from core import httptools @@ -17,15 +18,34 @@ from lib import generictools host = 'http://www.tvsinpagar.com/' +#Código para permitir usar un único canal para todas las webs clones de NewPct1 +clone_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte a lista de tuplas +host_index = 0 +host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto +i = 0 +for active_clone, channel_clone, host_clone, contentType_clone, info_clone in clone_list: + if i == host_index: + #channel_clone_name = channel_clone #ACTIVAR CUANDO SE PASE A NEWPCT1 + #host = 'http://%s/' % host_clone #ACTIVAR CUANDO SE PASE A NEWPCT1 + i += 1 + +#Carga de opciones del canal item = Item() if not item.channel: item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/') +channel_clone_name = scrapertools.find_single_match(host, r'(\w+)\.com\/') #QUITAR CUANDO SE PASE A NEWPCT1 __modo_grafico__ = config.get_setting('modo_grafico', item.channel) modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel) + def mainlist(item): logger.info() + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] thumb_pelis = get_thumb("channels_movie.png") @@ -64,20 +84,40 @@ def settingCanal(item): def submenu(item): logger.info() itemlist = [] - + try: data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) except: - logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) - return itemlist #Algo no funciona, pintamos lo que tenemos - data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") - data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com - + pass + + host_alt = host host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") patron = '
  • .*?(.*?)' - if "pelisyseries.com" in host and item.extra == "varios": #compatibilidad con mispelisy.series.com - data = ' Documentales' + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url) + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú + item, data = generictools.fail_over_newpct1(item, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + elif item.channel_alt: #Si ha habido fail-over, lo comento + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] caído')) + + host_alt = host.replace(item.channel_alt, item.channel) + del item.channel_alt + if item.url_alt: del item.url_alt + + #data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + #data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + + host_dom = host_alt.replace("https://", "").replace("http://", "").replace("www.", "") + patron = '
  • .*?(.*?)' + if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = ' Documentales' else: if data: data = scrapertools.get_match(data, patron) @@ -104,10 +144,10 @@ def submenu(item): Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra)) if item.extra == "peliculas": - itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host + "peliculas-hd/4kultrahd/", extra=item.extra)) + itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) itemlist.append( - Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host + "peliculas-hd/4kultrahd/", extra=item.extra)) - + Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) + return itemlist @@ -203,7 +243,8 @@ def listado(item): #logger.debug("patron: " + patron + " / fichas: " + fichas) # Identifico la página actual y el total de páginas para el pie de página - total_pag = scrapertools.find_single_match(data,'Last<\/a><\/li>') + patron_last_page = 'Last<\/a><\/li>' + total_pag = scrapertools.find_single_match(data, patron_last_page) if not item.post_num: post_num = 1 @@ -419,6 +460,9 @@ def listado(item): def listado_busqueda(item): logger.info() + + host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/') + itemlist = [] cnt_tot = 40 # Poner el num. máximo de items por página. Dejamos que la web lo controle cnt_title = 0 # Contador de líneas insertadas en Itemlist @@ -449,17 +493,24 @@ def listado_busqueda(item): #Máximo num. de líneas permitidas por TMDB. Máx de 5 páginas por Itemlist para no degradar el rendimiento while cnt_title <= cnt_tot and cnt_next < 5: + pattern = '' % item.pattern #seleccionamos el bloque que nos interesa try: data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data) except: - logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) - return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos - cnt_next += 1 - if not data: #Si la web está caída salimos sin dar error - logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) + pass + + cnt_next += 1 + if not data or not scrapertools.find_single_match(data, pattern): + logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data) + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú + item, data = generictools.fail_over_newpct1(item, pattern) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + elif item.channel_alt: #Si ha habido fail-over, lo comento + host = host.replace(item.channel_alt, item.channel) #Obtiene la dirección de la próxima página, si la hay try: @@ -824,6 +875,11 @@ def listado_busqueda(item): def findvideos(item): from core import channeltools logger.info() + + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] # Cualquiera de las tres opciones son válidas @@ -934,9 +990,20 @@ def findvideos(item): try: data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) except: + pass + + patron = 'class="btn-torrent">.*?window.location.href = "(.*?)";' #Patron para .torrent + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data or not scrapertools.find_single_match(data, patron): logger.error("ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url + " / DATA: " + data) + + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el vídeo + item, data = generictools.fail_over_newpct1(item, patron) + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("$!", "#!").replace("'", "\"").replace("ñ", "ñ").replace("//pictures", "/pictures") @@ -948,6 +1015,8 @@ def findvideos(item): else: item.title = re.sub(r'\s\[\d+,?\d*?\s\w[b|B]\]', '', item.title) #Quitamos size de título, si lo traía item.title = '%s [%s]' % (item.title, size) #Agregamos size al final del título + if size: + size = size.replace('GB', 'G B').replace('Gb', 'G b').replace('MB', 'M B').replace('Mb', 'M b') item.quality = re.sub(r'\s\[\d+,?\d*?\s\w[b|B]\]', '', item.quality) #Quitamos size de calidad, si lo traía #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB @@ -957,7 +1026,6 @@ def findvideos(item): item_local = item.clone() # obtenemos la url torrent - patron = 'class="btn-torrent">.*?window.location.href = "(.*?)";' item_local.url = scrapertools.find_single_match(data, patron) if not item_local.url: #error logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) @@ -969,17 +1037,17 @@ def findvideos(item): #Ahora pintamos el link del Torrent, si lo hay if item_local.url: # Hay Torrent ? - item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.quality, str(item_local.language)) #Preparamos título de Torrent + if size: + quality = '%s [%s]' % (item_local.quality, size) #Agregamos size al final del título + else: + quality = item_local.quality + item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (quality, str(item_local.language)) #Preparamos título de Torrent item_local.title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', item_local.title).strip() #Quitamos etiquetas vacías item_local.title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', item_local.title).strip() #Quitamos colores vacíos item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Servidor - if size: - quality = '%s [%s]' % (item_local.quality, size) #Agregamos size al final del título - else: - quality = item_local.quality - + itemlist.append(item_local.clone(quality=quality)) #Pintar pantalla logger.debug("TORRENT: " + item_local.url + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / tamaño: " + size + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) @@ -1163,9 +1231,20 @@ def findvideos(item): def episodios(item): logger.info() + + #Renombramos el canal al nombre de clone elegido + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() + itemlist = [] + # Obtener la información actualizada de la Serie. TMDB es imprescindible para Videoteca + if not item.infoLabels['tmdb_id']: + tmdb.set_infoLabels(item, True) + max_temp = 1 + if item.infoLabels['number_of_seasons']: + max_temp = item.infoLabels['number_of_seasons'] y = [] if modo_ultima_temp and item.library_playcounts: #Averiguar cuantas temporadas hay en Videoteca patron = 'season (\d+)' @@ -1173,16 +1252,30 @@ def episodios(item): for x in matches: y += [int(x)] max_temp = max(y) - - # Obtener la información actualizada de la Serie. TMDB es imprescindible para Videoteca - if not item.infoLabels['tmdb_id']: - tmdb.set_infoLabels(item, True) - + data = '' try: data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) - except: #Algún error de proceso, salimos - logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea" + item.url) + patron = '' % "buscar-list" # item.pattern + data_alt = '' + if data: data_alt = scrapertools.get_match(data, patron) + except: #Algún error de proceso + pass + + if "pelisyseries.com" in item.url: + pattern = ']*>
    ]+>(?P.*?)?<\/h3>.*?<\/li>' + else: + pattern = ']*>]+>(?P.*?)?<\/h2>' + + #Verificamos si se ha cargado una página, y si además tiene la estructura correcta + if not data_alt or not scrapertools.find_single_match(data_alt, pattern): + logger.error("ERROR 01: EPISODIOS: La Web no responde o la URL es erronea: " + item.url) + + #Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el vídeo + item, data = generictools.fail_over_newpct1(item, patron, pattern) + + if not data: #No se ha encontrado ningún canal activo para este vídeo + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo')) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) return itemlist @@ -1209,7 +1302,8 @@ def episodios(item): list_pages = [item.url] season = max_temp - if item.library_playcounts or item.tmdb_stat: #Comprobamos si realmente sabemos el num. máximo de temporadas + #Comprobamos si realmente sabemos el num. máximo de temporadas + if item.library_playcounts or (item.infoLabels['number_of_seasons'] and item.tmdb_stat): num_temporadas_flag = True else: num_temporadas_flag = False @@ -1226,11 +1320,11 @@ def episodios(item): if not data: raise except: - logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + data) + logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + str(data)) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos - if "pelisyseries.com" in host: + if "pelisyseries.com" in item.url: pattern = ']*>
    ]+>(?P.*?)?<\/h3>.*?<\/li>' else: pattern = ']*>]+>(?P.*?)?<\/h2>' @@ -1245,7 +1339,7 @@ def episodios(item): #Empezamos a generar cada episodio for url, thumb, info in matches: - if "pelisyseries.com" in host: #En esta web están en diferente orden + if "pelisyseries.com" in item.url: #En esta web están en diferente orden interm = url url = thumb thumb = interm @@ -1273,6 +1367,10 @@ def episodios(item): if scrapertools.find_single_match(info, '\[\d{3}\]'): info = re.sub(r'\[(\d{3}\])', r'[Cap.\1', info) + elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?[c|C]ap.*?\.(?P\d+)?.*?(?:(?P\d+))\]?\[(?P\w+)?(?P\w+)\]?'): + pattern = 'Temp.*?(?P\d+).*?[c|C]ap.*?\.(?P\d+)?.*?(?:(?P\d+))\]?\[(?P\w+)?(?P\w+)\]?' + elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?(?P\d{2})?(?:.*?(?P\d{2}))?.*?(?P\[\w+.*)\[.*?\]?'): + pattern = 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?(?P\d{2})?(?:.*?(?P\d{2}))?.*?(?P\[\w+.*)\[.*?\]?' elif scrapertools.find_single_match(info, 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?Cap\w?\.\s\d?(?P\d{2})(?:.*?(?P\d{2}))?.*?\[(?P\w+)\]?'): pattern = 'Temp.*?(?P\d+).*?\[(?P.*?)\].*?Cap\w?\.\s\d?(?P\d{2})(?:.*?(?P\d{2}))?.*?\[(?P\w+)\]?' elif scrapertools.find_single_match(info, '\[Cap.\d{2}_\d{2}\]'): @@ -1312,11 +1410,9 @@ def episodios(item): except: logger.error("ERROR 07: EPISODIOS: Error en número de Temporada o Episodio: " + " / TEMPORADA/EPISODIO: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / MATCHES: " + str(matches)) - #logger.error("TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / " + str(match['episode2']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern) if num_temporadas_flag and match['season'] != season and match['season'] > max_temp + 1: #Si el num de temporada está fuera de control, se trata pone en num. de temporada actual - #logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern + " / MATCHES: " + str(matches)) - #logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern) + logger.error("ERROR 07: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(match['season']) + " / " + str(match['episode']) + " / NUM_TEMPORADA: " + str(max_temp) + " / " + str(season) + " / PATRON: " + pattern + " / MATCHES: " + str(matches)) match['season'] = season item_local.contentSeason = season else: @@ -1331,11 +1427,11 @@ def episodios(item): item_local.quality = match['quality'] #Si hay quality se coge, si no, la de la serie item_local.quality = item_local.quality.replace("ALTA DEFINICION", "HDTV") - if match['lang'] and estado == False: - match['lang'] = match['lang'].replace("- ", "") + if match['lang'] and (estado == False or "especia" in str(match['lang']).lower()): + match['lang'] = match['lang'].replace("- ", "").replace("[", "").replace("]", "") item_local.infoLabels['episodio_titulo'] = match['lang'] item_local.infoLabels['title'] = item_local.infoLabels['episodio_titulo'] - + item_local.contentEpisodeNumber = match['episode'] if match['episode'] == 0: match['episode'] = 1 #Evitar errores en Videoteca @@ -1381,6 +1477,8 @@ def episodios(item): # Pasada por TMDB y clasificación de lista por temporada y episodio tmdb.set_infoLabels(itemlist, True) + + #logger.debug(item) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_episodios(item, itemlist) @@ -1395,7 +1493,7 @@ def actualizar_titulos(item): from platformcode import launcher item = generictools.update_title(item) #Llamamos al método que actualiza el título con tmdb.find_and_set_infoLabels - + #Volvemos a la siguiente acción en el canal return launcher.run(item) @@ -1403,6 +1501,9 @@ def actualizar_titulos(item): def search(item, texto): logger.info("search:" + texto) # texto = texto.replace(" ", "+") + + item.channel = channel_clone_name + if item.category: item.category = channel_clone_name.capitalize() try: item.post = "q=%s" % texto diff --git a/plugin.video.alfa/lib/generictools.py b/plugin.video.alfa/lib/generictools.py index 2423a84b..fc36c7fc 100644 --- a/plugin.video.alfa/lib/generictools.py +++ b/plugin.video.alfa/lib/generictools.py @@ -63,6 +63,8 @@ def update_title(item): if item.from_title: item.title = item.from_title del item.from_title + else: + item.add_videolibrary = True #Estamos Añadiendo a la Videoteca. Indicador para control de uso de los Canales #Sólo ejecutamos este código si no se ha hecho antes en el Canal. Por ejemplo, si se ha llamado desde Episodios, #ya no se ejecutará al Añadia a Videoteca, aunque desde el canal se podrá llamar tantas veces como se quiera, @@ -125,16 +127,21 @@ def update_title(item): item.title = item.title.replace("[" + str(rating_old) + "]", "[" + str(rating_new) + "]") if item.wanted: #Actualizamos Wanted, si existe item.wanted = item.contentTitle + if new_item.contentSeason: #Restauramos el núm. de Temporada después de TMDB + item.contentSeason = new_item.contentSeason #Para evitar el "efecto memoria" de TMDB, se le llama con un título ficticio para que resetee los buffers if item.contentSerieName: - new_item.infoLabels['tmdb_id'] = '289' #una peli no ambigua + new_item.infoLabels['tmdb_id'] = '289' #una serie no ambigua else: - new_item.infoLabels['tmdb_id'] = '111' #una serie no ambigua + new_item.infoLabels['tmdb_id'] = '111' #una peli no ambigua new_item.infoLabels['year'] = '-' + if new_item.contentSeason: + del new_item.infoLabels['season'] #Funciona mal con num. de Temporada scraper_return = scraper.find_and_set_infoLabels(new_item) #logger.debug(item) + return item @@ -158,25 +165,40 @@ def post_tmdb_listado(item, itemlist): """ - for item_local in itemlist: #Recorremos el Itenlist generado por el canal - title = item_local.title + #Borramos valores si ha habido fail-over + channel_alt = '' + if item.channel_alt: + channel_alt = item.channel + del item.channel_alt + if item.url_alt: + del item.url_alt + for item_local in itemlist: #Recorremos el Itenlist generado por el canal + title = item_local.title + + if item_local.contentSeason_save: #Restauramos el num. de Temporada + item_local.contentSeason = item_local.contentSeason_save + + #Borramos valores para cada Contenido si ha habido fail-over + if item_local.channel_alt: + del item_local.channel_alt + if item_local.url_alt: + del item_local.url_alt + #Restauramos la info adicional guarda en la lista title_subs, y la borramos de Item - if item_local.title_subs and len(item_local.title_subs) > 0: - title += " " + title_add = ' ' if item_local.title_subs: for title_subs in item_local.title_subs: if "audio" in title_subs.lower(): #se restaura info de Audio - title = '%s [%s]' % (title, scrapertools.find_single_match(title_subs, r'[a|A]udio (.*?)')) + title_add += scrapertools.find_single_match(title_subs, r'[a|A]udio (.*?)') continue if scrapertools.find_single_match(title_subs, r'(\d{4})'): #Se restaura el año, s no lo ha dado TMDB if not item_local.infoLabels['year'] or item_local.infoLabels['year'] == "-": item_local.infoLabels['year'] = scrapertools.find_single_match(title_subs, r'(\d{4})') continue - if not config.get_setting("unify"): #Si Titulos Inteligentes NO seleccionados: - title = '%s %s' % (title, title_subs) #se agregan el resto de etiquetas salvadas - else: - title = '%s -%s-' % (title, title_subs) #se agregan el resto de etiquetas salvadas + + title_add = title_add.rstrip() + title_add += '%s -%s-' % (title_add, title_subs) #se agregan el resto de etiquetas salvadas del item_local.title_subs #Preparamos el Rating del vídeo @@ -195,20 +217,49 @@ def post_tmdb_listado(item, itemlist): # Para Episodios, tomo el año de exposición y no el de inicio de la serie elif item_local.infoLabels['aired']: item_local.infoLabels['year'] = scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})') - + # Preparamos el título para series, con los núm. de temporadas, si las hay - if item_local.contentType == "season" or item_local.contentType == "tvshow": - if item.infoLabels['title']: del item.infoLabels['title'] - if item_local.contentType == "season": - if scrapertools.find_single_match(item_local.url, '-(\d+)x'): - title = '%s -Temporada %s' % (title, scrapertools.find_single_match(item_local.url, '-(\d+)x')) - if scrapertools.find_single_match(item_local.url, '-temporadas?-(\d+)'): - title = '%s -Temporada %s' % (title, scrapertools.find_single_match(item_local.url, '-temporadas?-(\d+)')) + if item_local.contentType in ['season', 'tvshow', 'episode']: + if item_local.infoLabels['title']: del item_local.infoLabels['title'] + + if item_local.contentType == "episode": + if "Temporada" in title: #Compatibilizamos "Temporada" con Unify + title = '%sx%s al 99 -' % (str(item_local.contentSeason), str(item_local.contentEpisodeNumber)) + if " al " in title: #Si son episodios múltiples, ponemos nombre de serie + if " al 99" in title.lower(): #Temporada completa. Buscamos num total de episodios + title = title.replace("99", str(item_local.infoLabels['temporada_num_episodios'])) + title = '%s %s' % (title, item_local.contentSerieName) + item_local.infoLabels['episodio_titulo'] = '%s - %s [%s] [%s]' % (scrapertools.find_single_match(title, r'(al \d+)'), item_local.contentSerieName, item_local.infoLabels['year'], rating) + + elif item_local.infoLabels['episodio_titulo']: + title = '%s %s, %s' % (title, item_local.infoLabels['episodio_titulo'], item_local.contentSerieName) + item_local.infoLabels['episodio_titulo'] = '%s, %s [%s] [%s]' % (item_local.infoLabels['episodio_titulo'], item_local.contentSerieName, item_local.infoLabels['year'], rating) + + else: #Si no hay título de episodio, ponermos el nombre de la serie + title = '%s %s' % (title, item_local.contentSerieName) + item_local.infoLabels['episodio_titulo'] = '%s [%s] [%s]' % (item_local.contentSerieName, 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') + if not item_local.contentSeason: + item_local.contentSeason = scrapertools.find_single_match(item_local.url, '-temporadas?-(\d+)') + if item_local.contentSeason: + title = '%s -Temporada %s' % (title, str(item_local.contentSeason)) + if not item_local.contentSeason_save: #Restauramos el num. de Temporada + item_local.contentSeason_save = item_local.contentSeason #Y lo volvemos a salvar + del item_local.infoLabels['season'] #Funciona mal con num. de Temporada. Luego lo restauramos + else: + title = '%s -Temporada !!!' % (title) + elif item.action == "search": title += " -Serie-" + elif item_local.extra == "varios" and item.action == "search": title += " -Varios-" item_local.contentTitle += " -Varios-" + + title += title_add #Se añaden etiquetas adicionales, si las hay #Ahora maquillamos un poco los titulos dependiendo de si se han seleccionado títulos inteleigentes o no if not config.get_setting("unify"): #Si Titulos Inteligentes NO seleccionados: @@ -218,6 +269,8 @@ def post_tmdb_listado(item, itemlist): title = title.replace("[", "-").replace("]", "-") #Limpiamos las etiquetas vacías + if item_local.infoLabels['episodio_titulo']: + item_local.infoLabels['episodio_titulo'] = item_local.infoLabels['episodio_titulo'].replace(" []", "").strip() title = title.replace("--", "").replace(" []", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', title).strip() title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', title).strip() @@ -226,11 +279,17 @@ def post_tmdb_listado(item, itemlist): title += ' -%s-' % item_local.channel.capitalize() if item_local.contentType == "movie": item_local.contentTitle += ' -%s-' % item_local.channel.capitalize() - + item_local.title = title #logger.debug("url: " + item_local.url + " / title: " + item_local.title + " / content title: " + item_local.contentTitle + "/" + item_local.contentSerieName + " / calidad: " + item_local.quality + "[" + str(item_local.language) + "]" + " / year: " + str(item_local.infoLabels['year'])) + #logger.debug(item_local) + + #Si ha habido fail-over, lo comento + if channel_alt: + itemlist.append(item.clone(action='', title="[COLOR yellow]" + channel_alt.capitalize() + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] caído')) return (item, itemlist) @@ -261,7 +320,7 @@ def post_tmdb_episodios(item, itemlist): modo_ultima_temp = '' if config.get_setting('seleccionar_ult_temporadda_activa', item.channel) is True or config.get_setting('seleccionar_ult_temporadda_activa', item.channel) is False: modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel) - + #Inicia variables para el control del núm de episodios por temporada num_episodios = 1 num_episodios_lista = [] @@ -270,8 +329,39 @@ def post_tmdb_episodios(item, itemlist): num_temporada_max = 99 num_episodios_flag = True - for item_local in itemlist: #Recorremos el Itenlist generado por el canal + #Restauramos el num de Temporada para hacer más flexible la elección de Videoteca + contentSeason = item.contentSeason + if item.contentSeason_save: + contentSeason = item.contentSeason_save + item.contentSeason = item.contentSeason_save + del item.contentSeason_save + #Restauramos valores si ha habido fail-over + channel_alt = '' + if item.channel_alt: + channel_alt = item.channel + item.channel = item.channel_alt + del item.channel_alt + if item.url_alt: + item.url = item.url_alt + del item.url_alt + + for item_local in itemlist: #Recorremos el Itenlist generado por el canal + if item_local.add_videolibrary: + del item_local.add_videolibrary + if item_local.add_menu: + del item_local.add_menu + + #Restauramos valores para cada Episodio si ha habido fail-over + if item_local.channel_alt: + item_local.channel = item_local.channel_alt + del item_local.channel_alt + if item_local.url_alt: + host_act = scrapertools.find_single_match(item_local.url, ':\/\/(.*?)\/') + host_org = scrapertools.find_single_match(item_local.url_alt, ':\/\/(.*?)\/') + item_local.url = item_local.url.replace(host_act, host_org) + del item_local.url_alt + #Si el título de la serie está verificado en TMDB, se intenta descubrir los eisodios fuera de rango, #que son probables errores de la Web if item.tmdb_stat: @@ -316,9 +406,7 @@ def post_tmdb_episodios(item, itemlist): elif item_local.infoLabels['aired']: item_local.infoLabels['year'] = scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})') - #Preparamos el título para que sea compatible con Añadir Serie a Videoteca - if item.infoLabels['title']: del item.infoLabels['title'] - + #Preparamos el título para que sea compatible con Añadir Serie a Videoteca if "Temporada" in item_local.title: #Compatibilizamos "Temporada" con Unify item_local.title = '%sx%s al 99 -' % (str(item_local.contentSeason), str(item_local.contentEpisodeNumber)) if " al " in item_local.title: #Si son episodios múltiples, ponemos nombre de serie @@ -334,13 +422,14 @@ def post_tmdb_episodios(item, itemlist): else: #Si no hay título de episodio, ponermos el nombre de la serie item_local.title = '%s %s' % (item_local.title, item_local.contentSerieName) item_local.infoLabels['episodio_titulo'] = '%s [%s] [%s]' % (item_local.contentSerieName, item_local.infoLabels['year'], rating) - #item_local.infoLabels['title'] = item_local.infoLabels['episodio_titulo'] #Componemos el título final, aunque con Unify usará infoLabels['episodio_titulo'] + item_local.infoLabels['title'] = item_local.infoLabels['episodio_titulo'] item_local.title = '%s [%s] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.title, item_local.infoLabels['year'], rating, item_local.quality, str(item_local.language)) #Quitamos campos vacíos item_local.infoLabels['episodio_titulo'] = item_local.infoLabels['episodio_titulo'].replace(" []", "").strip() + item_local.infoLabels['title'] = item_local.infoLabels['title'].replace(" []", "").strip() item_local.title = item_local.title.replace(" []", "").strip() item_local.title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', item_local.title).strip() item_local.title = re.sub(r'\s\[COLOR \w+\]-\[\/COLOR\]', '', item_local.title).strip() @@ -348,10 +437,13 @@ def post_tmdb_episodios(item, itemlist): #Si la información de num. total de episodios de TMDB no es correcta, tratamos de calcularla if num_episodios < item_local.contentEpisodeNumber: num_episodios = item_local.contentEpisodeNumber + if num_episodios > item_local.contentEpisodeNumber: + item_local.infoLabels['temporada_num_episodios'] = num_episodios + num_episodios_flag = False if num_episodios and not item_local.infoLabels['temporada_num_episodios']: item_local.infoLabels['temporada_num_episodios'] = num_episodios num_episodios_flag = False - num_episodios_lista[item_local.contentSeason] = [num_episodios] + num_episodios_lista[item_local.contentSeason] = num_episodios #logger.debug("title: " + item_local.title + " / url: " + item_local.url + " / calidad: " + item_local.quality + " / Season: " + str(item_local.contentSeason) + " / EpisodeNumber: " + str(item_local.contentEpisodeNumber) + " / num_episodios_lista: " + str(num_episodios_lista) + str(num_episodios_flag)) #logger.debug(item_local) @@ -361,23 +453,22 @@ def post_tmdb_episodios(item, itemlist): try: if not num_episodios_flag: #Si el num de episodios no está informado, acualizamos episodios de toda la serie for item_local in itemlist: - item_local.infoLabels['temporada_num_episodios'] = num_episodios_lista[item_local.contentSeason] + 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)) #Permitimos la actualización de los títulos, bien para uso inmediato, o para añadir a la videoteca - item.from_action = item.action #Salvamos la acción... - item.from_title = item.title #... y el título - #item.tmdb_stat=False #Fuerza la actualización de TMDB hasta desambiguar - itemlist.append(item.clone(title="** [COLOR yelow]Actualizar Títulos - vista previa videoteca[/COLOR] **", action="actualizar_titulos", extra="episodios", tmdb_stat=False)) - - contentSeason = item.contentSeason - if item.contentSeason_save: - contentSeason = item.contentSeason_save - del item.contentSeason_save + itemlist.append(item.clone(title="** [COLOR yelow]Actualizar Títulos - vista previa videoteca[/COLOR] **", action="actualizar_titulos", extra="episodios", tmdb_stat=False, from_action=item.action, from_title=item.title)) + #Borro num. Temporada si no viene de menú de Añadir a Videoteca y no está actualizando la Videoteca + if not item.library_playcounts: #si no está actualizando la Videoteca + if modo_serie_temp != '': #y puede cambiara a serie-temporada + if item.contentSeason and not item.add_menu: + del item.infoLabels['season'] #La decisión de ponerlo o no se toma en la zona de menús + #Ponemos el título de Añadir a la Videoteca, con el núm. de episodios de la última temporada y el estado de la Serie - if config.get_videolibrary_support() and len(itemlist) > 0: + if config.get_videolibrary_support() and len(itemlist) > 1: + item_local = itemlist[-2] title = '' if item_local.infoLabels['temporada_num_episodios']: @@ -406,16 +497,29 @@ def post_tmdb_episodios(item, itemlist): itemlist.append(item.clone(title="[COLOR yellow]Añadir esta Serie a la Videoteca[/COLOR]" + title, action="add_serie_to_library")) elif modo_serie_temp == 1: #si es Serie damos la opción de guardar la última temporada o la serie completa - 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)) - itemlist.append(item.clone(title="[COLOR yellow]Añadir esta Serie a Videoteca[/COLOR]" + title, action="add_serie_to_library", contentType="tvshow")) + 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)) else: #si no, damos la opción de guardar la temporada actual o la serie completa - itemlist.append(item.clone(title="[COLOR yellow]Añadir esta Serie a Videoteca[/COLOR]" + title, action="add_serie_to_library", contentType="tvshow")) - 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)) + 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)) + 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)) else: #Es un canal estándar, sólo una linea de Añadir a Videoteca - itemlist.append(item.clone(title="[COLOR yellow]Añadir esta serie a la videoteca[/COLOR]" + title, action="add_serie_to_library", extra="episodios")) + itemlist.append(item.clone(title="[COLOR yellow]Añadir esta serie a la videoteca[/COLOR]" + title, action="add_serie_to_library", extra="episodios", add_menu=True)) + + #Si ha habido fail-over, lo comento + if channel_alt: + itemlist.append(item.clone(action='', title="[COLOR yellow]" + channel_alt.capitalize() + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] caído')) + + if item.add_videolibrary: #Estamos Añadiendo a la Videoteca. + del item.add_videolibrary #Borramos ya el indicador + if item.add_menu: #Opción que avisa si se ha añadido a la Videoteca + del item.add_menu #desde la página de Episodios o desde Menú Contextual + + #logger.debug(item) return (item, itemlist) @@ -452,10 +556,9 @@ def post_tmdb_findvideos(item, itemlist): item.unify = config.get_setting("unify") #Salvamos la información de max num. de episodios por temporada para despues de TMDB + num_episodios = item.contentEpisodeNumber if item.infoLabels['temporada_num_episodios']: num_episodios = item.infoLabels['temporada_num_episodios'] - else: - num_episodios = 1 # Obtener la información actualizada del Episodio, si no la hay. Siempre cuando viene de Videoteca if not item.infoLabels['tmdb_id'] or (not item.infoLabels['episodio_titulo'] and item.contentType == 'episode'): @@ -464,7 +567,10 @@ def post_tmdb_findvideos(item, itemlist): tmdb.set_infoLabels(item, True) #Restauramos la información de max num. de episodios por temporada despues de TMDB try: - if item.infoLabels['temporada_num_episodios'] and int(num_episodios) > int(item.infoLabels['temporada_num_episodios']): + if item.infoLabels['temporada_num_episodios']: + if int(num_episodios) > int(item.infoLabels['temporada_num_episodios']): + item.infoLabels['temporada_num_episodios'] = num_episodios + else: item.infoLabels['temporada_num_episodios'] = num_episodios except: pass @@ -485,6 +591,9 @@ def post_tmdb_findvideos(item, itemlist): except: pass + if item.quality.lower() in ['gb', 'mb']: + item.quality = item.quality.replace('GB', 'G B').replace('Gb', 'G b').replace('MB', 'M B').replace('Mb', 'M b') + #Formateamos de forma especial el título para un episodio if item.contentType == "episode": #Series title = '%sx%s' % (str(item.contentSeason), str(item.contentEpisodeNumber).zfill(2)) #Temporada y Episodio @@ -509,7 +618,9 @@ def post_tmdb_findvideos(item, itemlist): else: #Si Titulos Inteligentes SÍ seleccionados: title_gen = '[COLOR gold]Enlaces Ver: [/COLOR]%s' % (title_gen) - if config.get_setting("quit_channel_name", "videolibrary") == 1 and item.contentChannel == "videolibrary": + if item.channel_alt: + title_gen = '[COLOR yellow]%s [/COLOR][ALT]: %s' % (item.channel.capitalize(), title_gen) + elif config.get_setting("quit_channel_name", "videolibrary") == 1 and item.contentChannel == "videolibrary": title_gen = '%s: %s' % (item.channel.capitalize(), title_gen) #Pintamos el pseudo-título con toda la información disponible del vídeo @@ -519,4 +630,118 @@ def post_tmdb_findvideos(item, itemlist): #logger.debug(item) - return (item, itemlist) \ No newline at end of file + return (item, itemlist) + + +def fail_over_newpct1(item, patron, patron2=None): + logger.info() + import ast + + """ + + Llamada para encontrar una web alternativa a un canal caído, clone de NewPct1 + + Creamos una liat de tuplas con los datos de los canales alternativos. Los datos de la tupla son: + + - 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 + - info reservado para uso futuro + + La llamada al método desde el principio de Submenu, Episodios y Findvideos, es: + + from lib import generictools + item, data = generictools.fail_over_newpct1(item, patron) + + - Entrada: patron: con este patron permite verificar si los datos de la nueva web son buenos + - Entrada (opcional): patron2: segundo patron opcional + - Saida: data: devuelve los datos del la nueva web. Si vuelve vacía es que no se ha encontrado alternativa + + """ + + data = '' + + #lista de tuplas con los datos de los canales alternativos + fail_over_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") + fail_over_list = ast.literal_eval(fail_over_list) + + #Recorremos la tupla identificando el canala que falla + for active, channel, channel_host, contentType, info in fail_over_list: + if channel != item.channel: #es el canal que falla? + continue + channel_failed = channel #salvamos el nombre del canal + channel_host_failed = channel_host #salvamos el nombre del host + channel_url_failed = item.url #salvamos la url + if item.action != 'submenu' and item.action != 'search' and item.contentType not in contentType: #soporta el fail_over de este contenido? + data = '' + return (item, data) #no soporta el fail_over de este contenido, no podemos hacer nada + + #Recorremos la tupla identificando canales activos que funcionen, distintos del caído, que soporten el contenido + for active, channel, channel_host, contentType, info in fail_over_list: + data_alt = '' + if channel == channel_failed or active == '0': #está activo el nuevo canal? + continue + if item.action != 'submenu' and item.action != 'search' and item.contentType not in contentType: #soporta el contenido? + continue + + #Hacemos el cambio de nombre de canal y url, conservando las anteriores como ALT + item.channel_alt = channel_failed + item.channel = channel + item.url_alt = channel_url_failed + item.url = channel_url_failed + item.url = item.url.replace(channel_host_failed, channel_host) + #quitamos el código de series, porque puede variar entre webs + if item.action == "episodios" or item.action == "get_seasons": + item.url = re.sub(r'\/\d+$', '', item.url) #parece que con el título solo ecuentra la serie, normalmente... + + #Leemos la nueva url + try: + if item.post: + data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url, post=item.post, timeout=2).data) + else: + data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url, timeout=2).data) + except: + data = '' + if not data: #no ha habido suerte, probamos con el siguiente canal válido + logger.error("ERROR 01: " + item.action + ": La Web no responde o la URL es erronea: " + item.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 + if (not ".com/images/no_imagen.jpg" in data and not ".com/images/imagen-no-disponible.jpg" in data) or item.action != "episodios": + if item.action == 'submenu': #Para submenú hacemos un cambio total de canal + patron = patron.replace(item.channel_alt, item.channel) #el patron lleva el nombre de host + if patron: + data_alt = scrapertools.find_single_match(data, patron) + 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: " + item.url + " / Patron: " + patron) + data = '' + if item.action == 'submenu': #restauramos el patrón para el siguiente canal + patron = patron.replace(item.channel, item.channel_alt) + continue + else: + #if item.action == "episodios" or item.action == "get_seasons": #guardamos la url real de esta web + #item.url += str(scrapertools.find_single_match(data, '
      .*?