def _threadDoPOSTJob(self, request: HydrusServerRequest.HydrusRequest): if 'subject_identifier' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account key, but did not get one!') subject_identifier = request.parsed_request_args['subject_identifier'] if subject_identifier.HasAccountKey(): subject_account_key = subject_identifier.GetAccountKey() else: raise HydrusExceptions.BadRequestException( 'The subject\'s account identifier did not include an account key!' ) HG.server_controller.WriteSynchronous('modify_account_unban', self._service_key, request.hydrus_account, subject_account_key) response_context = HydrusServerResources.ResponseContext(200) return response_context
def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): if 'subject_identifier' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account id, but did not get one!' ) subject_identifier = request.parsed_request_args[ 'subject_identifier' ] if subject_identifier.HasAccountKey(): subject_account_key = subject_identifier.GetAccountKey() else: raise HydrusExceptions.BadRequestException( 'The subject\'s account identifier did not include an account id!' ) if 'message' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting a new message, but did not get one!' ) message = request.parsed_request_args[ 'message' ] if not isinstance( message, str ): raise HydrusExceptions.BadRequestException( 'The given message was not a string!' ) HG.server_controller.WriteSynchronous( 'modify_account_set_message', self._service_key, request.hydrus_account, subject_account_key, message ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context
def ParseSystemPredicateStringsToPredicates( system_predicate_strings: typing.Collection[ str ] ) -> typing.List[ ClientSearch.Predicate ]: system_predicates = [] for s in system_predicate_strings: try: ( ext_pred_type, operator, value, unit ) = SystemPredicateParser.parse_system_predicate( s ) if ext_pred_type not in pred_generators: raise HydrusExceptions.BadRequestException( 'Sorry, do not know how to parse "{}" yet!'.format( s ) ) predicate = pred_generators[ ext_pred_type ]( operator, value, unit ) system_predicates.append( predicate ) except ValueError as e: raise HydrusExceptions.BadRequestException( 'Could not parse system predicate "{}"!'.format( s ) ) except Exception as e: raise HydrusExceptions.BadRequestException( 'Problem when trying to parse this system predicate: "{}"!'.format( s ) ) return system_predicates
def _threadDoGETJob(self, request: HydrusServerRequest.HydrusRequest): if 'subject_identifier' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account key, but did not get one!') subject_identifier = request.parsed_request_args['subject_identifier'] if subject_identifier.HasAccountKey(): subject_account_key = subject_identifier.GetAccountKey() else: raise HydrusExceptions.BadRequestException( 'The subject\'s account identifier did not include an account key!' ) subject_account = HG.server_controller.Read('account', self._service_key, subject_account_key) account_info = HG.server_controller.Read('account_info', self._service_key, request.hydrus_account, subject_account) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( {'account_info': account_info}) response_context = HydrusServerResources.ResponseContext(200, body=body) return response_context
def _threadDoPOSTJob( self, request: HydrusServerRequest.HydrusRequest ): update_period = request.parsed_request_args[ 'update_period' ] if update_period < HydrusNetwork.MIN_UPDATE_PERIOD: raise HydrusExceptions.BadRequestException( 'The update period was too low. It needs to be at least {}.'.format( HydrusData.TimeDeltaToPrettyTimeDelta( HydrusNetwork.MIN_UPDATE_PERIOD ) ) ) if update_period > HydrusNetwork.MAX_UPDATE_PERIOD: raise HydrusExceptions.BadRequestException( 'The update period was too high. It needs to be lower than {}.'.format( HydrusData.TimeDeltaToPrettyTimeDelta( HydrusNetwork.MAX_UPDATE_PERIOD ) ) ) old_update_period = self._service.GetUpdatePeriod() if old_update_period != update_period: self._service.SetUpdatePeriod( update_period ) HydrusData.Print( 'Account {} changed the update period to from "{}" to "{}".'.format( request.hydrus_account.GetAccountKey().hex(), HydrusData.TimeDeltaToPrettyTimeDelta( old_update_period ), HydrusData.TimeDeltaToPrettyTimeDelta( update_period ) ) ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context
def file_service_pred_generator(o, v, u): o_dict = { 'is not currently in': (False, HC.CONTENT_STATUS_CURRENT), 'is currently in': (True, HC.CONTENT_STATUS_CURRENT), 'is not pending to': (False, HC.CONTENT_STATUS_PENDING), 'is pending to': (True, HC.CONTENT_STATUS_PENDING) } (is_in, status) = o_dict[o] try: service_name = v service_key = HG.client_controller.services_manager.GetServiceKeyFromName( HC.FILE_SERVICES, service_name) except: raise HydrusExceptions.BadRequestException( 'Could not find the service "{}"!'.format(service_name)) return ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_SERVICE, (is_in, status, service_key))
def _callbackParsePOSTArgs( self, request ): request.content.seek( 0 ) if not request.requestHeaders.hasHeader( 'Content-Type' ): parsed_request_args = HydrusNetworking.ParsedRequestArguments() else: content_types = request.requestHeaders.getRawHeaders( 'Content-Type' ) content_type = content_types[0] try: mime = HC.mime_enum_lookup[ content_type ] except: raise HydrusExceptions.BadRequestException( 'Did not recognise Content-Type header!' ) total_bytes_read = 0 if mime == HC.APPLICATION_JSON: json_string = request.content.read() total_bytes_read += len( json_string ) parsed_request_args = HydrusNetwork.ParseNetworkBytesToParsedHydrusArgs( json_string ) else: ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() request.temp_file_info = ( os_file_handle, temp_path ) with open( temp_path, 'wb' ) as f: for block in HydrusPaths.ReadFileLikeAsBlocks( request.content ): f.write( block ) total_bytes_read += len( block ) decompression_bombs_ok = self._DecompressionBombsOK( request ) parsed_request_args = HydrusServerResources.ParseFileArguments( temp_path, decompression_bombs_ok ) self._reportDataUsed( request, total_bytes_read ) request.parsed_request_args = parsed_request_args return request
def CheckPermissionToSeeFiles( self, hash_ids ): with self._lock: if self._search_tag_filter.AllowsEverything(): return if self._last_search_results is None: raise HydrusExceptions.BadRequestException( 'It looks like those search results are no longer available--please run the search again!' ) num_files_asked_for = len( hash_ids ) num_files_allowed_to_see = len( self._last_search_results.intersection( hash_ids ) ) if num_files_allowed_to_see != num_files_asked_for: error_text = 'You do not seem to have access to all those files! You asked to see {} files, but you were only authorised to see {} of them!' error_text = error_text.format( HydrusData.ToHumanInt( num_files_asked_for ), HydrusData.ToHumanInt( num_files_allowed_to_see ) ) raise HydrusExceptions.InsufficientCredentialsException( error_text ) self._search_results_timeout = HydrusData.GetNow() + SEARCH_RESULTS_CACHE_TIMEOUT
def _threadDoPOSTJob(self, request): services = request.parsed_request_args['services'] unique_ports = {service.GetPort() for service in services} if len(unique_ports) < len(services): raise HydrusExceptions.BadRequestException( 'It looks like some of those services share ports! Please give them unique ports!' ) with HG.dirty_object_lock: HG.server_controller.SetServices(services) service_keys_to_access_keys = HG.server_controller.WriteSynchronous( 'services', request.hydrus_account, services) body = HydrusNetwork.DumpHydrusArgsToNetworkBytes( {'service_keys_to_access_keys': service_keys_to_access_keys}) response_context = HydrusServerResources.ResponseContext(200, body=body) return response_context
def file_service_pred_generator( o, v, u ): if o.startswith( 'is not' ): is_in = False else: is_in = True o_dict = { 'currently in' : HC.CONTENT_STATUS_CURRENT, 'deleted from' : HC.CONTENT_STATUS_DELETED, 'pending to' : HC.CONTENT_STATUS_PENDING, 'petitioned from' : HC.CONTENT_STATUS_PETITIONED } status = None for ( phrase, possible_status ) in o_dict.items(): if phrase in o: status = possible_status break if status is None: raise HydrusExceptions.BadRequestException( 'Did not understand the file service status!' ) try: service_name = v service_key = HG.client_controller.services_manager.GetServiceKeyFromName( HC.FILE_SERVICES, service_name ) except: raise HydrusExceptions.BadRequestException( 'Could not find the service "{}"!'.format( service_name ) ) return ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_SERVICE, ( is_in, status, service_key ) )
def _threadDoPOSTJob(self, request: HydrusServerRequest.HydrusRequest): if 'subject_identifier' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account key, but did not get one!') subject_identifier = request.parsed_request_args['subject_identifier'] if subject_identifier.HasAccountKey(): subject_account_key = subject_identifier.GetAccountKey() else: raise HydrusExceptions.BadRequestException( 'The subject\'s account identifier did not include an account key!' ) if 'expires' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting a new expiration timestamp, but did not get one!' ) expires = request.parsed_request_args['expires'] expires_is_none = expires is None expires_is_positive_integer = isinstance(expires, int) and expires > 0 expires_is_valid = expires_is_none or expires_is_positive_integer if not expires_is_valid: raise HydrusExceptions.BadRequestException( 'The given expiration timestamp was not None or an integer!') HG.server_controller.WriteSynchronous('modify_account_expires', self._service_key, request.hydrus_account, subject_account_key, expires) response_context = HydrusServerResources.ResponseContext(200) return response_context
def _threadDoGETJob(self, request: HydrusServerRequest.HydrusRequest): if 'subject_identifier' not in request.parsed_request_args: raise HydrusExceptions.BadRequestException( 'I was expecting an account identifier for the subject, but did not get one!' ) subject_identifier = request.parsed_request_args['subject_identifier'] if subject_identifier.HasAccountKey(): subject_account_key = subject_identifier.GetAccountKey() try: subject_account = HG.server_controller.Read( 'account', self._service_key, subject_account_key) except HydrusExceptions.InsufficientCredentialsException as e: raise HydrusExceptions.NotFoundException(e) elif subject_identifier.HasContent(): subject_content = subject_identifier.GetContent() subject_account = HG.server_controller.Read( 'account_from_content', self._service_key, subject_content) else: raise HydrusExceptions.BadRequestException( 'The subject\'s account identifier did not include an account key or content!' ) body = HydrusNetworkVariableHandling.DumpHydrusArgsToNetworkBytes( {'account': subject_account}) response_context = HydrusServerResources.ResponseContext(200, body=body) return response_context
def GetValue(self, key, expected_type, default_value=None): if key in self: value = self[key] if not isinstance(value, expected_type): error_text_lookup = {} error_text_lookup[int] = 'integer' error_text_lookup[str] = 'string' error_text_lookup[bytes] = 'hex-encoded bytestring' error_text_lookup[bool] = 'boolean' error_text_lookup[list] = 'list' error_text_lookup[dict] = 'object/dict' if expected_type in error_text_lookup: type_error_text = error_text_lookup[expected_type] else: type_error_text = 'unknown!' raise HydrusExceptions.BadRequestException( 'The parameter "{}" was not the expected type: {}!'.format( key, type_error_text)) return value else: if default_value is None: raise HydrusExceptions.BadRequestException( 'The required parameter "{}" was missing!'.format(key)) else: return default_value
def _callbackEstablishAccountFromHeader( self, request: HydrusServerRequest.HydrusRequest): session_key = None if request.requestHeaders.hasHeader('Cookie'): cookie_texts = request.requestHeaders.getRawHeaders('Cookie') cookie_text = cookie_texts[0] try: cookies = http.cookies.SimpleCookie(cookie_text) if 'session_key' in cookies: # Morsel, for real, ha ha ha morsel = cookies['session_key'] session_key_hex = morsel.value session_key = bytes.fromhex(session_key_hex) except: raise HydrusExceptions.BadRequestException( 'Problem parsing cookies for Session Cookie!') if session_key is None: access_key = self._parseHydrusNetworkAccessKey(request, key_required=False) if access_key is None: raise HydrusExceptions.MissingCredentialsException( 'No credentials found in request!') else: account = HG.server_controller.server_session_manager.GetAccountFromAccessKey( self._service_key, access_key) else: account = HG.server_controller.server_session_manager.GetAccount( self._service_key, session_key) request.hydrus_account = account return request
def _threadDoPOSTJob(self, request: HydrusServerRequest.HydrusRequest): nullification_period = request.parsed_request_args[ 'nullification_period'] if nullification_period < HydrusNetwork.MIN_NULLIFICATION_PERIOD: raise HydrusExceptions.BadRequestException( 'The anonymisation period was too low. It needs to be at least {}.' .format( HydrusData.TimeDeltaToPrettyTimeDelta( HydrusNetwork.MIN_NULLIFICATION_PERIOD))) if nullification_period > HydrusNetwork.MAX_NULLIFICATION_PERIOD: raise HydrusExceptions.BadRequestException( 'The anonymisation period was too high. It needs to be lower than {}.' .format( HydrusData.TimeDeltaToPrettyTimeDelta( HydrusNetwork.MAX_NULLIFICATION_PERIOD))) old_nullification_period = self._service.GetNullificationPeriod() if old_nullification_period != nullification_period: self._service.SetNullificationPeriod(nullification_period) HydrusData.Print( 'Account {} changed the anonymisation period to from "{}" to "{}".' .format( request.hydrus_account.GetAccountKey().hex(), HydrusData.TimeDeltaToPrettyTimeDelta( old_nullification_period), HydrusData.TimeDeltaToPrettyTimeDelta( nullification_period))) response_context = HydrusServerResources.ResponseContext(200) return response_context
def _threadDoPOSTJob(self, request: HydrusServerRequest.HydrusRequest): locked = HG.server_busy.acquire(False) # pylint: disable=E1111 if not locked: raise HydrusExceptions.BadRequestException( 'The server was already locked!') HG.server_controller.db.PauseAndDisconnect(True) # shut down db, wait until it is done? response_context = HydrusServerResources.ResponseContext(200) return response_context
def _threadDoPOSTJob(self, request: HydrusServerRequest.HydrusRequest): try: HG.server_busy.release() except threading.ThreadError: raise HydrusExceptions.BadRequestException( 'The server is not busy!') HG.server_controller.db.PauseAndDisconnect(False) response_context = HydrusServerResources.ResponseContext(200) return response_context
def _threadDoPOSTJob( self, request ): # check permission here since no db work request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_SERVICES, HC.PERMISSION_ACTION_OVERRULE ) try: HG.server_busy.release() except threading.ThreadError: raise HydrusExceptions.BadRequestException( 'The server is not busy!' ) HG.server_controller.db.PauseAndDisconnect( False ) response_context = HydrusServerResources.ResponseContext( 200 ) return response_context
def _threadDoPOSTJob( self, request ): # check permission here since no db work request.hydrus_account.CheckPermission( HC.CONTENT_TYPE_SERVICES, HC.PERMISSION_ACTION_OVERRULE ) locked = HG.server_busy.acquire( False ) # pylint: disable=E1111 if not locked: raise HydrusExceptions.BadRequestException( 'The server was already locked!' ) HG.server_controller.db.PauseAndDisconnect( True ) # shut down db, wait until it is done? response_context = HydrusServerResources.ResponseContext( 200 ) return response_context
def _threadDoPOSTJob(self, request: HydrusServerRequest.HydrusRequest): locked = HG.server_busy.acquire(False) # pylint: disable=E1111 if not locked: raise HydrusExceptions.BadRequestException( 'The server was already locked!') HG.server_controller.db.PauseAndDisconnect(True) TIME_BLOCK = 0.25 for i in range(int(5 / TIME_BLOCK)): if not HG.server_controller.db.IsConnected(): break time.sleep(TIME_BLOCK) response_context = HydrusServerResources.ResponseContext(200) return response_context
def GetValue(self, key, expected_type, expected_list_type=None, default_value=None): # not None because in JSON sometimes people put 'null' to mean 'did not enter this optional parameter' if key in self and self[key] is not None: value = self[key] error_text_lookup = {} error_text_lookup[int] = 'integer' error_text_lookup[str] = 'string' error_text_lookup[bytes] = 'hex-encoded bytestring' error_text_lookup[bool] = 'boolean' error_text_lookup[list] = 'list' error_text_lookup[dict] = 'object/dict' if not isinstance(value, expected_type): if expected_type in error_text_lookup: type_error_text = error_text_lookup[expected_type] else: type_error_text = 'unknown!' raise HydrusExceptions.BadRequestException( 'The parameter "{}" was not the expected type: {}!'.format( key, type_error_text)) if expected_type is list and expected_list_type is not None: for item in value: if not isinstance(item, expected_list_type): if expected_list_type in error_text_lookup: type_error_text = error_text_lookup[ expected_list_type] else: type_error_text = 'unknown!' raise HydrusExceptions.BadRequestException( 'The list parameter "{}" held an item that was not the expected type: {}!' .format(key, type_error_text)) return value else: if default_value is None: raise HydrusExceptions.BadRequestException( 'The required parameter "{}" was missing!'.format(key)) else: return default_value
def __missing__(self, key): raise HydrusExceptions.BadRequestException( 'It looks like the parameter "{}" was missing!'.format(key))
def ParseTwistedRequestGETArgs(requests_args, int_params, byte_params, string_params, json_params, json_byte_list_params): args = ParsedRequestArguments() for name_bytes in requests_args: values_bytes = requests_args[name_bytes] try: name = str(name_bytes, 'utf-8') except UnicodeDecodeError: continue value_bytes = values_bytes[0] try: value = str(value_bytes, 'utf-8') except UnicodeDecodeError: continue if name in int_params: try: args[name] = int(value) except Exception as e: raise HydrusExceptions.BadRequestException( 'I was expecting to parse \'' + name + '\' as an integer, but it failed.') from e elif name in byte_params: try: args[name] = bytes.fromhex(value) except Exception as e: raise HydrusExceptions.BadRequestException( 'I was expecting to parse \'' + name + '\' as a hex string, but it failed.') from e elif name in string_params: try: args[name] = urllib.parse.unquote(value) except Exception as e: raise HydrusExceptions.BadRequestException( 'I was expecting to parse \'' + name + '\' as a percent-encdode string, but it failed.') from e elif name in json_params: try: args[name] = json.loads(urllib.parse.unquote(value)) except Exception as e: raise HydrusExceptions.BadRequestException( 'I was expecting to parse \'' + name + '\' as a json-encoded string, but it failed.') from e elif name in json_byte_list_params: try: list_of_hex_strings = json.loads(urllib.parse.unquote(value)) args[name] = [ bytes.fromhex(hex_string) for hex_string in list_of_hex_strings ] except Exception as e: raise HydrusExceptions.BadRequestException( 'I was expecting to parse \'' + name + '\' as a json-encoded hex strings, but it failed.') from e return args
def ParseNetworkBytesToParsedHydrusArgs(network_bytes): if len(network_bytes) == 0: return HydrusSerialisable.SerialisableDictionary() args = HydrusSerialisable.CreateFromNetworkBytes(network_bytes) if not isinstance(args, dict): raise HydrusExceptions.BadRequestException( 'The given parameter did not seem to be a JSON Object!') args = ParsedRequestArguments(args) for param_name in BYTE_PARAMS: if param_name in args: args[param_name] = bytes.fromhex(args[param_name]) for param_name in JSON_BYTE_LIST_PARAMS: if param_name in args: args[param_name] = [ bytes.fromhex(encoded_item) for encoded_item in args[param_name] ] # account_types should be a serialisable list, so it just works if 'account' in args: args[ 'account'] = HydrusNetwork.Account.GenerateAccountFromSerialisableTuple( args['account']) if 'accounts' in args: account_tuples = args['accounts'] args['accounts'] = [ HydrusNetwork.Account.GenerateAccountFromSerialisableTuple( account_tuple) for account_tuple in account_tuples ] if 'service_keys_to_access_keys' in args: args['service_keys_to_access_keys'] = { bytes.fromhex(encoded_service_key): bytes.fromhex(encoded_access_key) for (encoded_service_key, encoded_access_key) in args['service_keys_to_access_keys'] } if 'services' in args: service_tuples = args['services'] args['services'] = [ HydrusNetwork.GenerateServiceFromSerialisableTuple(service_tuple) for service_tuple in service_tuples ] return args
def ParseFileArguments(path, decompression_bombs_ok=False): HydrusImageHandling.ConvertToPNGIfBMP(path) hash = HydrusFileHandling.GetHashFromPath(path) try: mime = HydrusFileHandling.GetMime(path) if mime in HC.DECOMPRESSION_BOMB_IMAGES and not decompression_bombs_ok: if HydrusImageHandling.IsDecompressionBomb(path): raise HydrusExceptions.InsufficientCredentialsException( 'File seemed to be a Decompression Bomb, which you cannot upload!' ) (size, mime, width, height, duration, num_frames, has_audio, num_words) = HydrusFileHandling.GetFileInfo(path, mime) except Exception as e: raise HydrusExceptions.BadRequestException('File ' + hash.hex() + ' could not parse: ' + str(e)) args = ParsedRequestArguments() args['path'] = path args['hash'] = hash args['size'] = size args['mime'] = mime if width is not None: args['width'] = width if height is not None: args['height'] = height if duration is not None: args['duration'] = duration if num_frames is not None: args['num_frames'] = num_frames args['has_audio'] = has_audio if num_words is not None: args['num_words'] = num_words if mime in HC.MIMES_WITH_THUMBNAILS: try: bounding_dimensions = HC.SERVER_THUMBNAIL_DIMENSIONS target_resolution = HydrusImageHandling.GetThumbnailResolution( (width, height), bounding_dimensions) thumbnail_bytes = HydrusFileHandling.GenerateThumbnailBytes( path, target_resolution, mime, duration, num_frames) except Exception as e: tb = traceback.format_exc() raise HydrusExceptions.BadRequestException( 'Could not generate thumbnail from that file:' + os.linesep + tb) args['thumbnail'] = thumbnail_bytes return args
def ParseTwistedRequestGETArgs(requests_args, int_params, byte_params, string_params, json_params, json_byte_list_params): args = ParsedRequestArguments() cbor_requested = b'cbor' in requests_args if cbor_requested and not CBOR_AVAILABLE: raise HydrusExceptions.NotAcceptable( 'Sorry, this service does not support CBOR!') for name_bytes in requests_args: values_bytes = requests_args[name_bytes] try: name = str(name_bytes, 'utf-8') except UnicodeDecodeError: continue value_bytes = values_bytes[0] try: value = str(value_bytes, 'utf-8') except UnicodeDecodeError: continue if name in int_params: try: args[name] = int(value) except Exception as e: raise HydrusExceptions.BadRequestException( 'I was expecting to parse \'' + name + '\' as an integer, but it failed.') from e elif name in byte_params: try: if name in HASH_BYTE_PARAMS and ':' in value: value = value.split(':', 1)[1] args[name] = bytes.fromhex(value) except Exception as e: raise HydrusExceptions.BadRequestException( 'I was expecting to parse \'' + name + '\' as a hex string, but it failed.') from e elif name in string_params: try: args[name] = urllib.parse.unquote(value) except Exception as e: raise HydrusExceptions.BadRequestException( 'I was expecting to parse \'' + name + '\' as a percent-encdode string, but it failed.') from e elif name in json_params: try: if cbor_requested: args[name] = cbor2.loads(base64.urlsafe_b64decode(value)) else: args[name] = json.loads(urllib.parse.unquote(value)) except Exception as e: raise HydrusExceptions.BadRequestException( 'I was expecting to parse \'' + name + '\' as a json-encoded string, but it failed.') from e elif name in json_byte_list_params: try: if cbor_requested: list_of_hex_strings = cbor2.loads( base64.urlsafe_b64decode(value)) else: list_of_hex_strings = json.loads( urllib.parse.unquote(value)) args[name] = [ bytes.fromhex(hex_string) for hex_string in list_of_hex_strings ] except Exception as e: raise HydrusExceptions.BadRequestException( 'I was expecting to parse \'' + name + '\' as a json-encoded hex strings, but it failed.') from e return args