250 lines
6.1 KiB
Python
250 lines
6.1 KiB
Python
#!/usr/bin/python
|
|
# coding: utf-8
|
|
|
|
########################
|
|
|
|
import sys
|
|
import xbmc
|
|
import xbmcaddon
|
|
import xbmcgui
|
|
import xbmcvfs
|
|
import xbmcplugin
|
|
import json
|
|
import time
|
|
import datetime
|
|
import os
|
|
import hashlib
|
|
import xml.etree.ElementTree as ET
|
|
import requests
|
|
import urllib.request as urllib
|
|
from urllib.parse import urlencode
|
|
from contextlib import contextmanager
|
|
|
|
########################
|
|
|
|
ADDON = xbmcaddon.Addon()
|
|
ADDON_ID = ADDON.getAddonInfo('id')
|
|
ADDON_DATA_PATH = os.path.join(xbmcvfs.translatePath("special://profile/addon_data/%s" % ADDON_ID))
|
|
|
|
NOTICE = xbmc.LOGINFO
|
|
WARNING = xbmc.LOGWARNING
|
|
DEBUG = xbmc.LOGDEBUG
|
|
ERROR = xbmc.LOGERROR
|
|
LOG_JSON = ADDON.getSettingBool('json_log')
|
|
KODI_VERSION = int(xbmc.getInfoLabel('System.BuildVersion')[:2])
|
|
|
|
DIALOG = xbmcgui.Dialog()
|
|
|
|
########################
|
|
|
|
|
|
def log(txt,loglevel=DEBUG,json=False,force=False):
|
|
if loglevel in [DEBUG, WARNING, ERROR] or force:
|
|
if force:
|
|
loglevel = NOTICE
|
|
|
|
if json:
|
|
txt = json_prettyprint(txt)
|
|
|
|
message = u'[ %s ] %s' % (ADDON_ID,txt)
|
|
xbmc.log(msg=message, level=loglevel)
|
|
|
|
|
|
def unicode_string(string):
|
|
string = u'%s' % string
|
|
return string
|
|
|
|
|
|
def remove_quotes(label):
|
|
if not label:
|
|
return ''
|
|
|
|
if label.startswith("'") and label.endswith("'") and len(label) > 2:
|
|
label = label[1:-1]
|
|
if label.startswith('"') and label.endswith('"') and len(label) > 2:
|
|
label = label[1:-1]
|
|
elif label.startswith('"') and label.endswith('"'):
|
|
label = label[6:-6]
|
|
|
|
return label
|
|
|
|
|
|
def get_joined_items(item):
|
|
if len(item) > 0 and item is not None:
|
|
item = '; '.join(item)
|
|
item = item + ';'
|
|
else:
|
|
item = ''
|
|
|
|
return item
|
|
|
|
|
|
def get_list_items(string):
|
|
return remove_empty(string.replace('; ',';').split(';'))
|
|
|
|
|
|
def get_key_item(items,key):
|
|
try:
|
|
return items.get(key)
|
|
except Exception:
|
|
return
|
|
|
|
|
|
def get_rounded_value(value):
|
|
try:
|
|
if not isinstance(value, str) and not isinstance(value, float):
|
|
value = str(value)
|
|
if not isinstance(value, float):
|
|
value = float(value)
|
|
|
|
return round(value,1)
|
|
|
|
except Exception:
|
|
return
|
|
|
|
|
|
def remove_empty(array):
|
|
cleaned_array = []
|
|
|
|
for item in array:
|
|
if not item or item in ['', ';']:
|
|
continue
|
|
cleaned_array.append(item)
|
|
|
|
return cleaned_array
|
|
|
|
|
|
def execute(cmd):
|
|
xbmc.executebuiltin(cmd)
|
|
|
|
|
|
def condition(condition):
|
|
return xbmc.getCondVisibility(condition)
|
|
|
|
|
|
def winprop(key, value=None, clear=False, window_id=10000):
|
|
window = xbmcgui.Window(window_id)
|
|
|
|
if clear:
|
|
window.clearProperty(key.replace('.json', '').replace('.bool', '').replace('.str', ''))
|
|
|
|
elif value is not None:
|
|
|
|
if key.endswith('.json'):
|
|
key = key.replace('.json', '')
|
|
value = json.dumps(value)
|
|
|
|
elif key.endswith('.bool'):
|
|
key = key.replace('.bool', '')
|
|
value = 'true' if value else 'false'
|
|
|
|
elif key.endswith('.str'):
|
|
key = key.replace('.str', '')
|
|
value = str(value)
|
|
|
|
window.setProperty(key, value)
|
|
|
|
else:
|
|
result = window.getProperty(key.replace('.json', '').replace('.bool', '').replace('.str', ''))
|
|
|
|
if result:
|
|
if key.endswith('.json'):
|
|
result = json.loads(result)
|
|
|
|
elif key.endswith('.bool'):
|
|
result = result in ('true', '1')
|
|
|
|
elif key.endswith('.str'):
|
|
result = eval(result)
|
|
|
|
return result
|
|
|
|
|
|
def json_call(method,properties=None,sort=None,query_filter=None,limit=None,params=None,item=None,options=None,limits=None,debug=False):
|
|
json_string = {'jsonrpc': '2.0', 'id': 1, 'method': method, 'params': {}}
|
|
|
|
if properties is not None:
|
|
json_string['params']['properties'] = properties
|
|
|
|
if limit is not None:
|
|
json_string['params']['limits'] = {'start': 0, 'end': int(limit)}
|
|
|
|
if sort is not None:
|
|
json_string['params']['sort'] = sort
|
|
|
|
if query_filter is not None:
|
|
json_string['params']['filter'] = query_filter
|
|
|
|
if options is not None:
|
|
json_string['params']['options'] = options
|
|
|
|
if limits is not None:
|
|
json_string['params']['limits'] = limits
|
|
|
|
if item is not None:
|
|
json_string['params']['item'] = item
|
|
|
|
if params is not None:
|
|
json_string['params'].update(params)
|
|
|
|
jsonrpc_call = json.dumps(json_string)
|
|
|
|
result = xbmc.executeJSONRPC(jsonrpc_call)
|
|
result = json.loads(result)
|
|
|
|
if debug:
|
|
log('--> JSON CALL: ' + json_prettyprint(json_string), force=True)
|
|
log('--> JSON RESULT: ' + json_prettyprint(result), force=True)
|
|
|
|
return result
|
|
|
|
|
|
def json_prettyprint(string):
|
|
return json.dumps(string, sort_keys=True, indent=4, separators=(',', ': '))
|
|
|
|
|
|
def xml_prettyprint(root,level=0):
|
|
i = '\n' + level * ' '
|
|
|
|
if len(root):
|
|
if not root.text or not root.text.strip():
|
|
root.text = i + ' '
|
|
|
|
if not root.tail or not root.tail.strip():
|
|
root.tail = i
|
|
|
|
for root in root:
|
|
xml_prettyprint(root, level+1)
|
|
|
|
if not root.tail or not root.tail.strip():
|
|
root.tail = i
|
|
|
|
else:
|
|
if level and (not root.tail or not root.tail.strip()):
|
|
root.tail = i
|
|
|
|
|
|
def notification(header=ADDON.getLocalizedString(32000),message=''):
|
|
DIALOG.notification(header, message, icon='special://home/addons/script.metadata.editor/resources/icon.png')
|
|
|
|
|
|
def reload_widgets():
|
|
# Notifies script.embuary.helper to reload widgets
|
|
execute('NotifyAll(%s,Finished)' % ADDON_ID)
|
|
|
|
|
|
@contextmanager
|
|
def busy_dialog(force=False):
|
|
if force:
|
|
execute('ActivateWindow(busydialognocancel)')
|
|
|
|
elif not winprop('UpdatingRatings.bool'):
|
|
# NFO writing usually only takes < 1s. Just show BusyDialog if it takes longer for whatever reason.
|
|
execute('AlarmClock(BusyAlarmDelay,ActivateWindow(busydialognocancel),00:02,silent)')
|
|
|
|
try:
|
|
yield
|
|
|
|
finally:
|
|
execute('CancelAlarm(BusyAlarmDelay,silent)')
|
|
execute('Dialog.Close(busydialognocancel)') |