def autoplay_config(item): logger.info() global autoplay_node dict_values = {} list_controls = [] channel_parameters = channeltools.get_channel_parameters(item.from_channel) channel_name = channel_parameters['title'] if not autoplay_node: # Obtiene el nodo AUTOPLAY desde el json autoplay_node = jsontools.get_node_from_file('autoplay', 'AUTOPLAY') channel_node = autoplay_node.get(item.from_channel, {}) settings_node = channel_node.get('settings', {}) allow_option = True active_settings = {"id": "active", "label": "AutoPlay (activar/desactivar la auto-reproduccion)", "color": "0xffffff99", "type": "bool", "default": False, "enabled": allow_option, "visible": allow_option} list_controls.append(active_settings) dict_values['active'] = settings_node.get('active', False) # Idioma status_language = config.get_setting("filter_languages", item.from_channel) if not status_language: status_language = 0 set_language = {"id": "language", "label": "Idioma para AutoPlay (Opcional)", "color": "0xffffff99", "type": "list", "default": 0, "enabled": "eq(-1,true)", "visible": True, "lvalues": get_languages(item.from_channel)} list_controls.append(set_language) dict_values['language'] = status_language separador = {"id": "label", "label": " " "_________________________________________________________________________________________", "type": "label", "enabled": True, "visible": True} list_controls.append(separador) # Seccion servidores favoritos server_list = channel_node.get("servers", []) if not server_list: enabled = False server_list = ["No disponible"] else: enabled = "eq(-3,true)" custom_servers_settings = {"id": "custom_servers", "label": " Servidores favoritos", "color": "0xff66ffcc", "type": "bool", "default": False, "enabled": enabled, "visible": True} list_controls.append(custom_servers_settings) if dict_values['active'] and enabled: dict_values['custom_servers'] = settings_node.get('custom_servers', False) else: dict_values['custom_servers'] = False for num in range(1, 4): pos1 = num + 3 default = num - 1 if default > len(server_list) - 1: default = 0 set_servers = {"id": "server_%s" % num, "label": u" \u2665 Servidor Favorito %s" % num, "color": "0xfffcab14", "type": "list", "default": default, "enabled": "eq(-%s,true)+eq(-%s,true)" % (pos1, num), "visible": True, "lvalues": server_list} list_controls.append(set_servers) dict_values["server_%s" % num] = settings_node.get("server_%s" % num, 0) if settings_node.get("server_%s" % num, 0) > len(server_list) - 1: dict_values["server_%s" % num] = 0 # Seccion Calidades favoritas quality_list = channel_node.get("quality", []) if not quality_list: enabled = False quality_list = ["No disponible"] else: enabled = "eq(-7,true)" custom_quality_settings = {"id": "custom_quality", "label": " Calidades Favoritas", "color": "0xff66ffcc", "type": "bool", "default": False, "enabled": enabled, "visible": True} list_controls.append(custom_quality_settings) if dict_values['active'] and enabled: dict_values['custom_quality'] = settings_node.get('custom_quality', False) else: dict_values['custom_quality'] = False for num in range(1, 4): pos1 = num + 7 default = num - 1 if default > len(quality_list) - 1: default = 0 set_quality = {"id": "quality_%s" % num, "label": u" \u2665 Calidad Favorita %s" % num, "color": "0xfff442d9", "type": "list", "default": default, "enabled": "eq(-%s,true)+eq(-%s,true)" % (pos1, num), "visible": True, "lvalues": quality_list} list_controls.append(set_quality) dict_values["quality_%s" % num] = settings_node.get("quality_%s" % num, 0) if settings_node.get("quality_%s" % num, 0) > len(quality_list) - 1: dict_values["quality_%s" % num] = 0 # Plan B dict_values['plan_b'] = settings_node.get('plan_b', False) enabled = "eq(-4,true)|eq(-8,true)" plan_b = {"id": "plan_b", "label": " Plan B (Si fallan los favoritos prueba otros enlaces)", "color": "0xffffff99", "type": "bool", "default": False, "enabled": enabled, "visible": True} list_controls.append(plan_b) # Seccion Prioridades priority_list = ["Servidor y Calidad", "Calidad y Servidor"] set_priority = {"id": "priority", "label": " Prioridad (Indica el orden para Auto-Reproducir)", "color": "0xffffff99", "type": "list", "default": 0, "enabled": True, "visible": "eq(-5,true)+eq(-9,true)+eq(-12,true)", "lvalues": priority_list} list_controls.append(set_priority) dict_values["priority"] = settings_node.get("priority", 0) # Abrir cuadro de dialogo platformtools.show_channel_settings(list_controls=list_controls, dict_values=dict_values, callback='save', item=item, caption='%s - AutoPlay' % channel_name)
def check_channels(inutile=''): """ leggo gli host dei canali dal file channels.json li controllo scrivo il file channels-test.json con i codici di errore e i nuovi url in caso di redirect gli url DEVONO avere http(s) Durante il controllo degli url vengono rieffettuati i controlli di ip, asdl e dns. Questo perchè può succedere che in un qualsiasi momento la connessione può avere problemi. Nel caso accada un problema, il controllo e relativa scrittura del file viene interrotto con messaggio di avvertimento """ logger.info() folderJson = xbmc.translatePath( xbmcaddon.Addon().getAddonInfo('path')).decode('utf-8') fileJson = 'channels.json' with open(folderJson + '/' + fileJson) as f: data = json.load(f) risultato = {} for chann, host in sorted(data.items()): ris = [] # per avere un'idea della tempistica # utile solo se si controllano tutti i canali # per i canali con error 522 si perdono circa 40 sec... logger.info("check #### INIZIO #### channel - host :%s - %s " % (chann, host)) rslt = Kdicc(lst_urls=[host]).http_Resp() # tutto ok if rslt['code'] == 200: risultato[chann] = host # redirect elif str(rslt['code']).startswith('3'): #risultato[chann] = str(rslt['code']) +' - '+ rslt['redirect'][:-1] if rslt['redirect'].endswith('/'): rslt['redirect'] = rslt['redirect'][:-1] risultato[chann] = rslt['redirect'] # sito inesistente elif rslt['code'] == -2: risultato[chann] = 'Host Sconosciuto - ' + str( rslt['code']) + ' - ' + host # sito non raggiungibile - probabili dns non settati elif rslt['code'] == 111: risultato[chann] = [ 'Host non raggiungibile - ' + str(rslt['code']) + ' - ' + host ] else: # altri tipi di errore #risultato[chann] = 'Errore Sconosciuto - '+str(rslt['code']) +' - '+ host risultato[chann] = host logger.info("check #### FINE #### rslt :%s " % (rslt)) fileJson_test = 'channels-test.json' # scrivo il file aggiornato with open(folderJson + '/' + fileJson_test, 'w') as f: data = json.dump(risultato, f, sort_keys=True, indent=4) logger.info(data)
def test_video_exists(page_url): logger.info("(page_url='%s')" % page_url) data = httptools.downloadpage(page_url).data if "Not Found" in data or "File was deleted" in data: return False, "[Watchvideo] El fichero no existe o ha sido borrado" return True, ""
def get_video_url(page_url, premium=False, user="", password="", video_password=""): logger.info("url=" + page_url) video_urls = [] if "hash=" in page_url: data = urllib.unquote(httptools.downloadpage(page_url).data) id_video = scrapertools.find_single_match(data, "vid':'([^']+)'") page_url = "http://hqq.watch/player/embed_player.php?vid=%s" % id_video else: page_url = page_url.replace("/watch_video.php?v=", "/player/embed_player.php?vid=") page_url = page_url.replace('https://netu.tv/', 'http://hqq.watch/') page_url = page_url.replace('https://waaw.tv/', 'http://hqq.watch/') data = httptools.downloadpage(page_url).data # ~ logger.debug(data) js_wise = scrapertools.find_single_match( data, "<script type=[\"']text/javascript[\"']>\s*;?(eval.*?)</script>") data = jswise(js_wise).replace("\\", "") # ~ logger.debug(data) alea = str(random.random())[2:] data_ip = httptools.downloadpage( 'http://hqq.watch/player/ip.php?type=json&rand=%s' % alea).data # ~ logger.debug(data_ip) json_data_ip = jsontools.load(data_ip) url = scrapertools.find_single_match( data, 'self\.location\.replace\("([^)]+)\)') url = url.replace('"+rand+"', alea) url = url.replace('"+data.ip+"', json_data_ip['ip']) url = url.replace('"+need_captcha+"', '0') #json_data_ip['need_captcha']) url = url.replace('"+token', '') # ~ logger.debug(url) headers = { "User-Agent": 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.127 Large Screen Safari/533.4 GoogleTV/162671' } data = httptools.downloadpage('http://hqq.watch' + url, headers=headers).data # ~ logger.debug(data) codigo_js = scrapertools.find_multiple_matches( data, '<script>document.write\(unescape\("([^"]+)') # ~ logger.debug(codigo_js) js_aux = urllib.unquote(codigo_js[0]) at = scrapertools.find_single_match(js_aux, 'var at = "([^"]+)') js_aux = urllib.unquote(codigo_js[1]) var_link_1 = scrapertools.find_single_match( js_aux, '&link_1=\\"\+encodeURIComponent\(([^)]+)') var_server_2 = scrapertools.find_single_match( js_aux, '&server_2=\\"\+encodeURIComponent\(([^)]+)') vid = scrapertools.find_single_match( js_aux, '&vid=\\"\+encodeURIComponent\(\\"([^"]+)') ext = '.mp4.m3u8' # ~ logger.debug('%s %s %s %s' % (at, var_link_1, var_server_2, vid)) js_wise = scrapertools.find_single_match( data, "<script type=[\"']text/javascript[\"']>\s*;?(eval.*?)</script>") data = jswise(js_wise).replace("\\", "") # ~ logger.debug(data) variables = scrapertools.find_multiple_matches( data, 'var ([a-zA-Z0-9]+) = "([^"]+)";') # ~ logger.debug(variables) for nombre, valor in variables: # ~ logger.debug('%s %s' % (nombre, valor)) if nombre == var_link_1: link_1 = valor if nombre == var_server_2: server_2 = valor link_m3u8 = 'http://hqq.watch/player/get_md5.php?ver=2&at=%s&adb=0&b=1&link_1=%s&server_2=%s&vid=%s&ext=%s' % ( at, link_1, server_2, vid, ext) # ~ logger.debug(link_m3u8) video_urls.append(["[netu.tv]", link_m3u8]) return video_urls
def get_source(url): logger.info() data = httptools.downloadpage(url).data data = re.sub(r'\n|\r|\t| |<br>|\s{2,}', "", data) return data
def listado(item): logger.info() itemlist = [] url_next_page = '' data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) #data = httptools.downloadpage(item.url).data data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") if item.modo != 'next' or item.modo == '': patron = '<ul class="' + item.extra + '">(.*?)</ul>' fichas = scrapertools.get_match(data, patron) page_extra = item.extra else: fichas = data page_extra = item.extra patron = '<a href="([^"]+).*?' # la url patron += 'title="([^"]+).*?' # el titulo patron += '<img.*?src="([^"]+)"[^>]+>.*?' # el thumbnail patron += '<h2.*?>(.*?)?<\/h2>' # titulo alternativo patron += '<span>([^<].*?)?<' # la calidad #logger.debug("patron: " + patron + " / fichas: " + fichas) matches = re.compile(patron, re.DOTALL).findall(fichas) # Paginacion if item.next_page != 'b': if len(matches) > 30: url_next_page = item.url matches = matches[:30] next_page = 'b' modo = 'continue' else: matches = matches[30:] 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 = matches_next_page[0] modo = 'next' for scrapedurl, scrapedtitle, scrapedthumbnail, title_alt, calidad in matches: url = scrapedurl title = scrapedtitle.replace("�", "ñ").replace("ñ", "ñ").replace( "Temp", " Temp").replace("Esp", " Esp").replace("Ing", " Ing").replace( "Eng", " Eng").replace("Calidad", "") title_alt = title_alt.replace("�", "ñ").replace("ñ", "ñ").replace( "Temp", " Temp").replace("Esp", " Esp").replace("Ing", " Ing").replace( "Eng", " Eng").replace("Calidad", "") thumbnail = scrapedthumbnail action = "findvideos" extra = "" context = "movie" year = scrapertools.find_single_match(scrapedthumbnail, r'-(\d{4})') if not year or year <= "1900": year = '-' if ".com/serie" in url and "/miniseries" not in url: action = "episodios" extra = "serie" context = "tvshow" title = scrapertools.find_single_match(title, '([^-]+)') title = title.replace("Ver online", "", 1).replace( "Descarga Serie HD", "", 1).replace("Ver en linea ", "", 1).strip() else: title = title.replace("Descargar torrent ", "", 1).replace( "Descarga Gratis ", "", 1).replace("Descargar Estreno ", "", 1).replace( "Pelicula en latino ", "", 1).replace("Descargar Pelicula ", "", 1).replace( "Descargar", "", 1).replace("Descarga", "", 1).replace("Bajar", "", 1).strip() if title.endswith("gratis"): title = title[:-7] if title.endswith("torrent"): title = title[:-8] if title.endswith("en HD"): title = title[:-6] if title == "": title = title_alt context_title = title_alt show = title_alt if not config.get_setting( "unify"): #Si Titulos Inteligentes NO seleccionados: if calidad: title = title + ' [' + calidad + "]" if not 'array' in title: itemlist.append( Item(channel=item.channel, action=action, title=title, url=url, thumbnail=thumbnail, extra=extra, show=context_title, contentTitle=context_title, contentType=context, quality=calidad, context=["buscar_trailer"], infoLabels={'year': year})) logger.debug("url: " + url + " / title: " + title + " / contxt title: " + context_title + " / context: " + context + " / calidad: " + calidad + " / year: " + year) tmdb.set_infoLabels(itemlist, True) if url_next_page: itemlist.append( Item(channel=item.channel, action="listado", title=">> Página siguiente", url=url_next_page, next_page=next_page, folder=True, text_color='yellow', text_bold=True, modo=modo, plot=extra, extra=page_extra)) return itemlist
def findvideos(item): logger.info() 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/") # Obtener la información actualizada del Episodio if item.contentType == "episode": if not item.contentTitle and (not item.infoLabels['title'] or item.infoLabels['title'] == 'null' or item.infoLabels['title'] == "None"): tmdb.set_infoLabels_item(item, seekTmdb=True) if not item.contentTitle: item.contentTitle = item.infoLabels['title'] # Descarga la página data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace("$!", "#!").replace("'", "\"").replace("ñ", "ñ").replace( "//pictures", "/pictures") title = scrapertools.find_single_match( data, "<h1.*?<strong>([^<]+)<\/strong>.*?<\/h1>" ) #corregido para adaptarlo a mispelisy.series.com title += scrapertools.find_single_match( data, "<h1.*?<strong>[^<]+<\/strong>([^<]+)<\/h1>" ) #corregido para adaptarlo a mispelisy.series.com #caratula = scrapertools.find_single_match(data, '<div class="entry-left">.*?src="([^"]+)"') caratula = scrapertools.find_single_match(data, '<h1.*?<img.*?src="([^"]+)') patron = 'openTorrent.*?title=".*?class="btn-torrent">.*?function openTorrent.*?href = "(.*?)";' # escraped torrent url = scrapertools.find_single_match(data, patron) if item.infoLabels['year']: #añadir el año al título general year = '[%s]' % str(item.infoLabels['year']) else: year = "" if item.infoLabels[ 'aired'] and item.contentType == "episode": #añadir el año de episodio para series year = scrapertools.find_single_match(str(item.infoLabels['aired']), r'\/(\d{4})') year = '[%s]' % year title_gen = title if item.contentType == "episode": #scrapear información duplicada en Series title = re.sub(r'Temp.*?\[', '[', title) title = re.sub(r'\[Cap.*?\]', '', title) title_epi = '%sx%s - %s' % (str( item.contentSeason), str( item.contentEpisodeNumber), item.contentTitle) title_gen = '%s %s, %s' % (title_epi, year, title) title_torrent = '%s, %s' % (title_epi, item.contentSerieName) else: title_torrent = item.contentTitle if item.infoLabels['quality']: if not config.get_setting( "unify"): #Si Titulos Inteligentes NO seleccionados: title_torrent = '%s [%s]' % (title_torrent, item.infoLabels['quality']) else: title_torrent = '%s (%s)' % (title_torrent, item.infoLabels['quality']) if not config.get_setting( "unify"): #Si Titulos Inteligentes NO seleccionados: title_gen = '[COLOR gold]**- Título: [/COLOR]%s -**' % (title_gen) else: title_gen = '[COLOR gold]Título: [/COLOR]%s' % (title_gen) if config.get_setting( "quit_channel_name", "videolibrary") == 1 and item.contentChannel == "videolibrary": title_gen = '%s: %s' % (item.channel.capitalize(), title_gen) itemlist.append( item.clone(title=title_gen, action="", folder=False)) #Título con todos los datos del vídeo title = title_torrent title_torrent = '[COLOR salmon]??[/COLOR], [COLOR yellow][Torrent]- [/COLOR]%s [online]' % ( title_torrent) if url != "": #Torrent itemlist.append( Item(channel=item.channel, action="play", server="torrent", title=title_torrent, fulltitle=title, url=url, thumbnail=caratula, plot=item.plot, infoLabels=item.infoLabels, folder=False)) logger.debug("TORRENT: url: " + url + " / title: " + title + " / calidad: " + item.quality + " / context: " + str(item.context)) # escraped ver vídeos, descargar vídeos un link, múltiples liks data = data.replace( "http://tumejorserie.com/descargar/url_encript.php?link=", "(") data = re.sub( r'javascript:;" onClick="popup\("http:\/\/(?:www.)?mispelisyseries.com\/\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) if len(enlaces_ver) > 0: if not config.get_setting( "unify"): #Si Titulos Inteligentes NO seleccionados: itemlist.append( item.clone(title="[COLOR gold]**- Enlaces Ver: -**[/COLOR]", action="", folder=False)) else: itemlist.append( item.clone(title="[COLOR gold] Enlaces Ver: [/COLOR]", action="", folder=False)) for logo, servidor, idioma, calidad, enlace, titulo in enlaces_ver: if "Ver" in titulo: servidor = servidor.replace("streamin", "streaminto") titulo = title mostrar_server = True if config.get_setting("hidepremium"): mostrar_server = servertools.is_server_enabled(servidor) titulo = '[COLOR yellow][%s]-[/COLOR] %s [online]' % ( servidor.capitalize(), titulo) logger.debug("VER: url: " + enlace + " / title: " + titulo + " / servidor: " + servidor + " / idioma: " + idioma) if mostrar_server: try: devuelve = servertools.findvideosbyserver(enlace, servidor) if devuelve: enlace = devuelve[0][1] item.alive = servertools.check_video_link( enlace, servidor) if item.alive.lower() == "ok": titulo = '%s, %s' % (item.alive, titulo) elif item.alive == "??": titulo = '[COLOR salmon]%s[/COLOR], %s' % ( item.alive, titulo) else: logger.debug(item.alive + ": / " + titulo + " / " + enlace) raise itemlist.append( Item(fanart=item.fanart, channel=item.channel, action="play", server=servidor, title=titulo, fulltitle=title, url=enlace, thumbnail=logo, plot=item.plot, infoLabels=item.infoLabels, folder=False)) except: pass if len(enlaces_descargar) > 0: if not config.get_setting( "unify"): #Si Titulos Inteligentes NO seleccionados: itemlist.append( item.clone( title="[COLOR gold]**- Enlaces Descargar: -**[/COLOR]", action="", folder=False)) else: itemlist.append( item.clone(title="[COLOR gold] Enlaces Descargar: [/COLOR]", action="", folder=False)) for logo, servidor, idioma, calidad, enlace, titulo in enlaces_descargar: if "Ver" not in titulo: servidor = servidor.replace("uploaded", "uploadedto") partes = enlace.split(" ") titulo = "Descarga " p = 1 logger.debug("DESCARGAR: url: " + enlace + " / title: " + titulo + title + " / servidor: " + servidor + " / idioma: " + idioma) for enlace in partes: parte_titulo = titulo + " (%s/%s)" % (p, len(partes)) p += 1 mostrar_server = True if config.get_setting("hidepremium"): mostrar_server = servertools.is_server_enabled(servidor) parte_titulo = '[COLOR yellow][%s]-[/COLOR] %s' % ( servidor.capitalize(), parte_titulo) if item.infoLabels['quality']: if not config.get_setting( "unify" ): #Si Titulos Inteligentes NO seleccionados: parte_titulo = '%s [%s]' % (parte_titulo, item.infoLabels['quality']) else: parte_titulo = '%s (%s)' % (parte_titulo, item.infoLabels['quality']) if mostrar_server: try: devuelve = servertools.findvideosbyserver( enlace, servidor) if devuelve: enlace = devuelve[0][1] if p <= 2: item.alive = servertools.check_video_link( enlace, servidor) if item.alive.lower() == "ok": parte_titulo = '%s, %s' % (item.alive, parte_titulo) elif item.alive == "??": parte_titulo = '[COLOR salmon]%s[/COLOR], %s' % ( item.alive, parte_titulo) else: logger.debug(item.alive + ": / " + parte_titulo + " / " + enlace) break itemlist.append( Item(fanart=item.fanart, channel=item.channel, action="play", server=servidor, title=parte_titulo, fulltitle=title, url=enlace, thumbnail=logo, plot=item.plot, infoLabels=item.infoLabels, folder=False)) except: pass return itemlist
def set_content(content_type, silent=False): """ Procedimiento para auto-configurar la videoteca de kodi con los valores por defecto @type content_type: str ('movie' o 'tvshow') @param content_type: tipo de contenido para configurar, series o peliculas """ continuar = True msg_text = "" videolibrarypath = config.get_setting("videolibrarypath") if content_type == 'movie': scraper = [config.get_localized_string(70093), config.get_localized_string(70096)] seleccion = platformtools.dialog_select(config.get_localized_string(70094), scraper) # Instalar The Movie Database if seleccion == -1 or seleccion == 0: if not xbmc.getCondVisibility('System.HasAddon(metadata.themoviedb.org)'): if not silent: # Preguntar si queremos instalar metadata.themoviedb.org install = platformtools.dialog_yesno(config.get_localized_string(60046)) else: install = True if install: try: # Instalar metadata.themoviedb.org xbmc.executebuiltin('xbmc.installaddon(metadata.themoviedb.org)', True) logger.info("Instalado el Scraper de películas de TheMovieDB") except: pass continuar = (install and xbmc.getCondVisibility('System.HasAddon(metadata.themoviedb.org)')) if not continuar: msg_text = config.get_localized_string(60047) if continuar: xbmc.executebuiltin('xbmc.addon.opensettings(metadata.themoviedb.org)', True) # Instalar Universal Movie Scraper elif seleccion == 1: if continuar and not xbmc.getCondVisibility('System.HasAddon(metadata.universal)'): continuar = False if not silent: # Preguntar si queremos instalar metadata.universal install = platformtools.dialog_yesno(config.get_localized_string(70095)) else: install = True if install: try: xbmc.executebuiltin('xbmc.installaddon(metadata.universal)', True) if xbmc.getCondVisibility('System.HasAddon(metadata.universal)'): continuar = True except: pass continuar = (install and continuar) if not continuar: msg_text = config.get_localized_string(70097) if continuar: xbmc.executebuiltin('xbmc.addon.opensettings(metadata.universal)', True) else: # SERIES scraper = [config.get_localized_string(70098), config.get_localized_string(70093)] seleccion = platformtools.dialog_select(config.get_localized_string(70107), scraper) # Instalar The TVDB if seleccion == -1 or seleccion == 0: if not xbmc.getCondVisibility('System.HasAddon(metadata.tvdb.com)'): if not silent: # Preguntar si queremos instalar metadata.tvdb.com install = platformtools.dialog_yesno(config.get_localized_string(60048)) else: install = True if install: try: # Instalar metadata.tvdb.com xbmc.executebuiltin('xbmc.installaddon(metadata.tvdb.com)', True) logger.info("Instalado el Scraper de series de The TVDB") except: pass continuar = (install and xbmc.getCondVisibility('System.HasAddon(metadata.tvdb.com)')) if not continuar: msg_text = config.get_localized_string(70099) if continuar: xbmc.executebuiltin('xbmc.addon.opensettings(metadata.tvdb.com)', True) # Instalar The Movie Database elif seleccion == 1: if continuar and not xbmc.getCondVisibility('System.HasAddon(metadata.tvshows.themoviedb.org)'): continuar = False if not silent: # Preguntar si queremos instalar metadata.tvshows.themoviedb.org install = platformtools.dialog_yesno(config.get_localized_string(70100)) else: install = True if install: try: # Instalar metadata.tvshows.themoviedb.org xbmc.executebuiltin('xbmc.installaddon(metadata.tvshows.themoviedb.org)', True) if xbmc.getCondVisibility('System.HasAddon(metadata.tvshows.themoviedb.org)'): continuar = True except: pass continuar = (install and continuar) if not continuar: msg_text = config.get_localized_string(60047) if continuar: xbmc.executebuiltin('xbmc.addon.opensettings(metadata.tvshows.themoviedb.org)', True) idPath = 0 idParentPath = 0 if continuar: continuar = False # Buscamos el idPath sql = 'SELECT MAX(idPath) FROM path' nun_records, records = execute_sql_kodi(sql) if nun_records == 1: idPath = records[0][0] + 1 sql_videolibrarypath = videolibrarypath if sql_videolibrarypath.startswith("special://"): sql_videolibrarypath = sql_videolibrarypath.replace('/profile/', '/%/').replace('/home/userdata/', '/%/') sep = '/' elif sql_videolibrarypath.startswith("smb://"): sep = '/' else: sep = os.sep if not sql_videolibrarypath.endswith(sep): sql_videolibrarypath += sep # Buscamos el idParentPath sql = 'SELECT idPath, strPath FROM path where strPath LIKE "%s"' % sql_videolibrarypath nun_records, records = execute_sql_kodi(sql) if nun_records == 1: idParentPath = records[0][0] videolibrarypath = records[0][1][:-1] continuar = True else: # No existe videolibrarypath en la BD: la insertamos sql_videolibrarypath = videolibrarypath if not sql_videolibrarypath.endswith(sep): sql_videolibrarypath += sep sql = 'INSERT INTO path (idPath, strPath, scanRecursive, useFolderNames, noUpdate, exclude) VALUES ' \ '(%s, "%s", 0, 0, 0, 0)' % (idPath, sql_videolibrarypath) nun_records, records = execute_sql_kodi(sql) if nun_records == 1: continuar = True idParentPath = idPath idPath += 1 else: msg_text = config.get_localized_string(70101) if continuar: continuar = False # Fijamos strContent, strScraper, scanRecursive y strSettings if content_type == 'movie': strContent = 'movies' scanRecursive = 2147483647 if seleccion == -1 or seleccion == 0: strScraper = 'metadata.themoviedb.org' path_settings = xbmc.translatePath("special://profile/addon_data/metadata.themoviedb.org/settings.xml") elif seleccion == 1: strScraper = 'metadata.universal' path_settings = xbmc.translatePath("special://profile/addon_data/metadata.universal/settings.xml") settings_data = filetools.read(path_settings) strSettings = ' '.join(settings_data.split()).replace("> <", "><") strSettings = strSettings.replace("\"","\'") strActualizar = "¿Desea configurar este Scraper en español como opción por defecto para películas?" if not videolibrarypath.endswith(sep): videolibrarypath += sep strPath = videolibrarypath + config.get_setting("folder_movies") + sep else: strContent = 'tvshows' scanRecursive = 0 if seleccion == -1 or seleccion == 0: strScraper = 'metadata.tvdb.com' path_settings = xbmc.translatePath("special://profile/addon_data/metadata.tvdb.com/settings.xml") elif seleccion == 1: strScraper = 'metadata.tvshows.themoviedb.org' path_settings = xbmc.translatePath("special://profile/addon_data/metadata.tvshows.themoviedb.org/settings.xml") settings_data = filetools.read(path_settings) strSettings = ' '.join(settings_data.split()).replace("> <", "><") strSettings = strSettings.replace("\"","\'") strActualizar = "¿Desea configurar este Scraper en español como opción por defecto para series?" if not videolibrarypath.endswith(sep): videolibrarypath += sep strPath = videolibrarypath + config.get_setting("folder_tvshows") + sep logger.info("%s: %s" % (content_type, strPath)) # Comprobamos si ya existe strPath en la BD para evitar duplicados sql = 'SELECT idPath FROM path where strPath="%s"' % strPath nun_records, records = execute_sql_kodi(sql) sql = "" if nun_records == 0: # Insertamos el scraper sql = 'INSERT INTO path (idPath, strPath, strContent, strScraper, scanRecursive, useFolderNames, ' \ 'strSettings, noUpdate, exclude, idParentPath) VALUES (%s, "%s", "%s", "%s", %s, 0, ' \ '"%s", 0, 0, %s)' % ( idPath, strPath, strContent, strScraper, scanRecursive, strSettings, idParentPath) else: if not silent: # Preguntar si queremos configurar themoviedb.org como opcion por defecto actualizar = platformtools.dialog_yesno(config.get_localized_string(70098), strActualizar) else: actualizar = True if actualizar: # Actualizamos el scraper idPath = records[0][0] sql = 'UPDATE path SET strContent="%s", strScraper="%s", scanRecursive=%s, strSettings="%s" ' \ 'WHERE idPath=%s' % (strContent, strScraper, scanRecursive, strSettings, idPath) if sql: nun_records, records = execute_sql_kodi(sql) if nun_records == 1: continuar = True if not continuar: msg_text = config.get_localized_string(60055) if not continuar: heading = config.get_localized_string(70102) % content_type elif content_type == 'SERIES' and not xbmc.getCondVisibility( 'System.HasAddon(metadata.tvshows.themoviedb.org)'): heading = config.get_localized_string(70103) % content_type msg_text = config.get_localized_string(60058) else: heading = config.get_localized_string(70103) % content_type msg_text = config.get_localized_string(70104) platformtools.dialog_notification(heading, msg_text, icon=1, time=3000) logger.info("%s: %s" % (heading, msg_text))
def sync_trakt_addon(path_folder): """ Actualiza los valores de episodios vistos si """ logger.info() # si existe el addon hacemos la busqueda if xbmc.getCondVisibility('System.HasAddon("script.trakt")'): # importamos dependencias paths = ["special://home/addons/script.module.dateutil/lib/", "special://home/addons/script.module.six/lib/", "special://home/addons/script.module.arrow/lib/", "special://home/addons/script.module.trakt/lib/", "special://home/addons/script.trakt/"] for path in paths: import sys sys.path.append(xbmc.translatePath(path)) # se obtiene las series vistas try: from resources.lib.traktapi import traktAPI traktapi = traktAPI() except: return shows = traktapi.getShowsWatched({}) shows = shows.items() # obtenemos el id de la serie para comparar import re _id = re.findall("\[(.*?)\]", path_folder, flags=re.DOTALL)[0] logger.debug("el id es %s" % _id) if "tt" in _id: type_id = "imdb" elif "tvdb_" in _id: _id = _id.strip("tvdb_") type_id = "tvdb" elif "tmdb_" in _id: type_id = "tmdb" _id = _id.strip("tmdb_") else: logger.error("No hay _id de la serie") return # obtenemos los valores de la serie from core import videolibrarytools tvshow_file = filetools.join(path_folder, "tvshow.nfo") head_nfo, serie = videolibrarytools.read_nfo(tvshow_file) # buscamos en las series de trakt for show in shows: show_aux = show[1].to_dict() try: _id_trakt = show_aux['ids'].get(type_id, None) # logger.debug("ID ES %s" % _id_trakt) if _id_trakt: if _id == _id_trakt: logger.debug("ENCONTRADO!! %s" % show_aux) # creamos el diccionario de trakt para la serie encontrada con el valor que tiene "visto" dict_trakt_show = {} for idx_season, season in enumerate(show_aux['seasons']): for idx_episode, episode in enumerate(show_aux['seasons'][idx_season]['episodes']): sea_epi = "%sx%s" % (show_aux['seasons'][idx_season]['number'], str(show_aux['seasons'][idx_season]['episodes'][idx_episode][ 'number']).zfill(2)) dict_trakt_show[sea_epi] = show_aux['seasons'][idx_season]['episodes'][idx_episode][ 'watched'] logger.debug("dict_trakt_show %s " % dict_trakt_show) # obtenemos las keys que son episodios regex_epi = re.compile('\d+x\d+') keys_episodes = [key for key in serie.library_playcounts if regex_epi.match(key)] # obtenemos las keys que son temporadas keys_seasons = [key for key in serie.library_playcounts if 'season ' in key] # obtenemos los numeros de las keys temporadas seasons = [key.strip('season ') for key in keys_seasons] # marcamos los episodios vistos for k in keys_episodes: serie.library_playcounts[k] = dict_trakt_show.get(k, 0) for season in seasons: episodios_temporada = 0 episodios_vistos_temporada = 0 # obtenemos las keys de los episodios de una determinada temporada keys_season_episodes = [key for key in keys_episodes if key.startswith("%sx" % season)] for k in keys_season_episodes: episodios_temporada += 1 if serie.library_playcounts[k] > 0: episodios_vistos_temporada += 1 # se comprueba que si todos los episodios están vistos, se marque la temporada como vista if episodios_temporada == episodios_vistos_temporada: serie.library_playcounts.update({"season %s" % season: 1}) temporada = 0 temporada_vista = 0 for k in keys_seasons: temporada += 1 if serie.library_playcounts[k] > 0: temporada_vista += 1 # se comprueba que si todas las temporadas están vistas, se marque la serie como vista if temporada == temporada_vista: serie.library_playcounts.update({serie.title: 1}) logger.debug("los valores nuevos %s " % serie.library_playcounts) filetools.write(tvshow_file, head_nfo + serie.tojson()) break else: continue else: logger.error("no se ha podido obtener el id, trakt tiene: %s" % show_aux['ids']) except: import traceback logger.error(traceback.format_exc())
def mark_content_as_watched_on_kodi(item, value=1): """ marca el contenido como visto o no visto en la libreria de Kodi @type item: item @param item: elemento a marcar @type value: int @param value: >0 para visto, 0 para no visto """ logger.info() # logger.debug("item:\n" + item.tostring('\n')) payload_f = '' if item.contentType == "movie": movieid = 0 payload = {"jsonrpc": "2.0", "method": "VideoLibrary.GetMovies", "params": {"properties": ["title", "playcount", "originaltitle", "file"]}, "id": 1} data = get_data(payload) if 'result' in data and "movies" in data['result']: if item.strm_path: #Si Item es de un episodio filename = filetools.basename(item.strm_path) head, tail = filetools.split(filetools.split(item.strm_path)[0]) else: #Si Item es de la Serie filename = filetools.basename(item.path) head, tail = filetools.split(filetools.split(item.path)[0]) path = filetools.join(tail, filename) for d in data['result']['movies']: if d['file'].replace("/", "\\").endswith(path.replace("/", "\\")): # logger.debug("marco la pelicula como vista") movieid = d['movieid'] break if movieid != 0: payload_f = {"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": { "movieid": movieid, "playcount": value}, "id": 1} else: # item.contentType != 'movie' episodeid = 0 payload = {"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes", "params": {"properties": ["title", "playcount", "showtitle", "file", "tvshowid"]}, "id": 1} data = get_data(payload) if 'result' in data and "episodes" in data['result']: if item.strm_path: #Si Item es de un episodio filename = filetools.basename(item.strm_path) head, tail = filetools.split(filetools.split(item.strm_path)[0]) else: #Si Item es de la Serie filename = filetools.basename(item.path) head, tail = filetools.split(filetools.split(item.path)[0]) path = filetools.join(tail, filename) for d in data['result']['episodes']: if d['file'].replace("/", "\\").endswith(path.replace("/", "\\")): # logger.debug("marco el episodio como visto") episodeid = d['episodeid'] break if episodeid != 0: payload_f = {"jsonrpc": "2.0", "method": "VideoLibrary.SetEpisodeDetails", "params": { "episodeid": episodeid, "playcount": value}, "id": 1} if payload_f: # Marcar como visto data = get_data(payload_f) # logger.debug(str(data)) if data['result'] != 'OK': logger.error("ERROR al poner el contenido como visto")
def mark_content_as_watched_on_alfa(path): from channels import videolibrary from core import videolibrarytools from core import scrapertools from core import filetools import re """ marca toda la serie o película como vista o no vista en la Videoteca de Alfa basado en su estado en la Videoteca de Kodi @type str: path @param path: carpeta de contenido a marcar """ logger.info() #logger.debug("path: " + path) FOLDER_MOVIES = config.get_setting("folder_movies") FOLDER_TVSHOWS = config.get_setting("folder_tvshows") VIDEOLIBRARY_PATH = config.get_videolibrary_config_path() if not VIDEOLIBRARY_PATH: return # Solo podemos marcar el contenido como vista en la BBDD de Kodi si la BBDD es local, # en caso de compartir BBDD esta funcionalidad no funcionara #if config.get_setting("db_mode", "videolibrary"): # return path2 = '' if "special://" in VIDEOLIBRARY_PATH: if FOLDER_TVSHOWS in path: path2 = re. sub(r'.*?%s' % FOLDER_TVSHOWS, VIDEOLIBRARY_PATH + "/" + FOLDER_TVSHOWS, path).replace("\\", "/") if FOLDER_MOVIES in path: path2 = re. sub(r'.*?%s' % FOLDER_MOVIES, VIDEOLIBRARY_PATH + "/" + FOLDER_MOVIES, path).replace("\\", "/") if "\\" in path: path = path.replace("/", "\\") head_nfo, item = videolibrarytools.read_nfo(path) #Leo el .nfo del contenido if FOLDER_TVSHOWS in path: #Compruebo si es CINE o SERIE contentType = "episode_view" #Marco la tabla de BBDD de Kodi Video nfo_name = "tvshow.nfo" #Construyo el nombre del .nfo path1 = path.replace("\\\\", "\\").replace(nfo_name, '') #para la SQL solo necesito la carpeta if not path2: path2 = path1.replace("\\", "/") #Formato no Windows else: path2 = path2.replace(nfo_name, '') else: contentType = "movie_view" #Marco la tabla de BBDD de Kodi Video path1 = path.replace("\\\\", "\\") #Formato Windows if not path2: path2 = path1.replace("\\", "/") #Formato no Windows nfo_name = scrapertools.find_single_match(path2, '\]\/(.*?)$') #Construyo el nombre del .nfo path1 = path1.replace(nfo_name, '') #para la SQL solo necesito la carpeta path2 = path2.replace(nfo_name, '') #para la SQL solo necesito la carpeta path2 = filetools.remove_smb_credential(path2) #Si el archivo está en un servidor SMB, quiamos las credenciales #Ejecutmos la sentencia SQL sql = 'select strFileName, playCount from %s where (strPath like "%s" or strPath like "%s")' % (contentType, path1, path2) nun_records = 0 records = None nun_records, records = execute_sql_kodi(sql) #ejecución de la SQL if nun_records == 0: #hay error? logger.error("Error en la SQL: " + sql + ": 0 registros") return #salimos: o no está catalogado en Kodi, o hay un error en la SQL for title, playCount in records: #Ahora recorremos todos los registros obtenidos if contentType == "episode_view": title_plain = title.replace('.strm', '') #Si es Serie, quitamos el sufijo .strm else: title_plain = scrapertools.find_single_match(item.strm_path, '.(.*?\s\[.*?\])') #si es peli, quitamos el título if playCount is None or playCount == 0: #todavía no se ha visto, lo ponemos a 0 playCount_final = 0 elif playCount >= 1: playCount_final = 1 title_plain = title_plain.decode("utf-8").encode("utf-8") #Hacemos esto porque si no genera esto: u'title_plain' item.library_playcounts.update({title_plain: playCount_final}) #actualizamos el playCount del .nfo if item.infoLabels['mediatype'] == "tvshow": #Actualizamos los playCounts de temporadas y Serie for season in item.library_playcounts: if "season" in season: #buscamos las etiquetas "season" dentro de playCounts season_num = int(scrapertools.find_single_match(season, 'season (\d+)')) #salvamos el núm, de Temporada item = videolibrary.check_season_playcount(item, season_num) #llamamos al método que actualiza Temps. y Series filetools.write(path, head_nfo + item.tojson())
data = jsontools.load(response) except Exception, ex: template = "An exception of type %s occured. Arguments:\n%r" message = template % (type(ex).__name__, ex.args) logger.error("error en xbmc_json_rpc_url: %s" % message) data = ["error"] else: try: data = jsontools.load(xbmc.executeJSONRPC(jsontools.dump(payload))) except Exception, ex: template = "An exception of type %s occured. Arguments:\n%r" message = template % (type(ex).__name__, ex.args) logger.error("error en xbmc.executeJSONRPC: %s" % message) data = ["error"] logger.info("data: %s" % data) return data def update(folder_content=config.get_setting("folder_tvshows"), folder=""): """ Actualiza la libreria dependiendo del tipo de contenido y la ruta que se le pase. @type folder_content: str @param folder_content: tipo de contenido para actualizar, series o peliculas @type folder: str @param folder: nombre de la carpeta a escanear. """ logger.info(folder)
def lista(item): logger.info() itemlist = [] if "channels" in item.url: canal = "" data = httptools.downloadpage(item.url).data id = scrapertools.find_single_match( data, '<section id="contenedor".*?a href="https://www.foxtube.com/pu/(\d+)' ) canal = scrapertools.find_single_match(data, 'path : \'([^\']+)\'') headers = { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' } post = {'path': '%s' % canal, 'order_vid': 'uv'} item.url = "https://www.foxtube.com/users/get/%s/videos/1/" % id data = httptools.downloadpage(item.url, post=post, headers=headers).data if "users" in item.url: canal = item.canal headers = { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' } post = {'path': '%s' % canal, 'order_vid': 'uv'} data = httptools.downloadpage(item.url, post=post, headers=headers).data else: data = httptools.downloadpage(item.url).data data = re.sub(r"\n|\r|\t| |<br>", "", data) data = data.replace("\\n", "").replace("\\", "") if "pornstars" in item.url: data = scrapertools.find_single_match( data, '<html lang="en">(.*?)>Similar pornstars</h2>') patron = '<article>.*?' patron += '<a href="([^"]+)".*?' patron += '<img.*?src="([^"]+)".*?' patron += 'alt="([^"]+)".*?' patron += '<span class="r\w">(.*?)</a>' matches = re.compile(patron, re.DOTALL).findall(data) for scrapedurl, scrapedthumbnail, scrapedtitle, duracion in matches: time = scrapertools.find_single_match(duracion, '<span>([^<]+)</span></span>') title = "[COLOR yellow]%s[/COLOR] %s" % (time, scrapedtitle) if 'HD' in duracion: title = "[COLOR yellow]%s[/COLOR] [COLOR red]HD[/COLOR] %s" % ( time, scrapedtitle) thumbnail = scrapedthumbnail.replace("https", "http") + "|Referer=%s/" % host plot = "" itemlist.append( item.clone(action="play", title=title, url=scrapedurl, thumbnail=thumbnail, fanart=thumbnail, plot=plot, contentTitle=title)) next_page = scrapertools.find_single_match( data, '<a rel="next" href="([^"]+)">>') if "pornstars" in item.url: next_page = scrapertools.find_single_match( data, '<a href="([^"]+)" rel="next">') if "users" in item.url: page = scrapertools.find_single_match(item.url, "(.*?/videos)/\d+") next_page = scrapertools.find_single_match( data, '<li class="selected">.*?data-pag="(\d+)"') if next_page: next_page = "%s/%s/" % (page, next_page) itemlist.append( item.clone(action="lista", title="[COLOR blue]Página Siguiente >>[/COLOR]", url=next_page, canal=canal)) else: next_page = urlparse.urljoin(item.url, next_page) itemlist.append( item.clone(action="lista", title="[COLOR blue]Página Siguiente >>[/COLOR]", url=next_page)) return itemlist
def start(itemlist, item): ''' Metodo principal desde donde se reproduce automaticamente los enlaces - En caso la opcion de personalizar activa utilizara las opciones definidas por el usuario. - En caso contrario intentara reproducir cualquier enlace que cuente con el idioma preferido. :param itemlist: list (lista de items listos para reproducir, o sea con action='play') :param item: item (el item principal del canal) :return: intenta autoreproducir, en caso de fallar devuelve el itemlist que recibio en un principio ''' logger.info() if not config.is_xbmc(): #platformtools.dialog_notification('AutoPlay ERROR', 'Sólo disponible para XBMC/Kodi') return itemlist global autoplay_node if not autoplay_node: # Obtiene el nodo AUTOPLAY desde el json autoplay_node = jsontools.get_node_from_file('autoplay', 'AUTOPLAY') if not item.channel in autoplay_node: return itemlist # Agrega servidores y calidades que no estaban listados a autoplay_node new_options = check_value(item.channel, itemlist) # Obtiene el nodo del canal desde autoplay_node channel_node = autoplay_node.get(item.channel, {}) # Obtiene los ajustes des autoplay para este canal settings_node = channel_node.get('settings', {}) if settings_node['active']: url_list_valid = [] autoplay_list = [] autoplay_b = [] favorite_servers = [] favorite_quality = [] # Guarda el valor actual de "Accion y Player Mode" en preferencias user_config_setting_action = config.get_setting("default_action") user_config_setting_player = config.get_setting("player_mode") # Habilita la accion "Ver en calidad alta" (si el servidor devuelve más de una calidad p.e. gdrive) if user_config_setting_action != 2: config.set_setting("default_action", 2) if user_config_setting_player != 0: config.set_setting("player_mode", 0) # Informa que AutoPlay esta activo #platformtools.dialog_notification('AutoPlay Activo', '', sound=False) # Prioridades a la hora de ordenar itemlist: # 0: Servidores y calidades # 1: Calidades y servidores # 2: Solo servidores # 3: Solo calidades # 4: No ordenar if settings_node['custom_servers'] and settings_node['custom_quality']: priority = settings_node['priority'] # 0: Servidores y calidades o 1: Calidades y servidores elif settings_node['custom_servers']: priority = 2 # Solo servidores elif settings_node['custom_quality']: priority = 3 # Solo calidades else: priority = 4 # No ordenar # Obtiene las listas servidores, calidades disponibles desde el nodo del json de AutoPlay server_list = channel_node.get('servers', []) for server in server_list: server = server.lower() quality_list = channel_node.get('quality', []) # Si no se definen calidades la se asigna default como calidad unica if len(quality_list) == 0: quality_list =['default'] # Se guardan los textos de cada servidor y calidad en listas p.e. favorite_servers = ['openload', # 'streamcloud'] for num in range(1, 4): favorite_servers.append(channel_node['servers'][settings_node['server_%s' % num]].lower()) favorite_quality.append(channel_node['quality'][settings_node['quality_%s' % num]]) # Se filtran los enlaces de itemlist y que se correspondan con los valores de autoplay for item in itemlist: autoplay_elem = dict() b_dict = dict() # Comprobamos q se trata de un item de video if 'server' not in item: continue # Agrega la opcion configurar AutoPlay al menu contextual if 'context' not in item: item.context = list() if not filter(lambda x: x['action'] == 'autoplay_config', context): item.context.append({"title": "Configurar AutoPlay", "action": "autoplay_config", "channel": "autoplay", "from_channel": item.channel}) # Si no tiene calidad definida le asigna calidad 'default' if item.quality == '': item.quality = 'default' # Se crea la lista para configuracion personalizada if priority < 2: # 0: Servidores y calidades o 1: Calidades y servidores # si el servidor y la calidad no se encuentran en las listas de favoritos o la url esta repetida, # descartamos el item if item.server.lower() not in favorite_servers or item.quality not in favorite_quality \ or item.url in url_list_valid: item.type_b = True b_dict['videoitem']= item autoplay_b.append(b_dict) continue autoplay_elem["indice_server"] = favorite_servers.index(item.server.lower()) autoplay_elem["indice_quality"] = favorite_quality.index(item.quality) elif priority == 2: # Solo servidores # si el servidor no se encuentra en la lista de favoritos o la url esta repetida, # descartamos el item if item.server.lower() not in favorite_servers or item.url in url_list_valid: item.type_b = True b_dict['videoitem'] = item autoplay_b.append(b_dict) continue autoplay_elem["indice_server"] = favorite_servers.index(item.server.lower()) elif priority == 3: # Solo calidades # si la calidad no se encuentra en la lista de favoritos o la url esta repetida, # descartamos el item if item.quality not in favorite_quality or item.url in url_list_valid: item.type_b = True b_dict['videoitem'] = item autoplay_b.append(b_dict) continue autoplay_elem["indice_quality"] = favorite_quality.index(item.quality) else: # No ordenar # si la url esta repetida, descartamos el item if item.url in url_list_valid: continue # Si el item llega hasta aqui lo añadimos al listado de urls validas y a autoplay_list url_list_valid.append(item.url) item.plan_b=True autoplay_elem['videoitem'] = item # autoplay_elem['server'] = item.server # autoplay_elem['quality'] = item.quality autoplay_list.append(autoplay_elem) # Ordenamos segun la prioridad if priority == 0: # Servidores y calidades autoplay_list.sort(key=lambda orden: (orden['indice_server'], orden['indice_quality'])) elif priority == 1: # Calidades y servidores autoplay_list.sort(key=lambda orden: (orden['indice_quality'], orden['indice_server'])) elif priority == 2: # Solo servidores autoplay_list.sort(key=lambda orden: orden['indice_server']) elif priority == 3: # Solo calidades autoplay_list.sort(key=lambda orden: orden['indice_quality']) # Se prepara el plan b, en caso de estar activo se agregan los elementos no favoritos al final plan_b = settings_node['plan_b'] ready = False text_b = '' if plan_b: autoplay_list.extend(autoplay_b) # Si hay elementos en la lista de autoplay se intenta reproducir cada elemento, hasta encontrar uno # funcional o fallen todos if autoplay_list or (plan_b and autoplay_b): played = False max_intentos = 5 max_intentos_servers = {} # Si se esta reproduciendo algo detiene la reproduccion if platformtools.is_playing(): platformtools.stop_video() for autoplay_elem in autoplay_list: play_item = Item # Si no es un elemento favorito si agrega el texto plan b if autoplay_elem['videoitem'].type_b: text_b = '(Plan B)' if not platformtools.is_playing() and not played: videoitem = autoplay_elem['videoitem'] logger.debug('videoitem %s' % videoitem) if videoitem.server.lower() not in max_intentos_servers: max_intentos_servers[videoitem.server.lower()] = max_intentos # Si se han alcanzado el numero maximo de intentos de este servidor saltamos al siguiente if max_intentos_servers[videoitem.server.lower()] == 0: continue lang = " " if hasattr(videoitem, 'language') and videoitem.language != "": lang = " '%s' " % videoitem.language platformtools.dialog_notification("AutoPlay %s" %text_b, "%s%s%s" % ( videoitem.server.upper(), lang, videoitem.quality.upper()), sound=False) # TODO videoitem.server es el id del server, pero podria no ser el nombre!!! # Intenta reproducir los enlaces # Si el canal tiene metodo play propio lo utiliza channel = __import__('channels.%s' % item.channel, None, None, ["channels.%s" % item.channel]) if hasattr(channel, 'play'): resolved_item = getattr(channel, 'play')(videoitem) if len(resolved_item) > 0: if isinstance(resolved_item[0], list): videoitem.video_urls = resolved_item else: videoitem = resolved_item[0] # Si no directamente reproduce y marca como visto # Verifica si el item viene de la videoteca try: if item.contentChannel =='videolibrary': # Marca como visto from platformcode import xbmc_videolibrary xbmc_videolibrary.mark_auto_as_watched(item) # Rellena el video con los datos del item principal y reproduce play_item = item.clone(url=videoitem) platformtools.play_video(play_item.url, autoplay=True) else: # Si no viene de la videoteca solo reproduce platformtools.play_video(videoitem, autoplay=True) except: pass try: if platformtools.is_playing(): played = True break except: logger.debug(str(len(autoplay_list))) # Si hemos llegado hasta aqui es por q no se ha podido reproducir max_intentos_servers[videoitem.server.lower()] -= 1 # Si se han alcanzado el numero maximo de intentos de este servidor # preguntar si queremos seguir probando o lo ignoramos if max_intentos_servers[videoitem.server.lower()] == 0: text = "Parece que los enlaces de %s no estan funcionando." % videoitem.server.upper() if not platformtools.dialog_yesno("AutoPlay", text, "¿Desea ignorar todos los enlaces de este servidor?"): max_intentos_servers[videoitem.server.lower()] = max_intentos # Si no quedan elementos en la lista se informa if autoplay_elem == autoplay_list[-1]: platformtools.dialog_notification('AutoPlay', 'No hubo enlaces funcionales') else: platformtools.dialog_notification('AutoPlay No Fue Posible', 'No Hubo Coincidencias') if new_options: platformtools.dialog_notification("AutoPlay", "Nueva Calidad/Servidor disponible en la " "configuracion", sound=False) # Restaura si es necesario el valor previo de "Accion y Player Mode" en preferencias if user_config_setting_action != 2: config.set_setting("default_action", user_config_setting_action) if user_config_setting_player != 0: config.set_setting("player_mode", user_config_setting_player) # devuelve la lista de enlaces para la eleccion manual return itemlist
def emergency_urls(item, channel=None, path=None): logger.info() import re """ Llamamos a Findvideos del canal con la variable "item.videolibray_emergency_urls = True" para obtener la variable "item.emergency_urls" con la lista de listas de tuplas de los enlaces torrent y de servidores directos para ese episodio o película En la lista [0] siempre deben ir los enlaces torrents, si los hay. Si se desea cachear los .torrents, la búsqueda va contra esa lista. En la lista dos irán los enlaces de servidores directos, pero también pueden ir enlaces magnet (que no son cacheables) """ #lanazamos un "lookup" en el "findvideos" del canal para obtener los enlaces de emergencia try: if channel == None: #Si el llamador no ha aportado la estructura de channel, se crea channel = generictools.verify_channel( item.channel ) #Se verifica si es un clon, que devuelva "newpct1" #channel = __import__('channels.%s' % channel, fromlist=["channels.%s" % channel]) channel = __import__('specials.%s' % channel_alt, fromlist=["specials.%s" % channel_alt]) if hasattr(channel, 'findvideos'): #Si el canal tiene "findvideos"... item.videolibray_emergency_urls = True #... se marca como "lookup" channel_save = item.channel #... guarda el canal original por si hay fail-over en Newpct1 item_res = getattr(channel, 'findvideos')(item) #... se procesa Findvideos item_res.channel = channel_save #... restaura el canal original por si hay fail-over en Newpct1 item_res.category = channel_save.capitalize() #... y la categoría del item_res.videolibray_emergency_urls #... y se borra la marca de lookup except: logger.error('ERROR al procesar el título en Findvideos del Canal: ' + item.channel + ' / ' + item.title) logger.error(traceback.format_exc()) item_res = item.clone( ) #Si ha habido un error, se devuelve el Item original if item_res.videolibray_emergency_urls: del item_res.videolibray_emergency_urls #... y se borra la marca de lookup #Si el usuario ha activado la opción "emergency_urls_torrents", se descargarán los archivos .torrent de cada título else: #Si se han cacheado con éxito los enlaces... try: referer = None post = None channel_bis = generictools.verify_channel(item.channel) if config.get_setting( "emergency_urls_torrents", channel_bis) and item_res.emergency_urls and path != None: videolibrary_path = config.get_videolibrary_path( ) #detectamos el path absoluto del título movies = config.get_setting("folder_movies") series = config.get_setting("folder_tvshows") if movies in path: folder = movies else: folder = series videolibrary_path = filetools.join(videolibrary_path, folder) i = 1 if item_res.referer: referer = item_res.referer if item_res.post: post = item_res.post for url in item_res.emergency_urls[ 0]: #Recorremos las urls de emergencia... torrents_path = re.sub(r'(?:\.\w+$)', '_%s.torrent' % str(i).zfill(2), path) path_real = caching_torrents( url, referer, post, torrents_path=torrents_path ) #... para descargar los .torrents if path_real: #Si ha tenido éxito... item_res.emergency_urls[0][i - 1] = path_real.replace( videolibrary_path, '') #se guarda el "path" relativo i += 1 #Restauramos variables originales if item.referer: item_res.referer = item.referer elif item_res.referer: del item_res.referer if item.referer: item_res.referer = item.referer elif item_res.referer: del item_res.referer item_res.url = item.url except: logger.error('ERROR al cachear el .torrent de: ' + item.channel + ' / ' + item.title) logger.error(traceback.format_exc()) item_res = item.clone( ) #Si ha habido un error, se devuelve el Item original #logger.debug(item_res.emergency_urls) return item_res #Devolvemos el Item actualizado con los enlaces de emergencia
def execute_sql_kodi(sql): """ Ejecuta la consulta sql contra la base de datos de kodi @param sql: Consulta sql valida @type sql: str @return: Numero de registros modificados o devueltos por la consulta @rtype nun_records: int @return: lista con el resultado de la consulta @rtype records: list of tuples """ logger.info() file_db = "" nun_records = 0 records = None # Buscamos el archivo de la BBDD de videos segun la version de kodi video_db = config.get_platform(True)['video_db'] if video_db: file_db = filetools.join(xbmc.translatePath("special://userdata/Database"), video_db) # metodo alternativo para localizar la BBDD if not file_db or not filetools.exists(file_db): file_db = "" for f in filetools.listdir(xbmc.translatePath("special://userdata/Database")): path_f = filetools.join(xbmc.translatePath("special://userdata/Database"), f) if filetools.isfile(path_f) and f.lower().startswith('myvideos') and f.lower().endswith('.db'): file_db = path_f break if file_db: logger.info("Archivo de BD: %s" % file_db) conn = None try: import sqlite3 conn = sqlite3.connect(file_db) cursor = conn.cursor() logger.info("Ejecutando sql: %s" % sql) cursor.execute(sql) conn.commit() records = cursor.fetchall() if sql.lower().startswith("select"): nun_records = len(records) if nun_records == 1 and records[0][0] is None: nun_records = 0 records = [] else: nun_records = conn.total_changes conn.close() logger.info("Consulta ejecutada. Registros: %s" % nun_records) except: logger.error("Error al ejecutar la consulta sql") if conn: conn.close() else: logger.debug("Base de datos no encontrada") return nun_records, records
def caching_torrents(url, referer=None, post=None, torrents_path=None, timeout=10, lookup=False, data_torrent=False): if torrents_path != None: logger.info("path = " + torrents_path) else: logger.info() if referer and post: logger.info('REFERER: ' + referer) from core import httptools torrent_file = '' headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'Referer': referer } #Necesario para el Post del .Torrent """ Descarga en el path recibido el .torrent de la url recibida, y pasa el decode Devuelve el path real del .torrent, o el path vacío si la operación no ha tenido éxito """ videolibrary_path = config.get_videolibrary_path( ) #Calculamos el path absoluto a partir de la Videoteca if torrents_path == None: if not videolibrary_path: torrents_path = '' if data_torrent: return (torrents_path, torrent_file) return torrents_path #Si hay un error, devolvemos el "path" vacío torrents_path = filetools.join( videolibrary_path, 'temp_torrents_Alfa', 'cliente_torrent_Alfa.torrent') #path de descarga temporal if '.torrent' not in torrents_path: torrents_path += '.torrent' #path para dejar el .torrent torrents_path_encode = filetools.encode( torrents_path) #encode utf-8 del path if url.endswith(".rar") or url.startswith( "magnet:"): #No es un archivo .torrent logger.error('No es un archivo Torrent: ' + url) torrents_path = '' if data_torrent: return (torrents_path, torrent_file) return torrents_path #Si hay un error, devolvemos el "path" vacío try: #Descargamos el .torrent if referer and post: #Descarga con POST response = httptools.downloadpage(url, headers=headers, post=post, follow_redirects=False, timeout=timeout) else: #Descarga sin post response = httptools.downloadpage(url, timeout=timeout) if not response.sucess: logger.error('Archivo .torrent no encontrado: ' + url) torrents_path = '' if data_torrent: return (torrents_path, torrent_file) return torrents_path #Si hay un error, devolvemos el "path" vacío torrent_file = response.data if "used CloudFlare" in torrent_file: #Si tiene CloudFlare, usamos este proceso response = httptools.downloadpage( "http://anonymouse.org/cgi-bin/anon-www.cgi/" + url.strip(), timeout=timeout) if not response.sucess: logger.error('Archivo .torrent no encontrado: ' + url) torrents_path = '' if data_torrent: return (torrents_path, torrent_file) return torrents_path #Si hay un error, devolvemos el "path" vacío torrent_file = response.data #Si es un archivo .ZIP tratamos de extraer el contenido if torrent_file.startswith("PK"): logger.info('Es un archivo .ZIP: ' + url) torrents_path_zip = filetools.join( videolibrary_path, 'temp_torrents_zip') #Carpeta de trabajo torrents_path_zip = filetools.encode(torrents_path_zip) torrents_path_zip_file = filetools.join( torrents_path_zip, 'temp_torrents_zip.zip') #Nombre del .zip import time filetools.rmdirtree( torrents_path_zip) #Borramos la carpeta temporal time.sleep(1) #Hay que esperar, porque si no da error filetools.mkdir(torrents_path_zip) #La creamos de nuevo if filetools.write(torrents_path_zip_file, torrent_file): #Salvamos el .zip torrent_file = '' #Borramos el contenido en memoria try: #Extraemos el .zip from core import ziptools unzipper = ziptools.ziptools() unzipper.extract(torrents_path_zip_file, torrents_path_zip) except: import xbmc xbmc.executebuiltin( 'XBMC.Extract("%s", "%s")' % (torrents_path_zip_file, torrents_path_zip)) time.sleep(1) import os for root, folders, files in os.walk( torrents_path_zip ): #Recorremos la carpeta para leer el .torrent for file in files: if file.endswith(".torrent"): input_file = filetools.join( root, file) #nombre del .torrent torrent_file = filetools.read( input_file) #leemos el .torrent filetools.rmdirtree( torrents_path_zip) #Borramos la carpeta temporal #Si no es un archivo .torrent (RAR, HTML,..., vacío) damos error if not scrapertools.find_single_match(torrent_file, '^d\d+:.*?\d+:'): logger.error('No es un archivo Torrent: ' + url) torrents_path = '' if data_torrent: return (torrents_path, torrent_file) return torrents_path #Si hay un error, devolvemos el "path" vacío #Salvamos el .torrent if not lookup: if not filetools.write(torrents_path_encode, torrent_file): logger.error('ERROR: Archivo .torrent no escrito: ' + torrents_path_encode) torrents_path = '' #Si hay un error, devolvemos el "path" vacío torrent_file = '' #... y el buffer del .torrent if data_torrent: return (torrents_path, torrent_file) return torrents_path except: torrents_path = '' #Si hay un error, devolvemos el "path" vacío torrent_file = '' #... y el buffer del .torrent logger.error('Error en el proceso de descarga del .torrent: ' + url + ' / ' + torrents_path_encode) logger.error(traceback.format_exc()) #logger.debug(torrents_path) if data_torrent: return (torrents_path, torrent_file) return torrents_path
def add_sources(path): logger.info() from xml.dom import minidom SOURCES_PATH = xbmc.translatePath("special://userdata/sources.xml") if os.path.exists(SOURCES_PATH): xmldoc = minidom.parse(SOURCES_PATH) else: # Crear documento xmldoc = minidom.Document() nodo_sources = xmldoc.createElement("sources") for type in ['programs', 'video', 'music', 'picture', 'files']: nodo_type = xmldoc.createElement(type) element_default = xmldoc.createElement("default") element_default.setAttribute("pathversion", "1") nodo_type.appendChild(element_default) nodo_sources.appendChild(nodo_type) xmldoc.appendChild(nodo_sources) # Buscamos el nodo video nodo_video = xmldoc.childNodes[0].getElementsByTagName("video")[0] # Buscamos el path dentro de los nodos_path incluidos en el nodo_video nodos_paths = nodo_video.getElementsByTagName("path") list_path = [p.firstChild.data for p in nodos_paths] logger.debug(list_path) if path in list_path: logger.debug("La ruta %s ya esta en sources.xml" % path) return logger.debug("La ruta %s NO esta en sources.xml" % path) # Si llegamos aqui es por q el path no esta en sources.xml, asi q lo incluimos nodo_source = xmldoc.createElement("source") # Nodo <name> nodo_name = xmldoc.createElement("name") sep = os.sep if path.startswith("special://") or path.startswith("smb://"): sep = "/" name = path if path.endswith(sep): name = path[:-1] nodo_name.appendChild(xmldoc.createTextNode(name.rsplit(sep)[-1])) nodo_source.appendChild(nodo_name) # Nodo <path> nodo_path = xmldoc.createElement("path") nodo_path.setAttribute("pathversion", "1") nodo_path.appendChild(xmldoc.createTextNode(path)) nodo_source.appendChild(nodo_path) # Nodo <allowsharing> nodo_allowsharing = xmldoc.createElement("allowsharing") nodo_allowsharing.appendChild(xmldoc.createTextNode('true')) nodo_source.appendChild(nodo_allowsharing) # Añadimos <source> a <video> nodo_video.appendChild(nodo_source) # Guardamos los cambios filetools.write(SOURCES_PATH, '\n'.join([x for x in xmldoc.toprettyxml().encode("utf-8").splitlines() if x.strip()]))
def listado_busqueda(item): logger.info() itemlist = [] data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") list_chars = [["ñ", "ñ"]] for el in list_chars: data = re.sub(r"%s" % el[0], el[1], data) try: get, post = scrapertools.find_single_match( data, '<ul class="pagination">.*?<a class="current" href.*?' '<a\s*href="([^"]+)"(?:\s*onClick=".*?\'([^"]+)\'.*?")') except: post = False if post: if "pg" in item.post: item.post = re.sub(r"pg=(\d+)", "pg=%s" % post, item.post) else: item.post += "&pg=%s" % post pattern = '<ul class="%s">(.*?)</ul>' % item.pattern data = scrapertools.get_match(data, pattern) pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2.*?>(?P<title>.*?)?<\/h2>' matches = re.compile(pattern, re.DOTALL).findall(data) for url, thumb, title in matches: real_title = scrapertools.find_single_match( title, r'<strong.*?>(.*?)Temporada.*?<\/strong>') #series if not real_title: real_title = scrapertools.find_single_match( title, r'(.*?)\[.*?]') #movies real_title = scrapertools.remove_htmltags(real_title).decode( 'iso-8859-1').encode('utf-8') real_title = scrapertools.htmlclean(real_title) real_title = real_title.replace("�", "ñ").replace("ñ", "ñ").replace( "Temp", " Temp").replace("Esp", " Esp").replace("Ing", " Ing").replace( "Eng", " Eng").replace("Calidad", "").replace("de la Serie", "") calidad = scrapertools.find_single_match( title, r'.*?\s*Calidad.*?<span[^>]+>[\[]\s*(?P<quality>.*?)\s*[\]]<\/span>' ) #series if calidad == "": calidad = scrapertools.find_single_match( title, r'..*?(\[.*?.*\])') #movies year = scrapertools.find_single_match(thumb, r'-(\d{4})') if not year or year <= "1900": year = '-' # fix encoding for title title = scrapertools.htmlclean(title) title = re.sub(r'(Calidad.*?\])', '', title) title = title.replace("�", "ñ").replace("ñ", "ñ").replace( "Temp", " Temp").replace("Esp", " Esp").replace("Ing", " Ing").replace( "Eng", " Eng").replace("Calidad", "").replace("de la Serie", "") if real_title == "": real_title = title if calidad == "": calidad = title context = "movie" url_real = True # no mostramos lo que no sean videos if "juego/" in url: continue # Codigo para rescatar lo que se puede 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 url or "-serie" in url) and "pelisyseries.com" in host: if "seriehd" in url: calidad_mps = "series-hd/" elif "serievo" in url: calidad_mps = "series-vo/" elif "serie-vo" in url: calidad_mps = "series-vo/" else: calidad_mps = "series/" if "no_image" in thumb: real_title_mps = title else: real_title_mps = re.sub(r'.*?\/\d+_', '', thumb) real_title_mps = re.sub(r'\.\w+.*?', '', real_title_mps) if "/0_" not in thumb and not "no_image" in thumb: serieid = scrapertools.find_single_match( thumb, 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_tvshow = host + calidad_mps + real_title_mps + "/" url_id = host + calidad_mps + real_title_mps + "/" + serieid data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).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" # item.pattern if not scrapertools.find_single_match(data_serie, pattern): data_serie = data = re.sub( r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).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): context = "movie" url_real = False if not config.get_setting( "unify" ): #Si Titulos Inteligentes NO seleccionados: if calidad: title = title + '[' + calidad + "]" else: url = url_tvshow else: url = url_id real_title_mps = real_title_mps.replace("-", " ") logger.debug("url: " + url + " / title: " + title + " / real_title: " + real_title + " / real_title_mps: " + real_title_mps + " / calidad_mps : " + calidad_mps + " / context : " + context) real_title = real_title_mps show = real_title if ".com/serie" in url and "/miniseries" not in url and url_real: if not config.get_setting( "unify"): #Si Titulos Inteligentes NO seleccionados: if calidad: title = title + '[' + calidad + "]" context = "tvshow" itemlist.append( Item(channel=item.channel, action="episodios", title=title, url=url, thumbnail=thumb, quality=calidad, show=show, extra="serie", context=["buscar_trailer"], contentType=context, contentTitle=real_title, contentSerieName=real_title, infoLabels={'year': year})) else: if config.get_setting( "unify"): #Si Titulos Inteligentes SI seleccionados: title = real_title itemlist.append( Item(channel=item.channel, action="findvideos", title=title, url=url, thumbnail=thumb, quality=calidad, show=show, context=["buscar_trailer"], contentType=context, contentTitle=real_title, infoLabels={'year': year})) logger.debug("url: " + url + " / title: " + title + " / real_title: " + real_title + " / show: " + show + " / calidad: " + calidad) tmdb.set_infoLabels(itemlist, True) if post: itemlist.append( item.clone(channel=item.channel, action="listado_busqueda", title=">> Página siguiente", text_color='yellow', text_bold=True, thumbnail=get_thumb("next.png"))) return itemlist
break if not path: path = filetools.join(TVSHOWS_PATH, ("%s [%s]" % (base_name, _id)).strip()) logger.info("Creando directorio serie: " + path) try: filetools.mkdir(path) except OSError, exception: if exception.errno != errno.EEXIST: raise tvshow_path = filetools.join(path, "tvshow.nfo") if not filetools.exists(tvshow_path): # Creamos tvshow.nfo, si no existe, con la head_nfo, info de la serie y marcas de episodios vistos logger.info("Creando tvshow.nfo: " + tvshow_path) head_nfo = scraper.get_nfo(item) item.infoLabels['mediatype'] = "tvshow" item.infoLabels['title'] = item.contentSerieName item_tvshow = Item(title=item.contentSerieName, channel="videolibrary", action="get_seasons", fanart=item.infoLabels['fanart'], thumbnail=item.infoLabels['thumbnail'], infoLabels=item.infoLabels, path=path.replace(TVSHOWS_PATH, "")) item_tvshow.library_playcounts = {} item_tvshow.library_urls = {item.channel: item.url} else: # Si existe tvshow.nfo, pero estamos añadiendo un nuevo canal actualizamos el listado de urls
def episodios(item): logger.info() itemlist = [] infoLabels = item.infoLabels data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") calidad = item.quality pattern = '<ul class="%s">(.*?)</ul>' % "pagination" # item.pattern pagination = scrapertools.find_single_match(data, pattern) if pagination: pattern = '<li><a href="([^"]+)">Last<\/a>' full_url = scrapertools.find_single_match(pagination, pattern) url, last_page = scrapertools.find_single_match( full_url, r'(.*?\/pg\/)(\d+)') list_pages = [item.url] for x in range(2, int(last_page) + 1): response = httptools.downloadpage('%s%s' % (url, x)) if response.sucess: list_pages.append("%s%s" % (url, x)) else: list_pages = [item.url] for index, page in enumerate(list_pages): data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).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 if scrapertools.find_single_match(data, pattern): data = scrapertools.get_match(data, pattern) else: logger.debug(item) logger.debug("data: " + data) return itemlist if "pelisyseries.com" in host: 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) #logger.debug("patron: " + pattern) #logger.debug(matches) season = "1" for url, thumb, info in matches: if "pelisyseries.com" in host: interm = url url = thumb thumb = interm 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) info = '><strong>%sTemporada %s Capitulo 0</strong> - <span >Español Castellano</span> Calidad <span >[%s]</span>' % ( item.contentTitle, season, item.infoLabels['quality']) r = re.compile(pattern) match = [m.groupdict() for m in r.finditer(info)][0] if match['season'] is None: match['season'] = season if match['episode'] is None: match['episode'] = "0" if match['quality']: item.quality = match['quality'] if match["episode2"]: multi = True title = "%s (%sx%s-%s) [%s]" % ( item.show, match["season"], str( match["episode"]).zfill(2), str( match["episode2"]).zfill(2), match["lang"]) if not config.get_setting("unify") and match[ "quality"]: #Si Titulos Inteligentes NO seleccionados: title = "%s[%s]" % (title, match["quality"]) else: multi = False title = "%s (%sx%s) [%s]" % ( item.show, match["season"], str( match["episode"]).zfill(2), match["lang"]) if not config.get_setting("unify") and match[ "quality"]: #Si Titulos Inteligentes NO seleccionados: title = "%s[%s]" % (title, match["quality"]) else: # old style if scrapertools.find_single_match(info, '\[\d{3}\]'): info = re.sub(r'\[(\d{3}\])', r'[Cap.\1', info) 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) 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>.*)?" 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) info = '%s [%s][Cap.%s00][Español]' % ( item.contentTitle, item.infoLabels['quality'], season) r = re.compile(pattern) match = [m.groupdict() for m in r.finditer(info)][0] str_lang = "" if match['quality']: item.quality = match['quality'] if match["lang"] is not None: str_lang = "[%s]" % match["lang"] item.quality = "%s %s" % (item.quality, match['lang']) if match["season2"] and match["episode2"]: multi = True if match["season"] == match["season2"]: title = "%s (%sx%s-%s) %s" % ( item.show, match["season"], match["episode"], match["episode2"], str_lang) if not config.get_setting("unify") and match[ "quality"]: #Si Titulos Inteligentes NO seleccionados: title = "%s[%s]" % (title, match["quality"]) else: title = "%s (%sx%s-%sx%s) %s" % ( item.show, match["season"], match["episode"], match["season2"], match["episode2"], str_lang) if not config.get_setting("unify") and match[ "quality"]: #Si Titulos Inteligentes NO seleccionados: title = "%s[%s]" % (title, match["quality"]) else: title = "%s (%sx%s) %s" % (item.show, match["season"], match["episode"], str_lang) if not config.get_setting("unify") and match[ "quality"]: #Si Titulos Inteligentes NO seleccionados: title = "%s[%s]" % (title, match["quality"]) multi = False season = match['season'] episode = match['episode'] logger.debug("title: " + title + " / url: " + url + " / calidad: " + item.quality + " / multi: " + str(multi) + " / Season: " + str(season) + " / EpisodeNumber: " + str(episode)) itemlist.append( Item(channel=item.channel, action="findvideos", title=title, url=url, thumbnail=thumb, quality=item.quality, multi=multi, contentSeason=season, contentEpisodeNumber=episode, infoLabels=infoLabels)) # order list #tmdb.set_infoLabels(itemlist, True) tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) if len(itemlist) > 1: itemlist = sorted( itemlist, key=lambda it: (int(it.contentSeason), int(it.contentEpisodeNumber))) if config.get_videolibrary_support() and len(itemlist) > 0: itemlist.append( item.clone(title="Añadir esta serie a la videoteca", action="add_serie_to_library", extra="episodios", quality=calidad)) return itemlist
def save_tvshow(item, episodelist): """ guarda en la libreria de series la serie con todos los capitulos incluidos en la lista episodelist @type item: item @param item: item que representa la serie a guardar @type episodelist: list @param episodelist: listado de items que representan los episodios que se van a guardar. @rtype insertados: int @return: el número de episodios insertados @rtype sobreescritos: int @return: el número de episodios sobreescritos @rtype fallidos: int @return: el número de episodios fallidos o -1 si ha fallado toda la serie @rtype path: str @return: directorio serie """ logger.info() # logger.debug(item.tostring('\n')) path = "" # Si llegados a este punto no tenemos titulo o code, salimos if not (item.contentSerieName or item.infoLabels['code']) or not item.channel: logger.debug("NO ENCONTRADO contentSerieName NI code") return 0, 0, -1, path # Salimos sin guardar scraper_return = scraper.find_and_set_infoLabels(item) # Llegados a este punto podemos tener: # scraper_return = True: Un item con infoLabels con la información actualizada de la serie # scraper_return = False: Un item sin información de la peli (se ha dado a cancelar en la ventana) # item.infoLabels['code'] == "" : No se ha encontrado el identificador de IMDB necesario para continuar, salimos if not scraper_return or not item.infoLabels['code']: # TODO de momento si no hay resultado no añadimos nada, # aunq podriamos abrir un cuadro para introducir el identificador/nombre a mano logger.debug("NO ENCONTRADO EN SCRAPER O NO TIENE code") return 0, 0, -1, path _id = item.infoLabels['code'][0] if config.get_setting( "original_title_folder", "videolibrary") == 1 and item.infoLabels['originaltitle']: base_name = item.infoLabels['originaltitle'] elif item.infoLabels['tvshowtitle']: base_name = item.infoLabels['tvshowtitle'] elif item.infoLabels['title']: base_name = item.infoLabels['title'] else: base_name = item.contentSerieName base_name = unicode(filetools.validate_path(base_name.replace('/', '-')), "utf8").encode("utf8") if config.get_setting("lowerize_title", "videolibrary") == 0: base_name = base_name.lower() for raiz, subcarpetas, ficheros in filetools.walk(TVSHOWS_PATH): for c in subcarpetas: code = scrapertools.find_single_match(c, '\[(.*?)\]') if code and code in item.infoLabels['code']: path = filetools.join(raiz, c) _id = code break if not path: path = filetools.join(TVSHOWS_PATH, ("%s [%s]" % (base_name, _id)).strip()) logger.info("Creando directorio serie: " + path) try: filetools.mkdir(path) except OSError, exception: if exception.errno != errno.EEXIST: raise
def peliculas(item): logger.info() itemlist = [] url_next_page = "" data = httptools.downloadpage(item.url).data data = re.sub(r"\n|\r|\t|\s{2}| ", "", data) patron = '<article class.*?' patron += '<a href="([^"]+)">.*?' patron += '<img src="([^"]+)".*?' patron += '<aside class="item-control down">(.*?)</aside>.*?' patron += '<small class="pull-right text-muted">([^<]+)</small>.*?' patron += '<h2 class.*?>([^<]+)</h2>' matches = re.compile(patron, re.DOTALL).findall(data) # Paginacion if item.next_page != 'b': if len(matches) > 30: url_next_page = item.url matches = matches[:30] next_page = 'b' else: matches = matches[30:] next_page = 'a' patron_next_page = 'Anteriores</a> <a href="([^"]+)" class="btn btn-default ".*?Siguiente' matches_next_page = re.compile(patron_next_page, re.DOTALL).findall(data) if len(matches_next_page) > 0: url_next_page = matches_next_page[0] for scrapedurl, scrapedthumbnail, idiomas, year, scrapedtitle in matches: patronidiomas = "<img src='([^']+)'" matchesidiomas = re.compile(patronidiomas, re.DOTALL).findall(idiomas) idiomas_disponibles = [] for idioma in matchesidiomas: if idioma.endswith("la_la.png"): idiomas_disponibles.append("LAT") elif idioma.endswith("en_en.png"): idiomas_disponibles.append("VO") elif idioma.endswith("en_es.png"): idiomas_disponibles.append("VOSE") elif idioma.endswith("es_es.png"): idiomas_disponibles.append("ESP") if idiomas_disponibles: idiomas_disponibles = "[" + "/".join(idiomas_disponibles) + "]" contentTitle = scrapertoolsV2.decodeHtmlentities(scrapedtitle.strip()) title = "%s %s" % (contentTitle, idiomas_disponibles) itemlist.append(Item(channel=item.channel, action="findvideos", title=title, url=scrapedurl, thumbnail=scrapedthumbnail, contentTitle=contentTitle, infoLabels={"year": year}, text_color=color1)) # Obtenemos los datos basicos de todas las peliculas mediante multihilos tmdb.set_infoLabels(itemlist) # Si es necesario añadir paginacion if url_next_page: itemlist.append( Item(channel=item.channel, action="peliculas", title=">> Página siguiente", thumbnail=thumbnail_host, url=url_next_page, next_page=next_page, folder=True, text_color=color3, text_bold=True)) return itemlist
def save_episodes(path, episodelist, serie, silent=False, overwrite=True): """ guarda en la ruta indicada todos los capitulos incluidos en la lista episodelist @type path: str @param path: ruta donde guardar los episodios @type episodelist: list @param episodelist: listado de items que representan los episodios que se van a guardar. @type serie: item @param serie: serie de la que se van a guardar los episodios @type silent: bool @param silent: establece si se muestra la notificación @param overwrite: permite sobreescribir los ficheros existentes @type overwrite: bool @rtype insertados: int @return: el número de episodios insertados @rtype sobreescritos: int @return: el número de episodios sobreescritos @rtype fallidos: int @return: el número de episodios fallidos """ logger.info() # No hay lista de episodios, no hay nada que guardar if not len(episodelist): logger.info("No hay lista de episodios, salimos sin crear strm") return 0, 0, 0 insertados = 0 sobreescritos = 0 fallidos = 0 news_in_playcounts = {} # Listamos todos los ficheros de la serie, asi evitamos tener que comprobar si existe uno por uno raiz, carpetas_series, ficheros = filetools.walk(path).next() ficheros = [filetools.join(path, f) for f in ficheros] nostrm_episodelist = [] for root, folders, files in filetools.walk(path): for file in files: season_episode = scrapertools.get_season_and_episode(file) if season_episode == "" or filetools.exists( filetools.join(path, "%s.strm" % season_episode)): continue nostrm_episodelist.append(season_episode) nostrm_episodelist = sorted(set(nostrm_episodelist)) # Silent es para no mostrar progreso (para videolibrary_service) if not silent: # progress dialog p_dialog = platformtools.dialog_progress( config.get_localized_string(20000), config.get_localized_string(60064)) p_dialog.update(0, config.get_localized_string(60065)) channel_alt = generictools.verify_channel( serie.channel) #Preparamos para añadir las urls de emergencia emergency_urls_stat = config.get_setting( "emergency_urls", channel_alt) #El canal quiere urls de emergencia? emergency_urls_succ = False try: channel = __import__('specials.%s' % channel_alt, fromlist=["specials.%s" % channel_alt]) except: channel = __import__('channels.%s' % channel_alt, fromlist=["channels.%s" % channel_alt]) if serie.torrent_caching_fail: #Si el proceso de conversión ha fallado, no se cachean emergency_urls_stat = 0 del serie.torrent_caching_fail new_episodelist = [] # Obtenemos el numero de temporada y episodio y descartamos los q no lo sean tags = [] if config.get_setting("enable_filter", "videolibrary"): tags = [ x.strip() for x in config.get_setting( "filters", "videolibrary").lower().split(",") ] for e in episodelist: if tags != [] and tags != None and any(tag in e.title.lower() for tag in tags): continue try: season_episode = scrapertools.get_season_and_episode(e.title) # Si se ha marcado la opción de url de emergencia, se añade ésta a cada episodio después de haber ejecutado Findvideos del canal if e.emergency_urls and isinstance(e.emergency_urls, dict): del e.emergency_urls #Borramos trazas anteriores json_path = filetools.join( path, ("%s [%s].json" % (season_episode, e.channel) ).lower()) #Path del .json del episodio if emergency_urls_stat == 1 and not e.emergency_urls and e.contentType == 'episode': #Guardamos urls de emergencia? if not silent: p_dialog.update(0, 'Cacheando enlaces y archivos .torrent...', e.title) #progress dialog if json_path in ficheros: #Si existe el .json sacamos de ahí las urls if overwrite: #pero solo si se se sobrescriben los .json json_epi = Item().fromjson( filetools.read(json_path)) #Leemos el .json if json_epi.emergency_urls: #si existen las urls de emergencia... e.emergency_urls = json_epi.emergency_urls #... las copiamos else: #y si no... e = emergency_urls(e, channel, json_path) #... las generamos else: e = emergency_urls( e, channel, json_path ) #Si el episodio no existe, generamos las urls if e.emergency_urls: #Si ya tenemos urls... emergency_urls_succ = True #... es un éxito y vamos a marcar el .nfo elif emergency_urls_stat == 2 and e.contentType == 'episode': #Borramos urls de emergencia? if e.emergency_urls: del e.emergency_urls emergency_urls_succ = True #... es un éxito y vamos a marcar el .nfo elif emergency_urls_stat == 3 and e.contentType == 'episode': #Actualizamos urls de emergencia? if not silent: p_dialog.update(0, 'Cacheando enlaces y archivos .torrent...', e.title) #progress dialog e = emergency_urls(e, channel, json_path) #generamos las urls if e.emergency_urls: #Si ya tenemos urls... emergency_urls_succ = True #... es un éxito y vamos a marcar el .nfo if not e.infoLabels["tmdb_id"] or ( serie.infoLabels["tmdb_id"] and e.infoLabels["tmdb_id"] != serie.infoLabels["tmdb_id"] ): #en series multicanal, prevalece el infolabels... e.infoLabels = serie.infoLabels #... del canal actual y no el del original e.contentSeason, e.contentEpisodeNumber = season_episode.split("x") new_episodelist.append(e) except: if e.contentType == 'episode': logger.error( "No se ha podido guardar las urls de emergencia de %s en la videoteca" % e.contentTitle) logger.error(traceback.format_exc()) continue # No hay lista de episodios, no hay nada que guardar if not len(new_episodelist): logger.info("No hay lista de episodios, salimos sin crear strm") return 0, 0, 0 # fix float porque la division se hace mal en python 2.x t = float(100) / len(new_episodelist) for i, e in enumerate(scraper.sort_episode_list(new_episodelist)): if not silent: p_dialog.update(int(math.ceil((i + 1) * t)), config.get_localized_string(60064), e.title) season_episode = "%sx%s" % (e.contentSeason, str( e.contentEpisodeNumber).zfill(2)) strm_path = filetools.join(path, "%s.strm" % season_episode) nfo_path = filetools.join(path, "%s.nfo" % season_episode) json_path = filetools.join(path, ("%s [%s].json" % (season_episode, e.channel)).lower()) if season_episode in nostrm_episodelist: continue strm_exists = strm_path in ficheros nfo_exists = nfo_path in ficheros json_exists = json_path in ficheros if not strm_exists: # Si no existe season_episode.strm añadirlo item_strm = Item(action='play_from_library', channel='videolibrary', strm_path=strm_path.replace(TVSHOWS_PATH, ""), infoLabels={}) item_strm.contentSeason = e.contentSeason item_strm.contentEpisodeNumber = e.contentEpisodeNumber item_strm.contentType = e.contentType item_strm.contentTitle = season_episode # FILTERTOOLS if item_strm.list_language: # si tvshow.nfo tiene filtro se le pasa al item_strm que se va a generar if "library_filter_show" in serie: item_strm.library_filter_show = serie.library_filter_show if item_strm.library_filter_show == "": logger.error( "Se ha producido un error al obtener el nombre de la serie a filtrar" ) # logger.debug("item_strm" + item_strm.tostring('\n')) # logger.debug("serie " + serie.tostring('\n')) strm_exists = filetools.write( strm_path, '%s?%s' % (addon_name, item_strm.tourl())) item_nfo = None if not nfo_exists and e.infoLabels["code"]: # Si no existe season_episode.nfo añadirlo scraper.find_and_set_infoLabels(e) head_nfo = scraper.get_nfo(e) item_nfo = e.clone(channel="videolibrary", url="", action='findvideos', strm_path=strm_path.replace(TVSHOWS_PATH, "")) if item_nfo.emergency_urls: del item_nfo.emergency_urls #Solo se mantiene en el .json del episodio nfo_exists = filetools.write(nfo_path, head_nfo + item_nfo.tojson()) # Solo si existen season_episode.nfo y season_episode.strm continuamos if nfo_exists and strm_exists: if not json_exists or overwrite: # Obtenemos infoLabel del episodio if not item_nfo: head_nfo, item_nfo = read_nfo(nfo_path) if not e.infoLabels["tmdb_id"] or ( item_nfo.infoLabels["tmdb_id"] and e.infoLabels["tmdb_id"] != item_nfo.infoLabels["tmdb_id"] ): #en series multicanal, prevalece el infolabels... e.infoLabels = item_nfo.infoLabels #... del canal actual y no el del original if filetools.write(json_path, e.tojson()): if not json_exists: logger.info("Insertado: %s" % json_path) insertados += 1 # Marcamos episodio como no visto news_in_playcounts[season_episode] = 0 # Marcamos la temporada como no vista news_in_playcounts["season %s" % e.contentSeason] = 0 # Marcamos la serie como no vista # logger.debug("serie " + serie.tostring('\n')) news_in_playcounts[serie.contentSerieName] = 0 else: logger.info("Sobreescrito: %s" % json_path) sobreescritos += 1 else: logger.info("Fallido: %s" % json_path) fallidos += 1 else: logger.info("Fallido: %s" % json_path) fallidos += 1 if not silent and p_dialog.iscanceled(): break if not silent: p_dialog.close() if news_in_playcounts: # Si hay nuevos episodios los marcamos como no vistos en tvshow.nfo ... tvshow_path = filetools.join(path, "tvshow.nfo") try: import datetime head_nfo, tvshow_item = read_nfo(tvshow_path) tvshow_item.library_playcounts.update(news_in_playcounts) #Si la operación de insertar/borrar urls de emergencia en los .jsons de los episodios ha tenido éxito, se marca el .nfo if emergency_urls_succ: if tvshow_item.emergency_urls and not isinstance( tvshow_item.emergency_urls, dict): del tvshow_item.emergency_urls if emergency_urls_stat in [ 1, 3 ]: #Operación de guardar/actualizar enlaces if not tvshow_item.emergency_urls: tvshow_item.emergency_urls = dict() tvshow_item.emergency_urls.update({serie.channel: True}) elif emergency_urls_stat == 2: #Operación de Borrar enlaces if tvshow_item.emergency_urls and tvshow_item.emergency_urls.get( serie.channel, False): tvshow_item.emergency_urls.pop( serie.channel, None) #borramos la entrada del .nfo if tvshow_item.active == 30: tvshow_item.active = 1 update_last = datetime.date.today() tvshow_item.update_last = update_last.strftime('%Y-%m-%d') update_next = datetime.date.today() + datetime.timedelta( days=int(tvshow_item.active)) tvshow_item.update_next = update_next.strftime('%Y-%m-%d') filetools.write(tvshow_path, head_nfo + tvshow_item.tojson()) except: logger.error("Error al actualizar tvshow.nfo") logger.error( "No se ha podido guardar las urls de emergencia de %s en la videoteca" % tvshow_item.contentSerieName) logger.error(traceback.format_exc()) fallidos = -1 else: # ... si ha sido correcto actualizamos la videoteca de Kodi if config.is_xbmc() and not silent: from platformcode import xbmc_videolibrary xbmc_videolibrary.update(FOLDER_TVSHOWS, filetools.basename(path)) if fallidos == len(episodelist): fallidos = -1 logger.debug("%s [%s]: insertados= %s, sobreescritos= %s, fallidos= %s" % (serie.contentSerieName, serie.channel, insertados, sobreescritos, fallidos)) return insertados, sobreescritos, fallidos
def mainlist(item): logger.info() autoplay.init(item.channel, list_servers, list_quality) itemlist = [] itemlist.append( Item(channel=item.channel, title="Nuevos Episodios", action="new_episodes", thumbnail=get_thumb('new_episodes', auto=True), url=host)) itemlist.append( Item(channel=item.channel, title="Ultimas", action="list_all", thumbnail=get_thumb('last', auto=True), url=host + 'emision')) itemlist.append( Item(channel=item.channel, title="Todas", action="list_all", thumbnail=get_thumb('all', auto=True), url=host + 'animes')) itemlist.append( Item(channel=item.channel, title="Anime", action="list_all", thumbnail=get_thumb('anime', auto=True), url=host + 'categoria/anime')) itemlist.append( Item(channel=item.channel, title="Películas", action="list_all", thumbnail=get_thumb('movies', auto=True), url=host + 'categoria/pelicula')) itemlist.append( Item(channel=item.channel, title="OVAs", action="list_all", thumbnail='', url=host + 'categoria/ova')) itemlist.append( Item(channel=item.channel, title="ONAs", action="list_all", thumbnail='', url=host + 'categoria/ona')) itemlist.append( Item(channel=item.channel, title="Especiales", action="list_all", thumbnail='', url=host + 'categoria/especial')) itemlist.append( Item(channel=item.channel, title="Buscar", action="search", url=host + 'search?q=', thumbnail=get_thumb('search', auto=True), fanart='https://s30.postimg.cc/pei7txpa9/buscar.png')) autoplay.show_option(item.channel, itemlist) itemlist = renumbertools.show_option(item.channel, itemlist) return itemlist
def save_movie(item): """ guarda en la libreria de peliculas el elemento item, con los valores que contiene. @type item: item @param item: elemento que se va a guardar. @rtype insertados: int @return: el número de elementos insertados @rtype sobreescritos: int @return: el número de elementos sobreescritos @rtype fallidos: int @return: el número de elementos fallidos o -1 si ha fallado todo """ logger.info() # logger.debug(item.tostring('\n')) insertados = 0 sobreescritos = 0 fallidos = 0 path = "" # Itentamos obtener el titulo correcto: # 1. contentTitle: Este deberia ser el sitio correcto, ya que title suele contener "Añadir a la videoteca..." # 2. fulltitle # 3. title if not item.contentTitle: # Colocamos el titulo correcto en su sitio para que scraper lo localize if item.fulltitle: item.contentTitle = item.fulltitle else: item.contentTitle = item.title # Si llegados a este punto no tenemos titulo, salimos if not item.contentTitle or not item.channel: logger.debug("NO ENCONTRADO contentTitle") return 0, 0, -1 # Salimos sin guardar scraper_return = scraper.find_and_set_infoLabels(item) # Llegados a este punto podemos tener: # scraper_return = True: Un item con infoLabels con la información actualizada de la peli # scraper_return = False: Un item sin información de la peli (se ha dado a cancelar en la ventana) # item.infoLabels['code'] == "" : No se ha encontrado el identificador de IMDB necesario para continuar, salimos if not scraper_return or not item.infoLabels['code']: # TODO de momento si no hay resultado no añadimos nada, # aunq podriamos abrir un cuadro para introducir el identificador/nombre a mano logger.debug("NO ENCONTRADO EN SCRAPER O NO TIENE code") return 0, 0, -1 _id = item.infoLabels['code'][0] # progress dialog p_dialog = platformtools.dialog_progress( config.get_localized_string(20000), config.get_localized_string(60062)) if config.get_setting( "original_title_folder", "videolibrary") == 1 and item.infoLabels['originaltitle']: base_name = item.infoLabels['originaltitle'] else: base_name = item.contentTitle base_name = unicode(filetools.validate_path(base_name.replace('/', '-')), "utf8").encode("utf8") if config.get_setting("lowerize_title", "videolibrary") == 0: base_name = base_name.lower() for raiz, subcarpetas, ficheros in filetools.walk(MOVIES_PATH): for c in subcarpetas: code = scrapertools.find_single_match(c, '\[(.*?)\]') if code and code in item.infoLabels['code']: path = filetools.join(raiz, c) _id = code break if not path: # Crear carpeta path = filetools.join(MOVIES_PATH, ("%s [%s]" % (base_name, _id)).strip()) logger.info("Creando directorio pelicula:" + path) if not filetools.mkdir(path): logger.debug("No se ha podido crear el directorio") return 0, 0, -1 nfo_path = filetools.join(path, "%s [%s].nfo" % (base_name, _id)) strm_path = filetools.join(path, "%s.strm" % base_name) json_path = filetools.join(path, ("%s [%s].json" % (base_name, item.channel.lower()))) nfo_exists = filetools.exists(nfo_path) strm_exists = filetools.exists(strm_path) json_exists = filetools.exists(json_path) if not nfo_exists: # Creamos .nfo si no existe logger.info("Creando .nfo: " + nfo_path) head_nfo = scraper.get_nfo(item) item_nfo = Item(title=item.contentTitle, channel="videolibrary", action='findvideos', library_playcounts={"%s [%s]" % (base_name, _id): 0}, infoLabels=item.infoLabels, library_urls={}) else: # Si existe .nfo, pero estamos añadiendo un nuevo canal lo abrimos head_nfo, item_nfo = read_nfo(nfo_path) if not strm_exists: # Crear base_name.strm si no existe item_strm = Item(channel='videolibrary', action='play_from_library', strm_path=strm_path.replace(MOVIES_PATH, ""), contentType='movie', contentTitle=item.contentTitle) strm_exists = filetools.write( strm_path, '%s?%s' % (addon_name, item_strm.tourl())) item_nfo.strm_path = strm_path.replace(MOVIES_PATH, "") # Solo si existen item_nfo y .strm continuamos if item_nfo and strm_exists: if json_exists: logger.info("El fichero existe. Se sobreescribe") sobreescritos += 1 else: insertados += 1 # Si se ha marcado la opción de url de emergencia, se añade ésta a la película después de haber ejecutado Findvideos del canal try: channel = generictools.verify_channel(item.channel) if config.get_setting("emergency_urls", channel) in [1, 3]: item = emergency_urls(item, None, json_path) if item_nfo.emergency_urls and not isinstance( item_nfo.emergency_urls, dict): del item_nfo.emergency_urls if not item_nfo.emergency_urls: item_nfo.emergency_urls = dict() item_nfo.emergency_urls.update({item.channel: True}) except: logger.error( "No se ha podido guardar las urls de emergencia de %s en la videoteca" % item.contentTitle) logger.error(traceback.format_exc()) if filetools.write(json_path, item.tojson()): p_dialog.update(100, 'Añadiendo película...', item.contentTitle) item_nfo.library_urls[item.channel] = item.url if filetools.write(nfo_path, head_nfo + item_nfo.tojson()): #logger.info("FOLDER_MOVIES : %s" % FOLDER_MOVIES) # actualizamos la videoteca de Kodi con la pelicula if config.is_xbmc(): from platformcode import xbmc_videolibrary xbmc_videolibrary.update(FOLDER_MOVIES, filetools.basename(path) + "/") p_dialog.close() return insertados, sobreescritos, fallidos # Si llegamos a este punto es por q algo ha fallado logger.error("No se ha podido guardar %s en la videoteca" % item.contentTitle) p_dialog.update(100, config.get_localized_string(60063), item.contentTitle) p_dialog.close() return 0, 0, -1
def printMatches(matches): i = 0 for match in matches: logger.info("%d %s" % (i, match)) i = i + 1
def add_tvshow(item, channel=None): """ Guarda contenido en la libreria de series. Este contenido puede ser uno de estos dos: - La serie con todos los capitulos incluidos en la lista episodelist. - Un solo capitulo descargado previamente en local. Para añadir episodios descargados en local, el item debe tener exclusivamente: - contentSerieName (o show): Titulo de la serie - contentTitle: titulo del episodio para extraer season_and_episode ("1x01 Piloto") - title: titulo a mostrar junto al listado de enlaces -findvideos- ("Reproducir video local") - infoLabels["tmdb_id"] o infoLabels["imdb_id"] - contentType != "movie" - channel = "downloads" - url : ruta local al video @type item: item @param item: item que representa la serie a guardar @type channel: modulo @param channel: canal desde el que se guardara la serie. Por defecto se importara item.from_channel o item.channel """ logger.info("show=#" + item.show + "#") if item.channel == "downloads": itemlist = [item.clone()] else: # Esta marca es porque el item tiene algo más aparte en el atributo "extra" item.action = item.extra if isinstance(item.extra, str) and "###" in item.extra: item.action = item.extra.split("###")[0] item.extra = item.extra.split("###")[1] if item.from_action: item.__dict__["action"] = item.__dict__.pop("from_action") if item.from_channel: item.__dict__["channel"] = item.__dict__.pop("from_channel") if not channel: try: #channel = __import__('channels.%s' % item.channel, fromlist=["channels.%s" % item.channel]) channel = __import__('specials.%s' % channel_alt, fromlist=["specials.%s" % channel_alt]) except ImportError: exec "import channels." + item.channel + " as channel" #Para desambiguar títulos, se provoca que TMDB pregunte por el título realmente deseado #El usuario puede seleccionar el título entre los ofrecidos en la primera pantalla #o puede cancelar e introducir un nuevo título en la segunda pantalla #Si lo hace en "Introducir otro nombre", TMDB buscará automáticamente el nuevo título #Si lo hace en "Completar Información", cambia parcialmente al nuevo título, pero no busca en TMDB. Hay que hacerlo #Si se cancela la segunda pantalla, la variable "scraper_return" estará en False. El usuario no quiere seguir item = generictools.update_title( item ) #Llamamos al método que actualiza el título con tmdb.find_and_set_infoLabels #if item.tmdb_stat: # del item.tmdb_stat #Limpiamos el status para que no se grabe en la Videoteca # Obtiene el listado de episodios itemlist = getattr(channel, item.action)(item) insertados, sobreescritos, fallidos, path = save_tvshow(item, itemlist) if not insertados and not sobreescritos and not fallidos: platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(60067)) logger.error( "La serie %s no se ha podido añadir a la videoteca. No se ha podido obtener ningun episodio" % item.show) elif fallidos == -1: platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(60068)) logger.error("La serie %s no se ha podido añadir a la videoteca" % item.show) elif fallidos > 0: platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(60069)) logger.error( "No se han podido añadir %s episodios de la serie %s a la videoteca" % (fallidos, item.show)) else: platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(60070)) logger.info( "Se han añadido %s episodios de la serie %s a la videoteca" % (insertados, item.show)) if config.is_xbmc(): if config.get_setting("sync_trakt_new_tvshow", "videolibrary"): import xbmc from platformcode import xbmc_videolibrary if config.get_setting("sync_trakt_new_tvshow_wait", "videolibrary"): # Comprobar que no se esta buscando contenido en la videoteca de Kodi while xbmc.getCondVisibility('Library.IsScanningVideo()'): xbmc.sleep(1000) # Se lanza la sincronizacion para la videoteca de Kodi xbmc_videolibrary.sync_trakt_kodi() # Se lanza la sincronización para la videoteca del addon xbmc_videolibrary.sync_trakt_addon(path)
def list_env(environment={}): if not environment: environment = get_environment() if environment['debug'] == 'False': logger.log_enable(True) logger.info('----------------------------------------------') logger.info('Variables de entorno Alfa: ' + environment['addon_version'] + ' Debug: ' + environment['debug']) logger.info("----------------------------------------------") logger.info('** OS Environ: %s' % os.environ) logger.info("----------------------------------------------") logger.info(environment['os_name'] + ' ' + environment['os_release'] + ' ' + environment['prod_model'] + ' ' + environment['machine'] + ' ' + environment['architecture'] + ' ' + environment['language']) logger.info('Kodi ' + environment['num_version'] + ', Vídeo: ' + environment['video_db'] + ', Python ' + environment['python_version']) if environment['cpu_usage']: logger.info('CPU: ' + environment['cpu_usage']) if environment['mem_total'] or environment['mem_free']: logger.info('Memoria: Total: ' + environment['mem_total'] + ' MB / Disp.: ' + environment['mem_free'] + ' MB / Buffers: ' + str(int(environment['kodi_buffer']) * 3) + ' MB / Buffermode: ' + environment['kodi_bmode'] + ' / Readfactor: ' + environment['kodi_rfactor']) logger.info('Userdata: ' + environment['userdata_path'] + ' - Libre: ' + environment['userdata_free'].replace('.', ',') + ' GB' + ' - Idioma: ' + environment['torrent_lang']) logger.info('Videoteca: Series/Epis: ' + environment['videolab_series'] + '/' + environment['videolab_episodios'] + ' - Pelis: ' + environment['videolab_pelis'] + ' - Upd: ' + environment['videolab_update'] + ' - Path: ' + environment['videolab_path_perm'] + ' - Libre: ' + environment['videolab_free'].replace('.', ',') + ' GB') if environment['torrent_list']: for x, cliente in enumerate(environment['torrent_list']): if x == 0: cliente_alt = cliente.copy() del cliente_alt['Torrent_opt'] logger.info('Torrent: Opt: %s, %s' % (str(cliente['Torrent_opt']), \ str(cliente_alt).replace('{', '').replace('}', '')\ .replace("'", '').replace('_', ' '))) elif x == 1 and environment['torrent_error']: logger.info('- ' + str(cliente).replace('{', '').replace('}', '')\ .replace("'", '').replace('_', ' ')) else: cliente_alt = cliente.copy() del cliente_alt['Plug_in'] del cliente_alt['Version'] cliente_alt['Libre'] = cliente_alt['Libre'].replace('.', ',') + ' GB' logger.info('- %s v.%s: %s' % (str(cliente['Plug_in']), str(cliente['Version']), \ str(cliente_alt).replace('{', '').replace('}', '').replace("'", '')\ .replace('\\\\', '\\'))) logger.info('Proxy: ' + environment['proxy_active']) logger.info('Assistant ver.: ' + environment['assistant_version'] + \ ' - Assistant UA: ' + environment['assistant_cf_ua'] + \ ' - Assistant path: ' + environment.get('assistant_path', '')) logger.info('TAMAÑO del LOG: ' + environment['log_size'].replace('.', ',') + ' MB') logger.info("----------------------------------------------") if environment['debug'] == 'False': logger.log_enable(False) return environment
def init(channel, list_servers, list_quality): ''' Comprueba la existencia de canal en el archivo de configuracion de Autoplay y si no existe lo añade. Es necesario llamar a esta funcion al entrar a cualquier canal que incluya la funcion Autoplay. :param channel: (str) id del canal :param list_servers: (list) lista inicial de servidores validos para el canal. No es necesario incluirlos todos, ya que la lista de servidores validos se ira actualizando dinamicamente. :param list_quality: (list) lista inicial de calidades validas para el canal. No es necesario incluirlas todas, ya que la lista de calidades validas se ira actualizando dinamicamente. :return: (bool) True si la inicializacion ha sido correcta. ''' logger.info() change = False result = True if not config.is_xbmc(): # platformtools.dialog_notification('AutoPlay ERROR', 'Sólo disponible para XBMC/Kodi') result = False else: autoplay_path = os.path.join(config.get_data_path(), "settings_channels", 'autoplay_data.json') if os.path.exists(autoplay_path): autoplay_node = jsontools.get_node_from_file('autoplay', "AUTOPLAY") else: change = True autoplay_node = {"AUTOPLAY": {}} if channel not in autoplay_node: change = True # Se comprueba que no haya calidades ni servidores duplicados if 'default' not in list_quality: list_quality.append('default') list_servers = list(set(list_servers)) list_quality = list(set(list_quality)) # Creamos el nodo del canal y lo añadimos channel_node = {"servers": list_servers, "quality": list_quality, "settings": { "active": False, "custom_servers": False, "custom_quality": False, "priority": 0}} for n in range(1, 4): s = c = 0 if len(list_servers) >= n: s = n - 1 if len(list_quality) >= n: c = n - 1 channel_node["settings"]["server_%s" % n] = s channel_node["settings"]["quality_%s" % n] = c autoplay_node[channel] = channel_node if change: result, json_data = jsontools.update_node(autoplay_node, 'autoplay', 'AUTOPLAY') if not result: heading = "Error al iniciar AutoPlay" msj = "Consulte su log para obtener mas información." icon = 1 platformtools.dialog_notification(heading, msj, icon, sound=False) return result