From 0200ed13416fe330e52959e95f9ed37242251350 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak <jpk@jimmykiselak.com> Date: Thu, 17 Mar 2016 20:19:13 -0400 Subject: [PATCH 01/13] refresh wallet balance every 3 seconds instead of 60 --- lbrynet/core/LBRYcrdWallet.py | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/lbrynet/core/LBRYcrdWallet.py b/lbrynet/core/LBRYcrdWallet.py index 88a9686ef..4b0002181 100644 --- a/lbrynet/core/LBRYcrdWallet.py +++ b/lbrynet/core/LBRYcrdWallet.py @@ -67,6 +67,9 @@ class LBRYWallet(object): self.stopped = True self.manage_running = False + self._manage_count = 0 + self._balance_refresh_time = 3 + self._batch_count = 60 def start(self): @@ -93,16 +96,20 @@ class LBRYWallet(object): self.next_manage_call.cancel() self.next_manage_call = None - d = self.manage() + d = self.manage(do_full=True) d.addErrback(self.log_stop_error) d.addCallback(lambda _: self._stop()) d.addErrback(self.log_stop_error) return d - def manage(self): + def manage(self, do_full=False): log.info("Doing manage") self.next_manage_call = None have_set_manage_running = [False] + self._manage_count += 1 + if self._manage_count % self._batch_count == 0: + self._manage_count = 0 + do_full = True def check_if_manage_running(): @@ -113,6 +120,8 @@ class LBRYWallet(object): self.manage_running = True have_set_manage_running[0] = True d.callback(True) + elif do_full is False: + d.callback(False) else: task.deferLater(reactor, 1, fire_if_not_running) @@ -121,20 +130,26 @@ class LBRYWallet(object): d = check_if_manage_running() - d.addCallback(lambda _: self._check_expected_balances()) + def do_manage(): + if do_full: + d = self._check_expected_balances() + d.addCallback(lambda _: self._send_payments()) + else: + d = defer.succeed(True) - d.addCallback(lambda _: self._send_payments()) + d.addCallback(lambda _: self.get_balance()) - d.addCallback(lambda _: self.get_balance()) + def set_wallet_balance(balance): + self.wallet_balance = balance - def set_wallet_balance(balance): - self.wallet_balance = balance + d.addCallback(set_wallet_balance) + return d - d.addCallback(set_wallet_balance) + d.addCallback(lambda should_run: do_manage() if should_run else None) def set_next_manage_call(): if not self.stopped: - self.next_manage_call = reactor.callLater(60, self.manage) + self.next_manage_call = reactor.callLater(self._balance_refresh_time, self.manage) d.addCallback(lambda _: set_next_manage_call()) From 4449bf3c75a5186ffe43ce02fc8abd21f128d9b5 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak <jpk@jimmykiselak.com> Date: Thu, 17 Mar 2016 21:55:06 -0400 Subject: [PATCH 02/13] change manage timer back to 60 seconds --- lbrynet/core/LBRYcrdWallet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbrynet/core/LBRYcrdWallet.py b/lbrynet/core/LBRYcrdWallet.py index 4b0002181..89fd3c98a 100644 --- a/lbrynet/core/LBRYcrdWallet.py +++ b/lbrynet/core/LBRYcrdWallet.py @@ -69,7 +69,7 @@ class LBRYWallet(object): self.manage_running = False self._manage_count = 0 self._balance_refresh_time = 3 - self._batch_count = 60 + self._batch_count = 20 def start(self): From 3cd74c06d6b8d7e325005086324928f3c80b9212 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak <jpk@jimmykiselak.com> Date: Sat, 19 Mar 2016 18:55:17 -0400 Subject: [PATCH 03/13] convert description in ControlHandlers to str so that the prompt does not get converted to unicode --- lbrynet/lbrynet_console/ControlHandlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbrynet/lbrynet_console/ControlHandlers.py b/lbrynet/lbrynet_console/ControlHandlers.py index 6cac5da64..54e072ec9 100644 --- a/lbrynet/lbrynet_console/ControlHandlers.py +++ b/lbrynet/lbrynet_console/ControlHandlers.py @@ -955,7 +955,7 @@ class AddStreamFromLBRYcrdName(AddStreamFromHash): def _get_info_to_show(self): i = AddStream._get_info_to_show(self) if self.description is not None: - i.append(("description", self.description)) + i.append(("description", str(self.description))) if self.key_fee is None or self.key_fee_address is None: i.append(("decryption key fee", "Free")) else: From a68d8917703d7fb9cc351b02dae45a3067fe0c8a Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak <jpk@jimmykiselak.com> Date: Sat, 19 Mar 2016 21:24:44 -0400 Subject: [PATCH 04/13] enable checking first run status multiple times --- lbrynet/core/LBRYcrdWallet.py | 24 +++++++++++++++++++++--- lbrynet/lbrynet_console/LBRYConsole.py | 2 +- lbrynet/lbrynet_daemon/LBRYDaemon.py | 2 +- lbrynet/lbrynet_gui/LBRYGui.py | 2 +- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lbrynet/core/LBRYcrdWallet.py b/lbrynet/core/LBRYcrdWallet.py index 89fd3c98a..be3f96b69 100644 --- a/lbrynet/core/LBRYcrdWallet.py +++ b/lbrynet/core/LBRYcrdWallet.py @@ -50,6 +50,10 @@ class LBRYWallet(object): """This class implements the LBRYWallet interface for the LBRYcrd payment system""" implements(ILBRYWallet) + _FIRST_RUN_UNKNOWN = 0 + _FIRST_RUN_YES = 1 + _FIRST_RUN_NO = 2 + def __init__(self, db_dir): self.db_dir = db_dir @@ -70,6 +74,7 @@ class LBRYWallet(object): self._manage_count = 0 self._balance_refresh_time = 3 self._batch_count = 20 + self._first_run = self._FIRST_RUN_UNKNOWN def start(self): @@ -419,6 +424,19 @@ class LBRYWallet(object): def get_available_balance(self): return float(self.wallet_balance - self.total_reserved_points) + def is_first_run(self): + if self._first_run == self._FIRST_RUN_UNKNOWN: + d = self._check_first_run() + + def set_first_run(is_first): + self._first_run = self._FIRST_RUN_YES if is_first else self._FIRST_RUN_NO + + d.addCallback(set_first_run) + else: + d = defer.succeed(None) + d.addCallback(lambda _: self._first_run == self._FIRST_RUN_YES) + return d + def _get_status_of_claim(self, txid, name, sd_hash): d = self.get_claims_from_tx(txid) @@ -534,7 +552,7 @@ class LBRYWallet(object): def get_name_claims(self): return defer.fail(NotImplementedError()) - def check_first_run(self): + def _check_first_run(self): return defer.fail(NotImplementedError()) def _get_raw_tx(self, txid): @@ -614,7 +632,7 @@ class LBRYcrdWallet(LBRYWallet): settings["rpc_port"] = int(l[8:].rstrip('\n')) return settings - def check_first_run(self): + def _check_first_run(self): d = self.get_balance() d.addCallback(lambda bal: threads.deferToThread(self._get_num_addresses_rpc) if bal == 0 else 2) d.addCallback(lambda num_addresses: True if num_addresses <= 1 else False) @@ -996,7 +1014,7 @@ class LBRYumWallet(LBRYWallet): func = getattr(self.cmd_runner, cmd.name) return threads.deferToThread(func) - def check_first_run(self): + def _check_first_run(self): return defer.succeed(self.first_run) def _get_raw_tx(self, txid): diff --git a/lbrynet/lbrynet_console/LBRYConsole.py b/lbrynet/lbrynet_console/LBRYConsole.py index d3fa39b2b..18bd6a8fc 100644 --- a/lbrynet/lbrynet_console/LBRYConsole.py +++ b/lbrynet/lbrynet_console/LBRYConsole.py @@ -253,7 +253,7 @@ class LBRYConsole(): return dl def check_first_run(self): - d = self.session.wallet.check_first_run() + d = self.session.wallet.is_first_run() d.addCallback(lambda is_first_run: self._do_first_run() if is_first_run else 0.0) return d diff --git a/lbrynet/lbrynet_daemon/LBRYDaemon.py b/lbrynet/lbrynet_daemon/LBRYDaemon.py index 410da8a81..85c441826 100644 --- a/lbrynet/lbrynet_daemon/LBRYDaemon.py +++ b/lbrynet/lbrynet_daemon/LBRYDaemon.py @@ -460,7 +460,7 @@ class LBRYDaemon(xmlrpc.XMLRPC): return dl def _check_first_run(self): - d = self.session.wallet.check_first_run() + d = self.session.wallet.is_first_run() d.addCallback(lambda is_first_run: self._do_first_run() if is_first_run else 0.0) return d diff --git a/lbrynet/lbrynet_gui/LBRYGui.py b/lbrynet/lbrynet_gui/LBRYGui.py index dcc20f649..3c83308a8 100644 --- a/lbrynet/lbrynet_gui/LBRYGui.py +++ b/lbrynet/lbrynet_gui/LBRYGui.py @@ -362,7 +362,7 @@ class LBRYDownloader(object): self.sd_identifier.add_stream_downloader_factory(LBRYFileStreamType, file_opener_factory) def check_first_run(self): - d = self.session.wallet.check_first_run() + d = self.session.wallet.is_first_run() d.addCallback(lambda is_first_run: self._do_first_run() if is_first_run else 0.0) return d From d36036a9fea7c02ddebb931d28207bf02518739a Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak <jpk@jimmykiselak.com> Date: Sat, 19 Mar 2016 21:50:38 -0400 Subject: [PATCH 05/13] Tell user to be patient if it's the first run and user has no funds --- lbrynet/lbrynet_console/ControlHandlers.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lbrynet/lbrynet_console/ControlHandlers.py b/lbrynet/lbrynet_console/ControlHandlers.py index 78e53b0dd..dd01f41b2 100644 --- a/lbrynet/lbrynet_console/ControlHandlers.py +++ b/lbrynet/lbrynet_console/ControlHandlers.py @@ -783,6 +783,9 @@ class AddStream(CommandHandler): d.addCallback(get_time_behind_blockchain) d.addCallback(self._show_time_behind_blockchain_download) d.addErrback(self._log_recent_blockchain_time_error_download) + d.addCallback(lambda _: self.wallet.is_first_run()) + d.addCallback(self._show_first_run_insufficient_funds) + d.addErrback(self._log_first_run_check_error) else: log.error("An unexpected error has caused the download to stop: %s" % err.getTraceback()) log_file = get_log_file() @@ -803,6 +806,16 @@ class AddStream(CommandHandler): def _log_recent_blockchain_time_error_download(self, err): log.error("An error occurred trying to look up the most recent blocktime: %s", err.getTraceback()) + def _show_first_run_insufficient_funds(self, is_first_run): + if is_first_run: + self.console.sendLine("\nThis appears to be the first time you have run LBRY. It can take\n" + "a few minutes for your testing LBC to show up. If you haven't\n" + "received them after a few minutes, please let us know.\n\n" + "Thank you for your patience.\n\n") + + def _log_first_run_check_error(self, err): + log.error("An error occurred checking if this was the first run: %s", err.getTraceback()) + class AddStreamFromSD(AddStream): #prompt_description = "Add a stream from a stream descriptor file" From a0b75d7ada0ae756425a8fa0ccad9ae8422bd921 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak <jpk@jimmykiselak.com> Date: Sat, 19 Mar 2016 22:30:55 -0400 Subject: [PATCH 06/13] Tell user to be patient if it's the first run and user has no funds, in two more places --- lbrynet/lbrynet_console/ControlHandlers.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lbrynet/lbrynet_console/ControlHandlers.py b/lbrynet/lbrynet_console/ControlHandlers.py index dd01f41b2..cbe5dd270 100644 --- a/lbrynet/lbrynet_console/ControlHandlers.py +++ b/lbrynet/lbrynet_console/ControlHandlers.py @@ -862,6 +862,9 @@ class AddStreamFromHash(AddStream): d.addCallback(get_time_behind_blockchain) d.addCallback(self._show_time_behind_blockchain_download) d.addErrback(self._log_recent_blockchain_time_error_download) + d.addCallback(lambda _: self.wallet.is_first_run()) + d.addCallback(self._show_first_run_insufficient_funds) + d.addErrback(self._log_first_run_check_error) d.addCallback(lambda _: self.console.sendLine("\n")) d.chainDeferred(self.finished_deferred) return @@ -1870,6 +1873,16 @@ class Publish(CommandHandler): def _log_best_blocktime_error(self, err): log.error("An error occurred checking the best time of the blockchain: %s", err.getTraceback()) + def _show_first_run_insufficient_funds(self, is_first_run): + if is_first_run: + self.console.sendLine("\nThis appears to be the first time you have run LBRY. It can take\n" + "a few minutes for your testing LBC to show up. If you haven't\n" + "received them after a few minutes, please let us know.\n\n" + "Thank you for your patience.\n\n") + + def _log_first_run_check_error(self, err): + log.error("An error occurred checking if this was the first run: %s", err.getTraceback()) + def _show_publish_error(self, err): message = "An error occurred publishing %s to %s. Error: %s." if err.check(InsufficientFundsError): @@ -1877,6 +1890,9 @@ class Publish(CommandHandler): d.addCallback(get_time_behind_blockchain) d.addCallback(self._show_time_behind_blockchain) d.addErrback(self._log_best_blocktime_error) + d.addCallback(lambda _: self.wallet.is_first_run()) + d.addCallback(self._show_first_run_insufficient_funds) + d.addErrback(self._log_first_run_check_error) error_message = "Insufficient funds" else: d = defer.succeed(True) From 246647641a43b1811672257a94eca2b1c74b7b43 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak <jpk@jimmykiselak.com> Date: Sat, 19 Mar 2016 22:39:47 -0400 Subject: [PATCH 07/13] remove some log statements that are useless, instead log whenever balance changes --- lbrynet/core/LBRYcrdWallet.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lbrynet/core/LBRYcrdWallet.py b/lbrynet/core/LBRYcrdWallet.py index be3f96b69..3c0c5f03f 100644 --- a/lbrynet/core/LBRYcrdWallet.py +++ b/lbrynet/core/LBRYcrdWallet.py @@ -108,7 +108,6 @@ class LBRYWallet(object): return d def manage(self, do_full=False): - log.info("Doing manage") self.next_manage_call = None have_set_manage_running = [False] self._manage_count += 1 @@ -145,6 +144,8 @@ class LBRYWallet(object): d.addCallback(lambda _: self.get_balance()) def set_wallet_balance(balance): + if self.wallet_balance != balance: + log.info("Got a new balance: %s", str(balance)) self.wallet_balance = balance d.addCallback(set_wallet_balance) @@ -272,8 +273,6 @@ class LBRYWallet(object): return d def _send_payments(self): - log.info("Trying to send payments, if there are any to be sent") - payments_to_send = {} for address, points in self.queued_payments.items(): log.info("Should be sending %s points to %s", str(points), str(address)) From df5b889f7d26ecfaf0db1b5bdb8d07470c647746 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak <jpk@jimmykiselak.com> Date: Mon, 21 Mar 2016 21:33:55 -0400 Subject: [PATCH 08/13] add a version to lbrynet --- lbrynet/__init__.py | 1 + setup.py | 32 +++++++++++++++++--------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/lbrynet/__init__.py b/lbrynet/__init__.py index c53c52efe..38cda8bd9 100644 --- a/lbrynet/__init__.py +++ b/lbrynet/__init__.py @@ -1,4 +1,5 @@ import logging +from version import __version__ logging.getLogger(__name__).addHandler(logging.NullHandler()) \ No newline at end of file diff --git a/setup.py b/setup.py index 68d476243..8dde41775 100644 --- a/setup.py +++ b/setup.py @@ -4,6 +4,13 @@ import ez_setup ez_setup.use_setuptools() from setuptools import setup, find_packages import sys +import os + +base_dir = os.path.abspath(os.path.dirname(__file__)) + + +from lbrynet import __version__ + console_scripts = ['lbrynet-console = lbrynet.lbrynet_console.LBRYConsole:launch_lbry_console', 'lbrynet-stdin-uploader = lbrynet.lbrynet_console.LBRYStdinUploader:launch_stdin_uploader', @@ -18,33 +25,28 @@ console_scripts = ['lbrynet-console = lbrynet.lbrynet_console.LBRYConsole:launch 'lbrynet-daemon = lbrynet.lbrynet_daemon.LBRYDaemon:main', 'stop-lbrynet-daemon = lbrynet.lbrynet_daemon.LBRYDaemon:stop'] + if sys.platform == 'darwin': console_scripts.append('lbrynet-daemon-status = lbrynet.lbrynet_daemon.LBRYOSXStatusBar:main') +gui_data_files = ['close2.gif', 'lbry-dark-242x80.gif', 'lbry-dark-icon.xbm', 'lbry-dark-icon.ico', + 'drop_down.gif', 'show_options.gif', 'hide_options.gif', 'lbry.conf'] +gui_data_paths = [os.path.join(base_dir, 'lbrynet', 'lbrynet_gui', f) for f in gui_data_files] + setup(name='lbrynet', - version='0.0.4', - packages=find_packages(), + version='.'.join([str(x) for x in __version__]), + packages=find_packages(base_dir), install_requires=['six>=1.9.0', 'pycrypto', 'twisted', 'miniupnpc', 'yapsy', 'seccure', 'python-bitcoinrpc==0.1', 'txJSON-RPC', 'requests>=2.4.2', 'unqlite==0.2.0', 'leveldb', 'lbryum'], entry_points={'console_scripts': console_scripts}, data_files=[ ('lbrynet/lbrynet_console/plugins', [ - 'lbrynet/lbrynet_console/plugins/blindrepeater.yapsy-plugin', + os.path.join(base_dir, 'lbrynet', 'lbrynet_console', 'plugins', + 'blindrepeater.yapsy-plugin') ] ), - ('lbrynet/lbrynet_gui', - [ - 'lbrynet/lbrynet_gui/close2.gif', - 'lbrynet/lbrynet_gui/lbry-dark-242x80.gif', - 'lbrynet/lbrynet_gui/lbry-dark-icon.xbm', - 'lbrynet/lbrynet_gui/lbry-dark-icon.ico', - 'lbrynet/lbrynet_gui/drop_down.gif', - 'lbrynet/lbrynet_gui/show_options.gif', - 'lbrynet/lbrynet_gui/hide_options.gif', - 'lbrynet/lbrynet_gui/lbry.conf', - ] - ) + ('lbrynet/lbrynet_gui', gui_data_paths) ], dependency_links=['https://github.com/lbryio/lbryum/tarball/master/#egg=lbryum'], ) \ No newline at end of file From e4a30c052eba060b01e0ade14dfdbfeabfeffede Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak <jpk@jimmykiselak.com> Date: Mon, 21 Mar 2016 21:37:15 -0400 Subject: [PATCH 09/13] put the actual version in __init__.py --- lbrynet/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lbrynet/__init__.py b/lbrynet/__init__.py index 38cda8bd9..f780625b8 100644 --- a/lbrynet/__init__.py +++ b/lbrynet/__init__.py @@ -1,5 +1,7 @@ import logging -from version import __version__ -logging.getLogger(__name__).addHandler(logging.NullHandler()) \ No newline at end of file +logging.getLogger(__name__).addHandler(logging.NullHandler()) + + +__version__ = (0, 2, 0) \ No newline at end of file From 141162e5aee02da87d7b2e25dbf8c8e51830c9a6 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg <alex@grin.io> Date: Tue, 22 Mar 2016 22:15:07 -0400 Subject: [PATCH 10/13] fixes so we can build an sdist --- MANIFEST.in | 2 ++ setup.py | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 000000000..97304ecca --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include lbrynet/lbrynet_console/plugins/blindrepeater.yapsy-plugin +recursive-include lbrynet/lbrynet_gui *.gif *.ico *.xbm *.conf diff --git a/setup.py b/setup.py index 8dde41775..ed9b2a866 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,5 @@ #!/usr/bin/env python -import ez_setup -ez_setup.use_setuptools() from setuptools import setup, find_packages import sys import os @@ -49,4 +47,4 @@ setup(name='lbrynet', ('lbrynet/lbrynet_gui', gui_data_paths) ], dependency_links=['https://github.com/lbryio/lbryum/tarball/master/#egg=lbryum'], - ) \ No newline at end of file + ) From e85683e40f0ab46fc2afe47ab7e5d4c109acc81a Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak <jpk@jimmykiselak.com> Date: Tue, 22 Mar 2016 22:42:45 -0400 Subject: [PATCH 11/13] show more informative messages when blockchain is catching up --- lbrynet/core/LBRYcrdWallet.py | 38 ++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/lbrynet/core/LBRYcrdWallet.py b/lbrynet/core/LBRYcrdWallet.py index 3c0c5f03f..9015da57f 100644 --- a/lbrynet/core/LBRYcrdWallet.py +++ b/lbrynet/core/LBRYcrdWallet.py @@ -893,6 +893,9 @@ class LBRYumWallet(LBRYWallet): self.cmd_runner = None self.first_run = False self.printed_retrieving_headers = False + self._start_check = None + self._catch_up_check = None + self._caught_up_counter = 0 def _start(self): @@ -912,21 +915,30 @@ class LBRYumWallet(LBRYWallet): alert.info("Running the wallet for the first time...this may take a moment.") self.printed_retrieving_headers = True return False - start_check.stop() + self._start_check.stop() + self._start_check = None if self.network.is_connected(): network_start_d.callback(True) else: network_start_d.errback(ValueError("Failed to connect to network.")) - start_check = task.LoopingCall(check_started) + self._start_check = task.LoopingCall(check_started) - d.addCallback(lambda _: start_check.start(.1)) + d.addCallback(lambda _: self._start_check.start(.1)) d.addCallback(lambda _: network_start_d) d.addCallback(lambda _: self._load_wallet()) d.addCallback(lambda _: self._get_cmd_runner()) return d def _stop(self): + if self._start_check is not None: + self._start_check.stop() + self._start_check = None + + if self._catch_up_check is not None: + self._catch_up_check.stop() + self._catch_up_check = None + d = defer.Deferred() def check_stopped(): @@ -964,16 +976,28 @@ class LBRYumWallet(LBRYWallet): remote_height = self.network.get_server_height() if remote_height != 0 and remote_height - local_height <= 5: - alert.info('Wallet loaded.') - catch_up_check.stop() + msg = "" + if self._caught_up_counter != 0: + msg += "All caught up. " + msg += "Wallet loaded." + alert.info(msg) + self._catch_up_check.stop() + self._catch_up_check = None blockchain_caught_d.callback(True) + elif remote_height != 0: + if self._caught_up_counter == 0: + alert.info('Catching up to the blockchain...showing blocks left...') + if self._caught_up_counter % 30 == 0: + alert.info('%d...', (remote_height - local_height)) + self._caught_up_counter += 1 - catch_up_check = task.LoopingCall(check_caught_up) + + self._catch_up_check = task.LoopingCall(check_caught_up) d = threads.deferToThread(get_wallet) d.addCallback(self._save_wallet) d.addCallback(lambda _: self.wallet.start_threads(self.network)) - d.addCallback(lambda _: catch_up_check.start(.1)) + d.addCallback(lambda _: self._catch_up_check.start(.1)) d.addCallback(lambda _: blockchain_caught_d) return d From 1ccd2a3cc9107d1cd17df66dc31019f3610ed5fd Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak <jpk@jimmykiselak.com> Date: Wed, 23 Mar 2016 22:02:02 -0400 Subject: [PATCH 12/13] do version better --- lbrynet/__init__.py | 3 ++- setup.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lbrynet/__init__.py b/lbrynet/__init__.py index f780625b8..eb4d8454c 100644 --- a/lbrynet/__init__.py +++ b/lbrynet/__init__.py @@ -4,4 +4,5 @@ import logging logging.getLogger(__name__).addHandler(logging.NullHandler()) -__version__ = (0, 2, 0) \ No newline at end of file +version = (0, 2, 0) +__version__ = ".".join([str(x) for x in version]) diff --git a/setup.py b/setup.py index ed9b2a866..4b8047d00 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ gui_data_files = ['close2.gif', 'lbry-dark-242x80.gif', 'lbry-dark-icon.xbm', 'l gui_data_paths = [os.path.join(base_dir, 'lbrynet', 'lbrynet_gui', f) for f in gui_data_files] setup(name='lbrynet', - version='.'.join([str(x) for x in __version__]), + version=__version__, packages=find_packages(base_dir), install_requires=['six>=1.9.0', 'pycrypto', 'twisted', 'miniupnpc', 'yapsy', 'seccure', 'python-bitcoinrpc==0.1', 'txJSON-RPC', 'requests>=2.4.2', 'unqlite==0.2.0', 'leveldb', 'lbryum'], entry_points={'console_scripts': console_scripts}, From c714a3f91c58680147e664622c0f89e1039c2aad Mon Sep 17 00:00:00 2001 From: Jack <jack@robisonservice.com> Date: Wed, 23 Mar 2016 22:27:48 -0400 Subject: [PATCH 13/13] merge updates --- lbrynet/core/LBRYcrdWallet.py | 18 +- lbrynet/lbrynet_console/LBRYConsole.py | 55 +- lbrynet/lbrynet_daemon/LBRYDaemon.py | 855 ++++++++++++------------- setup.py | 34 +- 4 files changed, 490 insertions(+), 472 deletions(-) diff --git a/lbrynet/core/LBRYcrdWallet.py b/lbrynet/core/LBRYcrdWallet.py index 3c0c5f03f..5ead82cb2 100644 --- a/lbrynet/core/LBRYcrdWallet.py +++ b/lbrynet/core/LBRYcrdWallet.py @@ -316,8 +316,8 @@ class LBRYWallet(object): except (ValueError, TypeError): return Failure(InvalidStreamInfoError(name)) known_fields = ['stream_hash', 'name', 'description', 'key_fee', 'key_fee_address', 'thumbnail', - 'content_license', 'sources', 'fee'] - known_sources = ['lbry_sd_hash'] + 'content_license', 'sources', 'fee', 'author'] + known_sources = ['lbry_sd_hash', 'btih', 'url'] known_fee_types = {'LBC': ['amount', 'address']} for field in known_fields: if field in value_dict: @@ -353,7 +353,7 @@ class LBRYWallet(object): return Failure(UnknownNameError(name)) def claim_name(self, name, sd_hash, amount, description=None, key_fee=None, - key_fee_address=None, thumbnail=None, content_license=None): + key_fee_address=None, thumbnail=None, content_license=None, author=None, sources=None): value = {"sources": {'lbry_sd_hash': sd_hash}} if description is not None: value['description'] = description @@ -363,6 +363,10 @@ class LBRYWallet(object): value['thumbnail'] = thumbnail if content_license is not None: value['content_license'] = content_license + if author is not None: + value['author'] = author + if sources is not None: + value['sources'] = sources d = self._send_name_claim(name, json.dumps(value), amount) @@ -930,13 +934,15 @@ class LBRYumWallet(LBRYWallet): d = defer.Deferred() def check_stopped(): - if self.network.is_connected(): - return False + if self.network: + if self.network.is_connected(): + return False stop_check.stop() self.network = None d.callback(True) - self.network.stop() + if self.network: + self.network.stop() stop_check = task.LoopingCall(check_stopped) stop_check.start(.1) diff --git a/lbrynet/lbrynet_console/LBRYConsole.py b/lbrynet/lbrynet_console/LBRYConsole.py index 18bd6a8fc..6cde77c3f 100644 --- a/lbrynet/lbrynet_console/LBRYConsole.py +++ b/lbrynet/lbrynet_console/LBRYConsole.py @@ -1,16 +1,21 @@ import logging -from lbrynet.core.Session import LBRYSession import os.path import argparse import requests import locale import sys + +if sys.platform == "darwin": + from appdirs import user_data_dir from yapsy.PluginManager import PluginManager from twisted.internet import defer, threads, stdio, task, error +from jsonrpc.proxy import JSONRPCProxy + +from lbrynet.core.Session import LBRYSession from lbrynet.lbrynet_console.ConsoleControl import ConsoleControl from lbrynet.lbrynet_console.LBRYSettings import LBRYSettings from lbrynet.lbryfilemanager.LBRYFileManager import LBRYFileManager -from lbrynet.conf import MIN_BLOB_DATA_PAYMENT_RATE # , MIN_BLOB_INFO_PAYMENT_RATE +from lbrynet.conf import MIN_BLOB_DATA_PAYMENT_RATE, API_CONNECTION_STRING # , MIN_BLOB_INFO_PAYMENT_RATE from lbrynet.core.utils import generate_id from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier from lbrynet.core.PaymentRateManager import PaymentRateManager @@ -461,7 +466,6 @@ class LBRYConsole(): def launch_lbry_console(): - from twisted.internet import reactor parser = argparse.ArgumentParser(description="Launch a lbrynet console") @@ -529,7 +533,7 @@ def launch_lbry_console(): created_data_dir = False if not args.data_dir: if sys.platform == "darwin": - data_dir = os.path.join(os.path.expanduser("~"), "Library/Application Support/lbrynet") + data_dir = user_data_dir("LBRY") else: data_dir = os.path.join(os.path.expanduser("~"), ".lbrynet") else: @@ -538,28 +542,35 @@ def launch_lbry_console(): os.mkdir(data_dir) created_data_dir = True + daemon = JSONRPCProxy.from_url(API_CONNECTION_STRING) + try: + daemon.is_running() + log.info("Attempt to start lbrynet-console while lbrynet-daemon is running") + print "lbrynet-daemon is running, you must turn it off before using lbrynet-console" + print "If you're running the app, quit before starting lbrynet-console" + print "If you're running lbrynet-daemon in a terminal, run 'stop-lbrynet-daemon' to turn it off" - log_format = "(%(asctime)s)[%(filename)s:%(lineno)s] %(funcName)s(): %(message)s" - formatter = logging.Formatter(log_format) + except: + log_format = "(%(asctime)s)[%(filename)s:%(lineno)s] %(funcName)s(): %(message)s" + formatter = logging.Formatter(log_format) - logger = logging.getLogger() - logger.setLevel(logging.DEBUG) - file_handler = logging.FileHandler(os.path.join(data_dir, "console.log")) - file_handler.setFormatter(formatter) - file_handler.addFilter(logging.Filter("lbrynet")) - logger.addHandler(file_handler) + logger = logging.getLogger() + logger.setLevel(logging.DEBUG) + file_handler = logging.FileHandler(os.path.join(data_dir, "console.log")) + file_handler.setFormatter(formatter) + file_handler.addFilter(logging.Filter("lbrynet")) + logger.addHandler(file_handler) - console = LBRYConsole(peer_port, dht_node_port, bootstrap_nodes, fake_wallet=args.fake_wallet, - lbrycrd_conf=args.lbrycrd_wallet_conf, lbrycrd_dir=args.lbrycrd_wallet_dir, - use_upnp=not args.disable_upnp, data_dir=data_dir, - created_data_dir=created_data_dir, lbrycrdd_path=args.lbrycrdd_path) - d = task.deferLater(reactor, 0, console.start) + console = LBRYConsole(peer_port, dht_node_port, bootstrap_nodes, fake_wallet=args.fake_wallet, + lbrycrd_conf=args.lbrycrd_wallet_conf, lbrycrd_dir=args.lbrycrd_wallet_dir, + use_upnp=not args.disable_upnp, data_dir=data_dir, + created_data_dir=created_data_dir, lbrycrdd_path=args.lbrycrdd_path) - d.addErrback(lambda _: reactor.stop()) - - reactor.addSystemEventTrigger('before', 'shutdown', console.shut_down) - reactor.run() + d = task.deferLater(reactor, 0, console.start) + d.addErrback(lambda _: reactor.stop()) + reactor.addSystemEventTrigger('before', 'shutdown', console.shut_down) + reactor.run() if __name__ == "__main__": - launch_lbry_console() \ No newline at end of file + launch_lbry_console() diff --git a/lbrynet/lbrynet_daemon/LBRYDaemon.py b/lbrynet/lbrynet_daemon/LBRYDaemon.py index 85c441826..d3b616b75 100644 --- a/lbrynet/lbrynet_daemon/LBRYDaemon.py +++ b/lbrynet/lbrynet_daemon/LBRYDaemon.py @@ -1,23 +1,26 @@ import locale import os import sys -import json +import simplejson as json import binascii -import webbrowser -import xmlrpclib import subprocess import logging -import argparse -import pwd import requests +# import rumps +# import httplib2 + +from twisted.web import server, resource, static +from twisted.internet import defer, threads, error, reactor +from txjsonrpc import jsonrpclib +from txjsonrpc.web import jsonrpc +from jsonrpc.proxy import JSONRPCProxy -from twisted.web import xmlrpc, server -from twisted.internet import defer, threads, reactor, error from datetime import datetime from decimal import Decimal from StringIO import StringIO from zipfile import ZipFile from urllib import urlopen +from appdirs import user_data_dir from lbrynet.core.PaymentRateManager import PaymentRateManager from lbrynet.core.server.BlobAvailabilityHandler import BlobAvailabilityHandlerFactory @@ -33,6 +36,7 @@ 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 +from lbrynet.conf import API_CONNECTION_STRING, API_PORT, API_ADDRESS, DEFAULT_TIMEOUT from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier, download_sd_blob from lbrynet.core.Session import LBRYSession from lbrynet.core.PTCWallet import PTCWallet @@ -41,28 +45,62 @@ from lbrynet.lbryfilemanager.LBRYFileManager import LBRYFileManager from lbrynet.lbryfile.LBRYFileMetadataManager import DBLBRYFileMetadataManager, TempLBRYFileMetadataManager log = logging.getLogger(__name__) -# logging.basicConfig(level=logging.DEBUG) +BAD_REQUEST = 400 +NOT_FOUND = 404 +OK_CODE = 200 # TODO add login credentials in a conf file -# functions to add: -# TODO send credits to address # TODO alert if your copy of a lbry file is out of date with the name record -BAD_REQUEST = (400, "Bad request") -NOT_FOUND = (404, "Not found") - -OK_CODE = 200 +class Bunch: + def __init__(self, params): + self.__dict__.update(params) -class LBRYDaemon(xmlrpc.XMLRPC): +class LBRYDaemon(jsonrpc.JSONRPC): """ - LBRYnet daemon + LBRYnet daemon, a jsonrpc interface to lbry functions """ + isLeaf = True + + def render(self, request): + request.content.seek(0, 0) + # Unmarshal the JSON-RPC data. + content = request.content.read() + parsed = jsonrpclib.loads(content) + functionPath = parsed.get("method") + args = parsed.get('params') + id = parsed.get('id') + version = parsed.get('jsonrpc') + if version: + version = int(float(version)) + elif id and not version: + version = jsonrpclib.VERSION_1 + else: + version = jsonrpclib.VERSION_PRE1 + # XXX this all needs to be re-worked to support logic for multiple + # versions... + try: + function = self._getFunction(functionPath) + except jsonrpclib.Fault, f: + self._cbRender(f, request, id, version) + else: + request.setHeader('Access-Control-Allow-Origin', ('http://localhost' + ':' + str(API_PORT))) + request.setHeader("content-type", "text/json") + if args == [{}]: + d = defer.maybeDeferred(function) + else: + d = defer.maybeDeferred(function, *args) + d.addErrback(self._ebRender, id) + d.addCallback(self._cbRender, request, id, version) + return server.NOT_DONE_YET def setup(self, wallet_type, check_for_updates): def _set_vars(wallet_type, check_for_updates): + reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown) + self.fetcher = None self.current_db_revision = 1 self.run_server = True @@ -71,7 +109,8 @@ class LBRYDaemon(xmlrpc.XMLRPC): if sys.platform != "darwin": self.db_dir = os.path.join(os.path.expanduser("~"), ".lbrynet") else: - self.db_dir = os.path.join(os.path.expanduser("~"), "Library/Application Support/lbrynet") + self.db_dir = user_data_dir("LBRY") + # self.db_dir = os.path.join(os.path.expanduser("~"), "Library/Application Support/lbrynet") self.blobfile_dir = os.path.join(self.db_dir, "blobfiles") self.peer_port = 3333 self.dht_node_port = 4444 @@ -82,11 +121,12 @@ class LBRYDaemon(xmlrpc.XMLRPC): self.wallet_dir = os.path.join(get_path(FOLDERID.RoamingAppData, UserHandle.current), "lbrycrd") elif sys.platform == "darwin": self.download_directory = os.path.join(os.path.expanduser("~"), 'Downloads') - self.wallet_dir = os.path.join(os.path.expanduser("~"), "Library/Application Support/lbrycrd") + # self.wallet_dir = os.path.join(os.path.expanduser("~"), "Library/Application Support/lbrycrd") + self.wallet_dir = user_data_dir("LBRY") else: self.wallet_dir = os.path.join(os.path.expanduser("~"), ".lbrycrd") self.download_directory = os.path.join(os.path.expanduser("~"), 'Downloads') - + self.daemon_conf = os.path.join(self.wallet_dir, 'daemon_settings.conf') self.wallet_conf = os.path.join(self.wallet_dir, "lbrycrd.conf") self.wallet_user = None self.wallet_password = None @@ -119,28 +159,31 @@ class LBRYDaemon(xmlrpc.XMLRPC): self.data_rate = MIN_BLOB_DATA_PAYMENT_RATE self.max_key_fee = DEFAULT_MAX_KEY_FEE self.max_search_results = DEFAULT_MAX_SEARCH_RESULTS - self.restart_message = "" self.startup_message = "" self.announced_startup = False self.search_timeout = 3.0 self.query_handlers = {} + self.default_settings = { + 'run_on_startup': False, + 'data_rate': MIN_BLOB_DATA_PAYMENT_RATE, + 'max_key_fee': 10.0, + 'default_download_directory': self.download_directory, + 'max_upload': 0.0, + 'max_download': 0.0 + } return defer.succeed(None) def _disp_startup(): - if self.restart_message: - print self.restart_message - else: - print "Started LBRYnet daemon" - print "The daemon can be shut down by running 'stop-lbrynet-daemon' in a terminal" - log.info('[' + str(datetime.now()) + '] Started lbrynet-daemon') + log.info("[" + str(datetime.now()) + "] Started lbrynet-daemon") return defer.succeed(None) - log.info('[' + str(datetime.now()) + '] Starting lbrynet-daemon') + log.info("[" + str(datetime.now()) + "] Starting lbrynet-daemon") d = defer.Deferred() - d.addCallback(lambda _: _set_vars(wallet_type, check_for_updates)) + d.addCallback(lambda _:_set_vars(wallet_type, check_for_updates)) + d.addCallback(lambda _: self._setup_daemon_settings()) d.addCallback(lambda _: threads.deferToThread(self._setup_data_directory)) d.addCallback(lambda _: self._check_db_migration()) d.addCallback(lambda _: self._get_settings()) @@ -152,104 +195,19 @@ class LBRYDaemon(xmlrpc.XMLRPC): d.addCallback(lambda _: self._setup_lbry_file_opener()) d.addCallback(lambda _: self._setup_query_handlers()) d.addCallback(lambda _: self._setup_server()) - # d.addCallback(lambda _: self._update() if self.check_for_updates == "True" and sys.platform == "darwin" - # else defer.succeed(None)) d.addCallback(lambda _: self._setup_fetcher()) d.addCallback(lambda _: _disp_startup()) d.callback(None) return defer.succeed(None) - def _update(self): - def _check_for_updater(): - if os.path.isdir("/Applications/LBRY Updater.app"): - print "Found LBRY updater" - return defer.succeed(None) - - print "LBRY updater not found, downloading and installing..." - url = urlopen("https://rawgit.com/jackrobison/lbrynet-app/master/LBRY%20Updater.app.zip") - zipped_app = ZipFile(StringIO(url.read())) - zipped_app.extractall("/Applications") - return defer.succeed(None) - - def _update_lbrynet(): - git_version = subprocess.check_output( - "git ls-remote https://github.com/lbryio/lbry.git | grep HEAD | cut -f 1", - shell=True) - if os.path.isfile(os.path.join(self.db_dir, "lbrynet_version.txt")): - f = open(os.path.join(self.db_dir, "lbrynet_version.txt"), 'r') - current_version = f.read() - f.close() - if git_version == current_version: - print "LBRYnet installation version " + current_version[:-1] + " is up to date" - return defer.succeed(None) - print "Update LBRYnet version " + current_version[:-1] + " --> " + git_version[:-1] - self.restart_message = "Updates available" - else: - print "Update LBRYnet to version " + git_version[:-1] - self.restart_message = "Updates available" - - return defer.succeed(None) - - def _update_lbrycrdd(): - git_version = subprocess.check_output( - "git ls-remote https://github.com/jackrobison/lbrynet-app.git | grep HEAD | cut -f 1", - shell=True) - if os.path.isfile(os.path.join(self.wallet_dir, "lbry_app_version.txt")): - f = open(os.path.join(self.wallet_dir, "lbry_app_version.txt"), 'r') - current_version = f.read() - f.close() - if git_version == current_version: - print "LBRY installation version " + current_version[:-1] + " is up to date" - return defer.succeed(None) - print "Update LBRY version " + current_version[:-1] + " --> " + git_version[:-1] - self.restart_message = "Updates available" - else: - print "Update LBRY to version " + git_version[:-1] - self.restart_message = "Updates available" - - return defer.succeed(None) - - def _update_lbryum(): - git_version = subprocess.check_output( - "git ls-remote https://github.com/lbryio/lbryum.git | grep HEAD | cut -f 1", - shell=True) - if os.path.isfile(os.path.join(self.db_dir, "lbryum_version.txt")): - f = open(os.path.join(self.db_dir, "lbryum_version.txt"), 'r') - current_version = f.read() - f.close() - if git_version == current_version: - print "LBRYum installation version " + current_version[:-1] + " is up to date" - return defer.succeed(None) - print "Update LBRYum version " + current_version[:-1] + " --> " + git_version[:-1] - self.restart_message = "Updates available" - else: - print "Update LBRYum to version " + git_version[:-1] - self.restart_message = "Updates available" - - return defer.succeed(None) - - d = _check_for_updater() - d.addCallback(lambda _: _update_lbrynet()) - d.addCallback(lambda _: _update_lbrycrdd() if self.wallet_type == 'lbrycrd' else _update_lbryum()) - d.addCallback(lambda _: os.system("open /Applications/LBRY\ Updater.app &>/dev/null") if self.restart_message - else defer.succeed(None)) - d.addCallbacks(lambda _: self._restart() if self.restart_message else defer.succeed(None)) + def _initial_setup(self): + return defer.fail(NotImplementedError()) + def _setup_daemon_settings(self): + self.session_settings = self.default_settings return defer.succeed(None) - def _restart(self): - def _disp_shutdown(): - print 'Restarting lbrynet daemon' - return defer.succeed(None) - - # LBRY Updater.app will restart the daemon - d = self._shutdown() - d.addCallback(lambda _: _disp_shutdown()) - d.addCallback(lambda _: reactor.callLater(1.0, reactor.stop)) - - return d - def _start_server(self): if self.peer_port is not None: @@ -323,15 +281,34 @@ class LBRYDaemon(xmlrpc.XMLRPC): return dl def _shutdown(self): - print 'Closing lbrynet session' + log.info("Closing lbrynet session") d = self._stop_server() if self.session is not None: d.addCallback(lambda _: self.session.shut_down()) return d - def _update_settings(self): - self.data_rate = self.session_settings['data_rate'] - self.max_key_fee = self.session_settings['max_key_fee'] + def _update_settings(self, settings): + if not isinstance(settings['run_on_startup'], bool): + return defer.fail() + elif not isinstance(settings['data_rate'], float): + return defer.fail() + elif not isinstance(settings['max_key_fee'], float): + return defer.fail() + elif not isinstance(settings['default_download_directory'], unicode): + return defer.fail() + elif not isinstance(settings['max_upload'], float): + return defer.fail() + elif not isinstance(settings['max_download'], float): + return defer.fail() + + self.session_settings['run_on_startup'] = settings['run_on_startup'] + self.session_settings['data_rate'] = settings['data_rate'] + self.session_settings['max_key_fee'] = settings['max_key_fee'] + self.session_settings['default_download_directory'] = settings['default_download_directory'] + self.session_settings['max_upload'] = settings['max_upload'] + self.session_settings['max_download'] = settings['max_download'] + + return defer.succeed(True) def _setup_fetcher(self): self.fetcher = FetcherDaemon(self.session, self.lbry_file_manager, self.lbry_file_metadata_manager, @@ -339,7 +316,7 @@ class LBRYDaemon(xmlrpc.XMLRPC): return defer.succeed(None) def _setup_data_directory(self): - print "Loading databases..." + log.info("Loading databases...") if self.created_data_dir: db_revision = open(os.path.join(self.db_dir, "db_revision"), mode='w') db_revision.write(str(self.current_db_revision)) @@ -356,7 +333,7 @@ class LBRYDaemon(xmlrpc.XMLRPC): old_revision = int(open(db_revision_file).read().strip()) if old_revision < self.current_db_revision: from lbrynet.db_migrator import dbmigrator - print "Upgrading your databases..." + log.info("Upgrading your databases...") d = threads.deferToThread(dbmigrator.migrate_db, self.db_dir, old_revision, self.current_db_revision) def print_success(old_dirs): @@ -367,7 +344,7 @@ class LBRYDaemon(xmlrpc.XMLRPC): success_string += old_dir if i + 1 < len(old_dir): success_string += ", " - print success_string + log.info(success_string) d.addCallback(print_success) return d @@ -396,7 +373,10 @@ class LBRYDaemon(xmlrpc.XMLRPC): 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) + self.lbry_file_manager = LBRYFileManager(self.session, + self.lbry_file_metadata_manager, + self.sd_identifier, + delete_data=True) return self.lbry_file_manager.setup() d.addCallback(lambda _: set_lbry_file_manager()) @@ -407,12 +387,11 @@ class LBRYDaemon(xmlrpc.XMLRPC): 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}) + MIN_BLOB_DATA_PAYMENT_RATE}) return d def get_wallet(): if self.wallet_type == "lbrycrd": - print "Using lbrycrd wallet" log.info("Using lbrycrd wallet") lbrycrdd_path = None if self.start_lbrycrdd is True: @@ -422,11 +401,9 @@ class LBRYDaemon(xmlrpc.XMLRPC): d = defer.succeed(LBRYcrdWallet(self.db_dir, wallet_dir=self.wallet_dir, wallet_conf=self.lbrycrd_conf, lbrycrdd_path=lbrycrdd_path)) elif self.wallet_type == "lbryum": - print "Using lbryum wallet" log.info("Using lbryum wallet") d = defer.succeed(LBRYumWallet(self.db_dir)) elif self.wallet_type == "ptc": - print "Using PTC wallet" log.info("Using PTC wallet") d = defer.succeed(PTCWallet(self.db_dir)) else: @@ -509,7 +486,6 @@ class LBRYDaemon(xmlrpc.XMLRPC): 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 @@ -533,20 +509,20 @@ class LBRYDaemon(xmlrpc.XMLRPC): self.sd_identifier.add_stream_downloader_factory(LBRYFileStreamType, downloader_factory) return defer.succeed(True) - def _download_name(self, name): - def _disp_file(file): - print '[' + str(datetime.now()) + ']' + ' Already downloaded: ' + str(file.stream_hash) - d = self._path_from_lbry_file(file) - return d + def _download_name(self, name, timeout=DEFAULT_TIMEOUT): + 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 defer.succeed(f) def _get_stream(name): def _disp(stream): - print '[' + str(datetime.now()) + ']' + ' Start stream: ' + stream['stream_hash'] + log.info("[" + str(datetime.now()) + "] Start stream: " + 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, - max_key_fee=self.max_key_fee, data_rate=self.data_rate) + max_key_fee=self.max_key_fee, data_rate=self.data_rate, timeout=timeout) d.addCallback(_disp) d.addCallback(lambda stream_info: stream.start(stream_info)) d.addCallback(lambda _: self._path_from_name(name)) @@ -555,12 +531,8 @@ class LBRYDaemon(xmlrpc.XMLRPC): 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: (OK_CODE, {'stream_hash': lbry_file.stream_hash, - 'path': os.path.join(self.download_directory, - lbry_file.file_name)}) - if lbry_file else NOT_FOUND) - d.addErrback(lambda _: NOT_FOUND) + d.addCallback(lambda _: self._path_from_name(name)) + d.addErrback(lambda err: defer.fail(NOT_FOUND)) return d @@ -584,27 +556,32 @@ class LBRYDaemon(xmlrpc.XMLRPC): 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] - if lbry_file: - return lbry_file[0] + for lbry_file in self.lbry_file_manager.lbry_files: + if lbry_file.stream_name == file_name: + if sys.platform == "darwin": + if os.path.isfile(os.path.join(self.download_directory, lbry_file.stream_name)): + return lbry_file + else: + return False + else: + return lbry_file else: - return None + return False 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 log.info("[" + 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" log.info("[" + 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.addCallback(_check) d.callback(None) return d @@ -615,7 +592,6 @@ class LBRYDaemon(xmlrpc.XMLRPC): def finish_deletion(lbry_file): d = lbry_file.delete_data() d.addCallback(lambda _: _delete_stream_data(lbry_file)) - d.addCallback(lambda _: _delete_file(lbry_file)) return d def _delete_stream_data(lbry_file): @@ -623,11 +599,10 @@ class LBRYDaemon(xmlrpc.XMLRPC): 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) + d.addCallback(lambda _: os.remove(os.path.join(self.download_directory, lbry_file.file_name)) if + os.path.isfile(os.path.join(self.download_directory, lbry_file.file_name)) else defer.succeed(None)) return d - def _delete_file(lbry_file): - os.remove(os.path.join(self.download_directory, lbry_file.file_name)) - d.addCallback(lambda _: finish_deletion(lbry_file)) return d @@ -635,7 +610,7 @@ class LBRYDaemon(xmlrpc.XMLRPC): 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)) + if lbry_file else defer.fail(UnknownNameError)) return d def _path_from_lbry_file(self, lbry_file): @@ -649,11 +624,9 @@ class LBRYDaemon(xmlrpc.XMLRPC): def _get_est_cost(self, name): def _check_est(d, name): if type(d.result) is float: - print '[' + str(datetime.now()) + '] Cost est for lbry://' + name + ': ' + str(d.result) + 'LBC' - log.info('[' + str(datetime.now()) + '] Cost est for lbry://' + name + ': ' + str(d.result) + 'LBC') + log.info("[" + str(datetime.now()) + "] Cost est for lbry://" + name + ": " + str(d.result) + "LBC") else: - print '[' + str(datetime.now()) + '] Timeout estimating cost for lbry://' + name + ', using key fee' - log.info('[' + str(datetime.now()) + '] Timeout estimating cost for lbry://' + name + ', using key fee') + log.info("[" + str(datetime.now()) + "] Timeout estimating cost for lbry://" + name + ", using key fee") d.cancel() return defer.succeed(None) @@ -674,94 +647,109 @@ class LBRYDaemon(xmlrpc.XMLRPC): return d - def xmlrpc_is_running(self): - if self.startup_message != "" and self.announced_startup == False: - print "Startup message:", self.startup_message - self.announced_startup = True - return self.startup_message - elif self.announced_startup: - return True - else: - return False + def _render_response(self, result, code): + return json.dumps({'result': result, 'code': code}) - def xmlrpc_get_settings(self): + # def _log_to_slack(self, msg): + # URL = "https://hooks.slack.com/services/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" + # h = httplib2.Http() + # h.request(URL, 'POST', json.dumps({"text": msg}), headers={'Content-Type': 'application/json'}) + + def jsonrpc_is_running(self): + """ + Returns a startup message when the daemon starts, after which it will return True + """ + + if self.startup_message != "" and self.announced_startup == False: + self.announced_startup = True + return self._render_response(self.startup_message, OK_CODE) + elif self.announced_startup: + return self._render_response(True, OK_CODE) + else: + return self._render_response(False, OK_CODE) + + def jsonrpc_get_settings(self): """ Get LBRY payment settings @return {'data_rate': float, 'max_key_fee': float} """ - if not self.session_settings: - self.session_settings = {'data_rate': self.data_rate, 'max_key_fee': self.max_key_fee} + log.info("[" + str(datetime.now()) + "] Get daemon settings") + return self._render_response(self.session_settings, OK_CODE) - print '[' + str(datetime.now()) + '] Get daemon settings' - return self.session_settings - - def xmlrpc_set_settings(self, settings): + def jsonrpc_set_settings(self, p): """ Set LBRY payment settings - @param settings dict: {'data_rate': float, 'max_key_fee': float} + @param settings: {'settings': {'data_rate': float, 'max_key_fee': float}} """ - self.session_settings = settings - self._update_settings() + d = self._update_settings(p) - print '[' + str(datetime.now()) + '] Set daemon settings' - return 'Set' + log.info("[" + str(datetime.now()) + "] Set daemon settings") + return self._render_response(True, OK_CODE) - def xmlrpc_start_fetcher(self): + def jsonrpc_start_fetcher(self): """ - Start autofetcher + Start automatically downloading new name claims as they happen + + @return: confirmation message """ self.fetcher.start() - print '[' + str(datetime.now()) + '] Start autofetcher' log.info('[' + str(datetime.now()) + '] Start autofetcher') - return 'Started autofetching' + # self._log_to_slack('[' + str(datetime.now()) + '] Start autofetcher') + return self._render_response("Started autofetching claims", OK_CODE) - def xmlrpc_stop_fetcher(self): + def jsonrpc_stop_fetcher(self): """ - Stop autofetcher + Stop automatically downloading new name claims as they happen + + @return: confirmation message """ self.fetcher.stop() - print '[' + str(datetime.now()) + '] Stop autofetcher' log.info('[' + str(datetime.now()) + '] Stop autofetcher') - return 'Stopped autofetching' + return self._render_response("Stopped autofetching claims", OK_CODE) - def xmlrpc_fetcher_status(self): + def jsonrpc_fetcher_status(self): """ - Start autofetcher + Get fetcher status + + @return: True/False """ - print '[' + str(datetime.now()) + '] Get fetcher status' - return str(self.fetcher.check_if_running()) + log.info("[" + str(datetime.now()) + "] Get fetcher status") + return self._render_response(self.fetcher.check_if_running(), OK_CODE) - def xmlrpc_get_balance(self): + def jsonrpc_get_balance(self): """ Get LBC balance + + @return: balance """ - print '[' + str(datetime.now()) + '] Get balance' - return str(self.session.wallet.wallet_balance) + log.info("[" + str(datetime.now()) + "] Get balance") + return self._render_response(self.session.wallet.wallet_balance, OK_CODE) - def xmlrpc_stop(self): + def jsonrpc_stop(self): """ Stop lbrynet-daemon + + @return: shutdown message """ def _disp_shutdown(): - log.info('Shutting down lbrynet daemon') - print 'Shutting down lbrynet daemon' + log.info("Shutting down lbrynet daemon") d = self._shutdown() d.addCallback(lambda _: _disp_shutdown()) d.addCallback(lambda _: reactor.callLater(1.0, reactor.stop)) - return defer.succeed('Shutting down') + return self._render_response("Shutting down", OK_CODE) - def xmlrpc_get_lbry_files(self): + def jsonrpc_get_lbry_files(self): """ Get LBRY files @@ -783,124 +771,89 @@ class LBRYDaemon(xmlrpc.XMLRPC): r.append(json.dumps(t)) - print '[' + str(datetime.now()) + '] Get LBRY files' - return r + log.info("[" + str(datetime.now()) + "] Get LBRY files") + return self._render_response(r, OK_CODE) - def xmlrpc_resolve_name(self, name): + def jsonrpc_resolve_name(self, p): """ Resolve stream info from a LBRY uri - @param: name + @param: {'name': name to look up} @return: info for name claim """ + params = Bunch(p) def _disp(info): - print '[' + str(datetime.now()) + ']' + ' Resolved info: ' + str(info['stream_hash']) - return info + log.info("[" + str(datetime.now()) + "] Resolved info: " + info['stream_hash']) + return self._render_response(info, OK_CODE) - d = self._resolve_name(name) - d.addCallbacks(_disp, lambda _: str('UnknownNameError')) + d = self._resolve_name(params.name) + d.addCallbacks(_disp, lambda _: self._render_response('error', NOT_FOUND)) d.callback(None) return d - def xmlrpc_get(self, name): + def jsonrpc_get(self, p): """ Download stream from a LBRY uri @param: name @return: {'stream_hash': hex string, 'path': path of download} """ + params = Bunch(p) - if name: - d = self._download_name(name) + if 'timeout' not in p.keys(): + params.timeout = DEFAULT_TIMEOUT + + if params.name: + d = self._download_name(params.name, timeout=params.timeout) + d.addCallbacks(lambda message: self._render_response(message, OK_CODE), + lambda err: self._render_response('error', NOT_FOUND)) else: - d = defer.succeed(BAD_REQUEST) + d = self._render_response('error', BAD_REQUEST) + return d - def xmlrpc_stop_lbry_file(self, stream_hash): + def jsonrpc_stop_lbry_file(self, p): + params = Bunch(p) + try: - lbry_file = [f for f in self.lbry_file_manager.lbry_files if f.stream_hash == stream_hash][0] + lbry_file = [f for f in self.lbry_file_manager.lbry_files if f.stream_hash == params.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)) + d.addCallback(lambda _: self._render_response("Stream has been stopped", OK_CODE)) + d.addErrback(lambda err: self._render_response(err.getTraceback(), )) return d else: - return defer.succeed('Stream was already stopped') + return json.dumps({'result': 'Stream was already stopped'}) + + def jsonrpc_start_lbry_file(self, p): + params = Bunch(p) - 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] + lbry_file = [f for f in self.lbry_file_manager.lbry_files if f.stream_hash == params.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') + return json.dumps({'result': 'Stream started'}) else: - return defer.succeed('Stream was already running') + return json.dumps({'result': 'Stream was already running'}) - def xmlrpc_render_html(self, html): - """ - Writes html to lbry.html in the downloads directory, then opens it with the browser - - @param html: - """ - - def _make_file(html, path): - f = open(path, 'w') - f.write(html) - f.close() - return defer.succeed(None) - - def _disp_err(err): - print str(err.getTraceback()) - return err - - path = os.path.join(self.download_directory, 'lbry.html') - - d = defer.Deferred() - d.addCallback(lambda _: _make_file(html, path)) - d.addCallback(lambda _: os.chown(path, pwd.getpwuid(os.getuid()).pw_uid, pwd.getpwuid(os.getuid()).pw_gid)) - d.addCallback(lambda _: webbrowser.open('file://' + path)) - d.addErrback(_disp_err) - d.callback(None) - - return d - - def xmlrpc_render_gui(self): - """ - Opens the lbry web ui in a browser - """ - - def _disp_err(err): - print str(err.getTraceback()) - return err - - d = defer.Deferred() - if sys.platform == 'darwin': - d.addCallback(lambda _: webbrowser.get('safari').open( - "file://" + str(os.path.join(self.download_directory, "lbryio/view/page/gui.html")))) - else: - d.addCallback(lambda _: webbrowser.open( - "file://" + str(os.path.join(self.download_directory, "lbryio/view/page/gui.html")))) - d.addErrback(_disp_err) - d.callback(None) - - return d - - def xmlrpc_search_nametrie(self, search): + def jsonrpc_search_nametrie(self, p): """ Search the nametrie for claims beginning with search - @param search: - @return: + @param {'search': search string} + @return: List of search results """ + params = Bunch(p) + def _clean(n): t = [] for i in n: @@ -910,26 +863,6 @@ class LBRYDaemon(xmlrpc.XMLRPC): t.append([i[1][0][1], i[1][1][1], i[1][2][1]]) return t - def _parse(results): - f = [] - for chain, meta, cost_est in results: - t = {} - if 'name' in chain.keys(): - t['name'] = chain['name'] - if 'thumbnail' in meta.keys(): - t['img'] = meta['thumbnail'] - else: - t['img'] = 'File://' + str( - os.path.join(self.download_directory, "lbryio/web/img/Free-speech-flag.svg")) - if 'name' in meta.keys(): - t['title'] = meta['name'] - if 'description' in meta.keys(): - t['description'] = meta['description'] - t['cost_est'] = cost_est - f.append(t) - - return f - def resolve_claims(claims): ds = [] for claim in claims: @@ -941,148 +874,163 @@ class LBRYDaemon(xmlrpc.XMLRPC): return defer.DeferredList(ds) def _disp(results): - print '[' + str(datetime.now()) + '] Found ' + str(len(results)) + ' results' - log.info('[' + str(datetime.now()) + '] Search results: ') + log.info('[' + str(datetime.now()) + '] Found ' + str(len(results)) + ' search results') + consolidated_results = [] for r in results: - log.info(str(r)) - return results + t = {} + t.update(r[0]) + if 'name' in r[1].keys(): + r[1]['stream_name'] = r[1]['name'] + del r[1]['name'] + t.update(r[1]) + t['cost_est'] = r[2] + consolidated_results.append(t) + # log.info(str(t)) + return self._render_response(consolidated_results, OK_CODE) - print '[' + str(datetime.now()) + '] Search nametrie: ' + search - log.info('[' + str(datetime.now()) + '] Search nametrie: ' + search) + log.info('[' + str(datetime.now()) + '] Search nametrie: ' + params.search) d = self.session.wallet.get_nametrie() - d.addCallback(lambda trie: [claim for claim in trie if claim['name'].startswith(search) and 'txid' in claim]) + d.addCallback(lambda trie: [claim for claim in trie if claim['name'].startswith(params.search) and 'txid' in claim]) d.addCallback(lambda claims: claims[:self.max_search_results]) d.addCallback(resolve_claims) d.addCallback(_clean) - d.addCallback(_parse) d.addCallback(_disp) return d - def xmlrpc_delete_lbry_file(self, file_name): + def jsonrpc_delete_lbry_file(self, p): + """ + Delete a lbry file + + @param {'file_name': string} + @return: confirmation message + """ + + params = Bunch(p) + def _disp(file_name): - print '[' + str(datetime.now()) + '] Deleted: ' + file_name - return defer.succeed('Deleted: ' + file_name) + log.info("[" + str(datetime.now()) + "] Deleted: " + file_name) + return self._render_response("Deleted: " + file_name, OK_CODE) - lbry_files = [self._delete_lbry_file(f) for f in self.lbry_file_manager.lbry_files if file_name == f.file_name] + lbry_files = [self._delete_lbry_file(f) for f in self.lbry_file_manager.lbry_files if params.file_name == f.file_name] d = defer.DeferredList(lbry_files) - d.addCallback(lambda _: _disp(file_name)) + d.addCallback(lambda _: _disp(params.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)) + def jsonrpc_publish(self, p): + """ + Make a new name claim - return d + @param: + @return: + """ - def xmlrpc_publish(self, metadata): - try: - metadata = json.loads(metadata) - except: - return defer.succeed(BAD_REQUEST) + params = Bunch(p) - required = ['name', 'file_path', 'bid'] + metadata_fields = {"name": unicode, "file_path": unicode, "bid": float, "author": unicode, "title": unicode, + "description": unicode, "thumbnail": unicode, "key_fee": float, "key_fee_address": unicode, + "content_license": unicode, "sources": dict} - for r in required: - if not r in metadata.keys(): - return defer.succeed(BAD_REQUEST) + for k in metadata_fields.keys(): + if k in params.__dict__.keys(): + if isinstance(params.__dict__[k], metadata_fields[k]): + if type(params.__dict__[k]) == unicode: + metadata_fields[k] = str(params.__dict__[k]) + else: + metadata_fields[k] = params.__dict__[k] + else: + metadata_fields[k] = None + else: + metadata_fields[k] = None - # if not os.path.isfile(metadata['file_path']): - # return defer.fail() - - if not isinstance(metadata['bid'], float) and metadata['bid'] > 0.0: - return defer.fail() - - name = metadata['name'] - file_path = metadata['file_path'] - bid = metadata['bid'] - - if 'title' in metadata.keys(): - title = metadata['title'] - else: - title = None - - if 'description' in metadata.keys(): - description = metadata['description'] - else: - description = None - - if 'thumbnail' in metadata.keys(): - thumbnail = metadata['thumbnail'] - else: - thumbnail = None - - if 'key_fee' in metadata.keys(): - if not float(metadata['key_fee']) == 0.0: - if not 'key_fee_address' in metadata.keys(): - return defer.fail() - key_fee = metadata['key_fee'] - else: - key_fee = 0.0 - - if 'key_fee_address' in metadata.keys(): - key_fee_address = metadata['key_fee_address'] - else: - key_fee_address = None - - if 'content_license' in metadata.keys(): - content_license = metadata['content_license'] - else: - content_license = None - - log.info('[' + str(datetime.now()) + '] Publish: ', name, file_path, bid, title, description, thumbnail, - key_fee, key_fee_address, content_license) + log.info("[" + str(datetime.now()) + "] Publish: ", metadata_fields) p = Publisher(self.session, self.lbry_file_manager, self.session.wallet) - d = p.start(name, file_path, bid, title, description, thumbnail, key_fee, key_fee_address, content_license) - d.addCallback(lambda msg: (OK_CODE, msg)) + d = p.start(name=metadata_fields['name'], + file_path=metadata_fields['file_path'], + bid=metadata_fields['bid'], + title=metadata_fields['title'], + description=metadata_fields['description'], + thumbnail=metadata_fields['thumbnail'], + key_fee=metadata_fields['key_fee'], + key_fee_address=metadata_fields['key_fee_address'], + content_license=metadata_fields['content_license'], + author=metadata_fields['author'], + sources=metadata_fields['sources']) + + d.addCallbacks(lambda msg: self._render_response(msg, OK_CODE), + lambda err: self._render_response(err.getTraceback(), BAD_REQUEST)) return d - def xmlrpc_abandon_name(self, txid): + def jsonrpc_abandon_name(self, p): + """ + Abandon and reclaim credits from a name claim + + @param: {'txid': string} + @return: txid + """ + params = Bunch(p) + def _disp(txid, tx): - print '[' + str(datetime.now()) + '] Spent coins from claim tx ' + txid + ' --> ' + tx - return tx + log.info("[" + str(datetime.now()) + "] Abandoned name claim tx " + txid) + return self._render_response(txid, OK_CODE) d = defer.Deferred() - d.addCallback(lambda _: self.session.wallet.abandon_name(txid)) - d.addCallback(lambda tx: _disp(txid, tx)) - d.addErrback(lambda err: str(err.getTraceback())) + d.addCallback(lambda _: self.session.wallet.abandon_name(params.txid)) + d.addCallback(lambda tx: _disp(params.txid, tx)) + d.addErrback(lambda err: self._render_response(err.getTraceback(), BAD_REQUEST)) d.callback(None) return d - def xmlrpc_get_name_claims(self): + def jsonrpc_get_name_claims(self): + """ + Get name claims + + @return: list of name claims + """ def _clean(claims): for c in claims: for k in c.keys(): if isinstance(c[k], Decimal): c[k] = float(c[k]) - return claims + return self._render_response(claims, OK_CODE) d = self.session.wallet.get_name_claims() d.addCallback(_clean) return d - def xmlrpc_get_time_behind_blockchain(self): + def jsonrpc_get_time_behind_blockchain(self): + """ + Get time behind blockchain + + @return: time behind blockchain + """ d = self.session.wallet.get_most_recent_blocktime() d.addCallback(get_time_behind_blockchain) + d.addCallbacks(lambda result: self._render_response(result, OK_CODE), + lambda result: self._render_response(result, BAD_REQUEST)) return d - def xmlrpc_get_new_address(self): + def jsonrpc_get_new_address(self): + """ + Generate a new wallet address + + @return: new wallet address + """ def _disp(address): - print "[" + str(datetime.now()) + "] Got new wallet address: " + address - return address + log.info("[" + str(datetime.now()) + "] Got new wallet address: " + address) + return json.dumps(self._render_response(address, OK_CODE)) d = self.session.wallet.get_new_address() d.addCallback(_disp) return d - # def xmlrpc_update_name(self, metadata): + # def jsonrpc_update_name(self, metadata): # def _disp(x): # print x # return x @@ -1102,15 +1050,15 @@ class LBRYDaemon(xmlrpc.XMLRPC): # # return d - def xmlrpc_toggle_fetcher_verbose(self): + def jsonrpc_toggle_fetcher_verbose(self): if self.fetcher.verbose: self.fetcher.verbose = False else: self.fetcher.verbose = True - return self.fetcher.verbose + return self._render_response(self.fetcher.verbose, OK_CODE) - def xmlrpc_check_for_new_version(self): + def jsonrpc_check_for_new_version(self): def _check_for_updates(package): git_version = subprocess.check_output("git ls-remote " + package['git'] + " | grep HEAD | cut -f 1", shell=True) up_to_date = False @@ -1147,64 +1095,113 @@ class LBRYDaemon(xmlrpc.XMLRPC): }, } - return [_check_for_updates(package_infos[p]) for p in package_infos.keys()] + r = [_check_for_updates(package_infos[p]) for p in package_infos.keys()] + log.info("[" + str(datetime.now()) + "] Check for new version: " + json.dumps(r)) + return self._render_response(r, OK_CODE) - def xmlrpc_start_status_bar_app(self): - if sys.platform == 'darwin': - if os.path.isdir("/Applications/LBRY.app"): - # subprocess.Popen("screen -dmS lbry-status bash -c 'lbrynet-daemon-status --startdaemon=False'", shell=True) - subprocess.Popen("screen -dmS lbry-status bash -c 'open /Applications/LBRY.app'") - return "Started" - else: - return "Couldn't find LBRY.app, try running the installer" - else: - return "Status bar not implemented on non OS X" - - def xmlrpc___dir__(self): + def jsonrpc___dir__(self): return ['is_running', 'get_settings', 'set_settings', 'start_fetcher', 'stop_fetcher', 'fetcher_status', 'get_balance', 'stop', 'get_lbry_files', 'resolve_name', 'get', 'search_nametrie', 'delete_lbry_file', 'check', 'publish', 'abandon_name', 'get_name_claims', 'get_time_behind_blockchain', 'get_new_address', 'toggle_fetcher_verbose', 'check_for_new_version'] -def stop(): - daemon = xmlrpclib.ServerProxy("http://localhost:7080/") - try: - status = daemon.is_running() - except: - status = False +class LBRYDaemonCommandHandler(object): + def __init__(self, command): + self._api = jsonrpc.Proxy(API_CONNECTION_STRING) + self.command = command - if status: - daemon.stop() - print "LBRYnet daemon stopped" - else: - print "LBRYnet daemon wasn't running" + def run(self, params=None): + if params: + d = self._api.callRemote(self.command, params) + else: + d = self._api.callRemote(self.command) + return d -def main(): - parser = argparse.ArgumentParser(description="Launch lbrynet-daemon") - parser.add_argument("--wallet", - help="lbrycrd or lbryum, default lbryum", - type=str, - default="lbryum") - parser.add_argument("--update", - help="True or false, default true", - type=str, - default="True") +class LBRYindex(resource.Resource): + def __init__(self, ui_dir): + resource.Resource.__init__(self) + self.ui_dir = ui_dir - args = parser.parse_args() + isLeaf = False - try: - daemon = xmlrpclib.ServerProxy("http://localhost:7080") - daemon.stop() - except: - pass + def _delayed_render(self, request, results): + request.write(str(results)) + request.finish() - daemon = LBRYDaemon() - daemon.setup(args.wallet, args.update) - reactor.listenTCP(7080, server.Site(daemon), interface='localhost') - reactor.run() + def getChild(self, name, request): + if name == '': + return self + return resource.Resource.getChild(self, name, request) + + def render_GET(self, request): + return static.File(os.path.join(self.ui_dir, "index.html")).render_GET(request) -if __name__ == '__main__': - main() \ No newline at end of file +class LBRYFileRender(resource.Resource): + isLeaf = False + + def _render_path(self, path): + extension = os.path.splitext(path)[1] + if extension in ['mp4', 'flv', 'mov', 'ogv']: + return r'<html><center><video src="' + path + r'" controls autoplay width="960" height="720"></center></html>' + + def _delayed_render(self, request, results): + request.write(str(results)) + request.finish() + + def render_GET(self, request): + if 'name' in request.args.keys(): + api = jsonrpc.Proxy(API_CONNECTION_STRING) + d = api.callRemote("get", {'name': request.args['name'][0]}) + d.addCallback(lambda response: self._delayed_render(request, self._render_path(json.loads(response)['result']['path'])) + if json.loads(response)['code'] == 200 + else self._delayed_render(request, "Error")) + + return server.NOT_DONE_YET + else: + self._delayed_render(request, "Error") + return server.NOT_DONE_YET + + +# class LBRYFilePage(resource.Resource): +# isLeaf = False +# +# def _delayed_render(self, request, results): +# request.write(str(results)) +# request.finish() +# +# h = "<tr><td><a href=/webapi?function=delete_lbry_file&file_name=%s>%s</a></td></tr>" +# +# d = LBRYDaemonCommandHandler('get_lbry_files').run() +# d.addCallback(lambda r: json.loads(r)['result']) +# d.addCallback(lambda lbry_files: [h % (json.loads(lbry_file)['file_name'], json.loads(lbry_file)['file_name']) for lbry_file in lbry_files]) +# d.addCallback(lambda r: "<html><table style='width:100%'>" + ''.join(r) + "</html>") +# d.addCallbacks(lambda results: self._delayed_render(request, results), +# lambda err: self._delayed_render(request, err.getTraceback())) +# +# return server.NOT_DONE_YET + + +class LBRYDaemonWeb(resource.Resource): + isLeaf = False + + def _delayed_render(self, request, results): + request.write(str(results)) + request.setResponseCode(json.loads(results)['code']) + request.finish() + + def render_GET(self, request): + func = request.args['function'][0] + del request.args['function'] + + p = {} + for k in request.args.keys(): + p[k] = request.args[k][0] + + d = LBRYDaemonCommandHandler(func).run(p) + d.addCallbacks(lambda results: self._delayed_render(request, results), + lambda err: self._delayed_render(request, json.dumps({'message': err.getTraceback(), 'code': BAD_REQUEST}))) + + return server.NOT_DONE_YET \ No newline at end of file diff --git a/setup.py b/setup.py index ed9b2a866..22d73b43e 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,15 @@ #!/usr/bin/env python -from setuptools import setup, find_packages -import sys -import os - -base_dir = os.path.abspath(os.path.dirname(__file__)) - - from lbrynet import __version__ +import ez_setup +import sys +import os +from setuptools import setup, find_packages + +base_dir = os.path.abspath(os.path.dirname(__file__)) + +ez_setup.use_setuptools() console_scripts = ['lbrynet-console = lbrynet.lbrynet_console.LBRYConsole:launch_lbry_console', 'lbrynet-stdin-uploader = lbrynet.lbrynet_console.LBRYStdinUploader:launch_stdin_uploader', @@ -20,22 +21,25 @@ console_scripts = ['lbrynet-console = lbrynet.lbrynet_console.LBRYConsole:launch 'lbrynet-gui = lbrynet.lbrynet_gui.gui:start_gui', 'lbrynet-lookup-hosts-for-hash = lbrynet.dht_scripts:get_hosts_for_hash_in_dht', 'lbrynet-announce_hash_to_dht = lbrynet.dht_scripts:announce_hash_to_dht', - 'lbrynet-daemon = lbrynet.lbrynet_daemon.LBRYDaemon:main', - 'stop-lbrynet-daemon = lbrynet.lbrynet_daemon.LBRYDaemon:stop'] + 'lbrynet-daemon = lbrynet.lbrynet_daemon.LBRYDaemonControl:start', + 'stop-lbrynet-daemon = lbrynet.lbrynet_daemon.LBRYDaemonControl:stop'] +requires = ['pycrypto', 'twisted', 'miniupnpc', 'yapsy', 'seccure', + 'python-bitcoinrpc==0.1', 'txJSON-RPC', 'requests>=2.4.2', 'unqlite==0.2.0', + 'leveldb', 'lbryum', 'jsonrpc', 'simplejson', 'appdirs'] if sys.platform == 'darwin': - console_scripts.append('lbrynet-daemon-status = lbrynet.lbrynet_daemon.LBRYOSXStatusBar:main') - + requires.append('six==1.9.0') +else: + requires.append('six>=1.9.0') gui_data_files = ['close2.gif', 'lbry-dark-242x80.gif', 'lbry-dark-icon.xbm', 'lbry-dark-icon.ico', 'drop_down.gif', 'show_options.gif', 'hide_options.gif', 'lbry.conf'] gui_data_paths = [os.path.join(base_dir, 'lbrynet', 'lbrynet_gui', f) for f in gui_data_files] -setup(name='lbrynet', - version='.'.join([str(x) for x in __version__]), +setup(name='lbrynet', version='.'.join([str(x) for x in __version__]), packages=find_packages(base_dir), - install_requires=['six>=1.9.0', 'pycrypto', 'twisted', 'miniupnpc', 'yapsy', 'seccure', 'python-bitcoinrpc==0.1', 'txJSON-RPC', 'requests>=2.4.2', 'unqlite==0.2.0', 'leveldb', 'lbryum'], + install_requires=requires, entry_points={'console_scripts': console_scripts}, data_files=[ ('lbrynet/lbrynet_console/plugins', @@ -47,4 +51,4 @@ setup(name='lbrynet', ('lbrynet/lbrynet_gui', gui_data_paths) ], dependency_links=['https://github.com/lbryio/lbryum/tarball/master/#egg=lbryum'], - ) + ) \ No newline at end of file