forked from LBRYCommunity/lbry-sdk
add lbry_ui_manager
This commit is contained in:
parent
8922fd6dde
commit
e7a580fd3a
4 changed files with 330 additions and 180 deletions
|
@ -36,8 +36,10 @@ UI_ADDRESS = "http://" + API_INTERFACE + ":" + str(API_PORT)
|
|||
PROTOCOL_PREFIX = "lbry"
|
||||
|
||||
DEFAULT_WALLET = "lbryum"
|
||||
WALLET_TYPES = ["lbryum", "lbrycrd"]
|
||||
DEFAULT_TIMEOUT = 30
|
||||
DEFAULT_MAX_SEARCH_RESULTS = 25
|
||||
DEFAULT_MAX_KEY_FEE = 100.0
|
||||
DEFAULT_SEARCH_TIMEOUT = 3.0
|
||||
DEFAULT_CACHE_TIME = 3600
|
||||
DEFAULT_CACHE_TIME = 3600
|
||||
DEFAULT_UI_BRANCH = "master"
|
||||
|
|
|
@ -31,13 +31,14 @@ from lbrynet.core.Error import UnknownNameError, InsufficientFundsError
|
|||
from lbrynet.lbryfile.StreamDescriptor import LBRYFileStreamType
|
||||
from lbrynet.lbryfile.client.LBRYFileDownloader import LBRYFileSaverFactory, LBRYFileOpenerFactory
|
||||
from lbrynet.lbryfile.client.LBRYFileOptions import add_lbry_file_to_sd_identifier
|
||||
from lbrynet.lbrynet_daemon.LBRYUIManager import LBRYUIManager
|
||||
from lbrynet.lbrynet_daemon.LBRYDownloader import GetStream
|
||||
from lbrynet.lbrynet_daemon.LBRYPublisher import Publisher
|
||||
from lbrynet.core.utils import generate_id
|
||||
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
|
||||
from lbrynet.conf import API_CONNECTION_STRING, API_PORT, API_ADDRESS, DEFAULT_TIMEOUT, UI_ADDRESS
|
||||
DEFAULT_WALLET, DEFAULT_SEARCH_TIMEOUT, DEFAULT_CACHE_TIME, DEFAULT_UI_BRANCH
|
||||
from lbrynet.conf import DEFAULT_TIMEOUT, WALLET_TYPES
|
||||
from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier, download_sd_blob
|
||||
from lbrynet.core.Session import LBRYSession
|
||||
from lbrynet.core.PTCWallet import PTCWallet
|
||||
|
@ -129,7 +130,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
|
||||
isLeaf = True
|
||||
|
||||
def __init__(self, ui_version_info, wallet_type=DEFAULT_WALLET):
|
||||
def __init__(self, root, wallet_type=DEFAULT_WALLET):
|
||||
jsonrpc.JSONRPC.__init__(self)
|
||||
reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
|
||||
|
||||
|
@ -139,9 +140,10 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
self.connected_to_internet = True
|
||||
self.connection_problem = None
|
||||
self.query_handlers = {}
|
||||
self.ui_version = ui_version_info.replace('\n', '')
|
||||
self.git_lbrynet_version = None
|
||||
self.git_lbryum_version = None
|
||||
self.ui_version = None
|
||||
self.ip = None
|
||||
self.wallet_type = wallet_type
|
||||
self.first_run = None
|
||||
self.log_file = LOG_FILENAME
|
||||
|
@ -152,20 +154,6 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
self.streams = {}
|
||||
self.known_dht_nodes = KNOWN_DHT_NODES
|
||||
self.first_run_after_update = False
|
||||
self.platform_info = {
|
||||
"processor": platform.processor(),
|
||||
"python_version: ": platform.python_version(),
|
||||
"platform": platform.platform(),
|
||||
"os_release": platform.release(),
|
||||
"os_system": platform.system(),
|
||||
"lbrynet_version: ": lbrynet_version,
|
||||
"lbryum_version: ": lbryum_version,
|
||||
"ui_version": self.ui_version,
|
||||
}
|
||||
try:
|
||||
self.platform_info['ip'] = json.load(urlopen('http://jsonip.com'))['ip']
|
||||
except:
|
||||
self.platform_info['ip'] = "Could not determine"
|
||||
|
||||
if os.name == "nt":
|
||||
from lbrynet.winhelpers.knownpaths import get_path, FOLDERID, UserHandle
|
||||
|
@ -261,7 +249,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
self.search_timeout = self.session_settings['search_timeout']
|
||||
self.download_timeout = self.session_settings['download_timeout']
|
||||
self.max_search_results = self.session_settings['max_search_results']
|
||||
self.wallet_type = self.session_settings['wallet_type'] if self.session_settings['wallet_type'] == wallet_type else wallet_type
|
||||
self.wallet_type = self.session_settings['wallet_type'] if self.session_settings['wallet_type'] in WALLET_TYPES else wallet_type
|
||||
self.delete_blobs_on_remove = self.session_settings['delete_blobs_on_remove']
|
||||
self.peer_port = self.session_settings['peer_port']
|
||||
self.dht_node_port = self.session_settings['dht_node_port']
|
||||
|
@ -319,6 +307,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
self.sd_identifier = StreamDescriptorIdentifier()
|
||||
self.stream_info_manager = TempLBRYFileMetadataManager()
|
||||
self.settings = LBRYSettings(self.db_dir)
|
||||
self.lbry_ui_manager = LBRYUIManager(root)
|
||||
self.blob_request_payment_rate_manager = None
|
||||
self.lbry_file_metadata_manager = None
|
||||
self.lbry_file_manager = None
|
||||
|
@ -392,7 +381,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
log.error(failure)
|
||||
return jsonrpclib.Fault(self.FAILURE, "error")
|
||||
|
||||
def setup(self):
|
||||
def setup(self, branch=DEFAULT_UI_BRANCH, user_specified=False):
|
||||
def _log_starting_vals():
|
||||
d = self._get_lbry_files()
|
||||
d.addCallback(lambda r: json.dumps([d[1] for d in r]))
|
||||
|
@ -437,6 +426,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
self.connection_problem_checker.start(1)
|
||||
|
||||
d = defer.Deferred()
|
||||
d.addCallback(lambda _: self.lbry_ui_manager.setup(branch=branch, user_specified=user_specified))
|
||||
d.addCallback(lambda _: self._initial_setup())
|
||||
d.addCallback(lambda _: threads.deferToThread(self._setup_data_directory))
|
||||
d.addCallback(lambda _: self._check_db_migration())
|
||||
|
@ -455,9 +445,29 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
|
||||
return defer.succeed(None)
|
||||
|
||||
def _get_platform(self):
|
||||
r = {
|
||||
"processor": platform.processor(),
|
||||
"python_version: ": platform.python_version(),
|
||||
"platform": platform.platform(),
|
||||
"os_release": platform.release(),
|
||||
"os_system": platform.system(),
|
||||
"lbrynet_version: ": lbrynet_version,
|
||||
"lbryum_version: ": lbryum_version,
|
||||
"ui_version": self.lbry_ui_manager.loaded_git_version,
|
||||
}
|
||||
if not self.ip:
|
||||
try:
|
||||
r['ip'] = json.load(urlopen('http://jsonip.com'))['ip']
|
||||
self.ip = r['ip']
|
||||
except:
|
||||
r['ip'] = "Could not determine"
|
||||
|
||||
return r
|
||||
|
||||
def _initial_setup(self):
|
||||
def _log_platform():
|
||||
log.info("Platform: " + json.dumps(self.platform_info))
|
||||
log.info("Platform: " + json.dumps(self._get_platform()))
|
||||
return defer.succeed(None)
|
||||
|
||||
d = _log_platform()
|
||||
|
@ -545,10 +555,13 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
return defer.succeed(True)
|
||||
|
||||
def _stop_server(self):
|
||||
if self.lbry_server_port is not None:
|
||||
self.lbry_server_port, p = None, self.lbry_server_port
|
||||
return defer.maybeDeferred(p.stopListening)
|
||||
else:
|
||||
try:
|
||||
if self.lbry_server_port is not None:
|
||||
self.lbry_server_port, p = None, self.lbry_server_port
|
||||
return defer.maybeDeferred(p.stopListening)
|
||||
else:
|
||||
return defer.succeed(True)
|
||||
except AttributeError:
|
||||
return defer.succeed(True)
|
||||
|
||||
def _setup_server(self):
|
||||
|
@ -630,17 +643,21 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
def _shutdown(self):
|
||||
log.info("Closing lbrynet session")
|
||||
log.info("Status at time of shutdown: " + self.startup_status[0])
|
||||
self.internet_connection_checker.stop()
|
||||
self.version_checker.stop()
|
||||
self.connection_problem_checker.stop()
|
||||
if self.internet_connection_checker.running:
|
||||
self.internet_connection_checker.stop()
|
||||
if self.version_checker.running:
|
||||
self.version_checker.stop()
|
||||
if self.connection_problem_checker.running:
|
||||
self.connection_problem_checker.stop()
|
||||
|
||||
d = self._upload_log(name_prefix="close", exclude_previous=False if self.first_run else True)
|
||||
d.addCallback(lambda _: self._stop_server())
|
||||
d.addErrback(lambda err: True)
|
||||
d.addCallback(lambda _: self.lbry_file_manager.stop())
|
||||
d.addErrback(lambda err: log.info("Bad server shutdown: " + err.getTraceback()))
|
||||
d.addErrback(lambda err: True)
|
||||
if self.session is not None:
|
||||
d.addCallback(lambda _: self.session.shut_down())
|
||||
d.addErrback(lambda err: log.info("Bad session shutdown: " + err.getTraceback()))
|
||||
d.addErrback(lambda err: True)
|
||||
return d
|
||||
|
||||
def _update_settings(self, settings):
|
||||
|
@ -819,7 +836,8 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
log.info("Using PTC wallet")
|
||||
d = defer.succeed(PTCWallet(self.db_dir))
|
||||
else:
|
||||
d = defer.fail()
|
||||
log.info("Requested unknown wallet '%s', using default lbryum" % self.wallet_type)
|
||||
d = defer.succeed(LBRYumWallet(self.db_dir))
|
||||
|
||||
d.addCallback(lambda wallet: {"wallet": wallet})
|
||||
return d
|
||||
|
@ -1392,10 +1410,11 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
"remote_lbryum": most recent lbryum version available from github
|
||||
"""
|
||||
|
||||
platform_info = self._get_platform()
|
||||
msg = {
|
||||
'platform': self.platform_info['platform'],
|
||||
'os_release': self.platform_info['os_release'],
|
||||
'os_system': self.platform_info['os_system'],
|
||||
'platform': platform_info['platform'],
|
||||
'os_release': platform_info['os_release'],
|
||||
'os_system': platform_info['os_system'],
|
||||
'lbrynet_version': lbrynet_version,
|
||||
'lbryum_version': lbryum_version,
|
||||
'ui_version': self.ui_version,
|
||||
|
@ -2113,25 +2132,18 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
#
|
||||
# return d
|
||||
|
||||
def jsonrpc_check_for_new_version(self):
|
||||
def jsonrpc_log(self, message):
|
||||
"""
|
||||
Checks local version against versions in __init__.py and version.py in the lbrynet and lbryum repos
|
||||
Log message
|
||||
|
||||
Args:
|
||||
None
|
||||
message: message to be logged
|
||||
Returns:
|
||||
true/false, true meaning that there is a new version available
|
||||
True
|
||||
"""
|
||||
|
||||
def _check_version():
|
||||
if (lbrynet_version >= self.git_lbrynet_version) and (lbryum_version >= self.git_lbryum_version):
|
||||
log.info("[" + str(datetime.now()) + "] Up to date")
|
||||
return self._render_response(False, OK_CODE)
|
||||
else:
|
||||
log.info("[" + str(datetime.now()) + "] Updates available")
|
||||
return self._render_response(True, OK_CODE)
|
||||
|
||||
return _check_version()
|
||||
log.info(message)
|
||||
return self._render_response(True, OK_CODE)
|
||||
|
||||
def jsonrpc_upload_log(self, p=None):
|
||||
"""
|
||||
|
@ -2140,7 +2152,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
Args, optional:
|
||||
'name_prefix': prefix to indicate what is requesting the log upload
|
||||
'exclude_previous': true/false, whether or not to exclude previous sessions from upload, defaults on true
|
||||
Returns
|
||||
Returns:
|
||||
True
|
||||
"""
|
||||
|
||||
|
@ -2171,3 +2183,22 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
d.addCallback(lambda _: self._log_to_slack(p['message']))
|
||||
d.addCallback(lambda _: self._render_response(True, OK_CODE))
|
||||
return d
|
||||
|
||||
def jsonrpc_configure_ui(self, p):
|
||||
"""
|
||||
Configure the UI being hosted
|
||||
|
||||
Args, optional:
|
||||
'branch': a branch name on lbryio/lbry-web-ui
|
||||
'path': path to a ui folder
|
||||
"""
|
||||
|
||||
if 'path' in p.keys():
|
||||
d = self.lbry_ui_manager.setup(user_specified=p['path'])
|
||||
elif 'branch' in p.keys():
|
||||
d = self.lbry_ui_manager.setup(branch=p['branch'])
|
||||
else:
|
||||
d = self.lbry_ui_manager.setup()
|
||||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
|
||||
return d
|
|
@ -18,7 +18,7 @@ from txjsonrpc.web import jsonrpc
|
|||
from zope.interface import implements
|
||||
|
||||
from lbrynet.lbrynet_daemon.LBRYDaemon import LBRYDaemon
|
||||
from lbrynet.conf import API_CONNECTION_STRING, API_ADDRESS, DEFAULT_WALLET, UI_ADDRESS
|
||||
from lbrynet.conf import API_CONNECTION_STRING, API_ADDRESS, DEFAULT_WALLET, UI_ADDRESS, DEFAULT_UI_BRANCH
|
||||
|
||||
|
||||
if sys.platform != "darwin":
|
||||
|
@ -149,22 +149,23 @@ class HostedLBRYFile(resource.Resource):
|
|||
self._producer = None
|
||||
resource.Resource.__init__(self)
|
||||
|
||||
def makeProducer(self, request, stream):
|
||||
def _save_producer(producer):
|
||||
self._producer = producer
|
||||
return defer.succeed(None)
|
||||
|
||||
range_header = request.getAllHeaders()['range'].replace('bytes=', '').split('-')
|
||||
start, stop = int(range_header[0]), range_header[1]
|
||||
log.info("[" + str(datetime.now()) + "] GET range %s-%s" % (start, stop))
|
||||
path = os.path.join(self._api.download_directory, stream.file_name)
|
||||
|
||||
d = stream.get_total_bytes()
|
||||
d.addCallback(lambda size: _save_producer(LBRYFileStreamer(request, path, start, stop, size)))
|
||||
d.addCallback(lambda _: request.registerProducer(self._producer, streaming=True))
|
||||
# request.notifyFinish().addCallback(lambda _: self._producer.stopProducing())
|
||||
request.notifyFinish().addErrback(self._responseFailed, d)
|
||||
return d
|
||||
# todo: fix LBRYFileStreamer and use it instead of static.File
|
||||
# def makeProducer(self, request, stream):
|
||||
# def _save_producer(producer):
|
||||
# self._producer = producer
|
||||
# return defer.succeed(None)
|
||||
#
|
||||
# range_header = request.getAllHeaders()['range'].replace('bytes=', '').split('-')
|
||||
# start, stop = int(range_header[0]), range_header[1]
|
||||
# log.info("[" + str(datetime.now()) + "] GET range %s-%s" % (start, stop))
|
||||
# path = os.path.join(self._api.download_directory, stream.file_name)
|
||||
#
|
||||
# d = stream.get_total_bytes()
|
||||
# d.addCallback(lambda size: _save_producer(LBRYFileStreamer(request, path, start, stop, size)))
|
||||
# d.addCallback(lambda _: request.registerProducer(self._producer, streaming=True))
|
||||
# # request.notifyFinish().addCallback(lambda _: self._producer.stopProducing())
|
||||
# request.notifyFinish().addErrback(self._responseFailed, d)
|
||||
# return d
|
||||
|
||||
def render_GET(self, request):
|
||||
if 'name' in request.args.keys():
|
||||
|
@ -182,125 +183,22 @@ class HostedLBRYFile(resource.Resource):
|
|||
request.finish()
|
||||
return server.NOT_DONE_YET
|
||||
|
||||
def _responseFailed(self, err, call):
|
||||
call.addErrback(lambda err: err.trap(error.ConnectionDone))
|
||||
call.addErrback(lambda err: err.trap(defer.CancelledError))
|
||||
call.addErrback(lambda err: log.info("Error: " + str(err)))
|
||||
call.cancel()
|
||||
# def _responseFailed(self, err, call):
|
||||
# call.addErrback(lambda err: err.trap(error.ConnectionDone))
|
||||
# call.addErrback(lambda err: err.trap(defer.CancelledError))
|
||||
# call.addErrback(lambda err: log.info("Error: " + str(err)))
|
||||
# call.cancel()
|
||||
|
||||
|
||||
class LBRYDaemonServer(object):
|
||||
def __init__(self):
|
||||
self.data_dir = user_data_dir("LBRY")
|
||||
if not os.path.isdir(self.data_dir):
|
||||
os.mkdir(self.data_dir)
|
||||
self.version_dir = os.path.join(self.data_dir, "ui_version_history")
|
||||
if not os.path.isdir(self.version_dir):
|
||||
os.mkdir(self.version_dir)
|
||||
self.config = os.path.join(self.version_dir, "active.json")
|
||||
self.ui_dir = os.path.join(self.data_dir, "lbry-web-ui")
|
||||
self.git_version = None
|
||||
self._api = None
|
||||
self.root = None
|
||||
|
||||
if not os.path.isfile(os.path.join(self.config)):
|
||||
self.loaded_git_version = None
|
||||
else:
|
||||
try:
|
||||
f = open(self.config, "r")
|
||||
loaded_ui = json.loads(f.read())
|
||||
f.close()
|
||||
self.loaded_git_version = loaded_ui['commit']
|
||||
self.loaded_branch = loaded_ui['branch']
|
||||
version_log.info("[" + str(datetime.now()) + "] Last used " + self.loaded_branch + " commit " + str(self.loaded_git_version).replace("\n", ""))
|
||||
except:
|
||||
self.loaded_git_version = None
|
||||
self.loaded_branch = None
|
||||
|
||||
def setup(self, branch="master", user_specified=None):
|
||||
self.branch = branch
|
||||
if user_specified:
|
||||
if os.path.isdir(user_specified):
|
||||
log.info("Using user specified UI directory: " + str(user_specified))
|
||||
self.branch = "user-specified"
|
||||
self.loaded_git_version = "user-specified"
|
||||
self.ui_dir = user_specified
|
||||
return defer.succeed("user-specified")
|
||||
else:
|
||||
log.info("User specified UI directory doesn't exist, using " + branch)
|
||||
else:
|
||||
log.info("Using UI branch: " + branch)
|
||||
self._git_url = "https://api.github.com/repos/lbryio/lbry-web-ui/git/refs/heads/%s" % branch
|
||||
self._dist_url = "https://raw.githubusercontent.com/lbryio/lbry-web-ui/%s/dist.zip" % branch
|
||||
|
||||
d = self._up_to_date()
|
||||
d.addCallback(lambda r: self._download_ui() if not r else self.branch)
|
||||
return d
|
||||
|
||||
def _up_to_date(self):
|
||||
def _get_git_info():
|
||||
response = urlopen(self._git_url)
|
||||
data = json.loads(response.read())
|
||||
return defer.succeed(data['object']['sha'])
|
||||
|
||||
def _set_git(version):
|
||||
self.git_version = version
|
||||
version_log.info("[" + str(datetime.now()) + "] UI branch " + self.branch + " has a most recent commit of: " + str(self.git_version).replace("\n", ""))
|
||||
|
||||
if self.git_version == self.loaded_git_version and os.path.isdir(self.ui_dir):
|
||||
version_log.info("[" + str(datetime.now()) + "] local copy of " + self.branch + " is up to date")
|
||||
return defer.succeed(True)
|
||||
else:
|
||||
if self.git_version == self.loaded_git_version:
|
||||
version_log.info("[" + str(datetime.now()) + "] Can't find ui files, downloading them again")
|
||||
else:
|
||||
version_log.info("[" + str(datetime.now()) + "] local copy of " + self.branch + " branch is out of date, updating")
|
||||
f = open(self.config, "w")
|
||||
f.write(json.dumps({'commit': self.git_version,
|
||||
'time': str(datetime.now()),
|
||||
'branch': self.branch}))
|
||||
f.close()
|
||||
return defer.succeed(False)
|
||||
|
||||
d = _get_git_info()
|
||||
d.addCallback(_set_git)
|
||||
return d
|
||||
|
||||
def _download_ui(self):
|
||||
def _delete_ui_dir():
|
||||
if os.path.isdir(self.ui_dir):
|
||||
if self.loaded_git_version:
|
||||
version_log.info("[" + str(datetime.now()) + "] Removed ui files for commit " + str(self.loaded_git_version).replace("\n", ""))
|
||||
log.info("Removing out of date ui files")
|
||||
shutil.rmtree(self.ui_dir)
|
||||
return defer.succeed(None)
|
||||
|
||||
def _dl_ui():
|
||||
url = urlopen(self._dist_url)
|
||||
z = ZipFile(StringIO(url.read()))
|
||||
names = [i for i in z.namelist() if '.DS_exStore' not in i and '__MACOSX' not in i]
|
||||
z.extractall(self.ui_dir, members=names)
|
||||
version_log.info("[" + str(datetime.now()) + "] Updated branch " + self.branch + ": " + str(self.loaded_git_version).replace("\n", "") + " --> " + self.git_version.replace("\n", ""))
|
||||
log.info("Downloaded files for UI commit " + str(self.git_version).replace("\n", ""))
|
||||
self.loaded_git_version = self.git_version
|
||||
return self.branch
|
||||
|
||||
d = _delete_ui_dir()
|
||||
d.addCallback(lambda _: _dl_ui())
|
||||
return d
|
||||
|
||||
def _setup_server(self, ui_ver, wallet):
|
||||
self._api = LBRYDaemon(ui_ver, wallet_type=wallet)
|
||||
self.root = LBRYindex(self.ui_dir)
|
||||
for d in [i[0] for i in os.walk(self.ui_dir) if os.path.dirname(i[0]) == self.ui_dir]:
|
||||
self.root.putChild(os.path.basename(d), static.File(d))
|
||||
def _setup_server(self, wallet):
|
||||
self.root = LBRYindex(os.path.join(os.path.join(data_dir, "lbry-ui"), "active"))
|
||||
self._api = LBRYDaemon(self.root, wallet_type=wallet)
|
||||
self.root.putChild("view", HostedLBRYFile(self._api))
|
||||
self.root.putChild(API_ADDRESS, self._api)
|
||||
return defer.succeed(True)
|
||||
|
||||
def start(self, branch="master", user_specified=False, wallet=DEFAULT_WALLET):
|
||||
d = self.setup(branch=branch, user_specified=user_specified)
|
||||
d.addCallback(lambda v: self._setup_server(v, wallet))
|
||||
d.addCallback(lambda _: self._api.setup())
|
||||
|
||||
def start(self, branch=DEFAULT_UI_BRANCH, user_specified=False, wallet=DEFAULT_WALLET):
|
||||
d = self._setup_server(self._setup_server(wallet))
|
||||
d.addCallback(lambda _: self._api.setup(branch, user_specified))
|
||||
return d
|
||||
|
|
219
lbrynet/lbrynet_daemon/LBRYUIManager.py
Normal file
219
lbrynet/lbrynet_daemon/LBRYUIManager.py
Normal file
|
@ -0,0 +1,219 @@
|
|||
import os
|
||||
import logging
|
||||
import shutil
|
||||
import sys
|
||||
import json
|
||||
|
||||
from urllib2 import urlopen
|
||||
from StringIO import StringIO
|
||||
from twisted.web import static
|
||||
from twisted.internet import defer
|
||||
from lbrynet.conf import DEFAULT_UI_BRANCH
|
||||
from lbrynet import __version__ as lbrynet_version
|
||||
from lbryum.version import ELECTRUM_VERSION as lbryum_version
|
||||
from zipfile import ZipFile
|
||||
from appdirs import user_data_dir
|
||||
|
||||
if sys.platform != "darwin":
|
||||
data_dir = os.path.join(os.path.expanduser("~"), ".lbrynet")
|
||||
else:
|
||||
data_dir = user_data_dir("LBRY")
|
||||
|
||||
if not os.path.isdir(data_dir):
|
||||
os.mkdir(data_dir)
|
||||
version_dir = os.path.join(data_dir, "ui_version_history")
|
||||
if not os.path.isdir(version_dir):
|
||||
os.mkdir(version_dir)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
log.addHandler(logging.FileHandler(os.path.join(data_dir, 'lbrynet-daemon.log')))
|
||||
log.setLevel(logging.INFO)
|
||||
|
||||
|
||||
class LBRYUIManager(object):
|
||||
def __init__(self, root):
|
||||
self.data_dir = user_data_dir("LBRY")
|
||||
self.ui_root = os.path.join(self.data_dir, "lbry-ui")
|
||||
self.active_dir = os.path.join(self.ui_root, "active")
|
||||
self.update_dir = os.path.join(self.ui_root, "update")
|
||||
|
||||
if not os.path.isdir(self.data_dir):
|
||||
os.mkdir(self.data_dir)
|
||||
if not os.path.isdir(self.ui_root):
|
||||
os.mkdir(self.ui_root)
|
||||
if not os.path.isdir(self.ui_root):
|
||||
os.mkdir(self.ui_root)
|
||||
if not os.path.isdir(self.ui_root):
|
||||
os.mkdir(self.ui_root)
|
||||
|
||||
self.config = os.path.join(self.ui_root, "active.json")
|
||||
self.update_requires = os.path.join(self.update_dir, "requirements.txt")
|
||||
self.requirements = {}
|
||||
self.ui_dir = self.active_dir
|
||||
self.git_version = None
|
||||
self.root = root
|
||||
|
||||
if not os.path.isfile(os.path.join(self.config)):
|
||||
self.loaded_git_version = None
|
||||
else:
|
||||
try:
|
||||
f = open(self.config, "r")
|
||||
loaded_ui = json.loads(f.read())
|
||||
f.close()
|
||||
self.loaded_git_version = loaded_ui['commit']
|
||||
self.loaded_branch = loaded_ui['branch']
|
||||
self.loaded_requirements = loaded_ui['requirements']
|
||||
except:
|
||||
self.loaded_git_version = None
|
||||
self.loaded_branch = None
|
||||
self.loaded_requirements = None
|
||||
|
||||
def setup(self, branch=DEFAULT_UI_BRANCH, user_specified=None):
|
||||
self.branch = branch
|
||||
if user_specified:
|
||||
if os.path.isdir(user_specified):
|
||||
log.info("Checking user specified UI directory: " + str(user_specified))
|
||||
self.branch = "user-specified"
|
||||
self.loaded_git_version = "user-specified"
|
||||
self.ui_dir = user_specified
|
||||
d = self.migrate_ui(source=user_specified)
|
||||
d.addCallback(lambda _: self._load_ui())
|
||||
return d
|
||||
else:
|
||||
log.info("User specified UI directory doesn't exist, using " + branch)
|
||||
else:
|
||||
log.info("Checking for updates for UI branch: " + branch)
|
||||
self._git_url = "https://api.github.com/repos/lbryio/lbry-web-ui/git/refs/heads/%s" % branch
|
||||
self._dist_url = "https://raw.githubusercontent.com/lbryio/lbry-web-ui/%s/dist.zip" % branch
|
||||
|
||||
d = self._up_to_date()
|
||||
d.addCallback(lambda r: self._download_ui() if not r else self.branch)
|
||||
return d
|
||||
|
||||
def _up_to_date(self):
|
||||
def _get_git_info():
|
||||
response = urlopen(self._git_url)
|
||||
data = json.loads(response.read())
|
||||
return defer.succeed(data['object']['sha'])
|
||||
|
||||
def _set_git(version):
|
||||
self.git_version = version.replace('\n', '')
|
||||
if self.git_version == self.loaded_git_version:
|
||||
log.info("UI is up to date")
|
||||
return defer.succeed(True)
|
||||
else:
|
||||
log.info("UI updates available, checking if installation meets requirements")
|
||||
return defer.succeed(False)
|
||||
|
||||
d = _get_git_info()
|
||||
d.addCallback(_set_git)
|
||||
return d
|
||||
|
||||
def migrate_ui(self, source=None):
|
||||
if not source:
|
||||
requires_file = self.update_requires
|
||||
source_dir = self.update_dir
|
||||
delete_source = True
|
||||
else:
|
||||
requires_file = os.path.join(source, "requirements.txt")
|
||||
source_dir = source
|
||||
delete_source = False
|
||||
|
||||
def _check_requirements():
|
||||
if not os.path.isfile(requires_file):
|
||||
log.info("No requirements.txt file, rejecting request to migrate this UI")
|
||||
return defer.succeed(False)
|
||||
|
||||
f = open(requires_file, "r")
|
||||
for requirement in [line for line in f.read().split('\n') if line]:
|
||||
t = requirement.split('=')
|
||||
if len(t) == 3:
|
||||
self.requirements[t[0]] = {'version': t[1], 'operator': '=='}
|
||||
elif t[0][-1] == ">":
|
||||
self.requirements[t[0][:-1]] = {'version': t[1], 'operator': '>='}
|
||||
elif t[0][-1] == "<":
|
||||
self.requirements[t[0][:-1]] = {'version': t[1], 'operator': '<='}
|
||||
f.close()
|
||||
passed_requirements = True
|
||||
for r in self.requirements:
|
||||
if r == 'lbrynet':
|
||||
c = lbrynet_version
|
||||
elif r == 'lbryum':
|
||||
c = lbryum_version
|
||||
else:
|
||||
c = None
|
||||
if c:
|
||||
if self.requirements[r]['operator'] == '==':
|
||||
if not self.requirements[r]['version'] == c:
|
||||
passed_requirements = False
|
||||
log.info("Local version %s of %s does not meet UI requirement for version %s" % (
|
||||
c, r, self.requirements[r]['version']))
|
||||
else:
|
||||
log.info("Local version of %s meets ui requirement" % r)
|
||||
if self.requirements[r]['operator'] == '>=':
|
||||
if not self.requirements[r]['version'] <= c:
|
||||
passed_requirements = False
|
||||
log.info("Local version %s of %s does not meet UI requirement for version %s" % (
|
||||
c, r, self.requirements[r]['version']))
|
||||
else:
|
||||
log.info("Local version of %s meets ui requirement" % r)
|
||||
if self.requirements[r]['operator'] == '<=':
|
||||
if not self.requirements[r]['version'] >= c:
|
||||
passed_requirements = False
|
||||
log.info("Local version %s of %s does not meet UI requirement for version %s" % (
|
||||
c, r, self.requirements[r]['version']))
|
||||
else:
|
||||
log.info("Local version of %s meets ui requirement" % r)
|
||||
return defer.succeed(passed_requirements)
|
||||
|
||||
def _disp_failure():
|
||||
log.info("Failed to satisfy requirements for branch '%s', update was not loaded" % self.branch)
|
||||
return defer.succeed(False)
|
||||
|
||||
def _do_migrate():
|
||||
if os.path.isdir(self.active_dir):
|
||||
shutil.rmtree(self.active_dir)
|
||||
shutil.copytree(source_dir, self.active_dir)
|
||||
if delete_source:
|
||||
shutil.rmtree(source_dir)
|
||||
|
||||
log.info("Loaded UI update")
|
||||
|
||||
f = open(self.config, "w")
|
||||
loaded_ui = {'commit': self.git_version, 'branch': self.branch, 'requirements': self.requirements}
|
||||
f.write(json.dumps(loaded_ui))
|
||||
f.close()
|
||||
|
||||
self.loaded_git_version = loaded_ui['commit']
|
||||
self.loaded_branch = loaded_ui['branch']
|
||||
self.loaded_requirements = loaded_ui['requirements']
|
||||
return defer.succeed(True)
|
||||
|
||||
d = _check_requirements()
|
||||
d.addCallback(lambda r: _do_migrate() if r else _disp_failure())
|
||||
return d
|
||||
|
||||
def _download_ui(self):
|
||||
def _delete_update_dir():
|
||||
if os.path.isdir(self.update_dir):
|
||||
shutil.rmtree(self.update_dir)
|
||||
return defer.succeed(None)
|
||||
|
||||
def _dl_ui():
|
||||
url = urlopen(self._dist_url)
|
||||
z = ZipFile(StringIO(url.read()))
|
||||
names = [i for i in z.namelist() if '.DS_exStore' not in i and '__MACOSX' not in i]
|
||||
z.extractall(self.update_dir, members=names)
|
||||
log.info("Downloaded files for UI commit " + str(self.git_version).replace("\n", ""))
|
||||
return self.branch
|
||||
|
||||
d = _delete_update_dir()
|
||||
d.addCallback(lambda _: _dl_ui())
|
||||
d.addCallback(lambda _: self.migrate_ui())
|
||||
d.addCallback(lambda _: self._load_ui())
|
||||
return d
|
||||
|
||||
def _load_ui(self):
|
||||
for d in [i[0] for i in os.walk(self.active_dir) if os.path.dirname(i[0]) == self.active_dir]:
|
||||
self.root.putChild(os.path.basename(d), static.File(d))
|
||||
return defer.succeed(True)
|
Loading…
Add table
Reference in a new issue