forked from LBRYCommunity/lbry-sdk
add LBRYFileProducer
-Add LBRYFileProducer, to host the contents of a download without having to keep re-opening it as it is added to -included sd hash in ManagedLBRYFileDownloader, to make comparing the contents of the file manager against name claims easier -add get_lbry_file function, which returns information about a LBRY file found by sd_hash, file name, or lbry uri
This commit is contained in:
parent
3e7c09bb44
commit
c2ec066c85
4 changed files with 180 additions and 38 deletions
|
@ -24,12 +24,21 @@ class ManagedLBRYFileDownloader(LBRYFileSaver):
|
|||
LBRYFileSaver.__init__(self, stream_hash, peer_finder, rate_limiter, blob_manager,
|
||||
stream_info_manager, payment_rate_manager, wallet, download_directory,
|
||||
upload_allowed, file_name)
|
||||
self.sd_hash = None
|
||||
self.rowid = rowid
|
||||
self.lbry_file_manager = lbry_file_manager
|
||||
self.saving_status = False
|
||||
|
||||
def restore(self):
|
||||
d = self.lbry_file_manager.get_lbry_file_status(self)
|
||||
d = self.stream_info_manager._get_sd_blob_hashes_for_stream(self.stream_hash)
|
||||
|
||||
def _save_sd_hash(sd_hash):
|
||||
self.sd_hash = sd_hash[0]
|
||||
return defer.succeed(None)
|
||||
|
||||
d.addCallback(_save_sd_hash)
|
||||
|
||||
d.addCallback(lambda _: self.lbry_file_manager.get_lbry_file_status(self))
|
||||
|
||||
def restore_status(status):
|
||||
if status == ManagedLBRYFileDownloader.STATUS_RUNNING:
|
||||
|
@ -87,6 +96,14 @@ class ManagedLBRYFileDownloader(LBRYFileSaver):
|
|||
|
||||
d = LBRYFileSaver._start(self)
|
||||
|
||||
d.addCallback(lambda _: self.stream_info_manager._get_sd_blob_hashes_for_stream(self.stream_hash))
|
||||
|
||||
def _save_sd_hash(sd_hash):
|
||||
self.sd_hash = sd_hash[0]
|
||||
return defer.succeed(None)
|
||||
|
||||
d.addCallback(_save_sd_hash)
|
||||
|
||||
d.addCallback(lambda _: self._save_status())
|
||||
|
||||
return d
|
||||
|
|
|
@ -68,7 +68,6 @@ handler = logging.handlers.RotatingFileHandler(LOG_FILENAME, maxBytes=2097152, b
|
|||
log.addHandler(handler)
|
||||
log.setLevel(logging.INFO)
|
||||
|
||||
|
||||
INITIALIZING_CODE = 'initializing'
|
||||
LOADING_DB_CODE = 'loading_db'
|
||||
LOADING_WALLET_CODE = 'loading_wallet'
|
||||
|
@ -875,7 +874,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
def _disp_file(f):
|
||||
file_path = os.path.join(self.download_directory, f.file_name)
|
||||
log.info("[" + str(datetime.now()) + "] Already downloaded: " + str(f.stream_hash) + " --> " + file_path)
|
||||
return {'stream_hash': f.stream_hash, 'path': file_path}
|
||||
return f
|
||||
|
||||
def _get_stream(name):
|
||||
def _disp(stream):
|
||||
|
@ -886,13 +885,14 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
log.info("[" + str(datetime.now()) + "] Start stream: " + stream_hash)
|
||||
return stream
|
||||
|
||||
d = self.session.wallet.get_stream_info_for_name(name)
|
||||
stream = GetStream(self.sd_identifier, self.session, self.session.wallet, self.lbry_file_manager,
|
||||
stream = GetStream(self.sd_identifier, self.session, self.session.wallet,
|
||||
self.lbry_file_manager,
|
||||
max_key_fee=self.max_key_fee, data_rate=self.data_rate, timeout=timeout,
|
||||
download_directory=download_directory)
|
||||
d = self.session.wallet.get_stream_info_for_name(name)
|
||||
d.addCallback(_disp)
|
||||
d.addCallback(lambda stream_info: stream.start(stream_info, name))
|
||||
d.addCallback(lambda r: {'stream_hash': r[0], 'path': r[1]} if r else server.failure)
|
||||
d.addCallback(lambda _: stream.downloader)
|
||||
|
||||
return d
|
||||
|
||||
|
@ -1028,17 +1028,60 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
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}
|
||||
'upload_allowed': f.upload_allowed, 'sd_hash': f.sd_hash}
|
||||
|
||||
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}
|
||||
'suggested_file_name': f.suggested_file_name, 'upload_allowed': f.upload_allowed,
|
||||
'sd_hash': f.sd_hash}
|
||||
|
||||
r.append(t)
|
||||
return r
|
||||
|
||||
def _get_lbry_file_by_uri(self, name):
|
||||
d = self.session.wallet.get_stream_info_for_name(name)
|
||||
d.addCallback(lambda info: info['stream_hash'])
|
||||
d.addCallback(lambda sd_hash: next(l for l in self.lbry_file_manager.lbry_files if l.sd_hash == sd_hash))
|
||||
return d
|
||||
|
||||
def _get_lbry_file_by_sd_hash(self, sd_hash):
|
||||
r = next(l for l in self.lbry_file_manager.lbry_files if l.sd_hash == sd_hash)
|
||||
return defer.succeed(r)
|
||||
|
||||
def _get_lbry_file_by_file_name(self, file_name):
|
||||
r = next(l for l in self.lbry_file_manager.lbry_files if l.file_name == file_name)
|
||||
return defer.succeed(r)
|
||||
|
||||
def _get_lbry_file(self, search_by, val):
|
||||
def _show_file(f):
|
||||
if f:
|
||||
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, 'sd_hash': f.sd_hash}
|
||||
|
||||
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,
|
||||
'sd_hash': f.sd_hash}
|
||||
return t
|
||||
else:
|
||||
return False
|
||||
|
||||
if search_by == "name":
|
||||
d = self._get_lbry_file_by_uri(val)
|
||||
elif search_by == "sd_hash":
|
||||
d = self._get_lbry_file_by_sd_hash(val)
|
||||
elif search_by == "file_name":
|
||||
d = self._get_lbry_file_by_file_name(val)
|
||||
d.addCallback(_show_file)
|
||||
return d
|
||||
|
||||
def _log_to_slack(self, msg):
|
||||
URL = "https://hooks.slack.com/services/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"
|
||||
msg = platform.platform() + ": " + base58.b58encode(self.lbryid)[:20] + ", " + msg
|
||||
|
@ -1330,12 +1373,42 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
'stream_name': string
|
||||
'suggested_file_name': string
|
||||
'upload_allowed': bool
|
||||
'sd_hash': string
|
||||
"""
|
||||
|
||||
r = self._get_lbry_files()
|
||||
log.info("[" + str(datetime.now()) + "] Get LBRY files")
|
||||
return self._render_response(r, OK_CODE)
|
||||
|
||||
def jsonrpc_get_lbry_file(self, p):
|
||||
"""
|
||||
Get lbry file
|
||||
|
||||
Args:
|
||||
'name': get file by lbry uri,
|
||||
'sd_hash': get file by the hash in the name claim,
|
||||
'file_name': get file by its name in the downloads folder,
|
||||
Returns:
|
||||
'completed': bool
|
||||
'file_name': string
|
||||
'key': hex string
|
||||
'points_paid': float
|
||||
'stopped': bool
|
||||
'stream_hash': base 58 string
|
||||
'stream_name': string
|
||||
'suggested_file_name': string
|
||||
'upload_allowed': bool
|
||||
'sd_hash': string
|
||||
"""
|
||||
|
||||
if p.keys()[0] in ['name', 'sd_hash', 'file_name']:
|
||||
search_type = p.keys()[0]
|
||||
d = self._get_lbry_file(search_type, p[search_type])
|
||||
else:
|
||||
d = defer.fail()
|
||||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||
return d
|
||||
|
||||
def jsonrpc_resolve_name(self, p):
|
||||
"""
|
||||
Resolve stream info from a LBRY uri
|
||||
|
@ -1391,6 +1464,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
|||
name = p['name']
|
||||
if p['name'] not in self.waiting_on.keys():
|
||||
d = self._download_name(name=name, timeout=timeout, download_directory=download_directory)
|
||||
d.addCallback(lambda l: {'stream_hash': l.sd_hash, 'path': os.path.join(self.download_directory, l.file_name)})
|
||||
d.addCallback(lambda message: self._render_response(message, OK_CODE))
|
||||
else:
|
||||
d = server.failure
|
||||
|
|
|
@ -2,6 +2,8 @@ import logging
|
|||
import subprocess
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from twisted.internet.task import LoopingCall
|
||||
from txjsonrpc.web import jsonrpc
|
||||
import json
|
||||
|
||||
|
@ -12,6 +14,7 @@ from datetime import datetime
|
|||
from appdirs import user_data_dir
|
||||
from twisted.web import server, static, resource
|
||||
from twisted.internet import defer
|
||||
from twisted.web.static import StaticProducer
|
||||
|
||||
from lbrynet.lbrynet_daemon.LBRYDaemon import LBRYDaemon
|
||||
from lbrynet.conf import API_CONNECTION_STRING, API_ADDRESS, DEFAULT_WALLET, UI_ADDRESS
|
||||
|
@ -50,9 +53,77 @@ class LBRYindex(resource.Resource):
|
|||
return static.File(os.path.join(self.ui_dir, "index.html")).render_GET(request)
|
||||
|
||||
|
||||
class HostedLBRYFile(static.File):
|
||||
def __init__(self, path):
|
||||
static.File.__init__(self, path=path)
|
||||
class LBRYFileProducer(StaticProducer):
|
||||
def __init__(self, request, lbry_stream):
|
||||
self.stream = lbry_stream
|
||||
self.updater = LoopingCall(self._check_for_data)
|
||||
StaticProducer.__init__(self, request, fileObject=file(lbry_stream.file_written_to))
|
||||
|
||||
def start(self):
|
||||
d = self._set_size()
|
||||
self.updater.start(5)
|
||||
|
||||
def _set_size(self):
|
||||
def _set(size):
|
||||
self.request.setHeader('content-length', str(size))
|
||||
self.request.setHeader('content-type', ' application/octet-stream')
|
||||
return defer.succeed(None)
|
||||
|
||||
d = self.stream.get_total_bytes()
|
||||
d.addCallback(_set)
|
||||
return d
|
||||
|
||||
def _check_for_data(self):
|
||||
self.fileObject.seek(self.fileObject.tell())
|
||||
data = self.fileObject.read()
|
||||
if data:
|
||||
self.request.write(data)
|
||||
|
||||
def _check_status(stream_status):
|
||||
if stream_status.running_status == "completed":
|
||||
self.stopProducing()
|
||||
return defer.succeed(None)
|
||||
|
||||
d = self.stream.status()
|
||||
d.addCallback(_check_status)
|
||||
|
||||
def resumeProducing(self):
|
||||
self.updater.start(1)
|
||||
|
||||
def stopProducing(self):
|
||||
self.updater.stop()
|
||||
self.fileObject.close()
|
||||
self.stream.stop()
|
||||
self.request.finish()
|
||||
|
||||
|
||||
class HostedLBRYFile(resource.Resource):
|
||||
def __init__(self, api):
|
||||
self._api = api
|
||||
self.stream = None
|
||||
self.streaming_file = None
|
||||
resource.Resource.__init__(self)
|
||||
|
||||
def _set_stream(self, stream):
|
||||
self.stream = stream
|
||||
|
||||
def makeProducer(self, request, stream):
|
||||
return LBRYFileProducer(request, stream)
|
||||
|
||||
def render_GET(self, request):
|
||||
if 'name' in request.args.keys():
|
||||
if request.args['name'][0] != 'lbry':
|
||||
if request.args['name'][0] != self.streaming_file:
|
||||
self.streaming_file = request.args['name'][0]
|
||||
d = self._api._download_name(request.args['name'][0])
|
||||
d.addCallback(self._set_stream)
|
||||
else:
|
||||
d = defer.succeed(None)
|
||||
d.addCallback(lambda _: self.makeProducer(request, self.stream).start())
|
||||
else:
|
||||
request.redirect(UI_ADDRESS)
|
||||
request.finish()
|
||||
return server.NOT_DONE_YET
|
||||
|
||||
|
||||
class LBRYFileRender(resource.Resource):
|
||||
|
@ -63,7 +134,7 @@ class LBRYFileRender(resource.Resource):
|
|||
api = jsonrpc.Proxy(API_CONNECTION_STRING)
|
||||
if request.args['name'][0] != 'lbry':
|
||||
d = api.callRemote("get", {'name': request.args['name'][0]})
|
||||
d.addCallback(lambda results: HostedLBRYFile(results['path']))
|
||||
d.addCallback(lambda results: static.File(results['path'], defaultType='video/octet-stream'))
|
||||
d.addCallback(lambda static_file: static_file.render_GET(request) if static_file.getFileSize() > 0
|
||||
else server.failure)
|
||||
else:
|
||||
|
@ -74,29 +145,6 @@ class LBRYFileRender(resource.Resource):
|
|||
return server.failure
|
||||
|
||||
|
||||
class LBRYBugReport(resource.Resource):
|
||||
isLeaf = False
|
||||
|
||||
def _delayed_render(self, request, results):
|
||||
request.write(results)
|
||||
request.finish()
|
||||
|
||||
def render_GET(self, request):
|
||||
return '<html><body><form method="POST">' \
|
||||
'<br>Please describe the problem you experienced and any information you think might be useful to us. Links to screenshots are great!</br>' \
|
||||
'<textarea cols="50" rows="10" name="message" type="text"></textarea>' \
|
||||
'<button>Submit</button>' \
|
||||
'</form></body></html>'
|
||||
|
||||
def render_POST(self, request):
|
||||
msg = request.args["message"][0]
|
||||
api = jsonrpc.Proxy(API_CONNECTION_STRING)
|
||||
d = api.callRemote("upload_log", {'name_prefix': 'report', 'exclude_previous': False, 'force': True, 'message': str(msg)})
|
||||
d.addCallback(lambda _: self._delayed_render(request, "<html><body>Your bug report is greatly appreciated! <a href='lbry://lbry'>Click here to return to LBRY</a></body></html>"))
|
||||
|
||||
return server.NOT_DONE_YET
|
||||
|
||||
|
||||
class LBRYDaemonServer(object):
|
||||
def __init__(self):
|
||||
self.data_dir = user_data_dir("LBRY")
|
||||
|
@ -207,8 +255,8 @@ class LBRYDaemonServer(object):
|
|||
self.root.putChild("font", static.File(os.path.join(self.ui_dir, "font")))
|
||||
self.root.putChild("img", static.File(os.path.join(self.ui_dir, "img")))
|
||||
self.root.putChild("js", static.File(os.path.join(self.ui_dir, "js")))
|
||||
self.root.putChild("view", LBRYFileRender())
|
||||
self.root.putChild("report", LBRYBugReport())
|
||||
# self.root.putChild("view", LBRYFileRender())
|
||||
self.root.putChild("view", HostedLBRYFile(self._api))
|
||||
self.root.putChild(API_ADDRESS, self._api)
|
||||
return defer.succeed(True)
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ class GetStream(object):
|
|||
self.timeout_counter = 0
|
||||
self.download_directory = download_directory
|
||||
self.download_path = None
|
||||
self.downloader = None
|
||||
self.finished = defer.Deferred()
|
||||
self.checker = LoopingCall(self.check_status)
|
||||
|
||||
|
@ -120,9 +121,11 @@ class GetStream(object):
|
|||
d = _pay_key_fee()
|
||||
else:
|
||||
d = defer.Deferred()
|
||||
self.downloader = downloader
|
||||
self.download_path = os.path.join(downloader.download_directory, downloader.file_name)
|
||||
d.addCallback(lambda _: log.info("Downloading " + str(self.stream_hash) + " --> " + str(self.download_path)))
|
||||
d.addCallback(lambda _: downloader.start())
|
||||
d.addCallback(lambda _: self.downloader.start())
|
||||
|
||||
|
||||
class FetcherDaemon(object):
|
||||
def __init__(self, session, lbry_file_manager, lbry_file_metadata_manager, wallet, sd_identifier, autofetcher_conf,
|
||||
|
|
Loading…
Reference in a new issue