lbry-sdk/lbrynet/lbrynet_daemon/DaemonCLI.py

195 lines
5.7 KiB
Python
Raw Normal View History

import argparse
2016-11-11 19:40:19 +01:00
import json
2017-01-03 20:13:01 +01:00
import os
2017-01-09 20:03:25 +01:00
import sys
from lbrynet import conf
from lbrynet.core import utils
2017-01-10 01:31:06 +01:00
from lbrynet.lbrynet_daemon.auth.client import JSONRPCException, LBRYAPIClient
2017-01-03 20:13:01 +01:00
from lbrynet.lbrynet_daemon.Daemon import LOADING_WALLET_CODE
2016-11-11 19:40:19 +01:00
from jsonrpc.common import RPCError
from urllib2 import URLError, HTTPError
from httplib import UNAUTHORIZED
2016-07-06 09:02:55 +02:00
2017-01-09 20:03:25 +01:00
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)
2017-01-09 20:03:25 +01:00
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['blockchain_status']['blocks_behind'] > 0
2017-01-09 20:03:25 +01:00
):
message += '. Blocks left: ' + str(status['blockchain_status']['blocks_behind'])
2017-01-09 20:03:25 +01:00
print " Status: " + message
return 1
2017-01-11 21:31:08 +01:00
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
2017-01-09 20:03:25 +01:00
if method in ['--help', '-h', 'help']:
if len(params) == 0:
2017-01-11 21:31:08 +01:00
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]))
)
2017-01-09 20:03:25 +01:00
else:
print_help_response(api.call('help', params))
2017-01-09 20:03:25 +01:00
elif method not in api.commands():
2017-01-11 21:31:08 +01:00
print_error("'" + method + "' is not a valid command.")
2017-01-09 20:03:25 +01:00
else:
try:
result = api.call(method, params)
if isinstance(result, basestring):
# printing the undumped string is prettier
print result
else:
print utils.json_dumps_pretty(result)
2017-01-10 01:31:06 +01:00
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_help_response(api.call('help', {'command': method}))
2017-01-10 01:31:06 +01:00
if hasattr(err, 'msg'):
print "Here's the traceback for the error you encountered:"
print err.msg
return 1
2017-01-09 20:03:25 +01:00
def print_help_response(help_response):
print help_response['help'] if 'help' in help_response else help_response
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
2017-01-09 20:03:25 +01:00
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:
2017-01-09 20:03:25 +01:00
try:
eq_pos = i.index('=')
except ValueError:
raise InvalidParameters('{} is not in <key>=<value> format'.format(i))
k, v = i[:eq_pos], i[eq_pos + 1:]
params_for_return[k] = guess_type(v)
return params_for_return
2017-01-09 20:03:25 +01:00
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()
2017-01-11 21:31:08 +01:00
def print_help(api):
2017-01-04 23:15:08 +01:00
print "\n".join([
"NAME",
" lbrynet-cli - LBRY command line client.",
"",
"USAGE",
" lbrynet-cli <command> [<args>]",
"",
"EXAMPLES",
2017-01-11 21:31:08 +01:00
" 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=' ')
2017-01-04 23:15:08 +01:00
])
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 = []
2017-01-09 20:03:25 +01:00
curr_line = ''
2017-01-04 23:15:08 +01:00
for item in l:
new_line = curr_line + item + separator
2017-01-09 20:03:25 +01:00
if len(new_line) + len(prefix) > width:
2017-01-04 23:15:08 +01:00
lines.append(curr_line)
2017-01-09 20:03:25 +01:00
curr_line = item + separator
2017-01-04 23:15:08 +01:00
else:
curr_line = new_line
2017-01-09 20:03:25 +01:00
lines.append(curr_line)
2017-01-04 23:15:08 +01:00
2017-01-09 20:03:25 +01:00
ret = prefix + ("\n" + prefix).join(lines)
if ret.endswith(separator):
ret = ret[:-len(separator)]
return ret
if __name__ == '__main__':
2017-01-09 20:03:25 +01:00
sys.exit(main())