import argparse import json import os import sys from lbrynet import conf from lbrynet.lbrynet_daemon.auth.client import JSONRPCException, LBRYAPIClient from lbrynet.lbrynet_daemon.Daemon import LOADING_WALLET_CODE from jsonrpc.common import RPCError from urllib2 import URLError, HTTPError from httplib import UNAUTHORIZED def main(): parser = argparse.ArgumentParser(add_help=False) _, arguments = parser.parse_known_args() conf.initialize_settings() api = LBRYAPIClient.get_client() try: status = api.status() except URLError as err: if isinstance(err, HTTPError) and err.code == UNAUTHORIZED: print_error("Daemon requires authentication, but none was provided.", suggest_help=False) else: 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 len(arguments) < 1: print_help(api) return 1 method = arguments[0] try: params = parse_params(arguments[1:]) except InvalidParameters as e: print_error(e.message) return 1 # TODO: check if port is bound. Error if its not if method in ['--help', '-h', 'help']: if len(params) == 0: print_help(api) elif 'command' not in params: print_error( 'To get help on a specific command, use `{} help command=COMMAND_NAME`'.format( os.path.basename(sys.argv[0])) ) else: print api.call('help', params).strip() elif method not in api.commands(): print_error("'" + method + "' is not a valid command.") 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, KeyError, JSONRPCException) 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.call('help', {'command': method}) if hasattr(err, 'msg'): print "Here's the traceback for the error you encountered:" print err.msg return 1 def guess_type(x): if '.' in x: try: return float(x) except ValueError: # not a float pass try: return int(x) except ValueError: 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: 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(api): print "\n".join([ "NAME", " lbrynet-cli - LBRY command line client.", "", "USAGE", " lbrynet-cli []", "", "EXAMPLES", " lbrynet-cli commands # list available commands", " lbrynet-cli status # get daemon status", " lbrynet-cli resolve_name name=what # resolve a name", " lbrynet-cli help command=resolve_name # get help for a command", "", "COMMANDS", wrap_list_to_term_width(api.commands(), prefix=' ') ]) def wrap_list_to_term_width(l, width=None, separator=', ', prefix=''): if width is None: try: _, width = os.popen('stty size', 'r').read().split() width = int(width) except: pass if not width: width = 80 lines = [] curr_line = '' for item in l: new_line = curr_line + item + separator if len(new_line) + len(prefix) > width: lines.append(curr_line) curr_line = item + separator else: curr_line = new_line lines.append(curr_line) ret = prefix + ("\n" + prefix).join(lines) if ret.endswith(separator): ret = ret[:-len(separator)] return ret if __name__ == '__main__': sys.exit(main())