def __get_data(self, item, global_filter_lang_id): dict_filtered_shows = filetools.get_node_from_data_json(item.channel, TAG_TVSHOW_FILTER) tvshow = item.show.lower().strip() global_filter_language = config.get_setting(global_filter_lang_id, item.channel) if tvshow in dict_filtered_shows.keys(): self.result = ResultFilter({TAG_ACTIVE: dict_filtered_shows[tvshow][TAG_ACTIVE], TAG_LANGUAGE: dict_filtered_shows[tvshow][TAG_LANGUAGE], TAG_QUALITY_ALLOWED: dict_filtered_shows[tvshow][TAG_QUALITY_ALLOWED]}) # opcion general "no filtrar" elif global_filter_language != 0: from core import channeltools list_controls, dict_settings = channeltools.get_channel_controls_settings(item.channel) for control in list_controls: if control["id"] == global_filter_lang_id: try: language = control["lvalues"][global_filter_language] # logger.debug("language %s" % language) except: logger.error("No se ha encontrado el valor asociado al codigo '%s': %s" % (global_filter_lang_id, global_filter_language)) break self.result = ResultFilter({TAG_ACTIVE: True, TAG_LANGUAGE: language, TAG_QUALITY_ALLOWED: []}) break
def __get_data(self, item, global_filter_lang_id): dict_filtered_shows = jsontools.get_node_from_file(item.channel, TAG_TVSHOW_FILTER) tvshow = item.show.lower().strip() global_filter_language = config.get_setting(global_filter_lang_id, item.channel) if tvshow in list(dict_filtered_shows.keys()): self.result = ResultFilter({TAG_ACTIVE: dict_filtered_shows[tvshow][TAG_ACTIVE], TAG_LANGUAGE: dict_filtered_shows[tvshow][TAG_LANGUAGE], TAG_QUALITY_ALLOWED: dict_filtered_shows[tvshow][TAG_QUALITY_ALLOWED]}) # general option "do not filter" elif global_filter_language != 0: from core import channeltools list_controls, dict_settings = channeltools.get_channel_controls_settings(item.channel) for control in list_controls: if control["id"] == global_filter_lang_id: try: language = control["lvalues"][global_filter_language] # logger.debug("language %s" % language) except: logger.error("The value associated with the code was not found '%s': %s" % (global_filter_lang_id, global_filter_language)) break self.result = ResultFilter({TAG_ACTIVE: True, TAG_LANGUAGE: language, TAG_QUALITY_ALLOWED: []}) break
def start(self, list_controls=None, dict_values=None, title="Opciones", callback=None, item=None, custom_button=None, channelpath = None): logger.info("[xbmc_config_menu] start") # Ruta para las imagenes de la ventana self.mediapath = os.path.join(config.get_runtime_path(), 'resources', 'skins', 'Default', 'media') # Capturamos los parametros self.list_controls = list_controls self.values = dict_values self.title = title self.callback = callback self.item = item if type(custom_button) == dict: self.custom_button = {} self.custom_button["label"] = custom_button.get("label", "") self.custom_button["function"] = custom_button.get("function", "") self.custom_button["visible"] = bool(custom_button.get("visible", True)) self.custom_button["close"] = bool(custom_button.get("close", False)) else: self.custom_button = None # Obtenemos el canal desde donde se ha echo la llamada y cargamos los settings disponibles para ese canal if not channelpath: channelpath = inspect.currentframe().f_back.f_back.f_code.co_filename self.channel = os.path.basename(channelpath).replace(".py", "") # Si no tenemos list_controls, hay que sacarlos del xml del canal if not self.list_controls: # Si la ruta del canal esta en la carpeta "channels", obtenemos los controles y valores mediante chaneltools if os.path.join(config.get_runtime_path(), "channels") in channelpath: # La llamada se hace desde un canal self.list_controls, default_values = channeltools.get_channel_controls_settings(self.channel) # En caso contrario salimos else: return None # Si no se pasan dict_values, creamos un dict en blanco if self.values is None: self.values = {} # Ponemos el titulo if self.title == "": self.title = str(config.get_localized_string(30100)) + " -- " + self.channel.capitalize() elif self.title.startswith('@') and unicode(self.title[1:]).isnumeric(): self.title = config.get_localized_string(int(self.title[1:])) # Muestra la ventana self.return_value = None self.doModal() return self.return_value
def get_channel_setting(name, channel): """ Retorna el valor de configuracion del parametro solicitado. Devuelve el valor del parametro 'name' en la configuracion propia del canal 'channel'. Si se especifica el nombre del canal busca en la ruta \addon_data\plugin.video.pelisalacarta\settings_channels el archivo channel_data.json y lee el valor del parametro 'name'. Si el archivo channel_data.json no existe busca en la carpeta channels el archivo channel.xml y crea un archivo channel_data.json antes de retornar el valor solicitado. Parametros: name -- nombre del parametro channel [ -- nombre del canal Retorna: value -- El valor del parametro 'name' """ #Creamos la carpeta si no existe if not os.path.exists(os.path.join(config.get_data_path(), "settings_channels")): os.mkdir(os.path.join(config.get_data_path(), "settings_channels")) file_settings= os.path.join(config.get_data_path(), "settings_channels", channel+"_data.json") dict_settings ={} if os.path.exists(file_settings): # Obtenemos configuracion guardada de ../settings/channel_data.json try: dict_file = jsontools.load_json(open(file_settings, "r").read()) if isinstance(dict_file, dict) and dict_file.has_key('settings'): dict_settings = dict_file['settings'] except EnvironmentError: logger.info("ERROR al leer el archivo: {0}".format(file_settings)) if len(dict_settings) == 0 or not dict_settings.has_key(name): # Obtenemos controles del archivo ../channels/channel.xml from core import channeltools try: list_controls, default_settings = channeltools.get_channel_controls_settings(channel) except: default_settings = {} if default_settings.has_key(name): # Si el parametro existe en el channel.xml creamos el channel_data.json default_settings.update(dict_settings) dict_settings = default_settings dict_file = {} dict_file['settings']= dict_settings # Creamos el archivo ../settings/channel_data.json json_data = jsontools.dump_json(dict_file).encode("utf-8") try: open(file_settings, "w").write(json_data) except EnvironmentError: logger.info("[config.py] ERROR al salvar el archivo: {0}".format(file_settings)) # Devolvemos el valor del parametro local 'name' si existe if dict_settings.has_key(name): return dict_settings[name] else: return None
def get_languages(channel): ''' Obtiene los idiomas desde el xml del canal :param channel: str :return: list ''' logger.info() list_language =['No filtrar'] list_controls, dict_settings = channeltools.get_channel_controls_settings(channel) for control in list_controls: if control["id"] == 'filter_languages': list_language = control["lvalues"] return list_language
def conf_tools(item): logger.info() # Activar o desactivar canales if item.extra == "channels_onoff": if config.get_platform( True )['num_version'] >= 17.0: # A partir de Kodi 16 se puede usar multiselect, y de 17 con preselect return channels_onoff(item) import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") excluded_channels = [ 'url', 'search', 'videolibrary', 'setting', 'news', # 'help', 'downloads' ] list_controls = [] try: list_controls.append({ 'id': "all_channels", 'type': "list", 'label': config.get_localized_string(60594), 'default': 0, 'enabled': True, 'visible': True, 'lvalues': [ '', config.get_localized_string(60591), config.get_localized_string(60592), config.get_localized_string(60593) ] }) for channel in channel_list: # Si el canal esta en la lista de exclusiones lo saltamos if channel.channel not in excluded_channels: channel_parameters = channeltools.get_channel_parameters( channel.channel) status_control = "" status = config.get_setting("enabled", channel.channel) # si status no existe es que NO HAY valor en _data.json if status is None: status = channel_parameters["active"] logger.debug("%s | Status (XML): %s" % (channel.channel, status)) if not status: status_control = config.get_localized_string(60595) else: logger.debug("%s | Status: %s" % (channel.channel, status)) control = { 'id': channel.channel, 'type': "bool", 'label': channel_parameters["title"] + status_control, 'default': status, 'enabled': True, 'visible': True } list_controls.append(control) else: continue except: import traceback logger.error("Error: %s" % traceback.format_exc()) else: return platformtools.show_channel_settings( list_controls=list_controls, item=item.clone(channel_list=channel_list), caption=config.get_localized_string(60596), callback="channel_status", custom_button={"visible": False}) # Comprobacion de archivos channel_data.json elif item.extra == "lib_check_datajson": itemlist = [] import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") # Tener una lista de exclusion no tiene mucho sentido por que se comprueba si channel.json tiene "settings", # pero por si acaso se deja excluded_channels = ['url', 'setting', 'help'] try: import os from core import jsontools for channel in channel_list: list_status = None default_settings = None # Se comprueba si el canal esta en la lista de exclusiones if channel.channel not in excluded_channels: # Se comprueba que tenga "settings", sino se salta list_controls, dict_settings = channeltools.get_channel_controls_settings( channel.channel) if not list_controls: itemlist.append( Item(channel=CHANNELNAME, title=channel.title + config.get_localized_string(60569), action="", folder=False, thumbnail=channel.thumbnail)) continue # logger.info(channel.channel + " SALTADO!") # Se cargan los ajustes del archivo json del canal file_settings = os.path.join( config.get_data_path(), "settings_channels", channel.channel + "_data.json") dict_settings = {} dict_file = {} if filetools.exists(file_settings): # logger.info(channel.channel + " Tiene archivo _data.json") channeljson_exists = True # Obtenemos configuracion guardada de ../settings/channel_data.json try: dict_file = jsontools.load( open(file_settings, "rb").read()) if isinstance(dict_file, dict) and 'settings' in dict_file: dict_settings = dict_file['settings'] except EnvironmentError: logger.error("ERROR al leer el archivo: %s" % file_settings) else: # logger.info(channel.channel + " No tiene archivo _data.json") channeljson_exists = False if channeljson_exists: try: datajson_size = filetools.getsize(file_settings) except: import traceback logger.error(channel.title + config.get_localized_string(60570) % traceback.format_exc()) else: datajson_size = None # Si el _data.json esta vacio o no existe... if (len(dict_settings) and datajson_size) == 0 or not channeljson_exists: # Obtenemos controles del archivo ../channels/channel.json needsfix = True try: # Se cargan los ajustes por defecto list_controls, default_settings = channeltools.get_channel_controls_settings( channel.channel) # logger.info(channel.title + " | Default: %s" % default_settings) except: import traceback logger.error(channel.title + config.get_localized_string(60570) % traceback.format_exc()) # default_settings = {} # Si _data.json necesita ser reparado o no existe... if needsfix or not channeljson_exists: if default_settings is not None: # Creamos el channel_data.json default_settings.update(dict_settings) dict_settings = default_settings dict_file['settings'] = dict_settings # Creamos el archivo ../settings/channel_data.json json_data = jsontools.dump(dict_file) try: open(file_settings, "wb").write(json_data) # logger.info(channel.channel + " - Archivo _data.json GUARDADO!") # El channel_data.json se ha creado/modificado list_status = config.get_localized_string( 60560) except EnvironmentError: logger.error( "ERROR al salvar el archivo: %s" % file_settings) else: if default_settings is None: list_status = config.get_localized_string( 60571) else: # logger.info(channel.channel + " - NO necesita correccion!") needsfix = False # Si se ha establecido el estado del canal se añade a la lista if needsfix is not None: if needsfix: if not channeljson_exists: list_status = config.get_localized_string( 60588) list_colour = "red" else: list_status = config.get_localized_string( 60589) list_colour = "green" else: # Si "needsfix" es "false" y "datjson_size" es None habra # ocurrido algun error if datajson_size is None: list_status = config.get_localized_string( 60590) list_colour = "red" else: list_status = config.get_localized_string( 60589) list_colour = "green" if list_status is not None: itemlist.append( Item(channel=CHANNELNAME, title=channel.title + list_status, action="", folder=False, thumbnail=channel.thumbnail, text_color=list_colour)) else: logger.error("Algo va mal con el canal %s" % channel.channel) # Si el canal esta en la lista de exclusiones lo saltamos else: continue except: import traceback logger.error("Error: %s" % traceback.format_exc()) return itemlist
def conf_tools(item): logger.info() # Activar o desactivar canales if item.extra == "channels_onoff": import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") excluded_channels = ['tengourl', 'buscador', 'biblioteca', 'configuracion', 'novedades', 'personal', 'ayuda', 'descargas'] list_controls = [] try: list_controls.append({'id': "all_channels", 'type': "list", 'label': "Todos los canales", 'default': 0, 'enabled': True, 'visible': True, 'lvalues': ['', 'Activar todos', 'Desactivar todos', 'Establecer estado por defecto']}) for channel in channel_list: # Si el canal esta en la lista de exclusiones lo saltamos if channel.channel not in excluded_channels: channel_parameters = channeltools.get_channel_parameters(channel.channel) status_control = "" status = config.get_setting("enabled", channel.channel) # si status no existe es que NO HAY valor en _data.json if status is None: status = channel_parameters["active"] logger.debug("%s | Status (XML): %s" % (channel.channel, status)) if not status: status_control = " [COLOR grey](Desactivado por defecto)[/COLOR]" else: logger.debug("%s | Status: %s" % (channel.channel, status)) control = {'id': channel.channel, 'type': "bool", 'label': channel_parameters["title"] + status_control, 'default': status, 'enabled': True, 'visible': True} list_controls.append(control) else: continue except: import traceback logger.error("Error: %s" % traceback.format_exc()) else: return platformtools.show_channel_settings(list_controls=list_controls, item=item.clone(channel_list=channel_list), caption="Canales", callback="channel_status", custom_button={"visible": False}) # Comprobacion de archivos channel_data.json elif item.extra == "lib_check_datajson": itemlist = [] import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") # Tener una lista de exclusion no tiene mucho sentido por que se comprueba si # el xml tiene "settings", pero por si acaso se deja excluded_channels = ['tengourl', 'configuracion', 'personal', 'ayuda'] try: import os from core import jsontools for channel in channel_list: list_status = None default_settings = None # Se comprueba si el canal esta en la lista de exclusiones if channel.channel not in excluded_channels: # Se comprueba que tenga "settings", sino se salta jsonchannel = channeltools.get_channel_json(channel.channel) if not jsonchannel.get("settings"): itemlist.append(Item(channel=CHANNELNAME, title=channel.title + " - No tiene ajustes por defecto", action="", folder=False, thumbnail=channel.thumbnail)) continue # logger.info(channel.channel + " SALTADO!") # Se cargan los ajustes del archivo json del canal file_settings = os.path.join(config.get_data_path(), "settings_channels", channel.channel + "_data.json") dict_settings = {} dict_file = {} if filetools.exists(file_settings): # logger.info(channel.channel + " Tiene archivo _data.json") channeljson_exists = True # Obtenemos configuracion guardada de ../settings/channel_data.json try: dict_file = jsontools.load_json(open(file_settings, "rb").read()) if isinstance(dict_file, dict) and 'settings' in dict_file: dict_settings = dict_file['settings'] except EnvironmentError: logger.error("ERROR al leer el archivo: %s" % file_settings) else: # logger.info(channel.channel + " No tiene archivo _data.json") channeljson_exists = False if channeljson_exists == True: try: datajson_size = filetools.getsize(file_settings) except: import traceback logger.error(channel.title + " | Detalle del error: %s" % traceback.format_exc()) else: datajson_size = None # Si el _data.json esta vacio o no existe... if (len(dict_settings) and datajson_size) == 0 or channeljson_exists == False: # Obtenemos controles del archivo ../channels/channel.xml needsfix = True try: # Se cargan los ajustes por defecto list_controls, default_settings = channeltools.get_channel_controls_settings(channel.channel) # logger.info(channel.title + " | Default: %s" % default_settings) except: import traceback logger.error(channel.title + " | Detalle del error: %s" % traceback.format_exc()) # default_settings = {} # Si _data.json necesita ser reparado o no existe... if needsfix == True or channeljson_exists == False: if default_settings is not None: # Creamos el channel_data.json default_settings.update(dict_settings) dict_settings = default_settings dict_file['settings'] = dict_settings # Creamos el archivo ../settings/channel_data.json json_data = jsontools.dump_json(dict_file) try: open(file_settings, "wb").write(json_data) # logger.info(channel.channel + " - Archivo _data.json GUARDADO!") # El channel_data.json se ha creado/modificado list_status = " - [COLOR red] CORREGIDO!![/COLOR]" except EnvironmentError: logger.error("ERROR al salvar el archivo: %s" % file_settings) else: if default_settings is None: list_status = " - [COLOR red] Imposible cargar los ajustes por defecto![/COLOR]" else: # logger.info(channel.channel + " - NO necesita correccion!") needsfix = False # Si se ha establecido el estado del canal se añade a la lista if needsfix is not None: if needsfix == True: if channeljson_exists == False: list_status = " - Ajustes creados" list_colour = "red" else: list_status = " - No necesita corrección" list_colour = "green" else: # Si "needsfix" es "false" y "datjson_size" es None habra # ocurrido algun error if datajson_size is None: list_status = " - Ha ocurrido algun error" list_colour = "red" else: list_status = " - No necesita corrección" list_colour = "green" if list_status is not None: itemlist.append(Item(channel=CHANNELNAME, title=channel.title + list_status, action="", folder=False, thumbnail=channel.thumbnail, text_color=list_colour)) else: logger.error("Algo va mal con el canal %s" % channel.channel) # Si el canal esta en la lista de exclusiones lo saltamos else: continue except: import traceback logger.error("Error: %s" % traceback.format_exc()) return itemlist
def setting_channel_new(item): import xbmcgui # Cargar lista de opciones (canales activos del usuario y que permitan búsqueda global) # ------------------------ lista = [] ids = [] lista_lang = [] lista_ctgs = [] channels_list = channelselector.filterchannels('all') for channel in channels_list: if channel.action == '': continue channel_parameters = channeltools.get_channel_parameters( channel.channel) # No incluir si en la configuracion del canal no existe "include_in_global_search" if not channel_parameters['include_in_global_search']: continue lbl = '%s' % channel_parameters['language'] lbl += ' %s' % ', '.join( config.get_localized_category(categ) for categ in channel_parameters['categories']) it = xbmcgui.ListItem(channel.title, lbl) it.setArt({'thumb': channel.thumbnail, 'fanart': channel.fanart}) lista.append(it) ids.append(channel.channel) lista_lang.append(channel_parameters['language']) lista_ctgs.append(channel_parameters['categories']) # Diálogo para pre-seleccionar # ---------------------------- preselecciones = [ 'Buscar con la selección actual', 'Modificar selección actual', 'Modificar partiendo de Recomendados', 'Modificar partiendo de Frecuentes', 'Modificar partiendo de Todos', 'Modificar partiendo de Ninguno', 'Modificar partiendo de Castellano', 'Modificar partiendo de Latino' ] presel_values = [ 'skip', 'actual', 'recom', 'freq', 'all', 'none', 'cast', 'lat' ] categs = [ 'movie', 'tvshow', 'documentary', 'anime', 'vos', 'direct', 'torrent' ] if config.get_setting('adult_mode') > 0: categs.append('adult') for c in categs: preselecciones.append('Modificar partiendo de %s' % config.get_localized_category(c)) presel_values.append(c) if item.action == 'setting_channel': # Configuración de los canales incluídos en la búsqueda del preselecciones[0] del presel_values[0] # else: # Llamada desde "buscar en otros canales" (se puede saltar la selección e ir directo a la búsqueda) ret = platformtools.dialog_select(config.get_localized_string(59994), preselecciones) if ret == -1: return False # pedido cancel if presel_values[ret] == 'skip': return True # continuar sin modificar elif presel_values[ret] == 'none': preselect = [] elif presel_values[ret] == 'all': preselect = range(len(ids)) elif presel_values[ret] in ['cast', 'lat']: preselect = [] for i, lg in enumerate(lista_lang): if presel_values[ret] in lg or '*' in lg: preselect.append(i) elif presel_values[ret] == 'actual': preselect = [] for i, canal in enumerate(ids): channel_status = config.get_setting('include_in_global_search', canal) if channel_status: preselect.append(i) elif presel_values[ret] == 'recom': preselect = [] for i, canal in enumerate(ids): _not, set_canal_list = channeltools.get_channel_controls_settings( canal) if set_canal_list.get('include_in_global_search', False): preselect.append(i) elif presel_values[ret] == 'freq': preselect = [] for i, canal in enumerate(ids): frequency = channeltools.get_channel_setting('frequency', canal, 0) if frequency > 0: preselect.append(i) else: preselect = [] for i, ctgs in enumerate(lista_ctgs): if presel_values[ret] in ctgs: preselect.append(i) # Diálogo para seleccionar # ------------------------ ret = xbmcgui.Dialog().multiselect(config.get_localized_string(59994), lista, preselect=preselect, useDetails=True) if not ret: return False # pedido cancel seleccionados = [ids[i] for i in ret] # Guardar cambios en canales para la búsqueda # ------------------------------------------- for canal in ids: channel_status = config.get_setting('include_in_global_search', canal) # if not channel_status: # channel_status = True if channel_status and canal not in seleccionados: config.set_setting('include_in_global_search', False, canal) elif not channel_status and canal in seleccionados: config.set_setting('include_in_global_search', True, canal) return True
def setting_channel_new(item): import xbmcgui # Load list of options (active user channels that allow global search) lista = [] ids = [] lista_lang = [] lista_ctgs = [] channels_list = channelselector.filterchannels('all') for channel in channels_list: if channel.action == '': continue channel_parameters = channeltools.get_channel_parameters(channel.channel) # Do not include if "include_in_global_search" does not exist in the channel configuration if not channel_parameters['include_in_global_search']: continue lbl = '%s' % channel_parameters['language'] lbl += ' %s' % ', '.join(config.get_localized_category(categ) for categ in channel_parameters['categories']) it = xbmcgui.ListItem(channel.title, lbl) it.setArt({'thumb': channel.thumbnail, 'fanart': channel.fanart}) lista.append(it) ids.append(channel.channel) lista_lang.append(channel_parameters['language']) lista_ctgs.append(channel_parameters['categories']) # Pre-select dialog preselecciones = [ config.get_localized_string(70570), config.get_localized_string(70571), # 'Modificar partiendo de Recomendados', # 'Modificar partiendo de Frecuentes', config.get_localized_string(70572), config.get_localized_string(70573), # 'Modificar partiendo de Castellano', # 'Modificar partiendo de Latino' ] # presel_values = ['skip', 'actual', 'recom', 'freq', 'all', 'none', 'cast', 'lat'] presel_values = ['skip', 'actual', 'all', 'none'] categs = ['movie', 'tvshow', 'documentary', 'anime', 'vos', 'direct', 'torrent'] for c in categs: preselecciones.append(config.get_localized_string(70577) + config.get_localized_category(c)) presel_values.append(c) if item.action == 'setting_channel': # Configuración de los canales incluídos en la búsqueda del preselecciones[0] del presel_values[0] # else: # Call from "search on other channels" (you can skip the selection and go directly to the search) ret = platformtools.dialog_select(config.get_localized_string(59994), preselecciones) if ret == -1: return False # order cancel if presel_values[ret] == 'skip': return True # continue unmodified elif presel_values[ret] == 'none': preselect = [] elif presel_values[ret] == 'all': preselect = list(range(len(ids))) elif presel_values[ret] in ['cast', 'lat']: preselect = [] for i, lg in enumerate(lista_lang): if presel_values[ret] in lg or '*' in lg: preselect.append(i) elif presel_values[ret] == 'actual': preselect = [] for i, canal in enumerate(ids): channel_status = config.get_setting('include_in_global_search', canal) if channel_status: preselect.append(i) elif presel_values[ret] == 'recom': preselect = [] for i, canal in enumerate(ids): _not, set_canal_list = channeltools.get_channel_controls_settings(canal) if set_canal_list.get('include_in_global_search', False): preselect.append(i) elif presel_values[ret] == 'freq': preselect = [] for i, canal in enumerate(ids): frequency = channeltools.get_channel_setting('frequency', canal, 0) if frequency > 0: preselect.append(i) else: preselect = [] for i, ctgs in enumerate(lista_ctgs): if presel_values[ret] in ctgs: preselect.append(i) # Dialog to select ret = platformtools.dialog_multiselect(config.get_localized_string(59994), lista, preselect=preselect, useDetails=True) if ret == None: return False # order cancel seleccionados = [ids[i] for i in ret] # Save changes to search channels for canal in ids: channel_status = config.get_setting('include_in_global_search', canal) # if not channel_status: # channel_status = True if channel_status and canal not in seleccionados: config.set_setting('include_in_global_search', False, canal) elif not channel_status and canal in seleccionados: config.set_setting('include_in_global_search', True, canal) return True
def show_channel_settings(self, list_controls=None, dict_values=None, caption="", callback=None, item=None, custom_button=None, channelpath=None): from core import config from core import channeltools import inspect if not os.path.isdir( os.path.join(config.get_data_path(), "settings_channels")): os.mkdir(os.path.join(config.get_data_path(), "settings_channels")) title = caption if type(custom_button) == dict: custom_button = { "label": custom_button.get("label", ""), "function": custom_button.get("function", ""), "visible": bool(custom_button.get("visible", True)), "close": bool(custom_button.get("close", False)) } else: custom_button = None #Obtenemos el canal desde donde se ha echo la llamada y cargamos los settings disponibles para ese canal if not channelpath: channelpath = inspect.currentframe( ).f_back.f_back.f_code.co_filename channelname = os.path.basename(channelpath).replace(".py", "") #Si no tenemos list_controls, hay que sacarlos del xml del canal if not list_controls: #Si la ruta del canal esta en la carpeta "channels", obtenemos los controles y valores mediante chaneltools if os.path.join(config.get_runtime_path(), "channels") in channelpath: # La llamada se hace desde un canal list_controls, default_values = channeltools.get_channel_controls_settings( channelname) #En caso contrario salimos else: return None #Si no se pasan dict_values, creamos un dict en blanco if dict_values == None: dict_values = {} #Ponemos el titulo if caption == "": caption = str(config.get_localized_string( 30100)) + " -- " + channelname.capitalize() elif caption.startswith('@') and unicode(caption[1:]).isnumeric(): caption = config.get_localized_string(int(caption[1:])) JsonData = {} JsonData["action"] = "OpenConfig" JsonData["data"] = {} JsonData["data"]["title"] = caption JsonData["data"]["custom_button"] = custom_button JsonData["data"]["items"] = [] # Añadir controles for c in list_controls: if not "default" in c: c["default"] = "" if not "color" in c: c["color"] = "auto" if not "label" in c: continue #Obtenemos el valor if not c["id"] in dict_values: if not callback: c["value"] = config.get_setting(c["id"], channelname) else: c["value"] = c["default"] # Translation if c['label'].startswith('@') and unicode( c['label'][1:]).isnumeric(): c['label'] = str(config.get_localized_string(c['label'][1:])) if c["label"].endswith(":"): c["label"] = c["label"][:-1] if c['type'] == 'list': lvalues = [] for li in c['lvalues']: if li.startswith('@') and unicode(li[1:]).isnumeric(): lvalues.append(str(config.get_localized_string( li[1:]))) else: lvalues.append(li) c['lvalues'] = lvalues JsonData["data"]["items"].append(c) ID = self.send_message(JsonData) close = False while True: data = self.get_data(ID) if type(data) == dict: JsonData["action"] = "HideLoading" JsonData["data"] = {} self.send_message(JsonData) for v in data: if data[v] == "true": data[v] = True if data[v] == "false": data[v] = False if unicode(data[v]).isnumeric(): data[v] = int(data[v]) if not callback: for v in data: config.set_setting(v, data[v], channelname) return None else: exec "from channels import " + channelname + " as cb_channel" exec "return_value = cb_channel." + callback + "(item, data)" return return_value elif data == "custom_button": try: cb_channel = __import__('channels.%s' % channelname, None, None, ["channels.%s" % channelname]) except ImportError: logger.error('Imposible importar %s' % channelname) else: return_value = getattr(cb_channel, custom_button['function'])(item) if custom_button["close"] == True: return return_value elif data == False: return None
def agrupa_datos(url, post=None, referer=True, json=False, proxy=True, forced_proxy=None, proxy_retries=1, force_check=False, force_login=True): global host, account if force_check or force_login: verify_login(force_check=force_check, force_login=force_login) headers = {'Referer': host} if 'episodes' in url or 'buscar' in url: headers['Referer'] += 'episodios' if not referer: headers.pop('Referer') # if cookie: # headers.update('Cookie:' 'language=es') if isinstance(referer, str): headers.update({'Referer': referer}) if host in host_blacklist: list_controls, dict_settings = channeltools.get_channel_controls_settings( "hdfull") config.set_setting("current_host", dict_settings['current_host'], channel="hdfull") host = dict_settings['current_host'] parsed = urlparse.urlparse(host) if len(parsed.path) > 1: parse_url = "https://%s/" % parsed.netloc config.set_setting("current_host", parse_url, channel="hdfull") url = re.sub(r'http(?:s|)://[^/]+/', host, url) page = httptools.downloadpage(url, post=post, headers=headers, ignore_response_code=True, proxy=proxy, forced_proxy=forced_proxy, proxy_retries=proxy_retries) if not page.sucess: list_controls, dict_settings = channeltools.get_channel_controls_settings( "hdfull") if dict_settings['current_host'] != config.get_setting( "current_host", channel="hdfull", default=""): config.set_setting("current_host", dict_settings['current_host'], channel="hdfull") host = dict_settings['current_host'] return agrupa_datos(url, post=post, referer=referer, json=json, proxy=True, forced_proxy='ProxyWeb', proxy_retries=0) if not page.sucess and not proxy: return agrupa_datos(url, post=post, referer=referer, json=json, proxy=True, forced_proxy='ProxyWeb', proxy_retries=0) if not page.sucess: account = False config.set_setting("logged", False, channel="hdfull") new_host = scrapertools.find_single_match( page.data, r'location.replace\("(http(?:s|)://\w+.hdfull.\w{2,4})') backup = scrapertools.find_single_match( page.data, r'onclick="redirect\(\)"><strong>(http[^<]+)') if not new_host and backup and 'dominio temporalmente' in page.data: new_host = backup if new_host: if not new_host.endswith('/'): new_host += '/' config.set_setting("current_host", new_host, channel="hdfull") url = re.sub(host, new_host, url) host = config.get_setting("current_host", channel="hdfull") return agrupa_datos(url, post=post, referer=referer, json=json) if json: return page.json # if raw: # return page.data data = page.data if PY3 and isinstance(data, bytes): data = "".join(chr(x) for x in bytes(data)) ## Agrupa los datos data = re.sub(r'\n|\r|\t| |<br>|<!--.*?-->', '', data) data = re.sub(r'\s+', ' ', data) data = re.sub(r'>\s<', '><', data) return data
def conf_tools(item): logger.info() # Activar/Desactivar canales if item.extra == "channels_onoff": import channelselector from core import channeltools from platformcode import platformtools channel_list = channelselector.filterchannels("allchannelstatus") channel_language = config.get_setting("channel_language") if channel_language == "": channel_language = "all" excluded_channels = ['tengourl', 'buscador', 'libreria', 'configuracion', 'novedades', 'personal', 'ayuda'] list_controls = [] try: list_controls.append({'id': "all_channels", 'type': "list", 'label': "Todos los canales", 'default': 0, 'enabled': True, 'visible': True, 'lvalues': ['', 'Activar todos', 'Desactivar todos', 'Establecer estado por defecto']}) for channel in channel_list: # Si el canal esta en la lista de exclusiones lo saltamos if channel.channel not in excluded_channels: # Se cargan los ajustes del archivo json del canal jsonchannel = channeltools.get_channel_json(channel.channel) if jsonchannel.get("settings") or jsonchannel.get("active"): channel_parameters = channeltools.get_channel_parameters(channel.channel) # No incluir 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 incluir si el canal es en un idioma filtrado if (channel_language != "all" and channel_parameters["language"] != channel_language): continue xml_status = None status = None xml_status = channel_parameters["active"] status_control = "" if config.get_setting("enabled", channel.channel): status = config.get_setting("enabled", channel.channel) # logger.info(channel.channel + " | Status: " + str(status)) else: status = xml_status # logger.info(channel.channel + " | Status (XML): " + str(status)) # Se establece el estado if status == "false" or status is False: status = False elif status == "true" or status is True: status = True if xml_status == "false": status_control = " [COLOR grey](Desactivado por defecto)[/COLOR]" if status is not None: control = {'id': channel.channel, 'type': "bool", 'label': channel_parameters["title"] + status_control, 'default': status, 'enabled': True, 'visible': True} list_controls.append(control) else: logger.info("Algo va mal con el canal " + channel.channel) else: continue return platformtools.show_channel_settings(list_controls=list_controls, caption="Activar/Desactivar canales", callback="channel_status") except: import traceback from platformcode import platformtools logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) platformtools.dialog_notification("Error", "Se ha producido un error con el canal" + channel.title) # Comprobacion de archivos channel_data.json elif item.extra == "lib_check_datajson": itemlist = [] import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") # Tener una lista de exclusion no tiene mucho sentido por que se comprueba si # el xml tiene "settings", pero por si acaso se deja excluded_channels = ['tengourl', 'configuracion', 'personal', 'ayuda'] try: import os from core import jsontools for channel in channel_list: needsfix = None list_status = None list_controls = None default_settings = None channeljson_exists = None # Se convierte el "channel.channel" del canal biblioteca para que no de error if channel.channel == "libreria": channel.channel = "biblioteca" # Se comprueba si el canal esta en la lista de exclusiones if channel.channel not in excluded_channels: # Se comprueba que tenga "settings", sino se salta jsonchannel = channeltools.get_channel_json(channel.channel) if not jsonchannel.get("settings"): itemlist.append(Item(channel=CHANNELNAME, title=channel.title + " - No tiene ajustes por defecto", action="", folder=False, thumbnail=channel.thumbnail)) continue # logger.info(channel.channel + " SALTADO!") # Se cargan los ajustes del archivo json del canal file_settings = os.path.join(config.get_data_path(), "settings_channels", channel.channel + "_data.json") dict_settings = {} dict_file = {} if filetools.exists(file_settings): # logger.info(channel.channel + " Tiene archivo _data.json") channeljson_exists = "true" # Obtenemos configuracion guardada de ../settings/channel_data.json try: dict_file = jsontools.load_json(open(file_settings, "rb").read()) if isinstance(dict_file, dict) and 'settings' in dict_file: dict_settings = dict_file['settings'] except EnvironmentError: logger.info("ERROR al leer el archivo: {0}".format(file_settings)) else: # logger.info(channel.channel + " No tiene archivo _data.json") channeljson_exists = "false" if channeljson_exists == "true": try: datajson_size = filetools.getsize(file_settings) except: import traceback logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) else: datajson_size = None # Si el _data.json esta vacio o no existe... if (len(dict_settings) and datajson_size) == 0 or channeljson_exists == "false": # Obtenemos controles del archivo ../channels/channel.xml needsfix = "true" try: # Se cargan los ajustes por defecto list_controls, default_settings = channeltools.get_channel_controls_settings(channel.channel) # logger.info(channel.title + " | Default: %s" % default_settings) except: import traceback logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) # default_settings = {} # Si _data.json necesita ser reparado o no existe... if needsfix == "true" or channeljson_exists == "false": if default_settings is not None: # Creamos el channel_data.json default_settings.update(dict_settings) dict_settings = default_settings dict_file['settings'] = dict_settings # Creamos el archivo ../settings/channel_data.json json_data = jsontools.dump_json(dict_file) try: open(file_settings, "wb").write(json_data) # logger.info(channel.channel + " - Archivo _data.json GUARDADO!") # El channel_data.json se ha creado/modificado list_status = " - [COLOR red] CORREGIDO!![/COLOR]" except EnvironmentError: logger.info("ERROR al salvar el archivo: {0}".format(file_settings)) else: if default_settings is None: list_status = " - [COLOR red] Imposible cargar los ajustes por defecto![/COLOR]" else: # logger.info(channel.channel + " - NO necesita correccion!") needsfix = "false" # Si se ha establecido el estado del canal se añade a la lista if needsfix is not None: if needsfix == "true": if channeljson_exists == "false": list_status = " - [COLOR red] Ajustes creados!![/COLOR]" else: list_status = " - [COLOR green] No necesita correccion[/COLOR]" else: # Si "needsfix" es "false" y "datjson_size" es None habra # ocurrido algun error if datajson_size is None: list_status = " - [COLOR red] Ha ocurrido algun error[/COLOR]" else: list_status = " - [COLOR green] No necesita correccion[/COLOR]" if list_status is not None: itemlist.append(Item(channel=CHANNELNAME, title=channel.title + list_status, action="", folder=False, thumbnail=channel.thumbnail)) else: logger.info("Algo va mal con el canal " + channel.channel) # Si el canal esta en la lista de exclusiones lo saltamos else: continue except: import traceback from platformcode import platformtools logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) platformtools.dialog_notification("Error", "Se ha producido un error con el canal" + channel.title) return itemlist else: from platformcode import platformtools platformtools.dialog_notification("pelisalacarta", "Error!") platformtools.itemlist_update(Item(channel=CHANNELNAME, action="submenu_tools"))
def show_channel_settings(self, list_controls=None, dict_values=None, caption="", callback=None, item=None, custom_button=None, channelpath=None): from platformcode import config from core import channeltools from core import servertools import inspect if not os.path.isdir( os.path.join(config.get_data_path(), "settings_channels")): os.mkdir(os.path.join(config.get_data_path(), "settings_channels")) title = caption if type(custom_button) == dict: custom_button = { "label": custom_button.get("label", ""), "function": custom_button.get("function", ""), "visible": bool(custom_button.get("visible", True)), "close": bool(custom_button.get("close", False)) } else: custom_button = None # Obtenemos el canal desde donde se ha echo la llamada y cargamos los settings disponibles para ese canal if not channelpath: channelpath = inspect.currentframe( ).f_back.f_back.f_code.co_filename channelname = os.path.basename(channelpath).split(".")[0] ch_type = os.path.basename(os.path.dirname(channelpath)) # Si no tenemos list_controls, hay que sacarlos del json del canal if not list_controls: # Si la ruta del canal esta en la carpeta "channels", obtenemos los controles y valores mediante chaneltools if os.path.join(config.get_runtime_path(), "channels") in channelpath: # La llamada se hace desde un canal list_controls, default_values = channeltools.get_channel_controls_settings( channelname) kwargs = {"channel": channelname} # Si la ruta del canal esta en la carpeta "servers", obtenemos los controles y valores mediante servertools elif os.path.join(config.get_runtime_path(), "servers") in channelpath: # La llamada se hace desde un server list_controls, default_values = servertools.get_server_controls_settings( channelname) kwargs = {"server": channelname} # En caso contrario salimos else: return None # Si no se pasan dict_values, creamos un dict en blanco if dict_values == None: dict_values = {} # Ponemos el titulo if caption == "": caption = str(config.get_localized_string( 30100)) + " -- " + channelname.capitalize() elif caption.startswith('@') and unicode(caption[1:]).isnumeric(): caption = config.get_localized_string(int(caption[1:])) JsonData = {} JsonData["action"] = "OpenConfig" JsonData["data"] = {} JsonData["data"]["title"] = self.kodi_labels_to_html(caption) JsonData["data"]["custom_button"] = custom_button JsonData["data"]["items"] = [] # Añadir controles for c in list_controls: if not "default" in c: c["default"] = "" if not "color" in c: c["color"] = "auto" if not "label" in c: continue # Obtenemos el valor if "id" in c: if not c["id"] in dict_values: if not callback: c["value"] = config.get_setting(c["id"], **kwargs) else: c["value"] = c["default"] dict_values[c["id"]] = c["value"] else: c["value"] = dict_values[c["id"]] # Translation if c['label'].startswith('@') and unicode( c['label'][1:]).isnumeric(): c['label'] = str(config.get_localized_string(c['label'][1:])) if c["label"].endswith(":"): c["label"] = c["label"][:-1] if c['type'] == 'list': lvalues = [] for li in c['lvalues']: if li.startswith('@') and unicode(li[1:]).isnumeric(): lvalues.append(str(config.get_localized_string( li[1:]))) else: lvalues.append(li) c['lvalues'] = lvalues c["label"] = self.kodi_labels_to_html(c["label"]) JsonData["data"]["items"].append(c) ID = self.send_message(JsonData) close = False while True: data = self.get_data(ID) if type(data) == dict: JsonData["action"] = "HideLoading" JsonData["data"] = {} self.send_message(JsonData) for v in data: if data[v] == "true": data[v] = True if data[v] == "false": data[v] = False if unicode(data[v]).isnumeric(): data[v] = int(data[v]) if callback and '.' in callback: package, callback = callback.rsplit('.', 1) else: package = '%s.%s' % (ch_type, channelname) cb_channel = None try: cb_channel = __import__(package, None, None, [package]) except ImportError: logger.error('Imposible importar %s' % package) if callback: # Si existe una funcion callback la invocamos ... return getattr(cb_channel, callback)(item, data) else: # si no, probamos si en el canal existe una funcion 'cb_validate_config' ... try: return getattr(cb_channel, 'cb_validate_config')(item, data) except AttributeError: # ... si tampoco existe 'cb_validate_config'... for v in data: config.set_setting(v, data[v], **kwargs) elif data == "custom_button": if '.' in callback: package, callback = callback.rsplit('.', 1) else: package = '%s.%s' % (ch_type, channelname) try: cb_channel = __import__(package, None, None, [package]) except ImportError: logger.error('Imposible importar %s' % package) else: return_value = getattr( cb_channel, custom_button['function'])(item, dict_values) if custom_button["close"] == True: return return_value else: JsonData["action"] = "custom_button" JsonData["data"] = {} JsonData["data"]["values"] = dict_values JsonData["data"]["return_value"] = return_value ID = self.send_message(JsonData) elif data == False: return None
def conf_tools(item): logger.info() # Activar o desactivar canales if item.extra == "channels_onoff": import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") channel_language = config.get_setting("channel_language") if channel_language == "": channel_language = "all" excluded_channels = ['tengourl', 'buscador', 'libreria', 'configuracion', 'novedades', 'personal', 'ayuda', 'descargas'] list_controls = [] try: list_controls.append({'id': "all_channels", 'type': "list", 'label': "Todos los canales", 'default': 0, 'enabled': True, 'visible': True, 'lvalues': ['', 'Activar todos', 'Desactivar todos', 'Establecer estado por defecto']}) for channel in channel_list: # Si el canal esta en la lista de exclusiones lo saltamos if channel.channel not in excluded_channels: # Se cargan los ajustes del archivo json del canal jsonchannel = channeltools.get_channel_json(channel.channel) if jsonchannel.get("settings") or jsonchannel.get("active"): channel_parameters = channeltools.get_channel_parameters(channel.channel) # No incluir si es un canal para adultos, y el modo adulto está desactivado if (channel_parameters["adult"] == "true" and config.get_setting("adult_mode") == "0"): continue # No incluir si el canal es en un idioma filtrado if (channel_language != "all" and channel_parameters["language"] != channel_language): continue status = None xml_status = channel_parameters["active"].replace("t", "T").replace("f", "F") xml_status = eval(xml_status) if config.get_setting("enabled", channel.channel): status = config.get_setting("enabled", channel.channel) status = status.replace("t", "T").replace("f", "F") status = eval(status) # logger.info(channel.channel + " | Status: " + str(status)) else: status = xml_status # logger.info(channel.channel + " | Status (XML): " + str(status)) status_control = "" if not xml_status: status_control = " [COLOR grey](Desactivado por defecto)[/COLOR]" if status is not None: control = {'id': channel.channel, 'type': "bool", 'label': channel_parameters["title"] + status_control, 'default': status, 'enabled': True, 'visible': True} list_controls.append(control) else: logger.info("Algo va mal con el canal " + channel.channel) else: continue return platformtools.show_channel_settings(list_controls=list_controls, caption="Canales", callback="channel_status", custom_button={"visible": False}) except: import traceback logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) platformtools.dialog_notification("Error", "Se ha producido un error con el canal %s" % channel.title) # Comprobacion de archivos channel_data.json elif item.extra == "lib_check_datajson": itemlist = [] import channelselector from core import channeltools channel_list = channelselector.filterchannels("allchannelstatus") # Tener una lista de exclusion no tiene mucho sentido por que se comprueba si # el xml tiene "settings", pero por si acaso se deja excluded_channels = ['tengourl', 'configuracion', 'personal', 'ayuda'] try: import os from core import jsontools for channel in channel_list: needsfix = None list_status = None list_controls = None default_settings = None channeljson_exists = None # Se convierte el "channel.channel" del canal biblioteca para que no de error if channel.channel == "libreria": channel.channel = "biblioteca" # Se comprueba si el canal esta en la lista de exclusiones if channel.channel not in excluded_channels: # Se comprueba que tenga "settings", sino se salta jsonchannel = channeltools.get_channel_json(channel.channel) if not jsonchannel.get("settings"): itemlist.append(Item(channel=CHANNELNAME, title=channel.title + " - No tiene ajustes por defecto", action="", folder=False, thumbnail=channel.thumbnail)) continue # logger.info(channel.channel + " SALTADO!") # Se cargan los ajustes del archivo json del canal file_settings = os.path.join(config.get_data_path(), "settings_channels", channel.channel + "_data.json") dict_settings = {} dict_file = {} if filetools.exists(file_settings): # logger.info(channel.channel + " Tiene archivo _data.json") channeljson_exists = "true" # Obtenemos configuracion guardada de ../settings/channel_data.json try: dict_file = jsontools.load_json(open(file_settings, "rb").read()) if isinstance(dict_file, dict) and 'settings' in dict_file: dict_settings = dict_file['settings'] except EnvironmentError: logger.info("ERROR al leer el archivo: %s" % file_settings) else: # logger.info(channel.channel + " No tiene archivo _data.json") channeljson_exists = "false" if channeljson_exists == "true": try: datajson_size = filetools.getsize(file_settings) except: import traceback logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) else: datajson_size = None # Si el _data.json esta vacio o no existe... if (len(dict_settings) and datajson_size) == 0 or channeljson_exists == "false": # Obtenemos controles del archivo ../channels/channel.xml needsfix = "true" try: # Se cargan los ajustes por defecto list_controls, default_settings = channeltools.get_channel_controls_settings(channel.channel) # logger.info(channel.title + " | Default: %s" % default_settings) except: import traceback logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) # default_settings = {} # Si _data.json necesita ser reparado o no existe... if needsfix == "true" or channeljson_exists == "false": if default_settings is not None: # Creamos el channel_data.json default_settings.update(dict_settings) dict_settings = default_settings dict_file['settings'] = dict_settings # Creamos el archivo ../settings/channel_data.json json_data = jsontools.dump_json(dict_file) try: open(file_settings, "wb").write(json_data) # logger.info(channel.channel + " - Archivo _data.json GUARDADO!") # El channel_data.json se ha creado/modificado list_status = " - [COLOR red] CORREGIDO!![/COLOR]" except EnvironmentError: logger.info("ERROR al salvar el archivo: %s" % file_settings) else: if default_settings is None: list_status = " - [COLOR red] Imposible cargar los ajustes por defecto![/COLOR]" else: # logger.info(channel.channel + " - NO necesita correccion!") needsfix = "false" # Si se ha establecido el estado del canal se añade a la lista if needsfix is not None: if needsfix == "true": if channeljson_exists == "false": list_status = " - Ajustes creados" list_colour = "red" else: list_status = " - No necesita correccion" list_colour = "green" else: # Si "needsfix" es "false" y "datjson_size" es None habra # ocurrido algun error if datajson_size is None: list_status = " - Ha ocurrido algun error" list_colour = "red" else: list_status = " - No necesita correccion" list_colour = "green" if list_status is not None: itemlist.append(Item(channel=CHANNELNAME, title=channel.title + list_status, action="", folder=False, thumbnail=channel.thumbnail, text_color=list_colour)) else: logger.info("Algo va mal con el canal %s" % channel.channel) # Si el canal esta en la lista de exclusiones lo saltamos else: continue except: import traceback logger.info(channel.title + " | Detalle del error: %s" % traceback.format_exc()) platformtools.dialog_notification("Error", "Se ha producido un error con el canal %s" % channel.title) return itemlist else: platformtools.dialog_notification("pelisalacarta", "Error!") platformtools.itemlist_update(Item(channel=CHANNELNAME, action="submenu_tools"))
def start(self, list_controls=None, dict_values=None, caption="", callback=None, item=None, custom_button=None, channelpath=None): log() # Media Path self.mediapath = os.path.join(config.get_runtime_path(), 'resources', 'skins', 'Default', 'media') # Params self.list_controls = list_controls self.values = dict_values self.caption = caption self.callback = callback self.item = item if isinstance(custom_button, dict): self.custom_button = {} self.custom_button["label"] = custom_button.get("label", "") self.custom_button["function"] = custom_button.get("function", "") self.custom_button["visible"] = bool( custom_button.get("visible", True)) self.custom_button["close"] = bool( custom_button.get("close", False)) else: self.custom_button = None # Load Channel Settings if not channelpath: channelpath = inspect.currentframe( ).f_back.f_back.f_code.co_filename self.channel = os.path.basename(channelpath).replace(".py", "") self.ch_type = os.path.basename(os.path.dirname(channelpath)) # If list_controls does not exist, it is removed from the channel json if not self.list_controls: # If the channel path is in the "channels" folder, we get the controls and values using chaneltools if os.path.join( config.get_runtime_path(), "channels") or os.path.join( config.get_runtime_path(), "specials") in channelpath: # The call is made from a channel self.list_controls, default_values = channeltools.get_channel_controls_settings( self.channel) self.kwargs = {"channel": self.channel} self.channelName = channeltools.get_channel_json( self.channel)['name'] # If the channel path is in the "servers" folder, we get the controls and values through servertools elif os.path.join(config.get_runtime_path(), "servers") in channelpath: # The call is made from a channel self.list_controls, default_values = servertools.get_server_controls_settings( self.channel) self.kwargs = {"server": self.channel} self.channelName = servertools.get_server_json( self.channel)['name'] # Else Exit else: return None # If dict_values are not passed, create a blank dict if self.values is None: self.values = {} # Make title if self.caption == "": self.caption = str( config.get_localized_string(30100)) + ' - ' + self.channelName matches = match(self.caption, patron=r'@(\d+)').matches if matches: for m in matches: self.caption = self.caption.replace( '@' + match, config.get_localized_string(int(m))) # Show Window self.return_value = None self.doModal() return self.return_value
def get_channel_setting(name, channel): """ Retorna el valor de configuracion del parametro solicitado. Devuelve el valor del parametro 'name' en la configuracion propia del canal 'channel'. Si se especifica el nombre del canal busca en la ruta \addon_data\plugin.video.pelisalacarta\settings_channels el archivo channel_data.json y lee el valor del parametro 'name'. Si el archivo channel_data.json no existe busca en la carpeta channels el archivo channel.xml y crea un archivo channel_data.json antes de retornar el valor solicitado. Parametros: name -- nombre del parametro channel [ -- nombre del canal Retorna: value -- El valor del parametro 'name' """ #Creamos la carpeta si no existe if not os.path.exists( os.path.join(config.get_data_path(), "settings_channels")): os.mkdir(os.path.join(config.get_data_path(), "settings_channels")) file_settings = os.path.join(config.get_data_path(), "settings_channels", channel + "_data.json") dict_settings = {} if os.path.exists(file_settings): # Obtenemos configuracion guardada de ../settings/channel_data.json try: dict_file = jsontools.load_json(open(file_settings, "r").read()) if isinstance(dict_file, dict) and dict_file.has_key('settings'): dict_settings = dict_file['settings'] except EnvironmentError: logger.info("ERROR al leer el archivo: {0}".format(file_settings)) if len(dict_settings) == 0 or not dict_settings.has_key(name): # Obtenemos controles del archivo ../channels/channel.xml from core import channeltools try: list_controls, default_settings = channeltools.get_channel_controls_settings( channel) except: default_settings = {} if default_settings.has_key( name ): # Si el parametro existe en el channel.xml creamos el channel_data.json default_settings.update(dict_settings) dict_settings = default_settings dict_file = {} dict_file['settings'] = dict_settings # Creamos el archivo ../settings/channel_data.json json_data = jsontools.dump_json(dict_file).encode("utf-8") try: open(file_settings, "w").write(json_data) except EnvironmentError: logger.info( "[config.py] ERROR al salvar el archivo: {0}".format( file_settings)) # Devolvemos el valor del parametro local 'name' si existe if dict_settings.has_key(name): return dict_settings[name] else: return None
def show_channel_settings(self, list_controls=None, dict_values=None, caption="", callback=None, item=None, custom_button=None, channelpath=None): from core import config from core import channeltools import inspect if not os.path.isdir(os.path.join(config.get_data_path(), "settings_channels")): os.mkdir(os.path.join(config.get_data_path(), "settings_channels")) title = caption if type(custom_button) == dict: custom_button = {"label" : custom_button.get("label", ""), "function" : custom_button.get("function", ""), "visible" : bool(custom_button.get("visible", True)), "close" : bool(custom_button.get("close", False))} else: custom_button = None #Obtenemos el canal desde donde se ha echo la llamada y cargamos los settings disponibles para ese canal if not channelpath: channelpath = inspect.currentframe().f_back.f_back.f_code.co_filename channelname = os.path.basename(channelpath).replace(".py", "") #Si no tenemos list_controls, hay que sacarlos del xml del canal if not list_controls: #Si la ruta del canal esta en la carpeta "channels", obtenemos los controles y valores mediante chaneltools if os.path.join(config.get_runtime_path(), "channels") in channelpath: # La llamada se hace desde un canal list_controls, default_values = channeltools.get_channel_controls_settings(channelname) #En caso contrario salimos else: return None #Si no se pasan dict_values, creamos un dict en blanco if dict_values == None: dict_values = {} #Ponemos el titulo if caption =="": caption = str(config.get_localized_string(30100)) + " -- " + channelname.capitalize() elif caption.startswith('@') and unicode(caption[1:]).isnumeric(): caption = config.get_localized_string(int(caption[1:])) JsonData = {} JsonData["action"]="OpenConfig" JsonData["data"]={} JsonData["data"]["title"]=caption JsonData["data"]["custom_button"]=custom_button JsonData["data"]["items"]=[] # Añadir controles for c in list_controls: if not "default" in c: c["default"] = "" if not "color" in c: c["color"] = "auto" if not "label" in c: continue #Obtenemos el valor if not c["id"] in dict_values: if not callback: c["value"]= config.get_setting(c["id"],channelname) else: c["value"] = c["default"] # Translation if c['label'].startswith('@') and unicode(c['label'][1:]).isnumeric(): c['label'] = str(config.get_localized_string(c['label'][1:])) if c["label"].endswith (":"): c["label"] = c["label"][:-1] if c['type'] == 'list': lvalues=[] for li in c['lvalues']: if li.startswith('@') and unicode(li[1:]).isnumeric(): lvalues.append(str(config.get_localized_string(li[1:]))) else: lvalues.append(li) c['lvalues'] = lvalues JsonData["data"]["items"].append(c) ID = self.send_message(JsonData) close = False while True: data = self.get_data(ID) if type(data) == dict: JsonData["action"]="HideLoading" JsonData["data"] = {} self.send_message(JsonData) for v in data: if data[v] == "true": data[v] = True if data[v] == "false": data[v] = False if unicode(data[v]).isnumeric(): data[v] = int(data[v]) if not callback: for v in data: config.set_setting(v,data[v],channelname) return None else: exec "from channels import " + channelname + " as cb_channel" exec "return_value = cb_channel." + callback + "(item, data)" return return_value elif data == "custom_button": try: cb_channel = __import__('channels.%s' % channelname, None, None, ["channels.%s" % channelname]) except ImportError: logger.error('Imposible importar %s' % channelname) else: return_value = getattr(cb_channel, custom_button['function'])(item) if custom_button["close"] == True: return return_value elif data == False: return None
def show_channel_settings(list_controls=None, dict_values=None, caption="", channelname="", callback=None, item=None): ''' Funcion que permite utilizar cuadros de configuracion personalizados. show_channel_settings(listado_controles, dict_values, caption, callback, item) Parametros: listado_controles: (list) Lista de controles a incluir en la ventana, segun el siguiente esquema: (opcional)list_controls= [ {'id': "nameControl1", 'type': "bool", # bool, text, list, label 'label': "Control 1: tipo RadioButton", 'color': '0xFFee66CC', # color del texto en formato ARGB hexadecimal 'default': True, 'enabled': True, 'visible': True }, {'id': "nameControl2", 'type': "text", # bool, text, list, label 'label': "Control 2: tipo Cuadro de texto", 'color': '0xFFee66CC', 'default': "Valor por defecto", 'hidden': False, # only for type = text Indica si hay que ocultar el texto (para passwords) 'enabled': True, 'visible': True }, {'id': "nameControl3", 'type': "list", # bool, text, list, label 'label': "Control 3: tipo Lista", 'color': '0xFFee66CC', 'default': 0, # Indice del valor por defecto en lvalues 'enabled': True, 'visible': True, 'lvalues':["item1", "item2", "item3", "item4"], # only for type = list }, {'id': "nameControl4", 'type': "label", # bool, text, list, label 'label': "Control 4: tipo Etiqueta", 'color': '0xFFee66CC', 'enabled': True, 'visible': True }] Si no se incluye el listado_controles, se intenta obtener del xml del canal desde donde se hace la llamada. El formato de los controles en el xml es: <?xml version="1.0" encoding="UTF-8" ?> <channel> ... ... <settings> <id>nameControl1</id> <type>bool</type> <label>Control 1: tipo RadioButton</label> <default>false</default> <enabled>true</enabled> <visible>true</visible> <color>0xFFee66CC</color> </settings> <settings> <id>nameControl2</id> <type>text</type> <label>Control 2: tipo Cuadro de texto</label> <default>Valor por defecto</default> <hidden>true</hidden> <enabled>true</enabled> <visible>true</visible> <color>0xFFee66CC</color> </settings> <settings> <id>nameControl3</id> <type>list</type> <label>Control 3: tipo Lista</label> <default>0</default> <enabled>true</enabled> <color>0xFFee66CC</color> <visible>true</visible> <lvalues>item1</lvalues> <lvalues>item2</lvalues> <lvalues>item3</lvalues> <lvalues>item4</lvalues> </settings> <settings> <id>nameControl4</id> <type>label</type> <label>Control 4: tipo Etiqueta</label> <enabled>true</enabled> <visible>true</visible> <color>0xFFee66CC</color> </settings> ... </channel> Los campos 'label', 'default' y 'lvalues' pueden ser un numero precedido de '@'. En cuyo caso se buscara el literal en el archivo string.xml del idioma seleccionado. Los campos 'enabled' y 'visible' admiten los comparadores eq(), gt() e it() y su funcionamiento se describe en: http://kodi.wiki/view/Add-on_settings#Different_types Por el momento en PLEX, tanto si quedan disabled, como no visible, los ocultamos (quitandolos del itemlist) Los campos hidden y color no tienen utilidad en PLEX (opcional)dict_values: (dict) Diccionario que representa el par (id: valor) de los controles de la lista. Si algun control de la lista no esta incluido en este diccionario se le asignara el valor por defecto. dict_values={"nameControl1": False, "nameControl2": "Esto es un ejemplo"} (opcional) caption: (str) Titulo de la ventana de configuracion. Se puede localizar mediante un numero precedido de '@' (opcional) callback (str) Nombre de la funcion, del canal desde el que se realiza la llamada, que sera invocada al pulsar el boton aceptar de la ventana. A esta funcion se le pasara como parametros el objeto 'item' y el dicionario 'dict_values' Retorno: Si se especifica 'callback' se devolvera lo que devuelva esta funcion. Si no devolvera None Ejemplos de uso: platformtools.show_channel_settings(): Así tal cual, sin pasar ningún argumento, la ventana detecta de que canal se ha hecho la llamada, y lee los ajustes del XML y carga los controles, cuando le das a Aceptar los vuelve a guardar. return platformtools.show_channel_settings(list_controls=list_controls, dict_values=dict_values, callback='cb', ítem=ítem): Así abre la ventana con los controles pasados y los valores de dict_values, si no se pasa dict_values, carga los valores por defecto de los controles, cuando le das a aceptar, llama a la función 'cb' del canal desde donde se ha llamado, pasando como parámetros, el ítem y el dict_values ''' logger.info("[plex_config_menu] show_channel_settings") global params itemlist = [] #Cuando venimos de hacer click en un control de la ventana, channelname ya se pasa como argumento, si no lo tenemos, detectamos de donde venimos if not channelname: channelpath = inspect.currentframe().f_back.f_back.f_code.co_filename channelname = os.path.basename(channelpath).replace(".py", "") #Si no tenemos list_controls, hay que sacarlos del xml del canal if not list_controls: #Si la ruta del canal esta en la carpeta "channels", obtenemos los controles y valores mediante chaneltools if os.path.join(config.get_runtime_path(), "channels") in channelpath: # La llamada se hace desde un canal list_controls, default_values = channeltools.get_channel_controls_settings( channelname) #En caso contrario salimos else: return itemlist #Si no se pasan dict_values, creamos un dict en blanco if dict_values == None: dict_values = {} #Ponemos el titulo if caption == "": caption = str(config.get_localized_string( "30100")) + " -- " + channelname.capitalize() elif caption.startswith('@') and unicode(caption[1:]).isnumeric(): caption = config.get_localized_string(int(caption[1:])) # Añadir controles for c in list_controls: #Obtenemos el valor if not c["id"] in dict_values: if not callback: dict_values[c["id"]] = config.get_setting(c["id"], channelname) else: if not 'default' in c: c["default"] = '' dict_values[c["id"]] = c["default"] # Translation if c['label'].startswith('@') and unicode(c['label'][1:]).isnumeric(): c['label'] = str(config.get_localized_string(c['label'][1:])) if c["label"].endswith(":"): c["label"] = c["label"][:-1] if c['type'] == 'list': lvalues = [] for li in c['lvalues']: if li.startswith('@') and unicode(li[1:]).isnumeric(): lvalues.append(str(config.get_localized_string(li[1:]))) else: lvalues.append(li) c['lvalues'] = lvalues #Tipos de controles if c['type'] == 'label': titulo = c["label"] itemlist.append( Item(channel=__channel__, action="control_label_click", title=titulo, extra=list_controls.index(c))) if c['type'] == 'bool': titulo = c["label"] + ":" + (' ' * 5) + ( "[X]" if dict_values[c["id"]] else "[ ]") itemlist.append( Item(channel=__channel__, action="control_bool_click", title=titulo, extra=list_controls.index(c))) elif c['type'] == 'list': titulo = c["label"] + ":" + (' ' * 5) + str( c["lvalues"][dict_values[c["id"]]]) itemlist.append( Item(channel=__channel__, action="control_list_click", title=titulo, extra=list_controls.index(c))) elif c['type'] == 'text': titulo = c["label"] + ":" + (' ' * 5) + str(dict_values[c["id"]]) item = Item(channel=__channel__, action="control_text_click", title=titulo, extra=list_controls.index(c)) item.type = "input" item.value = dict_values[c["id"]] itemlist.append(item) params = { "list_controls": list_controls, "dict_values": dict_values, "caption": caption, "channelname": channelname, "callback": callback, "item": item } if itemlist: #Creamos un itemlist nuevo añadiendo solo los items que han pasado la evaluacion evaluated = [] for x in range(len(list_controls)): #por el momento en PLEX, tanto si quedan disabled, como no visible, los ocultamos (quitandolos del itemlist) visible = evaluate(x, list_controls[x]["enabled"]) and evaluate( x, list_controls[x]["visible"]) if visible: evaluated.append(itemlist[x]) # Añadir Titulo evaluated.insert( 0, Item(channel=__channel__, action="control_label_click", title=caption)) # Añadir item aceptar y cancelar evaluated.append( Item(channel=__channel__, action="ok_Button_click", title="Aceptar")) evaluated.append( Item(channel=channelname, action="mainlist", title="Cancelar")) evaluated.append( Item(channel=__channel__, action="default_Button_click", title="Por defecto")) return evaluated
def show_channel_settings(list_controls=None, dict_values=None, caption="", callback=None,item=None, custom_button= None, channelpath= None): ''' Funcion que permite utilizar cuadros de configuracion personalizados. show_channel_settings(listado_controles, dict_values, caption, callback, item) Parametros: listado_controles: (list) Lista de controles a incluir en la ventana, segun el siguiente esquema: (opcional)list_controls= [ {'id': "nameControl1", 'type': "bool", # bool, text, list, label 'label': "Control 1: tipo RadioButton", 'color': '0xFFee66CC', # color del texto en formato ARGB hexadecimal 'default': True, 'enabled': True, 'visible': True }, {'id': "nameControl2", 'type': "text", # bool, text, list, label 'label': "Control 2: tipo Cuadro de texto", 'color': '0xFFee66CC', 'default': "Valor por defecto", 'hidden': False, # only for type = text Indica si hay que ocultar el texto (para passwords) 'enabled': True, 'visible': True }, {'id': "nameControl3", 'type': "list", # bool, text, list, label 'label': "Control 3: tipo Lista", 'color': '0xFFee66CC', 'default': 0, # Indice del valor por defecto en lvalues 'enabled': True, 'visible': True, 'lvalues':["item1", "item2", "item3", "item4"], # only for type = list }, {'id': "nameControl4", 'type': "label", # bool, text, list, label 'label': "Control 4: tipo Etiqueta", 'color': '0xFFee66CC', 'enabled': True, 'visible': True }] Si no se incluye el listado_controles, se intenta obtener del xml del canal desde donde se hace la llamada. El formato de los controles en el xml es: <?xml version="1.0" encoding="UTF-8" ?> <channel> ... ... <settings> <id>nameControl1</id> <type>bool</type> <label>Control 1: tipo RadioButton</label> <default>false</default> <enabled>true</enabled> <visible>true</visible> <color>0xFFee66CC</color> </settings> <settings> <id>nameControl2</id> <type>text</type> <label>Control 2: tipo Cuadro de texto</label> <default>Valor por defecto</default> <hidden>true</hidden> <enabled>true</enabled> <visible>true</visible> <color>0xFFee66CC</color> </settings> <settings> <id>nameControl3</id> <type>list</type> <label>Control 3: tipo Lista</label> <default>0</default> <enabled>true</enabled> <color>0xFFee66CC</color> <visible>true</visible> <lvalues>item1</lvalues> <lvalues>item2</lvalues> <lvalues>item3</lvalues> <lvalues>item4</lvalues> </settings> <settings> <id>nameControl4</id> <type>label</type> <label>Control 4: tipo Etiqueta</label> <enabled>true</enabled> <visible>true</visible> <color>0xFFee66CC</color> </settings> ... </channel> Los campos 'label', 'default' y 'lvalues' pueden ser un numero precedido de '@'. En cuyo caso se buscara el literal en el archivo string.xml del idioma seleccionado. Los campos 'enabled' y 'visible' admiten los comparadores eq(), gt() e it() y su funcionamiento se describe en: http://kodi.wiki/view/Add-on_settings#Different_types Por el momento en PLEX, tanto si quedan disabled, como no visible, los ocultamos (quitandolos del itemlist) Los campos hidden y color no tienen utilidad en PLEX (opcional)dict_values: (dict) Diccionario que representa el par (id: valor) de los controles de la lista. Si algun control de la lista no esta incluido en este diccionario se le asignara el valor por defecto. dict_values={"nameControl1": False, "nameControl2": "Esto es un ejemplo"} (opcional) caption: (str) Titulo de la ventana de configuracion. Se puede localizar mediante un numero precedido de '@' (opcional) callback (str) Nombre de la funcion, del canal desde el que se realiza la llamada, que sera invocada al pulsar el boton aceptar de la ventana. A esta funcion se le pasara como parametros el objeto 'item' y el dicionario 'dict_values' Retorno: Si se especifica 'callback' se devolvera lo que devuelva esta funcion. Si no devolvera None Ejemplos de uso: platformtools.show_channel_settings(): Así tal cual, sin pasar ningún argumento, la ventana detecta de que canal se ha hecho la llamada, y lee los ajustes del XML y carga los controles, cuando le das a Aceptar los vuelve a guardar. return platformtools.show_channel_settings(list_controls=list_controls, dict_values=dict_values, callback='cb', ítem=ítem): Así abre la ventana con los controles pasados y los valores de dict_values, si no se pasa dict_values, carga los valores por defecto de los controles, cuando le das a aceptar, llama a la función 'cb' del canal desde donde se ha llamado, pasando como parámetros, el ítem y el dict_values ''' logger.info("[plex_config_menu] show_channel_settings") global params itemlist = [] #Cuando venimos de hacer click en un control de la ventana, channelname ya se pasa como argumento, si no lo tenemos, detectamos de donde venimos if not channelpath: channelpath = inspect.currentframe().f_back.f_back.f_code.co_filename channelname = os.path.basename(channelpath).replace(".py", "") #Si no tenemos list_controls, hay que sacarlos del xml del canal if not list_controls: #Si la ruta del canal esta en la carpeta "channels", obtenemos los controles y valores mediante chaneltools if os.path.join(config.get_runtime_path(), "channels") in channelpath: # La llamada se hace desde un canal list_controls, default_values = channeltools.get_channel_controls_settings(channelname) #En caso contrario salimos else: return itemlist #Si no se pasan dict_values, creamos un dict en blanco if dict_values == None: dict_values = {} if type(custom_button) == dict: custom_button = {"label" : custom_button.get("label", ""), "function" : custom_button.get("function", ""), "visible" : bool(custom_button.get("visible", True)), "close" : bool(custom_button.get("close", False))} else: custom_button = None #Ponemos el titulo if caption =="": caption = str(config.get_localized_string("30100")) + " -- " + channelname.capitalize() elif caption.startswith('@') and unicode(caption[1:]).isnumeric(): caption = config.get_localized_string(int(caption[1:])) # Añadir controles for c in list_controls: #Obtenemos el valor if not c["id"] in dict_values: if not callback: dict_values[c["id"]]= config.get_setting(c["id"],channelname) else: if not 'default' in c: c["default"] = '' dict_values[c["id"]] = c["default"] # Translation if c['label'].startswith('@') and unicode(c['label'][1:]).isnumeric(): c['label'] = str(config.get_localized_string(c['label'][1:])) if c["label"].endswith (":"): c["label"] = c["label"][:-1] if c['type'] == 'list': lvalues=[] for li in c['lvalues']: if li.startswith('@') and unicode(li[1:]).isnumeric(): lvalues.append(str(config.get_localized_string(li[1:]))) else: lvalues.append(li) c['lvalues'] = lvalues #Tipos de controles if c['type'] == 'label': titulo = c["label"] itemlist.append(Item(channel=__channel__, action="control_label_click", title=titulo, extra=list_controls.index(c))) if c['type'] == 'bool': titulo = c["label"] + ":" + (' ' * 5) + ("[X]" if dict_values[c["id"]] else "[ ]") itemlist.append(Item(channel=__channel__, action="control_bool_click", title=titulo, extra=list_controls.index(c))) elif c['type'] == 'list': titulo = c["label"] + ":" + (' ' * 5) + str(c["lvalues"][dict_values[c["id"]]]) itemlist.append(Item(channel=__channel__, action="control_list_click", title=titulo, extra=list_controls.index(c))) elif c['type'] == 'text': titulo = c["label"] + ":" + (' ' * 5) + str(dict_values[c["id"]]) item= Item(channel=__channel__, action="control_text_click", title=titulo, extra=list_controls.index(c)) item.type = "input" item.value = dict_values[c["id"]] itemlist.append(item) params = {"list_controls":list_controls, "dict_values":dict_values, "caption":caption, "channelpath":channelpath, "callback":callback, "item":item, "custom_button": custom_button} if itemlist: #Creamos un itemlist nuevo añadiendo solo los items que han pasado la evaluacion evaluated = [] for x in range(len(list_controls)): #por el momento en PLEX, tanto si quedan disabled, como no visible, los ocultamos (quitandolos del itemlist) visible = evaluate(x, list_controls[x]["enabled"]) and evaluate(x, list_controls[x]["visible"]) if visible: evaluated.append(itemlist[x]) # Añadir Titulo evaluated.insert(0,Item(channel=__channel__, action="control_label_click", title=caption)) # Añadir item aceptar y cancelar evaluated.append(Item(channel=__channel__, action="ok_Button_click", title="Aceptar")) evaluated.append(Item(channel=channelname, action="mainlist", title="Cancelar")) if custom_button is None: evaluated.append(Item(channel=__channel__, action="default_Button_click", title="Por defecto")) else: if custom_button['visible'] == True: evaluated.append(Item(channel=__channel__, action="default_Button_click", title=custom_button["label"])) return evaluated