forked from LBRYCommunity/lbry-sdk
commit
a249097170
4 changed files with 361 additions and 193 deletions
|
@ -267,4 +267,6 @@ class LBRYSession(object):
|
||||||
log.info("Removed UPnP redirect for %s %d.", protocol, port)
|
log.info("Removed UPnP redirect for %s %d.", protocol, port)
|
||||||
self.upnp_redirects = []
|
self.upnp_redirects = []
|
||||||
|
|
||||||
return threads.deferToThread(threaded_unset_upnp)
|
d = threads.deferToThread(threaded_unset_upnp)
|
||||||
|
d.addErrback(lambda err: str(err))
|
||||||
|
return d
|
|
@ -1,3 +1,4 @@
|
||||||
|
from lbrynet.core.Error import UnknownNameError
|
||||||
from lbrynet.lbryfile.StreamDescriptor import LBRYFileStreamType
|
from lbrynet.lbryfile.StreamDescriptor import LBRYFileStreamType
|
||||||
from lbrynet.lbryfile.client.LBRYFileDownloader import LBRYFileSaverFactory, LBRYFileOpenerFactory
|
from lbrynet.lbryfile.client.LBRYFileDownloader import LBRYFileSaverFactory, LBRYFileOpenerFactory
|
||||||
from lbrynet.lbryfile.client.LBRYFileOptions import add_lbry_file_to_sd_identifier
|
from lbrynet.lbryfile.client.LBRYFileOptions import add_lbry_file_to_sd_identifier
|
||||||
|
@ -17,10 +18,26 @@ from datetime import datetime
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import json
|
||||||
|
import binascii
|
||||||
|
import webbrowser
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
#TODO add login credentials in a conf file
|
||||||
|
|
||||||
|
#issues with delete:
|
||||||
|
#TODO when stream is complete the generated file doesn't delete, but blobs do
|
||||||
|
#TODO when stream is stopped the generated file is deleted
|
||||||
|
|
||||||
|
#functions to add:
|
||||||
|
#TODO publish
|
||||||
|
#TODO send credits to address
|
||||||
|
#TODO get new address
|
||||||
|
#TODO alert if your copy of a lbry file is out of date with the name record
|
||||||
|
|
||||||
|
|
||||||
class LBRYDaemon(xmlrpc.XMLRPC):
|
class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
"""
|
"""
|
||||||
LBRYnet daemon
|
LBRYnet daemon
|
||||||
|
@ -38,7 +55,6 @@ class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
self.peer_port = 3333
|
self.peer_port = 3333
|
||||||
self.dht_node_port = 4444
|
self.dht_node_port = 4444
|
||||||
self.first_run = False
|
self.first_run = False
|
||||||
self.current_db_revision = 1
|
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
from lbrynet.winhelpers.knownpaths import get_path, FOLDERID, UserHandle
|
from lbrynet.winhelpers.knownpaths import get_path, FOLDERID, UserHandle
|
||||||
self.download_directory = get_path(FOLDERID.Downloads, UserHandle.current)
|
self.download_directory = get_path(FOLDERID.Downloads, UserHandle.current)
|
||||||
|
@ -84,22 +100,35 @@ class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
self.max_key_fee = 100.0
|
self.max_key_fee = 100.0
|
||||||
return defer.succeed(None)
|
return defer.succeed(None)
|
||||||
|
|
||||||
|
def _disp_startup():
|
||||||
|
print "Started LBRYnet daemon"
|
||||||
|
return defer.succeed(None)
|
||||||
|
|
||||||
d = defer.Deferred()
|
d = defer.Deferred()
|
||||||
d.addCallback(lambda _: _set_vars())
|
d.addCallback(lambda _: _set_vars())
|
||||||
d.addCallback(lambda _: threads.deferToThread(self._setup_data_directory))
|
d.addCallback(lambda _: threads.deferToThread(self._setup_data_directory))
|
||||||
d.addCallback(lambda _: self._check_db_migration())
|
d.addCallback(lambda _: self._check_db_migration())
|
||||||
d.addCallback(lambda _: self._get_settings())
|
d.addCallback(lambda _: self._get_settings())
|
||||||
d.addCallback(lambda _: self.get_lbrycrdd_path())
|
d.addCallback(lambda _: self._get_lbrycrdd_path())
|
||||||
d.addCallback(lambda _: self._get_session())
|
d.addCallback(lambda _: self._get_session())
|
||||||
d.addCallback(lambda _: add_lbry_file_to_sd_identifier(self.sd_identifier))
|
d.addCallback(lambda _: add_lbry_file_to_sd_identifier(self.sd_identifier))
|
||||||
d.addCallback(lambda _: self._setup_stream_identifier())
|
d.addCallback(lambda _: self._setup_stream_identifier())
|
||||||
d.addCallback(lambda _: self._setup_lbry_file_manager())
|
d.addCallback(lambda _: self._setup_lbry_file_manager())
|
||||||
d.addCallback(lambda _: self._setup_lbry_file_opener())
|
d.addCallback(lambda _: self._setup_lbry_file_opener())
|
||||||
d.addCallback(lambda _: self._setup_fetcher())
|
d.addCallback(lambda _: self._setup_fetcher())
|
||||||
|
d.addCallback(lambda _: _disp_startup())
|
||||||
d.callback(None)
|
d.callback(None)
|
||||||
|
|
||||||
return defer.succeed(None)
|
return defer.succeed(None)
|
||||||
|
|
||||||
|
def _shutdown(self):
|
||||||
|
print 'Closing lbrynet session'
|
||||||
|
if self.session is not None:
|
||||||
|
d = self.session.shut_down()
|
||||||
|
else:
|
||||||
|
d = defer.Deferred()
|
||||||
|
return d
|
||||||
|
|
||||||
def _update_settings(self):
|
def _update_settings(self):
|
||||||
self.data_rate = self.session_settings['data_rate']
|
self.data_rate = self.session_settings['data_rate']
|
||||||
self.max_key_fee = self.session_settings['max_key_fee']
|
self.max_key_fee = self.session_settings['max_key_fee']
|
||||||
|
@ -148,7 +177,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
d = self.settings.start()
|
d = self.settings.start()
|
||||||
d.addCallback(lambda _: self.settings.get_lbryid())
|
d.addCallback(lambda _: self.settings.get_lbryid())
|
||||||
d.addCallback(self.set_lbryid)
|
d.addCallback(self.set_lbryid)
|
||||||
d.addCallback(lambda _: self.get_lbrycrdd_path())
|
d.addCallback(lambda _: self._get_lbrycrdd_path())
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def set_lbryid(self, lbryid):
|
def set_lbryid(self, lbryid):
|
||||||
|
@ -218,7 +247,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
dl.addCallback(lambda _: self.session.setup())
|
dl.addCallback(lambda _: self.session.setup())
|
||||||
return dl
|
return dl
|
||||||
|
|
||||||
def get_lbrycrdd_path(self):
|
def _get_lbrycrdd_path(self):
|
||||||
def get_lbrycrdd_path_conf_file():
|
def get_lbrycrdd_path_conf_file():
|
||||||
lbrycrdd_path_conf_path = os.path.join(os.path.expanduser("~"), ".lbrycrddpath.conf")
|
lbrycrdd_path_conf_path = os.path.join(os.path.expanduser("~"), ".lbrycrddpath.conf")
|
||||||
if not os.path.exists(lbrycrdd_path_conf_path):
|
if not os.path.exists(lbrycrdd_path_conf_path):
|
||||||
|
@ -270,63 +299,123 @@ class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
return defer.succeed(True)
|
return defer.succeed(True)
|
||||||
|
|
||||||
def _download_name(self, name):
|
def _download_name(self, name):
|
||||||
def _disp(stream):
|
def _disp_file(file):
|
||||||
print '[' + str(datetime.now()) + ']' + ' Downloading: ' + str(stream.stream_hash)
|
print '[' + str(datetime.now()) + ']' + ' Already downloaded: ' + str(file.stream_hash)
|
||||||
log.debug('[' + str(datetime.now()) + ']' + ' Downloading: ' + str(stream.stream_hash))
|
d = self._path_from_lbry_file(file)
|
||||||
return defer.succeed(None)
|
return d
|
||||||
|
|
||||||
stream = GetStream(self.sd_identifier, self.session, self.session.wallet, self.lbry_file_manager,
|
def _get_stream(name):
|
||||||
max_key_fee=self.max_key_fee, data_rate=self.data_rate)
|
def _disp(stream):
|
||||||
self.downloads.append(stream)
|
print '[' + str(datetime.now()) + ']' + ' Start stream: ' + stream['stream_hash']
|
||||||
|
return stream
|
||||||
|
|
||||||
d = self.session.wallet.get_stream_info_for_name(name)
|
d = self.session.wallet.get_stream_info_for_name(name)
|
||||||
d.addCallback(lambda stream_info: stream.start(stream_info))
|
stream = GetStream(self.sd_identifier, self.session, self.session.wallet, self.lbry_file_manager,
|
||||||
d.addCallback(lambda _: _disp(stream))
|
max_key_fee=self.max_key_fee, data_rate=self.data_rate)
|
||||||
d.addCallback(lambda _: {'ts': datetime.now(),'name': name})
|
d.addCallback(_disp)
|
||||||
d.addErrback(lambda err: str(err.getTraceback()))
|
d.addCallback(lambda stream_info: stream.start(stream_info))
|
||||||
|
d.addCallback(lambda _: self._path_from_name(name))
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
d = self._check_history(name)
|
||||||
|
d.addCallback(lambda lbry_file: _get_stream(name) if not lbry_file else _disp_file(lbry_file))
|
||||||
|
d.addCallback(lambda _: self._check_history(name))
|
||||||
|
d.addCallback(lambda lbry_file: self._path_from_lbry_file(lbry_file) if lbry_file else 'Not found')
|
||||||
|
d.addErrback(lambda err: str(err))
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _path_from_name(self, name):
|
|
||||||
d = self.session.wallet.get_stream_info_for_name(name)
|
|
||||||
d.addCallback(lambda stream_info: stream_info['stream_hash'])
|
|
||||||
d.addCallback(lambda stream_hash: [{'stream_hash': stream.stream_hash,
|
|
||||||
'path': os.path.join(stream.downloader.download_directory,
|
|
||||||
stream.downloader.file_name)}
|
|
||||||
for stream in self.downloads if stream.stream_hash == stream_hash][0])
|
|
||||||
d.addErrback(lambda _: 'UnknownNameError')
|
|
||||||
return d
|
|
||||||
|
|
||||||
def _get_downloads(self):
|
|
||||||
downloads = []
|
|
||||||
for stream in self.downloads:
|
|
||||||
try:
|
|
||||||
downloads.append({'stream_hash': stream.stream_hash,
|
|
||||||
'path': os.path.join(stream.downloader.download_directory, stream.downloader.file_name)})
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return downloads
|
|
||||||
|
|
||||||
def _resolve_name(self, name):
|
def _resolve_name(self, name):
|
||||||
d = defer.Deferred()
|
d = defer.Deferred()
|
||||||
d.addCallback(lambda _: self.session.wallet.get_stream_info_for_name(name))
|
d.addCallback(lambda _: self.session.wallet.get_stream_info_for_name(name))
|
||||||
d.addErrback(lambda _: 'UnknownNameError')
|
d.addErrback(lambda _: defer.fail(UnknownNameError))
|
||||||
d.callback(None)
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_name_wc(self, name):
|
||||||
|
d = defer.Deferred()
|
||||||
|
d.addCallback(lambda _: self.session.wallet.get_stream_info_for_name(name))
|
||||||
|
d.addErrback(lambda _: defer.fail(UnknownNameError))
|
||||||
|
d.callback(None)
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _check_history(self, name):
|
||||||
|
def _get_lbry_file(path):
|
||||||
|
f = open(path, 'r')
|
||||||
|
l = json.loads(f.read())
|
||||||
|
f.close()
|
||||||
|
file_name = l['stream_name'].decode('hex')
|
||||||
|
lbry_file = [file for file in self.lbry_file_manager.lbry_files if file.stream_name == file_name][0]
|
||||||
|
return lbry_file
|
||||||
|
|
||||||
|
def _check(info):
|
||||||
|
stream_hash = info['stream_hash']
|
||||||
|
path = os.path.join(self.blobfile_dir, stream_hash)
|
||||||
|
if os.path.isfile(path):
|
||||||
|
print "[" + str(datetime.now()) + "] Search for lbry_file, returning: " + stream_hash
|
||||||
|
return defer.succeed(_get_lbry_file(path))
|
||||||
|
else:
|
||||||
|
print "[" + str(datetime.now()) + "] Search for lbry_file didn't return anything"
|
||||||
|
return defer.succeed(False)
|
||||||
|
|
||||||
|
d = self._resolve_name(name)
|
||||||
|
d.addCallbacks(_check, lambda _: False)
|
||||||
|
d.callback(None)
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _delete_lbry_file(self, lbry_file):
|
||||||
|
d = self.lbry_file_manager.delete_lbry_file(lbry_file)
|
||||||
|
|
||||||
|
def finish_deletion(lbry_file):
|
||||||
|
d = lbry_file.delete_data()
|
||||||
|
d.addCallback(lambda _: _delete_stream_data(lbry_file))
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _delete_stream_data(lbry_file):
|
||||||
|
s_h = lbry_file.stream_hash
|
||||||
|
d = self.lbry_file_manager.get_count_for_stream_hash(s_h)
|
||||||
|
# TODO: could possibly be a timing issue here
|
||||||
|
d.addCallback(lambda c: self.stream_info_manager.delete_stream(s_h) if c == 0 else True)
|
||||||
|
return d
|
||||||
|
|
||||||
|
d.addCallback(lambda _: finish_deletion(lbry_file))
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _path_from_name(self, name):
|
||||||
|
d = self._check_history(name)
|
||||||
|
d.addCallback(lambda lbry_file: {'stream_hash': lbry_file.stream_hash,
|
||||||
|
'path': os.path.join(self.download_directory, lbry_file.file_name)}
|
||||||
|
if lbry_file else defer.fail(UnknownNameError))
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _path_from_lbry_file(self, lbry_file):
|
||||||
|
if lbry_file:
|
||||||
|
r = {'stream_hash': lbry_file.stream_hash,
|
||||||
|
'path': os.path.join(self.download_directory, lbry_file.file_name)}
|
||||||
|
return defer.succeed(r)
|
||||||
|
else:
|
||||||
|
return defer.fail(UnknownNameError)
|
||||||
|
|
||||||
def xmlrpc_get_settings(self):
|
def xmlrpc_get_settings(self):
|
||||||
"""
|
"""
|
||||||
Get LBRY payment settings
|
Get LBRY payment settings
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not self.session_settings:
|
if not self.session_settings:
|
||||||
self.session_settings = {'data_rate': self.data_rate, 'max_key_fee': self.max_key_fee}
|
self.session_settings = {'data_rate': self.data_rate, 'max_key_fee': self.max_key_fee}
|
||||||
|
|
||||||
|
print '[' + str(datetime.now()) + '] Get daemon settings'
|
||||||
return self.session_settings
|
return self.session_settings
|
||||||
|
|
||||||
def xmlrpc_set_settings(self, settings):
|
def xmlrpc_set_settings(self, settings):
|
||||||
self.session_settings = settings
|
self.session_settings = settings
|
||||||
self._update_settings()
|
self._update_settings()
|
||||||
|
|
||||||
|
print '[' + str(datetime.now()) + '] Set daemon settings'
|
||||||
return 'Set'
|
return 'Set'
|
||||||
|
|
||||||
def xmlrpc_start_fetcher(self):
|
def xmlrpc_start_fetcher(self):
|
||||||
|
@ -335,7 +424,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.fetcher.start()
|
self.fetcher.start()
|
||||||
|
print '[' + str(datetime.now()) + '] Start autofetcher'
|
||||||
return str('Started autofetching')
|
return str('Started autofetching')
|
||||||
|
|
||||||
def xmlrpc_stop_fetcher(self):
|
def xmlrpc_stop_fetcher(self):
|
||||||
|
@ -344,7 +433,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.fetcher.stop()
|
self.fetcher.stop()
|
||||||
|
print '[' + str(datetime.now()) + '] Stop autofetcher'
|
||||||
return str('Started autofetching')
|
return str('Started autofetching')
|
||||||
|
|
||||||
def xmlrpc_fetcher_status(self):
|
def xmlrpc_fetcher_status(self):
|
||||||
|
@ -352,6 +441,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
Start autofetcher
|
Start autofetcher
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
print '[' + str(datetime.now()) + '] Get fetcher status'
|
||||||
return str(self.fetcher.check_if_running())
|
return str(self.fetcher.check_if_running())
|
||||||
|
|
||||||
def xmlrpc_get_balance(self):
|
def xmlrpc_get_balance(self):
|
||||||
|
@ -359,6 +449,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
Get LBC balance
|
Get LBC balance
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
print '[' + str(datetime.now()) + '] Get balance'
|
||||||
return str(self.session.wallet.wallet_balance)
|
return str(self.session.wallet.wallet_balance)
|
||||||
|
|
||||||
def xmlrpc_stop(self):
|
def xmlrpc_stop(self):
|
||||||
|
@ -366,8 +457,15 @@ class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
Stop the reactor
|
Stop the reactor
|
||||||
"""
|
"""
|
||||||
|
|
||||||
reactor.stop()
|
def _disp_shutdown():
|
||||||
return defer.succeed('Stopping')
|
print 'Shutting down lbrynet daemon'
|
||||||
|
|
||||||
|
d = self._shutdown()
|
||||||
|
d.addCallback(lambda _: _disp_shutdown())
|
||||||
|
d.addCallback(lambda _: reactor.stop())
|
||||||
|
d.callback(None)
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
def xmlrpc_get_lbry_files(self):
|
def xmlrpc_get_lbry_files(self):
|
||||||
"""
|
"""
|
||||||
|
@ -376,7 +474,23 @@ class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
@return: Managed LBRY files
|
@return: Managed LBRY files
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return [[str(i), str(dir(i))] for i in self.lbry_file_manager.lbry_files]
|
r = []
|
||||||
|
for f in self.lbry_file_manager.lbry_files:
|
||||||
|
if f.key:
|
||||||
|
t = {'completed': f.completed, 'file_name': f.file_name, 'key': binascii.b2a_hex(f.key),
|
||||||
|
'points_paid': f.points_paid, 'stopped': f.stopped, 'stream_hash': f.stream_hash,
|
||||||
|
'stream_name': f.stream_name, 'suggested_file_name': f.suggested_file_name,
|
||||||
|
'upload_allowed': f.upload_allowed}
|
||||||
|
|
||||||
|
else:
|
||||||
|
t = {'completed': f.completed, 'file_name': f.file_name, 'key': None, 'points_paid': f.points_paid,
|
||||||
|
'stopped': f.stopped, 'stream_hash': f.stream_hash, 'stream_name': f.stream_name,
|
||||||
|
'suggested_file_name': f.suggested_file_name, 'upload_allowed': f.upload_allowed}
|
||||||
|
|
||||||
|
r.append(json.dumps(t))
|
||||||
|
|
||||||
|
print '[' + str(datetime.now()) + '] Get LBRY files'
|
||||||
|
return r
|
||||||
|
|
||||||
def xmlrpc_resolve_name(self, name):
|
def xmlrpc_resolve_name(self, name):
|
||||||
"""
|
"""
|
||||||
|
@ -386,89 +500,155 @@ class LBRYDaemon(xmlrpc.XMLRPC):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _disp(info):
|
def _disp(info):
|
||||||
log.debug('[' + str(datetime.now()) + ']' + ' Resolved info: ' + str(info))
|
log.debug('[' + str(datetime.now()) + ']' + ' Resolved info: ' + str(info['stream_hash']))
|
||||||
print '[' + str(datetime.now()) + ']' + ' Resolved info: ' + str(info)
|
print '[' + str(datetime.now()) + ']' + ' Resolved info: ' + str(info['stream_hash'])
|
||||||
return info
|
return info
|
||||||
|
|
||||||
d = defer.Deferred()
|
d = self._resolve_name(name)
|
||||||
d.addCallback(lambda _: self.session.wallet.get_stream_info_for_name(name))
|
d.addCallbacks(_disp, lambda _: str('UnknownNameError'))
|
||||||
d.addErrback(lambda _: 'UnknownNameError')
|
|
||||||
d.addCallback(_disp)
|
|
||||||
d.callback(None)
|
d.callback(None)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def xmlrpc_get_downloads(self):
|
def xmlrpc_get(self, name):
|
||||||
"""
|
|
||||||
Get files downloaded in this session
|
|
||||||
|
|
||||||
@return: [{stream_hash, path}]
|
|
||||||
"""
|
|
||||||
|
|
||||||
downloads = []
|
|
||||||
|
|
||||||
for stream in self.downloads:
|
|
||||||
try:
|
|
||||||
downloads.append({'stream_hash': stream.stream_hash,
|
|
||||||
'path': os.path.join(stream.downloader.download_directory, stream.downloader.file_name)})
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return downloads
|
|
||||||
|
|
||||||
def xmlrpc_download_name(self, name):
|
|
||||||
"""
|
"""
|
||||||
Download stream from a LBRY uri
|
Download stream from a LBRY uri
|
||||||
|
|
||||||
@param: name
|
@param: name
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _disp(stream):
|
d = self._download_name(name)
|
||||||
print '[' + str(datetime.now()) + ']' + ' Downloading: ' + str(stream.stream_hash)
|
|
||||||
log.debug('[' + str(datetime.now()) + ']' + ' Downloading: ' + str(stream.stream_hash))
|
return d
|
||||||
|
|
||||||
|
def xmlrpc_stop_lbry_file(self, stream_hash):
|
||||||
|
try:
|
||||||
|
lbry_file = [f for f in self.lbry_file_manager.lbry_files if f.stream_hash == stream_hash][0]
|
||||||
|
except IndexError:
|
||||||
|
return defer.fail(UnknownNameError)
|
||||||
|
|
||||||
|
if not lbry_file.stopped:
|
||||||
|
d = self.lbry_file_manager.toggle_lbry_file_running(lbry_file)
|
||||||
|
d.addCallback(lambda _: 'Stream has been stopped')
|
||||||
|
d.addErrback(lambda err: str(err))
|
||||||
|
return d
|
||||||
|
else:
|
||||||
|
return defer.succeed('Stream was already stopped')
|
||||||
|
|
||||||
|
def xmlrpc_start_lbry_file(self, stream_hash):
|
||||||
|
try:
|
||||||
|
lbry_file = [f for f in self.lbry_file_manager.lbry_files if f.stream_hash == stream_hash][0]
|
||||||
|
except IndexError:
|
||||||
|
return defer.fail(UnknownNameError)
|
||||||
|
|
||||||
|
if lbry_file.stopped:
|
||||||
|
d = self.lbry_file_manager.toggle_lbry_file_running(lbry_file)
|
||||||
|
d.callback(None)
|
||||||
|
return defer.succeed('Stream started')
|
||||||
|
else:
|
||||||
|
return defer.succeed('Stream was already running')
|
||||||
|
|
||||||
|
|
||||||
|
def xmlrpc_render_html(self, html):
|
||||||
|
def _make_file(html, path):
|
||||||
|
f = open(path, 'w')
|
||||||
|
f.write(html)
|
||||||
|
f.close()
|
||||||
return defer.succeed(None)
|
return defer.succeed(None)
|
||||||
|
|
||||||
stream = GetStream(self.sd_identifier, self.session, self.session.wallet, self.lbry_file_manager,
|
def _disp_err(err):
|
||||||
max_key_fee=self.max_key_fee, data_rate=self.data_rate)
|
print str(err.getTraceback())
|
||||||
|
return err
|
||||||
|
|
||||||
self.downloads.append(stream)
|
path = os.path.join(self.download_directory, 'lbry.html')
|
||||||
|
|
||||||
d = self.session.wallet.get_stream_info_for_name(name)
|
d = defer.Deferred()
|
||||||
d.addCallback(lambda stream_info: stream.start(stream_info))
|
d.addCallback(lambda _: _make_file(html, path))
|
||||||
d.addCallback(lambda _: _disp(stream))
|
d.addCallback(lambda _: webbrowser.open('file://' + path))
|
||||||
d.addCallback(lambda _: {'ts': datetime.now(),'name': name})
|
d.addErrback(_disp_err)
|
||||||
d.addErrback(lambda err: str(err.getTraceback()))
|
|
||||||
|
|
||||||
return d
|
|
||||||
|
|
||||||
def xmlrpc_path_from_name(self, name):
|
|
||||||
"""
|
|
||||||
Get file path for a downloaded name
|
|
||||||
|
|
||||||
@param: name
|
|
||||||
@return: {stream_hash, path}:
|
|
||||||
"""
|
|
||||||
|
|
||||||
d = self.session.wallet.get_stream_info_for_name(name)
|
|
||||||
d.addCallback(lambda stream_info: stream_info['stream_hash'])
|
|
||||||
d.addCallback(lambda stream_hash: [{'stream_hash': stream.stream_hash,
|
|
||||||
'path': os.path.join(stream.downloader.download_directory,
|
|
||||||
stream.downloader.file_name)}
|
|
||||||
for stream in self.downloads if stream.stream_hash == stream_hash][0])
|
|
||||||
d.addErrback(lambda _: 'UnknownNameError')
|
|
||||||
return d
|
|
||||||
|
|
||||||
def xmlrpc_get(self, name):
|
|
||||||
"""
|
|
||||||
Download a name and return the path of the resulting file
|
|
||||||
|
|
||||||
@param: name:
|
|
||||||
@return: {stream_hash, path}:
|
|
||||||
"""
|
|
||||||
|
|
||||||
d = defer.Deferred(None)
|
|
||||||
d.addCallback(lambda _: self._download_name(name))
|
|
||||||
d.addCallback(lambda _: self._path_from_name(name))
|
|
||||||
d.callback(None)
|
d.callback(None)
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
def xmlrpc_render_gui(self):
|
||||||
|
def _disp_err(err):
|
||||||
|
print str(err.getTraceback())
|
||||||
|
return err
|
||||||
|
d = defer.Deferred()
|
||||||
|
d.addCallback(lambda _: webbrowser.open("https://rawgit.com/jackrobison/lbry.io/local/view/page/demo.html"))
|
||||||
|
d.addErrback(_disp_err)
|
||||||
|
d.callback(None)
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
def xmlrpc_search_nametrie(self, search):
|
||||||
|
def _return_d(x):
|
||||||
|
d = defer.Deferred()
|
||||||
|
d.addCallback(lambda _: x)
|
||||||
|
d.callback(None)
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _clean(n):
|
||||||
|
t = []
|
||||||
|
for i in n:
|
||||||
|
if i[0]:
|
||||||
|
if i[1][0][0] and i[1][1][0]:
|
||||||
|
i[1][0][1]['value'] = str(i[1][0][1]['value'])
|
||||||
|
t.append([i[1][0][1], i[1][1][1]])
|
||||||
|
return t
|
||||||
|
|
||||||
|
def _parse(results):
|
||||||
|
f = []
|
||||||
|
for chain, meta in results:
|
||||||
|
t = {}
|
||||||
|
if 'name' in chain.keys():
|
||||||
|
t['name'] = chain['name']
|
||||||
|
if 'thumbnail' in meta.keys():
|
||||||
|
t['img'] = meta['thumbnail']
|
||||||
|
if 'name' in meta.keys():
|
||||||
|
t['title'] = meta['name']
|
||||||
|
if 'description' in meta.keys():
|
||||||
|
t['description'] = meta['description']
|
||||||
|
if 'key_fee' in meta.keys():
|
||||||
|
t['cost_est'] = meta['key_fee']
|
||||||
|
else:
|
||||||
|
t['cost_est'] = 0.0
|
||||||
|
f.append(t)
|
||||||
|
|
||||||
|
return f
|
||||||
|
|
||||||
|
def _disp(results):
|
||||||
|
print '[' + str(datetime.now()) + '] Found ' + str(len(results)) + ' results'
|
||||||
|
return results
|
||||||
|
|
||||||
|
print '[' + str(datetime.now()) + '] Search nametrie: ' + search
|
||||||
|
|
||||||
|
filtered_results = [n for n in self.rpc_conn.getnametrie() if n['name'].startswith(search)]
|
||||||
|
filtered_results = [n for n in filtered_results if 'txid' in n.keys()]
|
||||||
|
resolved_results = [defer.DeferredList([_return_d(n), self._resolve_name_wc(n['name'])]) for n in filtered_results]
|
||||||
|
|
||||||
|
d = defer.DeferredList(resolved_results)
|
||||||
|
d.addCallback(_clean)
|
||||||
|
d.addCallback(_parse)
|
||||||
|
d.addCallback(_disp)
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
def xmlrpc_delete_lbry_file(self, file_name):
|
||||||
|
def _disp(file_name):
|
||||||
|
print '[' + str(datetime.now()) + '] Deleted: ' + file_name
|
||||||
|
return defer.succeed(str('Deleted: ' + file_name))
|
||||||
|
|
||||||
|
lbry_files = [self._delete_lbry_file(f) for f in self.lbry_file_manager.lbry_files if file_name == f.file_name]
|
||||||
|
d = defer.DeferredList(lbry_files)
|
||||||
|
d.addCallback(lambda _: _disp(file_name))
|
||||||
|
return d
|
||||||
|
|
||||||
|
def xmlrpc_check(self, name):
|
||||||
|
d = self._check_history(name)
|
||||||
|
d.addCallback(lambda lbry_file: self._path_from_lbry_file(lbry_file) if lbry_file else 'Not found')
|
||||||
|
d.addErrback(lambda err: str(err))
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,31 +13,23 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
class GetStream(object):
|
class GetStream(object):
|
||||||
def __init__(self, sd_identifier, session, wallet, lbry_file_manager, max_key_fee, pay_key=True, data_rate=0.5):
|
def __init__(self, sd_identifier, session, wallet, lbry_file_manager, max_key_fee, pay_key=True, data_rate=0.5):
|
||||||
self.finished_deferred = defer.Deferred(None)
|
|
||||||
self.wallet = wallet
|
self.wallet = wallet
|
||||||
self.resolved_name = None
|
self.resolved_name = None
|
||||||
self.description = None
|
self.description = None
|
||||||
self.key_fee = None
|
self.key_fee = None
|
||||||
self.key_fee_address = None
|
self.key_fee_address = None
|
||||||
|
self.data_rate = data_rate
|
||||||
|
self.pay_key = pay_key
|
||||||
self.name = None
|
self.name = None
|
||||||
self.session = session
|
self.session = session
|
||||||
self.payment_rate_manager = PaymentRateManager(self.session.base_payment_rate_manager)
|
self.payment_rate_manager = PaymentRateManager(self.session.base_payment_rate_manager)
|
||||||
self.loading_metadata_deferred = defer.Deferred()
|
|
||||||
self.lbry_file_manager = lbry_file_manager
|
self.lbry_file_manager = lbry_file_manager
|
||||||
self.sd_identifier = sd_identifier
|
self.sd_identifier = sd_identifier
|
||||||
self.metadata = None
|
|
||||||
self.loading_failed = False
|
|
||||||
self.resolved_name = None
|
|
||||||
self.description = None
|
|
||||||
self.key_fee = None
|
|
||||||
self.key_fee_address = None
|
|
||||||
self.stream_hash = None
|
self.stream_hash = None
|
||||||
self.max_key_fee = max_key_fee
|
self.max_key_fee = max_key_fee
|
||||||
self.stream_info = None
|
self.stream_info = None
|
||||||
self.stream_info_manager = None
|
self.stream_info_manager = None
|
||||||
self.downloader = None
|
|
||||||
self.data_rate = data_rate
|
|
||||||
self.pay_key = pay_key
|
|
||||||
|
|
||||||
def start(self, stream_info):
|
def start(self, stream_info):
|
||||||
self.stream_info = stream_info
|
self.stream_info = stream_info
|
||||||
|
@ -52,18 +44,9 @@ class GetStream(object):
|
||||||
else:
|
else:
|
||||||
self.key_fee = None
|
self.key_fee = None
|
||||||
self.key_fee_address = None
|
self.key_fee_address = None
|
||||||
self.stream_hash = self.stream_info['stream_hash']
|
|
||||||
elif 'stream_hash' in json.loads(self.stream_info['value']):
|
|
||||||
self.resolved_name = self.stream_info.get('name', None)
|
|
||||||
self.description = json.loads(self.stream_info['value']).get('description', None)
|
|
||||||
|
|
||||||
try:
|
self.stream_hash = self.stream_info['stream_hash']
|
||||||
if 'key_fee' in json.loads(self.stream_info['value']):
|
|
||||||
self.key_fee = float(json.loads(self.stream_info['value'])['key_fee'])
|
|
||||||
except ValueError:
|
|
||||||
self.key_fee = None
|
|
||||||
self.key_fee_address = json.loads(self.stream_info['value']).get('key_fee_address', None)
|
|
||||||
self.stream_hash = json.loads(self.stream_info['value'])['stream_hash']
|
|
||||||
else:
|
else:
|
||||||
print 'InvalidStreamInfoError'
|
print 'InvalidStreamInfoError'
|
||||||
raise InvalidStreamInfoError(self.stream_info)
|
raise InvalidStreamInfoError(self.stream_info)
|
||||||
|
@ -72,71 +55,42 @@ class GetStream(object):
|
||||||
if self.pay_key:
|
if self.pay_key:
|
||||||
print "Key fee (" + str(self.key_fee) + ") above limit of " + str(
|
print "Key fee (" + str(self.key_fee) + ") above limit of " + str(
|
||||||
self.max_key_fee) + ", didn't download lbry://" + str(self.resolved_name)
|
self.max_key_fee) + ", didn't download lbry://" + str(self.resolved_name)
|
||||||
return self.finished_deferred.callback(None)
|
return defer.fail(None)
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _get_downloader_for_return():
|
d = defer.Deferred(None)
|
||||||
return defer.succeed(self.downloader)
|
d.addCallback(lambda _: download_sd_blob(self.session, self.stream_hash, self.payment_rate_manager))
|
||||||
|
d.addCallback(self.sd_identifier.get_metadata_for_sd_blob)
|
||||||
|
d.addCallback(lambda metadata:
|
||||||
|
metadata.factories[1].make_downloader(metadata, [self.data_rate, True], self.payment_rate_manager))
|
||||||
|
d.addErrback(lambda err: err.trap(defer.CancelledError))
|
||||||
|
d.addErrback(lambda err: log.error("An exception occurred attempting to load the stream descriptor: %s", err.getTraceback()))
|
||||||
|
d.addCallback(self._start_download)
|
||||||
|
d.callback(None)
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _start_download(self, downloader):
|
||||||
|
def _pay_key_fee():
|
||||||
|
if self.key_fee is not None and self.key_fee_address is not None:
|
||||||
|
reserved_points = self.wallet.reserve_points(self.key_fee_address, self.key_fee)
|
||||||
|
if reserved_points is None:
|
||||||
|
return defer.fail(InsufficientFundsError())
|
||||||
|
print 'Key fee: ' + str(self.key_fee) + ' | ' + str(self.key_fee_address)
|
||||||
|
return self.wallet.send_points_to_address(reserved_points, self.key_fee)
|
||||||
|
return defer.succeed(None)
|
||||||
|
|
||||||
self.loading_metadata_deferred = defer.Deferred(None)
|
|
||||||
self.loading_metadata_deferred.addCallback(
|
|
||||||
lambda _: download_sd_blob(self.session, self.stream_hash, self.payment_rate_manager))
|
|
||||||
self.loading_metadata_deferred.addCallback(self.sd_identifier.get_metadata_for_sd_blob)
|
|
||||||
self.loading_metadata_deferred.addCallback(self._handle_metadata)
|
|
||||||
self.loading_metadata_deferred.addErrback(self._handle_load_canceled)
|
|
||||||
self.loading_metadata_deferred.addErrback(self._handle_load_failed)
|
|
||||||
if self.pay_key:
|
if self.pay_key:
|
||||||
self.loading_metadata_deferred.addCallback(lambda _: self._pay_key_fee())
|
d = _pay_key_fee()
|
||||||
self.loading_metadata_deferred.addCallback(lambda _: self._make_downloader())
|
|
||||||
self.loading_metadata_deferred.addCallback(lambda _: self.downloader.start())
|
|
||||||
self.loading_metadata_deferred.addErrback(self._handle_download_error)
|
|
||||||
self.loading_metadata_deferred.addCallback(lambda _: _get_downloader_for_return())
|
|
||||||
self.loading_metadata_deferred.callback(None)
|
|
||||||
|
|
||||||
return defer.succeed(None)
|
|
||||||
|
|
||||||
def _pay_key_fee(self):
|
|
||||||
if self.key_fee is not None and self.key_fee_address is not None:
|
|
||||||
reserved_points = self.wallet.reserve_points(self.key_fee_address, self.key_fee)
|
|
||||||
if reserved_points is None:
|
|
||||||
return defer.fail(InsufficientFundsError())
|
|
||||||
print 'Key fee: ' + str(self.key_fee) + ' | ' + str(self.key_fee_address)
|
|
||||||
return self.wallet.send_points_to_address(reserved_points, self.key_fee)
|
|
||||||
return defer.succeed(None)
|
|
||||||
|
|
||||||
def _handle_load_canceled(self, err):
|
|
||||||
err.trap(defer.CancelledError)
|
|
||||||
self.finished_deferred.callback(None)
|
|
||||||
|
|
||||||
def _handle_load_failed(self, err):
|
|
||||||
self.loading_failed = True
|
|
||||||
log.error("An exception occurred attempting to load the stream descriptor: %s", err.getTraceback())
|
|
||||||
print 'Load Failed: ', err.getTraceback()
|
|
||||||
self.finished_deferred.callback(None)
|
|
||||||
|
|
||||||
def _handle_metadata(self, metadata):
|
|
||||||
self.metadata = metadata
|
|
||||||
self.factory = self.metadata.factories[0]
|
|
||||||
return defer.succeed(None)
|
|
||||||
|
|
||||||
def _handle_download_error(self, err):
|
|
||||||
if err.check(InsufficientFundsError):
|
|
||||||
print "Download stopped due to insufficient funds."
|
|
||||||
else:
|
else:
|
||||||
print "Autoaddstream: An unexpected error has caused the download to stop: ", err.getTraceback()
|
d = defer.Deferred()
|
||||||
|
|
||||||
def _make_downloader(self):
|
downloader.start()
|
||||||
|
|
||||||
def _set_downloader(downloader):
|
print "Downloading", self.stream_hash, "-->", os.path.join(downloader.download_directory, downloader.file_name)
|
||||||
self.downloader = downloader
|
|
||||||
print "Downloading", self.stream_hash, "-->", os.path.join(self.downloader.download_directory,
|
|
||||||
self.downloader.file_name)
|
|
||||||
return self.downloader
|
|
||||||
|
|
||||||
self.downloader = self.factory.make_downloader(self.metadata, [self.data_rate, True], self.payment_rate_manager)
|
return d
|
||||||
self.downloader.addCallback(_set_downloader)
|
|
||||||
return defer.succeed(self.downloader)
|
|
||||||
|
|
||||||
|
|
||||||
class FetcherDaemon(object):
|
class FetcherDaemon(object):
|
||||||
|
@ -231,6 +185,7 @@ class FetcherDaemon(object):
|
||||||
for l in conf:
|
for l in conf:
|
||||||
if l.startswith("maxkey="):
|
if l.startswith("maxkey="):
|
||||||
settings["maxkey"] = float(l[7:].rstrip('\n'))
|
settings["maxkey"] = float(l[7:].rstrip('\n'))
|
||||||
|
print "Autofetcher using max key price of", settings["maxkey"], ", to start call start_fetcher()"
|
||||||
else:
|
else:
|
||||||
print "Autofetcher using default max key price of 0.0"
|
print "Autofetcher using default max key price of 0.0"
|
||||||
print "To change this create the file:"
|
print "To change this create the file:"
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
|
import os
|
||||||
|
import json
|
||||||
import webbrowser
|
import webbrowser
|
||||||
import xmlrpclib, sys
|
import xmlrpclib, sys
|
||||||
|
|
||||||
|
|
||||||
|
def render_video(path):
|
||||||
|
r = r'<center><video src="' + path + r'" controls autoplay width="960" height="720"></center>'
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
if len(args) == 0:
|
if len(args) == 0:
|
||||||
args.append('lbry://wonderfullife')
|
args.append('lbry://wonderfullife')
|
||||||
|
@ -12,9 +19,33 @@ def main(args):
|
||||||
print 'Too many args', args
|
print 'Too many args', args
|
||||||
|
|
||||||
else:
|
else:
|
||||||
daemon.download_name(str(args[0])[7:])
|
|
||||||
path = daemon.path_from_name(args[0][7:])[0]['path']
|
if args[0][7:] == 'lbry':
|
||||||
webbrowser.open('file://' + path)
|
daemon.render_gui()
|
||||||
|
|
||||||
|
elif args[0][7:] == 'settings':
|
||||||
|
r = daemon.get_settings()
|
||||||
|
html = "<body>" + json.dumps(r) + "</body>"
|
||||||
|
r = daemon.render_html(html)
|
||||||
|
|
||||||
|
else:
|
||||||
|
r = daemon.get(args[0][7:])
|
||||||
|
print r
|
||||||
|
path = r['path']
|
||||||
|
if path[0] != '/':
|
||||||
|
path = '/' + path
|
||||||
|
|
||||||
|
print path
|
||||||
|
filename = path.split('/')[len(path.split('/')) - 1]
|
||||||
|
extension = path.split('.')[len(path.split('.')) - 1]
|
||||||
|
|
||||||
|
if extension in ['mp4', 'flv', 'mov']:
|
||||||
|
html = render_video(path)
|
||||||
|
daemon.render_html(html)
|
||||||
|
|
||||||
|
else:
|
||||||
|
webbrowser.open('file://' + str(path))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main(sys.argv[1:])
|
main(sys.argv[1:])
|
Loading…
Reference in a new issue