class Rpc: def __init__(self, node: str, devel=False): self.client = HTTPClient(node) self.account = Account(self.client) self.chain = Chain(self.client) self.engine = Engine(self.client) self.mempool = Mempool(self.client) self.net = Net(self.client) if devel: self.devel = Devel(self.client) def ping(self): payload = Request("ping") self.client.send(payload) def version(self): payload = Request("version") response = self.client.send(payload) return response.data.result def commit_hash(self): payload = Request("commitHash") response = self.client.send(payload) return response.data.result
def main(): URL = "http://rpc-server:80/" HEADERS = {'content-type': 'application/json'} payload = { "method": "echo", "params": ["echome!"], "jsonrpc": "2.0", "id": 0, } payload2 = { "method": "add", "params": [2, 3], "jsonrpc": "2.0", "id": 0, } # 1st client client = HTTPClient(URL) # 2nd client response = client.send(payload2) # response = requests.post(URL, data=json.dumps(payload2), headers=HEADERS).json() # 3rd client # response = request(URL, "echo", value="Yoko") print('RPC Response', response.data)
def main(context: click.core.Context, method: str, request_type: str, id: Any, send: str) -> None: """ Create a JSON-RPC request. """ exit_status = 0 # Extract the jsonrpc arguments positional = [a for a in context.args if "=" not in a] named = { a.split("=")[0]: a.split("=")[1] for a in context.args if "=" in a } # Create the request if request_type == "notify": req = Notification(method, *positional, **named) else: req = Request(method, *positional, request_id=id, **named) # type: ignore # Sending? if send: client = HTTPClient(send) try: response = client.send(req) except JsonRpcClientError as e: click.echo(str(e), err=True) exit_status = 1 else: click.echo(response.text) # Otherwise, simply output the JSON-RPC request. else: click.echo(str(req)) sys.exit(exit_status)
def load_block_info(height_hash, fetch_size=True): block_data = dict() logging.getLogger('jsonrpcclient').setLevel(logging.ERROR) client = HTTPClient("http://127.0.0.1:20206/json_rpc") height_hash = str(height_hash) try: if len(height_hash) == 64: response = client.send(Request("getblock", hash=height_hash)).data.result else: height_hash = int(height_hash) response = client.send(Request("getblock", height=height_hash)).data.result except ReceivedNon2xxResponseError as e: logging.warning(e) return False, None block_data['block_hash'] = response['block_header']['hash'] block_data['block_difficulty'] = response['block_header']['difficulty'] block_data['timestamp'] = response['block_header']['timestamp'] block_data['time'] = datetime.utcfromtimestamp( block_data['timestamp']).strftime('%Y-%m-%d %H:%M:%S') block_data['height'] = response['block_header']['height'] block_data['topo_height'] = response['block_header']['topoheight'] block_data['depth'] = response['block_header']['depth'] block_data['tips'] = response['block_header']['tips'] json_data = json.loads(response['json']) block_data['miner_tx'] = json_data['miner_tx'] block_data[ 'miner_reward'] = response['block_header']['reward'] / 1000000000000 block_data['tx_hashes'] = json_data['tx_hashes'] block_data['size'] = 0 block_data['tx_size_list'] = list() if block_data['tx_hashes'] and fetch_size: block_data['tx_count'] = len(block_data['tx_hashes']) for tx in block_data['tx_hashes']: _, tx_data = load_tx_info(tx) block_data['size'] += tx_data['size'] block_data['tx_size_list'].append(tx_data['size']) block_data['size'] = "{0:.3f}".format(block_data['size']) block_data['hash_size_list'] = zip(block_data['tx_hashes'], block_data['tx_size_list']) else: block_data['tx_count'] = 0 return True, block_data
def fetch_seat_availability(departure_station, arrival_station, departure_date, departure_time, train_number): client = HTTPClient(pico_paths.endpoint) """ store into into a payload to be sent out to endpoint """ request = Request( method="get_availability", channelId=pico_paths.channelId, train=train_number, origin=departure_station, destination=arrival_station, date=departure_date, time=departure_time, offer_codes=pico_paths.off_codes, ) """ send for a response """ seat_response = client.send(request=request, cert=pico_paths.cert_path, verify=False) request['method'] = "get_price" price_response = client.send(request=request, cert=pico_paths.cert_path, verify=False) merged_data = {} for service in seat_response.data.result: train_instance_data = {} for key, value in seat_response.data.result[service].items(): price = price_response.data.result.get(service) if price is None: train_instance_data.update({key: {"seats": value, "price": 0}}) else: train_instance_data.update({ key: { "seats": value, "price": price_response.data.result[service][key] } }) merged_data.update({service: train_instance_data}) return merged_data
def _call_jsonrpc(self, target: str, method: RestMethod, params: Optional[NamedTuple], timeout): url = self._create_jsonrpc_url(target, method) http_client = HTTPClient(url) request = self._create_jsonrpc_params(method, params) response: Response = http_client.send(request, timeout=timeout) if isinstance(response.data, list): raise NotImplementedError( f"Received batch response. Data: {response.data}") else: return response.data.result
def message_sender(secondary_url, message, message_id, result_queue, retries_cnt): if retries_cnt <= retries: client = HTTPClient(secondary_url) print(len(message_id)) try: response = client.send(json.dumps(message)) print(json.loads(response.text)) message_id.append(response.data.id) result_queue.put(response.data.id) print(len(message_id)) except: print('exception') time.sleep(40) message_sender(secondary_url, message, message_id, result_queue, retries_cnt + 1) else: print('node ' + secondary_url + ' doesn''t work')
def hclient(remote_server, json_rpc): ''' sends a synchronous request to a remote RPC server ''' try: client = HTTPClient(remote_server) response = client.send(json_rpc) valstr = response.text val = json.loads(valstr) print("result: " + str(val["result"])) print("id: " + str(val["id"])) return valstr except Exception as err: logging.debug("node_client: " + str(err)) return '{"jsonrpc": "2.0", "result":"error", "id":"error"}'
def get_info(): logging.getLogger('jsonrpcclient').setLevel(logging.ERROR) client = HTTPClient("http://127.0.0.1:20206/json_rpc") network_data = dict() try: response = client.send(Request("get_info")).data.result network_data['difficulty'] = response['difficulty'] network_data['height'] = response['height'] network_data['topo_height'] = response['topoheight'] network_data['block_time'] = response['averageblocktime50'] network_data['total_supply'] = response['total_supply'] network_data['dynamic_fee_per_kb'] = response[ 'dynamic_fee_per_kb'] / 1000000000000 network_data['hash_rate'] = "{0:.3f}".format( float(network_data['difficulty']) / (12 * 1000000)) return network_data except ReceivedNon2xxResponseError as e: logging.warning(e)
class PlayerService: default_data = ('playlistid', 'speed', 'shuffled', 'repeat') def __init__(self, config: KodiConfiguration): self.config = config self.__check_connection() self.__gather_data() def pause(self): player_state = self.__get_player_state(self.player_id) if player_state.speed == 0: logger.info("Player has been already paused") return response = self.client.send( Request('Player.PlayPause', self.player_id, 'toggle', id_generator=id_generators.random())) if response.data.ok: logger.info("Player is paused") else: raise KodiActionException('Player.PlayPause') def play(self): player_state = self.__get_player_state(self.player_id) if player_state.speed == 1: logger.info("Player has been already played") return response = self.client.send( Request('Player.PlayPause', self.player_id, 'toggle', id_generator=id_generators.random())) if response.data.ok: logger.info("Player is played") else: raise KodiActionException("Player.PlayPause") def clean_current_playlist(self): response = self.client.send( Request('Playlist.Clear', self.playlist_id, id_generator=id_generators.random())) if response.data.ok: logger.info('Current playlist has cleaned') else: raise KodiActionException('Playlist.Clean') def add_playlist_by_name(self, name: str): kodi_files = self.__get_playlist_files() playlist: KodiFile = None for kodi_file in kodi_files: if kodi_file.label == name: playlist = kodi_file break if not playlist: raise KodiCannotFindPlaylistException(name) request = dict() request['directory'] = playlist.file response = self.client.send( Request('Playlist.Insert', self.playlist_id, 0, request, id_generator=id_generators.random())) if not response.data.ok: raise KodiActionException('Playlist.Insert') logger.info("Successfully insert playlist \"%s\"" % name) def open_playlist(self): request = dict() request['position'] = 0 request['playlistid'] = self.playlist_id response = self.client.send(Request('Player.Open', id_generator=id_generators.random(), item=request, options=dict())) if not response.data.ok: raise KodiActionException('Player.Open') player_state = self.__get_player_state(self.player_id) if player_state.speed == 0: logger.warning("Player has been stopped! Try to play it.") self.play() def __check_connection(self): url = "%s://%s:%s/jsonrpc" % (self.config.protocol, self.config.host, self.config.port) self.client = HTTPClient(url) self.client.session.auth = (self.config.username, self.config.passwd) response = self.client.send(Request('Application.GetProperties', list(), id_generator=id_generators.random())) if not response.data.ok: raise KodiServerCheckException() def __gather_data(self): self.player_id = self.__get_player() player_state = self.__get_player_state(self.player_id) self.playlist_id = player_state.playlist_id def __get_player(self) -> int: response = self.client.send(Request('Player.GetActivePlayers', id_generator=id_generators.random())) if not response.data.ok: raise KodiCannotGetActivePlayerException() return response.data.result[0]['playerid'] def __get_player_state(self, player_id: int) -> PlayerState: response = self.client.send( Request('Player.GetProperties', player_id, self.default_data, id_generator=id_generators.random())) if not response.data.ok: raise KodiActionException('Player.GetProperties') raw_state = response.data.result return PlayerState(player_id, raw_state['playlistid'], raw_state['speed'], raw_state['shuffled'], raw_state['repeat']) def __get_playlist_files(self) -> List[KodiFile]: properties = ('title', 'file', 'mimetype', 'thumbnail', 'dateadded') sort = dict() sort['method'] = 'none' sort['order'] = 'ascending' response = self.client.send(Request('Files.GetDirectory', id_generator=id_generators.random(), directory='special://profile/playlists/video', media='video', properties=properties, sort=sort)) if not response.data.ok: raise KodiActionException("Files.GetDirectory") files = list() for file in response.data.result['files']: files.append(KodiFile(file['file'], file['filetype'], file['label'], file['mimetype'], file['thumbnail'], file['title'], file['type'])) return files
from jsonrpcclient.clients.http_client import HTTPClient import json try: client = HTTPClient("http://127.0.0.24:8081") print("RPC client is ready") response = client.send('{"jsonrpc": "2.0", "method": "fibonacci", \ "params":{ "m":100, "n":200}, "id":31 }') print("have json fibonacci response from server: " + response.text) val = response.text val = json.loads(val) print("result: " + str(val["result"])) print("id: " + str(val["id"])) print("fibonacci number is: " + str(val["result"]["result"])) except Exception as error: print(error)
class JsonRpcTest(unittest.TestCase): @classmethod def setUpClass(cls): cls.gen_id = random() def setUp(self): self.client = HTTPClient('http://127.0.0.1:8080') def tearDown(self): self.client.session.close() def test_single_args(self): r = self.client.request('test.hello', 'WORLD', id_generator=self.gen_id) self.assertEqual(r.data.result, 'Hello WORLD!') def test_single_kwargs(self): r = self.client.request('test.hello', who='WORLD', id_generator=self.gen_id) self.assertEqual(r.data.result, 'Hello WORLD!') def test_single_notification(self): r = self.client.notify('test.hello', who='WORLD') self.assertEqual(r.text, '') def test_single_err(self): with self.assertRaises(ReceivedErrorResponseError) as cm: self.client.request('test.test_div', 10, 0, id_generator=self.gen_id) exception = cm.exception self.assertEqual(exception.args[0], 'division by zero') def test_batch(self): gen_id = iter(range(100)) batch = ( Request('vadd.test', 5, 10, id_generator=gen_id), Request('vsub.test', arg1=10, arg2=9, id_generator=gen_id), Request('test.hello', 'WORLD', id_generator=gen_id), Request('nonexistent_method', id_generator=gen_id), Request('test.test_div', 10, 0, id_generator=gen_id), ) resp = self.client.send(batch) self.assertEqual(len(resp.data), 5) for r in resp.data: if r.id == 0: self.assertEqual(r.result, 15) elif r.id == 1: self.assertEqual(r.result, 1) elif r.id == 2: self.assertEqual(r.result, 'Hello WORLD!') elif r.id == 3: self.assertFalse(r.ok) self.assertEqual(r.code, -32601) elif r.id == 4: self.assertFalse(r.ok) self.assertEqual(r.code, -32000) self.assertEqual(r.message, 'division by zero')
import logging from jsonrpcclient.clients.http_client import HTTPClient from jsonrpcclient.requests import Request, Notification client = HTTPClient("http://localhost:5000") response = client.send( [Request("ping"), Notification("ping"), Request("ping")]) for data in response.data: if data.ok: print("{}: {}".format(data.id, data.result)) else: logging.error("%d: %s", data.id, data.message)
from jsonrpcclient.clients.http_client import HTTPClient from jsonrpcclient.requests import Request client = HTTPClient("http://localhost:8080/myobjectrpc") resp = client.send(Request("subtract", 10, 3)) print(f"10 - 3 = {resp.data.result}")
class HttpRpcClient(RpcClient): def __init__(self, endpoint_url): super().__init__(endpoint_url) self.client = HTTPClient(endpoint_url) def _request(self, path, **kwargs): # set default requests timeout kwargs['timeout'] = 10 # # add our global requests params # if self._requests_params: # kwargs.update(self._requests_params) kwargs['data'] = kwargs.get('data', None) kwargs['headers'] = kwargs.get('headers', None) # full_path = self._create_path(path) # uri = self._create_uri(full_path) rcp_request = Request(path) if kwargs['data']: rcp_request.update(params=kwargs['data']) response = self.client.send(rcp_request) return self._handle_response(response) @staticmethod def _handle_response(response): """Internal helper for handling API responses from the server. Raises the appropriate exceptions when necessary; otherwise, returns the response. """ try: res = response.raw.json() if 'error' in res and res['error']: raise BinanceChainRPCException(response) # by default return full response # if it's a normal response we have a data attribute, return that if 'result' in res: res = res['result'] return res except ValueError: raise BinanceChainRequestException('Invalid Response: %s' % response.text) def get_path_list(self): return self._request('') def get_abci_info(self): """Get some info about the application. https://binance-chain.github.io/api-reference/node-rpc.html#abciinfo """ return self._request('abci_info') def get_consensus_state(self): """ConsensusState returns a concise summary of the consensus state. UNSTABLE https://binance-chain.github.io/api-reference/node-rpc.html#consensusstate """ return self._request('consensus_state') def dump_consensus_state(self): """DumpConsensusState dumps consensus state. UNSTABLE https://binance-chain.github.io/api-reference/node-rpc.html#dumpconsensusstate """ return self._request('dump_consensus_state') def get_genesis(self): """Get genesis file. https://binance-chain.github.io/api-reference/node-rpc.html#genesis """ return self._request('genesis') def get_net_info(self): """Get network info. https://binance-chain.github.io/api-reference/node-rpc.html#netinfo """ return self._request('net_info') def get_num_unconfirmed_txs(self): """Get number of unconfirmed transactions. https://binance-chain.github.io/api-reference/node-rpc.html#numunconfirmedtxs """ return self._request('num_unconfirmed_txs') def get_status(self): """Get Tendermint status including node info, pubkey, latest block hash, app hash, block height and time. https://binance-chain.github.io/api-reference/node-rpc.html#status """ return self._request('status') def get_health(self): """Get node health. Returns empty result (200 OK) on success, no response - in case of an error. https://binance-chain.github.io/api-reference/node-rpc.html#health """ return self._request('health') def get_unconfirmed_txs(self): """Get unconfirmed transactions (maximum ?limit entries) including their number. https://binance-chain.github.io/api-reference/node-rpc.html#unconfirmedtxs """ return self._request('unconfirmed_txs') def get_validators(self): """Get the validator set at the given block height. If no height is provided, it will fetch the current validator set. https://binance-chain.github.io/api-reference/node-rpc.html#validators """ return self._request('validators') def abci_query(self, data: str, path: Optional[str] = None, prove: Optional[bool] = None, height: Optional[int] = None): """Query the application for some information. https://binance-chain.github.io/api-reference/node-rpc.html#abciquery path string Path to the data ("/a/b/c") data []byte Data height int64 Height (0 means latest) prove bool Includes proof if true """ data = {'data': data} if path: data['path'] = path if prove: data['prove'] = str(prove) if height: data['height'] = str(height) return self._request('abci_query', data=data) def get_block(self, height: int): """Get block at a given height. If no height is provided, it will fetch the latest block. https://binance-chain.github.io/api-reference/node-rpc.html#block height int64 """ data = {'height': str(height)} return self._request('block', data=data) def get_block_result(self, height: int): """BlockResults gets ABCIResults at a given height. If no height is provided, it will fetch results for the latest block. https://binance-chain.github.io/api-reference/node-rpc.html#blockresults height int64 """ data = {'height': str(height)} return self._request('block_result', data=data) def get_block_commit(self, height: int): """Get block commit at a given height. If no height is provided, it will fetch the commit for the latest block. https://binance-chain.github.io/api-reference/node-rpc.html#commit height int64 0 """ data = {'height': str(height)} return self._request('commit', data=data) def get_blockchain_info(self, min_height: int, max_height: int): """Get block headers for minHeight <= height <= maxHeight. Block headers are returned in descending order (highest first). Returns at most 20 items. https://binance-chain.github.io/api-reference/node-rpc.html#blockchaininfo min_height int64 0 max_height int64 0 """ assert max_height > min_height data = {'minHeight': str(min_height), 'maxHeight': str(max_height)} return self._request('blockchain', data=data) def broadcast_tx_async(self, tx: str): """Returns right away, with no response https://binance-chain.github.io/api-reference/node-rpc.html#broadcasttxasync tx str """ data = {'tx': tx} return self._request('broadcast_tx_async', data=data) def broadcast_tx_commit(self, tx: str): """CONTRACT: only returns error if mempool.CheckTx() errs or if we timeout waiting for tx to commit. https://binance-chain.github.io/api-reference/node-rpc.html#broadcasttxcommit tx str """ data = {'tx': tx} return self._request('broadcast_tx_commit', data=data) def broadcast_tx_sync(self, tx: str): """Returns with the response from CheckTx. https://binance-chain.github.io/api-reference/node-rpc.html#broadcasttxsync tx str """ data = {'tx': tx} return self._request('broadcast_tx_sync', data=data) def get_consensus_params(self, height: Optional[int] = None): """Get the consensus parameters at the given block height. If no height is provided, it will fetch the current consensus params. https://binance-chain.github.io/api-reference/node-rpc.html#consensusparams height: int """ data = None if height: data = {'height': str(height)} return self._request('consensus_params', data=data) def get_tx(self, tx_hash: str, prove: Optional[bool] = None): """Tx allows you to query the transaction results. nil could mean the transaction is in the mempool, invalidated, or was not sent in the first place. https://binance-chain.github.io/api-reference/node-rpc.html#tx tx_hash string "" true Query prove bool false false Include proofs of the transactions inclusion in the block """ data = {'hash': tx_hash} if prove: data['prove'] = str(prove) return self._request('tx', data=data) def tx_search(self, query: str, prove: Optional[bool] = None, page: Optional[int] = None, limit: Optional[int] = None): """TxSearch allows you to query for multiple transactions results. It returns a list of transactions (maximum ?per_page entries) and the total count. https://binance-chain.github.io/api-reference/node-rpc.html#txsearch query string "" true Query prove bool false false Include proofs of the transactions inclusion in the block page int 1 false Page number (1-based) per_page int 30 false Number of entries per page (max: 100) """ data = {'query': query} if prove: data['prove'] = str(prove) if page: data['page'] = str(page) if limit: data['limit'] = str(limit) return self._request('tx_search', data=data)
class Client(object): def __init__(self, host='localhost', port=CC_DEFAULT_RPC_PORT, version="2.0", tls=False): self.version = version self.host = host self.port = port self.tls = tls scheme = 'http' if self.tls: scheme += 's' url = '{}://{}:{}'.format(scheme, self.host, self.port) self.http_client = HTTPClient(url) def _call(self, method, parameters, id=1): payload = { "method": method, "params": parameters, "jsonrpc": self.version, "id": id, } response = self.http_client.send(json.dumps(payload)) return response.data.result # ACCOUNTS def create_account(self, passphrase): if not isinstance(passphrase, str): raise TypeError('Parameter "passphrase" must be a string') return self._call("accounts_createAccount", [passphrase]) def unlock_account(self, acc, passphrase): if not isinstance(acc, str): raise TypeError('Parameter "acc" must be a string') if not isinstance(passphrase, str): raise TypeError('Parameter "passphrase" must be a string') return self._call("accounts_unlockAccount", [acc, passphrase]) def lock_account(self, account, token): self.http_client.session.headers.update({"Authorization": "Bearer " + token}) if not isinstance(account, str): raise TypeError('Parameter "account" must be a string') if not isinstance(token, str): raise TypeError('Parameter "token" must be a string') return self._call("accounts_lockAccount", [account]) def delete_account(self, acc, passphrase): if not isinstance(acc, str): raise TypeError('Parameter "acc" must be a string') if not isinstance(passphrase, str): raise TypeError('Parameter "passphrase" must be a string') return self._call("accounts_deleteAccount", [acc, passphrase]) def list_accounts(self): return self._call("accounts_listAccounts", []) # BOOTNODES def get_bootnodes(self): return self._call("bootnodes_getBootnodes", []) def set_bootnodes(self, nodes): if not isinstance(nodes, list): raise TypeError('Parameter "nodes" must be given in a list form') return self._call("bootnodes_setBootnodes", [nodes]) # SWARM SERVICE def run_swarm_service(self, service, nodes): if not isinstance(nodes, list): raise TypeError('Parameter "nodes" must be given in a list form') if not isinstance(service, dict): raise TypeError('Parameter "service" must be a dictionary') return self._call("service_run", [json.dumps(service), nodes]) def leave_swarm_service(self, nodes): if not isinstance(nodes, list): raise TypeError('Parameter "nodes" must be given in a list form') return self._call("service_leave", [nodes]) def remove_swarm_service(self, service_name): if not isinstance(service_name, str): raise TypeError('Parameter "service_name" must be given in a string form') return self._call("service_removeService", service_name) # DISCOVER NODES def discover_nodes(self, num): if not isinstance(num, int): raise TypeError('Parameter "num" must a positive integer') return self._call("discovery_discover", [num]) # DOCKER IMAGE MANAGER def load_image_to_node(self, node_id, image_hash, token): self.http_client.session.headers.update({"Authorization": "Bearer " + token}) if not isinstance(node_id, str): raise TypeError('Parameter "node_id" must be a string') if not isinstance(image_hash, str): raise TypeError('Parameter "image_hash" must be a string') return self._call("imagemanager_pushImage", [node_id, image_hash]) def execute_image(self, node_id, dock_image_id): if not isinstance(node_id, str): raise TypeError('Parameter "node_id" must be a string') if not isinstance(dock_image_id, str): raise TypeError('Parameter "dock_image_id" must be a string') return self._call("imagemanager_runImage", [node_id, dock_image_id]) def inspect_container(self, node_id, dock_cont_id): if not isinstance(node_id, str): raise TypeError('Parameter "node_id" must be a string') if not isinstance(dock_cont_id, str): raise TypeError('Parameter "dock_cont_id" must be a string') return self._call("imagemanager_inspectContainer", [node_id, dock_cont_id]) def list_node_images(self, node_id, token): self.http_client.session.headers.update({"Authorization": "Bearer " + token}) if not isinstance(node_id, str): raise TypeError('Parameter "node_id" must be a string') return self._call("imagemanager_listImages", [node_id]) def list_node_containers(self, node_id, token): self.http_client.session.headers.update({"Authorization": "Bearer " + token}) if not isinstance(node_id, str): raise TypeError('Parameter "node_id" must be a string') return self._call("imagemanager_listContainers", [node_id]) # LEVEL DB def lvldb_stats(self): return self._call("lvldb_getDBStats", []) def lvldb_select_image(self, image_id): if not isinstance(image_id, str): raise TypeError('Parameter "image_id" must be a string') return self._call("lvldb_selectImage", [image_id]) def lvldb_select_image_account(self, image_hash): if not isinstance(image_hash, str): raise TypeError('Parameter "image_id" must be a string') return self._call("lvldb_selectImageAccount", [image_hash]) def lvldb_select_type(self, typeName): if not isinstance(typeName, str): raise TypeError('Parameter "typeName" must be a string') return self._call("lvldb_selectType", [typeName]) def lvldb_select_all(self): return self._call("lvldb_selectAll", [])
def can_send_whisper_to(self, sender_id: str, target_user_name: str) -> (bool, int): url = "{}/{}".format(self.host, self.path_whisper) # might not be an int in some applications try: sender_id = int(sender_id) except ValueError: pass try: request = str( Request( method="whisper.validate", senderId=sender_id, receiverName=target_user_name, )) request_and_hash = self.private_key + request sign_hash = hashlib.md5( request_and_hash.encode('utf-8')).hexdigest() client = HTTPClient(url) client.session.headers.update({ "Content-Type": "application/json-rpc", "X-RPC-SIGN": sign_hash }) response = client.send(request).data except Exception as e: self.logger.error("could not call remote endpoint {}: {}".format( url, str(e))) self.env.capture_exception(sys.exc_info()) self.logger.exception(e) return True, ErrorCodes.REMOTE_ERROR if response is None: self.logger.error("received None response for jsonrpc call") return True, ErrorCodes.OK if not response.ok: self.logger.error( "remote jsonrpc call failed, error_msg: {}".format( str(response))) return True, ErrorCodes.OK self.logger.debug( "response for sender_id {} and target_user_name {}: {}".format( sender_id, target_user_name, str(response))) # '.data' is hinted JSONRPCResponse in lib, but if successful, it's a SuccessResponse, which # has the 'result' variable that JSONRPCResponse doesn't, so add the 'noqa' to skip warnings success = response.result.get('success', 1) # noqa error_msg = response.result.get('error_msg', '[empty error in response]') # noqa error_code = response.result.get('error', '-1') # noqa try: error_code = int(float(error_code)) except Exception as e: self.logger.error( "could not convert error code '{}' to int: {}".format( error_code, str(e))) self.logger.exception(traceback.format_exc()) self.env.capture_exception(sys.exc_info()) errors = { 50000: "generic error", 50001: "only contacts can whisper", 50002: "whisper is turned off", } if error_code in errors.keys(): self.logger.info( "got error code {} '{}' when checking whisper from {} to {}". format(error_code, errors.get(error_code), sender_id, target_user_name)) if error_code == 50001: return False, ErrorCodes.NOT_ALLOWED_TO_WHISPER_NOT_A_CONTACT elif error_code == 50002: return False, ErrorCodes.NOT_ALLOWED_TO_WHISPER_TURNED_OFF elif error_code == 50000 and error_msg == "whisper self": return False, ErrorCodes.NOT_ALLOWED_TO_WHISPER_SELF elif error_code == 50000: return False, ErrorCodes.NOT_ALLOWED_TO_WHISPER_GENERIC_ERROR return success == 1, ErrorCodes.OK