def post_data(self, url, data_in, custom_timeout=int(plugin_addon.getSetting('timeout'))): """ Send a message to the server and wait for a response Args: url: the URL to send the data to data_in: the message to send (in json) custom_timeout: if not given timeout from plugin setting will be used Returns: The response from the server """ import error_handler as eh from error_handler import ErrorPriority if data_in is None: data_in = b'' headers = { 'Content-Type': 'application/json', 'Accept': 'application/json', } apikey = plugin_addon.getSetting('apikey') if apikey is not None and apikey != '': headers['apikey'] = apikey eh.spam('POSTing Data ---') eh.spam('URL:', url) eh.spam('Headers:', headers) eh.spam('POST Body:', data_in) try: # self.encode(url) # py3 fix req = Request(url, self.encode(data_in), headers) data_out = None response = urlopen(req, timeout=custom_timeout) data_out = response.read() response.close() eh.spam('Response Body:', data_out) eh.spam('Checking Response for a text error.\n') if data_out is not None and data_out != '': self.parse_possible_error(req, data_out) except timeout: # if using very short time out to not wait for response it will throw time out err, # but we check if that was intended by checking custom_timeout # if it wasn't intended we handle it the old way if custom_timeout == int(plugin_addon.getSetting('timeout')): eh.exception(ErrorPriority.HIGH) except http_error as err: raise err except Exception as ex: xbmc.log('==== post_data error ==== %s ' % ex, xbmc.LOGNOTICE) eh.exception(ErrorPriority.HIGH) return data_out
def send_profile(): eh.spam('Trying to send_profile(). Wish me luck!') log_setsuzoku(Category.EIGAKAN, Action.PROFILE, Event.SEND) # setup client on server settings = {} # tweak-ninja settings['manual_mode'] = plugin_addon.getSetting('eigakan_manual_mode') settings['h_resolution'] = plugin_addon.getSetting('eigakan_h_resolution') settings['h_bitrate'] = plugin_addon.getSetting('eigakan_h_bitrate') settings['l_resolution'] = plugin_addon.getSetting('eigakan_l_resolution') settings['l_bitrate'] = plugin_addon.getSetting('eigakan_l_bitrate') settings['x264_preset'] = plugin_addon.getSetting('eigakan_x264_preset') settings['burn_subs'] = plugin_addon.getSetting('burnEigakan') # lang-master settings['pref_audio'] = plugin_addon.getSetting('audiolangEigakan') settings['pref_subs'] = plugin_addon.getSetting('subEigakan') settings = json.dumps(settings) eh.spam('send_profile() data = %s' % settings) try: pyproxy.post_data(eigakan_host + '/api/clientid/%s' % get_device_id(), settings) # if no error, lets mark that we did full handshake with eigakan plugin_addon.setSetting('eigakan_handshake', 'true') except Exception as ex: plugin_addon.setSetting('eigakan_handshake', 'false') eh.spam('error while send_profile(): %s' % ex)
def get_json(self, url_in, direct=False, force_cache=False, cache_time=0): """ use 'get' to return json body as string :param url_in: :param direct: force to bypass cache :param force_cache: force to use cache even if disabled :param cache_time: ignore setting to set custom cache expiration time, mainly to expire data quicker to refresh watch flags :return: """ import error_handler as eh from error_handler import ErrorPriority try: timeout = plugin_addon.getSetting('timeout') if self.api_key is None or self.api_key == '': apikey = plugin_addon.getSetting('apikey') else: apikey = self.api_key # if cache is disabled, overwrite argument and force it to direct if plugin_addon.getSetting('enableCache') != 'true': direct = True if direct and not force_cache: body = self.get_data(url_in, None, timeout, apikey) else: import cache eh.spam('Getting a Cached Response ---') eh.spam('URL:', url_in) db_row = cache.get_data_from_cache(url_in) if db_row is not None: valid_until = cache_time if cache_time > 0 else int( plugin_addon.getSetting('expireCache')) expire_second = time.time() - float(db_row[1]) if expire_second > valid_until: # expire, get new date eh.spam('The cached data is stale.') body = self.get_data(url_in, None, timeout, apikey) cache.remove_cache(url_in) cache.add_cache(url_in, body) else: body = db_row[0] else: eh.spam('No cached data was found for the URL.') body = self.get_data(url_in, None, timeout, apikey) cache.add_cache(url_in, body) except http_error as err: raise err except Exception as ex: xbmc.log(' ========= ERROR JSON ============ %s' % ex, xbmc.LOGNOTICE) eh.exception(ErrorPriority.HIGH) body = None return body
def clear_image_cache(): """ Clear image cache in kodi db :return: """ log_setsuzoku(Category.MAINTENANCE, Action.IMAGE, Event.CLEAN) ret = xbmcgui.Dialog().yesno(plugin_addon.getLocalizedString(30104), plugin_addon.getLocalizedString(30081), plugin_addon.getLocalizedString(30112)) if ret: db_files = [] db_path = os.path.join(pyproxy.decode(xbmc.translatePath('special://home')), 'userdata') db_path = os.path.join(db_path, 'Database') for r, d, f in os.walk(db_path): for files in f: if 'Textures' in files: db_files.append(files) for db_file in db_files: db_connection = database.connect(os.path.join(db_path, db_file)) db_cursor = db_connection.cursor() db_cursor.execute('DELETE FROM texture WHERE url LIKE "%' + plugin_addon.getSetting('port') + '/api/%"') db_connection.commit() db_cursor.execute('DELETE FROM texture WHERE url LIKE "%nakamori%"') db_connection.commit() db_connection.close() if len(db_files) > 0: xbmcgui.Dialog().ok('', plugin_addon.getLocalizedString(30138))
def show_messages(): # finalize the defaultdict so that it won't create new keys anymore __exceptions.default_factory = None if len(__exceptions) == 0: return if ErrorPriority.BLOCKING in __exceptions: exes = __exceptions[ErrorPriority.BLOCKING] exes = Counter(exes).items() exes = sorted(exes) print_exceptions(exes) show_dialog_for_exception(exes[0]) sys.exit() if ErrorPriority.HIGHEST in __exceptions: exes = __exceptions[ErrorPriority.HIGHEST] exes = Counter(exes).items() exes = sorted(exes) print_exceptions(exes) show_dialog_for_exception(exes[0]) if ErrorPriority.HIGH in __exceptions: exes = __exceptions[ErrorPriority.HIGH] exes = Counter(exes).items() exes = sorted(exes) print_exceptions(exes) show_notification_for_exception(exes[0]) if ErrorPriority.NORMAL in __exceptions: exes = __exceptions[ErrorPriority.NORMAL] exes = Counter(exes).items() exes = sorted(exes) print_exceptions(exes) if ErrorPriority.LOW in __exceptions: exes = __exceptions[ErrorPriority.LOW] exes = Counter(exes).items() exes = sorted(exes) # log all if we are spamming if plugin_addon.getSetting('spamLog') != 'true': exes = next([x for x in exes if x[1] > 5], []) print_exceptions(exes) if plugin_addon.getSetting( 'spamLog') == 'true' and ErrorPriority.LOWEST in __exceptions: exes = __exceptions[ErrorPriority.LOWEST] exes = Counter(exes).items() exes = sorted(exes) # log only if we are spamming if plugin_addon.getSetting('spamLog') != 'true': exes = next([x for x in exes if x[1] > 5], []) print_exceptions(exes)
def external_player(self, player_obj): """ In Kodi 18+, xbmc.Player has a isExternalPlayer() method. In earlier versions, the user must specify :param player_obj: the player object to check :return: true or false :rtype: bool """ return plugin_addon.getSetting('external_player').lower() == 'true'
def post_json(self, url_in, body, custom_timeout=int(plugin_addon.getSetting('timeout'))): """ Push data to server using 'POST' method :param url_in: :param body: :param custom_timeout: if not given timeout from plugin setting will be used :return: """ if len(body) > 3: proper_body = '{' + body + '}' return self.post_data(url=url_in, data_in=proper_body, custom_timeout=custom_timeout) else: return None
def exception_internal(exc_type, exc_obj, exc_tb, priority, message=''): """ The priority determines how the system will handle or display the error. The message is self-explanatory. sys.exc_info() will give the required information for the first arguments. Otherwise, just pass None to them. :param exc_type: :param exc_obj: :type exc_obj: Exception :param exc_tb: :param priority: The priority of the Error :type priority: ErrorPriority :param message: a custom message to give the user. If left blank, it will use the exception's :return: """ msg = message # apparently sometimes they give us exc_type as a str instead of a type if exc_type is None: exc_type = 'Exception' if not isinstance(exc_type, str): exc_type = exc_type.__name__ place = get_simple_trace(fullpath=True) if exc_obj is not None and exc_tb is not None: if msg == '': msg = str(exc_obj) ex = NakamoriError(msg, exc_type, place) if priority == ErrorPriority.BLOCKING or plugin_addon.getSetting( 'spamLog') == 'true': for line in traceback.format_exc().replace('\r', '\n').split('\n'): # skip empty lines if len(line) == 0: continue # skip the try_function wrapper if ' in try_inner2' in line or 'return func(*args, **kwargs)' in line or 'error_handler' in line: continue tr = line.replace('\\', '/').replace(addon_path, '.') ex.exc_full_trace.append(tr) else: ex = NakamoriError(msg, exc_type, place) # Learning opportunity! If you don't want it to interrupt you with errors, then change the logic in show_... # That way, you will still get logs of the errors, but no interruptions! # With the previous logic, you are basically saying `if False: else xbmc.log()` __exceptions[priority].append(ex)
def check_eigakan(): try: eigakan_data = pyproxy.get_json(eigakan_host + '/api/version') if eigakan_data is None: return False elif 'eigakan' not in eigakan_data: # raise RuntimeError('Invalid response from Eigakan') return False else: if plugin_addon.getSetting('eigakan_handshake') == 'false': eh.spam('We did not find Eigakan handshake') try: pyproxy.get_json(eigakan_host + '/api/clientid/%s' % get_device_id()) except http_err as err: if int(err.code) == 404: eh.spam('We did not find device profile on Eigakan, sending new one...') plugin_addon.setSetting('eigakan_handshake', 'false') send_profile() else: return False return True except: return False
def move_position_on_list(control_list, position=0, absolute=False): """ Move to the position in a list - use episode number for position Args: control_list: the list control position: the move_position_on_listindex of the item not including settings absolute: bypass setting and set position directly """ if not absolute: if position < 0: position = 0 if plugin_addon.getSetting('show_continue') == 'true': position = int(position + 1) if get_kodi_setting('filelists.showparentdiritems'): position = int(position + 1) try: control_list.selectItem(position) xbmc.log(' move_position_on_list : %s ' % position, xbmc.LOGNOTICE) except: try: control_list.selectItem(position - 1) except Exception as e: xbmc.log(' -----> ERROR -----> %s' % e, xbmc.LOGNOTICE) eh.exception(ErrorPriority.HIGH, localize2(30015))
def spam(*args): if plugin_addon.getSetting('spamLog') == 'true': log(*args)
from nakamori_utils.script_utils import log_setsuzoku from setsuzoku import Category, Action, Event try: from sqlite3 import dbapi2 as database except: # noinspection PyUnresolvedReferences from pysqlite2 import dbapi2 as database localize = script_addon.getLocalizedString localize2 = lib_addon.getLocalizedString sorting_types = [] eigakan_url = plugin_addon.getSetting('ipEigakan') eigakan_port = plugin_addon.getSetting('portEigakan') eigakan_host = 'http://' + eigakan_url + ':' + eigakan_port class Sorting(object): class SortingMethod(object): def __init__(self, container_id, name, listitem_id): self.container_id = container_id self.name = name self.listitem_id = listitem_id sorting_types.append(self) # There are apparently two lists. SetSortMethod uses a container sorting list, and ListItem uses the one from stubs none = SortingMethod(45, localize2(30001), xbmcplugin.SORT_METHOD_UNSORTED) label = SortingMethod(1, localize2(30002), xbmcplugin.SORT_METHOD_LABEL)