# -*- coding: utf-8 -*- # ------------------------------------------------------------ # Channel for recent videos on several channels # ------------------------------------------------------------ #from builtins import str import sys from core.support import typo PY3 = False if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int import glob import os import re import time from threading import Thread from channelselector import get_thumb, auto_filter from core import channeltools from core import jsontools from core import scrapertools, support 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 = ["red", "0xFF65B3DA", "yellow"] # color1, color2, color3 = perfil[__perfil__] list_newest = [] list_newest_tourl = [] channels_id_name = {} menu_cache_path = os.path.join(config.get_data_path(), "settings_channels", 'menu_cache_data.json') menu_settings_path = os.path.join(config.get_data_path(), "settings_channels", 'menu_settings_data.json') def mainlist(item): logger.info() itemlist = [] # list_canales, any_active = get_channels_list() channel_language = config.get_setting("channel_language", default="auto") if channel_language == 'auto': channel_language = auto_filter() #if list_canales['peliculas']: thumbnail = get_thumb("movie.png") new_item = Item(channel=item.channel, action="novedades", extra="peliculas", title=config.get_localized_string(30122), thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) # thumbnail = get_thumb("movie_4k.png") # new_item = Item(channel=item.channel, action="novedades", extra="4k", title=config.get_localized_string(70208), 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=config.get_localized_string(70209), # thumbnail=thumbnail) # set_category_context(new_item) # itemlist.append(new_item) #if list_canales['infantiles']: # thumbnail = get_thumb("children.png") # new_item = Item(channel=item.channel, action="novedades", extra="infantiles", title=config.get_localized_string(60510), # thumbnail=thumbnail) # set_category_context(new_item) # itemlist.append(new_item) #if list_canales['series']: thumbnail = get_thumb("tvshow.png") new_item = Item(channel=item.channel, action="novedades", extra="series", title=config.get_localized_string(60511), thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) #if list_canales['anime']: thumbnail = get_thumb("anime.png") new_item = Item(channel=item.channel, action="novedades", extra="anime", title=config.get_localized_string(60512), thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) # if channel_language == "all": # # if list_canales['Italiano']: # thumbnail = get_thumb("italian.png") # new_item = Item(channel=item.channel, action="novedades", extra="italiano", title=config.get_localized_string(70563), # thumbnail=thumbnail) # set_category_context(new_item) # itemlist.append(new_item) # if list_canales['Torrent']: # thumbnail = get_thumb("channels_torrent.png") # new_item = Item(channel=item.channel, action="novedades", extra="torrent", title=config.get_localized_string(70171), thumbnail=thumbnail) # set_category_context(new_item) # itemlist.append(new_item) #if list_canales['documentales']: thumbnail = get_thumb("documentary.png") new_item = Item(channel=item.channel, action="novedades", extra="documentales", title=config.get_localized_string(60513), thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) thumbnail = get_thumb("setting_0.png") itemlist.append(Item(channel='shortcuts', action="SettingOnPosition", category=7, setting=1, title=typo(config.get_localized_string(70285), 'bold color kod'), thumbnail=thumbnail)) return itemlist def set_category_context(item): item.context = [{"title": config.get_localized_string(60514) % item.title, "extra": item.extra, "action": "setting_channel", "channel": item.channel}] item.category = config.get_localized_string(60679) % item.extra def get_channels_list(): logger.info() ## import web_pdb; web_pdb.set_trace() ## list_canales = {'peliculas': [], '4k': [], 'terror': [], 'infantiles': [], 'series': [], 'anime': [], ## 'castellano': [], 'latino':[], 'italiano':[], 'torrent':[], 'documentales': []} list_canales = {'peliculas': [], 'series': [],'anime': [], 'italiano':[], '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") if channel_language =="auto": channel_language = auto_filter() 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 el canal es en un idioma filtrado if channel_language != "all" and channel_language not in str(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 set_cache(item): logger.info() item.mode = 'set_cache' t = Thread(target=novedades, args=[item]) t.start() #t.join() def get_from_cache(item): logger.info() itemlist=[] cache_node = jsontools.get_node_from_file('menu_cache_data.json', 'cached') first=item.last last = first+40 #if last >=len(cache_node[item.extra]): # last = len(cache_node[item.extra]) for cached_item in cache_node[item.extra][first:last]: new_item= Item() new_item = new_item.fromurl(cached_item) itemlist.append(new_item) if item.mode == 'silent': set_cache(item) if last >= len(cache_node[item.extra]): item.mode='finish' itemlist = add_menu_items(item, itemlist) else: item.mode='get_cached' item.last =last itemlist = add_menu_items(item, itemlist) return itemlist def add_menu_items(item, itemlist): logger.info() menu_icon = get_thumb('menu.png') menu = Item(channel="channelselector", action="getmainlist", viewmode="movie", thumbnail=menu_icon, title='Menu') itemlist.insert(0, menu) if item.mode != 'finish': if item.mode == 'get_cached': last=item.last else: last = len(itemlist) refresh_icon = get_thumb('more.png') refresh = item.clone(thumbnail=refresh_icon, mode='get_cached',title='Mas', last=last) itemlist.insert(len(itemlist), refresh) return itemlist def novedades(item): logger.info() global list_newest threads = [] list_newest = [] start_time = time.time() mode = item.mode if mode == '': mode = 'normal' if mode=='get_cached': if os.path.exists(menu_cache_path): return get_from_cache(item) multithread = config.get_setting("multithread", "news") logger.info("multithread= " + str(multithread)) if not multithread: if platformtools.dialog_yesno(config.get_localized_string(60515), config.get_localized_string(60516), config.get_localized_string(60517), config.get_localized_string(60518)): if config.set_setting("multithread", True, "news"): multithread = True if mode == 'normal': progreso = platformtools.dialog_progress(item.category, config.get_localized_string(60519)) list_canales, any_active = get_channels_list() if config.is_xbmc(): from specials import side_menu if mode=='silent' and any_active and len(list_canales[item.extra]) > 0: side_menu.set_menu_settings(item) aux_list=[] for canal in list_canales[item.extra]: if len(aux_list)<2: aux_list.append(canal) list_canales[item.extra]=aux_list if mode == 'set_cache': list_canales[item.extra] = list_canales[item.extra][2:] 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) if mode == 'normal': progreso.update(percentage, "", config.get_localized_string(60520) % channel_title) # Modo single Thread else: if mode == 'normal': logger.info("Obteniendo novedades de channel_id=" + channel_id) progreso.update(percentage, "", config.get_localized_string(60520) % 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] if mode == 'normal': mensaje = config.get_localized_string(30994) % (", ".join(list_pendent_names)) progreso.update(percentage, config.get_localized_string(60521) % (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()] if mode == 'normal': mensaje = config.get_localized_string(60522) % (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 mode != 'normal': result_mode=0 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) if mode == 'normal': progreso.close() if mode == 'silent': set_cache(item) item.mode = 'set_cache' ret = add_menu_items(item, ret) if mode != 'set_cache': return ret else: if mode != 'set_cache': no_channels = platformtools.dialog_ok(config.get_localized_string(30130) + ' - ' + item.extra, config.get_localized_string(70661), config.get_localized_string(70662)) return def get_newest(channel_id, categoria): logger.info("channel_id=" + channel_id + ", categoria=" + categoria) global list_newest global list_newest_tourl # 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))) exist=False if os.path.exists(menu_cache_path): cache_node = jsontools.get_node_from_file('menu_cache_data.json', 'cached') exist=True else: cache_node = {} #logger.debug('cache node: %s' % cache_node) for item in list_result: # logger.info("item="+item.tostring()) item.channel = channel_id list_newest.append(item) list_newest_tourl.append(item.tourl()) cache_node[categoria] = list_newest_tourl jsontools.update_node(cache_node, 'menu_cache_data.json', "cached") except: logger.error("No se pueden recuperar novedades de: " + channel_id) import traceback logger.error(traceback.format_exc()) def get_title(item): #support.log("ITEM NEWEST ->", item) # item.contentSerieName c'è anche se è un film if item.contentSerieName and item.contentType != 'movie': # Si es una serie title = item.contentSerieName #title = re.compile("\[.*?\]", re.DOTALL).sub("", item.contentSerieName) if not scrapertools.get_season_and_episode(title) and item.contentEpisodeNumber: # contentSeason non c'è in support if not item.contentSeason: item.contentSeason = '1' title = "%sx%s - %s" % (item.contentSeason, str(item.contentEpisodeNumber).zfill(2), title) else: seas = scrapertools.get_season_and_episode(item.title) if seas: title = "%s - %s" % (seas, title) elif item.contentTitle: # Si es una pelicula con el canal adaptado title = item.contentTitle elif item.contentTitle: # Si el canal no esta adaptado title = item.contentTitle 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) title = '[B]'+title+'[/B]' if item.contentLanguage == '': pass elif type(item.contentLanguage) == list and len(item.contentLanguage) ==1: title += support.typo(item.contentLanguage[0], '_ [] color kod') elif type(item.contentLanguage) != '': title += support.typo(item.contentLanguage, '_ [] color kod') elif type(item.contentLanguage) == list: title += item.contentLanguage if item.quality: title += support.typo(item.quality, '_ [] color kod') season_ = support.typo(config.get_localized_string(70736), '_ [] color white bold') if (type(item.args) != bool and 'season_completed' in item.news and not item.episode) else '' if season_: title += season_ return title def no_group(list_result_canal): itemlist = [] global channels_id_name for i in list_result_canal: #support.log("NO GROUP i -> ", i) canale = channels_id_name[i.channel] canale = canale # per differenziarlo dal colore delle altre voci i.title = get_title(i) + " [" + canale + "]" # 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.contentLanguage: ## i.title += ' [%s]' % i.contentLanguage ## 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 list(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 += config.get_localized_string(70210) % (canales, canales_no_duplicados[-1]) else: title += config.get_localized_string(70211) % (', '.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=config.get_localized_string(60525), text_bold = True, thumbnail=get_thumb("setting_0.png"), folder=False)) itemlist.append(Item(channel=item.channel, action="setting_channel", extra="peliculas", title=config.get_localized_string(60526), thumbnail=get_thumb("movie.png"), folder=False)) # itemlist.append(Item(channel=item.channel, action="setting_channel", extra="4K", title=config.get_localized_string(70207), # thumbnail=get_thumb("movie.png"), folder=False)) # itemlist.append(Item(channel=item.channel, action="setting_channel", extra="infantiles", title=config.get_localized_string(60527), # thumbnail=get_thumb("children.png"), # folder=False)) itemlist.append(Item(channel=item.channel, action="setting_channel", extra="series", title=config.get_localized_string(60528), thumbnail=get_thumb("tvshow.png"), folder=False)) itemlist.append(Item(channel=item.channel, action="setting_channel", extra="anime", title=config.get_localized_string(60529), thumbnail=get_thumb("anime.png"), folder=False)) # itemlist.append( # Item(channel=item.channel, action="setting_channel", extra="castellano", title=config.get_localized_string(70212), # thumbnail=get_thumb("documentary.png"), folder=False)) # itemlist.append(Item(channel=item.channel, action="setting_channel", extra="latino", title=config.get_localized_string(70213), # thumbnail=get_thumb("documentary.png"), folder=False)) # itemlist.append(Item(channel=item.channel, action="setting_channel", extra="torrent", title=config.get_localized_string(70214), # thumbnail=get_thumb("documentary.png"), folder=False)) itemlist.append(Item(channel=item.channel, action="setting_channel", extra="documentales", title=config.get_localized_string(60530), thumbnail=get_thumb("documentary.png"), folder=False)) itemlist.append(Item(channel=item.channel, action="settings", title=config.get_localized_string(60531), thumbnail=get_thumb("setting_0.png"), folder=False)) return itemlist def settings(item): return platformtools.show_channel_settings(caption=config.get_localized_string(60532)) def setting_channel(item): channels_path = os.path.join(config.get_runtime_path(), "channels", '*.json') channel_language = config.get_setting("channel_language", default="auto") if channel_language == 'auto': channel_language = auto_filter() 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 el canal es en un idioma filtrado if channel_language != "all" and channel_language not in str(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 = config.get_localized_string(60533) + item.title.replace(config.get_localized_string(60525), "- ").strip() if config.get_setting("custom_button_value_news", item.channel): custom_button_label = config.get_localized_string(59992) else: custom_button_label = config.get_localized_string(59991) return platformtools.show_channel_settings(list_controls=list_controls, caption=caption, 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 list(dict_values.keys()): dict_values[v] = not value if config.set_setting("custom_button_value_news", not value, item.channel) == True: return {"label": config.get_localized_string(59992)} else: return {"label": config.get_localized_string(59991)}