diff --git a/plugin.video.alfa/channels/descargas2020.py b/plugin.video.alfa/channels/descargas2020.py index 98e005c6..e017ae9e 100644 --- a/plugin.video.alfa/channels/descargas2020.py +++ b/plugin.video.alfa/channels/descargas2020.py @@ -12,40 +12,53 @@ from core import httptools from core import scrapertools from core import servertools from core.item import Item -from platformcode import config, logger +from platformcode import config, logger, platformtools from core import tmdb from lib import generictools -host = 'http://descargas2020.com/' +channel_py = 'newpct1' #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 +clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte en array host_index = 0 -host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto +host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #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 + channel_clone_name = channel_clone #Nombre del Canal elegido + host = host_clone #URL del Canal elegido + break + i += 1 +item = Item() +item.channel_host = host +if item.channel != channel_py: + item.channel = channel_py +item.category = channel_clone_name.capitalize() #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) +__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB? +modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada? +timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage +if timeout == 0: timeout = None + +platformtools.dialog_ok("NewPct1, ¡¡¡he vuelto como canal VIRTUAL!!!", "Hemos centralizado la gestión de los clones de NewPct1 en el canal virtual NewPct1. Los clones desaparecerán en breve.", "Para más información lee el tutorial: https://alfa-addon.com /threads/newpct1-implantando-alta-disponibilidad.1200/") + +#Vayamos a la siguiente acción en el canal Newpct1 +from platformcode import launcher +channel_clone_name = "descargas2020" #Nombre del Canal elegido +host = "http://descargas2020.com/" +item.category = channel_clone_name.capitalize() +item.action = "mainlist" +item.channel_host = host +launcher.run(item) def mainlist(item): logger.info() + if item.channel != channel_py: + return - #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") @@ -58,20 +71,20 @@ def mainlist(item): thumb_settings = get_thumb("setting_0.png") itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=host, - extra="peliculas", thumbnail=thumb_pelis )) + extra="peliculas", thumbnail=thumb_pelis, category=item.category)) itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=host, extra="series", - thumbnail=thumb_series)) + thumbnail=thumb_series, category=item.category)) itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=host, extra="varios", - thumbnail=thumb_docus)) + thumbnail=thumb_docus, category=item.category)) itemlist.append( - Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar)) + Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar, category=item.category)) itemlist.append( - Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings)) + Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category)) itemlist.append( - Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings)) + Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category)) return itemlist @@ -85,68 +98,60 @@ def submenu(item): logger.info() itemlist = [] + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass - host_alt = host - host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") - patron = '
  • .*?(.*?)' + patron = '
  • <\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>' #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) + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url + 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, 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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: 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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) - host_alt = host.replace(item.channel_alt, item.channel) - del item.channel_alt if item.url_alt: del item.url_alt + del item.channel_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' + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = '
  • Documentales
  • ' else: - if data: - data = scrapertools.get_match(data, patron) - if not data: - logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: 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 - else: - return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa + if not data: + logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 - patron = '<.*?href="([^"]+)".*?>([^>]+)' + patron = '
  • ([^>]+)<\/a><\/li>' matches = re.compile(patron, re.DOTALL).findall(data) + if not matches: logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 for scrapedurl, scrapedtitle in matches: title = scrapedtitle.strip() - url = scrapedurl - itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra)) - itemlist.append( - Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra)) + #Preguntamos por las entradas que no corresponden al "extra" + if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)): + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) + itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl)) if item.extra == "peliculas": - 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_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) + itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/")) + itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/")) return itemlist @@ -155,28 +160,41 @@ def alfabeto(item): logger.info() itemlist = [] - data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) + data = '' + data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url, timeout=timeout).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") patron = '' - if data: - data = scrapertools.get_match(data, patron) - else: - return itemlist + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + 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, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: 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.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) + + if item.url_alt: del item.url_alt + del item.channel_alt + + data = scrapertools.get_match(data, patron) patron = ']+>([^>]+)' matches = re.compile(patron, re.DOTALL).findall(data) if not matches: - logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log')) + logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: 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 for scrapedurl, scrapedtitle in matches: title = scrapedtitle.upper() - url = scrapedurl - itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra)) + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) return itemlist @@ -191,11 +209,21 @@ def listado(item): if item.totalItems: del item.totalItems + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|()", "", httptools.downloadpage(item.url, timeout=timeout).data) except: + pass + + patron = '' #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, patron) and not '

    ( 0 ) Resultados encontrados ' in data): 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')) + #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.category + ': 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 #Establecemos los valores básicos en función del tipo de contenido @@ -218,7 +246,7 @@ def listado(item): fichas = scrapertools.get_match(data, patron) if not fichas and not '

    ( 0 ) Resultados encontrados ' 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 elif '

    ( 0 ) Resultados encontrados ' in data: #no hay vídeos return itemlist @@ -235,7 +263,7 @@ def listado(item): matches = re.compile(patron, re.DOTALL).findall(fichas) if not matches: #error logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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("MATCHES: " + str(len(matches))) @@ -460,13 +488,21 @@ def listado(item): def listado_busqueda(item): logger.info() - - host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/') + + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + if item.category and item.category != "newest": + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() 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 cnt_pag = 0 # Contador de líneas leídas de Matches + timeout_search = 5 # Timeout un poco más largo para las búsquedas + if timeout > 5: + timeout_search = timeout # Timeout un poco más largo para las búsquedas + data = '' if item.cnt_pag: cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item @@ -493,21 +529,21 @@ 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) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data) except: pass - cnt_next += 1 - if not data or not scrapertools.find_single_match(data, pattern): + cnt_next += 1 + pattern = '
      (.*?)
    ' % item.pattern #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, pattern) and not '

    ( 0 ) Resultados encontrados ' in data): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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) @@ -531,7 +567,6 @@ def listado_busqueda(item): pattern = '
      (.*?)
    ' % item.pattern #seleccionamos el bloque que nos interesa data_alt = data data = scrapertools.get_match(data, pattern) - #pattern = ']*>(?P.*?)?<\/h2>' pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb @@ -541,7 +576,8 @@ def listado_busqueda(item): matches_alt = re.compile(pattern, re.DOTALL).findall(data) if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log')) + item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist. @@ -830,14 +866,14 @@ def listado_busqueda(item): url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar... #Leemos la página, a ver si es una página de episodios - data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).data) + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data) data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") data_serie = data_serie.replace("chapters", "buscar-list") pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página, #intentarlo con la otra url - data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).data) + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data) data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") data_serie = data_serie.replace("chapters", "buscar-list") @@ -876,9 +912,10 @@ 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() + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() itemlist = [] @@ -987,8 +1024,9 @@ def findvideos(item): excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar # Descarga la página + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass @@ -1001,7 +1039,7 @@ def findvideos(item): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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") @@ -1029,7 +1067,7 @@ def findvideos(item): 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) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso #logger.debug("Patron: " + patron + " url: " + item_local.url) @@ -1054,6 +1092,8 @@ def findvideos(item): #logger.debug(item_local) # VER vídeos, descargar vídeos un link, o múltiples links + data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados + host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(") data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data) @@ -1066,7 +1106,7 @@ def findvideos(item): enlaces_ver = re.compile(patron, re.DOTALL).findall(data) enlaces_descargar = enlaces_ver #logger.debug(enlaces_ver) - + #Recorre todos los links de VER, si está permitido cnt_enl_ver = 1 cnt_enl_verif = 1 @@ -1100,7 +1140,7 @@ def findvideos(item): if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo? if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador? #Llama a la subfunción de check_list_links(itemlist) para cada link de servidor - item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ? + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos? if item_local.alive == "Ok": #Sí cnt_enl_verif += 1 #Movemos los contadores @@ -1190,7 +1230,7 @@ def findvideos(item): if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo? if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador? #Llama a la subfunción de check_list_links(itemlist) para primer link de servidor - item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ? + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos? if item_local.alive == "Ok": #Sí cnt_enl_verif += 1 #Movemos los contadores @@ -1232,9 +1272,10 @@ 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() + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() itemlist = [] @@ -1255,7 +1296,7 @@ def episodios(item): data = '' try: - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data) patron = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern data_alt = '' if data: data_alt = scrapertools.get_match(data, patron) @@ -1276,7 +1317,7 @@ def episodios(item): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 #Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página @@ -1312,7 +1353,7 @@ def episodios(item): break try: if not data: - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern @@ -1321,7 +1362,7 @@ def episodios(item): raise except: 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 item.url: @@ -1331,7 +1372,7 @@ def episodios(item): matches = re.compile(pattern, re.DOTALL).findall(data) if not matches: #error logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 #logger.debug("patron: " + pattern) @@ -1399,7 +1440,7 @@ def episodios(item): match = [m.groupdict() for m in r.finditer(info)][0] if not match: #error logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico @@ -1449,8 +1490,6 @@ def episodios(item): if item_local.active: del item_local.active - if item_local.category: - del item_local.category if item_local.infoLabels['title']: del item_local.infoLabels['title'] item_local.context = "['buscar_trailer']" @@ -1467,6 +1506,8 @@ def episodios(item): del item_local.update_last if item_local.update_next: del item_local.update_next + if item_local.channel_host: + del item_local.channel_host itemlist.append(item_local.clone()) @@ -1501,9 +1542,6 @@ 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/grantorrent.py b/plugin.video.alfa/channels/grantorrent.py index e4e4de76..597ad7b4 100644 --- a/plugin.video.alfa/channels/grantorrent.py +++ b/plugin.video.alfa/channels/grantorrent.py @@ -680,6 +680,8 @@ def episodios(item): del item_local.update_last if item_local.update_next: del item_local.update_next + if item_local.channel_host: + del item_local.channel_host #Verificamos el idioma por si encontramos algo if not item_local.language: diff --git a/plugin.video.alfa/channels/mejortorrent.py b/plugin.video.alfa/channels/mejortorrent.py index 50c29870..8fc53494 100755 --- a/plugin.video.alfa/channels/mejortorrent.py +++ b/plugin.video.alfa/channels/mejortorrent.py @@ -495,7 +495,7 @@ def listado_busqueda(item): matches += re.compile(patron, re.DOTALL).findall(data) matches_cnt = len(matches) - if not matches and not 'Se han encontrado <b>0</b> resultados.' in data: #error + if not matches and not 'Se han encontrado <b>0</b> resultados.' and not "href='/juego-descargar-torrent" 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 @@ -828,6 +828,21 @@ def episodios(item): item_local.action = "findvideos" item_local.contentType = "episode" item_local.extra = "episodios" + if item_local.library_playcounts: + del item_local.library_playcounts + if item_local.library_urls: + del item_local.library_urls + if item_local.path: + del item_local.path + if item_local.update_last: + del item_local.update_last + if item_local.update_next: + del item_local.update_next + if item_local.channel_host: + del item_local.channel_host + + item_local.title = '' + item_local.context = "['buscar_trailer']" item_local.url = urlparse.urljoin(host, scrapedurl) diff --git a/plugin.video.alfa/channels/mispelisyseries.py b/plugin.video.alfa/channels/mispelisyseries.py index 0d207a6f..8811b706 100644 --- a/plugin.video.alfa/channels/mispelisyseries.py +++ b/plugin.video.alfa/channels/mispelisyseries.py @@ -12,40 +12,53 @@ from core import httptools from core import scrapertools from core import servertools from core.item import Item -from platformcode import config, logger +from platformcode import config, logger, platformtools from core import tmdb from lib import generictools -host = 'http://mispelisyseries.com/' +channel_py = 'newpct1' #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 +clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte en array host_index = 0 -host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto +host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #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 + channel_clone_name = channel_clone #Nombre del Canal elegido + host = host_clone #URL del Canal elegido + break + i += 1 +item = Item() +item.channel_host = host +if item.channel != channel_py: + item.channel = channel_py +item.category = channel_clone_name.capitalize() #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) +__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB? +modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada? +timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage +if timeout == 0: timeout = None + +platformtools.dialog_ok("NewPct1, ¡¡¡he vuelto como canal VIRTUAL!!!", "Hemos centralizado la gestión de los clones de NewPct1 en el canal virtual NewPct1. Los clones desaparecerán en breve.", "Para más información lee el tutorial: https://alfa-addon.com /threads/newpct1-implantando-alta-disponibilidad.1200/") + +#Vayamos a la siguiente acción en el canal Newpct1 +from platformcode import launcher +channel_clone_name = "mispelisyseries" #Nombre del Canal elegido +host = "http://mispelisyseries.com/" +item.category = channel_clone_name.capitalize() +item.action = "mainlist" +item.channel_host = host +launcher.run(item) def mainlist(item): logger.info() + if item.channel != channel_py: + return - #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") @@ -58,20 +71,20 @@ def mainlist(item): thumb_settings = get_thumb("setting_0.png") itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=host, - extra="peliculas", thumbnail=thumb_pelis )) + extra="peliculas", thumbnail=thumb_pelis, category=item.category)) itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=host, extra="series", - thumbnail=thumb_series)) + thumbnail=thumb_series, category=item.category)) itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=host, extra="varios", - thumbnail=thumb_docus)) + thumbnail=thumb_docus, category=item.category)) itemlist.append( - Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar)) + Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar, category=item.category)) itemlist.append( - Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings)) + Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category)) itemlist.append( - Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings)) + Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category)) return itemlist @@ -85,68 +98,60 @@ def submenu(item): logger.info() itemlist = [] + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass - host_alt = host - host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") - patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>' + patron = '<li><a\s?class="[^"]+"\s?href="http:[^"]+"><i\s?class=.*><\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>' #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) + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url + 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, 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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: 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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) - host_alt = host.replace(item.channel_alt, item.channel) - del item.channel_alt if item.url_alt: del item.url_alt + del item.channel_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 = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>' - if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com - data = '<a href="' + host_alt + 'varios/" title="Documentales"><i class="icon-rocket"></i> Documentales</a>' + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = '<li><a href="' + item.channel_host + 'varios/" title="Documentales">Documentales</a></li>' else: - if data: - data = scrapertools.get_match(data, patron) - if not data: - logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: 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 - else: - return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa + if not data: + logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 - patron = '<.*?href="([^"]+)".*?>([^>]+)</a>' + patron = '<li><a.*?href="([^"]+)"\s?.itle="[^"]+"\s?>([^>]+)<\/a><\/li>' matches = re.compile(patron, re.DOTALL).findall(data) + if not matches: logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 for scrapedurl, scrapedtitle in matches: title = scrapedtitle.strip() - url = scrapedurl - itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra)) - itemlist.append( - Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra)) + #Preguntamos por las entradas que no corresponden al "extra" + if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)): + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) + itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl)) if item.extra == "peliculas": - 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_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) + itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/")) + itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/")) return itemlist @@ -155,28 +160,41 @@ def alfabeto(item): logger.info() itemlist = [] - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = '' + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") patron = '<ul class="alfabeto">(.*?)</ul>' - if data: - data = scrapertools.get_match(data, patron) - else: - return itemlist + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + 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, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: 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.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) + + if item.url_alt: del item.url_alt + del item.channel_alt + + data = scrapertools.get_match(data, patron) patron = '<a href="([^"]+)"[^>]+>([^>]+)</a>' matches = re.compile(patron, re.DOTALL).findall(data) if not matches: - logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log')) + logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: 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 for scrapedurl, scrapedtitle in matches: title = scrapedtitle.upper() - url = scrapedurl - itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra)) + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) return itemlist @@ -191,11 +209,21 @@ def listado(item): if item.totalItems: del item.totalItems + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: + pass + + patron = '<ul class="' + clase + '">(.*?)</ul>' #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, patron) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data): 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')) + #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.category + ': 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 #Establecemos los valores básicos en función del tipo de contenido @@ -218,7 +246,7 @@ def listado(item): fichas = scrapertools.get_match(data, patron) if not fichas and not '<h3><strong>( 0 ) Resultados encontrados </strong>' 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 elif '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #no hay vídeos return itemlist @@ -235,7 +263,7 @@ def listado(item): matches = re.compile(patron, re.DOTALL).findall(fichas) if not matches: #error logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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("MATCHES: " + str(len(matches))) @@ -460,13 +488,21 @@ def listado(item): def listado_busqueda(item): logger.info() - - host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/') + + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + if item.category and item.category != "newest": + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() 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 cnt_pag = 0 # Contador de líneas leídas de Matches + timeout_search = 5 # Timeout un poco más largo para las búsquedas + if timeout > 5: + timeout_search = timeout # Timeout un poco más largo para las búsquedas + data = '' if item.cnt_pag: cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item @@ -493,21 +529,21 @@ 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 = '<ul class="%s">(.*?)</ul>' % 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) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data) except: pass - cnt_next += 1 - if not data or not scrapertools.find_single_match(data, pattern): + cnt_next += 1 + pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, pattern) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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) @@ -531,7 +567,6 @@ def listado_busqueda(item): pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa data_alt = data data = scrapertools.get_match(data, pattern) - #pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2.*?>(?P<title>.*?)?<\/h2>' pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb @@ -541,7 +576,8 @@ def listado_busqueda(item): matches_alt = re.compile(pattern, re.DOTALL).findall(data) if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log')) + item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist. @@ -830,14 +866,14 @@ def listado_busqueda(item): url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar... #Leemos la página, a ver si es una página de episodios - data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).data) + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data) data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") data_serie = data_serie.replace("chapters", "buscar-list") pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página, #intentarlo con la otra url - data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).data) + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data) data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") data_serie = data_serie.replace("chapters", "buscar-list") @@ -876,9 +912,10 @@ 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() + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() itemlist = [] @@ -987,8 +1024,9 @@ def findvideos(item): excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar # Descarga la página + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass @@ -1001,7 +1039,7 @@ def findvideos(item): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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") @@ -1029,7 +1067,7 @@ def findvideos(item): 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) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso #logger.debug("Patron: " + patron + " url: " + item_local.url) @@ -1054,6 +1092,8 @@ def findvideos(item): #logger.debug(item_local) # VER vídeos, descargar vídeos un link, o múltiples links + data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados + host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(") data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data) @@ -1066,7 +1106,7 @@ def findvideos(item): enlaces_ver = re.compile(patron, re.DOTALL).findall(data) enlaces_descargar = enlaces_ver #logger.debug(enlaces_ver) - + #Recorre todos los links de VER, si está permitido cnt_enl_ver = 1 cnt_enl_verif = 1 @@ -1100,7 +1140,7 @@ def findvideos(item): if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo? if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador? #Llama a la subfunción de check_list_links(itemlist) para cada link de servidor - item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ? + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos? if item_local.alive == "Ok": #Sí cnt_enl_verif += 1 #Movemos los contadores @@ -1190,7 +1230,7 @@ def findvideos(item): if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo? if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador? #Llama a la subfunción de check_list_links(itemlist) para primer link de servidor - item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ? + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos? if item_local.alive == "Ok": #Sí cnt_enl_verif += 1 #Movemos los contadores @@ -1232,9 +1272,10 @@ 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() + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() itemlist = [] @@ -1255,7 +1296,7 @@ def episodios(item): data = '' try: - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data) patron = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern data_alt = '' if data: data_alt = scrapertools.get_match(data, patron) @@ -1276,7 +1317,7 @@ def episodios(item): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 #Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página @@ -1312,7 +1353,7 @@ def episodios(item): break try: if not data: - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern @@ -1321,7 +1362,7 @@ def episodios(item): raise except: 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 item.url: @@ -1331,7 +1372,7 @@ def episodios(item): matches = re.compile(pattern, re.DOTALL).findall(data) if not matches: #error logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 #logger.debug("patron: " + pattern) @@ -1399,7 +1440,7 @@ def episodios(item): match = [m.groupdict() for m in r.finditer(info)][0] if not match: #error logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico @@ -1449,8 +1490,6 @@ def episodios(item): if item_local.active: del item_local.active - if item_local.category: - del item_local.category if item_local.infoLabels['title']: del item_local.infoLabels['title'] item_local.context = "['buscar_trailer']" @@ -1467,6 +1506,8 @@ def episodios(item): del item_local.update_last if item_local.update_next: del item_local.update_next + if item_local.channel_host: + del item_local.channel_host itemlist.append(item_local.clone()) @@ -1501,9 +1542,6 @@ 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/newpct1.json b/plugin.video.alfa/channels/newpct1.json new file mode 100644 index 00000000..a121e330 --- /dev/null +++ b/plugin.video.alfa/channels/newpct1.json @@ -0,0 +1,565 @@ +{ + "id": "newpct1", + "name": "Newpct1", + "active": true, + "adult": false, + "language": ["*"], + "thumbnail": "newpct1.png", + "banner": "newpct1.png", + "categories": [ + "movie", + "tvshow", + "anime", + "torrent", + "latino", + "documentary", + "vos", + "direct" + ], + "settings": [ + { + "id": "include_in_global_search", + "type": "bool", + "label": "Incluir en busqueda global", + "default": true, + "enabled": true, + "visible": true + }, + { + "id": "modo_grafico", + "type": "bool", + "label": "Buscar información extra (TMDB)", + "default": true, + "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', 'http://torrentrapid.com/', 'movie, tvshow, season, episode', ''), ('1', 'torrentlocura', 'http://torrentlocura.com/', 'movie, tvshow, season, episode', ''), ('1', 'tumejortorrent', 'http://tumejortorrent.com/', 'movie, tvshow, season, episode', ''), ('1', 'tvsinpagar', 'http://www.tvsinpagar.com/', 'tvshow, season, episode', ''), ('1', 'descargas2020', 'http://descargas2020.com/', 'movie, tvshow, season, episode', ''), ('1', 'mispelisyseries', 'http://mispelisyseries.com/', 'movie', 'search')", + "enabled": true, + "visible": false + }, + { + "id": "seleccionar_ult_temporadda_activa", + "type": "bool", + "label": "Seleccionar para Videoteca si estará activa solo la última Temporada", + "default": true, + "enabled": true, + "visible": true + }, + { + "id": "clonenewpct1_ver_enlaces_veronline", + "type": "list", + "label": "Mostrar enlaces Ver Online", + "default": 1, + "enabled": true, + "visible": true, + "lvalues": [ + "No", + "Todos", + "1", + "5", + "10", + "20" + ] + }, + { + "id": "clonenewpct1_verificar_enlaces_veronline", + "type": "list", + "label": "Verificar enlaces Ver Online", + "default": 1, + "enabled": true, + "visible": "!eq(-1,'No')", + "lvalues": [ + "No", + "Todos", + "1", + "5", + "10", + "20" + ] + }, + { + "id": "clonenewpct1_verificar_enlaces_veronline_validos", + "type": "bool", + "label": "¿Contar sólo enlaces 'verificados' en Ver Online?", + "default": true, + "enabled": true, + "visible": "!eq(-1,'No') + !eq(-2,'No')" + }, + { + "id": "clonenewpct1_excluir1_enlaces_veronline", + "type": "list", + "label": "Excluir Servidores para Ver Online", + "default": 9, + "max_excl": 5, + "enabled": true, + "visible": "!eq(-3,'No')", + "lvalues": [ + "No", + "Bankupload", + "Clipwatching", + "Flashx", + "Katfile", + "Mega", + "Mexashare", + "Movshare", + "Mowvideo", + "Openload", + "Powvideo", + "Rapidgator", + "Streamango", + "Streamcloud", + "Streame", + "Streaminto", + "Streamplay", + "Thevideo", + "Turbobit", + "Uploadedto", + "Uptobox", + "Userscloud", + "Vidabc", + "Vidspot" + ] + }, + { + "id": "clonenewpct1_excluir2_enlaces_veronline", + "type": "list", + "label": "Excluir Servidores para Ver Online", + "default": 12, + "enabled": true, + "visible": "!eq(-1,'No')", + "lvalues": [ + "No", + "Bankupload", + "Clipwatching", + "Flashx", + "Katfile", + "Mega", + "Mexashare", + "Movshare", + "Mowvideo", + "Openload", + "Powvideo", + "Rapidgator", + "Streamango", + "Streamcloud", + "Streame", + "Streaminto", + "Streamplay", + "Thevideo", + "Turbobit", + "Uploadedto", + "Uptobox", + "Userscloud", + "Vidabc", + "Vidspot" + ] + }, + { + "id": "clonenewpct1_excluir3_enlaces_veronline", + "type": "list", + "label": "Excluir Servidores para Ver Online", + "default": 20, + "enabled": true, + "visible": "!eq(-1,'No')", + "lvalues": [ + "No", + "Bankupload", + "Clipwatching", + "Flashx", + "Katfile", + "Mega", + "Mexashare", + "Movshare", + "Mowvideo", + "Openload", + "Powvideo", + "Rapidgator", + "Streamango", + "Streamcloud", + "Streame", + "Streaminto", + "Streamplay", + "Thevideo", + "Turbobit", + "Uploadedto", + "Uptobox", + "Userscloud", + "Vidabc", + "Vidspot" + ] + }, + { + "id": "clonenewpct1_excluir4_enlaces_veronline", + "type": "list", + "label": "Excluir Servidores para Ver Online", + "default": 0, + "enabled": true, + "visible": "!eq(-1,'No')", + "lvalues": [ + "No", + "Bankupload", + "Clipwatching", + "Flashx", + "Katfile", + "Mega", + "Mexashare", + "Movshare", + "Mowvideo", + "Openload", + "Powvideo", + "Rapidgator", + "Streamango", + "Streamcloud", + "Streame", + "Streaminto", + "Streamplay", + "Thevideo", + "Turbobit", + "Uploadedto", + "Uptobox", + "Userscloud", + "Vidabc", + "Vidspot" + ] + }, + { + "id": "clonenewpct1_excluir5_enlaces_veronline", + "type": "list", + "label": "Excluir Servidores para Ver Online", + "default": 0, + "enabled": true, + "visible": "!eq(-1,'No')", + "lvalues": [ + "No", + "Bankupload", + "Clipwatching", + "Flashx", + "Katfile", + "Mega", + "Mexashare", + "Movshare", + "Mowvideo", + "Openload", + "Powvideo", + "Rapidgator", + "Streamango", + "Streamcloud", + "Streame", + "Streaminto", + "Streamplay", + "Thevideo", + "Turbobit", + "Uploadedto", + "Uptobox", + "Userscloud", + "Vidabc", + "Vidspot" + ] + }, + { + "id": "clonenewpct1_ver_enlaces_descargas", + "type": "list", + "label": "Mostrar enlaces Descargas", + "default": 0, + "enabled": true, + "visible": true, + "lvalues": [ + "No", + "Todos", + "1", + "5", + "10", + "20", + "30", + "50", + "100" + ] + }, + { + "id": "clonenewpct1_verificar_enlaces_descargas", + "type": "list", + "label": "Verificar enlaces Descargas", + "default": 1, + "enabled": true, + "visible": "!eq(-1,'No')", + "lvalues": [ + "No", + "Todos", + "1", + "5", + "10", + "20", + "30", + "50", + "100" + ] + }, + { + "id": "clonenewpct1_verificar_enlaces_descargas_validos", + "type": "bool", + "label": "¿Contar sólo enlaces 'verificados' en Descargar?", + "default": true, + "enabled": true, + "visible": "!eq(-1,'No') + !eq(-2,'No')" + }, + { + "id": "clonenewpct1_excluir1_enlaces_descargas", + "type": "list", + "label": "Excluir Servidores para Ver Descargas", + "default": 0, + "enabled": true, + "visible": "!eq(-3,'No')", + "lvalues": [ + "No", + "Bankupload", + "Clipwatching", + "Flashx", + "Katfile", + "Mega", + "Mexashare", + "Movshare", + "Mowvideo", + "Openload", + "Powvideo", + "Rapidgator", + "Streamango", + "Streamcloud", + "Streame", + "Streaminto", + "Streamplay", + "Thevideo", + "Turbobit", + "Uploadedto", + "Uptobox", + "Userscloud", + "Vidabc", + "Vidspot" + ] + }, + { + "id": "clonenewpct1_excluir2_enlaces_descargas", + "type": "list", + "label": "Excluir Servidores para Ver Descargas", + "default": 0, + "enabled": true, + "visible": "!eq(-1,'No')", + "lvalues": [ + "No", + "Bankupload", + "Clipwatching", + "Flashx", + "Katfile", + "Mega", + "Mexashare", + "Movshare", + "Mowvideo", + "Openload", + "Powvideo", + "Rapidgator", + "Streamango", + "Streamcloud", + "Streame", + "Streaminto", + "Streamplay", + "Thevideo", + "Turbobit", + "Uploadedto", + "Uptobox", + "Userscloud", + "Vidabc", + "Vidspot" + ] + }, + { + "id": "clonenewpct1_excluir3_enlaces_descargas", + "type": "list", + "label": "Excluir Servidores para Descargas", + "default": 0, + "enabled": true, + "visible": "!eq(-1,'No')", + "lvalues": [ + "No", + "Bankupload", + "Clipwatching", + "Flashx", + "Katfile", + "Mega", + "Mexashare", + "Movshare", + "Mowvideo", + "Openload", + "Powvideo", + "Rapidgator", + "Streamango", + "Streamcloud", + "Streame", + "Streaminto", + "Streamplay", + "Thevideo", + "Turbobit", + "Uploadedto", + "Uptobox", + "Userscloud", + "Vidabc", + "Vidspot" + ] + }, + { + "id": "clonenewpct1_excluir4_enlaces_descargas", + "type": "list", + "label": "Excluir Servidores para Descargas", + "default": 0, + "enabled": true, + "visible": "!eq(-1,'No')", + "lvalues": [ + "No", + "Bankupload", + "Clipwatching", + "Flashx", + "Katfile", + "Mega", + "Mexashare", + "Movshare", + "Mowvideo", + "Openload", + "Powvideo", + "Rapidgator", + "Streamango", + "Streamcloud", + "Streame", + "Streaminto", + "Streamplay", + "Thevideo", + "Turbobit", + "Uploadedto", + "Uptobox", + "Userscloud", + "Vidabc", + "Vidspot" + ] + }, + { + "id": "clonenewpct1_excluir5_enlaces_descargas", + "type": "list", + "label": "Excluir Servidores para Descargas", + "default": 0, + "enabled": true, + "visible": "!eq(-1,'No')", + "lvalues": [ + "No", + "Bankupload", + "Clipwatching", + "Flashx", + "Katfile", + "Mega", + "Mexashare", + "Movshare", + "Mowvideo", + "Openload", + "Powvideo", + "Rapidgator", + "Streamango", + "Streamcloud", + "Streame", + "Streaminto", + "Streamplay", + "Thevideo", + "Turbobit", + "Uploadedto", + "Uptobox", + "Userscloud", + "Vidabc", + "Vidspot" + ] + }, + { + "id": "include_in_newest_peliculas", + "type": "bool", + "label": "Incluir en Novedades - Peliculas", + "default": true, + "enabled": true, + "visible": false + }, + { + "id": "include_in_newest_series", + "type": "bool", + "label": "Incluir en Novedades - Episodios de series", + "default": true, + "enabled": true, + "visible": false + }, + { + "id": "include_in_newest_anime", + "type": "bool", + "label": "Incluir en Novedades - Anime", + "default": true, + "enabled": true, + "visible": false + }, + { + "id": "include_in_newest_documentales", + "type": "bool", + "label": "Incluir en Novedades - Documentales", + "default": true, + "enabled": true, + "visible": false + }, + { + "id": "include_in_newest_latino", + "type": "bool", + "label": "Incluir en Novedades - Documentales", + "default": true, + "enabled": true, + "visible": false + }, + { + "id": "include_in_newest_4k", + "type": "bool", + "label": "Incluir en Novedades - 4K", + "default": true, + "enabled": true, + "visible": false + }, + { + "id": "clonenewpct1_timeout_downloadpage", + "type": "list", + "label": "Timeout (segs.) en descarga de páginas o verificación de servidores", + "default": 5, + "enabled": true, + "visible": true, + "lvalues": [ + "None", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10" + ] + } + ] +} \ No newline at end of file diff --git a/plugin.video.alfa/channels/newpct1.py b/plugin.video.alfa/channels/newpct1.py new file mode 100644 index 00000000..8edb752c --- /dev/null +++ b/plugin.video.alfa/channels/newpct1.py @@ -0,0 +1,1610 @@ +# -*- coding: utf-8 -*- + +import re +import sys +import urllib +import urlparse +import datetime +import ast + +from channelselector import get_thumb +from core import httptools +from core import scrapertools +from core import servertools +from core.item import Item +from platformcode import config, logger +from core import tmdb +from lib import generictools + +channel_py = 'newpct1' + +#Código para permitir usar un único canal para todas las webs clones de NewPct1 +clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte en array +host_index = 0 +host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #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 #Nombre del Canal elegido + host = host_clone #URL del Canal elegido + break + i += 1 +item = Item() +if item.channel != channel_py: + item.channel = channel_py + +#Carga de opciones del canal +__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB? +modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada? +timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage +if timeout == 0: timeout = None + + +def mainlist(item): + logger.info() + + itemlist = [] + + if not item.channel_host: + item.channel_host = host + if item.category.lower() == channel_py: + item.category = channel_clone_name.capitalize() + + thumb_pelis = get_thumb("channels_movie.png") + thumb_pelis_hd = get_thumb("channels_movie_hd.png") + thumb_series = get_thumb("channels_tvshow.png") + thumb_series_hd = get_thumb("channels_tvshow_hd.png") + thumb_series_az = get_thumb("channels_tvshow_az.png") + thumb_docus = get_thumb("channels_documentary.png") + thumb_buscar = get_thumb("search.png") + thumb_settings = get_thumb("setting_0.png") + + itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=item.channel_host, + extra="peliculas", thumbnail=thumb_pelis, category=item.category)) + + itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=item.channel_host, extra="series", + thumbnail=thumb_series, category=item.category)) + + itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=item.channel_host, extra="varios", + thumbnail=thumb_docus, category=item.category)) + itemlist.append( + Item(channel=item.channel, action="search", title="Buscar", url=item.channel_host + "buscar", thumbnail=thumb_buscar, category=item.category)) + + itemlist.append( + Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category)) + itemlist.append( + Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category)) + + return itemlist + + +def settingCanal(item): + from platformcode import platformtools + return platformtools.show_channel_settings() + + +def submenu(item): + logger.info() + itemlist = [] + + data = '' + try: + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) + except: + pass + + patron = '<li><a\s?class="[^"]+"\s?href="http:[^"]+"><i\s?class=.*><\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>' + #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 + 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, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: 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.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) + + if item.url_alt: del item.url_alt + del item.channel_alt + + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = '<li><a href="' + item.channel_host + 'varios/" title="Documentales">Documentales</a></li>' + else: + data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa + if not data: + logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 + + patron = '<li><a.*?href="([^"]+)"\s?.itle="[^"]+"\s?>([^>]+)<\/a><\/li>' + matches = re.compile(patron, re.DOTALL).findall(data) + + if not matches: + logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 + + for scrapedurl, scrapedtitle in matches: + title = scrapedtitle.strip() + + #Preguntamos por las entradas que no corresponden al "extra" + if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)): + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) + itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl)) + + if item.extra == "peliculas": + itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/")) + itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/")) + + return itemlist + + +def alfabeto(item): + logger.info() + itemlist = [] + + data = '' + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + + patron = '<ul class="alfabeto">(.*?)</ul>' + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + 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, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: 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.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) + + if item.url_alt: del item.url_alt + del item.channel_alt + + data = scrapertools.get_match(data, patron) + + patron = '<a href="([^"]+)"[^>]+>([^>]+)</a>' + + matches = re.compile(patron, re.DOTALL).findall(data) + if not matches: + logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: 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 + + for scrapedurl, scrapedtitle in matches: + title = scrapedtitle.upper() + + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) + + return itemlist + + +def listado(item): + logger.info() + itemlist = [] + clase = "pelilist" # etiqueta para localizar zona de listado de contenidos + url_next_page ='' # Controlde paginación + cnt_tot = 30 # Poner el num. máximo de items por página + + if item.totalItems: + del item.totalItems + + data = '' + try: + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) + except: + pass + + patron = '<ul class="' + clase + '">(.*?)</ul>' #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, patron) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data): + logger.error("ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + 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 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.category + ': 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 + + #Establecemos los valores básicos en función del tipo de contenido + if item.extra == "peliculas": + item.action = "findvideos" + item.contentType = "movie" + pag = True #Sí hay paginación + elif item.extra == "series" and not "/miniseries" in item.url: + item.action = "episodios" + item.contentType = "tvshow" + pag = True + elif item.extra == "varios" or "/miniseries" in item.url: + item.action = "findvideos" + item.contentType = "movie" + pag = True + + #Selecciona el tramo de la página con el listado de contenidos + patron = '<ul class="' + clase + '">(.*?)</ul>' + if data: + fichas = scrapertools.get_match(data, patron) + if not fichas and not '<h3><strong>( 0 ) Resultados encontrados </strong>' 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.category + ': 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 + elif '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #no hay vídeos + return itemlist + else: + return itemlist + page_extra = clase + + #Scrapea los datos de cada vídeo. Título alternativo se mantiene, aunque no se usa de momento + patron = '<a href="([^"]+).*?' # la url + patron += 'title="([^"]+).*?' # el titulo + patron += '<img.*?src="([^"]+)"[^>]+>.*?' # el thumbnail + patron += '<h2.*?>(.*?)?<\/h2>' # titulo alternativo. Se trunca en títulos largos + patron += '<span>([^<].*?)?<' # la calidad + matches = re.compile(patron, re.DOTALL).findall(fichas) + if not matches: #error + logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas) + itemlist.append(item.clone(action='', title=item.category + ': 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("MATCHES: " + str(len(matches))) + #logger.debug(matches) + #logger.debug("patron: " + patron + " / fichas: " + fichas) + + # Identifico la página actual y el total de páginas para el pie de página + patron_last_page = '<a href="[^"]+(\d+)">Last<\/a><\/li>' + total_pag = scrapertools.find_single_match(data, patron_last_page) + + if not item.post_num: + post_num = 1 + else: + post_num = int(item.post_num) + 1 + if not total_pag: + total_pag = 1 + #Calcula las páginas del canal por cada página de la web + total_pag = int(total_pag) * int((float(len(matches))/float(cnt_tot)) + 0.999999) + + # Preparamos la paginación. + if not item.cnt_pag: + cnt_pag = 0 + else: + cnt_pag = item.cnt_pag + del item.cnt_pag + + matches_cnt = len(matches) + if item.next_page != 'b': + if matches_cnt > cnt_pag + cnt_tot: + url_next_page = item.url + matches = matches[cnt_pag:cnt_pag+cnt_tot] + next_page = '' + if matches_cnt <= cnt_pag + (cnt_tot * 2): + if pag: + next_page = 'b' + modo = 'continue' + else: + matches = matches[cnt_pag:cnt_pag+cnt_tot] + next_page = 'a' + patron_next_page = '<a href="([^"]+)">Next<\/a>' + matches_next_page = re.compile(patron_next_page, re.DOTALL).findall(data) + modo = 'continue' + if len(matches_next_page) > 0: + url_next_page = urlparse.urljoin(item.url, matches_next_page[0]) + modo = 'next' + + # Avanzamos el contador de líneas en una página + if item.next_page: + del item.next_page + if modo == 'next': + cnt_pag = 0 + else: + cnt_pag += cnt_tot + + #Tratamos todos los contenidos, creardo una variable local de Item + for scrapedurl, scrapedtitle, scrapedthumbnail, title_alt, calidad in matches: + item_local = item.clone() + if item_local.tipo: + del item_local.tipo + if item_local.totalItems: + del item_local.totalItems + if item_local.post_num: + del item_local.post_num + if item_local.category: + del item_local.category + + item_local.title = '' + item_local.context = "['buscar_trailer']" + + # Limpiamos títulos, Sacamos datos de calidad, audio y lenguaje + title = re.sub('\r\n', '', scrapedtitle).decode('iso-8859-1').encode('utf8').strip() + title_alt = re.sub('\r\n', '', title_alt).decode('iso-8859-1').encode('utf8').strip() + title = title.replace("á", "a").replace("é", "e").replace("í", "i").replace("ó", "o").replace("ú", "u").replace("ü", "u").replace("�", "ñ").replace("ñ", "ñ").replace(".", " ") + title_alt = title_alt.replace("á", "a").replace("é", "e").replace("í", "i").replace("ó", "o").replace("ú", "u").replace("ü", "u").replace("�", "ñ").replace("ñ", "ñ") + + item_local.quality = calidad + 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() or ".com/pelicula/" in scrapedurl or ".com/series-vo" in scrapedurl or "-vo/" in scrapedurl or "vos" in calidad.lower() or "vose" in calidad.lower() or "v.o.s" in calidad.lower() or "sub" in calidad.lower() or ".com/peliculas-vo" in item.url: + item_local.language += ["VOS"] + title = title.replace(" [Subs. integrados]", "").replace(" [subs. Integrados]", "").replace(" [VOSE", "").replace(" [VOS", "").replace(" (V.O.S.E)", "").replace(" VO", "").replace("Subtitulos", "") + if "latino" in title.lower() or "argentina" in title.lower() or "-latino/" in scrapedurl or "latino" in calidad.lower() or "argentina" in calidad.lower(): + item_local.language += ["LAT"] + + #Guardamos info de 3D en calidad y limpiamos + if "3d" in title.lower(): + if not "3d" in item_local.quality.lower(): + item_local.quality = item_local.quality + " 3D" + calidad3D = scrapertools.find_single_match(title, r'\s(3[d|D]\s\w+)') + if calidad3D: + item_local.quality = item_local.quality.replace("3D", calidad3D) + title = re.sub(r'\s3[d|D]\s\w+', '', title) + title = re.sub(r'\s3[d|D]', '', title) + title_alt = re.sub(r'\s3[d|D]\s\w+', '', title_alt) + title_alt = re.sub(r'\s3[d|D]', '', title_alt) + if "imax" in title.lower(): + item_local.quality = item_local.quality + " IMAX" + title = title.replace(" IMAX", "").replace(" imax", "") + title_alt = title_alt.replace(" IMAX", "").replace(" imax", "") + if "2d" in title.lower(): + title = title.replace("(2D)", "").replace("(2d)", "").replace("2D", "").replace("2d", "") + title_subs += ["[2D]"] + + #Extraemos info adicional del título y la guardamos para después de TMDB + if "temp" in title.lower() or "cap" in title.lower(): #Eliminamos Temporada, solo nos interesa la serie completa + title = re.sub(r' - [t|T]emp\w+ \d+ Comp\w+\d+[x|X]\d+', ' Completa', title) + title = re.sub(r' - [t|T]emp\w+ \d+x\d+', '', title) + title = re.sub(r' - [t|T]emp\w+ \d+', '', title) + title = re.sub(r' - [t|T]emp\w+.*?\d+', '', title) + title = re.sub(r' [t|T]emp.*?\d+x\d+', '', title) + title = re.sub(r' [t|T]emp.*?\d+', '', title) + title = re.sub(r' [c|C]ap.*?\d+', '', title) + 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.lower() or "multileng" in title.lower() or "multileng" in item_local.quality.lower() or (("espa" in title.lower() or "spani" in title.lower()) and "VOS" in item_local.language): + item_local.language[0:0] = ["DUAL"] + title = re.sub(r'\[[D|d]ual.*?\]', '', title) + title = re.sub(r'\[[M|m]ultileng.*?\]', '', title) + item_local.quality = re.sub(r'\[[M|m]ultileng.*?\]', '', item_local.quality) + if "duolog" in title.lower(): + title_subs += ["[Saga]"] + title = title.replace(" Duologia", "").replace(" duologia", "").replace(" Duolog", "").replace(" duolog", "") + if "trilog" in title.lower(): + title_subs += ["[Saga]"] + title = title.replace(" Trilogia", "").replace(" trilogia", "").replace(" Trilog", "").replace(" trilog", "") + if "extendida" in title.lower(): + title_subs += ["[V. Extendida]"] + title = title.replace(" Version Extendida", "").replace(" (Version Extendida)", "").replace(" V. Extendida", "").replace(" VExtendida", "").replace(" V Extendida", "") + if "saga" in title.lower(): + title = title.replace(" Saga Completa", "").replace(" saga sompleta", "").replace(" Saga", "").replace(" saga", "") + title_subs += ["[Saga]"] + if "colecc" in title.lower() or "completa" in title.lower(): + title = title.replace(" Coleccion", "").replace(" coleccion", "").replace(" Colecci", "").replace(" colecci", "").replace(" Completa", "").replace(" completa", "").replace(" COMPLETA", "") + if scrapertools.find_single_match(title, r'(- [m|M].*?serie ?\w+)'): + title = re.sub(r'- [m|M].*?serie ?\w+', '', title) + title_subs += ["[Miniserie]"] + + #Limpiamos restos en título + title = title.replace("Castellano", "").replace("castellano", "").replace("inglés", "").replace("ingles", "").replace("Inglés", "").replace("Ingles", "").replace("Ingl", "").replace("Engl", "").replace("Calidad", "").replace("de la Serie", "") + title_alt = title_alt.replace("Castellano", "").replace("castellano", "").replace("inglés", "").replace("ingles", "").replace("Inglés", "").replace("Ingles", "").replace("Ingl", "").replace("Engl", "").replace("Calidad", "").replace("de la Serie", "") + + #Limpiamos cabeceras y colas del título + title = re.sub(r'Descargar\s\w+\-\w+', '', title) + title = re.sub(r'\(COMPLE.*?\)', '', title) + title = re.sub(r'\(\d{4}\)$', '', title) + title = re.sub(r'\d{4}$', '', title) + title = re.sub(r' \d+x\d+', '', title) + title = re.sub(r' x\d+', '', title) + + title = title.replace("Ver online ", "").replace("Descarga Serie HD ", "").replace("Descargar Serie HD ", "").replace("Descarga Serie ", "").replace("Descargar Serie ", "").replace("Ver en linea ", "").replace("Ver en linea", "").replace("HD ", "").replace("(Proper)", "").replace("RatDVD", "").replace("DVDRiP", "").replace("DVDRIP", "").replace("DVDRip", "").replace("DVDR", "").replace("DVD9", "").replace("DVD", "").replace("DVBRIP", "").replace("DVB", "").replace("LINE", "").replace("- ES ", "").replace("ES ", "").replace("COMPLETA", "").replace("(", "-").replace(")", "-").replace(".", " ").strip() + + title = title.replace("Descargar torrent ", "").replace("Descarga Gratis ", "").replace("Descargar Estreno ", "").replace("Descargar Estrenos ", "").replace("Pelicula en latino ", "").replace("Descargar Pelicula ", "").replace("Descargar Peliculas ", "").replace("Descargar peliculas ", "").replace("Descargar Todas ", "").replace("Descargar Otras ", "").replace("Descargar ", "").replace("Descarga ", "").replace("Bajar ", "").replace("HDRIP ", "").replace("HDRiP ", "").replace("HDRip ", "").replace("RIP ", "").replace("Rip", "").replace("RiP", "").replace("XviD", "").replace("AC3 5.1", "").replace("AC3", "").replace("1080p ", "").replace("720p ", "").replace("DVD-Screener ", "").replace("TS-Screener ", "").replace("Screener ", "").replace("BdRemux ", "").replace("BR ", "").replace("4KULTRA", "").replace("FULLBluRay", "").replace("FullBluRay", "").replace("BluRay", "").replace("Bonus Disc", "").replace("de Cine ", "").replace("TeleCine ", "").replace("latino", "").replace("Latino", "").replace("argentina", "").replace("Argentina", "").strip() + + if title.endswith("torrent gratis"): title = title[:-15] + if title.endswith("gratis"): title = title[:-7] + if title.endswith("torrent"): title = title[:-8] + if title.endswith("en HD"): title = title[:-6] + if title.endswith(" -"): title = title[:-2] + if "en espa" in title: title = title[:-11] + + item_local.quality = item_local.quality.replace("gratis ", "") + if "HDR" in title: + title = title.replace(" HDR", "") + if not "HDR" in item_local.quality: + item_local.quality += " HDR" + + title = title.strip() + title_alt = title_alt.strip() + item_local.quality = item_local.quality.strip() + + if not title: #Usamos solo el title_alt en caso de que no exista el título original + title = title_alt + if not title: + title = "SIN TITULO" + + #Limpieza final del título y guardado en las variables según su tipo de contenido + title = scrapertools.remove_htmltags(title) + item_local.title = title + if item_local.contentType == "movie": + item_local.contentTitle = title + else: + item_local.contentSerieName = title + + #Guardamos el resto de variables del vídeo + item_local.url = scrapedurl + item_local.thumbnail = scrapedthumbnail + item_local.contentThumbnail = scrapedthumbnail + + #Guardamos el año que puede venir en la url, por si luego no hay resultados desde TMDB + year = '' + if item_local.contentType == "movie": + year = scrapertools.find_single_match(scrapedurl, r'(\d{4})') + if year >= "1900" and year <= "2040" and year != "2020": + title_subs += [year] + item_local.infoLabels['year'] = '-' + + #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 + + #Agrega el item local a la lista itemlist + itemlist.append(item_local.clone()) + + #Pasamos a TMDB la lista completa Itemlist + tmdb.set_infoLabels(itemlist, __modo_grafico__) + + #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: + itemlist.append( + Item(channel=item.channel, action="listado", title="[COLOR gold][B]Pagina siguiente >> [/B][/COLOR]" + str(post_num) + " de " + str(total_pag), url=url_next_page, next_page=next_page, cnt_pag=cnt_pag, post_num=post_num, pag=pag, modo=modo, extra=item.extra)) + + #logger.debug(url_next_page + " / " + next_page + " / " + str(matches_cnt) + " / " + str(cnt_pag)+ " / " + str(total_pag) + " / " + str(pag) + " / " + modo + " / " + item.extra) + + return itemlist + +def listado_busqueda(item): + logger.info() + + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + if item.category and item.category != "newest": + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() + + 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 + cnt_pag = 0 # Contador de líneas leídas de Matches + timeout_search = 5 # Timeout un poco más largo para las búsquedas + if timeout > 5: + timeout_search = timeout # Timeout un poco más largo para las búsquedas + data = '' + + if item.cnt_pag: + cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item + del item.cnt_pag + if item.totalItems: + del item.totalItems + if item.text_bold: + del item.text_bold + if item.text_color: + del item.text_color + + #Sistema de paginado para evitar páginas vacías o semi-vacías en casos de búsquedas con series con muchos episodios + title_lista = [] # Guarda la lista de series que ya están en Itemlist, para no duplicar lineas + if item.title_lista: # Si viene de una pasada anterior, la lista ya estará guardada + title_lista = item.title_lista # Se usa la lista de páginas anteriores en Item + title_lista_alt = [] + for url in title_lista: + title_lista_alt += [url] #hacemos una copia no vinculada de title_lista + matches = [] + cnt_next = 0 + total_pag = 1 + post_num = 1 + + #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: + + try: + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data) + except: + pass + + cnt_next += 1 + pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, pattern) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data): + 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.category + ': 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: + post_actual = item.post #Guardamos el post actual por si hay overflow de Itemlist y hay que hechar marcha atrás + get, post, total_pag = scrapertools.find_single_match(data, '<ul class="pagination">.*?<a\s*href="([^"]+)"(?:\s*onClick=".*?\(\'([^"]+)\'\);">Next<\/a>.*?onClick=".*?\(\'([^"]+)\'\);">Last<\/a>)') + except: + post = False + cnt_next = 99 #No hay más páginas. Salir del bucle después de procesar ésta + + if post: #puntero a la siguiente página. Cada página de la web tiene 30 entradas + if "pg" in item.post: + item.post = re.sub(r"pg=(\d+)", "pg=%s" % post, item.post) + else: + item.post += "&pg=%s" % post + post_num = int(post)-1 #Guardo página actual + + # Preparamos un patron que pretence recoger todos los datos significativos del video + pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa + data_alt = data + data = scrapertools.get_match(data, pattern) + pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url + pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título + pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb + pattern += '<h2.*?(?P<calidad>\[.*?)?<\/h2.*?' #calidad + pattern += '<span.*?>\d+-\d+-(?P<year>\d{4})?<\/span>*.?' #año + pattern += '<span.*?>(?P<size>\d+[\.|\s].*?[GB|MB])?<\/span>' #tamaño (significativo para peliculas) + matches_alt = re.compile(pattern, re.DOTALL).findall(data) + if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error + logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log')) + item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay + return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + + #Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist. + #Se controlará cuantas páginas web se tienen que leer para rellenar la lista, sin pasarse + + title_lista_alt_for = [] #usamos está lista de urls para el FOR, luego la integramos en la del WHILE + for scrapedurl, scrapedtitle, scrapedthumbnail, calidad, year, size in matches_alt: + + #Realiza un control de las series que se añaden, ya que el buscador devuelve episodios y no las series completas + #Se analiza si la url de la serie ya se ha listado antes. Si es así, esa entrada se ignora + #Cuando llega al num. máximo de entradas por página, la pinta y guarda los contadores y la lista de series + scrapedurl_alt = scrapedurl + if "pelisyseries.com" in host: #Excepción para mispelisyseries.com. + scrapedurl_alt = re.sub(r'\/[c|C]ap.*?-\d+-al-\d+', '', scrapedurl_alt) #Scrapeo el capítulo para hacerlo serie + scrapedurl_alt = re.sub(r'\/[c|C]ap.*?-\d+', '', scrapedurl_alt) #Scrapeo el capítulo para hacerlo serie + scrapedurl_alt = re.sub(r'\/[c|C]ap.*?-', '', scrapedurl_alt) #Scrapeo el capítulo para hacerlo serie + scrapedurl_alt = re.sub(r'\/\d{5,7}', '', scrapedurl_alt) #Scrapeo el capítulo para hacerlo serie + if scrapedurl_alt in title_lista_alt: # si ya se ha tratado, pasamos al siguiente item + continue # solo guardamos la url para series y docus + + if scrapedurl_alt in title_lista_alt or scrapedurl_alt in title_lista_alt_for: # si ya se ha tratado, pasamos al siguiente item + continue # solo guardamos la url para series y docus + + if ".com/serie" in scrapedurl or "/serie" in scrapedurl or "-serie" in scrapedurl or "varios/" in scrapedurl: + title_lista_alt_for += [scrapedurl_alt] + + if "juego/" in scrapedurl: # no mostramos lo que no sean videos + continue + cnt_title += 1 # Sería una línea real más para Itemlist + + #Control de página + if cnt_title > cnt_tot*0.65: #si se acerca al máximo num. de lineas por pagina, tratamos lo que tenemos + cnt_next = 99 #Casi completo, no sobrepasar con la siguiente página + if cnt_title > cnt_tot: + cnt_title = 99 #Sobrepasado el máximo. Ignoro página actual + item.post = post_actual #Restauro puntero "next" a la página actual, para releearla en otra pasada + post_num -= 1 #Restauro puntero a la página actual en el pie de página + break + + if cnt_title <= cnt_tot: + matches.extend(matches_alt) #Acumulamos las entradas a tratar. Si nos hemos pasado ignoro última página + title_lista_alt.extend(title_lista_alt_for) + + #logger.debug("PATRON: " + pattern) + #logger.debug(matches) + #logger.debug(title_lista_alt) + #logger.debug(data) + + cnt_title = 0 + for scrapedurl, scrapedtitle, scrapedthumbnail, calidad, year, size in matches: + cnt_pag += 1 + + #Realiza un control de las series que se añaden, ya que el buscador devuelve episodios y no las series completas + #Se analiza si la url de la serie ya se ha listado antes. Si es así, esa entrada se ignora + #El control de página ya se ha realizado más arriba + if "pelisyseries.com" in host: #Excepción para mispelisyseries.com. + scrapedurl_alt = scrapedurl + scrapedurl_alt = re.sub(r'\/[c|C]ap.*?-\d+-al-\d+', '', scrapedurl_alt) #Scrapeo el capítulo para hacerlo serie + scrapedurl_alt = re.sub(r'\/[c|C]ap.*?-\d+', '', scrapedurl_alt) #Scrapeo el capítulo para hacerlo serie + scrapedurl_alt = re.sub(r'\/[c|C]ap.*?-', '', scrapedurl_alt) #Scrapeo el capítulo para hacerlo serie + scrapedurl_alt = re.sub(r'\/\d{5,7}', '', scrapedurl_alt) #Scrapeo el capítulo para hacerlo serie + if scrapedurl_alt in title_lista: # si ya se ha tratado, pasamos al siguiente item + continue # solo guardamos la url para series y docus + + if scrapedurl in title_lista: # si ya se ha tratado, pasamos al siguiente item + continue # solo guardamos la url para series y docus + + if ".com/serie" in scrapedurl or "/serie" in scrapedurl or "-serie" in scrapedurl or "varios/" in scrapedurl: + if "pelisyseries.com" in host: + title_lista += [scrapedurl_alt] + else: + title_lista += [scrapedurl] + if "juego/" in scrapedurl or "xbox" in scrapedurl.lower() or "xbox" in scrapedtitle.lower() or "windows" in scrapedtitle.lower() or "windows" in calidad.lower() or "nintendo" in scrapedtitle.lower() or "xbox" in calidad.lower() or "epub" in calidad.lower() or "pdf" in calidad.lower() or "pcdvd" in calidad.lower() or "crack" in calidad.lower(): # no mostramos lo que no sean videos + continue + cnt_title += 1 # Sería una línea real más para Itemlist + + #Creamos una copia de Item para cada contenido + item_local = item.clone() + if item_local.category: + del item_local.category + if item_local.tipo: + del item_local.tipo + if item_local.totalItems: + del item_local.totalItems + if item_local.post: + del item_local.post + if item_local.pattern: + del item_local.pattern + if item_local.title_lista: + del item_local.title_lista + item_local.adult = True + del item_local.adult + item_local.folder = True + del item_local.folder + item_local.title = '' + item_local.context = "['buscar_trailer']" + + #Establecemos los valores básicos en función del tipo de contenido + if (".com/serie" in scrapedurl or "/serie" in scrapedurl or "-serie" in scrapedurl) and not "/miniseries" in scrapedurl: #Series + item_local.action = "episodios" + item_local.contentType = "tvshow" + item_local.extra = "series" + elif "varios/" in scrapedurl or "/miniseries" in scrapedurl: #Documentales y varios + item_local.action = "findvideos" + item_local.contentType = "movie" + item_local.extra = "varios" + else: #Películas + item_local.action = "findvideos" + item_local.contentType = "movie" + item_local.extra = "peliculas" + + # Limpiamos títulos, Sacamos datos de calidad, audio y lenguaje + title = re.sub('\r\n', '', scrapedtitle).decode('iso-8859-1').encode('utf8').strip() + title = title.replace("á", "a").replace("é", "e").replace("í", "i").replace("ó", "o").replace("ú", "u").replace("ü", "u").replace("�", "ñ").replace("ñ", "ñ") + + item_local.quality = scrapertools.htmlclean(calidad) + 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() or ".com/pelicula/" in scrapedurl or ".com/series-vo" in scrapedurl or "-vo/" in scrapedurl or "vos" in calidad.lower() or "vose" in calidad.lower() or "v.o.s" in calidad.lower() or "sub" in calidad.lower() or ".com/peliculas-vo" in item.url: + item_local.language += ["VOS"] + title = title.replace(" [Subs. integrados]", "").replace(" [subs. Integrados]", "").replace(" [VOSE", "").replace(" [VOS", "").replace(" (V.O.S.E)", "").replace(" VO", "").replace("Subtitulos", "") + if "latino" in title.lower() or "argentina" in title.lower() or "-latino/" in scrapedurl or "latino" in calidad.lower() or "argentina" in calidad.lower(): + item_local.language += ["LAT"] + + #Guardamos info de 3D en calidad y limpiamos + if "3d" in title.lower(): + if not "3d" in item_local.quality.lower(): + item_local.quality = "3D " + item_local.quality + calidad3D = scrapertools.find_single_match(title, r'\s(3[d|D]\s\w+)') + if calidad3D: + item_local.quality = item_local.quality.replace("3D", calidad3D) + title = re.sub(r'\s3[d|D]\s\w+', '', title) + title = re.sub(r'\s3[d|D]', '', title) + if "imax" in title.lower(): + item_local.quality = item_local.quality + " IMAX" + title = title.replace(" IMAX", "").replace(" imax", "") + if "2d" in title.lower(): + title = title.replace("(2D)", "").replace("(2d)", "").replace("2D", "").replace("2d", "") + title_subs += ["[2D]"] + + #Extraemos info adicional del título y la guardamos para después de TMDB + if ("temp" in title.lower() or "cap" in title.lower()) and item_local.contentType != "movie": + #Eliminamos Temporada de Series, solo nos interesa la serie completa + title = re.sub(r' - [t|T]emp\w+ \d+ Comp\w+\d+[x|X]\d+', ' Completa', title) + title = re.sub(r' - [t|T]emp\w+ \d+[x|X]\d+', '', title) + title = re.sub(r' - [t|T]emp\w+ \d+', '', title) + title = re.sub(r' - [t|T]emp\w+.*?\d+', '', title) + title = re.sub(r' [t|T]emp.*?\d+[x|X]\d+', '', title) + title = re.sub(r' [t|T]emp.*?\d+', '', title) + title = re.sub(r' [c|C]ap.*?\d+', '', title) + 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.lower() or "multileng" in title.lower() or "multileng" in item_local.quality.lower() or (("espa" in title.lower() or "spani" in title.lower()) and "VOS" in item_local.language): + item_local.language[0:0] = ["DUAL"] + title = re.sub(r'\[[D|d]ual.*?\]', '', title) + title = re.sub(r'\[[M|m]ultileng.*?\]', '', title) + item_local.quality = re.sub(r'\[[M|m]ultileng.*?\]', '', item_local.quality) + if "duolog" in title.lower(): + title_subs += ["[Saga]"] + title = title.replace(" Duologia", "").replace(" duologia", "").replace(" Duolog", "").replace(" duolog", "") + if "trilog" in title.lower(): + title_subs += ["[Saga]"] + title = title.replace(" Trilogia", "").replace(" trilogia", "").replace(" Trilog", "").replace(" trilog", "") + if "extendida" in title.lower(): + title_subs += ["[V. Extendida]"] + title = title.replace(" Version Extendida", "").replace(" (Version Extendida)", "").replace(" V. Extendida", "").replace(" VExtendida", "").replace(" V Extendida", "") + if "saga" in title.lower(): + title = title.replace(" Saga Completa", "").replace(" saga completa", "").replace(" Saga", "").replace(" saga", "") + title_subs += ["[Saga]"] + if "colecc" in title.lower() or "completa" in title.lower(): + title = title.replace(" Coleccion", "").replace(" coleccion", "").replace(" Colecci", "").replace(" colecci", "").replace(" Completa", "").replace(" completa", "").replace(" COMPLETA", "") + title_subs += ["[Saga]"] + if scrapertools.find_single_match(title, r'(- [m|M].*?serie ?\w+)'): + title = re.sub(r'- [m|M].*?serie ?\w+', '', title) + title_subs += ["[Miniserie]"] + + #Limpiamos restos en título + title = title.replace("Castellano", "").replace("castellano", "").replace("inglés", "").replace("ingles", "").replace("Inglés", "").replace("Ingles", "").replace("Ing", "").replace("Eng", "").replace("Calidad", "").replace("de la Serie", "") + + #Limpiamos cabeceras y colas del título + title = re.sub(r'Descargar\s\w+\-\w+', '', title) + title = re.sub(r'\(COMPLE.*?\)', '', title) + title = re.sub(r'\(\d{4}\)$', '', title) + title = re.sub(r'\d{4}$', '', title) + title = re.sub(r' \d+x\d+', '', title) + title = re.sub(r' x\d+', '', title) + + title = title.replace("Ver online ", "").replace("Descarga Serie HD ", "").replace("Descargar Serie HD ", "").replace("Descarga Serie ", "").replace("Descargar Serie ", "").replace("Ver en linea ", "").replace("Ver en linea", "").replace("HD ", "").replace("(Proper)", "").replace("RatDVD", "").replace("DVDRiP", "").replace("DVDRIP", "").replace("DVDRip", "").replace("DVDR", "").replace("DVD9", "").replace("DVD", "").replace("DVBRIP", "").replace("DVB", "").replace("LINE", "").replace("- ES ", "").replace("ES ", "").replace("COMPLETA", "").replace("(", "-").replace(")", "-").replace(".", " ").strip() + + title = title.replace("Descargar torrent ", "").replace("Descarga Gratis ", "").replace("Descargar Estreno ", "").replace("Descargar Estrenos ", "").replace("Pelicula en latino ", "").replace("Descargar Pelicula ", "").replace("Descargar Peliculas ", "").replace("Descargar peliculas ", "").replace("Descargar Todas ", "").replace("Descargar Otras ", "").replace("Descargar ", "").replace("Descarga ", "").replace("Bajar ", "").replace("HDRIP ", "").replace("HDRiP ", "").replace("HDRip ", "").replace("RIP ", "").replace("Rip", "").replace("RiP", "").replace("XviD", "").replace("AC3 5.1", "").replace("AC3", "").replace("1080p ", "").replace("720p ", "").replace("DVD-Screener ", "").replace("TS-Screener ", "").replace("Screener ", "").replace("BdRemux ", "").replace("BR ", "").replace("4KULTRA", "").replace("FULLBluRay", "").replace("FullBluRay", "").replace("BluRay", "").replace("Bonus Disc", "").replace("de Cine ", "").replace("TeleCine ", "").replace("latino", "").replace("Latino", "").replace("argentina", "").replace("Argentina", "").strip() + + if "pelisyseries.com" in host and item_local.contentType == "tvshow": + titulo = '' + title = title.lower() + title = re.sub(r'\d+[x|X]\d+', '', title) + while len(title) > 0: + palabra = scrapertools.find_single_match(title, r'(^[A-Za-z0-9_.-?ñ]+)') + if not palabra: + break + title = title.replace(palabra, '') + title = re.sub(r'^\s+\??', '', title) + title = re.sub(r'^-\s?', '', title) + titulo += palabra + " " + palabra = "" + title = titulo.title() + + if title.endswith("torrent gratis"): title = title[:-15] + if title.endswith("gratis"): title = title[:-7] + if title.endswith("torrent"): title = title[:-8] + if title.endswith("en HD"): title = title[:-6] + if title.endswith(" -"): title = title[:-2] + if "en espa" in title: title = title[:-11] + #title = re.sub(r'^\s', '', title) + title = title.replace("a?o", 'año').replace("a?O", 'año').replace("A?o", 'Año').replace("A?O", 'Año').strip() + + #Preparamos calidad + item_local.quality = item_local.quality.replace("[ ", "").replace(" ]", "") #Preparamos calidad para Series + item_local.quality = re.sub(r'\[\d{4}\]', '', item_local.quality) #Quitar año, si lo tiene + item_local.quality = re.sub(r'\[Cap.*?\]', '', item_local.quality) #Quitar episodios, si lo tiene + item_local.quality = re.sub(r'\[Docu.*?\]', '', item_local.quality) #Quitar tipo contenidos, si lo tiene + #Mirar si es DUAL + if "VOS" in item_local.language and "DUAL" not in item_local.language and ("[sp" in item_local.quality.lower() or "espa" in item_local.quality.lower() or "cast" in item_local.quality.lower() or "spani" in item_local.quality.lower()): + item_local.language[0:0] = ["DUAL"] + if ("[es-" in item_local.quality.lower() or (("cast" in item_local.quality.lower() or "espa" in item_local.quality.lower() or "spani" in item_local.quality.lower()) and ("eng" in item_local.quality.lower() or "ing" in item_local.quality.lower()))) and "DUAL" not in item_local.language: #Mirar si es DUAL + item_local.language[0:0] = ["DUAL"] #Salvar DUAL en idioma + item_local.quality = re.sub(r'\[[es|ES]-\w+]', '', item_local.quality) #borrar DUAL + item_local.quality = re.sub(r'[\s|-][c|C]aste.+', '', item_local.quality) #Borrar después de Castellano + item_local.quality = re.sub(r'[\s|-][e|E]spa.+', '', item_local.quality) #Borrar después de Español + item_local.quality = re.sub(r'[\s|-|\[][s|S]pani.+', '', item_local.quality) #Borrar después de Spanish + item_local.quality = re.sub(r'[\s|-][i|I|e|E]ngl.+', '', item_local.quality) #Borrar después de Inglés-English + item_local.quality = item_local.quality.replace("[", "").replace("]", " ").replace("ALTA DEFINICION", "HDTV").replace(" Cap", "") + #Borrar palabras innecesarias restantes + item_local.quality = item_local.quality.replace("Espaol", "").replace("Español", "").replace("Espa", "").replace("Castellano ", "").replace("Castellano", "").replace("Spanish", "").replace("English", "").replace("Ingles", "").replace("Latino", "").replace("+Subs", "").replace("-Subs", "").replace("Subs", "").replace("VOSE", "").replace("VOS", "").strip() + + #Limpieza final del título y guardado en las variables según su tipo de contenido + item_local.title = title + if item_local.contentType == "movie": + item_local.contentTitle = title + size = size.replace(".", ",") + item_local.quality = '%s [%s]' % (item_local.quality, size) + else: + item_local.contentSerieName = title + + #Guardamos el resto de variables del vídeo + item_local.url = scrapedurl + item_local.thumbnail = scrapedthumbnail + item_local.contentThumbnail = scrapedthumbnail + + #Guardamos el año que puede venir en la url, por si luego no hay resultados desde TMDB + if year >= "1900" and year <= "2040" and year != "2020": + title_subs += [year] + item_local.infoLabels['year'] = '-' + + #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 + + # Codigo para rescatar lo que se pueda en pelisy.series.com de Series para la Videoteca. la URL apunta al capítulo y no a la Serie. Nombre de Serie frecuentemente en blanco. Se obtiene de Thumb, así como el id de la serie + if ("/serie" in item_local.url or "-serie" in item_local.url) and "pelisyseries.com" in host: + #Extraer la calidad de la serie basados en la info de la url + if "seriehd" in url: + calidad_mps = "series-hd/" + elif "serievo" in url or "serie-vo" in url: + calidad_mps = "series-vo/" + else: + calidad_mps = "series/" + + if "no_image" in scrapedthumbnail: + real_title_mps = item_local.title + else: + real_title_mps = re.sub(r'.*?\/\d+_', '', scrapedthumbnail) + real_title_mps = re.sub(r'\.\w+.*?', '', real_title_mps) + + #Extraer el ID de la serie desde Thumbs (4 dígitos). Si no hay, nulo + if "/0_" not in scrapedthumbnail and not "no_image" in scrapedthumbnail: + serieid = scrapertools.find_single_match(scrapedthumbnail, r'.*?\/\w\/(?P<serieid>\d+).*?.*') + if len(serieid) > 5: + serieid = "" + else: + serieid = "" + + #detectar si la url creada de tvshow es válida o hay que volver atras + url_id = host + calidad_mps + real_title_mps + "/" + serieid #A veces necesita el serieid... + url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar... + + #Leemos la página, a ver si es una página de episodios + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data) + data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") + data_serie = data_serie.replace("chapters", "buscar-list") + + pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios + if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página, + #intentarlo con la otra url + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data) + data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") + data_serie = data_serie.replace("chapters", "buscar-list") + + if not scrapertools.find_single_match(data_serie, pattern): #No ha habido suerte ... + item_local.contentType = "movie" #tratarlo el capítulo como película + item_local.extra = "peliculas" + else: + item_local.url = url_tvshow #Cambiamos url de episodio por el de serie + else: + item_local.url = url_id #Cambiamos url de episodio por el de serie + + #logger.debug("url: " + item_local.url + " / title o/n: " + item_local.title + " / " + real_title_mps + " / calidad_mps : " + calidad_mps + " / contentType : " + item_local.contentType) + + item_local.title = real_title_mps #Esperemos que el nuevo título esté bien + + #Agrega el item local a la lista itemlist + itemlist.append(item_local.clone()) + + 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, __modo_grafico__) + + #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB + item, itemlist = generictools.post_tmdb_listado(item, itemlist) + + if post: + itemlist.append(item.clone(channel=item.channel, action="listado_busqueda", title="[COLOR gold][B]Pagina siguiente >> [/B][/COLOR]" + str(post_num) + " de " + str(total_pag), thumbnail=get_thumb("next.png"), title_lista=title_lista, cnt_pag=cnt_pag)) + + #logger.debug("Titulos: " + str(len(itemlist)) + " Matches: " + str(len(matches)) + " Post: " + str(item.post) + " / " + str(post_actual) + " / " + str(total_pag)) + + return itemlist + +def findvideos(item): + from core import channeltools + logger.info() + + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() + + itemlist = [] + + # Cualquiera de las tres opciones son válidas + # item.url = item.url.replace(".com/",".com/ver-online/") + # item.url = item.url.replace(".com/",".com/descarga-directa/") + item.url = item.url.replace(".com/", ".com/descarga-torrent/") + + #Función para limitar la verificación de enlaces de Servidores para Ver online y Descargas + try: + #Inicializamos las variables por si hay un error en medio del proceso + channel_exclude = [] + ver_enlaces = [] + ver_enlaces_veronline = -1 #Ver todos los enlaces Ver Online + verificar_enlaces_veronline = -1 #Verificar todos los enlaces Ver Online + verificar_enlaces_veronline_validos = True #"¿Contar sólo enlaces 'verificados' en Ver Online?" + excluir_enlaces_veronline = [] #Lista vacía de servidores excluidos en Ver Online + ver_enlaces_descargas = 0 #Ver todos los enlaces Descargar + verificar_enlaces_descargas = -1 #Verificar todos los enlaces Descargar + verificar_enlaces_descargas_validos = True #"¿Contar sólo enlaces 'verificados' en Descargar?" + excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar + + #Leemos las opciones de permitir Servidores para Ver Online y Descargas + #Cargamos en .json del canal para ver las listas de valores en settings + channel_exclude = channeltools.get_channel_json(item.channel) + for settings in channel_exclude['settings']: #Se recorren todos los settings + if settings['id'] == "clonenewpct1_excluir1_enlaces_veronline": #lista de enlaces a excluir + max_excl = int(settings['max_excl']) #Máximo número de servidores excluidos + channel_exclude = settings['lvalues'] #Cargamos la lista de servidores + if settings['id'] == "clonenewpct1_ver_enlaces_descargas": #Número de enlances a ver o verificar + ver_enlaces = settings['lvalues'] #Cargamos la lista de num. de enlaces + + #Primer loop para enlaces de Ver Online. + #Carga la variable de ver + ver_enlaces_veronline = int(config.get_setting("clonenewpct1_ver_enlaces_veronline", item.channel)) + if ver_enlaces_veronline == 1: #a "Todos" le damos valor -1. Para "No" dejamos 0 + ver_enlaces_veronline = -1 + if ver_enlaces_veronline > 1: #para los demás valores, tomamos los de la lista + ver_enlaces_veronline = int(ver_enlaces[ver_enlaces_veronline]) + + #Carga la variable de verificar + verificar_enlaces_veronline = int(config.get_setting("clonenewpct1_verificar_enlaces_veronline", item.channel)) + if verificar_enlaces_veronline == 1: #a "Todos" le damos valor -1. Para "No" dejamos 0 + verificar_enlaces_veronline = -1 + if verificar_enlaces_veronline > 1: #para los demás valores, tomamos los de la lista + verificar_enlaces_veronline = int(ver_enlaces[verificar_enlaces_veronline]) + + #Carga la variable de contar sólo los servidores verificados + verificar_enlaces_veronline_validos = int(config.get_setting("clonenewpct1_verificar_enlaces_veronline_validos", item.channel)) + + #Carga la variable de lista de servidores excluidos + x = 1 + for x in range(1, max_excl+1): #recorremos todas las opciones de canales exluidos + valor = str(config.get_setting("clonenewpct1_excluir%s_enlaces_veronline" % x, item.channel)) + valor = int(valor) + if valor > 0: #Evitamos "No" + excluir_enlaces_veronline += [channel_exclude[valor]] #Añadimos el nombre de servidor excluido a la lista + x += 1 + + #Segundo loop para enlaces de Descargar. + #Carga la variable de ver + ver_enlaces_descargas = int(config.get_setting("clonenewpct1_ver_enlaces_descargas", item.channel)) + if ver_enlaces_descargas == 1: #a "Todos" le damos valor -1. Para "No" dejamos 0 + ver_enlaces_descargas = -1 + if ver_enlaces_descargas > 1: #para los demás valores, tomamos los de la lista + ver_enlaces_descargas = int(ver_enlaces[ver_enlaces_descargas]) + + #Carga la variable de verificar + verificar_enlaces_descargas = int(config.get_setting("clonenewpct1_verificar_enlaces_descargas", item.channel)) + if verificar_enlaces_descargas == 1: #a "Todos" le damos valor -1. Para "No" dejamos 0 + verificar_enlaces_descargas = -1 + if verificar_enlaces_descargas > 1: #para los demás valores, tomamos los de la lista + verificar_enlaces_descargas = int(ver_enlaces[verificar_enlaces_descargas]) + + #Carga la variable de contar sólo los servidores verificados + verificar_enlaces_descargas_validos = int(config.get_setting("clonenewpct1_verificar_enlaces_descargas_validos", item.channel)) + + #Carga la variable de lista de servidores excluidos + x = 1 + for x in range(1, max_excl+1): #recorremos todas las opciones de canales exluidos + valor = str(config.get_setting("clonenewpct1_excluir%s_enlaces_descargas" % x, item.channel)) + valor = int(valor) + if valor > 0: #Evitamos "No" + excluir_enlaces_descargas += [channel_exclude[valor]] #Añadimos el nombre de servidor excluido a la lista + x += 1 + + except Exception, ex: #En caso de error, lo mostramos y reseteamos todas las variables + logger.error("Error en la lectura de parámentros del .json del canal: " + item.channel + " \n%s" % ex) + #Mostrar los errores + logger.error(ver_enlaces_veronline) + logger.error(verificar_enlaces_veronline) + logger.error(verificar_enlaces_veronline_validos) + logger.error(excluir_enlaces_veronline) + logger.error(ver_enlaces_descargas) + logger.error(verificar_enlaces_descargas) + logger.error(verificar_enlaces_descargas_validos) + logger.error(excluir_enlaces_descargas) + #Resetear las variables a sus valores por defecto + ver_enlaces_veronline = -1 #Ver todos los enlaces Ver Online + verificar_enlaces_veronline = -1 #Verificar todos los enlaces Ver Online + verificar_enlaces_veronline_validos = True #"¿Contar sólo enlaces 'verificados' en Ver Online?" + excluir_enlaces_veronline = [] #Lista vacía de servidores excluidos en Ver Online + ver_enlaces_descargas = 0 #Ver todos los enlaces Descargar + verificar_enlaces_descargas = -1 #Verificar todos los enlaces Descargar + verificar_enlaces_descargas_validos = True #"¿Contar sólo enlaces 'verificados' en Descargar?" + excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar + + # Descarga la página + data = '' + try: + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).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.category + ': 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") + + #Añadimos el tamaño para todos + size = scrapertools.find_single_match(data, '<div class="entry-left".*?><a href=".*?span class=.*?>Size:<\/strong>?\s(\d+?\.?\d*?\s\w[b|B])<\/span>') + size = size.replace(".", ",") #sustituimos . por , porque Unify lo borra + if not size: + size = scrapertools.find_single_match(item.quality, '\s\[(\d+,?\d*?\s\w[b|B])\]') + 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 + item, itemlist = generictools.post_tmdb_findvideos(item, itemlist) + + #Generamos una copia de Item para trabajar sobre ella + item_local = item.clone() + + # obtenemos la url torrent + 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) + itemlist.append(item.clone(action='', title=item.category + ': 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 + item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso + #logger.debug("Patron: " + patron + " url: " + item_local.url) + #logger.debug(data) + + #Ahora pintamos el link del Torrent, si lo hay + if item_local.url: # Hay 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 + + 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) + #logger.debug(item_local) + + # VER vídeos, descargar vídeos un link, o múltiples links + data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados + + host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") + data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(") + data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data) + + # Nuevo sistema de scrapeo de servidores creado por Torrentlocula, compatible con otros clones de Newpct1 + patron = '<div class=\"box1\"[^<]+<img src=\"([^<]+)?" style[^<]+><\/div[^<]+<div class="box2">([^<]+)?<\/div[^<]+<div class="box3">([^<]+)?' + patron += '<\/div[^<]+<div class="box4">([^<]+)?<\/div[^<]+<div class="box5"><a href=(.*?)? rel.*?' + patron += '<\/div[^<]+<div class="box6">([^<]+)?<' + + enlaces_ver = re.compile(patron, re.DOTALL).findall(data) + enlaces_descargar = enlaces_ver + #logger.debug(enlaces_ver) + + #Recorre todos los links de VER, si está permitido + cnt_enl_ver = 1 + cnt_enl_verif = 1 + for logo, servidor, idioma, calidad, enlace, title in enlaces_ver: + if ver_enlaces_veronline == 0: #Si no se quiere Ver Online, se sale del bloque + break + if "ver" in title.lower(): + servidor = servidor.replace("streamin", "streaminto") + + if servidor.capitalize() in excluir_enlaces_veronline: #Servidor excluido, pasamos al siguiente + continue + mostrar_server = True + if config.get_setting("hidepremium"): #Si no se aceptan servidore premium, se ignoran + mostrar_server = servertools.is_server_enabled(servidor) + + #logger.debug("VER: url: " + enlace + " / title: " + title + " / servidor: " + servidor + " / idioma: " + idioma) + + #Si el servidor es válido, se comprueban si los links están activos + if mostrar_server: + try: + if cnt_enl_ver <= ver_enlaces_veronline or ver_enlaces_veronline == -1: + devuelve = servertools.findvideosbyserver(enlace, servidor) #existe el link ? + if verificar_enlaces_veronline == 0: + cnt_enl_ver += 1 + else: + break #Si se ha agotado el contador de verificación, se sale de Ver Online + + if devuelve: #Hay link + enlace = devuelve[0][1] #Se guarda el link + item_local.alive = "??" #Se asume poe defecto que es link es dudoso + if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo? + if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador? + #Llama a la subfunción de check_list_links(itemlist) para cada link de servidor + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? + if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos? + if item_local.alive == "Ok": #Sí + cnt_enl_verif += 1 #Movemos los contadores + cnt_enl_ver += 1 #Movemos los contadores + else: #Si no es necesario que sean links válidos, sumamos + cnt_enl_verif += 1 #Movemos los contadores + cnt_enl_ver += 1 #Movemos los contadores + else: + break #Si se ha agotado el contador de verificación, se sale de Ver Online + + #Si el link no está activo se ignora + if item_local.alive == "??": #dudoso + item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][%s][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (servidor.capitalize(), item_local.quality, str(item_local.language)) + elif item_local.alive.lower() == "no": #No está activo. Lo preparo, pero no lo pinto + item_local.title = '[COLOR red][%s][/COLOR] [COLOR yellow][%s][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.alive, servidor.capitalize(), item_local.quality, str(item_local.language)) + logger.debug(item_local.alive + ": ALIVE / " + title + " / " + servidor + " / " + enlace) + raise + else: #Sí está activo + item_local.title = '[COLOR yellow][%s][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (servidor.capitalize(), item_local.quality, str(item_local.language)) + + #Preparamos el resto de variables de Item para ver los vídeos en directo + item_local.action = "play" + item_local.server = servidor + item_local.url = enlace + 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() + itemlist.append(item_local.clone()) + except: + pass + + #Ahora vemos los enlaces de DESCARGAR + if len(enlaces_descargar) > 0 and ver_enlaces_descargas != 0: + + #Pintamos un pseudo-título de Descargas + if not item.unify: #Si Titulos Inteligentes NO seleccionados: + itemlist.append(item_local.clone(title="[COLOR gold]**- Enlaces Descargar: -**[/COLOR]", action="")) + else: + itemlist.append(item_local.clone(title="[COLOR gold] Enlaces Descargar: [/COLOR]", action="")) + + #Recorre todos los links de DESCARGAR + cnt_enl_ver = 1 + cnt_enl_verif = 1 + for logo, servidor, idioma, calidad, enlace, title in enlaces_descargar: + if ver_enlaces_descargas == 0: + break + + if "Ver" not in title: + servidor = servidor.replace("uploaded", "uploadedto") + partes = enlace.split(" ") #Partimos el enlace en cada link de las partes + title = "Descarga" #Usamos la palabra reservada de Unify para que no formatee el título + + if servidor.capitalize() in excluir_enlaces_descargas: #Servidor excluido, pasamos al siguiente + continue + + #logger.debug("DESCARGAR: url: " + enlace + " / title: " + title + title + " / servidor: " + servidor + " / idioma: " + idioma) + + #Recorremos cada una de las partes. Vemos si el primer link está activo. Si no lo está ignoramos todo el enlace + p = 1 + for enlace in partes: + if not item.unify: #Si titles Inteligentes NO seleccionados: + parte_title = "[COLOR yellow][%s][/COLOR] %s (%s/%s) [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]" % (servidor.capitalize(), title, p, len(partes), item_local.quality, str(item_local.language)) + else: + parte_title = "[COLOR yellow]%s-[/COLOR] %s %s/%s [COLOR limegreen]-%s[/COLOR] [COLOR red]-%s[/COLOR]" % (servidor.capitalize(), title, p, len(partes), item_local.quality, str(item_local.language)) + p += 1 + mostrar_server = True + if config.get_setting("hidepremium"): #Si no se aceptan servidore premium, se ignoran + mostrar_server = servertools.is_server_enabled(servidor) + + #Si el servidor es válido, se comprueban si los links están activos + if mostrar_server: + try: + if cnt_enl_ver <= ver_enlaces_descargas or ver_enlaces_descargas == -1: + devuelve = servertools.findvideosbyserver(enlace, servidor) #activo el link ? + if verificar_enlaces_descargas == 0: + cnt_enl_ver += 1 + else: + ver_enlaces_descargas = 0 #FORZAR SALIR de DESCARGAS + break #Si se ha agotado el contador de verificación, se sale de "Enlace" + + if devuelve: + enlace = devuelve[0][1] + + #Verifica si está activo el primer link. Si no lo está se ignora el enlace-servidor entero + if p <= 2: + item_local.alive = "??" #Se asume poe defecto que es link es dudoso + if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo? + if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador? + #Llama a la subfunción de check_list_links(itemlist) para primer link de servidor + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? + if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos? + if item_local.alive == "Ok": #Sí + cnt_enl_verif += 1 #Movemos los contadores + cnt_enl_ver += 1 #Movemos los contadores + else: #Si no es necesario que sean links válidos, sumamos + cnt_enl_verif += 1 #Movemos los contadores + cnt_enl_ver += 1 #Movemos los contadores + else: + ver_enlaces_descargas = 0 #FORZAR SALIR de DESCARGAS + break #Si se ha agotado el contador de verificación, se sale de "Enlace" + + if item_local.alive == "??": #dudoso + if not item.unify: #Si titles Inteligentes NO seleccionados: + parte_title = '[COLOR yellow][?][/COLOR] %s' % (parte_title) + else: + parte_title = '[COLOR yellow]%s[/COLOR]-%s' % (item_local.alive, parte_title) + elif item_local.alive.lower() == "no": #No está activo. Lo preparo, pero no lo pinto + if not item.unify: #Si titles Inteligentes NO seleccionados: + parte_title = '[COLOR red][%s][/COLOR] %s' % (item_local.alive, parte_title) + else: + parte_title = '[COLOR red]%s[/COLOR]-%s' % (item_local.alive, parte_title) + logger.debug(item_local.alive + ": ALIVE / " + title + " / " + servidor + " / " + enlace) + break + + #Preparamos el resto de variables de Item para descargar los vídeos + item_local.action = "play" + item_local.server = servidor + item_local.url = enlace + item_local.title = parte_title.replace("[]", "").strip() + item_local.title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', item_local.title).strip() + item_local.title = re.sub(r'\[COLOR \w+\]-\[\/COLOR\]', '', item_local.title).strip() + itemlist.append(item_local.clone()) + except: + pass + + return itemlist + + +def episodios(item): + logger.info() + + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').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+)' + matches = re.compile(patron, re.DOTALL).findall(str(item.library_playcounts)) + for x in matches: + y += [int(x)] + max_temp = max(y) + + data = '' + try: + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data) + patron = '<ul class="%s">(.*?)</ul>' % "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 = '<li[^>]*><div class.*?src="(?P<thumb>[^"]+)?".*?<a class.*?href="(?P<url>[^"]+).*?<h3[^>]+>(?P<info>.*?)?<\/h3>.*?<\/li>' + else: + pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2[^>]+>(?P<info>.*?)?<\/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.category + ': 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 + + #Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página + pattern = '<ul class="%s">(.*?)</ul>' % "pagination" # item.pattern + pagination = scrapertools.find_single_match(data, pattern) + if pagination: + if "/pg/" in item.url: + act_page = int(scrapertools.find_single_match(item.url, r'\/pg\/(\d+)')) #Num página actual + else: + act_page = 1 + pattern = '<li><a href="([^"]+)">Last<\/a>' #Busca última página + full_url = scrapertools.find_single_match(pagination, pattern) + url, last_page = scrapertools.find_single_match(full_url, r'(.*?\/pg\/)(\d+)') + last_page = int(last_page) + list_pages = [item.url] + for x in range(act_page + 1, last_page + 1): #carga cada página para obtener la url de la siguiente + #LAS SIGUIENTES 3 LINEAS ANULADAS: no es necesario leer la pagína siguiente. Se supone que está activa + #response = httptools.downloadpage('%s%s'% (url,x)) + #if response.sucess: + # list_pages.append("%s%s" % (url, x)) #Guarda la url de la siguiente página en una lista + list_pages.append("%s%s" % (url, x)) #Guarda la url de la siguiente página en una lista + else: + list_pages = [item.url] + + season = max_temp + #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 + for page in list_pages: #Recorre la lista de páginas + if not list_pages: + break + try: + if not data: + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data) + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com + pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern + data = scrapertools.get_match(data, pattern) + if not data: + raise + except: + 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.category + ': 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 item.url: + pattern = '<li[^>]*><div class.*?src="(?P<thumb>[^"]+)?".*?<a class.*?href="(?P<url>[^"]+).*?<h3[^>]+>(?P<info>.*?)?<\/h3>.*?<\/li>' + else: + pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2[^>]+>(?P<info>.*?)?<\/h2>' + matches = re.compile(pattern, re.DOTALL).findall(data) + if not matches: #error + logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': 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 + + #logger.debug("patron: " + pattern) + #logger.debug(matches) + + #Empezamos a generar cada episodio + for url, thumb, info in matches: + if "pelisyseries.com" in item.url: #En esta web están en diferente orden + interm = url + url = thumb + thumb = interm + + item_local = item.clone() #Creamos copia local de Item por episodio + item_local.url = url + item_local.contentThumbnail = thumb + estado = True #Buena calidad de datos por defecto + + if "<span" in info: # new style + pattern = ".*?[^>]+>.*?Temporada\s*(?P<season>\d+)?.*?Capitulo(?:s)?\s*(?P<episode>\d+)?" \ + "(?:.*?(?P<episode2>\d+)?)<.+?<span[^>]+>(?P<lang>.*?)?<\/span>\s*Calidad\s*<span[^>]+>" \ + "[\[]\s*(?P<quality>.*?)?\s*[\]]<\/span>" + if "Especial" in info: # Capitulos Especiales + pattern = ".*?[^>]+>.*?Temporada.*?\[.*?(?P<season>\d+).*?\].*?Capitulo.*?\[\s*(?P<episode>\d+).*?\]?(?:.*?(?P<episode2>\d+)?)<.+?<span[^>]+>(?P<lang>.*?)?<\/span>\s*Calidad\s*<span[^>]+>[\[]\s*(?P<quality>.*?)?\s*[\]]<\/span>" + + if not scrapertools.find_single_match(info, pattern): #en caso de error de formato, creo uno básico + logger.debug("patron episodioNEW: " + pattern) + logger.debug(info) + logger.debug(item_local.url) + info = '><strong>%sTemporada %s Capitulo 0</strong> - <span >Español Castellano</span> Calidad <span >[%s]</span>' % (item_local.contentSerieName, season, item_local.quality) + + else: # old style. Se intenta buscar un patrón que encaje con los diversos formatos antiguos. Si no, se crea + pattern = '\[(?P<quality>.*?)\]\[Cap.(?P<season>\d).*?(?P<episode>\d{2})(?:_(?P<season2>\d+)(?P<episode2>\d{2}))?\].*?(?P<lang>.*)?' #Patrón básico por defecto + + 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<season>\d+).*?[c|C]ap.*?\.(?P<episode>\d+)?.*?(?:(?P<episode2>\d+))\]?\[(?P<lang>\w+)?(?P<quality>\w+)\]?'): + pattern = 'Temp.*?(?P<season>\d+).*?[c|C]ap.*?\.(?P<episode>\d+)?.*?(?:(?P<episode2>\d+))\]?\[(?P<lang>\w+)?(?P<quality>\w+)\]?' + elif scrapertools.find_single_match(info, 'Temp.*?(?P<season>\d+).*?\[(?P<quality>.*?)\].*?(?P<episode>\d{2})?(?:.*?(?P<episode2>\d{2}))?.*?(?P<lang>\[\w+.*)\[.*?\]?'): + pattern = 'Temp.*?(?P<season>\d+).*?\[(?P<quality>.*?)\].*?(?P<episode>\d{2})?(?:.*?(?P<episode2>\d{2}))?.*?(?P<lang>\[\w+.*)\[.*?\]?' + elif scrapertools.find_single_match(info, 'Temp.*?(?P<season>\d+).*?\[(?P<quality>.*?)\].*?Cap\w?\.\s\d?(?P<episode>\d{2})(?:.*?(?P<episode2>\d{2}))?.*?\[(?P<lang>\w+)\]?'): + pattern = 'Temp.*?(?P<season>\d+).*?\[(?P<quality>.*?)\].*?Cap\w?\.\s\d?(?P<episode>\d{2})(?:.*?(?P<episode2>\d{2}))?.*?\[(?P<lang>\w+)\]?' + elif scrapertools.find_single_match(info, '\[Cap.\d{2}_\d{2}\]'): + info = re.sub(r'\[Cap.(\d{2})_(\d{2})\]', r'[Cap.1\1_1\2]', info) + elif scrapertools.find_single_match(info, '\[Cap.([A-Za-z]+)\]'): + info = re.sub(r'\[Cap.([A-Za-z]+)\]', '[Cap.100]', info) + elif "completa" in info.lower(): + info = info.replace("COMPLETA", "Caps. 01_99") + pattern = 'Temp.*?(?P<season>\d+).*?Cap\w?\.\s\d?(?P<episode>\d{2})(?:.*?(?P<episode2>\d{2}))?.*?\[(?P<quality>.*?)\].*?\[(?P<lang>\w+)\]?' + if scrapertools.find_single_match(info, '\[Cap.\d{2,3}'): + pattern = "\[(?P<quality>.*?)\].*?\[Cap.(?P<season>\d).*?(?P<episode>\d{2})(?:_(?P<season2>\d+)" \ + "(?P<episode2>\d{2}))?.*?\].*?(?:\[(?P<lang>.*?)\])?" + elif scrapertools.find_single_match(info, 'Cap.\d{2,3}'): + pattern = ".*?Temp.*?\s(?P<quality>.*?)\s.*?Cap.(?P<season>\d).*?(?P<episode>\d{2})(?:_(?P<season2>\d+)(?P<episode2>\d{2}))?.*?\s(?P<lang>.*)?" + elif scrapertools.find_single_match(info, '(?P<quality>.*?)?(?P<season>\d)[x|X|\.](?P<episode>\d{2})\s?(?:_(?P<season2>\d+)(?P<episode2>\d{2}))?.*?(?P<lang>.*)?'): + pattern = "(?P<quality>.*?)?(?P<season>\d)[x|X|\.](?P<episode>\d{2})\s?(?:_(?P<season2>\d+)(?P<episode2>\d{2}))?.*?(?P<lang>.*)?" + estado = False #Mala calidad de datos + if not scrapertools.find_single_match(info, pattern): #en caso de error de formato, creo uno básico + logger.debug("patron episodioOLD: " + pattern) + logger.debug(info) + logger.debug(item_local.url) + info = '%s - Temp.%s [%s][Cap.%s00][Spanish]' % (item_local.contentSerieName, season, item_local.quality, season) + estado = False #Mala calidad de datos + + r = re.compile(pattern) + match = [m.groupdict() for m in r.finditer(info)][0] + if not match: #error + logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info) + itemlist.append(item.clone(action='', title=item.category + ': 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 match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico + if match['episode'] is None: match['episode'] = "0" + try: + match['season'] = int(match['season']) + match['episode'] = int(match['episode']) + 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)) + + 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)) + match['season'] = season + item_local.contentSeason = season + else: + item_local.contentSeason = match['season'] + season = match['season'] + if match['episode'] > 0: + num_temporadas_flag = True + if season > max_temp: + max_temp = season + + if match['quality'] and not item_local.quality and estado == True: + 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 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 + if match["episode2"]: #Hay episodio dos? es una entrada múltiple? + item_local.title = "%sx%s al %s -" % (str(match["season"]), str(match["episode"]).zfill(2), str(match["episode2"]).zfill(2)) #Creamos un título con el rango de episodios + else: #Si es un solo episodio, se formatea ya + item_local.title = "%sx%s -" % (match["season"], str(match["episode"]).zfill(2)) + + if modo_ultima_temp and item.library_playcounts: #Si solo se actualiza la última temporada de Videoteca + if item_local.contentSeason < max_temp: + list_pages = [] #Sale del bucle de leer páginas + break #Sale del bucle actual del FOR de episodios por página + #if ('%sx%s' % (str(item_local.contentSeason), str(item_local.contentEpisodeNumber).zfill(2))) in item.library_playcounts: + # continue + + if item_local.active: + del item_local.active + if item_local.infoLabels['title']: + del item_local.infoLabels['title'] + item_local.context = "['buscar_trailer']" + item_local.action = "findvideos" + item_local.contentType = "episode" + item_local.extra = "episodios" + if item_local.library_playcounts: + del item_local.library_playcounts + if item_local.library_urls: + del item_local.library_urls + if item_local.path: + del item_local.path + if item_local.update_last: + del item_local.update_last + if item_local.update_next: + del item_local.update_next + if item_local.channel_host: + del item_local.channel_host + + itemlist.append(item_local.clone()) + + data = '' + + if len(itemlist) > 1: + itemlist = sorted(itemlist, key=lambda it: (int(it.contentSeason), int(it.contentEpisodeNumber))) #clasificamos + + # 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) + + 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): + logger.info("search:" + texto) + # texto = texto.replace(" ", "+") + + try: + item.post = "q=%s" % texto + item.pattern = "buscar-list" + itemlist = listado_busqueda(item) + + return itemlist + + # Se captura la excepción, para no interrumpir al buscador global si un canal falla + except: + import sys + for line in sys.exc_info(): + logger.error("%s" % line) + return [] + +def newest(categoria): + logger.info() + itemlist = [] + item = Item() + + item.title = "newest" + item.category = "newest" + item.action = "listado" + item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/') + + try: + if categoria == 'peliculas': + item.url = host+'peliculas/' + item.extra = "peliculas" + itemlist = listado(item) + if ">> Página siguiente" in itemlist[-1].title: + itemlist.pop() + + if categoria == 'series': + item.url = host+'series/' + item.extra = "series" + itemlist.extend(listado(item)) + if ">> Página siguiente" in itemlist[-1].title: + itemlist.pop() + + if categoria == '4k': + item.url = host+'peliculas-hd/4kultrahd/' + item.extra = "peliculas" + itemlist.extend(listado(item)) + if ">> Página siguiente" in itemlist[-1].title: + itemlist.pop() + + if categoria == 'anime': + item.url = host+'anime/' + item.extra = "peliculas" + itemlist.extend(listado(item)) + if ">> Página siguiente" in itemlist[-1].title: + itemlist.pop() + + if categoria == 'documentales': + item.url = host+'documentales/' + item.extra = "varios" + itemlist.extend(listado(item)) + if ">> Página siguiente" in itemlist[-1].title: + itemlist.pop() + + if categoria == 'latino': + item.url = host+'peliculas-latino/' + item.extra = "peliculas" + itemlist.extend(listado(item)) + if ">> Página siguiente" in itemlist[-1].title: + itemlist.pop() + + # Se captura la excepción, para no interrumpir al canal novedades si un canal falla + except: + import sys + for line in sys.exc_info(): + logger.error("{0}".format(line)) + return [] + + return itemlist diff --git a/plugin.video.alfa/channels/torrentlocura.py b/plugin.video.alfa/channels/torrentlocura.py index 5bfd66a9..04d3c7c7 100755 --- a/plugin.video.alfa/channels/torrentlocura.py +++ b/plugin.video.alfa/channels/torrentlocura.py @@ -12,40 +12,53 @@ from core import httptools from core import scrapertools from core import servertools from core.item import Item -from platformcode import config, logger +from platformcode import config, logger, platformtools from core import tmdb from lib import generictools -host = 'http://torrentlocura.com/' +channel_py = 'newpct1' #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 +clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte en array host_index = 0 -host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto +host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #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 + channel_clone_name = channel_clone #Nombre del Canal elegido + host = host_clone #URL del Canal elegido + break + i += 1 +item = Item() +item.channel_host = host +if item.channel != channel_py: + item.channel = channel_py +item.category = channel_clone_name.capitalize() #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) +__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB? +modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada? +timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage +if timeout == 0: timeout = None + +platformtools.dialog_ok("NewPct1, ¡¡¡he vuelto como canal VIRTUAL!!!", "Hemos centralizado la gestión de los clones de NewPct1 en el canal virtual NewPct1. Los clones desaparecerán en breve.", "Para más información lee el tutorial: https://alfa-addon.com /threads/newpct1-implantando-alta-disponibilidad.1200/") + +#Vayamos a la siguiente acción en el canal Newpct1 +from platformcode import launcher +channel_clone_name = "torrentlocura" #Nombre del Canal elegido +host = "http://torrentlocura.com/" +item.category = channel_clone_name.capitalize() +item.action = "mainlist" +item.channel_host = host +launcher.run(item) def mainlist(item): logger.info() + if item.channel != channel_py: + return - #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") @@ -58,20 +71,20 @@ def mainlist(item): thumb_settings = get_thumb("setting_0.png") itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=host, - extra="peliculas", thumbnail=thumb_pelis )) + extra="peliculas", thumbnail=thumb_pelis, category=item.category)) itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=host, extra="series", - thumbnail=thumb_series)) + thumbnail=thumb_series, category=item.category)) itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=host, extra="varios", - thumbnail=thumb_docus)) + thumbnail=thumb_docus, category=item.category)) itemlist.append( - Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar)) + Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar, category=item.category)) itemlist.append( - Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings)) + Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category)) itemlist.append( - Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings)) + Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category)) return itemlist @@ -85,68 +98,60 @@ def submenu(item): logger.info() itemlist = [] + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass - host_alt = host - host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") - patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>' + patron = '<li><a\s?class="[^"]+"\s?href="http:[^"]+"><i\s?class=.*><\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>' #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) + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url + 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, 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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: 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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) - host_alt = host.replace(item.channel_alt, item.channel) - del item.channel_alt if item.url_alt: del item.url_alt + del item.channel_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 = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>' - if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com - data = '<a href="' + host_alt + 'varios/" title="Documentales"><i class="icon-rocket"></i> Documentales</a>' + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = '<li><a href="' + item.channel_host + 'varios/" title="Documentales">Documentales</a></li>' else: - if data: - data = scrapertools.get_match(data, patron) - if not data: - logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: 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 - else: - return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa + if not data: + logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 - patron = '<.*?href="([^"]+)".*?>([^>]+)</a>' + patron = '<li><a.*?href="([^"]+)"\s?.itle="[^"]+"\s?>([^>]+)<\/a><\/li>' matches = re.compile(patron, re.DOTALL).findall(data) + if not matches: logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 for scrapedurl, scrapedtitle in matches: title = scrapedtitle.strip() - url = scrapedurl - itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra)) - itemlist.append( - Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra)) + #Preguntamos por las entradas que no corresponden al "extra" + if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)): + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) + itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl)) if item.extra == "peliculas": - 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_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) + itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/")) + itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/")) return itemlist @@ -155,28 +160,41 @@ def alfabeto(item): logger.info() itemlist = [] - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = '' + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") patron = '<ul class="alfabeto">(.*?)</ul>' - if data: - data = scrapertools.get_match(data, patron) - else: - return itemlist + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + 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, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: 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.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) + + if item.url_alt: del item.url_alt + del item.channel_alt + + data = scrapertools.get_match(data, patron) patron = '<a href="([^"]+)"[^>]+>([^>]+)</a>' matches = re.compile(patron, re.DOTALL).findall(data) if not matches: - logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log')) + logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: 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 for scrapedurl, scrapedtitle in matches: title = scrapedtitle.upper() - url = scrapedurl - itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra)) + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) return itemlist @@ -191,11 +209,21 @@ def listado(item): if item.totalItems: del item.totalItems + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: + pass + + patron = '<ul class="' + clase + '">(.*?)</ul>' #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, patron) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data): 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')) + #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.category + ': 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 #Establecemos los valores básicos en función del tipo de contenido @@ -218,7 +246,7 @@ def listado(item): fichas = scrapertools.get_match(data, patron) if not fichas and not '<h3><strong>( 0 ) Resultados encontrados </strong>' 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 elif '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #no hay vídeos return itemlist @@ -235,7 +263,7 @@ def listado(item): matches = re.compile(patron, re.DOTALL).findall(fichas) if not matches: #error logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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("MATCHES: " + str(len(matches))) @@ -460,13 +488,21 @@ def listado(item): def listado_busqueda(item): logger.info() - - host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/') + + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + if item.category and item.category != "newest": + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() 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 cnt_pag = 0 # Contador de líneas leídas de Matches + timeout_search = 5 # Timeout un poco más largo para las búsquedas + if timeout > 5: + timeout_search = timeout # Timeout un poco más largo para las búsquedas + data = '' if item.cnt_pag: cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item @@ -493,21 +529,21 @@ 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 = '<ul class="%s">(.*?)</ul>' % 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) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data) except: pass - cnt_next += 1 - if not data or not scrapertools.find_single_match(data, pattern): + cnt_next += 1 + pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, pattern) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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) @@ -531,7 +567,6 @@ def listado_busqueda(item): pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa data_alt = data data = scrapertools.get_match(data, pattern) - #pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2.*?>(?P<title>.*?)?<\/h2>' pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb @@ -541,7 +576,8 @@ def listado_busqueda(item): matches_alt = re.compile(pattern, re.DOTALL).findall(data) if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log')) + item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist. @@ -830,14 +866,14 @@ def listado_busqueda(item): url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar... #Leemos la página, a ver si es una página de episodios - data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).data) + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data) data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") data_serie = data_serie.replace("chapters", "buscar-list") pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página, #intentarlo con la otra url - data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).data) + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data) data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") data_serie = data_serie.replace("chapters", "buscar-list") @@ -876,9 +912,10 @@ 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() + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() itemlist = [] @@ -987,8 +1024,9 @@ def findvideos(item): excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar # Descarga la página + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass @@ -1001,7 +1039,7 @@ def findvideos(item): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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") @@ -1029,7 +1067,7 @@ def findvideos(item): 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) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso #logger.debug("Patron: " + patron + " url: " + item_local.url) @@ -1054,6 +1092,8 @@ def findvideos(item): #logger.debug(item_local) # VER vídeos, descargar vídeos un link, o múltiples links + data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados + host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(") data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data) @@ -1066,7 +1106,7 @@ def findvideos(item): enlaces_ver = re.compile(patron, re.DOTALL).findall(data) enlaces_descargar = enlaces_ver #logger.debug(enlaces_ver) - + #Recorre todos los links de VER, si está permitido cnt_enl_ver = 1 cnt_enl_verif = 1 @@ -1100,7 +1140,7 @@ def findvideos(item): if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo? if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador? #Llama a la subfunción de check_list_links(itemlist) para cada link de servidor - item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ? + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos? if item_local.alive == "Ok": #Sí cnt_enl_verif += 1 #Movemos los contadores @@ -1190,7 +1230,7 @@ def findvideos(item): if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo? if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador? #Llama a la subfunción de check_list_links(itemlist) para primer link de servidor - item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ? + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos? if item_local.alive == "Ok": #Sí cnt_enl_verif += 1 #Movemos los contadores @@ -1232,9 +1272,10 @@ 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() + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() itemlist = [] @@ -1255,7 +1296,7 @@ def episodios(item): data = '' try: - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data) patron = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern data_alt = '' if data: data_alt = scrapertools.get_match(data, patron) @@ -1276,7 +1317,7 @@ def episodios(item): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 #Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página @@ -1312,7 +1353,7 @@ def episodios(item): break try: if not data: - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern @@ -1321,7 +1362,7 @@ def episodios(item): raise except: 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 item.url: @@ -1331,7 +1372,7 @@ def episodios(item): matches = re.compile(pattern, re.DOTALL).findall(data) if not matches: #error logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 #logger.debug("patron: " + pattern) @@ -1399,7 +1440,7 @@ def episodios(item): match = [m.groupdict() for m in r.finditer(info)][0] if not match: #error logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico @@ -1449,8 +1490,6 @@ def episodios(item): if item_local.active: del item_local.active - if item_local.category: - del item_local.category if item_local.infoLabels['title']: del item_local.infoLabels['title'] item_local.context = "['buscar_trailer']" @@ -1467,6 +1506,8 @@ def episodios(item): del item_local.update_last if item_local.update_next: del item_local.update_next + if item_local.channel_host: + del item_local.channel_host itemlist.append(item_local.clone()) @@ -1501,9 +1542,6 @@ 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 f9106274..323d6468 100644 --- a/plugin.video.alfa/channels/torrentrapid.json +++ b/plugin.video.alfa/channels/torrentrapid.json @@ -53,7 +53,7 @@ "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', '')", + "default": "('1', 'torrentrapid', 'http://torrentrapid.com/', 'movie, tvshow, season, episode', ''), ('1', 'torrentlocura', 'http://torrentlocura.com/', 'movie, tvshow, season, episode', ''), ('1', 'tumejortorrent', 'http://tumejortorrent.com/', 'movie, tvshow, season, episode', ''), ('1', 'tvsinpagar', 'http://www.tvsinpagar.com/', 'tvshow, season, episode', ''), ('1', 'descargas2020', 'http://descargas2020.com/', 'movie, tvshow, season, episode', ''), ('1', 'mispelisyseries', 'http://mispelisyseries.com/', 'movie', 'search')", "enabled": true, "visible": false }, @@ -539,6 +539,27 @@ "default": true, "enabled": true, "visible": false + }, + { + "id": "clonenewpct1_timeout_downloadpage", + "type": "list", + "label": "Timeout (segs.) en descarga de páginas o verificación de servidores", + "default": 5, + "enabled": true, + "visible": true, + "lvalues": [ + "None", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10" + ] } ] } \ No newline at end of file diff --git a/plugin.video.alfa/channels/torrentrapid.py b/plugin.video.alfa/channels/torrentrapid.py index 292d7faa..ac2d77c4 100644 --- a/plugin.video.alfa/channels/torrentrapid.py +++ b/plugin.video.alfa/channels/torrentrapid.py @@ -12,40 +12,53 @@ from core import httptools from core import scrapertools from core import servertools from core.item import Item -from platformcode import config, logger +from platformcode import config, logger, platformtools from core import tmdb from lib import generictools -host = 'http://torrentrapid.com/' +channel_py = 'newpct1' #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 +clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte en array host_index = 0 -host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto +host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #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 + channel_clone_name = channel_clone #Nombre del Canal elegido + host = host_clone #URL del Canal elegido + break + i += 1 +item = Item() +item.channel_host = host +if item.channel != channel_py: + item.channel = channel_py +item.category = channel_clone_name.capitalize() #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) +__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB? +modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada? +timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage +if timeout == 0: timeout = None + +platformtools.dialog_ok("NewPct1, ¡¡¡he vuelto como canal VIRTUAL!!!", "Hemos centralizado la gestión de los clones de NewPct1 en el canal virtual NewPct1. Los clones desaparecerán en breve.", "Para más información lee el tutorial: https://alfa-addon.com /threads/newpct1-implantando-alta-disponibilidad.1200/") + +#Vayamos a la siguiente acción en el canal Newpct1 +from platformcode import launcher +channel_clone_name = "torrentrapid" #Nombre del Canal elegido +host = "http://torrentrapid.com/" +item.category = channel_clone_name.capitalize() +item.action = "mainlist" +item.channel_host = host +launcher.run(item) def mainlist(item): logger.info() + if item.channel != channel_py: + return - #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") @@ -58,20 +71,20 @@ def mainlist(item): thumb_settings = get_thumb("setting_0.png") itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=host, - extra="peliculas", thumbnail=thumb_pelis )) + extra="peliculas", thumbnail=thumb_pelis, category=item.category)) itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=host, extra="series", - thumbnail=thumb_series)) + thumbnail=thumb_series, category=item.category)) itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=host, extra="varios", - thumbnail=thumb_docus)) + thumbnail=thumb_docus, category=item.category)) itemlist.append( - Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar)) + Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar, category=item.category)) itemlist.append( - Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings)) + Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category)) itemlist.append( - Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings)) + Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category)) return itemlist @@ -85,68 +98,60 @@ def submenu(item): logger.info() itemlist = [] + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass - host_alt = host - host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") - patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>' + patron = '<li><a\s?class="[^"]+"\s?href="http:[^"]+"><i\s?class=.*><\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>' #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) + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url + 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, 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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: 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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) - host_alt = host.replace(item.channel_alt, item.channel) - del item.channel_alt if item.url_alt: del item.url_alt + del item.channel_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 = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>' - if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com - data = '<a href="' + host_alt + 'varios/" title="Documentales"><i class="icon-rocket"></i> Documentales</a>' + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = '<li><a href="' + item.channel_host + 'varios/" title="Documentales">Documentales</a></li>' else: - if data: - data = scrapertools.get_match(data, patron) - if not data: - logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: 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 - else: - return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa + if not data: + logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 - patron = '<.*?href="([^"]+)".*?>([^>]+)</a>' + patron = '<li><a.*?href="([^"]+)"\s?.itle="[^"]+"\s?>([^>]+)<\/a><\/li>' matches = re.compile(patron, re.DOTALL).findall(data) + if not matches: logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 for scrapedurl, scrapedtitle in matches: title = scrapedtitle.strip() - url = scrapedurl - itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra)) - itemlist.append( - Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra)) + #Preguntamos por las entradas que no corresponden al "extra" + if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)): + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) + itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl)) if item.extra == "peliculas": - 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_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) + itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/")) + itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/")) return itemlist @@ -155,28 +160,41 @@ def alfabeto(item): logger.info() itemlist = [] - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = '' + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") patron = '<ul class="alfabeto">(.*?)</ul>' - if data: - data = scrapertools.get_match(data, patron) - else: - return itemlist + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + 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, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: 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.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) + + if item.url_alt: del item.url_alt + del item.channel_alt + + data = scrapertools.get_match(data, patron) patron = '<a href="([^"]+)"[^>]+>([^>]+)</a>' matches = re.compile(patron, re.DOTALL).findall(data) if not matches: - logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log')) + logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: 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 for scrapedurl, scrapedtitle in matches: title = scrapedtitle.upper() - url = scrapedurl - itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra)) + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) return itemlist @@ -191,11 +209,21 @@ def listado(item): if item.totalItems: del item.totalItems + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: + pass + + patron = '<ul class="' + clase + '">(.*?)</ul>' #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, patron) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data): 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')) + #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.category + ': 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 #Establecemos los valores básicos en función del tipo de contenido @@ -218,7 +246,7 @@ def listado(item): fichas = scrapertools.get_match(data, patron) if not fichas and not '<h3><strong>( 0 ) Resultados encontrados </strong>' 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 elif '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #no hay vídeos return itemlist @@ -235,7 +263,7 @@ def listado(item): matches = re.compile(patron, re.DOTALL).findall(fichas) if not matches: #error logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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("MATCHES: " + str(len(matches))) @@ -460,13 +488,21 @@ def listado(item): def listado_busqueda(item): logger.info() - - host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/') + + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + if item.category and item.category != "newest": + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() 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 cnt_pag = 0 # Contador de líneas leídas de Matches + timeout_search = 5 # Timeout un poco más largo para las búsquedas + if timeout > 5: + timeout_search = timeout # Timeout un poco más largo para las búsquedas + data = '' if item.cnt_pag: cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item @@ -493,21 +529,21 @@ 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 = '<ul class="%s">(.*?)</ul>' % 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) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data) except: pass - cnt_next += 1 - if not data or not scrapertools.find_single_match(data, pattern): + cnt_next += 1 + pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, pattern) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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) @@ -531,7 +567,6 @@ def listado_busqueda(item): pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa data_alt = data data = scrapertools.get_match(data, pattern) - #pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2.*?>(?P<title>.*?)?<\/h2>' pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb @@ -541,7 +576,8 @@ def listado_busqueda(item): matches_alt = re.compile(pattern, re.DOTALL).findall(data) if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log')) + item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist. @@ -830,14 +866,14 @@ def listado_busqueda(item): url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar... #Leemos la página, a ver si es una página de episodios - data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).data) + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data) data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") data_serie = data_serie.replace("chapters", "buscar-list") pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página, #intentarlo con la otra url - data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).data) + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data) data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") data_serie = data_serie.replace("chapters", "buscar-list") @@ -876,9 +912,10 @@ 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() + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() itemlist = [] @@ -987,8 +1024,9 @@ def findvideos(item): excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar # Descarga la página + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass @@ -1001,7 +1039,7 @@ def findvideos(item): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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") @@ -1029,7 +1067,7 @@ def findvideos(item): 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) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso #logger.debug("Patron: " + patron + " url: " + item_local.url) @@ -1054,6 +1092,8 @@ def findvideos(item): #logger.debug(item_local) # VER vídeos, descargar vídeos un link, o múltiples links + data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados + host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(") data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data) @@ -1066,7 +1106,7 @@ def findvideos(item): enlaces_ver = re.compile(patron, re.DOTALL).findall(data) enlaces_descargar = enlaces_ver #logger.debug(enlaces_ver) - + #Recorre todos los links de VER, si está permitido cnt_enl_ver = 1 cnt_enl_verif = 1 @@ -1100,7 +1140,7 @@ def findvideos(item): if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo? if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador? #Llama a la subfunción de check_list_links(itemlist) para cada link de servidor - item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ? + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos? if item_local.alive == "Ok": #Sí cnt_enl_verif += 1 #Movemos los contadores @@ -1190,7 +1230,7 @@ def findvideos(item): if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo? if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador? #Llama a la subfunción de check_list_links(itemlist) para primer link de servidor - item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ? + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos? if item_local.alive == "Ok": #Sí cnt_enl_verif += 1 #Movemos los contadores @@ -1232,9 +1272,10 @@ 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() + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() itemlist = [] @@ -1255,7 +1296,7 @@ def episodios(item): data = '' try: - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data) patron = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern data_alt = '' if data: data_alt = scrapertools.get_match(data, patron) @@ -1276,7 +1317,7 @@ def episodios(item): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 #Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página @@ -1312,7 +1353,7 @@ def episodios(item): break try: if not data: - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern @@ -1321,7 +1362,7 @@ def episodios(item): raise except: 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 item.url: @@ -1331,7 +1372,7 @@ def episodios(item): matches = re.compile(pattern, re.DOTALL).findall(data) if not matches: #error logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 #logger.debug("patron: " + pattern) @@ -1399,7 +1440,7 @@ def episodios(item): match = [m.groupdict() for m in r.finditer(info)][0] if not match: #error logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico @@ -1449,8 +1490,6 @@ def episodios(item): if item_local.active: del item_local.active - if item_local.category: - del item_local.category if item_local.infoLabels['title']: del item_local.infoLabels['title'] item_local.context = "['buscar_trailer']" @@ -1467,6 +1506,8 @@ def episodios(item): del item_local.update_last if item_local.update_next: del item_local.update_next + if item_local.channel_host: + del item_local.channel_host itemlist.append(item_local.clone()) @@ -1501,9 +1542,6 @@ 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 105b8cda..a49c07bc 100644 --- a/plugin.video.alfa/channels/tumejortorrent.py +++ b/plugin.video.alfa/channels/tumejortorrent.py @@ -12,40 +12,53 @@ from core import httptools from core import scrapertools from core import servertools from core.item import Item -from platformcode import config, logger +from platformcode import config, logger, platformtools from core import tmdb from lib import generictools -host = 'http://tumejortorrent.com/' +channel_py = 'newpct1' #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 +clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte en array host_index = 0 -host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto +host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #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 + channel_clone_name = channel_clone #Nombre del Canal elegido + host = host_clone #URL del Canal elegido + break + i += 1 +item = Item() +item.channel_host = host +if item.channel != channel_py: + item.channel = channel_py +item.category = channel_clone_name.capitalize() #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) +__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB? +modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada? +timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage +if timeout == 0: timeout = None + +platformtools.dialog_ok("NewPct1, ¡¡¡he vuelto como canal VIRTUAL!!!", "Hemos centralizado la gestión de los clones de NewPct1 en el canal virtual NewPct1. Los clones desaparecerán en breve.", "Para más información lee el tutorial: https://alfa-addon.com /threads/newpct1-implantando-alta-disponibilidad.1200/") + +#Vayamos a la siguiente acción en el canal Newpct1 +from platformcode import launcher +channel_clone_name = "tumejortorrent" #Nombre del Canal elegido +host = "http://tumejortorrent.com/" +item.category = channel_clone_name.capitalize() +item.action = "mainlist" +item.channel_host = host +launcher.run(item) def mainlist(item): logger.info() + if item.channel != channel_py: + return - #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") @@ -58,20 +71,20 @@ def mainlist(item): thumb_settings = get_thumb("setting_0.png") itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=host, - extra="peliculas", thumbnail=thumb_pelis )) + extra="peliculas", thumbnail=thumb_pelis, category=item.category)) itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=host, extra="series", - thumbnail=thumb_series)) + thumbnail=thumb_series, category=item.category)) itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=host, extra="varios", - thumbnail=thumb_docus)) + thumbnail=thumb_docus, category=item.category)) itemlist.append( - Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar)) + Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar, category=item.category)) itemlist.append( - Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings)) + Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category)) itemlist.append( - Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings)) + Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category)) return itemlist @@ -85,68 +98,60 @@ def submenu(item): logger.info() itemlist = [] + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass - host_alt = host - host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") - patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>' + patron = '<li><a\s?class="[^"]+"\s?href="http:[^"]+"><i\s?class=.*><\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>' #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) + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url + 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, 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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: 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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) - host_alt = host.replace(item.channel_alt, item.channel) - del item.channel_alt if item.url_alt: del item.url_alt + del item.channel_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 = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>' - if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com - data = '<a href="' + host_alt + 'varios/" title="Documentales"><i class="icon-rocket"></i> Documentales</a>' + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = '<li><a href="' + item.channel_host + 'varios/" title="Documentales">Documentales</a></li>' else: - if data: - data = scrapertools.get_match(data, patron) - if not data: - logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: 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 - else: - return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa + if not data: + logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 - patron = '<.*?href="([^"]+)".*?>([^>]+)</a>' + patron = '<li><a.*?href="([^"]+)"\s?.itle="[^"]+"\s?>([^>]+)<\/a><\/li>' matches = re.compile(patron, re.DOTALL).findall(data) + if not matches: logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 for scrapedurl, scrapedtitle in matches: title = scrapedtitle.strip() - url = scrapedurl - itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra)) - itemlist.append( - Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra)) + #Preguntamos por las entradas que no corresponden al "extra" + if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)): + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) + itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl)) if item.extra == "peliculas": - 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_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) + itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/")) + itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/")) return itemlist @@ -155,28 +160,41 @@ def alfabeto(item): logger.info() itemlist = [] - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = '' + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") patron = '<ul class="alfabeto">(.*?)</ul>' - if data: - data = scrapertools.get_match(data, patron) - else: - return itemlist + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + 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, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: 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.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) + + if item.url_alt: del item.url_alt + del item.channel_alt + + data = scrapertools.get_match(data, patron) patron = '<a href="([^"]+)"[^>]+>([^>]+)</a>' matches = re.compile(patron, re.DOTALL).findall(data) if not matches: - logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log')) + logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: 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 for scrapedurl, scrapedtitle in matches: title = scrapedtitle.upper() - url = scrapedurl - itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra)) + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) return itemlist @@ -191,11 +209,21 @@ def listado(item): if item.totalItems: del item.totalItems + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: + pass + + patron = '<ul class="' + clase + '">(.*?)</ul>' #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, patron) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data): 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')) + #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.category + ': 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 #Establecemos los valores básicos en función del tipo de contenido @@ -218,7 +246,7 @@ def listado(item): fichas = scrapertools.get_match(data, patron) if not fichas and not '<h3><strong>( 0 ) Resultados encontrados </strong>' 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 elif '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #no hay vídeos return itemlist @@ -235,7 +263,7 @@ def listado(item): matches = re.compile(patron, re.DOTALL).findall(fichas) if not matches: #error logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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("MATCHES: " + str(len(matches))) @@ -460,13 +488,21 @@ def listado(item): def listado_busqueda(item): logger.info() - - host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/') + + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + if item.category and item.category != "newest": + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() 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 cnt_pag = 0 # Contador de líneas leídas de Matches + timeout_search = 5 # Timeout un poco más largo para las búsquedas + if timeout > 5: + timeout_search = timeout # Timeout un poco más largo para las búsquedas + data = '' if item.cnt_pag: cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item @@ -493,21 +529,21 @@ 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 = '<ul class="%s">(.*?)</ul>' % 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) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data) except: pass - cnt_next += 1 - if not data or not scrapertools.find_single_match(data, pattern): + cnt_next += 1 + pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, pattern) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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) @@ -531,7 +567,6 @@ def listado_busqueda(item): pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa data_alt = data data = scrapertools.get_match(data, pattern) - #pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2.*?>(?P<title>.*?)?<\/h2>' pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb @@ -541,7 +576,8 @@ def listado_busqueda(item): matches_alt = re.compile(pattern, re.DOTALL).findall(data) if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log')) + item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist. @@ -830,14 +866,14 @@ def listado_busqueda(item): url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar... #Leemos la página, a ver si es una página de episodios - data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).data) + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data) data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") data_serie = data_serie.replace("chapters", "buscar-list") pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página, #intentarlo con la otra url - data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).data) + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data) data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") data_serie = data_serie.replace("chapters", "buscar-list") @@ -876,9 +912,10 @@ 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() + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() itemlist = [] @@ -987,8 +1024,9 @@ def findvideos(item): excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar # Descarga la página + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass @@ -1001,7 +1039,7 @@ def findvideos(item): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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") @@ -1029,7 +1067,7 @@ def findvideos(item): 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) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso #logger.debug("Patron: " + patron + " url: " + item_local.url) @@ -1054,6 +1092,8 @@ def findvideos(item): #logger.debug(item_local) # VER vídeos, descargar vídeos un link, o múltiples links + data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados + host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(") data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data) @@ -1066,7 +1106,7 @@ def findvideos(item): enlaces_ver = re.compile(patron, re.DOTALL).findall(data) enlaces_descargar = enlaces_ver #logger.debug(enlaces_ver) - + #Recorre todos los links de VER, si está permitido cnt_enl_ver = 1 cnt_enl_verif = 1 @@ -1100,7 +1140,7 @@ def findvideos(item): if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo? if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador? #Llama a la subfunción de check_list_links(itemlist) para cada link de servidor - item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ? + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos? if item_local.alive == "Ok": #Sí cnt_enl_verif += 1 #Movemos los contadores @@ -1190,7 +1230,7 @@ def findvideos(item): if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo? if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador? #Llama a la subfunción de check_list_links(itemlist) para primer link de servidor - item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ? + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos? if item_local.alive == "Ok": #Sí cnt_enl_verif += 1 #Movemos los contadores @@ -1232,9 +1272,10 @@ 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() + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() itemlist = [] @@ -1255,7 +1296,7 @@ def episodios(item): data = '' try: - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data) patron = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern data_alt = '' if data: data_alt = scrapertools.get_match(data, patron) @@ -1276,7 +1317,7 @@ def episodios(item): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 #Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página @@ -1312,7 +1353,7 @@ def episodios(item): break try: if not data: - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern @@ -1321,7 +1362,7 @@ def episodios(item): raise except: 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 item.url: @@ -1331,7 +1372,7 @@ def episodios(item): matches = re.compile(pattern, re.DOTALL).findall(data) if not matches: #error logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 #logger.debug("patron: " + pattern) @@ -1399,7 +1440,7 @@ def episodios(item): match = [m.groupdict() for m in r.finditer(info)][0] if not match: #error logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico @@ -1449,8 +1490,6 @@ def episodios(item): if item_local.active: del item_local.active - if item_local.category: - del item_local.category if item_local.infoLabels['title']: del item_local.infoLabels['title'] item_local.context = "['buscar_trailer']" @@ -1467,6 +1506,8 @@ def episodios(item): del item_local.update_last if item_local.update_next: del item_local.update_next + if item_local.channel_host: + del item_local.channel_host itemlist.append(item_local.clone()) @@ -1501,9 +1542,6 @@ 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 8a0ef203..60f73eb5 100644 --- a/plugin.video.alfa/channels/tvsinpagar.py +++ b/plugin.video.alfa/channels/tvsinpagar.py @@ -12,40 +12,53 @@ from core import httptools from core import scrapertools from core import servertools from core.item import Item -from platformcode import config, logger +from platformcode import config, logger, platformtools from core import tmdb from lib import generictools -host = 'http://www.tvsinpagar.com/' +channel_py = 'newpct1' #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 +clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones +clone_list = ast.literal_eval(clone_list) #la convierte en array host_index = 0 -host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto +host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #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 + channel_clone_name = channel_clone #Nombre del Canal elegido + host = host_clone #URL del Canal elegido + break + i += 1 +item = Item() +item.channel_host = host +if item.channel != channel_py: + item.channel = channel_py +item.category = channel_clone_name.capitalize() #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) +__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB? +modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada? +timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage +if timeout == 0: timeout = None + +platformtools.dialog_ok("NewPct1, ¡¡¡he vuelto como canal VIRTUAL!!!", "Hemos centralizado la gestión de los clones de NewPct1 en el canal virtual NewPct1. Los clones desaparecerán en breve.", "Para más información lee el tutorial: https://alfa-addon.com /threads/newpct1-implantando-alta-disponibilidad.1200/") + +#Vayamos a la siguiente acción en el canal Newpct1 +from platformcode import launcher +channel_clone_name = "tvsinpagar" #Nombre del Canal elegido +host = "http://www.tvsinpagar.com/" +item.category = channel_clone_name.capitalize() +item.action = "mainlist" +item.channel_host = host +launcher.run(item) def mainlist(item): logger.info() + if item.channel != channel_py: + return - #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") @@ -58,20 +71,20 @@ def mainlist(item): thumb_settings = get_thumb("setting_0.png") itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=host, - extra="peliculas", thumbnail=thumb_pelis )) + extra="peliculas", thumbnail=thumb_pelis, category=item.category)) itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=host, extra="series", - thumbnail=thumb_series)) + thumbnail=thumb_series, category=item.category)) itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=host, extra="varios", - thumbnail=thumb_docus)) + thumbnail=thumb_docus, category=item.category)) itemlist.append( - Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar)) + Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar, category=item.category)) itemlist.append( - Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings)) + Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category)) itemlist.append( - Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings)) + Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category)) return itemlist @@ -85,68 +98,60 @@ def submenu(item): logger.info() itemlist = [] + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass - host_alt = host - host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") - patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>' + patron = '<li><a\s?class="[^"]+"\s?href="http:[^"]+"><i\s?class=.*><\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>' #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) + logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url + 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, 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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: 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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) - host_alt = host.replace(item.channel_alt, item.channel) - del item.channel_alt if item.url_alt: del item.url_alt + del item.channel_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 = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>' - if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com - data = '<a href="' + host_alt + 'varios/" title="Documentales"><i class="icon-rocket"></i> Documentales</a>' + data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") + data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com + if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com + data = '<li><a href="' + item.channel_host + 'varios/" title="Documentales">Documentales</a></li>' else: - if data: - data = scrapertools.get_match(data, patron) - if not data: - logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: 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 - else: - return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos + data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa + if not data: + logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 - patron = '<.*?href="([^"]+)".*?>([^>]+)</a>' + patron = '<li><a.*?href="([^"]+)"\s?.itle="[^"]+"\s?>([^>]+)<\/a><\/li>' matches = re.compile(patron, re.DOTALL).findall(data) + if not matches: logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: 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 for scrapedurl, scrapedtitle in matches: title = scrapedtitle.strip() - url = scrapedurl - itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra)) - itemlist.append( - Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra)) + #Preguntamos por las entradas que no corresponden al "extra" + if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)): + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) + itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl)) if item.extra == "peliculas": - 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_alt + "peliculas-hd/4kultrahd/", extra=item.extra)) + itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/")) + itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/")) return itemlist @@ -155,28 +160,41 @@ def alfabeto(item): logger.info() itemlist = [] - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = '' + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") patron = '<ul class="alfabeto">(.*?)</ul>' - if data: - data = scrapertools.get_match(data, patron) - else: - return itemlist + if not data or not scrapertools.find_single_match(data, patron): + logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + 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, patron) + + if not data: #Si no ha logrado encontrar nada, salimos + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: 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.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible')) + + if item.url_alt: del item.url_alt + del item.channel_alt + + data = scrapertools.get_match(data, patron) patron = '<a href="([^"]+)"[^>]+>([^>]+)</a>' matches = re.compile(patron, re.DOTALL).findall(data) if not matches: - logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) - itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log')) + logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: 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 for scrapedurl, scrapedtitle in matches: title = scrapedtitle.upper() - url = scrapedurl - itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra)) + itemlist.append(item.clone(action="listado", title=title, url=scrapedurl)) return itemlist @@ -191,11 +209,21 @@ def listado(item): if item.totalItems: del item.totalItems + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: + pass + + patron = '<ul class="' + clase + '">(.*?)</ul>' #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, patron) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data): 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')) + #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.category + ': 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 #Establecemos los valores básicos en función del tipo de contenido @@ -218,7 +246,7 @@ def listado(item): fichas = scrapertools.get_match(data, patron) if not fichas and not '<h3><strong>( 0 ) Resultados encontrados </strong>' 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 elif '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #no hay vídeos return itemlist @@ -235,7 +263,7 @@ def listado(item): matches = re.compile(patron, re.DOTALL).findall(fichas) if not matches: #error logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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("MATCHES: " + str(len(matches))) @@ -460,13 +488,21 @@ def listado(item): def listado_busqueda(item): logger.info() - - host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/') + + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + if item.category and item.category != "newest": + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() 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 cnt_pag = 0 # Contador de líneas leídas de Matches + timeout_search = 5 # Timeout un poco más largo para las búsquedas + if timeout > 5: + timeout_search = timeout # Timeout un poco más largo para las búsquedas + data = '' if item.cnt_pag: cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item @@ -493,21 +529,21 @@ 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 = '<ul class="%s">(.*?)</ul>' % 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) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data) except: pass - cnt_next += 1 - if not data or not scrapertools.find_single_match(data, pattern): + cnt_next += 1 + pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa + if not data or (not scrapertools.find_single_match(data, pattern) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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) @@ -531,7 +567,6 @@ def listado_busqueda(item): pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa data_alt = data data = scrapertools.get_match(data, pattern) - #pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2.*?>(?P<title>.*?)?<\/h2>' pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb @@ -541,7 +576,8 @@ def listado_busqueda(item): matches_alt = re.compile(pattern, re.DOTALL).findall(data) if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log')) + item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist. @@ -830,14 +866,14 @@ def listado_busqueda(item): url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar... #Leemos la página, a ver si es una página de episodios - data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).data) + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data) data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") data_serie = data_serie.replace("chapters", "buscar-list") pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página, #intentarlo con la otra url - data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).data) + data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data) data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8") data_serie = data_serie.replace("chapters", "buscar-list") @@ -876,9 +912,10 @@ 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() + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() itemlist = [] @@ -987,8 +1024,9 @@ def findvideos(item): excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar # Descarga la página + data = '' try: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass @@ -1001,7 +1039,7 @@ def findvideos(item): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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") @@ -1029,7 +1067,7 @@ def findvideos(item): 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) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso #logger.debug("Patron: " + patron + " url: " + item_local.url) @@ -1054,6 +1092,8 @@ def findvideos(item): #logger.debug(item_local) # VER vídeos, descargar vídeos un link, o múltiples links + data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados + host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "") data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(") data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data) @@ -1066,7 +1106,7 @@ def findvideos(item): enlaces_ver = re.compile(patron, re.DOTALL).findall(data) enlaces_descargar = enlaces_ver #logger.debug(enlaces_ver) - + #Recorre todos los links de VER, si está permitido cnt_enl_ver = 1 cnt_enl_verif = 1 @@ -1100,7 +1140,7 @@ def findvideos(item): if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo? if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador? #Llama a la subfunción de check_list_links(itemlist) para cada link de servidor - item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ? + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos? if item_local.alive == "Ok": #Sí cnt_enl_verif += 1 #Movemos los contadores @@ -1190,7 +1230,7 @@ def findvideos(item): if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo? if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador? #Llama a la subfunción de check_list_links(itemlist) para primer link de servidor - item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ? + item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ? if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos? if item_local.alive == "Ok": #Sí cnt_enl_verif += 1 #Movemos los contadores @@ -1232,9 +1272,10 @@ 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() + #Renombramos el canal al nombre de clone elegido. Actualizados URL + host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)') + #item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() itemlist = [] @@ -1255,7 +1296,7 @@ def episodios(item): data = '' try: - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data) patron = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern data_alt = '' if data: data_alt = scrapertools.get_match(data, patron) @@ -1276,7 +1317,7 @@ def episodios(item): 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 #Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página @@ -1312,7 +1353,7 @@ def episodios(item): break try: if not data: - data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data) + data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern @@ -1321,7 +1362,7 @@ def episodios(item): raise except: 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 item.url: @@ -1331,7 +1372,7 @@ def episodios(item): matches = re.compile(pattern, re.DOTALL).findall(data) if not matches: #error logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 #logger.debug("patron: " + pattern) @@ -1399,7 +1440,7 @@ def episodios(item): match = [m.groupdict() for m in r.finditer(info)][0] if not match: #error logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info) - 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')) + itemlist.append(item.clone(action='', title=item.category + ': 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 match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico @@ -1449,8 +1490,6 @@ def episodios(item): if item_local.active: del item_local.active - if item_local.category: - del item_local.category if item_local.infoLabels['title']: del item_local.infoLabels['title'] item_local.context = "['buscar_trailer']" @@ -1467,6 +1506,8 @@ def episodios(item): del item_local.update_last if item_local.update_next: del item_local.update_next + if item_local.channel_host: + del item_local.channel_host itemlist.append(item_local.clone()) @@ -1501,9 +1542,6 @@ 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/videolibrary.py b/plugin.video.alfa/channels/videolibrary.py index 0946f92c..0d2559aa 100644 --- a/plugin.video.alfa/channels/videolibrary.py +++ b/plugin.video.alfa/channels/videolibrary.py @@ -292,6 +292,7 @@ def get_episodes(item): def findvideos(item): logger.info() + from lib import generictools # logger.debug("item:\n" + item.tostring('\n')) itemlist = [] @@ -321,10 +322,11 @@ def findvideos(item): list_canales[nom_canal] = filetools.join(path_dir, fd) num_canales = len(list_canales) - # logger.debug(str(list_canales)) + if 'downloads' in list_canales: json_path = list_canales['downloads'] item_json = Item().fromjson(filetools.read(json_path)) + item_json = generictools.redirect_clone_newpct1(item_json) ###### Redirección al canal NewPct1.py si es un clone item_json.contentChannel = "local" # Soporte para rutas relativas en descargas if filetools.is_relative(item_json.url): @@ -362,7 +364,12 @@ def findvideos(item): for nom_canal, json_path in list_canales.items(): if filtro_canal and filtro_canal != nom_canal.capitalize(): continue - + + item_canal = Item() + item_canal.channel = nom_canal + item_canal = generictools.redirect_clone_newpct1(item_canal) ###### Redirección al canal NewPct1.py si es un clone + nom_canal = item_canal.channel + # Importamos el canal de la parte seleccionada try: channel = __import__('channels.%s' % nom_canal, fromlist=["channels.%s" % nom_canal]) @@ -370,6 +377,7 @@ def findvideos(item): exec "import channels." + nom_canal + " as channel" item_json = Item().fromjson(filetools.read(json_path)) + item_json = generictools.redirect_clone_newpct1(item_json) ###### Redirección al canal NewPct1.py si es un clone list_servers = [] try: diff --git a/plugin.video.alfa/lib/generictools.py b/plugin.video.alfa/lib/generictools.py index fc36c7fc..db8589ac 100644 --- a/plugin.video.alfa/lib/generictools.py +++ b/plugin.video.alfa/lib/generictools.py @@ -21,6 +21,8 @@ from core.item import Item from platformcode import config, logger from core import tmdb +channel_py = "newpct1" + def update_title(item): logger.info() @@ -64,7 +66,13 @@ def update_title(item): 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 + if item.contentType != "movie": + item.add_videolibrary = True #Estamos Añadiendo a la Videoteca. Indicador para control de uso de los Canales + else: + if item.channel == channel_py: #Si es una peli de NewPct1, ponemos el nombre del clone + item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + if item.channel_host: #Borramos ya el indicador para que no se guarde en la Videoteca + del item.channel_host #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, @@ -168,10 +176,13 @@ def post_tmdb_listado(item, itemlist): #Borramos valores si ha habido fail-over channel_alt = '' if item.channel_alt: - channel_alt = item.channel + channel_alt = item.channel_alt del item.channel_alt if item.url_alt: del item.url_alt + #Ajustamos el nombre de la categoría + if item.category != "newest": + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() for item_local in itemlist: #Recorremos el Itenlist generado por el canal title = item_local.title @@ -185,6 +196,10 @@ def post_tmdb_listado(item, itemlist): if item_local.url_alt: del item_local.url_alt + #Ajustamos el nombre de la categoría + if item_local.category != "newest": + item_local.category = scrapertools.find_single_match(item_local.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() + #Restauramos la info adicional guarda en la lista title_subs, y la borramos de Item title_add = ' ' if item_local.title_subs: @@ -199,7 +214,8 @@ def post_tmdb_listado(item, itemlist): 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 + item_local.title_subs = [] + del item_local.title_subs #Preparamos el Rating del vídeo rating = '' @@ -276,9 +292,9 @@ def post_tmdb_listado(item, itemlist): title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', title).strip() if item.category == "newest": #Viene de Novedades. Marcamos el título con el nombre del canal - title += ' -%s-' % item_local.channel.capitalize() + title += ' -%s-' % scrapertools.find_single_match(item_local.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() if item_local.contentType == "movie": - item_local.contentTitle += ' -%s-' % item_local.channel.capitalize() + item_local.contentTitle += ' -%s-' % scrapertools.find_single_match(item_local.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() item_local.title = title @@ -288,8 +304,8 @@ def post_tmdb_listado(item, itemlist): #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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + channel_alt.capitalize() + '[/COLOR] inaccesible')) return (item, itemlist) @@ -329,19 +345,29 @@ def post_tmdb_episodios(item, itemlist): num_temporada_max = 99 num_episodios_flag = True - #Restauramos el num de Temporada para hacer más flexible la elección de Videoteca + #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 + #Ajustamos el nombre de la categoría + item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() + #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.channel == channel_py: + if item.channel_alt: + channel_alt = item.category + item.category = item.channel_alt.capitalize() + del item.channel_alt + else: + if item.channel_alt: + channel_alt = item.channel + item.channel = item.channel_alt + item.category = item.channel_alt.capitalize() + del item.channel_alt if item.url_alt: item.url = item.url_alt del item.url_alt @@ -351,17 +377,31 @@ def post_tmdb_episodios(item, itemlist): del item_local.add_videolibrary if item_local.add_menu: del item_local.add_menu + if item_local.contentSeason_save: + del item_local.contentSeason_save - #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 + #Ajustamos el nombre de la categoría si es un clone de NewPct1 + item_local.category = scrapertools.find_single_match(item_local.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize() + + #Restauramos valores para cada Episodio si ha habido fail-over de un clone de NewPct1 + if item_local.channel == channel_py: + if item_local.channel_alt: + item_local.category = item_local.channel_alt + del item_local.channel_alt + else: + 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 está actualizando videoteca de una serie NewPct1, restauramos el channel con el nombre del clone + if item_local.channel == channel_py and (item.library_playcounts or item.add_videolibrary): + item_local.channel = scrapertools.find_single_match(item_local.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + #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: @@ -448,6 +488,10 @@ def post_tmdb_episodios(item, itemlist): #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) + #Si está actualizando videoteca de una serie NewPct1, restauramos el channel con el nombre del clone + if item.channel == channel_py and (item.library_playcounts or item.add_videolibrary): + item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/') + #Terminado el repaso de cada episodio, cerramos con el pié de página #En primer lugar actualizamos todos los episodios con su núm máximo de episodios por temporada try: @@ -512,13 +556,13 @@ def post_tmdb_episodios(item, itemlist): #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')) + itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category.capitalize() + '[/COLOR] inaccesible')) 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 - + del item.add_menu #desde la página de Episodios o desde Menú Contextual + #logger.debug(item) return (item, itemlist) @@ -593,6 +637,10 @@ def post_tmdb_findvideos(item, itemlist): 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') + + #Ajustamos el nombre de la categoría + if item.channel != channel_py: + item.category = item.channel.capitalize() #Formateamos de forma especial el título para un episodio if item.contentType == "episode": #Series @@ -619,9 +667,9 @@ def post_tmdb_findvideos(item, itemlist): title_gen = '[COLOR gold]Enlaces Ver: [/COLOR]%s' % (title_gen) if item.channel_alt: - title_gen = '[COLOR yellow]%s [/COLOR][ALT]: %s' % (item.channel.capitalize(), title_gen) + title_gen = '[COLOR yellow]%s [/COLOR][ALT]: %s' % (item.category.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) + title_gen = '%s: %s' % (item.category.capitalize(), title_gen) #Pintamos el pseudo-título con toda la información disponible del vídeo item.action = "" @@ -633,7 +681,7 @@ def post_tmdb_findvideos(item, itemlist): return (item, itemlist) -def fail_over_newpct1(item, patron, patron2=None): +def fail_over_newpct1(item, patron, patron2=None, timeout=None): logger.info() import ast @@ -641,56 +689,74 @@ def fail_over_newpct1(item, patron, patron2=None): 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: + Creamos una array 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 + - action_excluded lista las acciones que está excluidas para ese canal - La llamada al método desde el principio de Submenu, Episodios y Findvideos, es: + La llamada al método desde el principio de Submenu, Listado_Búsqueda, 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 + - Entrada (opcional): timeout: valor de espera máximo en download de página. Por defecto 3 - 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) + if timeout == None: + timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage + if timeout == 0: timeout = None - #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 + data = '' + channel_failed = '' + + #Array con los datos de los canales alternativos + fail_over_list = config.get_setting('clonenewpct1_channels_list', channel_py) + fail_over_list = ast.literal_eval(fail_over_list) + + #Recorremos el Array identificando el canal que falla + for active, channel, channel_host, contentType, action_excluded in fail_over_list: + if item.channel == channel_py: + if channel != item.category.lower(): #es el canal/categoría que falla? + continue + else: + if channel != item.channel: #es el canal que falla? + continue + channel_failed = channel #salvamos el nombre del canal o categoría channel_host_failed = channel_host #salvamos el nombre del host channel_url_failed = item.url #salvamos la url - if item.action != 'submenu' and item.action != 'search' and item.contentType not in contentType: #soporta el fail_over de este contenido? + if (item.action == 'episodios' or item.action == 'findvideos') 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 + break + + if not channel_failed: + logger.debug(item) + return (item, data) #Algo no ha funcionado, 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: + #Recorremos el Array identificando canales activos que funcionen, distintos del caído, que soporten el contenido + for active, channel, channel_host, contentType, action_excluded in fail_over_list: data_alt = '' - if channel == channel_failed or active == '0': #está activo el nuevo canal? + if channel == channel_failed or active == '0' or item.action in action_excluded: #es válido el nuevo canal? continue - if item.action != 'submenu' and item.action != 'search' and item.contentType not in contentType: #soporta el contenido? + if (item.action == 'episodios' or item.action == 'findvideos') 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 + if item.channel != channel_py: + item.channel = channel + item.category = channel.capitalize() item.url_alt = channel_url_failed item.url = channel_url_failed item.url = item.url.replace(channel_host_failed, channel_host) + item.channel_host = 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... @@ -698,9 +764,9 @@ def fail_over_newpct1(item, patron, patron2=None): #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) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout).data) else: - data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=2).data) + data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: data = '' if not data: #no ha habido suerte, probamos con el siguiente canal válido @@ -710,38 +776,62 @@ def fail_over_newpct1(item, patron, patron2=None): #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, '<ul class="buscar-list">.*?<img src=".*?\/pictures\/.*?(\/\d+)_')) - #para Submenu y Search cambiamos también la Categoria - if item.action == 'submenu' or item.action == 'search': - item.category = item.channel.capitalize() break #por fin !!! Este canal parece que funciona else: logger.error("ERROR 02: " + item.action + ": Ha cambiado la estructura de la Web: " + item.url + " / Patron: " + patron) data = '' continue - #logger.debug(item) - if not data: #Si no ha logrado encontrar nada, salimos limpiando variables - if item.channel_alt: - item.channel = item.channel_alt - del item.channel_alt + if item.channel == channel_py: + if item.channel_alt: + item.category = item.channel_alt.capitalize() + del item.channel_alt + else: + if item.channel_alt: + item.channel = item.channel_alt + del item.channel_alt if item.url_alt: item.url = item.url_alt del item.url_alt + if item.channel_host: + del item.channel_host - return (item, data) \ No newline at end of file + return (item, data) + + +def redirect_clone_newpct1(item): + logger.info() + + """ + + Llamada para redirigir cualquier llamada a un clone de NewPct1 a NewPct1.py + Incluye las llamadas estándar del canal y la llamadas externas: + - Play fron Library + - Videolibrary Update + + La lógica es reemplazar item.channel por "newpct1" y dejar el nombre del clone en item.category. + De esta forma utiliza siempre el código de NewPct1.py, aunque con las urls y apariencia del clone seleccionado por el usuario. + + Este método interroga la configruación de NewPct1 para extraer la lista de canales clones. Si item.channel es un clone de NewPct1 y está en esa lista, actualiza item.channel='newpct1' + + La llamada recibe el parámetro Item y lo devuleve actualizado + + """ + + #Array con los datos de los canales alternativos + fail_over_list = config.get_setting('clonenewpct1_channels_list', channel_py) + + channel = "'%s'" % item.channel + if channel in fail_over_list: + item.channel = channel_py + + return item \ No newline at end of file diff --git a/plugin.video.alfa/videolibrary_service.py b/plugin.video.alfa/videolibrary_service.py index 2d578d31..939f90c3 100644 --- a/plugin.video.alfa/videolibrary_service.py +++ b/plugin.video.alfa/videolibrary_service.py @@ -18,16 +18,19 @@ from channels import videolibrary def update(path, p_dialog, i, t, serie, overwrite): logger.info("Actualizando " + path) + from lib import generictools insertados_total = 0 - #logger.debug(serie) + head_nfo, it = videolibrarytools.read_nfo(path + '/tvshow.nfo') # logger.debug("%s: %s" %(serie.contentSerieName,str(list_canales) )) for channel, url in serie.library_urls.items(): serie.channel = channel serie.url = url + + serie = generictools.redirect_clone_newpct1(serie) ###### Redirección al canal NewPct1.py si es un clone - channel_enabled = channeltools.is_enabled(channel) + channel_enabled = channeltools.is_enabled(serie.channel) if channel_enabled: @@ -38,13 +41,14 @@ def update(path, p_dialog, i, t, serie, overwrite): pathchannels = filetools.join(config.get_runtime_path(), "channels", serie.channel + '.py') logger.info("Cargando canal: " + pathchannels + " " + serie.channel) - logger.debug(serie) if serie.library_filter_show: - serie.show = serie.library_filter_show.get(channel, serie.contentSerieName) + serie.show = serie.library_filter_show.get(serie.channel, serie.contentSerieName) obj = imp.load_source(serie.channel, pathchannels) itemlist = obj.episodios(serie) + + serie.channel = channel #Restauramos el valor incial del clone de NewPct1 try: if int(overwrite) == 3: