diff --git a/lbrynet/core/client/AutoDownloader.py b/lbrynet/core/client/AutoDownloader.py index 70edce257..df69f561f 100644 --- a/lbrynet/core/client/AutoDownloader.py +++ b/lbrynet/core/client/AutoDownloader.py @@ -113,6 +113,142 @@ class AutoAddStream(object): return self.downloader +class GetStream(object): + def __init__(self, console, sd_identifier, session, wallet, lbry_file_manager, max_key_fee, + console_on=True, pay_key=True): + self.finished_deferred = defer.Deferred(None) + self.console_on = console_on + self.pay_key = pay_key + self.console = console + self.wallet = wallet + self.resolved_name = None + self.description = None + self.key_fee = None + self.key_fee_address = None + self.name = None + self.session = session + 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.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.max_key_fee = max_key_fee + self.stream_info = None + self.stream_info_manager = None + self.downloader = None + + def start(self, stream_info): + self.stream_info = stream_info + try: + if '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: + 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: + raise InvalidStreamInfoError(self.stream_info) + + except: + if 'stream_hash' in self.stream_info.keys(): + self.description = self.stream_info['description'] + if 'key_fee' in self.stream_info.keys(): + self.key_fee = float(self.stream_info['key_fee']) + self.key_fee_address = self.stream_info['key_fee_address'] + else: + self.key_fee = None + self.stream_hash = self.stream_info['stream_hash'] + else: + raise InvalidStreamInfoError(self.stream_info) + + # if self.key_fee < self.max_key_fee: + # if self.pay_key: + # if self.console_on: + # self.console.sendLine("Key fee (" + str(self.key_fee) + ") above limit of " + str( + # self.max_key_fee) + ", didn't download lbry://" + str(self.resolved_name)) + # return self.finished_deferred.callback(None) + # else: + # pass + # else: + # pass + + def _get_downloader_for_return(): + return defer.succeed(self.downloader) + + 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) + 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()) + return self.wallet.send_points_to_address(reserved_points, self.key_fee) + if self.console_on: + self.console.sendLine("Sent key fee" + str(self.key_fee_address) + " | " + str(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 + if self.console_on: + self.console.sendLine("handle load failed: " + str(err.getTraceback())) + 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) #self._start_download() + + def _handle_download_error(self, err): + if self.console_on: + if err.check(InsufficientFundsError): + self.console.sendLine("Download stopped due to insufficient funds.") + else: + self.console.sendLine( + "Autoaddstream: An unexpected error has caused the download to stop: %s" % err.getTraceback()) + else: + print "Autoaddstream: An unexpected error has caused the download to stop: ", err.getTraceback() + + def _make_downloader(self): + + def _set_downloader(downloader): + self.downloader = downloader + print os.path.join(self.downloader.download_directory, self.downloader.file_name) + return self.downloader + + self.downloader = self.factory.make_downloader(self.metadata, [0.5, True], self.payment_rate_manager) + self.downloader.addCallback(_set_downloader) + return defer.succeed(self.downloader) + + class AutoFetcher(object): def __init__(self, session, lbry_file_manager, lbry_file_metadata_manager, wallet, sd_identifier, autofetcher_conf): self.autofetcher_conf = autofetcher_conf diff --git a/lbrynet/lbryfilemanager/LBRYFileManager.py b/lbrynet/lbryfilemanager/LBRYFileManager.py index f27f6052e..c2e426bfa 100644 --- a/lbrynet/lbryfilemanager/LBRYFileManager.py +++ b/lbrynet/lbryfilemanager/LBRYFileManager.py @@ -31,7 +31,10 @@ class LBRYFileManager(object): self.sd_identifier = sd_identifier self.lbry_files = [] self.sql_db = None - self.download_directory = os.getcwd() + if os.name == 'posix': + self.download_directory = os.path.join(os.path.expanduser("~"), 'Downloads') + else: + self.download_directory = os.getcwd() def setup(self): d = self._open_db() diff --git a/lbrynet/lbrynet_daemon/LBRYDaemon.py b/lbrynet/lbrynet_daemon/LBRYDaemon.py new file mode 100644 index 000000000..cb9e6e54c --- /dev/null +++ b/lbrynet/lbrynet_daemon/LBRYDaemon.py @@ -0,0 +1,282 @@ +import os +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.core.client.AutoDownloader import GetStream +from lbrynet.core.utils import generate_id +from lbrynet.lbrynet_console.LBRYSettings import LBRYSettings +from lbrynet.conf import MIN_BLOB_DATA_PAYMENT_RATE +from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier +from lbrynet.core.Session import LBRYSession +from lbrynet.core.PTCWallet import PTCWallet +from lbrynet.core.LBRYcrdWallet import LBRYcrdWallet +from lbrynet.lbryfilemanager.LBRYFileManager import LBRYFileManager +from lbrynet.lbryfile.LBRYFileMetadataManager import DBLBRYFileMetadataManager, TempLBRYFileMetadataManager +from twisted.web import xmlrpc, server +from twisted.internet import defer, threads, reactor +from datetime import datetime + + +class LBRYDaemon(xmlrpc.XMLRPC): + """ + LBRYnet daemon + """ + + def setup(self): + def _set_vars(): + self.run_server = True + self.session = None + self.known_dht_nodes = [('104.236.42.182', 4000)] + self.db_dir = os.path.join(os.path.expanduser("~"), ".lbrynet") + self.blobfile_dir = os.path.join(self.db_dir, "blobfiles") + self.peer_port = 3333 + self.dht_node_port = 4444 + self.first_run = False + self.current_db_revision = 1 + if os.name == "nt": + from lbrynet.winhelpers.knownpaths import get_path, FOLDERID, UserHandle + self.download_directory = get_path(FOLDERID.Downloads, UserHandle.current) + self.wallet_dir = os.path.join(get_path(FOLDERID.RoamingAppData, UserHandle.current), "lbrycrd") + else: + self.download_directory = os.path.join(os.path.expanduser("~"), 'Downloads') + self.wallet_dir = os.path.join(os.path.expanduser("~"), ".lbrycrd") + self.wallet_conf = os.path.join(self.wallet_dir, "lbrycrd.conf") + self.wallet_user = None + self.wallet_password = None + self.sd_identifier = StreamDescriptorIdentifier() + self.stream_info_manager = TempLBRYFileMetadataManager() + self.wallet_rpc_port = 8332 + self.download_deferreds = [] + self.stream_frames = [] + self.default_blob_data_payment_rate = MIN_BLOB_DATA_PAYMENT_RATE + self.use_upnp = True + self.start_lbrycrdd = True + if os.name == "nt": + self.lbrycrdd_path = "lbrycrdd.exe" + else: + self.lbrycrdd_path = "./lbrycrdd" + self.delete_blobs_on_remove = True + self.blob_request_payment_rate_manager = None + self.lbry_file_metadata_manager = None + self.lbry_file_manager = None + self.settings = LBRYSettings(self.db_dir) + self.wallet_type = "lbrycrd" + self.lbrycrd_dir = os.path.join(os.path.expanduser("~"), ".lbrycrd") + self.lbrycrd_conf = os.path.join(self.lbrycrd_dir, "lbrycrd.conf") + self.rpc_conn = None + return defer.succeed(None) + + d = defer.Deferred() + d.addCallback(lambda _: _set_vars()) + d.addCallback(lambda _: self._get_settings()) + d.addCallback(lambda _: self.get_lbrycrdd_path()) + d.addCallback(lambda _: self._get_session()) + d.addCallback(lambda _: add_lbry_file_to_sd_identifier(self.sd_identifier)) + d.addCallback(lambda _: self._setup_stream_identifier()) + d.addCallback(lambda _: self._setup_lbry_file_manager()) + d.addCallback(lambda _: self._setup_lbry_file_opener()) + d.callback(None) + + return defer.succeed(None) + + def _get_settings(self): + d = self.settings.start() + d.addCallback(lambda _: self.settings.get_lbryid()) + d.addCallback(self.set_lbryid) + d.addCallback(lambda _: self.get_lbrycrdd_path()) + return d + + def set_lbryid(self, lbryid): + if lbryid is None: + return self._make_lbryid() + else: + self.lbryid = lbryid + + def _make_lbryid(self): + self.lbryid = generate_id() + d = self.settings.save_lbryid(self.lbryid) + return d + + def _setup_lbry_file_manager(self): + self.lbry_file_metadata_manager = DBLBRYFileMetadataManager(self.db_dir) + d = self.lbry_file_metadata_manager.setup() + + def set_lbry_file_manager(): + self.lbry_file_manager = LBRYFileManager(self.session, self.lbry_file_metadata_manager, self.sd_identifier) + return self.lbry_file_manager.setup() + + d.addCallback(lambda _: set_lbry_file_manager()) + + return d + + def _get_session(self): + def get_default_data_rate(): + d = self.settings.get_default_data_payment_rate() + d.addCallback(lambda rate: {"default_data_payment_rate": + rate if rate is not None else MIN_BLOB_DATA_PAYMENT_RATE}) + return d + + def get_wallet(): + if self.wallet_type == "lbrycrd": + lbrycrdd_path = None + if self.start_lbrycrdd is True: + lbrycrdd_path = self.lbrycrdd_path + if not lbrycrdd_path: + lbrycrdd_path = self.default_lbrycrdd_path + d = defer.succeed(LBRYcrdWallet(self.db_dir, wallet_dir=self.lbrycrd_dir, wallet_conf=self.lbrycrd_conf, + lbrycrdd_path=lbrycrdd_path)) + else: + d = defer.succeed(PTCWallet(self.db_dir)) + d.addCallback(lambda wallet: {"wallet": wallet}) + return d + + d1 = get_default_data_rate() + d2 = get_wallet() + + def combine_results(results): + r = {} + for success, result in results: + if success is True: + r.update(result) + return r + + def create_session(results): + self.session = LBRYSession(results['default_data_payment_rate'], db_dir=self.db_dir, lbryid=self.lbryid, + blob_dir=self.blobfile_dir, dht_node_port=self.dht_node_port, + known_dht_nodes=self.known_dht_nodes, peer_port=self.peer_port, + use_upnp=self.use_upnp, wallet=results['wallet']) + self.rpc_conn = self.session.wallet.get_rpc_conn_x() + + dl = defer.DeferredList([d1, d2], fireOnOneErrback=True) + + dl.addCallback(combine_results) + + dl.addCallback(create_session) + + dl.addCallback(lambda _: self.session.setup()) + + return dl + + def get_lbrycrdd_path(self): + def get_lbrycrdd_path_conf_file(): + lbrycrdd_path_conf_path = os.path.join(os.path.expanduser("~"), ".lbrycrddpath.conf") + if not os.path.exists(lbrycrdd_path_conf_path): + return "" + lbrycrdd_path_conf = open(lbrycrdd_path_conf_path) + lines = lbrycrdd_path_conf.readlines() + return lines + + d = threads.deferToThread(get_lbrycrdd_path_conf_file) + + def load_lbrycrdd_path(conf): + for line in conf: + if len(line.strip()) and line.strip()[0] != "#": + self.lbrycrdd_path = line.strip() + print self.lbrycrdd_path + + d.addCallback(load_lbrycrdd_path) + return d + + def _setup_stream_identifier(self): + file_saver_factory = LBRYFileSaverFactory(self.session.peer_finder, self.session.rate_limiter, + self.session.blob_manager, self.stream_info_manager, + self.session.wallet, self.download_directory) + self.sd_identifier.add_stream_downloader_factory(LBRYFileStreamType, file_saver_factory) + file_opener_factory = LBRYFileOpenerFactory(self.session.peer_finder, self.session.rate_limiter, + self.session.blob_manager, self.stream_info_manager, + self.session.wallet) + self.sd_identifier.add_stream_downloader_factory(LBRYFileStreamType, file_opener_factory) + return defer.succeed(None) + + def _setup_lbry_file_manager(self): + self.lbry_file_metadata_manager = DBLBRYFileMetadataManager(self.db_dir) + d = self.lbry_file_metadata_manager.setup() + + def set_lbry_file_manager(): + self.lbry_file_manager = LBRYFileManager(self.session, self.lbry_file_metadata_manager, self.sd_identifier) + return self.lbry_file_manager.setup() + + d.addCallback(lambda _: set_lbry_file_manager()) + + return d + + def _setup_lbry_file_opener(self): + + downloader_factory = LBRYFileOpenerFactory(self.session.peer_finder, self.session.rate_limiter, + self.session.blob_manager, self.stream_info_manager, + self.session.wallet) + self.sd_identifier.add_stream_downloader_factory(LBRYFileStreamType, downloader_factory) + return defer.succeed(True) + + def xmlrpc_getbalance(self): + """ + Get LBC balance + """ + return str(self.session.wallet.wallet_balance) + + def xmlrpc_stop(self): + """ + Stop the reactor + """ + + reactor.stop() + return defer.succeed('Stopping') + + def xmlrpc_resolve_name(self, name): + """ + Resolve stream info from a LBRY uri + """ + + def _disp(info): + print '[' + str(datetime.now()) + ']' + ' Resolved info: ' + str(info) + return info + + d = defer.Deferred() + d.addCallback(lambda _: self.session.wallet.get_stream_info_for_name(name)) + d.addCallback(_disp) + d.callback(None) + return d + + def xmlrpc_get_downloads(self): + """ + Get downloads + """ + + downloads = [{'stream_hash': stream.stream_hash, + 'path': os.path.join(stream.downloader.download_directory, stream.downloader.file_name)} + for stream in self.download_deferreds] + return downloads + + def xmlrpc_download_name(self, name): + """ + Download stream from a LBRY uri + """ + + def _disp(): + try: + stream = self.download_deferreds[-1] + print '[' + str(datetime.now()) + ']' + ' Downloading: ' + str(stream.stream_hash) + return defer.succeed(None) + except: + pass + + stream = GetStream(None, self.sd_identifier, self.session, self.session.wallet, + self.lbry_file_manager, 25.0, console_on=False, pay_key=True) + self.download_deferreds.append(stream) + + d = defer.Deferred() + d.addCallback(lambda _: self.session.wallet.get_stream_info_for_name(name)) + d.addCallback(lambda stream_info: stream.start(stream_info)) + d.addCallback(lambda _: _disp()) + d.callback(None) + msg = {'ts': datetime.now(),'name': name} + return defer.succeed(str(msg)) + +def main(): + daemon = LBRYDaemon() + daemon.setup() + reactor.listenTCP(7080, server.Site(daemon)) + reactor.run() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/lbrynet/lbrynet_daemon/LBRYURIHandler/LBRYURIHandler.py b/lbrynet/lbrynet_daemon/LBRYURIHandler/LBRYURIHandler.py new file mode 100644 index 000000000..2e1faa479 --- /dev/null +++ b/lbrynet/lbrynet_daemon/LBRYURIHandler/LBRYURIHandler.py @@ -0,0 +1,22 @@ +import os +import webbrowser +import xmlrpclib, sys + + +def main(args): + if len(args) == 0: + args.append('lbry://economicsman') + + daemon = xmlrpclib.ServerProxy('http://localhost:7080/') + + if len(args) > 1: + print 'Too many args', args + else: + resolved = daemon.resolve_name(str(args[0])[7:]) + daemon.download_name(str(args[0])[7:]) + path = [h for h in daemon.get_downloads() if h['stream_hash'] == resolved['stream_hash']][0]['path'] + webbrowser.open('file://' + path) + + +if __name__ == "__main__": + main(sys.argv[1:]) \ No newline at end of file diff --git a/lbrynet/lbrynet_daemon/LBRYURIHandler/dist/LBRYURIHandler.app/Contents/Info.plist b/lbrynet/lbrynet_daemon/LBRYURIHandler/dist/LBRYURIHandler.app/Contents/Info.plist new file mode 100644 index 000000000..4f5993ff1 --- /dev/null +++ b/lbrynet/lbrynet_daemon/LBRYURIHandler/dist/LBRYURIHandler.app/Contents/Info.plist @@ -0,0 +1,117 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + LBRYURIHandler + CFBundleDocumentTypes + + + CFBundleTypeOSTypes + + **** + fold + disk + + CFBundleTypeRole + Viewer + + + CFBundleExecutable + LBRYURIHandler + +CFBundleURLTypes + + + CFBundleURLName + LBRYURIHandler + CFBundleURLSchemes + + lbry + + + +NSUIElement + + + CFBundleIconFile + PythonApplet.icns + CFBundleIdentifier + org.pythonmac.unspecified.LBRYURIHandler + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + LBRYURIHandler + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.0.0 + CFBundleSignature + ???? + CFBundleVersion + 0.0.0 + LSHasLocalizedDisplayName + + NSAppleScriptEnabled + + NSHumanReadableCopyright + Copyright not specified + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + PyMainFileNames + + __boot__ + + PyOptions + + alias + + argv_emulation + + emulate_shell_environment + + no_chdir + + prefer_ppc + + site_packages + + use_faulthandler + + use_pythonpath + + verbose + + + PyResourcePackages + + + PyRuntimeLocations + + @executable_path/../Frameworks/Python.framework/Versions/2.7/Python + + PythonInfoDict + + PythonExecutable + /Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python + PythonLongVersion + 2.7.10 (v2.7.10:15c95b7d81dc, May 23 2015, 09:33:12) +[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] + PythonShortVersion + 2.7 + py2app + + alias + + template + app + version + 0.9 + + + + diff --git a/lbrynet/lbrynet_daemon/LBRYURIHandler/setup.py b/lbrynet/lbrynet_daemon/LBRYURIHandler/setup.py new file mode 100644 index 000000000..fbb83f5dc --- /dev/null +++ b/lbrynet/lbrynet_daemon/LBRYURIHandler/setup.py @@ -0,0 +1,19 @@ +""" +This is a setup.py script generated by py2applet + +Usage: + python setup.py py2app +""" + +from setuptools import setup + +APP = ['LBRYURIHandler.py'] +DATA_FILES = [] +OPTIONS = {'argv_emulation': True} + +setup( + app=APP, + data_files=DATA_FILES, + options={'py2app': OPTIONS}, + setup_requires=['py2app'], +) diff --git a/lbrynet/lbrynet_daemon/__init__.py b/lbrynet/lbrynet_daemon/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lbrynet/lbrynet_gui/LBRYGui.py b/lbrynet/lbrynet_gui/LBRYGui.py index fad1d0fb0..1926d80fe 100644 --- a/lbrynet/lbrynet_gui/LBRYGui.py +++ b/lbrynet/lbrynet_gui/LBRYGui.py @@ -57,7 +57,8 @@ class LBRYDownloader(object): if os.name == "nt": self.lbrycrdd_path = "lbrycrdd.exe" else: - self.lbrycrdd_path = "./lbrycrdd" + self.lbrycrdd_path = None + self.default_lbrycrdd_path = "./lbrycrdd" self.delete_blobs_on_remove = True self.blob_request_payment_rate_manager = None @@ -123,7 +124,7 @@ class LBRYDownloader(object): if not os.path.exists(lbrycrdd_path_conf_path): return "" lbrycrdd_path_conf = open(lbrycrdd_path_conf_path) - lines = lbrycrdd_path_conf.readline() + lines = lbrycrdd_path_conf.readlines() return lines d = threads.deferToThread(get_lbrycrdd_path_conf_file) @@ -293,6 +294,8 @@ class LBRYDownloader(object): lbrycrdd_path = None if self.start_lbrycrdd is True: lbrycrdd_path = self.lbrycrdd_path + if not lbrycrdd_path: + lbrycrdd_path = self.default_lbrycrdd_path wallet = LBRYcrdWallet(self.db_dir, wallet_dir=self.wallet_dir, wallet_conf=self.wallet_conf, lbrycrdd_path=lbrycrdd_path)