349 lines
16 KiB
Python
349 lines
16 KiB
Python
# -*- coding: utf-8 -*-
|
|
# ------------------------------------------------------------
|
|
# channeltools - Tools for working with channels
|
|
# ------------------------------------------------------------
|
|
|
|
from __future__ import absolute_import
|
|
|
|
from core import jsontools
|
|
from platformcode import config, logger
|
|
|
|
DEFAULT_UPDATE_URL = "/channels/"
|
|
dict_channels_parameters = dict()
|
|
default_file = dict()
|
|
|
|
remote_path = 'https://raw.githubusercontent.com/kodiondemand/media/master/'
|
|
|
|
def is_enabled(channel_name):
|
|
logger.debug("channel_name=" + channel_name)
|
|
return get_channel_parameters(channel_name)["active"] and getChannelSetting("enabled", channel=channel_name, default=True)
|
|
|
|
|
|
def get_channel_parameters(channel_name):
|
|
from core import filetools
|
|
global dict_channels_parameters
|
|
|
|
if channel_name not in dict_channels_parameters:
|
|
try:
|
|
channel_parameters = get_channel_json(channel_name)
|
|
logger.debug(channel_parameters)
|
|
if channel_parameters:
|
|
# name and default changes
|
|
channel_parameters["title"] = channel_parameters.pop("name") + (' [DEPRECATED]' if 'deprecated' in channel_parameters and channel_parameters['deprecated'] else '')
|
|
channel_parameters["channel"] = channel_parameters.pop("id")
|
|
|
|
# if the key does not exist, they are declared a default value so that there are no failures in the functions that call it
|
|
channel_parameters["update_url"] = channel_parameters.get("update_url", DEFAULT_UPDATE_URL)
|
|
channel_parameters["language"] = channel_parameters.get("language", ["all"])
|
|
channel_parameters["active"] = channel_parameters.get("active", False)
|
|
channel_parameters["include_in_global_search"] = channel_parameters.get("include_in_global_search", False)
|
|
channel_parameters["categories"] = channel_parameters.get("categories", list())
|
|
|
|
channel_parameters["thumbnail"] = channel_parameters.get("thumbnail", "")
|
|
channel_parameters["banner"] = channel_parameters.get("banner", "")
|
|
channel_parameters["fanart"] = channel_parameters.get("fanart", "")
|
|
|
|
# Images: url and local files are allowed inside "resources / images"
|
|
if channel_parameters.get("thumbnail") and "://" not in channel_parameters["thumbnail"]:
|
|
channel_parameters["thumbnail"] = filetools.join(remote_path, "resources", "thumb", channel_parameters["thumbnail"])
|
|
if channel_parameters.get("banner") and "://" not in channel_parameters["banner"]:
|
|
channel_parameters["banner"] = filetools.join(remote_path, "resources", "banner", channel_parameters["banner"])
|
|
if channel_parameters.get("fanart") and "://" not in channel_parameters["fanart"]:
|
|
channel_parameters["fanart"] = filetools.join(remote_path, "resources", channel_parameters["fanart"])
|
|
|
|
# We obtain if the channel has configuration options
|
|
channel_parameters["has_settings"] = False
|
|
if 'settings' in channel_parameters:
|
|
channel_parameters['settings'] = get_default_settings(channel_name)
|
|
for s in channel_parameters['settings']:
|
|
if 'id' in s:
|
|
if s['id'] == "include_in_global_search":
|
|
channel_parameters["include_in_global_search"] = True
|
|
elif s['id'] == "filter_languages":
|
|
channel_parameters["filter_languages"] = s.get('lvalues', [])
|
|
elif s['id'].startswith("include_in_"):
|
|
channel_parameters["has_settings"] = True
|
|
|
|
del channel_parameters['settings']
|
|
|
|
dict_channels_parameters[channel_name] = channel_parameters
|
|
|
|
else:
|
|
# To avoid cases where channels are not defined as configuration, we throw the exception and thus we have the basic values
|
|
raise Exception
|
|
|
|
except Exception as ex:
|
|
logger.error(channel_name + ".json error \n%s" % ex)
|
|
channel_parameters = dict()
|
|
channel_parameters["channel"] = ""
|
|
channel_parameters['active'] = False
|
|
channel_parameters["language"] = ""
|
|
channel_parameters["update_url"] = DEFAULT_UPDATE_URL
|
|
return channel_parameters
|
|
|
|
return dict_channels_parameters[channel_name]
|
|
|
|
|
|
def get_channel_json(channel_name):
|
|
logger.debug("channel_name=" + channel_name)
|
|
from core import filetools
|
|
channel_json = None
|
|
try:
|
|
channel_path = filetools.join(config.getRuntimePath(), "channels", channel_name + ".json")
|
|
if not filetools.isfile(channel_path):
|
|
channel_path = filetools.join(config.getRuntimePath(), "specials", channel_name + ".json")
|
|
if not filetools.isfile(channel_path):
|
|
channel_path = filetools.join(config.getRuntimePath(), "servers", channel_name + ".json")
|
|
if not filetools.isfile(channel_path):
|
|
channel_path = filetools.join(config.getRuntimePath(), "servers", "debriders",
|
|
channel_name + ".json")
|
|
|
|
if filetools.isfile(channel_path):
|
|
logger.debug("channel_data=" + channel_path)
|
|
channel_json = jsontools.load(filetools.read(channel_path))
|
|
logger.debug("channel_json= %s" % channel_json)
|
|
|
|
except Exception as ex:
|
|
template = "An exception of type %s occured. Arguments:\n%r"
|
|
message = template % (type(ex).__name__, ex.args)
|
|
logger.error("{} | {}".format(channel_name,message))
|
|
|
|
return channel_json
|
|
|
|
|
|
def get_channel_controls_settings(channel_name):
|
|
logger.debug("channel_name=" + channel_name)
|
|
dict_settings = {}
|
|
|
|
list_controls = get_default_settings(channel_name)
|
|
|
|
for c in list_controls:
|
|
if 'id' not in c or 'type' not in c or 'default' not in c:
|
|
# If any control in the list does not have id, type or default, we ignore it
|
|
continue
|
|
# new dict with key(id) and value(default) from settings
|
|
if c['type'] == 'list' and c.get('values'):
|
|
dict_settings[c['id']] = list(c['values'])[c['default']]
|
|
elif c['type'] == 'list' and c.get('dvalues'):
|
|
dict_settings[c['id']] = list(c['dvalues'].values())[c['default']]
|
|
else:
|
|
dict_settings[c['id']] = c['default']
|
|
|
|
return list_controls, dict_settings
|
|
|
|
|
|
def get_lang(channel_name):
|
|
channel = __import__('channels.%s' % channel_name, fromlist=["channels.%s" % channel_name])
|
|
list_language = [config.getLocalizedString(70522)]
|
|
if hasattr(channel, 'list_language'):
|
|
for language in channel.list_language:
|
|
list_language.append(language)
|
|
logger.debug(list_language)
|
|
else:
|
|
sub = False
|
|
langs = []
|
|
language = get_channel_json(channel_name).get('language', list())
|
|
for lang in language:
|
|
if 'vos' not in lang:
|
|
langs.append(lang.upper())
|
|
else:
|
|
sub = True
|
|
if sub == True:
|
|
for lang in langs:
|
|
list_language.append(lang)
|
|
list_language.append('Sub-' + lang)
|
|
else:
|
|
for lang in langs:
|
|
list_language.append(lang)
|
|
return list_language
|
|
|
|
|
|
def get_default_settings(channel_name):
|
|
from core import filetools
|
|
import copy
|
|
|
|
default_path = filetools.join(config.getRuntimePath(), 'default_channel_settings' + '.json')
|
|
if channel_name not in ['trakt', 'autoplay']:
|
|
global default_file
|
|
else:
|
|
default_file = {}
|
|
if not default_file:
|
|
default_file = jsontools.load(filetools.read(default_path))
|
|
|
|
channel_path = filetools.join(config.getRuntimePath(), 'channels', channel_name + '.json')
|
|
|
|
if filetools.exists(channel_path):
|
|
default_controls = default_file['settings']
|
|
default_controls_renumber = default_file['renumber']
|
|
channel_json = get_channel_json(channel_name)
|
|
|
|
# Collects configurations
|
|
channel_language = channel_json['language']
|
|
channel_controls = channel_json['settings']
|
|
categories = channel_json['categories']
|
|
not_active = channel_json['not_active'] if 'not_active' in channel_json else []
|
|
default_off = channel_json['default_off'] if 'default_off' in channel_json else []
|
|
|
|
# Apply default configurations if they do not exist
|
|
# logger.dbg()
|
|
for control in copy.deepcopy(default_controls):
|
|
if control['id'] not in str(channel_controls):
|
|
if 'include_in_newest' in control['id'] and 'include_in_newest' not in not_active and control['id'] not in not_active:
|
|
label = control['id'].split('_')
|
|
label = label[-1]
|
|
if label == 'movie':
|
|
if 'movie' in categories:
|
|
control['label'] = config.getLocalizedString(70727) + ' - ' + config.getLocalizedString( 30122)
|
|
control['default'] = False if ('include_in_newest' in default_off) or ( ' include_in_newest_movie' in default_off) else True
|
|
channel_controls.append(control)
|
|
else:
|
|
pass
|
|
elif label == 'tvshow':
|
|
if 'tvshow' in categories:
|
|
control['label'] = config.getLocalizedString(70727) + ' - ' + config.getLocalizedString( 30123)
|
|
control['default'] = False if ('include_in_newest' in default_off) or ( 'include_in_newest_tvshow' in default_off) else True
|
|
channel_controls.append(control)
|
|
else:
|
|
pass
|
|
elif label == 'anime':
|
|
if 'anime' in categories:
|
|
control['label'] = config.getLocalizedString(70727) + ' - ' + config.getLocalizedString( 30124)
|
|
control['default'] = False if ('include_in_newest' in default_off) or ( 'include_in_newest_anime' in default_off) else True
|
|
channel_controls.append(control)
|
|
else:
|
|
pass
|
|
|
|
else:
|
|
control['label'] = config.getLocalizedString(70727) + ' - ' + label.capitalize()
|
|
control['default'] = control['default'] if control['id'] not in default_off else False
|
|
channel_controls.append(control)
|
|
|
|
elif control['id'] not in not_active and 'include_in_newest' not in control['id']:
|
|
if type(control['default']) == bool:
|
|
control['default'] = control['default'] if control['id'] not in default_off else False
|
|
channel_controls.append(control)
|
|
|
|
if 'anime' in categories:
|
|
for control in default_controls_renumber:
|
|
if control['id'] not in str(channel_controls):
|
|
channel_controls.append(control)
|
|
else:
|
|
pass
|
|
else:
|
|
return get_channel_json(channel_name).get('settings', list())
|
|
return channel_controls
|
|
|
|
|
|
def getChannelSetting(name, channel, default=None):
|
|
from core import filetools
|
|
"""
|
|
Returns the configuration value of the requested parameter.
|
|
|
|
Returns the value of the parameter 'name' in the own configuration of the channel 'channel'.
|
|
|
|
Look in the path \addon_data\plugin.video.kod\settings_channels for the file channel_data.json and read
|
|
the value of the parameter 'name'. If the file channel_data.json does not exist look in the channels folder for the file
|
|
channel.json and create a channel_data.json file before returning the requested value. If the parameter 'name'
|
|
also does not exist in the channel.json file the default parameter is returned.
|
|
|
|
|
|
@param name: parameter name
|
|
@type name: str
|
|
@param channel: channel name
|
|
@type channel: str
|
|
@param default: return value in case the name parameter does not exist
|
|
@type default: any
|
|
|
|
@return: The value of the parameter 'name'
|
|
@rtype: any
|
|
|
|
"""
|
|
file_settings = filetools.join(config.getDataPath(), "settings_channels", channel + "_data.json")
|
|
dict_settings = {}
|
|
dict_file = {}
|
|
|
|
if filetools.exists(file_settings):
|
|
# We get saved configuration from ../settings/channel_data.json
|
|
try:
|
|
dict_file = jsontools.load(filetools.read(file_settings))
|
|
if isinstance(dict_file, dict) and 'settings' in dict_file:
|
|
dict_settings = dict_file['settings']
|
|
except EnvironmentError:
|
|
logger.error("ERROR when reading the file: %s" % file_settings)
|
|
|
|
if not dict_settings or name not in dict_settings:
|
|
# We get controls from the file ../channels/channel.json
|
|
try:
|
|
list_controls, default_settings = get_channel_controls_settings(channel)
|
|
except:
|
|
default_settings = {}
|
|
|
|
if name in default_settings: #If the parameter exists in the channel.json we create the channel_data.json
|
|
default_settings.update(dict_settings)
|
|
dict_settings = default_settings
|
|
dict_file['settings'] = dict_settings
|
|
# We create the file ../settings/channel_data.json
|
|
json_data = jsontools.dump(dict_file)
|
|
if not filetools.write(file_settings, json_data, silent=True):
|
|
logger.error("ERROR saving file: %s" % file_settings)
|
|
|
|
# We return the value of the local parameter 'name' if it exists, if default is not returned
|
|
return dict_settings.get(name, default)
|
|
|
|
|
|
def setChannelSetting(name, value, channel):
|
|
from core import filetools
|
|
"""
|
|
Sets the configuration value of the indicated parameter.
|
|
|
|
Set 'value' as the value of the parameter 'name' in the own configuration of the channel 'channel'.
|
|
Returns the changed value or None if the assignment could not be completed.
|
|
|
|
If the name of the channel is specified, search in the path \addon_data\plugin.video.kod\settings_channels the
|
|
channel_data.json file and set the parameter 'name' to the value indicated by 'value'.
|
|
If the parameter 'name' does not exist, it adds it, with its value, to the corresponding file.
|
|
|
|
@param name: parameter name
|
|
@type name: str
|
|
@param value: parameter value
|
|
@type value: str
|
|
@param channel: channel name
|
|
@type channel: str
|
|
|
|
@return: 'value' if the value could be set and None otherwise
|
|
@rtype: str, None
|
|
|
|
"""
|
|
# We create the folder if it does not exist
|
|
if not filetools.exists(filetools.join(config.getDataPath(), "settings_channels")):
|
|
filetools.mkdir(filetools.join(config.getDataPath(), "settings_channels"))
|
|
|
|
file_settings = filetools.join(config.getDataPath(), "settings_channels", channel + "_data.json")
|
|
dict_settings = {}
|
|
|
|
dict_file = None
|
|
|
|
if filetools.exists(file_settings):
|
|
# We get saved settings from ../settings/channel_data.json
|
|
try:
|
|
dict_file = jsontools.load(filetools.read(file_settings))
|
|
dict_settings = dict_file.get('settings', {})
|
|
except EnvironmentError:
|
|
logger.error("ERROR when reading the file: %s" % file_settings)
|
|
|
|
dict_settings[name] = value
|
|
|
|
# we check if dict_file exists and it is a dictionary, if not we create it
|
|
if dict_file is None or not dict_file:
|
|
dict_file = {}
|
|
|
|
dict_file['settings'] = dict_settings
|
|
|
|
# Creamos el archivo ../settings/channel_data.json
|
|
json_data = jsontools.dump(dict_file)
|
|
if not filetools.write(file_settings, json_data, silent=True):
|
|
logger.error("ERROR saving file: %s" % file_settings)
|
|
return None
|
|
|
|
return value
|