# -*- coding: utf-8 -*- # ------------------------------------------------------------ # Channel for recent videos on several channels # ------------------------------------------------------------ import glob import os import re import time from threading import Thread from channelselector import get_thumb from core import channeltools from core import scrapertools from core.item import Item from platformcode import config, logger from platformcode import platformtools THUMBNAILS = {'0': 'posters', '1': 'banners', '2': 'squares'} __perfil__ = config.get_setting('perfil', "news") # Fijar perfil de color perfil = [['0xFF0B7B92', '0xFF89FDFB', '0xFFACD5D4'], ['0xFFB31313', '0xFFFF9000', '0xFFFFEE82'], ['0xFF891180', '0xFFCB22D7', '0xFFEEA1EB'], ['0xFFA5DEE5', '0xFFE0F9B5', '0xFFFEFDCA'], ['0xFFF23557', '0xFF22B2DA', '0xFFF0D43A']] color1, color2, color3 = perfil[__perfil__] list_newest = [] channels_id_name = {} def mainlist(item): logger.info() itemlist = [] list_canales, any_active = get_channels_list() #if list_canales['peliculas']: thumbnail = get_thumb("channels_movie.png") new_item = Item(channel=item.channel, action="novedades", extra="peliculas", title="Películas", thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) #if list_canales['terror']: thumbnail = get_thumb("channels_horror.png") new_item = Item(channel=item.channel, action="novedades", extra="terror", title="Peliculas de miedo!", thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) #if list_canales['infantiles']: thumbnail = get_thumb("channels_children.png") new_item = Item(channel=item.channel, action="novedades", extra="infantiles", title="Para niños", thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) #if list_canales['series']: thumbnail = get_thumb("channels_tvshow.png") new_item = Item(channel=item.channel, action="novedades", extra="series", title="Episodios de series", thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) #if list_canales['anime']: thumbnail = get_thumb("channels_anime.png") new_item = Item(channel=item.channel, action="novedades", extra="anime", title="Episodios de anime", thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) #if list_canales['documentales']: thumbnail = get_thumb("channels_documentary.png") new_item = Item(channel=item.channel, action="novedades", extra="documentales", title="Documentales", thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) return itemlist def set_category_context(item): item.context = [{"title": "Canales incluidos en: %s" % item.title, "extra": item.extra, "action": "setting_channel", "channel": item.channel}] item.category = "Novedades en %s" % item.extra def get_channels_list(): logger.info() list_canales = {'peliculas': [], 'terror': [], 'infantiles': [], 'series': [], 'anime': [], 'documentales': []} any_active = False # Rellenar listas de canales disponibles channels_path = os.path.join(config.get_runtime_path(), "channels", '*.json') channel_language = config.get_setting("channel_language", default="all") for infile in sorted(glob.glob(channels_path)): channel_id = os.path.basename(infile)[:-5] channel_parameters = channeltools.get_channel_parameters(channel_id) # No incluir si es un canal inactivo if not channel_parameters["active"]: continue # No incluir si es un canal para adultos, y el modo adulto está desactivado if channel_parameters["adult"] and config.get_setting("adult_mode") == 0: continue # No incluir si el canal es en un idioma filtrado if channel_language != "all" and channel_language not in channel_parameters["language"] \ and "*" not in channel_parameters["language"]: continue # Incluir en cada categoria, si en su configuracion el canal esta activado para mostrar novedades for categoria in list_canales: include_in_newest = config.get_setting("include_in_newest_" + categoria, channel_id) if include_in_newest: channels_id_name[channel_id] = channel_parameters["title"] list_canales[categoria].append((channel_id, channel_parameters["title"])) any_active = True return list_canales, any_active def novedades(item): logger.info() global list_newest threads = [] list_newest = [] start_time = time.time() multithread = config.get_setting("multithread", "news") 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, "news"): multithread = True progreso = platformtools.dialog_progress(item.category, "Buscando canales...") list_canales, any_active = get_channels_list() if any_active and len(list_canales[item.extra])>0: import math # fix float porque la division se hace mal en python 2.x number_of_channels = float(100) / len(list_canales[item.extra]) for index, channel in enumerate(list_canales[item.extra]): channel_id, channel_title = channel percentage = int(math.ceil((index + 1) * number_of_channels)) # if progreso.iscanceled(): # progreso.close() # logger.info("Búsqueda cancelada") # return itemlist # Modo Multi Thread if multithread: t = Thread(target=get_newest, args=[channel_id, item.extra], name=channel_title) t.start() threads.append(t) progreso.update(percentage, "", "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 threads if a.isAlive()] t = float(100) / len(pendent) while pendent: index = (len(threads) - len(pendent)) + 1 percentage = int(math.ceil(index * t)) list_pendent_names = [a.getName() for a in pendent] mensaje = "Buscando en %s" % (", ".join(list_pendent_names)) progreso.update(percentage, "Finalizado en %d/%d canales..." % (len(threads) - len(pendent), len(threads)), mensaje) logger.debug(mensaje) if progreso.iscanceled(): logger.info("Busqueda de novedades cancelada") break time.sleep(0.5) pendent = [a for a in threads 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", "news") if result_mode == 0: # Agrupados por contenido ret = group_by_content(list_newest) elif result_mode == 1: # Agrupados por canales ret = group_by_channel(list_newest) else: # Sin agrupar ret = no_group(list_newest) 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 else: no_channels = platformtools.dialog_ok('Novedades - %s'%item.extra, 'No se ha definido ningun canal para la ' 'busqueda.','Utilice el menu contextual ' 'para agregar al menos uno') return def get_newest(channel_id, categoria): logger.info("channel_id=" + channel_id + ", categoria=" + categoria) global list_newest # Solicitamos las novedades de la categoria (item.extra) buscada en el canal channel # Si no existen novedades para esa categoria en el canal devuelve una lista vacia try: puede = True try: modulo = __import__('channels.%s' % channel_id, fromlist=["channels.%s" % channel_id]) except: try: exec "import channels." + channel_id + " as modulo" except: puede = False if not puede: return logger.info("running channel " + modulo.__name__ + " " + modulo.__file__) list_result = modulo.newest(categoria) logger.info("canal= %s %d resultados" % (channel_id, len(list_result))) for item in list_result: # logger.info("item="+item.tostring()) item.channel = channel_id list_newest.append(item) except: logger.error("No se pueden recuperar novedades de: " + channel_id) import traceback logger.error(traceback.format_exc()) def get_title(item): if item.contentSerieName: # Si es una serie title = item.contentSerieName if not scrapertools.get_season_and_episode(title) and item.contentEpisodeNumber: if not item.contentSeason: item.contentSeason = '1' title = "%s - %sx%s" % (title, item.contentSeason, str(item.contentEpisodeNumber).zfill(2)) elif item.contentTitle: # Si es una pelicula con el canal adaptado title = item.contentTitle elif item.fulltitle: # Si el canal no esta adaptado title = item.fulltitle else: # Como ultimo recurso title = item.title # Limpiamos el titulo de etiquetas de formato anteriores title = re.compile("\[/*COLO.*?\]", re.DOTALL).sub("", title) title = re.compile("\[/*B\]", re.DOTALL).sub("", title) title = re.compile("\[/*I\]", re.DOTALL).sub("", title) return title def no_group(list_result_canal): itemlist = [] global channels_id_name for i in list_result_canal: i.title = get_title(i) + " [" + channels_id_name[i.channel] + "]" i.text_color = color3 itemlist.append(i.clone()) return sorted(itemlist, key=lambda it: it.title.lower()) def group_by_channel(list_result_canal): global channels_id_name dict_canales = {} itemlist = [] for i in list_result_canal: if i.channel not in dict_canales: dict_canales[i.channel] = [] # Formatear titulo i.title = get_title(i) # Añadimos el contenido al listado de cada canal dict_canales[i.channel].append(i) # Añadimos el contenido encontrado en la lista list_result for c in sorted(dict_canales): itemlist.append(Item(channel="news", title=channels_id_name[c] + ':', text_color=color1, text_bold=True)) for i in dict_canales[c]: if i.contentQuality: i.title += ' (%s)' % i.contentQuality if i.language: i.title += ' [%s]' % i.language i.title = ' %s' % i.title i.text_color = color3 itemlist.append(i.clone()) return itemlist def group_by_content(list_result_canal): global channels_id_name dict_contenidos = {} list_result = [] for i in list_result_canal: # Formatear titulo i.title = get_title(i) # Eliminar tildes y otros caracteres especiales para la key import unicodedata try: new_key = i.title.lower().strip().decode("UTF-8") new_key = ''.join((c for c in unicodedata.normalize('NFD', new_key) if unicodedata.category(c) != 'Mn')) except: new_key = i.title if new_key in dict_contenidos: # Si el contenido ya estaba en el diccionario añadirlo a la lista de opciones... dict_contenidos[new_key].append(i) else: # ...sino añadirlo al diccionario dict_contenidos[new_key] = [i] # Añadimos el contenido encontrado en la lista list_result for v in dict_contenidos.values(): title = v[0].title if len(v) > 1: # Eliminar de la lista de nombres de canales los q esten duplicados canales_no_duplicados = [] for i in v: if i.channel not in canales_no_duplicados: canales_no_duplicados.append(channels_id_name[i.channel]) if len(canales_no_duplicados) > 1: canales = ', '.join([i for i in canales_no_duplicados[:-1]]) title += " (En %s y %s)" % (canales, canales_no_duplicados[-1]) else: title += " (En %s)" % (', '.join([i for i in canales_no_duplicados])) new_item = v[0].clone(channel="news", title=title, action="show_channels", sub_list=[i.tourl() for i in v], extra=channels_id_name) else: new_item = v[0].clone(title=title) new_item.text_color = color3 list_result.append(new_item) return sorted(list_result, key=lambda it: it.title.lower()) def show_channels(item): logger.info() global channels_id_name channels_id_name = item.extra itemlist = [] for i in item.sub_list: new_item = Item() new_item = new_item.fromurl(i) # logger.debug(new_item.tostring()) if new_item.contentQuality: new_item.title += ' (%s)' % new_item.contentQuality if new_item.language: new_item.title += ' [%s]' % new_item.language new_item.title += ' (%s)' % channels_id_name[new_item.channel] new_item.text_color = color1 itemlist.append(new_item.clone()) return itemlist def menu_opciones(item): itemlist = list() itemlist.append(Item(channel=item.channel, title="Canales incluidos en:", thumbnail=get_thumb("setting_0.png"), folder=False)) itemlist.append(Item(channel=item.channel, action="setting_channel", extra="peliculas", title=" - Películas ", thumbnail=get_thumb("channels_movie.png"), folder=False)) itemlist.append(Item(channel=item.channel, action="setting_channel", extra="infantiles", title=" - Para niños", thumbnail=get_thumb("channels_children.png"), folder=False)) itemlist.append(Item(channel=item.channel, action="setting_channel", extra="series", title=" - Episodios de series", thumbnail=get_thumb("channels_tvshow.png"), folder=False)) itemlist.append(Item(channel=item.channel, action="setting_channel", extra="anime", title=" - Episodios de anime", thumbnail=get_thumb("channels_anime.png"), folder=False)) itemlist.append(Item(channel=item.channel, action="setting_channel", extra="documentales", title=" - Documentales", thumbnail=get_thumb("channels_documentary.png"), folder=False)) itemlist.append(Item(channel=item.channel, action="settings", title="Otros ajustes", thumbnail=get_thumb("setting_0.png"), folder=False)) return itemlist def settings(item): return platformtools.show_channel_settings(caption="configuración -- Novedades") def setting_channel(item): channels_path = os.path.join(config.get_runtime_path(), "channels", '*.json') channel_language = config.get_setting("channel_language", default="all") list_controls = [] for infile in sorted(glob.glob(channels_path)): channel_id = os.path.basename(infile)[:-5] channel_parameters = channeltools.get_channel_parameters(channel_id) # No incluir si es un canal inactivo if not channel_parameters["active"]: continue # No incluir si es un canal para adultos, y el modo adulto está desactivado if channel_parameters["adult"] and config.get_setting("adult_mode") == 0: continue # No incluir si el canal es en un idioma filtrado if channel_language != "all" and channel_language not in channel_parameters["language"] \ and "*" not in channel_parameters["language"]: continue # No incluir si en su configuracion el canal no existe 'include_in_newest' include_in_newest = config.get_setting("include_in_newest_" + item.extra, channel_id) if include_in_newest is None: continue control = {'id': channel_id, 'type': "bool", 'label': channel_parameters["title"], 'default': include_in_newest, 'enabled': True, 'visible': True} list_controls.append(control) caption = "Canales incluidos en Novedades " + item.title.replace("Canales incluidos en: ", "- ").strip() if config.get_setting("custom_button_value_news", item.channel): custom_button_label = "Ninguno" else: custom_button_label = "Todos" return platformtools.show_channel_settings(list_controls=list_controls, caption="Canales incluidos en Novedades", callback="save_settings", item=item, custom_button={'visible': True, 'function': "cb_custom_button", 'close': False, 'label': custom_button_label}) def save_settings(item, dict_values): for v in dict_values: config.set_setting("include_in_newest_" + item.extra, dict_values[v], v) def cb_custom_button(item, dict_values): value = config.get_setting("custom_button_value_news", item.channel) if value == "": value = False for v in dict_values.keys(): dict_values[v] = not value if config.set_setting("custom_button_value_news", not value, item.channel) == True: return {"label": "Ninguno"} else: return {"label": "Todos"}