diff --git a/lbrynet/lbrynet_daemon/DaemonCLI.py b/lbrynet/lbrynet_daemon/DaemonCLI.py index 11e052058..f4b152fb6 100644 --- a/lbrynet/lbrynet_daemon/DaemonCLI.py +++ b/lbrynet/lbrynet_daemon/DaemonCLI.py @@ -1,14 +1,90 @@ -import sys import argparse import json -from lbrynet import conf import os +import sys + +from lbrynet import conf from lbrynet.lbrynet_daemon.auth.client import LBRYAPIClient from lbrynet.lbrynet_daemon.Daemon import LOADING_WALLET_CODE from jsonrpc.common import RPCError from urllib2 import URLError +def main(): + parser = argparse.ArgumentParser(add_help=False) + _, arguments = parser.parse_known_args() + + if len(arguments) < 1: + print_help() + return 1 + + method = arguments[0] + try: + params = parse_params(arguments[1:]) + except InvalidParameters as e: + print_error(e.message) + return 1 + + conf.initialize_settings() + api = LBRYAPIClient.get_client() + + # TODO: check if port is bound. Error if its not + + try: + status = api.status() + except URLError: + print_error("Could not connect to daemon. Are you sure it's running?", + suggest_help=False) + return 1 + + if status['startup_status']['code'] != "started": + print "Daemon is in the process of starting. Please try again in a bit." + message = status['startup_status']['message'] + if message: + if ( + status['startup_status']['code'] == LOADING_WALLET_CODE + and status['blocks_behind'] > 0 + ): + message += '. Blocks left: ' + str(status['blocks_behind']) + print " Status: " + message + return 1 + + if method in ['--help', '-h', 'help']: + if len(params) == 0: + print_help() + print "\nCOMMANDS\n" + wrap_list_to_term_width(api.commands(), prefix=' ') + else: + print api.help(params).strip() + + elif method not in api.commands(): + print_error("Function '" + method + "' is not a valid function.") + + else: + try: + result = api.call(method, params) + if isinstance(result, basestring): + # printing the undumped string is prettier + print result + else: + print json.dumps(result, sort_keys=True, indent=2, separators=(',', ': ')) + except RPCError as err: + handle_error(err, api, method) + except KeyError as err: + handle_error(err, api, method) + + +def handle_error(err, api, method): + # TODO: The api should return proper error codes + # and messages so that they can be passed along to the user + # instead of this generic message. + # https://app.asana.com/0/158602294500137/200173944358192 + print "Something went wrong, here's the usage for %s:" % method + print api.help({'function': method}) + if hasattr(err, 'msg'): + print "Here's the traceback for the error you encountered:" + print err.msg + + def guess_type(x): if '.' in x: try: @@ -22,17 +98,44 @@ def guess_type(x): return x +def parse_params(params): + if len(params) > 1: + return get_params_from_kwargs(params) + elif len(params) == 1: + try: + return json.loads(params[0]) + except ValueError: + return get_params_from_kwargs(params) + else: + return {} + + +class InvalidParameters(Exception): + pass + + def get_params_from_kwargs(params): params_for_return = {} for i in params: - if '=' not in i: - print 'WARNING: Argument "' + i + '" is missing a parameter name. Please use name=value' - continue - eq_pos = i.index('=') - params_for_return[i[:eq_pos]] = guess_type(i[eq_pos + 1:]) + try: + eq_pos = i.index('=') + except ValueError: + raise InvalidParameters('{} is not in = format'.format(i)) + k, v = i[:eq_pos], i[eq_pos + 1:] + params_for_return[k] = guess_type(v) return params_for_return +def print_help_suggestion(): + print "See `{} help` for more information.".format(os.path.basename(sys.argv[0])) + + +def print_error(message, suggest_help=True): + print "ERROR: " + message + if suggest_help: + print_help_suggestion() + + def print_help(): print "\n".join([ "NAME", @@ -60,94 +163,21 @@ def wrap_list_to_term_width(l, width=None, separator=', ', prefix=''): width = 80 lines = [] - curr_line = prefix + curr_line = '' for item in l: new_line = curr_line + item + separator - if len(new_line) > width: + if len(new_line) + len(prefix) > width: lines.append(curr_line) - curr_line = prefix + item + separator + curr_line = item + separator else: curr_line = new_line + lines.append(curr_line) - return "\n".join(lines) - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('params', nargs=argparse.ZERO_OR_MORE, default=None) - args = parser.parse_args() - - if len(args.params) < 1: - print_help() - sys.exit(1) - - method = args.params[0] - params = args.params[1:] - - if len(params) > 1: - params = get_params_from_kwargs(params) - elif len(params) == 1: - try: - params = json.loads(params[0]) - except ValueError: - params = get_params_from_kwargs(params) - else: - params = {} - - conf.initialize_settings() - api = LBRYAPIClient.get_client() - - # TODO: check if port is bound - - try: - status = api.status() - except URLError: - print "Could not connect to lbrynet-daemon. Are you sure it's running?" - sys.exit(1) - - if status['startup_status']['code'] != "started": - print "Daemon is in the process of starting. Please try again in a bit." - message = status['startup_status']['message'] - if message: - if status['startup_status']['code'] == LOADING_WALLET_CODE \ - and status['blocks_behind'] > 0: - message += '. Blocks left: ' + str(status['blocks_behind']) - print " Status: " + message - sys.exit(1) - - if method in ['--help', '-h', 'help']: - if len(params) == 0: - print_help() - print "\nCOMMANDS\n" + wrap_list_to_term_width(api.commands(), prefix=' ') - else: - print api.help(params).strip() - - elif method not in api.commands(): - print ( - "Function '" + method + "' is not a valid function.\n" - "See '" + os.path.basename(sys.argv[0]) + " help'" - ) - - else: - try: - result = api.call(method, params) - print json.dumps(result, sort_keys=True, indent=2) - except RPCError as err: - # TODO: The api should return proper error codes - # and messages so that they can be passed along to the user - # instead of this generic message. - # https://app.asana.com/0/158602294500137/200173944358192 - print "Something went wrong, here's the usage for %s:" % method - print api.help({'function': method}) - print "Here's the traceback for the error you encountered:" - print err.msg - except KeyError as err: - print "Something went wrong, here's the usage for %s:" % method - print api.help({'function': method}) - if hasattr(err, 'msg'): - print "Here's the traceback for the error you encountered:" - print err.msg + ret = prefix + ("\n" + prefix).join(lines) + if ret.endswith(separator): + ret = ret[:-len(separator)] + return ret if __name__ == '__main__': - main() + sys.exit(main()) diff --git a/lbrynet/lbrynet_daemon/DaemonControl.py b/lbrynet/lbrynet_daemon/DaemonControl.py index 541880491..8b40d5848 100644 --- a/lbrynet/lbrynet_daemon/DaemonControl.py +++ b/lbrynet/lbrynet_daemon/DaemonControl.py @@ -9,7 +9,7 @@ from jsonrpc.proxy import JSONRPCProxy from lbrynet import analytics from lbrynet import conf from lbrynet.core import utils -from lbrynet.lbrynet_daemon.auth import client +from lbrynet.lbrynet_daemon.auth.client import LBRYAPIClient from lbrynet.lbrynet_daemon.DaemonServer import DaemonServer @@ -24,7 +24,7 @@ def stop(): conf.initialize_settings() log_support.configure_console() try: - client.LBRYAPIClient.config().stop() + LBRYAPIClient.get_client().call('stop') except Exception: log.exception('Failed to stop deamon') else: diff --git a/lbrynet/lbrynet_daemon/auth/server.py b/lbrynet/lbrynet_daemon/auth/server.py index ea3847cfc..c8bfce547 100644 --- a/lbrynet/lbrynet_daemon/auth/server.py +++ b/lbrynet/lbrynet_daemon/auth/server.py @@ -15,6 +15,8 @@ from lbrynet.lbrynet_daemon.auth.client import LBRY_SECRET log = logging.getLogger(__name__) +EMPTY_PARAMS = [{}] + def default_decimal(obj): if isinstance(obj, Decimal): @@ -131,6 +133,7 @@ class AuthJSONRPCServer(AuthorizedBase): if self._initialize_session(session_id): def expire_session(): self._unregister_user_session(session_id) + session.startCheckingExpiration() session.notifyOnExpire(expire_session) message = "OK" @@ -182,7 +185,7 @@ class AuthJSONRPCServer(AuthorizedBase): self._render_error(err, request, id_, version) return server.NOT_DONE_YET - if args == [{}]: + if args == EMPTY_PARAMS: d = defer.maybeDeferred(function) else: d = defer.maybeDeferred(function, *args) @@ -308,7 +311,7 @@ class AuthJSONRPCServer(AuthorizedBase): if version == jsonrpclib.VERSION_PRE1: if not isinstance(result, jsonrpclib.Fault): result_for_return = (result_for_return,) - # Convert the result (python) to JSON-RPC + try: encoded_message = jsonrpclib.dumps( result_for_return, id=id_, version=version, default=default_decimal) diff --git a/packaging/uri_handler/LBRYURIHandler.py b/packaging/uri_handler/LBRYURIHandler.py index 1ff002833..d22aeea19 100644 --- a/packaging/uri_handler/LBRYURIHandler.py +++ b/packaging/uri_handler/LBRYURIHandler.py @@ -49,7 +49,8 @@ class LBRYURIHandler(object): def check_daemon(self): try: - self.started_daemon = self.daemon.is_running() + status = self.daemon.call('status') + self.started_daemon = status['is_running'] except: self.started_daemon = False