def download_from_best_server(item): logger.info("contentAction: %s | contentChannel: %s | url: %s" % (item.contentAction, item.contentChannel, item.url)) result = {"downloadStatus": STATUS_CODES.error} progreso = platformtools.dialog_progress( config.get_localized_string(30101), config.get_localized_string(70179)) channel = __import__('channels.%s' % item.contentChannel, None, None, ["channels.%s" % item.contentChannel]) progreso.update(50, config.get_localized_string(70184), config.get_localized_string(70180) % item.contentChannel) if hasattr(channel, item.contentAction): play_items = getattr(channel, item.contentAction)(item.clone( action=item.contentAction, channel=item.contentChannel)) else: play_items = servertools.find_video_items( item.clone(action=item.contentAction, channel=item.contentChannel)) play_items = [ x for x in play_items if x.action == "play" and not "trailer" in x.title.lower() ] progreso.update(100, config.get_localized_string(70183), config.get_localized_string(70181) % len(play_items), config.get_localized_string(70182)) if config.get_setting("server_reorder", "downloads") == 1: play_items.sort(key=sort_method) if progreso.iscanceled(): return {"downloadStatus": STATUS_CODES.canceled} progreso.close() # Recorremos el listado de servers, hasta encontrar uno que funcione for play_item in play_items: play_item = item.clone(**play_item.__dict__) play_item.contentAction = play_item.action play_item.infoLabels = item.infoLabels result = download_from_server(play_item) if progreso.iscanceled(): result["downloadStatus"] = STATUS_CODES.canceled # Tanto si se cancela la descarga como si se completa dejamos de probar mas opciones if result["downloadStatus"] in [ STATUS_CODES.canceled, STATUS_CODES.completed ]: result["downloadServer"] = { "url": play_item.url, "server": play_item.server } break return result
def cb_servers_favorites(server_names, dict_values): dict_name = {} progreso = platformtools.dialog_progress( config.get_localized_string(60557), config.get_localized_string(60558)) for i, v in list(dict_values.items()): if i == "favorites_servers": config.set_setting("favorites_servers", v) elif int(v) > 0: dict_name[server_names[v]] = int(i) servers_list = list(servertools.get_servers_list().items()) n = len(servers_list) i = 1 for server, server_parameters in servers_list: if server_parameters['name'] in list(dict_name.keys()): config.set_setting("favorites_servers_list", dict_name[server_parameters['name']], server=server) else: config.set_setting("favorites_servers_list", 0, server=server) progreso.update( old_div((i * 100), n), config.get_localized_string(60559) % server_parameters['name']) i += 1 if not dict_name: # Si no hay ningun servidor en lalista desactivarla config.set_setting("favorites_servers", False) progreso.close()
def downloadfileGzipped(url, pathfichero): logger.info("url=" + url) nombrefichero = pathfichero logger.info("filename=" + nombrefichero) import xbmc nombrefichero = xbmc.makeLegalFilename(nombrefichero) logger.info("filename=" + nombrefichero) patron = "(http://[^/]+)/.+" matches = re.compile(patron, re.DOTALL).findall(url) if len(matches): logger.info("Main URL: " + matches[0]) url1 = matches[0] else: url1 = url txheaders = { 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; ' 'Media Center PC 5.0; .NET CLR 3.0.04506)', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'es-es,es;q=0.8,en-us;q=0.5,en;q=0.3', 'Accept-Encoding': 'gzip,deflate', 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'Keep-Alive': '115', 'Connection': 'keep-alive', 'Referer': url1, } txdata = "" # Crea el diálogo de progreso from platformcode import platformtools progreso = platformtools.dialog_progress("addon", config.get_localized_string(60200), url.split("|")[0], nombrefichero) # Timeout del socket a 60 segundos socket.setdefaulttimeout(10) h = urllib2.HTTPHandler(debuglevel=0) request = urllib2.Request(url, txdata, txheaders) # if existSize > 0: # request.add_header('Range', 'bytes=%d-' % (existSize, )) opener = urllib2.build_opener(h) urllib2.install_opener(opener) try: connexion = opener.open(request) except urllib2.HTTPError, e: logger.error("error %d (%s) al abrir la url %s" % (e.code, e.msg, url)) # print e.code # print e.msg # print e.hdrs # print e.fp progreso.close() # El error 416 es que el rango pedido es mayor que el fichero => es que ya está completo if e.code == 416: return 0 else: return -2
def save_download_tvshow(item): logger.info("contentAction: %s | contentChannel: %s | contentType: %s | contentSerieName: %s" % (item.contentAction, item.contentChannel, item.contentType, item.contentSerieName)) progreso = platformtools.dialog_progress("Descargas", "Obteniendo datos de la serie") tmdb.find_and_set_infoLabels_tmdb(item) item.downloadFilename = item.downloadFilename = "%s [%s]" % (item.contentSerieName, item.contentChannel) progreso.update(0, "Obteniendo episodios...", "conectando con %s..." % item.contentChannel) episodes = get_episodes(item) progreso.update(0, "Añadiendo capitulos...", " ") for x, i in enumerate(episodes): progreso.update(x * 100 / len(episodes), "%dx%0.2d: %s" % (i.contentSeason, i.contentEpisodeNumber, i.contentTitle)) write_json(i) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), "¿Iniciar la descarga ahora?"): platformtools.dialog_ok(config.get_localized_string(30101), str(len(episodes)) + " capitulos de: " + item.contentSerieName, config.get_localized_string(30109)) else: for i in episodes: res = start_download(i) if res == STATUS_CODES.canceled: break
def select_server(item): logger.info( "contentAction: %s | contentChannel: %s | url: %s" % (item.contentAction, item.contentChannel, item.url)) progreso = platformtools.dialog_progress(config.get_localized_string(30101), config.get_localized_string(70179)) channel = __import__('channels.%s' % item.contentChannel, None, None, ["channels.%s" % item.contentChannel]) progreso.update(50, config.get_localized_string(70184), config.get_localized_string(70180) % item.contentChannel) if hasattr(channel, item.contentAction): play_items = getattr(channel, item.contentAction)( item.clone(action=item.contentAction, channel=item.contentChannel)) else: play_items = servertools.find_video_items(item.clone(action=item.contentAction, channel=item.contentChannel)) play_items = filter(lambda x: x.action == "play" and not "trailer" in x.title.lower(), play_items) progreso.update(100, config.get_localized_string(70183), config.get_localized_string(70181) % len(play_items), config.get_localized_string(70182)) for x, i in enumerate(play_items): if not i.server and hasattr(channel, "play"): play_items[x] = getattr(channel, "play")(i) seleccion = platformtools.dialog_select(config.get_localized_string(70192), ["Auto"] + [s.title for s in play_items]) if seleccion > 1: update_json(item.path, { "downloadServer": {"url": play_items[seleccion - 1].url, "server": play_items[seleccion - 1].server}}) elif seleccion == 0: update_json(item.path, {"downloadServer": {}}) platformtools.itemlist_refresh()
def select_server(item): logger.info("contentAction: %s | contentChannel: %s | url: %s" % (item.contentAction, item.contentChannel, item.url)) progreso = platformtools.dialog_progress("Descargas", "Obteniendo lista de servidores disponibles...") channel = __import__('channels.%s' % item.contentChannel, None, None, ["channels.%s" % item.contentChannel]) progreso.update(50, "Obteniendo lista de servidores disponibles:", "Conectando con %s..." % item.contentChannel) if hasattr(channel, item.contentAction): play_items = getattr(channel, item.contentAction)(item.clone(action = item.contentAction, channel = item.contentChannel)) else: play_items = servertools.find_video_items(item.clone(action = item.contentAction, channel = item.contentChannel)) play_items = filter(lambda x: x.action == "play" and not "trailer" in x.title.lower(), play_items) progreso.update(100, "Obteniendo lista de servidores disponibles", "Servidores disponibles: %s" % len(play_items), "Identificando servidores...") for x, i in enumerate(play_items): if not i.server and hasattr(channel, "play"): play_items[x] = getattr(channel,"play")(i) seleccion = platformtools.dialog_select("Selecciona el servidor", ["Auto"] + [s.title for s in play_items]) if seleccion > 1: update_json(item.path, {"downloadServer": {"url": play_items[seleccion -1].url, "server": play_items[seleccion -1].server}}) elif seleccion == 0: update_json(item.path, {"downloadServer": {}}) platformtools.itemlist_refresh()
def testear_lista_proxies(url, proxies=[]): threads = [] proxies_info = {} # resultados de los tests num_proxies = float(len(proxies)) # float para calcular porcentaje progreso = platformtools.dialog_progress('Testeando proxies', '%d proxies a comprobar. Cancelar si tarda demasiado.' % num_proxies) for proxy in proxies: if proxy in proxies_info: continue # por si hay repetidos proxies_info[proxy] = {'ok': False, 'time': 0, 'len': 0, 'code': ''} t = Thread(target=do_test_proxy, args=[url, proxy, proxies_info[proxy]]) t.setDaemon(True) t.start() threads.append(t) if progreso.iscanceled(): break pendent = [a for a in threads if a.isAlive()] while len(pendent) > 0: hechos = num_proxies - len(pendent) perc = int(hechos / num_proxies * 100) validos = sum([1 for proxy in proxies if proxies_info[proxy]['ok']]) progreso.update(perc, 'Finalizado en %d de %d proxies. Válidos %d. Cancelar si tarda demasiado o ya hay varios válidos.' % (hechos, num_proxies, validos)) if progreso.iscanceled(): break time.sleep(0.5) pendent = [a for a in threads if a.isAlive()] progreso.close() # Ordenar según proxy válido y tiempo de respuesta return sorted(proxies_info.items(), key=lambda x: (-x[1]['ok'], x[1]['time']))
def cb_servers_favorites(server_names, dict_values): dict_name = {} progreso = platformtools.dialog_progress("Salvataggio impostazioni...", "Aspetta un attimo per favore.") for i, v in dict_values.items(): if i == "favorites_servers": config.set_setting("favorites_servers", v) elif int(v) > 0: dict_name[server_names[v]] = int(i) servers_list = servertools.get_servers_list().items() n = len(servers_list) i = 1 for server, server_parameters in servers_list: if server_parameters['name'] in dict_name.keys(): config.set_setting("favorites_servers_list", dict_name[server_parameters['name']], server=server) else: config.set_setting("favorites_servers_list", 100, server=server) progreso.update( (i * 100) / n, "Salvataggio impostazioni...%s" % server_parameters['name']) i += 1 if not dict_name: #Si no hay ningun servidor en lalista desactivarla config.set_setting("favorites_servers", False) progreso.close()
def save_download_movie(item): logger.info("contentAction: %s | contentChannel: %s | contentTitle: %s" % (item.contentAction, item.contentChannel, item.contentTitle)) progreso = platformtools.dialog_progress( config.get_localized_string(30101), config.get_localized_string(70191)) set_movie_title(item) result = scraper.find_and_set_infoLabels(item) if not result: progreso.close() return save_download_video(item) progreso.update(0, config.get_localized_string(60062)) item.downloadFilename = filetools.validate_path( "%s [%s]" % (item.contentTitle.strip(), item.contentChannel)) write_json(item) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), config.get_localized_string(70189)): platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle, config.get_localized_string(30109)) else: start_download(item)
def save_download_movie(item): logger.info("contentAction: %s | contentChannel: %s | contentTitle: %s" % (item.contentAction, item.contentChannel, item.contentTitle)) progreso = platformtools.dialog_progress( "Descargas", "Obteniendo datos de la pelicula") result = scraper.find_and_set_infoLabels(item) if not result: progreso.close() item.contentType = "video" return save_download_video(item) progreso.update(0, "Añadiendo pelicula...") item.downloadFilename = filetools.validate_path( "%s [%s]" % (item.contentTitle.strip(), item.contentChannel)) write_json(item) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), "¿Iniciar la descarga ahora?"): platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle, config.get_localized_string(30109)) else: start_download(item)
def copy(path, dest, silent = False): """ Copia un archivo @param path: ruta del fichero a copiar @type path: str @param dest: ruta donde copiar @type dest: str @rtype: bool @return: devuelve False en caso de error """ import time try: fo = file_open(path, "rb") fd = file_open(dest, "wb") if fo and fd: if not silent: dialogo = platformtools.dialog_progress("Copiando archivo", "") size = getsize(path) copiado = 0 while True: if not silent: dialogo.update(copiado * 100 / size, basename(path)) buf=fo.read(1024*1024) if not buf: break if not silent and dialogo.iscanceled(): dialogo.close() return False fd.write(buf) copiado +=len(buf) if not silent: dialogo.close() except: logger.error("ERROR al copiar el archivo: %s" %(path)) logger.error(traceback.format_exc()) return False else: return True
def save_download_movie(item): logger.info("pelisalacarta.channels.descargas save_download_movie") progreso = platformtools.dialog_progress( "Descargas", "Obteniendo datos de la pelicula") tmdb.find_and_set_infoLabels_tmdb(item) progreso.update(0, "Añadiendo pelicula...") item.action = "menu" item.channel = "descargas" item.downloadStatus = 0 item.downloadProgress = 0 item.downloadSize = 0 item.downloadCompleted = 0 item.downloadFilename = "%s [%s]" % (item.contentTitle.strip(), item.contentChannel) if item.text_color: del item.text_color if item.text_bold: del item.text_bold if item.text_italic: del item.text_italic item.path = filetools.encode( os.path.join(config.get_setting("downloadlistpath"), str(time.time()) + ".json")) filetools.write(item.path, item.tojson()) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), "¿Iniciar la descarga ahora?"): platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle, config.get_localized_string(30109)) else: start_download(item)
def save_download_movie(item): logger.info("pelisalacarta.channels.descargas save_download_movie") progreso = platformtools.dialog_progress("Descargas", "Obteniendo datos de la pelicula") tmdb.find_and_set_infoLabels_tmdb(item) progreso.update(0, "Añadiendo pelicula...") item.action = "menu" item.channel = "descargas" item.downloadStatus = 0 item.downloadProgress = 0 item.downloadSize = 0 item.downloadCompleted = 0 item.downloadFilename = "%s [%s]" % (item.contentTitle.strip(), item.contentChannel) if item.text_color: del item.text_color if item.text_bold: del item.text_bold if item.text_italic: del item.text_italic item.path = filetools.encode(os.path.join(config.get_setting("downloadlistpath"), str(time.time()) + ".json")) filetools.write(item.path, item.tojson()) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), "¿Iniciar la descarga ahora?"): platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle, config.get_localized_string(30109)) else: start_download(item)
def save_download_tvshow(item): logger.info("contentAction: %s | contentChannel: %s | contentType: %s | contentSerieName: %s" % (item.contentAction, item.contentChannel, item.contentType, item.contentSerieName)) progreso = platformtools.dialog_progress("Descargas", "Obteniendo datos de la serie") scraper.find_and_set_infoLabels(item) item.downloadFilename = filetools.validate_path("%s [%s]" % (item.contentSerieName, item.contentChannel)) progreso.update(0, "Obteniendo episodios...", "conectando con %s..." % item.contentChannel) episodes = get_episodes(item) progreso.update(0, "Añadiendo capitulos...", " ") for x, i in enumerate(episodes): progreso.update(x * 100 / len(episodes), "%dx%0.2d: %s" % (i.contentSeason, i.contentEpisodeNumber, i.contentTitle)) write_json(i) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), "¿Iniciar la descarga ahora?"): platformtools.dialog_ok(config.get_localized_string(30101), str(len(episodes)) + " capitulos de: " + item.contentSerieName, config.get_localized_string(30109)) else: for i in episodes: res = start_download(i) if res == STATUS_CODES.canceled: break
def save_download_movie(item): logger.info("contentAction: %s | contentChannel: %s | contentTitle: %s" % (item.contentAction, item.contentChannel, item.contentTitle)) progreso = platformtools.dialog_progress("Download", "Info sui contenuti film") set_movie_title(item) result = scraper.find_and_set_infoLabels(item) if not result: progreso.close() return save_download_video(item) progreso.update(0, "Aggiunta item...") item.downloadFilename = filetools.validate_path( "%s [%s]" % (item.contentTitle.strip(), item.contentChannel)) write_json(item) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), "Iniziare il download adesso?"): platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle, config.get_localized_string(30109)) else: start_download(item)
def save_download_tvshow(item): logger.info("contentAction: %s | contentChannel: %s | contentType: %s | contentSerieName: %s" % ( item.contentAction, item.contentChannel, item.contentType, item.contentSerieName)) progreso = platformtools.dialog_progress("Download", "Recupero della serie") scraper.find_and_set_infoLabels(item) item.downloadFilename = filetools.validate_path("%s [%s]" % (item.contentSerieName, item.contentChannel)) progreso.update(0, "Recupero episodi...", "connessione a %s..." % item.contentChannel) episodes = get_episodes(item) progreso.update(0, "Aggiunta capitoli...", " ") for x, i in enumerate(episodes): progreso.update(x * 100 / len(episodes), "%dx%0.2d: %s" % (i.contentSeason, i.contentEpisodeNumber, i.contentTitle)) write_json(i) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), "Avviare il download adesso?"): platformtools.dialog_ok(config.get_localized_string(30101), str(len(episodes)) + " capitoli di: " + item.contentSerieName, config.get_localized_string(30109)) else: for i in episodes: res = start_download(i) if res == STATUS_CODES.canceled: break
def save_download_video(item): logger.info("contentAction: %s | contentChannel: %s | contentTitle: %s" % (item.contentAction, item.contentChannel, item.contentTitle)) progreso = platformtools.dialog_progress("Descargas", "Añadiendo video...") if not item.contentTitle: item.contentTitle = re.sub("\[[^\]]+\]|\([^\)]+\)", "", item.fulltitle).strip() if not item.contentTitle: item.contentTitle = re.sub("\[[^\]]+\]|\([^\)]+\)", "", item.title).strip() item.downloadFilename = filetools.validate_path( "%s [%s]" % (item.contentTitle.strip(), item.contentChannel)) write_json(item) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), "¿Iniciar la descarga ahora?"): platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle, config.get_localized_string(30109)) else: start_download(item)
def save_download_movie(item): logger.info("contentAction: %s | contentChannel: %s | contentTitle: %s" % ( item.contentAction, item.contentChannel, item.contentTitle)) progreso = platformtools.dialog_progress("Download", "Recupero del film") result = scraper.find_and_set_infoLabels(item) if not result: progreso.close() item.contentType = "video" return save_download_video(item) progreso.update(0, "Aggiunta del film...") item.downloadFilename = filetools.validate_path("%s [%s]" % (item.contentTitle.strip(), item.contentChannel)) write_json(item) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), "Avviare il download adesso?"): platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle, config.get_localized_string(30109)) else: start_download(item)
def download_from_best_server(item, ask=False): logger.info( "contentAction: %s | contentChannel: %s | url: %s" % (item.contentAction, item.contentChannel, item.url)) result = {"downloadStatus": STATUS_CODES.error} progreso = platformtools.dialog_progress("Download", "Recupero l'elenco dei server disponibili...") channel = __import__('channels.%s' % item.contentChannel, None, None, ["channels.%s" % item.contentChannel]) progreso.update(50, "Recupero l'elenco dei server disponibili.", "Connessione a %s..." % item.contentChannel) if hasattr(channel, item.contentAction): play_items = getattr(channel, item.contentAction)( item.clone(action=item.contentAction, channel=item.contentChannel)) else: play_items = servertools.find_video_items(item.clone(action=item.contentAction, channel=item.contentChannel)) play_items = filter(lambda x: x.action == "play", play_items) progreso.update(100, "Recupero l'elenco dei server disponibili.", "Server disponibili: %s" % len(play_items), "Identifico i server...") for i in play_items: if not i.server: i.server = servertools.get_server_from_url(i.url) if progreso.iscanceled(): return {"downloadStatus": STATUS_CODES.canceled} play_items.sort(key=sort_method) if progreso.iscanceled(): return {"downloadStatus": STATUS_CODES.canceled} progreso.close() if not ask: # Recorremos el listado de servers, hasta encontrar uno que funcione for play_item in play_items: play_item = item.clone(**play_item.__dict__) play_item.contentAction = play_item.action play_item.infoLabels = item.infoLabels result = download_from_server(play_item) if progreso.iscanceled(): result["downloadStatus"] = STATUS_CODES.canceled # Tanto si se cancela la descarga como si se completa dejamos de probar mas opciones if result["downloadStatus"] in [STATUS_CODES.canceled, STATUS_CODES.completed]: break else: seleccion = platformtools.dialog_select("Selezionare il server", [s.title for s in play_items]) if seleccion > -1: play_item = item.clone(**play_items[seleccion].__dict__) play_item.contentAction = play_item.action play_item.infoLabels = item.infoLabels result = download_from_server(play_item) else: result["downloadStatus"] = STATUS_CODES.canceled return result
def cb_servers_favorites(server_names, dict_values): dict_name = {} progreso = platformtools.dialog_progress("Guardando configuración...", "Espere un momento por favor.") for i, v in dict_values.items(): if i == "favorites_servers": config.set_setting("favorites_servers", v) elif int(v) > 0: dict_name[server_names[v]] = int(i) servers_list = servertools.get_servers_list().items() n = len(servers_list) i = 1 for server, server_parameters in servers_list: if server_parameters['name'] in dict_name.keys(): config.set_setting("favorites_servers_list", dict_name[server_parameters['name']], server=server) else: config.set_setting("favorites_servers_list", 0, server=server) progreso.update((i * 100) / n, "Guardando configuración...%s" % server_parameters['name']) i += 1 if not dict_name: #Si no hay ningun servidor en lalista desactivarla config.set_setting("favorites_servers", False) progreso.close()
def save_download_tvshow(item): logger.info("pelisalacarta.channels.descargas save_download_tvshow") logger.info("Tipo: %s" % item.contentType) progreso = platformtools.dialog_progress("Descargas", "Obteniendo datos de la serie") tmdb.find_and_set_infoLabels_tmdb(item) item.downloadFilename = item.downloadFilename = "%s [%s]" % (item.contentSerieName, item.contentChannel) episodes = get_episodes(item) progreso.update(0, "Añadiendo capitulos...") for x, i in enumerate(episodes): progreso.update(x * 100 / len(episodes), os.path.basename(i.downloadFilename)) i.path = os.path.join(config.get_setting("downloadlistpath"), str(time.time()) + ".json") filetools.write(i.path, i.tojson()) time.sleep(0.1) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), "¿Iniciar la descarga ahora?"): platformtools.dialog_ok(config.get_localized_string(30101), str(len(episodes)) + " capitulos de: " + item.contentSerieName, config.get_localized_string(30109)) else: for i in episodes: res = start_download(i) if res == 1: break
def copy(path, dest, silent=False, vfs=True): """ Copy a file @param path: path of the file to copy @type path: str @param dest: path to copy @type dest: str @param silent: the dialog box is displayed or not @type silent: bool @rtype: bool @return: returns False on error """ try: if xbmc_vfs and vfs: path = encode(path) dest = encode(dest) if not silent: dialogo = platformtools.dialog_progress("Copying file", "") return bool(xbmcvfs.copy(path, dest)) fo = file_open(path, "rb") fd = file_open(dest, "wb") if fo and fd: if not silent: dialogo = platformtools.dialog_progress("Copying file", "") size = getsize(path) copiado = 0 while True: if not silent: dialogo.update(old_div(copiado * 100, size), basename(path)) buf = fo.read(1024 * 1024) if not buf: break if not silent and dialogo.iscanceled(): dialogo.close() return False fd.write(buf) copiado += len(buf) if not silent: dialogo.close() except: logger.error("ERROR when copying the file: %s" % path) if not silent: logger.error(traceback.format_exc()) return False else: return True
def copy(path, dest, silent=False, vfs=True): """ Copia un archivo @param path: ruta del fichero a copiar @type path: str @param dest: ruta donde copiar @type dest: str @param silent: se muestra o no el cuadro de dialogo @type silent: bool @rtype: bool @return: devuelve False en caso de error """ try: if xbmc_vfs and vfs: path = encode(path) dest = encode(dest) if not silent: dialogo = platformtools.dialog_progress("Copiando archivo", "") return bool(xbmcvfs.copy(path, dest)) fo = file_open(path, "rb") fd = file_open(dest, "wb") if fo and fd: if not silent: dialogo = platformtools.dialog_progress("Copiando archivo", "") size = getsize(path) copiado = 0 while True: if not silent: dialogo.update(old_div(copiado * 100, size), basename(path)) buf = fo.read(1024 * 1024) if not buf: break if not silent and dialogo.iscanceled(): dialogo.close() return False fd.write(buf) copiado += len(buf) if not silent: dialogo.close() except: logger.error("ERROR al copiar el archivo: %s" % path) if not silent: logger.error(traceback.format_exc()) return False else: return True
def download_from_best_server(item): logger.info("contentAction: %s | contentChannel: %s | url: %s" % (item.contentAction, item.contentChannel, item.url)) result = {"downloadStatus": STATUS_CODES.error} progreso = platformtools.dialog_progress( "Download", "Lista dei server disponibili...") channel = __import__('channels.%s' % item.contentChannel, None, None, ["channels.%s" % item.contentChannel]) progreso.update(50, "Lista dei server disponibili.", "Connessione a %s..." % item.contentChannel) if hasattr(channel, item.contentAction): play_items = getattr(channel, item.contentAction)(item.clone( action=item.contentAction, channel=item.contentChannel)) else: play_items = servertools.find_video_items( item.clone(action=item.contentAction, channel=item.contentChannel)) play_items = filter( lambda x: x.action == "play" and not "trailer" in x.title.lower(), play_items) progreso.update(100, "Lista dei server disponibili.", "Server disponibili: %s" % len(play_items), "Sto identificando i server...") if config.get_setting("server_reorder", "descargas") == 1: play_items.sort(key=sort_method) if progreso.iscanceled(): return {"downloadStatus": STATUS_CODES.canceled} progreso.close() # Recorremos el listado de servers, hasta encontrar uno que funcione for play_item in play_items: play_item = item.clone(**play_item.__dict__) play_item.contentAction = play_item.action play_item.infoLabels = item.infoLabels result = download_from_server(play_item) if progreso.iscanceled(): result["downloadStatus"] = STATUS_CODES.canceled # Tanto si se cancela la descarga como si se completa dejamos de probar mas opciones if result["downloadStatus"] in [ STATUS_CODES.canceled, STATUS_CODES.completed ]: result["downloadServer"] = { "url": play_item.url, "server": play_item.server } break return result
def save_settings(item, dict_values): progreso = platformtools.dialog_progress(config.get_localized_string(59988), config.get_localized_string(59989)) n = len(dict_values) for i, v in enumerate(dict_values): progreso.update((i * 100) / n, config.get_localized_string(59988)) config.set_setting("include_in_global_search", dict_values[v], v) progreso.close()
def save_settings(item, dict_values): progreso = platformtools.dialog_progress("Guardando configuración...", "Espere un momento por favor.") n = len(dict_values) for i, v in enumerate(dict_values): progreso.update((i * 100) / n, "Guardando configuración...") config.set_setting("include_in_global_search", dict_values[v], v) progreso.close()
def search_links_abando(item): logger.info("streamondemand.channels.trailertools search_links_abando") data = scrapertools.downloadpage(item.url) itemlist = [] if "Lo sentimos, no tenemos trailer" in data: itemlist.append(item.clone(title="Nessun video disponibile", action="", text_color="")) else: if item.contextual: progreso = platformtools.dialog_progress("Cercando su abandomoviez", "Caricando i trailer...") progreso.update(10) i = 0 message = "Caricando i trailer..." patron = '<div class="col-md-3 col-xs-6"><a href="([^"]+)".*?' \ 'Images/(\d+).gif.*?</div><small>(.*?)</small>' matches = scrapertools.find_multiple_matches(data, patron) if len(matches) == 0: trailer_url = scrapertools.find_single_match(data, '<iframe.*?src="([^"]+)"') if trailer_url != "": trailer_url = trailer_url.replace("embed/", "watch?v=") code = scrapertools.find_single_match(trailer_url, 'v=([A-z0-9\-_]+)') thumbnail = "https://img.youtube.com/vi/%s/0.jpg" % code itemlist.append(item.clone(title="Trailer [youtube]", url=trailer_url, server="youtube", thumbnail=thumbnail, action="play", text_color="white")) else: for scrapedurl, language, scrapedtitle in matches: if language == "1": idioma = " (ESP)" else: idioma = " (V.O)" scrapedurl = urlparse.urljoin("http://www.abandomoviez.net/%s" % item.prefix, scrapedurl) scrapedtitle = scrapertools.htmlclean(scrapedtitle) + idioma + " [youtube]" if item.contextual: i += 1 message += ".." progreso.update(10 + (90*i/len(matches)), message) scrapedtitle = "[COLOR white]%s[/COLOR]" % scrapedtitle data_trailer = scrapertools.downloadpage(scrapedurl) trailer_url = scrapertools.find_single_match(data_trailer, 'iframe.*?src="([^"]+)"') trailer_url = trailer_url.replace("embed/", "watch?v=") code = scrapertools.find_single_match(trailer_url, 'v=([A-z0-9\-_]+)') thumbnail = "https://img.youtube.com/vi/%s/0.jpg" % code itemlist.append(item.clone(title=scrapedtitle, url=trailer_url, server="youtube", action="play", thumbnail=thumbnail, text_color="white")) if item.contextual: progreso.close() if keyboard: if item.contextual: title = "[COLOR green]%s[/COLOR]" else: title = "%s" itemlist.append(item.clone(title=title % "Ricerca manuale su Abandomoviez", action="manual_search", thumbnail="", text_color="green", extra="abandomoviez")) return itemlist
def search_links_abando(item): logger.info() data = scrapertools.downloadpage(item.url) itemlist = [] if "Lo sentimos, no tenemos trailer" in data: itemlist.append(item.clone(title="No hay ningún vídeo disponible", action="", text_color="")) else: if item.contextual: progreso = platformtools.dialog_progress("Buscando en abandomoviez", "Cargando trailers...") progreso.update(10) i = 0 message = "Cargando trailers..." patron = '<div class="col-md-3 col-xs-6"><a href="([^"]+)".*?' \ 'Images/(\d+).gif.*?</div><small>(.*?)</small>' matches = scrapertools.find_multiple_matches(data, patron) if len(matches) == 0: trailer_url = scrapertools.find_single_match(data, '<iframe.*?src="([^"]+)"') if trailer_url != "": trailer_url = trailer_url.replace("embed/", "watch?v=") code = scrapertools.find_single_match(trailer_url, 'v=([A-z0-9\-_]+)') thumbnail = "https://img.youtube.com/vi/%s/0.jpg" % code itemlist.append(item.clone(title="Trailer [youtube]", url=trailer_url, server="youtube", thumbnail=thumbnail, action="play", text_color="white")) else: for scrapedurl, language, scrapedtitle in matches: if language == "1": idioma = " (ESP)" else: idioma = " (V.O)" scrapedurl = urlparse.urljoin("http://www.abandomoviez.net/%s" % item.prefix, scrapedurl) scrapedtitle = scrapertools.htmlclean(scrapedtitle) + idioma + " [youtube]" if item.contextual: i += 1 message += ".." progreso.update(10 + (90*i/len(matches)), message) scrapedtitle = "[COLOR white]%s[/COLOR]" % scrapedtitle data_trailer = scrapertools.downloadpage(scrapedurl) trailer_url = scrapertools.find_single_match(data_trailer, 'iframe.*?src="([^"]+)"') trailer_url = trailer_url.replace("embed/", "watch?v=") code = scrapertools.find_single_match(trailer_url, 'v=([A-z0-9\-_]+)') thumbnail = "https://img.youtube.com/vi/%s/0.jpg" % code itemlist.append(item.clone(title=scrapedtitle, url=trailer_url, server="youtube", action="play", thumbnail=thumbnail, text_color="white")) if item.contextual: progreso.close() if keyboard: if item.contextual: title = "[COLOR green]%s[/COLOR]" else: title = "%s" itemlist.append(item.clone(title=title % "Búsqueda Manual en Abandomoviez", action="manual_search", thumbnail="", text_color="green", extra="abandomoviez")) return itemlist
def download_from_server(item): unsupported_servers = ["torrent"] progreso = platformtools.dialog_progress("Descargas", "Probando con: %s" % item.server) channel = __import__('channels.%s' % item.contentChannel, None, None, ["channels.%s" % item.contentChannel]) if hasattr(channel, "play"): progreso.update(50, "Probando con: %s" % item.server, "Conectando con %s..." % item.contentChannel) try: itemlist = getattr(channel, "play")(item.clone(channel=item.contentChannel, action=item.contentAction)) except: logger.error("Error en el canal %s" % item.contentChannel) else: if len(itemlist): download_item = item.clone(**itemlist[0].__dict__) download_item.contentAction = download_item.action download_item.infoLabels = item.infoLabels item = download_item else: logger.info("No hay nada que reproducir") return {"downloadStatus": STATUS_CODES.error} logger.info("contentAction: %s | contentChannel: %s | server: %s | url: %s" % (item.contentAction, item.contentChannel, item.server, item.url)) progreso.close() if not item.server or not item.url or not item.contentAction == "play" or item.server in unsupported_servers: logger.error("El Item no contiene los parametros necesarios.") return {"downloadStatus": STATUS_CODES.error} video_urls, puedes, motivo = servertools.resolve_video_urls_for_playing(item.server, item.url, item.password, True) # Si no esta disponible, salimos if not puedes: logger.info("El vídeo **NO** está disponible") return {"downloadStatus": STATUS_CODES.error} else: logger.info("El vídeo **SI** está disponible") result = {} # Recorre todas las opciones hasta que consiga descargar una correctamente for video_url in reversed(video_urls): result = download_from_url(video_url[1], item) if result["downloadStatus"] in [STATUS_CODES.canceled, STATUS_CODES.completed]: break # Error en la descarga, continuamos con la siguiente opcion if result["downloadStatus"] == STATUS_CODES.error: continue # Devolvemos el estado return result
def download_from_best_server(item): logger.info("pelisalacarta.channels.descargas download_from_best_server") progreso = platformtools.dialog_progress( "Descargas", "Obteniendo lista de servidores disponibles...") # importamos el canal channel = __import__('channels.%s' % item.contentChannel, fromlist=["channels.%s" % item.contentChannel]) if hasattr(channel, item.contentAction): # Obtenemos el listado de servers play_items = getattr(channel, item.contentAction)(item) else: play_items = servertools.find_video_items(item) progreso.update(100, "Servidores disponibles: %s" % len(play_items)) # Las ordenamos segun calidad play_items.sort(key=ordenar) result = {"downloadStatus": 3} if progreso.iscanceled(): result["downloadStatus"] = 1 return result time.sleep(3) progreso.close # Recorremos el listado de servers, hasta encontrar uno que funcione for play_item in play_items: if play_item.action == "play": # Si el canal tiene funcion play, la lanza if hasattr(channel, "play"): itemlist = getattr(channel, "play")(play_item) if len(itemlist): play_item = itemlist[0] else: logger.info("No hay nada que reproducir") return result else: continue # Lanzamos la descarga download_item = item.clone() download_item.__dict__.update(play_item.__dict__) result = download_from_server(download_item) if progreso.iscanceled(): result["downloadStatus"] = 1 # Tanto si se cancela la descarga como si se completa dejamos de probar mas opciones if result["downloadStatus"] in [1, 2]: break return result
def move(path, dest, silent=False, strict=False, vfs=True, ch_mod=''): """ Mueve un archivo @param path: ruta del fichero a mover @type path: str @param dest: ruta donde mover @type dest: str @rtype: bool @return: devuelve False en caso de error """ try: if xbmc_vfs and vfs: if not exists(path): return False path = encode(path) dest = encode(dest) result = bool(xbmcvfs.rename(path, dest)) if not result and not strict: if not silent: logger.error( "ERROR al MOVER el archivo: %s. Copiando y borrando" % path) result = bool(copy(path, dest, su=True)) if not result: return False xbmcvfs.delete(path) if result and ch_mod: result = chmod(dest, ch_mod, silent=silent) return result # samba/samba elif path.lower().startswith("smb://") and dest.lower().startswith( "smb://"): dest = encode(dest, True) path = encode(path, True) samba.rename(path, dest) # local/local elif not path.lower().startswith( "smb://") and not dest.lower().startswith("smb://"): dest = encode(dest) path = encode(path) os.rename(path, dest) # mixto En este caso se copia el archivo y luego se elimina el de origen else: if not silent: dialogo = platformtools.dialog_progress("Copiando archivo", "") return copy(path, dest) == True and remove(path) == True except: logger.error("ERROR al mover el archivo: %s a %s" % (path, dest)) if not silent: logger.error(traceback.format_exc()) return False else: return True
def download_from_best_server(item): logger.info("pelisalacarta.channels.descargas download_from_best_server") progreso = platformtools.dialog_progress("Descargas", "Obteniendo lista de servidores disponibles...") # importamos el canal channel = __import__('channels.%s' % item.contentChannel, fromlist=["channels.%s" % item.contentChannel]) if hasattr(channel, item.contentAction): # Obtenemos el listado de servers play_items = getattr(channel, item.contentAction)(item) else: play_items = servertools.find_video_items(item) progreso.update(100, "Servidores disponibles: %s" % len(play_items)) # Las ordenamos segun calidad play_items.sort(key=ordenar) result = {"downloadStatus": 3} if progreso.iscanceled(): result["downloadStatus"] = 1 return result time.sleep(3) progreso.close # Recorremos el listado de servers, hasta encontrar uno que funcione for play_item in play_items: if play_item.action == "play": # Si el canal tiene funcion play, la lanza if hasattr(channel, "play"): itemlist = getattr(channel, "play")(play_item) if len(itemlist): play_item = itemlist[0] else: logger.info("No hay nada que reproducir") return result else: continue # Lanzamos la descarga download_item = item.clone() download_item.__dict__.update(play_item.__dict__) result = download_from_server(download_item) if progreso.iscanceled(): result["downloadStatus"] = 1 # Tanto si se cancela la descarga como si se completa dejamos de probar mas opciones if result["downloadStatus"] in [1, 2]: break return result
def update_infolabels_show(tmdb_id, with_tvdb=False): logger.info() if with_tvdb: from core import tvdb as scrapper else: from core import tmdb as scrapper tit = 'Actualizando datos desde ' + ('TVDB' if with_tvdb else 'TMDB') progreso = platformtools.dialog_progress(tit, 'Serie y temporadas ...') db = TrackingData() cambios = [] # Serie # ----- infolabels = db.get_show(tmdb_id) it = Item(infoLabels = infolabels) # ~ logger.debug(it) scrapper.set_infoLabels_item(it) # ~ logger.debug(it) if base64.b64encode(jsontools.dump(infolabels)) != base64.b64encode(jsontools.dump(it.infoLabels)): db.save_show(tmdb_id, it.infoLabels) cambios.append('Serie') # Temporadas # ---------- rows = db.get_seasons(tmdb_id) num_rows = len(rows) n = 0 for season, infolabels in rows: it = Item(infoLabels = infolabels) # ~ logger.debug(it) scrapper.set_infoLabels_item(it) # ~ logger.debug(it) if base64.b64encode(jsontools.dump(infolabels)) != base64.b64encode(jsontools.dump(it.infoLabels)): db.save_season(tmdb_id, season, it.infoLabels) cambios.append('T%d' % season) n += 1 perc = int(n / num_rows * 100) progreso.update(perc, tit, 'Procesada temporada %d' % season) if progreso.iscanceled(): break # Para episodios podrían ser demasiadas llamadas a tmdb, mejor hacerlo por una temporada concreta progreso.close() commit = True if len(cambios) > 0 else False db.close(commit=commit) msg = 'Sin cambios en la serie ni en las temporadas.' if not commit else 'Actualizados cambios en %s.' % ', '.join(cambios) logger.info(msg) return commit, msg
def process(channel_list, category, news, total_channels, startpage=False, save=False): itemlist = list() searching = list() searching_titles = list() number_of_channels = float(100) / len(channel_list) config.set_setting('tmdb_active', False) searching += channel_list searching_titles += channel_list cnt = 0 if not startpage: progress = platformtools.dialog_progress("%s (%s) Seleccionados " % (category, total_channels), "Obteniendo novedades. Por favor espere...") with futures.ThreadPoolExecutor(max_workers=max_workers) as executor: c_results = [executor.submit(get_channel_news, ch, news) for ch in channel_list] for index, res in enumerate(futures.as_completed(c_results)): cnt += 1 percentage = int(math.ceil((index + 1) * number_of_channels)) finished = res.result()[0] if not startpage: if progress.iscanceled(): break if finished in searching: searching_titles.remove(searching_titles[searching.index(finished)]) searching.remove(finished) if not startpage: progress.update(percentage, "Obteniendo novedades. Por favor espere..." + '\n' + str(searching_titles) + '\n' + ' ' + '\n' + ' ' + '\n' + ' ') if len(res.result()) > 1: if save: save_results(finished, res.result()[1], news) else: itemlist += res.result()[1] if not startpage: progress.close() config.set_setting('tmdb_active', True) return itemlist
def start_dialog(self, title="Descargando..."): from platformcode import platformtools progreso = platformtools.dialog_progress(title, "Iniciando descarga...") self.start() while self.state == self.states.downloading and not progreso.iscanceled(): time.sleep(0.1) line1 = "%s" % (self.filename) line2 = "%.2f%% - %.2f %s de %.2f %s a %.2f %s/s (%d/%d)" % ( self.progress, self.downloaded[1], self.downloaded[2], self.size[1], self.size[2], self.speed[1], self.speed[2], self.connections[0], self.connections[1]) line3 = "Tiempo restante: %s" % (self.remaining_time) progreso.update(int(self.progress), line1, line2, line3) if self.state == self.states.downloading: self.stop() progreso.close()
def start_dialog(self, title=config.get_localized_string(60200)): from platformcode import platformtools progreso = platformtools.dialog_progress(title, config.get_localized_string(60201)) self.start() while self.state == self.states.downloading and not progreso.iscanceled(): time.sleep(0.1) line1 = "%s" % (self.filename) line2 = config.get_localized_string(59983) % ( self.progress, self.downloaded[1], self.downloaded[2], self.size[1], self.size[2], self.speed[1], self.speed[2], self.connections[0], self.connections[1]) line3 = config.get_localized_string(60202) % (self.remaining_time) progreso.update(int(self.progress), line1 + '\n' + line2 + '\n' + line3 + '\n' + ' ') if self.state == self.states.downloading: self.stop() progreso.close()
def save_library_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("pelisalacarta.platformcode.library savelibrary_movie") insertados = 0 sobreescritos = 0 fallidos = 0 logger.debug(item.tostring('\n')) if not item.fulltitle or not item.channel: return 0, 0, -1 # Salimos sin guardar # progress dialog p_dialog = platformtools.dialog_progress('pelisalacarta', 'Añadiendo película...') filename = title_to_filename("{0} [{1}].strm".format(item.fulltitle.strip().lower(), item.channel)) logger.debug(filename) fullfilename = join_path(MOVIES_PATH, filename) addon_name = sys.argv[0].strip() if not addon_name: addon_name = "plugin://plugin.video.pelisalacarta/" if path_exists(fullfilename): logger.info("pelisalacarta.platformcode.library savelibrary el fichero existe. Se sobreescribe") sobreescritos += 1 else: insertados += 1 p_dialog.update(100, 'Añadiendo película...', item.fulltitle) p_dialog.close() if save_file('{addon}?{url}'.format(addon=addon_name, url=item.tourl()), fullfilename): item = get_video_id_from_scraper(item, config.get_setting("scrap_ask_name") == "true", "movie") if 'id_Tmdb' in item.infoLabels: create_nfo_file(item.infoLabels['id_Tmdb'], fullfilename[:-5], "cine") return insertados, sobreescritos, fallidos else: return 0, 0, 1
def __init__(self, key, referer): if sys.version_info[0] < 3: self.rc = None platformtools.dialog_ok( 'reCAPTCHA', 'Il sito sta mostrando la schermata "Non sono un robot".\nQuesta schermata tuttavia è superabile solo da kodi 19' ) else: prog = platformtools.dialog_progress( 'Caricamento reCAPTCHA', 'Il sito sta mostrando la schermata "Non sono un robot"') filetools.rmdirtree(temp_dir) self.rc = ReCaptcha(api_key=key, site_url=referer, user_agent=httptools.get_user_agent(), lang=lang) prog.close()
def save_download_video(item): logger.info("contentAction: %s | contentChannel: %s | contentTitle: %s" % (item.contentAction, item.contentChannel, item.contentTitle)) progreso = platformtools.dialog_progress("Descargas", "Añadiendo video...") if not item.contentTitle: item.contentTitle = re.sub("\[[^\]]+\]|\([^\)]+\)","",item.fulltitle).strip() if not item.contentTitle: item.contentTitle = re.sub("\[[^\]]+\]|\([^\)]+\)","",item.title).strip() item.downloadFilename = "%s [%s]" % (item.contentTitle.strip(), item.contentChannel) write_json(item) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), "¿Iniciar la descarga ahora?"): platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle, config.get_localized_string(30109)) else: start_download(item)
def save_download_movie(item): logger.info("contentAction: %s | contentChannel: %s | contentTitle: %s" % (item.contentAction, item.contentChannel, item.contentTitle)) progreso = platformtools.dialog_progress("Descargas", "Obteniendo datos de la pelicula") result = tmdb.find_and_set_infoLabels_tmdb(item) if not result: progreso.close() item.contentType = "video" return save_download_video(item) progreso.update(0, "Añadiendo pelicula...") item.downloadFilename = "%s [%s]" % (item.contentTitle.strip(), item.contentChannel) write_json(item) progreso.close() if not platformtools.dialog_yesno(config.get_localized_string(30101), "¿Iniciar la descarga ahora?"): platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle, config.get_localized_string(30109)) else: start_download(item)
def save_library_episodes(path, episodelist): """ 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. @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("pelisalacarta.platformcode.library savelibrary_episodes") insertados = 0 sobreescritos = 0 fallidos = 0 # progress dialog p_dialog = platformtools.dialog_progress('pelisalacarta', 'Añadiendo episodios...') p_dialog.update(0, 'Añadiendo episodio...') # fix float porque la division se hace mal en python 2.x t = float(100) / len(episodelist) addon_name = sys.argv[0].strip() if not addon_name: addon_name = "plugin://plugin.video.pelisalacarta/" for i, e in enumerate(episodelist): p_dialog.update(int(math.ceil(i * t)), 'Añadiendo episodio...', e.title) # Añade todos menos el que dice "Añadir esta serie..." o "Descargar esta serie..." if e.action == "add_serie_to_library" or e.action == "download_all_episodes": continue e.action = "play_from_library" e.category = "Series" nuevo = False filename = "{0}.strm".format(scrapertools.get_season_and_episode(e.title.lower())) fullfilename = join_path(path, filename) # logger.debug(fullfilename) if not path_exists(fullfilename): nuevo = True if save_file('{addon}?{url}'.format(addon=addon_name, url=e.tourl()), fullfilename): if nuevo: insertados += 1 else: sobreescritos += 1 else: fallidos += 1 if p_dialog.iscanceled(): break p_dialog.close() logger.debug("insertados= {0}, sobreescritos={1}, fallidos={2}".format(insertados, sobreescritos, fallidos)) return insertados, sobreescritos, fallidos
def novedades(item): logger.info("streamondemand.channels.novedades item="+item.tostring()) global list_newest l_hilo = [] list_newest = [] start_time = time.time() multithread = config.get_setting("multithread", "novedades") logger.info("streamondemand.channels.novedades multithread="+str(multithread)) if not multithread: if platformtools.dialog_yesno("Multi-thread disattivato", "Il multi-thread consente una miglior performance nella ricerca", "Nei sistemi con poche risorse potrebbe essere imprecisa", "Attivare il multi-thread?"): if config.set_setting("multithread", True, "novedades"): multithread = True progreso = platformtools.dialog_progress(item.category, "Cercando nei canali ...") list_canales = get_list_canales() number_of_channels = len(list_canales[item.extra]) for index, channel in enumerate(list_canales[item.extra]): channel_id, channel_title = channel percentage = index * 100 / number_of_channels # Modo Multi Thread if multithread: t = Thread(target=get_newest, args=[channel_id, item.extra], name=channel_title) t.start() l_hilo.append(t) progreso.update(percentage/2, "Cercando in '%s' ..." % channel_title) # Modo single Thread else: logger.info("Ottenendo novità da channel_id=" + channel_id) progreso.update(percentage, "Cercando in '%s' ..." % channel_title) get_newest(channel_id, item.extra) # Modo Multi Thread: esperar q todos los hilos terminen if multithread: pendent = [a for a in l_hilo if a.isAlive()] while pendent: percentage = (len(l_hilo) - len(pendent)) * 100 / len(l_hilo) if len(pendent) > 5: progreso.update(percentage, "Cercando in %d/%d canali ..." % (len(pendent), len(l_hilo))) else: list_pendent_names = [a.getName() for a in pendent] mensaje = "Cercando in %s" % (", ".join(list_pendent_names)) progreso.update(percentage, mensaje) logger.debug(mensaje) if progreso.iscanceled(): logger.info("Ricerca di novità annullata") break time.sleep(0.5) pendent = [a for a in l_hilo if a.isAlive()] mensaje = "Risultati ottenuti: %s | Tempo: %2.f secondi" % ( len(list_newest), time.time()-start_time) progreso.update(100, mensaje) logger.info(mensaje) start_time = time.time() #logger.debug(start_time) result_mode = config.get_setting("result_mode", "novedades") if result_mode == 0: # Agrupados por contenido ret = agruparXcontenido(list_newest, item.extra) elif result_mode == 1: # Agrupados por canales ret = agruparXcanal(list_newest, item.extra) else: # Sin agrupar ret = noAgrupar(list_newest, item.extra) while time.time()-start_time < 2: # mostrar cuadro de progreso con el tiempo empleado durante almenos 2 segundos time.sleep(0.5) progreso.close() return ret
def download_from_url(url, item): logger.info("pelisalacarta.channels.descargas download_from_url - Intentando descargar: %s" % (url)) if url.lower().endswith(".m3u8") or url.lower().startswith("rtmp"): save_server_statistics(item.server, 0, False) return {"downloadStatus": STATUS_CODES.error} # Obtenemos la ruta de descarga y el nombre del archivo download_path = filetools.dirname(filetools.join(config.get_setting("downloadpath"), item.downloadFilename)) file_name = filetools.basename(filetools.join(config.get_setting("downloadpath"), item.downloadFilename)) # Creamos la carpeta si no existe if not filetools.exists(download_path): filetools.mkdir(download_path) # Mostramos el progreso progreso = platformtools.dialog_progress("Descargas", "Iniciando descarga...") # Lanzamos la descarga d = Downloader(url, filetools.encode(download_path), filetools.encode(file_name)) d.start() # Monitorizamos la descarga hasta que se termine o se cancele while d.state == d.states.downloading and not progreso.iscanceled(): time.sleep(0.1) line1 = "%s" % (filetools.decode(d.filename)) line2 = "%.2f%% - %.2f %s de %.2f %s a %.2f %s/s (%d/%d)" % ( d.progress, d.downloaded[1], d.downloaded[2], d.size[1], d.size[2], d.speed[1], d.speed[2], d.connections[0], d.connections[1]) line3 = "Tiempo restante: %s" % (d.remaining_time) progreso.update(int(d.progress), line1, line2, line3) # Descarga detenida. Obtenemos el estado: # Se ha producido un error en la descarga if d.state == d.states.error: logger.info("pelisalacarta.channels.descargas download_video - Error al intentar descargar %s" % (url)) d.stop() progreso.close() status = STATUS_CODES.error # Aun está descargando (se ha hecho click en cancelar) elif d.state == d.states.downloading: logger.info("pelisalacarta.channels.descargas download_video - Descarga detenida") d.stop() progreso.close() status = STATUS_CODES.canceled # La descarga ha finalizado elif d.state == d.states.completed: logger.info("pelisalacarta.channels.descargas download_video - Descargado correctamente") progreso.close() status = STATUS_CODES.completed if item.downloadSize and item.downloadSize != d.size[0]: status = STATUS_CODES.error save_server_statistics(item.server, d.speed[0], d.state != d.states.error) if progreso.iscanceled(): status = STATUS_CODES.canceled dir = os.path.dirname(item.downloadFilename) file = filetools.join(dir, filetools.decode(d.filename)) if status == STATUS_CODES.completed: move_to_libray(item.clone(downloadFilename = file)) return {"downloadUrl": d.download_url, "downloadStatus": status, "downloadSize": d.size[0], "downloadProgress": d.progress, "downloadCompleted": d.downloaded[0], "downloadFilename": file}
def novedades(item): logger.info() global list_newest l_hilo = [] list_newest = [] start_time = time.time() multithread = config.get_setting("multithread", "novedades") logger.info("multithread= "+str(multithread)) if not multithread: if platformtools.dialog_yesno("Búsqueda concurrente desactivada", "La búsqueda concurrente de novedades proporciona", "una mayor velocidad y su desactivación solo es aconsejable en caso de fallo.", "¿Desea activar la búsqueda concurrente ahora?"): if config.set_setting("multithread", True, "novedades"): multithread = True progreso = platformtools.dialog_progress(item.category, "Buscando canales...") list_canales = get_list_canales() number_of_channels = len(list_canales[item.extra]) for index, channel in enumerate(list_canales[item.extra]): channel_id, channel_title = channel percentage = index * 100 / number_of_channels # Modo Multi Thread if multithread: t = Thread(target=get_newest, args=[channel_id, item.extra], name=channel_title) t.start() l_hilo.append(t) progreso.update(percentage/2, "Buscando en '%s'..." % channel_title) # Modo single Thread else: logger.info("Obteniendo novedades de channel_id=" + channel_id) progreso.update(percentage, "Buscando en '%s'..." % channel_title) get_newest(channel_id, item.extra) # Modo Multi Thread: esperar q todos los hilos terminen if multithread: pendent = [a for a in l_hilo if a.isAlive()] while pendent: percentage = (len(l_hilo) - len(pendent)) * 100 / len(l_hilo) if len(pendent) > 5: progreso.update(percentage, "Buscando en %d/%d canales..." % (len(pendent), len(l_hilo))) else: list_pendent_names = [a.getName() for a in pendent] mensaje = "Buscando en %s" % (", ".join(list_pendent_names)) progreso.update(percentage, mensaje) logger.debug(mensaje) if progreso.iscanceled(): logger.info("Busqueda de novedades cancelada") break time.sleep(0.5) pendent = [a for a in l_hilo if a.isAlive()] mensaje = "Resultados obtenidos: %s | Tiempo: %2.f segundos" % ( len(list_newest), time.time()-start_time) progreso.update(100, mensaje) logger.info(mensaje) start_time = time.time() #logger.debug(start_time) result_mode = config.get_setting("result_mode", "novedades") if result_mode == 0: # Agrupados por contenido ret = agruparXcontenido(list_newest, item.extra) elif result_mode == 1: # Agrupados por canales ret = agruparXcanal(list_newest, item.extra) else: # Sin agrupar ret = noAgrupar(list_newest, item.extra) while time.time()-start_time < 2: # mostrar cuadro de progreso con el tiempo empleado durante almenos 2 segundos time.sleep(0.5) progreso.close() return ret
def save_library_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("pelisalacarta.platformcode.library save_library_movie") # 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 biblioteca..." # 2. fulltitle # 3. title if not item.contentTitle: # Colocamos el titulo correcto en su sitio para que tmdb 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 # TODO configurar para segun el scraper se llamara a uno u otro tmdb_return = tmdb.find_and_set_infoLabels_tmdb(item) # Llegados a este punto podemos tener: # tmdb_return = True: Un item con infoLabels con la información actualizada de la peli # tmdb_return = False: Un item sin información de la peli (se ha dado a cancelar en la ventana) # item.infoLabels['imdb_id'] == "" : No se ha encontrado el identificador de IMDB necesario para continuar, salimos if not tmdb_return or not item.infoLabels['imdb_id']: # 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 TMDB O NO TIENE IMDB_ID") return 0, 0, -1 _id = item.infoLabels['imdb_id'] # progress dialog p_dialog = platformtools.dialog_progress('pelisalacarta', 'Añadiendo película...') base_name = filetools.text2filename(item.contentTitle) for raiz, subcarpetas, ficheros in filetools.walk(MOVIES_PATH): for c in subcarpetas: if c.endswith("[%s]" % _id): path = filetools.join(raiz, c) break if not path: # Crear carpeta path = filetools.join(MOVIES_PATH, ("%s [%s]" % (base_name, _id)).strip()) logger.info("pelisalacarta.platformcode.library save_library_movie Creando directorio pelicula:" + path) try: filetools.mkdir(path) except OSError, exception: if exception.errno != errno.EEXIST: raise
def save_library_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] # Silent es para no mostrar progreso (para library_service) if not silent: # progress dialog p_dialog = platformtools.dialog_progress('streamondemand', 'Aggiunta episodi...') p_dialog.update(0, 'Aggiunta episodio...') new_episodelist =[] # Obtenemos el numero de temporada y episodio y descartamos los q no lo sean for e in episodelist: try: season_episode = scrapertools.get_season_and_episode(e.title) e.infoLabels = serie.infoLabels e.contentSeason, e.contentEpisodeNumber = season_episode.split("x") new_episodelist.append(e) except: 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)), 'Aggiunta episodio...', 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()) 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='biblioteca', 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_idiomas: # 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="biblioteca", url="", action='findvideos', strm_path=strm_path.replace(TVSHOWS_PATH, "")) 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) e.infoLabels = item_nfo.infoLabels 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.contentTitle] = 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) 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") fallidos = -1 else: # ... si ha sido correcto actualizamos la biblioteca de Kodi if config.is_xbmc() and not silent: from platformcode import xbmc_library xbmc_library.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 authentication(): logger.info("pelisalacarta.servers.realdebrid authentication") try: client_id = "YTWNFBIJEEBP6" # Se solicita url y código de verificación para conceder permiso a la app url = "http://api.real-debrid.com/oauth/v2/device/code?client_id=%s&new_credentials=yes" % (client_id) data = scrapertools.downloadpage(url, headers=headers.items()) data = jsontools.load_json(data) verify_url = data["verification_url"] user_code = data["user_code"] device_code = data["device_code"] intervalo = data["interval"] dialog_auth = platformtools.dialog_progress("Autentificación. No cierres esta ventana!!", "1. Entra en la siguiente url: %s" % verify_url, "2. Ingresa este código en la página y presiona Allow: %s" % user_code, "3. Espera a que se cierre esta ventana") # Generalmente cada 5 segundos se intenta comprobar si el usuario ha introducido el código while True: time.sleep(intervalo) try: if dialog_auth.iscanceled(): return "" url = "https://api.real-debrid.com/oauth/v2/device/credentials?client_id=%s&code=%s" \ % (client_id, device_code) data = scrapertools.downloadpage(url, headers=headers.items()) data = jsontools.load_json(data) if "client_secret" in data: # Código introducido, salimos del bucle break except: pass try: dialog_auth.close() except: pass debrid_id = data["client_id"] secret = data["client_secret"] # Se solicita el token de acceso y el de actualización para cuando el primero caduque post = urllib.urlencode({"client_id": debrid_id, "client_secret": secret, "code": device_code, "grant_type": "http://oauth.net/grant_type/device/1.0"}) data = scrapertools.downloadpage("https://api.real-debrid.com/oauth/v2/token", post=post, headers=headers.items()) data = jsontools.load_json(data) token = data["access_token"] refresh = data["refresh_token"] channeltools.set_channel_setting("realdebrid_id", debrid_id, "realdebrid") channeltools.set_channel_setting("realdebrid_secret", secret, "realdebrid") channeltools.set_channel_setting("realdebrid_token", token, "realdebrid") channeltools.set_channel_setting("realdebrid_refresh", refresh, "realdebrid") return token except: import traceback logger.error(traceback.format_exc()) return ""
def save_library_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 biblioteca..." # 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('streamondemand', 'Aggiunta film...') if config.get_setting("original_title_folder", "biblioteca") == 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").lower().encode("utf8") 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="biblioteca", 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='biblioteca', 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 if filetools.write(json_path, item.tojson()): p_dialog.update(100, 'Aggiunta film...', item.contentTitle) item_nfo.library_urls[item.channel] = item.url if filetools.write(nfo_path, head_nfo + item_nfo.tojson()): # actualizamos la biblioteca de Kodi con la pelicula if config.is_xbmc(): from platformcode import xbmc_library xbmc_library.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 biblioteca" % item.contentTitle) p_dialog.update(100, 'Aggiunta fallita...', item.contentTitle) p_dialog.close() return 0, 0, -1
def save_library_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("streamondemand.platformcode.library savelibrary_movie") insertados = 0 sobreescritos = 0 fallidos = 0 logger.debug(item.tostring('\n')) # Itentamos obtener el titulo correcto: # 1. contentTitle: Este deveria ser el sitio correcto # 2. fulltitle # 3. title titulo = item.contentTitle if not titulo: titulo = item.fulltitle if not titulo: titulo = item.title # Colocamos el titulo en su sitio para que tmdb lo localize item.contentTitle = titulo # Si llegados a este punto no tenemos titulo, salimos if not item.contentTitle or not item.channel: return 0, 0, -1 # Salimos sin guardar # TODO configurar para segun el scraper se llamara a uno u otro tmdb.find_and_set_infoLabels_tmdb(item, config.get_setting("scrap_ask_name") == "true") # Llegados a este punto podemos tener: # Un item con infoLabels con la información actualizada de la peli # Un item sin información de la peli (se ha dado a cancelar en la ventana) # progress dialog p_dialog = platformtools.dialog_progress('streamondemand', 'Aggiunta film...') filename = "{0} [{1}].strm".format(item.fulltitle.strip().lower(), item.channel) logger.debug(filename) fullfilename = filetools.join(MOVIES_PATH, filename) addon_name = sys.argv[0].strip() if not addon_name or addon_name.startswith("default.py"): addon_name = "plugin://plugin.video.streamondemand/" if filetools.exists(fullfilename): logger.info("streamondemand.platformcode.library savelibrary el fichero existe. Se sobreescribe") sobreescritos += 1 else: insertados += 1 p_dialog.update(100, 'Añadiendo película...', item.contentTitle) p_dialog.close() item.strm = True # Para depuración creamos un .json al lado del .strm, para poder visualizar que parametros se estan guardando filetools.write(fullfilename + ".json", item.tojson()) if filetools.write(fullfilename, '{addon}?{url}'.format(addon=addon_name, url=item.tourl())): if 'tmdb_id' in item.infoLabels: create_nfo_file(item.infoLabels['tmdb_id'], fullfilename[:-5], "cine") else: if filetools.exists(fullfilename[:-5] + ".nfo"): filetools.remove(fullfilename[:-5] + ".nfo") # actualizamos la biblioteca de Kodi con la pelicula # TODO arreglar el porque hay que poner la ruta special ruta = "special://home/userdata/addon_data/plugin.video.streamondemand/library/CINE/" update(ruta) return insertados, sobreescritos, fallidos else: return 0, 0, 1
def resolve_video_urls_for_playing(server,url,video_password="",muestra_dialogo=False): logger.info("pelisalacarta.core.servertools resolve_video_urls_for_playing, server="+server+", url="+url) video_urls = [] torrent = False server = server.lower() # Si el vídeo es "directo", no hay que buscar más if server=="directo" or server=="local": logger.info("pelisalacarta.core.servertools server=directo, la url es la buena") try: import urlparse parsed_url = urlparse.urlparse(url) logger.info("parsed_url="+str(parsed_url)) extension = parsed_url.path[-4:] except: extension = url[-4:] video_urls = [[ "%s [%s]" % (extension,server) , url ]] return video_urls,True,"" # Averigua las URL de los vídeos else: # Carga el conector try: # Muestra un diágo de progreso if muestra_dialogo: from platformcode import platformtools progreso = platformtools.dialog_progress( "pelisalacarta" , "Conectando con "+server) server_parameters = get_server_parameters(server) #Cuenta las opciones disponibles, para calcular el porcentaje opciones = [] if server_parameters["free"] == "true": opciones.append("free") opciones.extend([premium for premium in server_parameters["premium"] if config.get_setting(premium+"premium")=="true"]) logger.info("pelisalacarta.core.servertools opciones disponibles para " + server + ": " + str(len(opciones)) + " "+str(opciones)) # Sustituye el código por otro "Plex compatible" #exec "from servers import "+server+" as server_connector" servers_module = __import__("servers."+server) server_connector = getattr(servers_module,server) logger.info("pelisalacarta.core.servertools servidor de "+server+" importado") # Si tiene una función para ver si el vídeo existe, lo comprueba ahora if hasattr(server_connector, 'test_video_exists'): logger.info("pelisalacarta.core.servertools invocando a "+server+".test_video_exists") puedes,motivo = server_connector.test_video_exists( page_url=url ) # Si la funcion dice que no existe, fin if not puedes: logger.info("pelisalacarta.core.servertools test_video_exists dice que el video no existe") if muestra_dialogo: progreso.close() return video_urls,puedes,motivo else: logger.info("pelisalacarta.core.servertools test_video_exists dice que el video SI existe") # Obtiene enlaces free if server_parameters["free"]=="true": if muestra_dialogo: progreso.update((100 / len(opciones)) * opciones.index("free") , "Conectando con "+server) logger.info("pelisalacarta.core.servertools invocando a "+server+".get_video_url") video_urls = server_connector.get_video_url( page_url=url , video_password=video_password ) # Si no se encuentran vídeos en modo free, es porque el vídeo no existe if len(video_urls)==0: if muestra_dialogo: progreso.close() return video_urls,False,"No se puede encontrar el vídeo en "+server # Obtiene enlaces para las diferentes opciones premium error_message = [] for premium in server_parameters["premium"]: if config.get_setting(premium+"premium")=="true": if muestra_dialogo: progreso.update((100 / len(opciones)) * opciones.index(premium) , "Conectando con "+premium) exec "from servers import "+premium+" as premium_conector" if premium == "realdebrid": debrid_urls = premium_conector.get_video_url( page_url=url , premium=True , video_password=video_password ) if not "REAL-DEBRID:" in debrid_urls[0][0]: video_urls.extend(debrid_urls) else: error_message.append(debrid_urls[0][0]) elif premium == "alldebrid": alldebrid_urls = premium_conector.get_video_url( page_url=url , premium=True , user=config.get_setting(premium+"user") , password=config.get_setting(premium+"password"), video_password=video_password ) if not "Alldebrid:" in alldebrid_urls[0][0]: video_urls.extend(alldebrid_urls) else: error_message.append(alldebrid_urls[0][0]) else: video_urls.extend(premium_conector.get_video_url( page_url=url , premium=True , user=config.get_setting(premium+"user") , password=config.get_setting(premium+"password"), video_password=video_password )) if not video_urls and error_message: return video_urls, False, " || ".join(error_message) if muestra_dialogo: progreso.update( 100 , "Proceso finalizado") # Cierra el diálogo de progreso if muestra_dialogo: progreso.close() # Llegas hasta aquí y no tienes ningún enlace para ver, así que no vas a poder ver el vídeo if len(video_urls)==0: # ¿Cual es el motivo? # 1) No existe -> Ya está controlado # 2) No tienes alguna de las cuentas premium compatibles # Lista de las cuentas que soportan este servidor listapremium = [] for premium in server_parameters["premium"]: listapremium.append(get_server_parameters(premium)["name"]) return video_urls,False,"Para ver un vídeo en "+server+" necesitas<br/>una cuenta en "+" o ".join(listapremium) except: if muestra_dialogo: progreso.close() import traceback logger.info(traceback.format_exc()) return video_urls,False,"Se ha producido un error en<br/>el conector con "+server return video_urls,True,""
def do_search(item, categories=[]): multithread = config.get_setting("multithread", "buscador") result_mode = config.get_setting("result_mode", "buscador") logger.info() tecleado = item.extra itemlist = [] channels_path = os.path.join(config.get_runtime_path(), "channels", '*.xml') logger.info("channels_path=%s" % channels_path) channel_language = config.get_setting("channel_language") logger.info("channel_language=%s" % channel_language) if channel_language == "": channel_language = "all" logger.info("channel_language=%s" % channel_language) # Para Kodi es necesario esperar antes de cargar el progreso, de lo contrario # el cuadro de progreso queda "detras" del cuadro "cargando..." y no se le puede dar a cancelar time.sleep(0.5) progreso = platformtools.dialog_progress("Buscando '%s'..." % tecleado, "") channel_files = sorted(glob.glob(channels_path), key=lambda x: os.path.basename(x)) number_of_channels = len(channel_files) searches = [] search_results = {} start_time = time.time() if multithread: progreso.update(0, "Buscando '%s'..." % tecleado) for index, infile in enumerate(channel_files): try: percentage = (index * 100) / number_of_channels basename = os.path.basename(infile) basename_without_extension = basename[:-4] logger.info("%s..." % basename_without_extension) channel_parameters = channeltools.get_channel_parameters(basename_without_extension) # No busca si es un canal inactivo if channel_parameters["active"] != "true": logger.info("%s no incluido" % basename_without_extension) continue # En caso de busqueda por categorias if categories: if not any(cat in channel_parameters["categories"] for cat in categories): logger.info("%s no incluido" % basename_without_extension) continue # No busca si es un canal para adultos, y el modo adulto está desactivado if channel_parameters["adult"] == "true" and config.get_setting("adult_mode") == "0": logger.info("%s no incluido" % basename_without_extension) continue # No busca si el canal es en un idioma filtrado if channel_language != "all" and channel_parameters["language"] != channel_language: logger.info("%s no incluido" % basename_without_extension) continue # No busca si es un canal excluido de la busqueda global include_in_global_search = channel_parameters["include_in_global_search"] if include_in_global_search in ["", "true"]: # Buscar en la configuracion del canal include_in_global_search = str(config.get_setting("include_in_global_search", basename_without_extension)) # Si no hay valor en la configuración del canal se incluye ya que así estaba por defecto '''if include_in_global_search == "": include_in_global_search = "true"''' if include_in_global_search.lower() != "true": logger.info("%s no incluido" % basename_without_extension) continue if progreso.iscanceled(): progreso.close() logger.info("Busqueda cancelada") return itemlist # Modo Multi Thread if multithread: t = Thread(target=channel_search, args=[search_results, channel_parameters, tecleado], name=channel_parameters["title"]) t.setDaemon(True) t.start() searches.append(t) # Modo single Thread else: logger.info("Intentado busqueda en " + basename_without_extension + " de " + tecleado) channel_search(search_results, channel_parameters, tecleado) logger.info("%s incluido en la busqueda" % basename_without_extension) progreso.update(percentage / 2, "Iniciada busqueda de '%s' en %s..." % (tecleado, channel_parameters["title"])) except: continue logger.error("No se puede buscar en: %s" % channel_parameters["title"]) import traceback logger.error(traceback.format_exc()) # Modo Multi Thread # Usando isAlive() no es necesario try-except, # ya que esta funcion (a diferencia de is_alive()) # es compatible tanto con versiones antiguas de python como nuevas if multithread: pendent = [a for a in searches if a.isAlive()] while pendent: percentage = (len(searches) - len(pendent)) * 100 / len(searches) completed = len(searches) - len(pendent) if len(pendent) > 5: progreso.update(percentage, "Busqueda terminada en %d de %d canales..." % (completed, len(searches))) else: list_pendent_names = [a.getName() for a in pendent] mensaje = "Buscando en %s" % (", ".join(list_pendent_names)) progreso.update(percentage, mensaje) logger.debug(mensaje) if progreso.iscanceled(): logger.info("Busqueda cancelada") break time.sleep(0.5) pendent = [a for a in searches if a.isAlive()] total = 0 for channel in sorted(search_results.keys()): for search in search_results[channel]: total += len(search["itemlist"]) title = channel if result_mode == 0: if len(search_results[channel]) > 1: title += " [" + search["item"].title.strip() + "]" title += " (" + str(len(search["itemlist"])) + ")" title = re.sub("\[COLOR [^\]]+\]", "", title) title = re.sub("\[/COLOR]", "", title) extra = search["item"].extra + "{}" + search["item"].channel + "{}" + tecleado itemlist.append(Item(title=title, channel="buscador", action="channel_result", url=search["item"].url, extra=extra, folder=True)) else: title = ">> Resultados del canal %s:" % title itemlist.append(Item(title=title, channel="buscador", action="", folder=False, text_color="yellow")) itemlist.extend(search["itemlist"]) # itemlist.append(Item(title="", channel="buscador", action="", folder=False)) title = "Buscando: '%s' | Encontrado: %d vídeos | Tiempo: %2.f segundos" % (tecleado, total, time.time()-start_time) itemlist.insert(0, Item(title=title, text_color='yellow')) progreso.close() return itemlist
def do_search(item, categories=[]): multithread = config.get_setting("multithread","buscador") result_mode = config.get_setting("result_mode","buscador") logger.info("pelisalacarta.channels.buscador do_search") tecleado = item.extra itemlist = [] channels_path = os.path.join(config.get_runtime_path(), "channels", '*.xml') logger.info("pelisalacarta.channels.buscador channels_path="+channels_path) channel_language = config.get_setting("channel_language") logger.info("pelisalacarta.channels.buscador channel_language="+channel_language) if channel_language == "": channel_language = "all" logger.info("pelisalacarta.channels.buscador channel_language="+channel_language) #Para Kodi es necesario esperar antes de cargar el progreso, de lo contrario #el cuadro de progreso queda "detras" del cuadro "cargando..." y no se le puede dar a cancelar time.sleep(0.5) progreso = platformtools.dialog_progress("Buscando " + tecleado,"") channel_files = glob.glob(channels_path) number_of_channels = len(channel_files) searches = [] search_results = {} start_time = time.time() if multithread: progreso.update(0, "Buscando %s..." % (tecleado)) for index, infile in enumerate(channel_files): percentage = index*100/number_of_channels basename = os.path.basename(infile) basename_without_extension = basename[:-4] channel_parameters = channeltools.get_channel_parameters(basename_without_extension) # No busca si es un canal inactivo if channel_parameters["active"] != "true": continue # En caso de busqueda por categorias if categories: if not any(cat in channel_parameters["categories"] for cat in categories): continue # No busca si es un canal para adultos, y el modo adulto está desactivado if channel_parameters["adult"] == "true" and config.get_setting("adult_mode") == "false": continue # No busca si el canal es en un idioma filtrado if channel_language != "all" and channel_parameters["language"] != channel_language: continue # No busca si es un canal excluido de la busqueda global include_in_global_search = channel_parameters["include_in_global_search"] if include_in_global_search == "": #Buscar en la configuracion del canal include_in_global_search = str(config.get_setting("include_in_global_search",basename_without_extension)) if include_in_global_search.lower() != "true": continue if progreso.iscanceled(): break #Modo Multi Thread if multithread: t = Thread(target=channel_search,args=[search_results, channel_parameters, tecleado]) t.setDaemon(True) t.start() searches.append(t) #Modo single Thread else: logger.info("pelisalacarta.channels.buscador Intentado busqueda en " + basename_without_extension + " de " + tecleado) progreso.update(percentage, "Buscando %s en %s..." % (tecleado, channel_parameters["title"])) channel_search(search_results, channel_parameters, tecleado) #Modo Multi Thread if multithread : pendent = len([a for a in searches if a.is_alive()]) while pendent: pendent = len([a for a in searches if a.is_alive()]) percentage = (len(searches) - pendent) * 100 / len(searches) progreso.update(percentage, "Buscando %s en %d canales..." % (tecleado, len(searches))) if progreso.iscanceled(): break time.sleep(0.5) total = 0 for channel in sorted(search_results.keys()): for search in search_results[channel]: total+= len(search["itemlist"]) if result_mode ==0: title = channel if len(search_results[channel]) > 1: title += " [" + search["item"].title.strip() + "]" title +=" (" + str(len(search["itemlist"])) + ")" title = re.sub("\[COLOR [^\]]+\]","",title) title = re.sub("\[/COLOR]","",title) extra = search["item"].extra + "{}" + search["item"].channel + "{}" + tecleado itemlist.append(Item(title=title, channel="buscador",action="channel_result", url=search["item"].url, extra = extra, folder=True)) else: itemlist.extend(search["itemlist"]) title="Buscando: '%s' | Encontrado: %d vídeos | Tiempo: %2.f segundos" % (tecleado,total, time.time()-start_time) itemlist.insert(0,Item(title=title, color='yellow')) progreso.close() return itemlist
def save_library_episodes(path, episodelist, serie, silent=False): """ 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 @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("streamondemand.platformcode.library save_library_episodes") # No hay lista de episodios, no hay nada que guardar if not len(episodelist): logger.info("streamondemand.platformcode.library save_library_episodes No hay lista de episodios, " "salimos sin crear strm") return 0, 0, 0 insertados = 0 sobreescritos = 0 fallidos = 0 # Silent es para no mostrar progreso (para library_service) if not silent: # progress dialog p_dialog = platformtools.dialog_progress('streamondemand', 'Aggiunta episodi...') p_dialog.update(0, 'Aggiunta episodio...') # fix float porque la division se hace mal en python 2.x t = float(100) / len(episodelist) addon_name = sys.argv[0].strip() if not addon_name or addon_name.startswith("default.py"): addon_name = "plugin://plugin.video.streamondemand/" for i, e in enumerate(episodelist): if not silent: p_dialog.update(int(math.ceil((i + 1) * t)), 'Aggiunta episodio...', e.title) # Añade todos menos el que dice "Añadir esta serie..." o "Descargar esta serie..." if e.action == "add_serie_to_library" or e.action == "download_all_episodes": continue season_episode = scrapertools.get_season_and_episode(e.title.lower()) e.infoLabels = serie.infoLabels e.contentSeason, e.contentEpisodeNumber = season_episode.split("x") filename = "{0}.strm".format(season_episode) fullfilename = filetools.join(path, filename) nuevo = not filetools.exists(fullfilename) if e.infoLabels.get("tmdb_id"): tmdb.find_and_set_infoLabels_tmdb(e, config.get_setting("scrap_ask_name") == "true") e.strm = True # Para depuración creamos un .json al lado del .strm, para poder visualizar que parametros se estan guardando filetools.write(fullfilename + ".json", e.tojson()) # TODO fix temporal, en algunas ocasiones no se reproduce desde la biblioteca de kodi si tiene valor # por ejemplo serie doctor who, en seriesblanco e.infoLabels['tmdb_id'] = "" if filetools.write(fullfilename, '{addon}?{url}'.format(addon=addon_name, url=e.tourl())): if nuevo: insertados += 1 else: sobreescritos += 1 else: fallidos += 1 if not silent and p_dialog.iscanceled(): break if not silent: p_dialog.close() # si se han añadido episodios los actualizamos en la biblioteca de Kodi con la serie if fallidos >= 0: # TODO arreglar el porque hay que poner la ruta special ruta = "special://home/userdata/addon_data/plugin.video.streamondemand/library/SERIES/" + \ "{0} [{1}]".format(serie.contentSerieName.strip().lower(), serie.channel).lower() + "/" update(ruta) logger.debug("insertados= {0}, sobreescritos={1}, fallidos={2}".format(insertados, sobreescritos, fallidos)) return insertados, sobreescritos, fallidos
def save_library_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("pelisalacarta.platformcode.library save_library_episodes") # No hay lista de episodios, no hay nada que guardar if not len(episodelist): logger.info("pelisalacarta.platformcode.library save_library_episodes No hay lista de episodios, " "salimos sin crear strm") return 0, 0, 0 insertados = 0 sobreescritos = 0 fallidos = 0 news_in_playcounts = {} # Silent es para no mostrar progreso (para library_service) if not silent: # progress dialog p_dialog = platformtools.dialog_progress('pelisalacarta', 'Añadiendo episodios...') p_dialog.update(0, 'Añadiendo episodio...') # fix float porque la division se hace mal en python 2.x t = float(100) / len(episodelist) for i, e in enumerate(episodelist): if not silent: p_dialog.update(int(math.ceil((i + 1) * t)), 'Añadiendo episodio...', e.title) # Añade todos menos el que dice "Añadir esta serie..." o "Descargar esta serie..." if e.action == "add_serie_to_library" or e.action == "download_all_episodes": continue try: if e.channel == "descargas": season_episode = scrapertools.get_season_and_episode(e.contentTitle.lower()) else: season_episode = scrapertools.get_season_and_episode(e.title.lower()) e.infoLabels = serie.infoLabels e.contentSeason, e.contentEpisodeNumber = season_episode.split("x") season_episode = "%sx%s" % (e.contentSeason, str(e.contentEpisodeNumber).zfill(2)) except: continue strm_path = filetools.join(path, "%s.strm" % season_episode) if not filetools.exists(strm_path): # Si no existe season_episode.strm añadirlo item_strm = e.clone(action='play_from_library', channel='biblioteca', 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 # si el canal tiene filtro se le pasa el nombre que tiene guardado para que filtre correctamente, if item_strm.list_idiomas: # si viene de library_service se obtiene del fichero tvshow.nfo, propiedad "library_filter_show" if "library_filter_show" in serie: item_strm.library_filter_show = serie.library_filter_show.get(serie.channel, "") # si se ha agregado la serie lo obtenemos del titulo. else: item_strm.library_filter_show = serie.title 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')) filetools.write(strm_path, '%s?%s' % (addon_name, item_strm.tourl())) nfo_path = filetools.join(path, "%s.nfo" % season_episode) item_nfo = None if not filetools.exists(nfo_path) and e.infoLabels.get("tmdb_id"): # Si no existe season_episode.nfo añadirlo tmdb.find_and_set_infoLabels_tmdb(e) item_nfo = e.clone(channel="biblioteca", url="", action='findvideos', strm_path=strm_path.replace(TVSHOWS_PATH, "")) url_scraper = "https://www.themoviedb.org/tv/%s/season/%s/episode/%s\n" % (item_nfo.infoLabels['tmdb_id'], item_nfo.contentSeason, item_nfo.contentEpisodeNumber) filetools.write(nfo_path, url_scraper + item_nfo.tojson()) # Solo si existen season_episode.nfo y season_episode.strm continuamos json_path = filetools.join(path, ("%s [%s].json" % (season_episode, e.channel)).lower()) if filetools.exists(nfo_path) and filetools.exists(strm_path): nuevo = not filetools.exists(json_path) if nuevo or overwrite: # Obtenemos infoLabel del episodio if not item_nfo: item_nfo = Item().fromjson(filetools.read(nfo_path, 1)) e.infoLabels = item_nfo.infoLabels if filetools.write(json_path, e.tojson()): if nuevo: logger.info("pelisalacarta.platformcode.library savelibrary 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.contentTitle] = 0 else: logger.info("pelisalacarta.platformcode.library savelibrary Sobreescrito: %s" % json_path) sobreescritos += 1 else: logger.info("pelisalacarta.platformcode.library savelibrary Fallido: %s" % json_path) fallidos += 1 else: logger.info("pelisalacarta.platformcode.library savelibrary 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: url_scraper = filetools.read(tvshow_path, 0, 1) tvshow_item = Item().fromjson(filetools.read(tvshow_path, 1)) tvshow_item.library_playcounts.update(news_in_playcounts) filetools.write(tvshow_path, url_scraper + tvshow_item.tojson()) except: logger.error("Error al actualizar tvshow.nfo") fallidos = -1 # ... y actualizamos la biblioteca de Kodi if config.is_xbmc(): 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