def wait_for_infolabel(self, label_name, expected_value, sleep_msecs=5, cycles=1000): # sadly it's necessary to wait until kodi has the new Container infolabel ... label_value = '' counter = 0 while counter <= cycles: counter += 1 xbmc_sleep(sleep_msecs) label_value = str(getInfoLabel(label_name)) if label_value == expected_value: break self.log_debug('wait_for_infolabel {}: msecs waited: {} values do match {} final value {}', label_name, (counter * sleep_msecs), (expected_value == label_value), label_value)
def set_folder(self, list_items, pluginurl, pluginhandle, pluginquery, folder_type, title=None): folder_defs = CONST['FOLDERS'].get(folder_type) old_pluginurl = getInfoLabel('Container.FolderPath') old_postion = getInfoLabel('Container.CurrentItem') addDirectoryItems(pluginhandle, list_items, len(list_items)) if title is not None: setPluginCategory(pluginhandle, title) if 'content_type' in folder_defs.keys(): self.log_debug('set_folder: set content_type: {}', folder_defs['content_type']) setContent(pluginhandle, folder_defs['content_type']) endOfDirectory(handle=pluginhandle, cacheToDisc=(folder_defs.get('cacheable', False) and (self.get_bool_setting('disable_foldercache') is False))) self.wait_for_infolabel('Container.FolderPath', compat._format('{}{}', pluginurl, pluginquery)) if 'view_mode' in folder_defs.keys(): self.set_view_mode(folder_defs['view_mode']) if 'sort' in folder_defs.keys(): self.set_folder_sort(folder_defs['sort']) # reset the postion to the last "known" if it is gt 1, if pluginurls matching -> likely to be a 'refresh' if getInfoLabel('Container.FolderPath') == old_pluginurl and old_postion.isdigit() and int(old_postion) > 1: from xbmcgui import Window, getCurrentWindowId, getCurrentWindowDialogId # wait untl all Dialogs are closed; 10099 => WINDOW_DIALOG_POINTER => smallest dialog_id; max 500 msecs dialog_wait_counter = 0 while dialog_wait_counter <= 100 and getCurrentWindowDialogId() >= 10099: xbmc_sleep(5) dialog_wait_counter += 1 self.log_debug('waited {} msecs for all dialogs to be closed', (dialog_wait_counter * 5)) self.log_debug('FolderPath old pos {} ', old_postion) focus_id = Window(getCurrentWindowId()).getFocusId() set_postion = old_postion cmd = compat._format('Control.SetFocus({},{})', focus_id, set_postion) executebuiltin(cmd) self.log_debug('set current pos executebuiltin({})', cmd) # wait for the correct postion to be applied; max 500 msecs self.wait_for_infolabel('Container.CurrentItem', old_postion, cycles=100)
def get_graphql_response(self, operation, variables={}, retry_count=0, force_refresh_auth=False, force_cache=False): xbmc_helper().log_debug('get_graphql_response: Operation: {}', operation) if isinstance(CONST['GRAPHQL'][operation].get('REQUIRED_VARIABLES', None), list): for required_var in CONST['GRAPHQL'][operation]['REQUIRED_VARIABLES']: if required_var not in variables.keys(): if required_var in CONST['GRAPHQL']['STATIC_VARIABLES'].keys(): variables.update({required_var: CONST['GRAPHQL']['STATIC_VARIABLES'][required_var]}) else: xbmc_helper().log_error('Not all required variables set for operation {} required var {} set vars{}', operation, required_var, variables) exit(0) if force_refresh_auth is True: self.get_auth_token(force_refresh=True) request_url = CONST['GRAPHQL']['API_URL'] if CONST['GRAPHQL'][operation].get('BOOKMARKS', False) is True and self.get_auth_token().get('has_account', False) is False: query = CONST['GRAPHQL'][operation]['QUERY'].replace('isBookmarked ', '') else: query = CONST['GRAPHQL'][operation]['QUERY'] params = { 'query': compat._format( '{} {} {}', 'query' if CONST['GRAPHQL'][operation].get('IS_MUTATION', False) is False else 'mutation', '' if CONST['GRAPHQL'][operation].get('OPERATION', None) is None else CONST['GRAPHQL'][operation]['OPERATION'], query) } if len(variables.keys()) != 0: if CONST['GRAPHQL'][operation].get('IS_MUTATION', False) is False: params.update({'variables': dumps(variables)}) else: params.update({'variables': variables}) if CONST['GRAPHQL'][operation].get('OPERATION', None) is not None: params.update({ 'operationName': CONST['GRAPHQL'][operation].get('OPERATION'), 'extensions': { 'persistedQuery': { 'version': 1, 'sha256Hash': sha256(params['query'].encode('utf-8')).hexdigest(), }, } }) if CONST['GRAPHQL'][operation].get('IS_MUTATION', False) is False: params.update({'extensions': dumps(params['extensions'])}) headers = copy(self.config['GRAPHQL_HEADERS']) account_state = False if operation != 'ACCOUNT' and operation != 'USER_PROFILE' and self.get_auth_token().get('has_account', False) is not False: account_state = self.get_account_state() if account_state is not False: headers.append(('Joyn-User-State', account_state)) headers.append(('Authorization', self.get_access_token())) api_response = {} no_cache = False if force_cache is True else CONST['GRAPHQL'][operation].get('NO_CACHE', False) try: if CONST['GRAPHQL'][operation].get('IS_MUTATION', False) is False: api_response = request_helper.get_json_response(url=request_url, config=self.config, params=params, headers=headers, no_cache=no_cache, return_json_errors=['INVALID_JWT']) else: api_response = request_helper.post_json(url=request_url, config=self.config, data=params, additional_headers=headers, no_cache=no_cache, return_json_errors=['INVALID_JWT']) if isinstance(api_response, dict) and 'json_errors' in api_response.keys(): if 'INVALID_JWT' in api_response['json_errors']: self.get_graphql_response(operation=operation, variables=variables, retry_count=retry_count, force_refresh_auth=True) except Exception as e: xbmc_helper().log_error('Could not complete graphql request: {} params {}', e, params) if isinstance(api_response, dict) and 'errors' in api_response.keys(): xbmc_helper().log_error('GraphQL query returned errors: {} params {}', api_response['errors'], params) if isinstance(api_response, dict) and 'data' in api_response.keys() and api_response['data'] is not None: return api_response['data'] else: xbmc_helper().log_error('GraphQL query returned no data - response: {} params {}', api_response, params) if retry_count < 3: xbmc_helper().log_error('Retrying to complete graphql request ... retry count: {}', retry_count) xbmc_sleep(500) return self.get_graphql_response(operation=operation, variables=variables, retry_count=(retry_count + 1)) else: xbmc_helper().notification( compat._format(xbmc_helper().translation('ERROR'), 'GraphQL'), xbmc_helper().translation('MSG_GAPHQL_ERROR'), ) exit(0)