more cleaning up
This commit is contained in:
parent
aecafbbebd
commit
4d79a7828c
7 changed files with 276 additions and 222 deletions
|
@ -45,10 +45,7 @@ KNOWN_DHT_NODES = [('104.236.42.182', 4000),
|
|||
POINTTRADER_SERVER = 'http://ec2-54-187-192-68.us-west-2.compute.amazonaws.com:2424'
|
||||
#POINTTRADER_SERVER = 'http://127.0.0.1:2424'
|
||||
|
||||
if IS_DEVELOPMENT_VERSION:
|
||||
SEARCH_SERVERS = ["http://107.170.207.64:50005"]
|
||||
else:
|
||||
SEARCH_SERVERS = ["http://lighthouse1.lbry.io:50005",
|
||||
SEARCH_SERVERS = ["http://lighthouse1.lbry.io:50005",
|
||||
"http://lighthouse2.lbry.io:50005",
|
||||
"http://lighthouse3.lbry.io:50005"]
|
||||
|
||||
|
@ -67,6 +64,9 @@ if os.name == "nt":
|
|||
else:
|
||||
ICON_PATH = "app.icns"
|
||||
APP_NAME = "LBRY"
|
||||
|
||||
ORIGIN = "http://%s:%i" % (API_INTERFACE, API_PORT)
|
||||
REFERER = "http://%s:%i/" % (API_INTERFACE, API_PORT)
|
||||
API_CONNECTION_STRING = "http://%s:%i/%s" % (API_INTERFACE, API_PORT, API_ADDRESS)
|
||||
UI_ADDRESS = "http://%s:%i" % (API_INTERFACE, API_PORT)
|
||||
PROTOCOL_PREFIX = "lbry"
|
||||
|
@ -88,11 +88,6 @@ CURRENCIES = {
|
|||
'USD': {'type': 'fiat'},
|
||||
}
|
||||
|
||||
ALLOWED_DURING_STARTUP = ['is_running', 'is_first_run',
|
||||
'get_time_behind_blockchain', 'stop',
|
||||
'daemon_status', 'get_start_notice',
|
||||
'version', 'get_search_servers']
|
||||
|
||||
LOGGLY_TOKEN = 'LJEzATH4AzRgAwxjAP00LwZ2YGx3MwVgZTMuBQZ3MQuxLmOv'
|
||||
|
||||
ANALYTICS_ENDPOINT = 'https://api.segment.io/v1'
|
||||
|
|
|
@ -94,3 +94,6 @@ class InvalidHeaderError(Exception):
|
|||
|
||||
class InvalidAuthenticationToken(Exception):
|
||||
pass
|
||||
|
||||
class SubhandlerError(Exception):
|
||||
pass
|
|
@ -40,7 +40,8 @@ from lbrynet.lbrynet_daemon.LBRYDownloader import GetStream
|
|||
from lbrynet.lbrynet_daemon.LBRYPublisher import Publisher
|
||||
from lbrynet.lbrynet_daemon.LBRYExchangeRateManager import ExchangeRateManager
|
||||
from lbrynet.lbrynet_daemon.Lighthouse import LighthouseClient
|
||||
from lbrynet.lbrynet_daemon.auth.server import LBRYJSONRPCServer, auth_required, authorizer
|
||||
from lbrynet.lbrynet_daemon.auth.server import AuthJSONRPCServer
|
||||
from lbrynet.lbrynet_daemon.auth.util import get_auth_message
|
||||
from lbrynet.metadata.LBRYMetadata import Metadata, verify_name_characters
|
||||
from lbrynet.core import log_support
|
||||
from lbrynet.core import utils
|
||||
|
@ -49,7 +50,7 @@ from lbrynet.lbrynet_console.LBRYSettings import LBRYSettings
|
|||
from lbrynet.conf import MIN_BLOB_DATA_PAYMENT_RATE, DEFAULT_MAX_SEARCH_RESULTS, \
|
||||
KNOWN_DHT_NODES, DEFAULT_MAX_KEY_FEE, DEFAULT_WALLET, \
|
||||
DEFAULT_SEARCH_TIMEOUT, DEFAULT_CACHE_TIME, DEFAULT_UI_BRANCH, \
|
||||
LOG_POST_URL, LOG_FILE_NAME, REFLECTOR_SERVERS, SEARCH_SERVERS, ALLOWED_DURING_STARTUP
|
||||
LOG_POST_URL, LOG_FILE_NAME, REFLECTOR_SERVERS, SEARCH_SERVERS
|
||||
from lbrynet.conf import DEFAULT_SD_DOWNLOAD_TIMEOUT
|
||||
from lbrynet.conf import DEFAULT_TIMEOUT
|
||||
from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier, download_sd_blob, BlobStreamDescriptorReader
|
||||
|
@ -122,10 +123,8 @@ BAD_REQUEST = 400
|
|||
NOT_FOUND = 404
|
||||
OK_CODE = 200
|
||||
|
||||
# TODO add login credentials in a conf file
|
||||
# TODO alert if your copy of a lbry file is out of date with the name record
|
||||
|
||||
|
||||
REMOTE_SERVER = "www.google.com"
|
||||
|
||||
|
||||
|
@ -134,14 +133,17 @@ class Parameters(object):
|
|||
self.__dict__.update(kwargs)
|
||||
|
||||
|
||||
@authorizer
|
||||
class LBRYDaemon(LBRYJSONRPCServer):
|
||||
class LBRYDaemon(AuthJSONRPCServer):
|
||||
"""
|
||||
LBRYnet daemon, a jsonrpc interface to lbry functions
|
||||
"""
|
||||
|
||||
def __init__(self, root, wallet_type=None):
|
||||
LBRYJSONRPCServer.__init__(self)
|
||||
AuthJSONRPCServer.__init__(self)
|
||||
self.allowed_during_startup = ['is_running', 'is_first_run',
|
||||
'get_time_behind_blockchain', 'stop',
|
||||
'daemon_status', 'get_start_notice',
|
||||
'version', 'get_search_servers']
|
||||
reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
|
||||
|
||||
self.startup_status = STARTUP_STAGES[0]
|
||||
|
@ -392,6 +394,17 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
f.write("rpcpassword=" + password)
|
||||
log.info("Done writing lbrycrd.conf")
|
||||
|
||||
@AuthJSONRPCServer.subhandler
|
||||
def _exclude_lbrycrd_only_commands_from_lbryum_session(self, request):
|
||||
request.content.seek(0, 0)
|
||||
content = request.content.read()
|
||||
parsed = jsonrpclib.loads(content)
|
||||
function_path = parsed.get("method")
|
||||
if self.wallet_type == "lbryum" and function_path in ['set_miner', 'get_miner_status']:
|
||||
log.warning("Mining commands are not available in lbryum")
|
||||
raise Exception("Command not available in lbryum")
|
||||
return True
|
||||
|
||||
def setup(self, branch=DEFAULT_UI_BRANCH, user_specified=False, branch_specified=False, host_ui=True):
|
||||
def _log_starting_vals():
|
||||
log.info("Starting balance: " + str(self.session.wallet.wallet_balance))
|
||||
|
@ -1337,7 +1350,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
def _search(self, search):
|
||||
return self.lighthouse_client.search(search)
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_is_running(self):
|
||||
"""
|
||||
Check if lbrynet daemon is running
|
||||
|
@ -1354,7 +1367,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
else:
|
||||
return self._render_response(False, OK_CODE)
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_daemon_status(self):
|
||||
"""
|
||||
Get lbrynet daemon status information
|
||||
|
@ -1386,10 +1398,8 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
else:
|
||||
r['message'] = "Catching up with the blockchain"
|
||||
r['progress'] = 0
|
||||
log.info("daemon status: " + str(r))
|
||||
return self._render_response(r, OK_CODE)
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_is_first_run(self):
|
||||
"""
|
||||
Check if this is the first time lbrynet daemon has been run
|
||||
|
@ -1410,7 +1420,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_get_start_notice(self):
|
||||
"""
|
||||
Get special message to be displayed at startup
|
||||
|
@ -1430,7 +1439,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
else:
|
||||
self._render_response(self.startup_message, OK_CODE)
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_version(self):
|
||||
"""
|
||||
Get lbry version information
|
||||
|
@ -1465,7 +1473,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
log.info("Get version info: " + json.dumps(msg))
|
||||
return self._render_response(msg, OK_CODE)
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_get_settings(self):
|
||||
"""
|
||||
Get lbrynet daemon settings
|
||||
|
@ -1494,7 +1502,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
log.info("Get daemon settings")
|
||||
return self._render_response(self.session_settings, OK_CODE)
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_set_settings(self, p):
|
||||
"""
|
||||
Set lbrynet daemon settings
|
||||
|
@ -1522,7 +1530,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_help(self, p=None):
|
||||
"""
|
||||
Function to retrieve docstring for API function
|
||||
|
@ -1537,17 +1544,17 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
"""
|
||||
|
||||
if not p:
|
||||
return self._render_response(self._listFunctions(), OK_CODE)
|
||||
return self._render_response(self.callable_methods.keys(), OK_CODE)
|
||||
elif 'callable_during_start' in p.keys():
|
||||
return self._render_response(ALLOWED_DURING_STARTUP, OK_CODE)
|
||||
return self._render_response(self.allowed_during_startup, OK_CODE)
|
||||
elif 'function' in p.keys():
|
||||
func_path = p['function']
|
||||
function = self._getFunction(func_path)
|
||||
function = self.callable_methods.get(func_path)
|
||||
return self._render_response(function.__doc__, OK_CODE)
|
||||
else:
|
||||
return self._render_response(self.jsonrpc_help.__doc__, OK_CODE)
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_get_balance(self):
|
||||
"""
|
||||
Get balance
|
||||
|
@ -1561,7 +1568,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
log.info("Get balance")
|
||||
return self._render_response(float(self.session.wallet.wallet_balance), OK_CODE)
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_stop(self):
|
||||
"""
|
||||
Stop lbrynet-daemon
|
||||
|
@ -1581,7 +1587,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
|
||||
return self._render_response("Shutting down", OK_CODE)
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_get_lbry_files(self):
|
||||
"""
|
||||
Get LBRY files
|
||||
|
@ -1608,7 +1614,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_get_lbry_file(self, p):
|
||||
"""
|
||||
Get lbry file
|
||||
|
@ -1638,7 +1644,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_resolve_name(self, p):
|
||||
"""
|
||||
Resolve stream info from a LBRY uri
|
||||
|
@ -1660,7 +1665,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallbacks(lambda info: self._render_response(info, OK_CODE), lambda _: server.failure)
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_get_claim_info(self, p):
|
||||
"""
|
||||
Resolve claim info from a LBRY uri
|
||||
|
@ -1685,7 +1689,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def _process_get_parameters(self, p):
|
||||
"""Extract info from input parameters and fill in default values for `get` call."""
|
||||
# TODO: this process can be abstracted s.t. each method
|
||||
|
@ -1707,7 +1711,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
name=name
|
||||
)
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_get(self, p):
|
||||
"""Download stream from a LBRY uri.
|
||||
|
||||
|
@ -1738,7 +1742,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda message: self._render_response(message, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_stop_lbry_file(self, p):
|
||||
"""
|
||||
Stop lbry file
|
||||
|
@ -1764,7 +1768,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_start_lbry_file(self, p):
|
||||
"""
|
||||
Stop lbry file
|
||||
|
@ -1789,7 +1793,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_get_est_cost(self, p):
|
||||
"""
|
||||
Get estimated cost for a lbry uri
|
||||
|
@ -1811,7 +1814,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_search_nametrie(self, p):
|
||||
"""
|
||||
Search the nametrie for claims
|
||||
|
@ -1848,7 +1851,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_delete_lbry_file(self, p):
|
||||
"""
|
||||
Delete a lbry file
|
||||
|
@ -1878,7 +1881,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_publish(self, p):
|
||||
"""
|
||||
Make a new name claim and publish associated data to lbrynet
|
||||
|
@ -1955,7 +1958,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_abandon_claim(self, p):
|
||||
"""
|
||||
Abandon a name and reclaim credits from the claim
|
||||
|
@ -1982,7 +1985,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_abandon_name(self, p):
|
||||
"""
|
||||
DEPRECIATED, use abandon_claim
|
||||
|
@ -1995,7 +1998,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
|
||||
return self.jsonrpc_abandon_claim(p)
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_support_claim(self, p):
|
||||
"""
|
||||
Support a name claim
|
||||
|
@ -2015,7 +2018,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_get_name_claims(self):
|
||||
"""
|
||||
Get my name claims
|
||||
|
@ -2039,7 +2042,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_get_claims_for_name(self, p):
|
||||
"""
|
||||
Get claims for a name
|
||||
|
@ -2055,7 +2057,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_get_transaction_history(self):
|
||||
"""
|
||||
Get transaction history
|
||||
|
@ -2070,7 +2072,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_get_transaction(self, p):
|
||||
"""
|
||||
Get a decoded transaction from a txid
|
||||
|
@ -2087,7 +2088,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_address_is_mine(self, p):
|
||||
"""
|
||||
Checks if an address is associated with the current wallet.
|
||||
|
@ -2105,7 +2106,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_get_public_key_from_wallet(self, p):
|
||||
"""
|
||||
Get public key from wallet address
|
||||
|
@ -2120,7 +2121,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d = self.session.wallet.get_pub_keys(wallet)
|
||||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_get_time_behind_blockchain(self):
|
||||
"""
|
||||
Get number of blocks behind the blockchain
|
||||
|
@ -2144,7 +2144,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_get_new_address(self):
|
||||
"""
|
||||
Generate a new wallet address
|
||||
|
@ -2164,7 +2164,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda address: self._render_response(address, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_send_amount_to_address(self, p):
|
||||
"""
|
||||
Send credits to an address
|
||||
|
@ -2189,7 +2189,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda _: self._render_response(True, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_get_best_blockhash(self):
|
||||
"""
|
||||
Get hash of most recent block
|
||||
|
@ -2204,7 +2203,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_get_block(self, p):
|
||||
"""
|
||||
Get contents of a block
|
||||
|
@ -2227,7 +2225,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_get_claims_for_tx(self, p):
|
||||
"""
|
||||
Get claims for tx
|
||||
|
@ -2247,7 +2244,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_download_descriptor(self, p):
|
||||
"""
|
||||
Download and return a sd blob
|
||||
|
@ -2264,7 +2261,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallbacks(lambda r: self._render_response(r, OK_CODE), lambda _: self._render_response(False, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_get_nametrie(self):
|
||||
"""
|
||||
Get the nametrie
|
||||
|
@ -2280,7 +2276,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_set_miner(self, p):
|
||||
"""
|
||||
Start of stop the miner, function only available when lbrycrd is set as the wallet
|
||||
|
@ -2300,7 +2296,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_get_miner_status(self):
|
||||
"""
|
||||
Get status of miner
|
||||
|
@ -2315,7 +2311,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_log(self, p):
|
||||
"""
|
||||
Log message
|
||||
|
@ -2330,7 +2325,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
log.info("API client log request: %s" % message)
|
||||
return self._render_response(True, OK_CODE)
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_upload_log(self, p=None):
|
||||
"""
|
||||
Upload log
|
||||
|
@ -2372,7 +2366,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda _: self._render_response(True, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_configure_ui(self, p):
|
||||
"""
|
||||
Configure the UI being hosted
|
||||
|
@ -2397,7 +2391,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_reveal(self, p):
|
||||
"""
|
||||
Reveal a file or directory in file browser
|
||||
|
@ -2417,7 +2411,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda _: self._render_response(True, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_get_peers_for_hash(self, p):
|
||||
"""
|
||||
Get peers for blob hash
|
||||
|
@ -2435,7 +2429,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_announce_all_blobs_to_dht(self):
|
||||
"""
|
||||
Announce all blobs to the dht
|
||||
|
@ -2450,7 +2444,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda _: self._render_response("Announced", OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_reflect(self, p):
|
||||
"""
|
||||
Reflect a stream
|
||||
|
@ -2467,7 +2461,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallbacks(lambda _: self._render_response(True, OK_CODE), lambda err: self._render_response(err.getTraceback(), OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_get_blob_hashes(self):
|
||||
"""
|
||||
Returns all blob hashes
|
||||
|
@ -2482,7 +2476,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
@AuthJSONRPCServer.auth_required
|
||||
def jsonrpc_reflect_all_blobs(self):
|
||||
"""
|
||||
Reflects all saved blobs
|
||||
|
@ -2498,20 +2492,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
|
|||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
@auth_required
|
||||
def jsonrpc_get_search_servers(self):
|
||||
"""
|
||||
Get list of lighthouse servers
|
||||
|
||||
Args:
|
||||
None
|
||||
Returns:
|
||||
List of address:port
|
||||
"""
|
||||
|
||||
d = self._render_response(SEARCH_SERVERS, OK_CODE)
|
||||
return d
|
||||
|
||||
|
||||
def get_lbrynet_version_from_github():
|
||||
"""Return the latest released version from github."""
|
||||
|
|
|
@ -14,7 +14,7 @@ class HttpPasswordRealm(object):
|
|||
self.resource = resource
|
||||
|
||||
def requestAvatar(self, avatarId, mind, *interfaces):
|
||||
log.info("Processing request for %s", avatarId)
|
||||
log.debug("Processing request for %s", avatarId)
|
||||
if resource.IResource in interfaces:
|
||||
return (resource.IResource, self.resource, lambda: None)
|
||||
raise NotImplementedError()
|
||||
|
|
|
@ -5,7 +5,7 @@ import os
|
|||
import base64
|
||||
import json
|
||||
|
||||
from lbrynet.lbrynet_daemon.auth.util import load_api_keys, APIKey, API_KEY_NAME
|
||||
from lbrynet.lbrynet_daemon.auth.util import load_api_keys, APIKey, API_KEY_NAME, get_auth_message
|
||||
from lbrynet.conf import API_INTERFACE, API_ADDRESS, API_PORT
|
||||
from lbrynet.conf import DATA_DIR
|
||||
|
||||
|
@ -55,8 +55,8 @@ class LBRYAPIClient(object):
|
|||
'method': self.__service_name,
|
||||
'params': args,
|
||||
'id': self.__id_count}
|
||||
to_auth = str(pre_auth_postdata['method']).encode('hex') + str(pre_auth_postdata['id']).encode('hex')
|
||||
token = self.__api_key.get_hmac(to_auth.decode('hex'))
|
||||
to_auth = get_auth_message(pre_auth_postdata)
|
||||
token = self.__api_key.get_hmac(to_auth)
|
||||
pre_auth_postdata.update({'hmac': token})
|
||||
postdata = json.dumps(pre_auth_postdata)
|
||||
service_url = self.__service_url
|
||||
|
@ -79,16 +79,13 @@ class LBRYAPIClient(object):
|
|||
next_secret = headers.get(LBRY_SECRET, False)
|
||||
|
||||
if next_secret:
|
||||
# print "Next secret: %s" % next_secret
|
||||
self.__api_key.secret = next_secret
|
||||
self.__cookies = cookies
|
||||
|
||||
# print "Postdata: %s" % postdata
|
||||
if http_response is None:
|
||||
raise JSONRPCException({
|
||||
'code': -342, 'message': 'missing HTTP response from server'})
|
||||
|
||||
# print "-----\n%s\n------" % http_response.text
|
||||
http_response.raise_for_status()
|
||||
|
||||
response = http_response.json()
|
||||
|
@ -104,20 +101,18 @@ class LBRYAPIClient(object):
|
|||
@classmethod
|
||||
def config(cls, key_name=None, key=None, pw_path=None, timeout=HTTP_TIMEOUT, connection=None, count=0,
|
||||
service=None, cookies=None, auth=None, url=None, login_url=None):
|
||||
|
||||
api_key_name = API_KEY_NAME if not key_name else key_name
|
||||
pw_path = os.path.join(DATA_DIR, ".api_keys") if not pw_path else pw_path
|
||||
|
||||
if not key:
|
||||
keys = load_api_keys(pw_path)
|
||||
api_key = keys.get(api_key_name, False)
|
||||
else:
|
||||
api_key = APIKey(name=api_key_name, secret=key)
|
||||
|
||||
if login_url is None:
|
||||
service_url = "http://%s:%s@%s:%i/%s" % (api_key_name, api_key.secret, API_INTERFACE, API_PORT, API_ADDRESS)
|
||||
else:
|
||||
service_url = login_url
|
||||
|
||||
id_count = count
|
||||
|
||||
if auth is None and connection is None and cookies is None and url is None:
|
||||
|
@ -134,10 +129,8 @@ class LBRYAPIClient(object):
|
|||
pass
|
||||
authpair = user + b':' + passwd
|
||||
auth_header = b'Basic ' + base64.b64encode(authpair)
|
||||
|
||||
conn = requests.Session()
|
||||
conn.auth = (user, passwd)
|
||||
|
||||
req = requests.Request(method='POST',
|
||||
url=service_url,
|
||||
auth=conn.auth,
|
||||
|
@ -148,11 +141,9 @@ class LBRYAPIClient(object):
|
|||
r = req.prepare()
|
||||
http_response = conn.send(r)
|
||||
cookies = http_response.cookies
|
||||
# print "Logged in"
|
||||
|
||||
uid = cookies.get(TWISTED_SESSION)
|
||||
api_key = APIKey.new(seed=uid)
|
||||
# print "Created temporary api key"
|
||||
|
||||
else:
|
||||
# This is a client that already has a session, use it
|
||||
auth_header = auth
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
import logging
|
||||
|
||||
from decimal import Decimal
|
||||
from twisted.web import server
|
||||
from zope.interface import implements
|
||||
from twisted.web import server, resource
|
||||
from twisted.internet import defer
|
||||
from txjsonrpc import jsonrpclib
|
||||
from txjsonrpc.web import jsonrpc
|
||||
from txjsonrpc.web.jsonrpc import Handler
|
||||
|
||||
from lbrynet.core.Error import InvalidAuthenticationToken, InvalidHeaderError
|
||||
from lbrynet.lbrynet_daemon.auth.util import APIKey
|
||||
from lbrynet.core.Error import InvalidAuthenticationToken, InvalidHeaderError, SubhandlerError
|
||||
from lbrynet.conf import API_INTERFACE, REFERER, ORIGIN
|
||||
from lbrynet.lbrynet_daemon.auth.util import APIKey, get_auth_message
|
||||
from lbrynet.lbrynet_daemon.auth.client import LBRY_SECRET
|
||||
from lbrynet.conf import ALLOWED_DURING_STARTUP
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -20,42 +19,166 @@ def default_decimal(obj):
|
|||
return float(obj)
|
||||
|
||||
|
||||
def authorizer(cls):
|
||||
cls.authorized_functions = []
|
||||
for methodname in dir(cls):
|
||||
class AuthorizedBase(object):
|
||||
def __init__(self):
|
||||
self.authorized_functions = []
|
||||
self.subhandlers = []
|
||||
self.callable_methods = {}
|
||||
|
||||
for methodname in dir(self):
|
||||
if methodname.startswith("jsonrpc_"):
|
||||
method = getattr(cls, methodname)
|
||||
method = getattr(self, methodname)
|
||||
self.callable_methods.update({methodname.split("jsonrpc_")[1]: method})
|
||||
if hasattr(method, '_auth_required'):
|
||||
cls.authorized_functions.append(methodname.split("jsonrpc_")[1])
|
||||
return cls
|
||||
self.authorized_functions.append(methodname.split("jsonrpc_")[1])
|
||||
elif not methodname.startswith("__"):
|
||||
method = getattr(self, methodname)
|
||||
if hasattr(method, '_subhandler'):
|
||||
self.subhandlers.append(method)
|
||||
|
||||
|
||||
def auth_required(f):
|
||||
@staticmethod
|
||||
def auth_required(f):
|
||||
f._auth_required = True
|
||||
return f
|
||||
|
||||
@staticmethod
|
||||
def subhandler(f):
|
||||
f._subhandler = True
|
||||
return f
|
||||
|
||||
@authorizer
|
||||
class LBRYJSONRPCServer(jsonrpc.JSONRPC):
|
||||
|
||||
class AuthJSONRPCServer(AuthorizedBase):
|
||||
"""
|
||||
Authorized JSONRPC server used as the base class for the LBRY API
|
||||
|
||||
API methods are named with a leading "jsonrpc_"
|
||||
|
||||
Decorators:
|
||||
@AuthJSONRPCServer.auth_required: this requires the client include a valid hmac authentication token in their
|
||||
request
|
||||
|
||||
@AuthJSONRPCServer.subhandler: include the tagged method in the processing of requests, to allow inheriting
|
||||
classes to modify request handling. Tagged methods will be passed the request
|
||||
object, and return True when finished to indicate success
|
||||
|
||||
Attributes:
|
||||
allowed_during_startup (list): list of api methods that are callable before the server has finished
|
||||
startup
|
||||
|
||||
sessions (dict): dictionary of active session_id: lbrynet.lbrynet_daemon.auth.util.APIKey values
|
||||
|
||||
authorized_functions (list): list of api methods that require authentication
|
||||
|
||||
subhandlers (list): list of subhandlers
|
||||
|
||||
callable_methods (dict): dictionary of api_callable_name: method values
|
||||
"""
|
||||
implements(resource.IResource)
|
||||
|
||||
isLeaf = True
|
||||
OK = 200
|
||||
UNAUTHORIZED = 401
|
||||
NOT_FOUND = 8001
|
||||
FAILURE = 8002
|
||||
|
||||
def __init__(self):
|
||||
jsonrpc.JSONRPC.__init__(self)
|
||||
AuthorizedBase.__init__(self)
|
||||
self.allowed_during_startup = []
|
||||
self.sessions = {}
|
||||
|
||||
def setup(self):
|
||||
return NotImplementedError()
|
||||
|
||||
def render(self, request):
|
||||
assert self._check_headers(request), InvalidHeaderError
|
||||
|
||||
session = request.getSession()
|
||||
session_id = session.uid
|
||||
|
||||
# if this is a new session, send a new secret and set the expiration, otherwise, session.touch()
|
||||
if self._initialize_session(session_id):
|
||||
def expire_session():
|
||||
self._unregister_user_session(session_id)
|
||||
session.startCheckingExpiration()
|
||||
session.notifyOnExpire(expire_session)
|
||||
message = "OK"
|
||||
request.setResponseCode(self.OK)
|
||||
self._set_headers(request, message, True)
|
||||
self._render_message(request, message)
|
||||
return server.NOT_DONE_YET
|
||||
session.touch()
|
||||
|
||||
request.content.seek(0, 0)
|
||||
content = request.content.read()
|
||||
try:
|
||||
parsed = jsonrpclib.loads(content)
|
||||
except ValueError:
|
||||
return server.failure
|
||||
|
||||
function_name = parsed.get('method')
|
||||
args = parsed.get('params')
|
||||
id = parsed.get('id')
|
||||
token = parsed.pop('hmac', None)
|
||||
version = self._get_jsonrpc_version(parsed.get('jsonrpc'), id)
|
||||
|
||||
try:
|
||||
self._run_subhandlers(request)
|
||||
except SubhandlerError:
|
||||
return server.failure
|
||||
|
||||
reply_with_next_secret = False
|
||||
if function_name in self.authorized_functions:
|
||||
try:
|
||||
self._verify_token(session_id, parsed, token)
|
||||
except InvalidAuthenticationToken:
|
||||
log.warning("API validation failed")
|
||||
request.setResponseCode(self.UNAUTHORIZED)
|
||||
request.finish()
|
||||
return server.NOT_DONE_YET
|
||||
self._update_session_secret(session_id)
|
||||
reply_with_next_secret = True
|
||||
|
||||
try:
|
||||
function = self._get_jsonrpc_method(function_name)
|
||||
except Exception:
|
||||
log.warning("Unknown method: %s", function_name)
|
||||
return server.failure
|
||||
|
||||
d = defer.maybeDeferred(function) if args == [{}] else defer.maybeDeferred(function, *args)
|
||||
# cancel the response if the connection is broken
|
||||
notify_finish = request.notifyFinish()
|
||||
notify_finish.addErrback(self._response_failed, d)
|
||||
d.addErrback(self._errback_render, id)
|
||||
d.addCallback(self._callback_render, request, id, version, reply_with_next_secret)
|
||||
d.addErrback(notify_finish.errback)
|
||||
|
||||
return server.NOT_DONE_YET
|
||||
|
||||
def _register_user_session(self, session_id):
|
||||
"""
|
||||
Add or update a HMAC secret for a session
|
||||
|
||||
@param session_id:
|
||||
@return: secret
|
||||
"""
|
||||
token = APIKey.new()
|
||||
self.sessions.update({session_id: token})
|
||||
return token
|
||||
|
||||
def _responseFailed(self, err, call):
|
||||
def _unregister_user_session(self, session_id):
|
||||
log.info("Unregister API session")
|
||||
del self.sessions[session_id]
|
||||
|
||||
def _response_failed(self, err, call):
|
||||
log.debug(err.getTraceback())
|
||||
|
||||
def _set_headers(self, request, data):
|
||||
request.setHeader("Access-Control-Allow-Origin", "localhost")
|
||||
def _set_headers(self, request, data, update_secret=False):
|
||||
request.setHeader("Access-Control-Allow-Origin", API_INTERFACE)
|
||||
request.setHeader("Content-Type", "text/json")
|
||||
request.setHeader("Content-Length", str(len(data)))
|
||||
if update_secret:
|
||||
session_id = request.getSession().uid
|
||||
request.setHeader(LBRY_SECRET, self.sessions.get(session_id).secret)
|
||||
|
||||
def _render_message(self, request, message):
|
||||
request.write(message)
|
||||
|
@ -64,112 +187,81 @@ class LBRYJSONRPCServer(jsonrpc.JSONRPC):
|
|||
def _check_headers(self, request):
|
||||
origin = request.getHeader("Origin")
|
||||
referer = request.getHeader("Referer")
|
||||
|
||||
if origin not in [None, 'http://localhost:5279']:
|
||||
if origin not in [None, ORIGIN]:
|
||||
log.warning("Attempted api call from %s", origin)
|
||||
raise InvalidHeaderError
|
||||
|
||||
if referer is not None and not referer.startswith('http://localhost:5279/'):
|
||||
return False
|
||||
if referer is not None and not referer.startswith(REFERER):
|
||||
log.warning("Attempted api call from %s", referer)
|
||||
raise InvalidHeaderError
|
||||
return False
|
||||
return True
|
||||
|
||||
def _handle(self, request):
|
||||
def _check_function_path(function_path):
|
||||
def _check_function_path(self, function_path):
|
||||
if function_path not in self.callable_methods:
|
||||
log.warning("Unknown method: %s", function_path)
|
||||
return False
|
||||
if not self.announced_startup:
|
||||
if function_path not in ALLOWED_DURING_STARTUP:
|
||||
if function_path not in self.allowed_during_startup:
|
||||
log.warning("Cannot call %s during startup", function_path)
|
||||
raise Exception("Function not allowed")
|
||||
return False
|
||||
return True
|
||||
|
||||
def _get_function(function_path):
|
||||
function = self._getFunction(function_path)
|
||||
return function
|
||||
def _get_jsonrpc_method(self, function_path):
|
||||
assert self._check_function_path(function_path)
|
||||
return self.callable_methods.get(function_path)
|
||||
|
||||
def _verify_token(session_id, message, token):
|
||||
request.setHeader(LBRY_SECRET, "")
|
||||
api_key = self.sessions.get(session_id, None)
|
||||
assert api_key is not None, InvalidAuthenticationToken
|
||||
r = api_key.compare_hmac(message, token)
|
||||
assert r, InvalidAuthenticationToken
|
||||
def _initialize_session(self, session_id):
|
||||
if not self.sessions.get(session_id, False):
|
||||
log.info("Initializing new api session")
|
||||
self.sessions.update({session_id: APIKey.new(seed=session_id, name=session_id)})
|
||||
return True
|
||||
return False
|
||||
|
||||
def _verify_token(self, session_id, message, token):
|
||||
to_auth = get_auth_message(message)
|
||||
api_key = self.sessions.get(session_id)
|
||||
assert api_key.compare_hmac(to_auth, token), InvalidAuthenticationToken
|
||||
|
||||
def _update_session_secret(self, session_id):
|
||||
# log.info("Generating new token for next request")
|
||||
self.sessions.update({session_id: APIKey.new(name=session_id)})
|
||||
request.setHeader(LBRY_SECRET, self.sessions.get(session_id).secret)
|
||||
|
||||
session = request.getSession()
|
||||
session_id = session.uid
|
||||
session_store = self.sessions.get(session_id, False)
|
||||
|
||||
if not session_store:
|
||||
token = APIKey.new(seed=session_id, name=session_id)
|
||||
log.info("Initializing new api session")
|
||||
self.sessions.update({session_id: token})
|
||||
# log.info("Generated token %s", str(self.sessions[session_id]))
|
||||
|
||||
request.content.seek(0, 0)
|
||||
content = request.content.read()
|
||||
|
||||
parsed = jsonrpclib.loads(content)
|
||||
|
||||
functionPath = parsed.get("method")
|
||||
|
||||
_check_function_path(functionPath)
|
||||
require_auth = functionPath in self.authorized_functions
|
||||
if require_auth:
|
||||
token = parsed.pop('hmac')
|
||||
to_auth = functionPath.encode('hex') + str(parsed.get('id')).encode('hex')
|
||||
_verify_token(session_id, to_auth.decode('hex'), token)
|
||||
|
||||
args = parsed.get('params')
|
||||
id = parsed.get('id')
|
||||
version = parsed.get('jsonrpc')
|
||||
|
||||
def _get_jsonrpc_version(self, version=None, id=None):
|
||||
if version:
|
||||
version = int(float(version))
|
||||
version_for_return = int(float(version))
|
||||
elif id and not version:
|
||||
version = jsonrpclib.VERSION_1
|
||||
version_for_return = jsonrpclib.VERSION_1
|
||||
else:
|
||||
version = jsonrpclib.VERSION_PRE1
|
||||
|
||||
if self.wallet_type == "lbryum" and functionPath in ['set_miner', 'get_miner_status']:
|
||||
log.warning("Mining commands are not available in lbryum")
|
||||
raise Exception("Command not available in lbryum")
|
||||
version_for_return = jsonrpclib.VERSION_PRE1
|
||||
return version_for_return
|
||||
|
||||
def _run_subhandlers(self, request):
|
||||
for handler in self.subhandlers:
|
||||
try:
|
||||
function = _get_function(functionPath)
|
||||
if args == [{}]:
|
||||
d = defer.maybeDeferred(function)
|
||||
else:
|
||||
d = defer.maybeDeferred(function, *args)
|
||||
except jsonrpclib.Fault as f:
|
||||
d = self._cbRender(f, request, id, version)
|
||||
finally:
|
||||
# cancel the response if the connection is broken
|
||||
notify_finish = request.notifyFinish()
|
||||
notify_finish.addErrback(self._responseFailed, d)
|
||||
d.addErrback(self._ebRender, id)
|
||||
d.addCallback(self._cbRender, request, id, version)
|
||||
d.addErrback(notify_finish.errback)
|
||||
assert handler(request)
|
||||
except Exception as err:
|
||||
log.error(err.message)
|
||||
raise SubhandlerError
|
||||
|
||||
def _cbRender(self, result, request, id, version):
|
||||
if isinstance(result, Handler):
|
||||
result = result.result
|
||||
|
||||
if isinstance(result, dict):
|
||||
result = result['result']
|
||||
def _callback_render(self, result, request, id, version, auth_required=False):
|
||||
result_for_return = result if not isinstance(result, dict) else result['result']
|
||||
|
||||
if version == jsonrpclib.VERSION_PRE1:
|
||||
if not isinstance(result, jsonrpclib.Fault):
|
||||
result = (result,)
|
||||
result_for_return = (result_for_return,)
|
||||
# Convert the result (python) to JSON-RPC
|
||||
try:
|
||||
s = jsonrpclib.dumps(result, version=version, default=default_decimal)
|
||||
self._render_message(request, s)
|
||||
encoded_message = jsonrpclib.dumps(result_for_return, version=version, default=default_decimal)
|
||||
self._set_headers(request, encoded_message, auth_required)
|
||||
self._render_message(request, encoded_message)
|
||||
except:
|
||||
f = jsonrpclib.Fault(self.FAILURE, "can't serialize output")
|
||||
s = jsonrpclib.dumps(f, version=version)
|
||||
self._set_headers(request, s)
|
||||
self._render_message(request, s)
|
||||
fault = jsonrpclib.Fault(self.FAILURE, "can't serialize output")
|
||||
encoded_message = jsonrpclib.dumps(fault, version=version)
|
||||
self._set_headers(request, encoded_message)
|
||||
self._render_message(request, encoded_message)
|
||||
|
||||
def _ebRender(self, failure, id):
|
||||
def _errback_render(self, failure, id):
|
||||
log.error("Request failed:")
|
||||
log.error(failure)
|
||||
log.error(failure.value)
|
||||
log.error(id)
|
||||
|
@ -177,19 +269,6 @@ class LBRYJSONRPCServer(jsonrpc.JSONRPC):
|
|||
return failure.value
|
||||
return server.failure
|
||||
|
||||
def render(self, request):
|
||||
try:
|
||||
self._check_headers(request)
|
||||
except InvalidHeaderError:
|
||||
return server.failure
|
||||
|
||||
try:
|
||||
self._handle(request)
|
||||
except:
|
||||
return server.failure
|
||||
|
||||
return server.NOT_DONE_YET
|
||||
|
||||
def _render_response(self, result, code):
|
||||
return defer.succeed({'result': result, 'code': code})
|
||||
|
||||
|
|
|
@ -85,3 +85,9 @@ def initialize_api_key_file(key_path):
|
|||
new_api_key = APIKey.new(name=API_KEY_NAME)
|
||||
keys.update({new_api_key.name: new_api_key})
|
||||
save_api_keys(keys, key_path)
|
||||
|
||||
|
||||
def get_auth_message(message_dict):
|
||||
to_auth = message_dict.get('method').encode('hex')
|
||||
to_auth += str(message_dict.get('id')).encode('hex')
|
||||
return to_auth.decode('hex')
|
Loading…
Reference in a new issue