From c8b3cacf90715c0390c4a3fbf890dfb136bcae09 Mon Sep 17 00:00:00 2001 From: jurialmunkey Date: Sun, 12 Nov 2023 16:00:16 +1100 Subject: [PATCH] :sparkles: Allow skinvariables templates to addnfo with operations --- resources/lib/method.py | 139 ++---------------------- resources/lib/operations.py | 138 +++++++++++++++++++++++ resources/lib/skinshortcuts_template.py | 6 +- 3 files changed, 152 insertions(+), 131 deletions(-) create mode 100644 resources/lib/operations.py diff --git a/resources/lib/method.py b/resources/lib/method.py index a5acda4..087a780 100644 --- a/resources/lib/method.py +++ b/resources/lib/method.py @@ -14,7 +14,7 @@ class FileUtils(jurialmunkey.futils.FileUtils): boolean = jurialmunkey.parser.boolean -def _set_animation(animations): +def set_animation_list(animations): import xbmcgui win_id = xbmcgui.getCurrentWindowId() window = xbmcgui.Window(win_id) @@ -24,14 +24,14 @@ def _set_animation(animations): def set_animation(set_animation, **kwargs): - _set_animation([ + set_animation_list([ (control_id, event, effect,) for i in set_animation.split('||') for control_id, event, effect in i.split('|') ]) -def _run_executebuiltin(builtins): +def run_executebuiltin_list(builtins): import xbmc for builtin in builtins: if builtin.startswith('sleep='): @@ -44,7 +44,7 @@ def _run_executebuiltin(builtins): if builtin.startswith('animation='): animation = builtin[10:] control_id, event, effect = animation.split('|') - _set_animation([(control_id, event, effect, )]) + set_animation_list([(control_id, event, effect, )]) continue xbmc.executebuiltin(builtin) @@ -53,137 +53,16 @@ def run_executebuiltin(run_executebuiltin=None, use_rules=False, **kwargs): if not run_executebuiltin: return if not boolean(use_rules): - return _run_executebuiltin(run_executebuiltin.split('||')) + return run_executebuiltin_list(run_executebuiltin.split('||')) - import re - import xbmc from json import loads from jurialmunkey.futils import load_filecontent + from resources.lib.operations import RuleOperations meta = loads(str(load_filecontent(run_executebuiltin))) - - def _check_rules(rules): - result = True - for rule in rules: - # Rules can have sublists of rules - if isinstance(rule, list): - result = _check_rules(rule) - if not result: - continue - return True - rule = rule.format(**kwargs) - if not xbmc.getCondVisibility(rule): - return False - return result - - def _get_actions_list(rule_actions): - actions_list = [] - - if not isinstance(rule_actions, list): - rule_actions = [rule_actions] - - for action in rule_actions: - - # Parts are prefixed with percent % so needs to be replaced - if isinstance(action, str) and action.startswith('%'): - action = action.format(**kwargs) - action = meta['parts'][action[1:]] - - # Standard actions are strings - add formatted action to list and continue - if isinstance(action, str): - actions_list.append(action.format(**kwargs)) - continue - - # Sublists of actions are lists - recursively add sublists and continue - if isinstance(action, list): - actions_list += _get_actions_list(action) - continue - - # Rules are dictionaries - successful rules add their actions and stop iterating (like a skin variable) - if _check_rules(action['rules']): - actions_list += _get_actions_list(action['value']) - break - - return actions_list - - def _set_infolabels(d): - for k, v in d.items(): - k = k.format(**kwargs) - v = v.format(**kwargs) - kwargs[k] = xbmc.getInfoLabel(v) - - def _set_regex(d): - for k, v in d.items(): - k = k.format(**kwargs) - kwargs[k] = re.sub(v['regex'].format(**kwargs), v['value'].format(**kwargs), v['input'].format(**kwargs)) - - def _set_values(d): - for k, v in d.items(): - k = k.format(**kwargs) - kwargs[k] = _get_actions_list(v)[0] - - def _set_sums(d): - for k, v in d.items(): - k = k.format(**kwargs) - kwargs[k] = sum([int(i.format(**kwargs)) for i in v]) - - def _set_decode(d): - from urllib.parse import unquote_plus - for k, v in d.items(): - k = k.format(**kwargs) - v = v.format(**kwargs) - kwargs[k] = unquote_plus(v) - - def _set_encode(d): - from urllib.parse import quote_plus - for k, v in d.items(): - k = k.format(**kwargs) - v = v.format(**kwargs) - kwargs[k] = quote_plus(v) - - def _set_escape(d): - from xml.sax.saxutils import escape - for k, v in d.items(): - k = k.format(**kwargs) - v = v.format(**kwargs) - kwargs[k] = escape(v) - - def _set_lower(d): - for k, v in d.items(): - k = k.format(**kwargs) - kwargs[k] = v.format(**kwargs).lower() - - def _set_upper(d): - for k, v in d.items(): - k = k.format(**kwargs) - kwargs[k] = v.format(**kwargs).upper() - - def _set_capitalize(d): - for k, v in d.items(): - k = k.format(**kwargs) - kwargs[k] = v.format(**kwargs).capitalize() - - routes = { - 'infolabels': _set_infolabels, - 'regex': _set_regex, - 'values': _set_values, - 'sums': _set_sums, - 'decode': _set_decode, - 'encode': _set_encode, - 'escape': _set_escape, - 'lower': _set_lower, - 'upper': _set_upper, - 'capitalize': _set_capitalize, - } - - operations = [{i: meta[i]} for i in routes if i in meta] + meta.get('operations', []) - - for i in operations: - for k, v in i.items(): - routes[k](v) - - actions_list = _get_actions_list(meta['actions']) - return _run_executebuiltin(actions_list) + rule_operations = RuleOperations(meta, **kwargs) + actions_list = rule_operations.get_actions_list(rule_operations.meta['actions']) + return run_executebuiltin_list(actions_list) def get_paramstring_tuplepairs(paramstring): diff --git a/resources/lib/operations.py b/resources/lib/operations.py new file mode 100644 index 0000000..b4c7df9 --- /dev/null +++ b/resources/lib/operations.py @@ -0,0 +1,138 @@ +import re +import xbmc + + +class RuleOperations(): + def __init__(self, meta, **params): + self.meta = meta + self.params = params + self.run_operations() + + def run_operations(self): + for i in self.operations: + for k, v in i.items(): + self.routes[k](v) + + @property + def operations(self): + return [{i: self.meta[i]} for i in self.routes if i in self.meta] + self.meta.get('operations', []) + + @property + def routes(self): + try: + return self._routes + except AttributeError: + self._routes = { + 'infolabels': self.set_infolabels, + 'regex': self.set_regex, + 'values': self.set_values, + 'sums': self.set_sums, + 'decode': self.set_decode, + 'encode': self.set_encode, + 'escape': self.set_escape, + 'lower': self.set_lower, + 'upper': self.set_upper, + 'capitalize': self.set_capitalize, + } + return self._routes + + def set_infolabels(self, d): + for k, v in d.items(): + k = k.format(**self.params) + v = v.format(**self.params) + self.params[k] = xbmc.getInfoLabel(v) + + def set_regex(self, d): + for k, v in d.items(): + k = k.format(**self.params) + self.params[k] = re.sub(v['regex'].format(**self.params), v['value'].format(**self.params), v['input'].format(**self.params)) + + def set_values(self, d): + for k, v in d.items(): + k = k.format(**self.params) + self.params[k] = self.get_actions_list(v)[0] + + def set_sums(self, d): + for k, v in d.items(): + k = k.format(**self.params) + self.params[k] = sum([int(i.format(**self.params)) for i in v]) + + def set_decode(self, d): + from urllib.parse import unquote_plus + for k, v in d.items(): + k = k.format(**self.params) + v = v.format(**self.params) + self.params[k] = unquote_plus(v) + + def set_encode(self, d): + from urllib.parse import quote_plus + for k, v in d.items(): + k = k.format(**self.params) + v = v.format(**self.params) + self.params[k] = quote_plus(v) + + def set_escape(self, d): + from xml.sax.saxutils import escape + for k, v in d.items(): + k = k.format(**self.params) + v = v.format(**self.params) + self.params[k] = escape(v) + + def set_lower(self, d): + for k, v in d.items(): + k = k.format(**self.params) + self.params[k] = v.format(**self.params).lower() + + def set_upper(self, d): + for k, v in d.items(): + k = k.format(**self.params) + self.params[k] = v.format(**self.params).upper() + + def set_capitalize(self, d): + for k, v in d.items(): + k = k.format(**self.params) + self.params[k] = v.format(**self.params).capitalize() + + def check_rules(self, rules): + result = True + for rule in rules: + # Rules can have sublists of rules + if isinstance(rule, list): + result = self.check_rules(rule) + if not result: + continue + return True + rule = rule.format(**self.params) + if not xbmc.getCondVisibility(rule): + return False + return result + + def get_actions_list(self, rule_actions): + actions_list = [] + + if not isinstance(rule_actions, list): + rule_actions = [rule_actions] + + for action in rule_actions: + + # Parts are prefixed with percent % so needs to be replaced + if isinstance(action, str) and action.startswith('%'): + action = action.format(**self.params) + action = self.meta['parts'][action[1:]] + + # Standard actions are strings - add formatted action to list and continue + if isinstance(action, str): + actions_list.append(action.format(**self.params)) + continue + + # Sublists of actions are lists - recursively add sublists and continue + if isinstance(action, list): + actions_list += self.get_actions_list(action) + continue + + # Rules are dictionaries - successful rules add their actions and stop iterating (like a skin variable) + if self.check_rules(action['rules']): + actions_list += self.get_actions_list(action['value']) + break + + return actions_list diff --git a/resources/lib/skinshortcuts_template.py b/resources/lib/skinshortcuts_template.py index a1c864c..ec0dc40 100644 --- a/resources/lib/skinshortcuts_template.py +++ b/resources/lib/skinshortcuts_template.py @@ -64,7 +64,11 @@ def update_xml(self, force=False, no_reload=False, genxml='', **kwargs): self.meta['genxml'] += [{k: v for j in i.split('|') for k, v in (j.split('='), )} for i in genxml.split('||')] if genxml else [] self.meta['getnfo'] = {k: xbmc.getInfoLabel(v) for k, v in self.meta['getnfo'].items()} if 'getnfo' in self.meta else {} self.meta['getnfo'].update(kwargs) - self.meta['getnfo'].update({f'{k}_escaped': escape(v) for k, v in self.meta['getnfo'].items() if not k.endswith('_escaped')}) + self.meta['getnfo'].update({f'{k}_escaped': escape(v) for k, v in self.meta['getnfo'].items() if v and k and not k.endswith('_escaped')}) + + if 'addnfo' in self.meta: + from resources.lib.operations import RuleOperations + self.meta['getnfo'].update(RuleOperations(self.meta['addnfo'], **self.meta['getnfo']).params) content = self.create_xml( self.meta['genxml'],