From 979f8efa79b160a6c301998aed7f6d0679b71af3 Mon Sep 17 00:00:00 2001 From: Jack Date: Tue, 6 Dec 2016 12:35:27 -0500 Subject: [PATCH] remove unused lbrynet-console --- lbrynet/lbrynet_console/Console.py | 574 ---- lbrynet/lbrynet_console/ConsoleControl.py | 176 -- lbrynet/lbrynet_console/ControlHandlers.py | 2626 ----------------- lbrynet/lbrynet_console/Plugin.py | 13 - lbrynet/lbrynet_console/__init__.py | 8 - lbrynet/lbrynet_console/interfaces.py | 24 - .../plugins/BlindRepeater/BlindBlobHandler.py | 15 - .../plugins/BlindRepeater/BlindInfoManager.py | 78 - .../BlindRepeater/BlindMetadataHandler.py | 321 -- .../BlindRepeater/BlindProgressManager.py | 93 - .../plugins/BlindRepeater/BlindRepeater.py | 113 - .../BlindRepeaterControlHandlers.py | 335 --- .../BlindRepeater/BlindRepeaterSettings.py | 106 - .../BlindRepeater/PaymentRateManager.py | 20 - .../plugins/BlindRepeater/ValuableBlobInfo.py | 9 - .../BlindRepeater/ValuableBlobQueryHandler.py | 202 -- .../plugins/BlindRepeater/__init__.py | 130 - .../plugins/BlindRepeater/interfaces.py | 6 - lbrynet/lbrynet_console/plugins/__init__.py | 0 .../plugins/blindrepeater.yapsy-plugin | 8 - lbrynet/lbrynet_daemon/Daemon.py | 2 +- .../Settings.py | 0 22 files changed, 1 insertion(+), 4858 deletions(-) delete mode 100644 lbrynet/lbrynet_console/Console.py delete mode 100644 lbrynet/lbrynet_console/ConsoleControl.py delete mode 100644 lbrynet/lbrynet_console/ControlHandlers.py delete mode 100644 lbrynet/lbrynet_console/Plugin.py delete mode 100644 lbrynet/lbrynet_console/__init__.py delete mode 100644 lbrynet/lbrynet_console/interfaces.py delete mode 100644 lbrynet/lbrynet_console/plugins/BlindRepeater/BlindBlobHandler.py delete mode 100644 lbrynet/lbrynet_console/plugins/BlindRepeater/BlindInfoManager.py delete mode 100644 lbrynet/lbrynet_console/plugins/BlindRepeater/BlindMetadataHandler.py delete mode 100644 lbrynet/lbrynet_console/plugins/BlindRepeater/BlindProgressManager.py delete mode 100644 lbrynet/lbrynet_console/plugins/BlindRepeater/BlindRepeater.py delete mode 100644 lbrynet/lbrynet_console/plugins/BlindRepeater/BlindRepeaterControlHandlers.py delete mode 100644 lbrynet/lbrynet_console/plugins/BlindRepeater/BlindRepeaterSettings.py delete mode 100644 lbrynet/lbrynet_console/plugins/BlindRepeater/PaymentRateManager.py delete mode 100644 lbrynet/lbrynet_console/plugins/BlindRepeater/ValuableBlobInfo.py delete mode 100644 lbrynet/lbrynet_console/plugins/BlindRepeater/ValuableBlobQueryHandler.py delete mode 100644 lbrynet/lbrynet_console/plugins/BlindRepeater/__init__.py delete mode 100644 lbrynet/lbrynet_console/plugins/BlindRepeater/interfaces.py delete mode 100644 lbrynet/lbrynet_console/plugins/__init__.py delete mode 100644 lbrynet/lbrynet_console/plugins/blindrepeater.yapsy-plugin rename lbrynet/{lbrynet_console => lbrynet_daemon}/Settings.py (100%) diff --git a/lbrynet/lbrynet_console/Console.py b/lbrynet/lbrynet_console/Console.py deleted file mode 100644 index 04d3136c1..000000000 --- a/lbrynet/lbrynet_console/Console.py +++ /dev/null @@ -1,574 +0,0 @@ -# TODO: THERE IS A LOT OF CODE IN THIS MODULE THAT SHOULD BE REMOVED -# AS IT IS REPEATED IN THE LBRYDaemon MODULE -import logging -import os.path -import argparse -import requests -import locale -import sys -import webbrowser - -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 lbrynet.lbrynet_daemon.auth.client import LBRYAPIClient - -from lbrynet import analytics -from lbrynet.core.Session import Session -from lbrynet.lbrynet_console.ConsoleControl import ConsoleControl -from lbrynet.lbrynet_console.Settings import Settings -from lbrynet.lbryfilemanager.EncryptedFileManager import EncryptedFileManager -from lbrynet.conf import settings -from lbrynet.core.utils import generate_id -from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier -from lbrynet.core.PaymentRateManager import PaymentRateManager -from lbrynet.core.server.BlobRequestHandler import BlobRequestHandlerFactory -from lbrynet.core.server.ServerProtocol import ServerProtocolFactory -from lbrynet.core.PTCWallet import PTCWallet -from lbrynet.lbryfile.client.EncryptedFileOptions import add_lbry_file_to_sd_identifier -from lbrynet.lbryfile.client.EncryptedFileDownloader import EncryptedFileOpenerFactory -from lbrynet.lbryfile.StreamDescriptor import EncryptedFileStreamType -from lbrynet.lbryfile.EncryptedFileMetadataManager import DBEncryptedFileMetadataManager, TempEncryptedFileMetadataManager -from lbrynet.lbrynet_console.ControlHandlers import ApplicationStatusFactory, GetWalletBalancesFactory, ShutDownFactory -from lbrynet.lbrynet_console.ControlHandlers import ImmediateAnnounceAllBlobsFactory -from lbrynet.lbrynet_console.ControlHandlers import EncryptedFileStatusFactory, DeleteEncryptedFileChooserFactory -from lbrynet.lbrynet_console.ControlHandlers import ToggleEncryptedFileRunningChooserFactory -from lbrynet.lbrynet_console.ControlHandlers import ModifyApplicationDefaultsFactory -from lbrynet.lbrynet_console.ControlHandlers import CreateEncryptedFileFactory, PublishStreamDescriptorChooserFactory -from lbrynet.lbrynet_console.ControlHandlers import ShowPublishedSDHashesChooserFactory -from lbrynet.lbrynet_console.ControlHandlers import CreatePlainStreamDescriptorChooserFactory -from lbrynet.lbrynet_console.ControlHandlers import ShowEncryptedFileStreamHashChooserFactory, AddStreamFromHashFactory -from lbrynet.lbrynet_console.ControlHandlers import AddStreamFromSDFactory, AddStreamFromLBRYcrdNameFactory -from lbrynet.lbrynet_console.ControlHandlers import ClaimNameFactory, GetNewWalletAddressFactory -from lbrynet.lbrynet_console.ControlHandlers import ShowServerStatusFactory, ModifyServerSettingsFactory -from lbrynet.lbrynet_console.ControlHandlers import ModifyEncryptedFileOptionsChooserFactory, StatusFactory -from lbrynet.lbrynet_console.ControlHandlers import PeerStatsAndSettingsChooserFactory, PublishFactory -from lbrynet.lbrynet_console.ControlHandlers import BlockchainStatusFactory -from lbrynet.core.Wallet import LBRYumWallet - - -log = logging.getLogger(__name__) -alert = logging.getLogger("lbryalert." + __name__) - - -class Console(): - """A class which can upload and download file streams to and from the network""" - def __init__(self, peer_port, dht_node_port, known_dht_nodes, fake_wallet, - lbrycrd_conf, lbrycrd_dir, use_upnp, data_dir, created_data_dir, - lbrycrdd_path): - """ - @param peer_port: the network port on which to listen for peers - - @param dht_node_port: the network port on which to listen for dht node requests - - @param known_dht_nodes: a list of (ip_address, dht_port) which will be used to join the DHT network - """ - self.peer_port = peer_port - self.dht_node_port = dht_node_port - self.known_dht_nodes = known_dht_nodes - self.fake_wallet = fake_wallet - self.lbrycrd_conf = lbrycrd_conf - self.lbrycrd_dir = lbrycrd_dir - if not self.lbrycrd_dir: - if sys.platform == "darwin": - self.lbrycrd_dir = os.path.join(os.path.expanduser("~"), "Library/Application Support/lbrycrd") - else: - self.lbrycrd_dir = os.path.join(os.path.expanduser("~"), ".lbrycrd") - if not self.lbrycrd_conf: - self.lbrycrd_conf = os.path.join(self.lbrycrd_dir, "lbrycrd.conf") - self.lbrycrdd_path = lbrycrdd_path - self.use_upnp = use_upnp - self.lbry_server_port = None - self.session = None - self.lbry_file_metadata_manager = None - self.lbry_file_manager = None - self.db_dir = data_dir - self.current_db_revision = 1 - self.blobfile_dir = os.path.join(self.db_dir, "blobfiles") - self.created_data_dir = created_data_dir - self.plugin_manager = PluginManager() - self.plugin_manager.setPluginPlaces([ - os.path.join(self.db_dir, "plugins"), - os.path.join(os.path.dirname(__file__), "plugins"), - ]) - self.command_handlers = [] - self.query_handlers = {} - - self.settings = Settings(self.db_dir) - self.blob_request_payment_rate_manager = None - self.lbryid = None - self.sd_identifier = StreamDescriptorIdentifier() - self.plugin_objects = [] - self.db_migration_revisions = None - - def start(self): - """Initialize the session and restore everything to its saved state""" - d = self._setup_controller() - d.addCallback(lambda _: threads.deferToThread(self._setup_data_directory)) - d.addCallback(lambda _: self._check_db_migration()) - d.addCallback(lambda _: self._get_settings()) - d.addCallback(lambda _: self._get_session()) - d.addCallback(lambda _: add_lbry_file_to_sd_identifier(self.sd_identifier)) - d.addCallback(lambda _: self._setup_lbry_file_manager()) - d.addCallback(lambda _: self._setup_lbry_file_opener()) - d.addCallback(lambda _: self._setup_control_handlers()) - d.addCallback(lambda _: self._setup_query_handlers()) - d.addCallback(lambda _: self._load_plugins()) - d.addCallback(lambda _: self._setup_server()) - d.addCallback(lambda _: self._start_controller()) - d.addErrback(self._show_start_error) - return d - - def _show_start_error(self, error): - print error.getTraceback() - log.error("An error occurred during start up: %s", error.getTraceback()) - return error - - def _show_shutdown_error(self, error): - print error.getErrorMessage() - log.error("An error occurred during shutdown: %s", error.getTraceback()) - return error - - def shut_down(self): - """Stop the session, all currently running streams, and stop the server""" - d = self._shut_down() - if self.session is not None: - d.addCallback(lambda _: self.session.shut_down()) - d.addErrback(self._show_shutdown_error) - return d - - def add_control_handlers(self, control_handlers): - for control_handler in control_handlers: - self.command_handlers.append(control_handler) - - def add_query_handlers(self, query_handlers): - - def _set_query_handlers(statuses): - from future_builtins import zip - for handler, (success, status) in zip(query_handlers, statuses): - if success is True: - self.query_handlers[handler] = status - - ds = [] - for handler in query_handlers: - ds.append(self.settings.get_query_handler_status(handler.get_primary_query_identifier())) - dl = defer.DeferredList(ds) - dl.addCallback(_set_query_handlers) - return dl - - def _setup_data_directory(self): - alert.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)) - db_revision.close() - log.debug("Created the db revision file: %s", str(os.path.join(self.db_dir, "db_revision"))) - if not os.path.exists(self.blobfile_dir): - os.mkdir(self.blobfile_dir) - log.debug("Created the blobfile directory: %s", str(self.blobfile_dir)) - - def _check_db_migration(self): - old_revision = 1 - db_revision_file = os.path.join(self.db_dir, "db_revision") - if os.path.exists(db_revision_file): - 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..." - d = threads.deferToThread(dbmigrator.migrate_db, self.db_dir, old_revision, self.current_db_revision) - - def print_success(old_dirs): - success_string = "Finished upgrading the databases. It is now safe to delete the" - success_string += " following directories, if you feel like it. It won't make any" - success_string += " difference.\nAnyway here they are: " - for i, old_dir in enumerate(old_dirs): - success_string += old_dir - if i + 1 < len(old_dir): - success_string += ", " - print success_string - - d.addCallback(print_success) - return d - return defer.succeed(True) - - def _get_settings(self): - d = self.settings.start() - d.addCallback(lambda _: self.settings.get_lbryid()) - d.addCallback(self.set_lbryid) - 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 _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 settings.data_rate}) - return d - - def get_wallet(): - if self.fake_wallet: - d = defer.succeed(PTCWallet(self.db_dir)) - else: - d = defer.succeed(LBRYumWallet(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): - - alert.info("Databases loaded.") - - self.session = Session(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']) - - dl = defer.DeferredList([d1, d2], fireOnOneErrback=True) - - dl.addCallback(combine_results) - - dl.addCallback(create_session) - - dl.addCallback(lambda _: self.session.setup()) - - dl.addCallback(lambda _: self.check_first_run()) - - dl.addCallback(self._show_first_run_result) - - return dl - - def check_first_run(self): - 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 - - def _do_first_run(self): - d = self.session.wallet.get_new_address() - - def send_request(url, data): - r = requests.post(url, json=data) - if r.status_code == 200: - return r.json()['credits_sent'] - return 0.0 - - def log_error(err): - log.warning("unable to request free credits. %s", err.getErrorMessage()) - return 0.0 - - def request_credits(address): - url = "http://credreq.lbry.io/requestcredits" - data = {"address": address} - d = threads.deferToThread(send_request, url, data) - d.addErrback(log_error) - return d - - d.addCallback(request_credits) - return d - - @staticmethod - def _show_first_run_result(credits_received): - if credits_received != 0.0: - points_string = locale.format_string("%.2f LBC", (round(credits_received, 2),), - grouping=True) - alert.info("\n\nThank you for testing the alpha version of LBRY!\n\n" - "You have been given %s for free because we love you.\n" - "Please give them a few minutes to show up while you\n" - "catch up with our blockchain.\n", points_string) - - def _setup_lbry_file_manager(self): - self.lbry_file_metadata_manager = DBEncryptedFileMetadataManager(self.db_dir) - d = self.lbry_file_metadata_manager.setup() - - def set_lbry_file_manager(): - self.lbry_file_manager = EncryptedFileManager(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): - stream_info_manager = TempEncryptedFileMetadataManager() - downloader_factory = EncryptedFileOpenerFactory(self.session.peer_finder, self.session.rate_limiter, - self.session.blob_manager, stream_info_manager, - self.session.wallet) - self.sd_identifier.add_stream_downloader_factory(EncryptedFileStreamType, downloader_factory) - return defer.succeed(True) - - def _setup_control_handlers(self): - handlers = [ - ApplicationStatusFactory(self.session.rate_limiter, self.session.dht_node), - GetWalletBalancesFactory(self.session.wallet), - ModifyApplicationDefaultsFactory(self), - ShutDownFactory(self), - PeerStatsAndSettingsChooserFactory(self.session.peer_manager), - EncryptedFileStatusFactory(self.lbry_file_manager), - AddStreamFromSDFactory(self.sd_identifier, self.session.base_payment_rate_manager, - self.session.wallet), - DeleteEncryptedFileChooserFactory(self.lbry_file_metadata_manager, self.session.blob_manager, - self.lbry_file_manager), - ToggleEncryptedFileRunningChooserFactory(self.lbry_file_manager), - CreateEncryptedFileFactory(self.session, self.lbry_file_manager), - PublishStreamDescriptorChooserFactory(self.lbry_file_metadata_manager, - self.session.blob_manager), - ShowPublishedSDHashesChooserFactory(self.lbry_file_metadata_manager, - self.lbry_file_manager), - CreatePlainStreamDescriptorChooserFactory(self.lbry_file_manager), - ShowEncryptedFileStreamHashChooserFactory(self.lbry_file_manager), - ModifyEncryptedFileOptionsChooserFactory(self.lbry_file_manager), - AddStreamFromHashFactory(self.sd_identifier, self.session, self.session.wallet), - StatusFactory(self, self.session.rate_limiter, self.lbry_file_manager, - self.session.blob_manager, self.session.wallet if not self.fake_wallet else None), - ImmediateAnnounceAllBlobsFactory(self.session.blob_manager) - ] - self.add_control_handlers(handlers) - if not self.fake_wallet: - lbrycrd_handlers = [ - AddStreamFromLBRYcrdNameFactory(self.sd_identifier, self.session, - self.session.wallet), - ClaimNameFactory(self.session.wallet, self.lbry_file_manager, - self.session.blob_manager), - GetNewWalletAddressFactory(self.session.wallet), - PublishFactory(self.session, self.lbry_file_manager, self.session.wallet), - BlockchainStatusFactory(self.session.wallet) - ] - self.add_control_handlers(lbrycrd_handlers) - if self.peer_port is not None: - server_handlers = [ - ShowServerStatusFactory(self), - ModifyServerSettingsFactory(self), - ] - self.add_control_handlers(server_handlers) - - def _setup_query_handlers(self): - handlers = [ - self.session.wallet.get_wallet_info_query_handler_factory(), - ] - - def get_blob_request_handler_factory(rate): - self.blob_request_payment_rate_manager = PaymentRateManager( - self.session.base_payment_rate_manager, rate - ) - handlers.append(BlobRequestHandlerFactory( - self.session.blob_manager, self.session.wallet, - self.blob_request_payment_rate_manager, analytics.Track() - )) - - d1 = self.settings.get_server_data_payment_rate() - d1.addCallback(get_blob_request_handler_factory) - - dl = defer.DeferredList([d1]) - dl.addCallback(lambda _: self.add_query_handlers(handlers)) - return dl - - def _load_plugins(self): - d = threads.deferToThread(self.plugin_manager.collectPlugins) - - def setup_plugins(): - ds = [] - for plugin in self.plugin_manager.getAllPlugins(): - self.plugin_objects.append(plugin.plugin_object) - ds.append(plugin.plugin_object.setup(self)) - return defer.DeferredList(ds) - - d.addCallback(lambda _: setup_plugins()) - return d - - def _stop_plugins(self): - ds = [] - for plugin_object in self.plugin_objects: - ds.append(defer.maybeDeferred(plugin_object.stop)) - return defer.DeferredList(ds) - - def _setup_server(self): - - def restore_running_status(running): - if running is True: - return self.start_server() - return defer.succeed(True) - - dl = self.settings.get_server_running_status() - dl.addCallback(restore_running_status) - return dl - - def start_server(self): - - if self.peer_port is not None: - - server_factory = ServerProtocolFactory(self.session.rate_limiter, - self.query_handlers, - self.session.peer_manager) - from twisted.internet import reactor - try: - self.lbry_server_port = reactor.listenTCP(self.peer_port, server_factory) - except error.CannotListenError as e: - import traceback - log.error("Couldn't bind to port %d. %s", self.peer_port, traceback.format_exc()) - raise ValueError("%s lbrynet may already be running on your computer.", str(e)) - return defer.succeed(True) - - def stop_server(self): - if self.lbry_server_port is not None: - self.lbry_server_port, p = None, self.lbry_server_port - return defer.maybeDeferred(p.stopListening) - else: - return defer.succeed(True) - - def _setup_controller(self): - self.controller = ConsoleControl() - stdio.StandardIO(self.controller) - logger = logging.getLogger() - formatter = logging.Formatter("%(message)s") - alert_handler = logging.StreamHandler(self.controller) - alert_handler.setFormatter(formatter) - alert_handler.addFilter(logging.Filter("lbryalert")) - alert_handler.setLevel(logging.DEBUG) - logger.addHandler(alert_handler) - return defer.succeed(True) - - def _start_controller(self): - return self.controller.start(self.command_handlers) - - def _shut_down(self): - self.plugin_manager = None - ds = [] - if self.lbry_file_metadata_manager is not None: - d = self.lbry_file_metadata_manager.stop() - d.addCallback(lambda _: self.lbry_file_manager.stop()) - ds.append(d) - ds.append(self.stop_server()) - ds.append(self._stop_plugins()) - dl = defer.DeferredList(ds) - return dl - - -def launch_lbry_console(): - from twisted.internet import reactor - - parser = argparse.ArgumentParser(description="Launch a lbrynet console") - parser.add_argument("--no_listen_peer", - help="Don't listen for incoming data connections.", - action="store_true") - parser.add_argument("--peer_port", - help="The port on which the console will listen for incoming data connections.", - type=int, default=3333) - parser.add_argument("--no_listen_dht", - help="Don't listen for incoming DHT connections.", - action="store_true") - parser.add_argument("--dht_node_port", - help="The port on which the console will listen for DHT connections.", - type=int, default=4444) - parser.add_argument("--fake_wallet", - help="Testing purposes only. Use a non-blockchain wallet.", - action="store_true") - parser.add_argument("--no_dht_bootstrap", - help="Don't try to connect to the DHT", - action="store_true") - parser.add_argument("--dht_bootstrap_host", - help="The hostname of a known DHT node, to be used to bootstrap into the DHT. " - "Must be used with --dht_bootstrap_port", - type=str, default='104.236.42.182') - parser.add_argument("--dht_bootstrap_port", - help="The port of a known DHT node, to be used to bootstrap into the DHT. Must " - "be used with --dht_bootstrap_host", - type=int, default=4000) - parser.add_argument("--disable_upnp", - help="Don't try to use UPnP to enable incoming connections through the firewall", - action="store_true") - parser.add_argument("--data_dir", - help=("The full path to the directory in which lbrynet data and metadata will be stored. " - "Default: ~/.lbrynet on linux, ~/Library/Application Support/lbrynet on OS X"), - type=str) - parser.add_argument("--lbrycrdd_path", - help="The path to lbrycrdd, which will be launched if it isn't running. If" - "this option is chosen, lbrycrdd will be used as the interface to the" - "blockchain. By default, a lightweight interface is used.") - parser.add_argument("--lbrycrd_wallet_dir", - help="The directory in which lbrycrd data will stored. Used if lbrycrdd is " - "launched by this application.") - parser.add_argument("--lbrycrd_wallet_conf", - help="The configuration file for the LBRYcrd wallet. Default: ~/.lbrycrd/lbrycrd.conf", - type=str) - - args = parser.parse_args() - - if args.no_dht_bootstrap: - bootstrap_nodes = [] - else: - bootstrap_nodes = [(args.dht_bootstrap_host, args.dht_bootstrap_port)] - - if args.no_listen_peer: - peer_port = None - else: - peer_port = args.peer_port - - if args.no_listen_dht: - dht_node_port = None - else: - dht_node_port = args.dht_node_port - - created_data_dir = False - if not args.data_dir: - if sys.platform == "darwin": - data_dir = user_data_dir("LBRY") - else: - data_dir = os.path.join(os.path.expanduser("~"), ".lbrynet") - else: - data_dir = args.data_dir - if not os.path.exists(data_dir): - os.mkdir(data_dir) - created_data_dir = True - - daemon = LBRYAPIClient.config() - 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" - - webbrowser.open("http://localhost:5279") - - 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) - - - console = Console(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) - d.addErrback(lambda _: reactor.stop()) - reactor.addSystemEventTrigger('before', 'shutdown', console.shut_down) - reactor.run() - -if __name__ == "__main__": - launch_lbry_console() diff --git a/lbrynet/lbrynet_console/ConsoleControl.py b/lbrynet/lbrynet_console/ConsoleControl.py deleted file mode 100644 index be52da843..000000000 --- a/lbrynet/lbrynet_console/ConsoleControl.py +++ /dev/null @@ -1,176 +0,0 @@ -from twisted.protocols import basic -from twisted.internet import defer -import logging - - -log = logging.getLogger(__name__) - - -class ConsoleControl(basic.LineReceiver): - from os import linesep as delimiter - - def __init__(self): - self.connected = False - self.buffer = [] - self.command_handlers = {} - self.current_handler = None - - def start(self, command_handlers): - self.command_handlers = {h.command: h for h in command_handlers} - self.current_handler = None - self.send_initial_prompt() - return defer.succeed(True) - - def connectionMade(self): - self.connected = True - if self.buffer: - self.send(self.buffer) - self.buffer = [] - - def send_initial_prompt(self): - self.sendLine("") - self.sendLine("You should have received 1000 LBC the first time you ran\n" - "this program. If you did not, let us know! But first give\n" - "them a moment to show up. The block time is currently 30\n" - "seconds so they should show up within a couple of minutes.\n\n" - "Welcome to lbrynet-console!") - self.sendLine("") - self.sendLine("Enter a command. Try 'get wonderfullife' or 'help' to see more options.") - self.show_prompt() - - def send(self, s): - self.transport.write(s) - - def write(self, s): - if self.connected is False: - self.buffer.append(s) - else: - self.send(s) - - def flush(self): - if self.connected is True and self.buffer: - self.send(self.buffer) - self.buffer = [] - - def show_prompt(self): - self.send("> ") - - def show_quick_help(self): - self.sendLine("Available commands:") - self.sendLine("") - showed_help_all = False - sorted_handlers = sorted(self.command_handlers.items(), key=lambda x: x[0]) - sorted_handlers = sorted(sorted_handlers, key=lambda x: x[1].priority, reverse=True) - for command, handler in sorted_handlers: - if handler.priority > 0: - if showed_help_all is False and handler.priority < 10: - self.sendLine("help-all - Show the full list of available commands") - showed_help_all = True - self.sendLine(command + " - " + handler.short_help) - self.sendLine("") - self.sendLine("For more information about any command type 'help '") - - def show_full_help(self): - self.sendLine("Available commands:") - self.sendLine("") - for command, handler in sorted(self.command_handlers.items(), key=lambda x: x[0]): - self.sendLine(command + " - " + handler.short_help) - self.sendLine("") - self.sendLine("For more information about any command type 'help '") - - def handler_done(self): - self.current_handler = None - self.show_prompt() - - def handler_failed(self, err): - self.current_handler = None - self.sendLine("An error occurred:") - self.sendLine(err.getTraceback()) - self.show_prompt() - - def lineReceived(self, line): - if not self.command_handlers: - return - if self.current_handler is None: - words = line.split() - if len(words) == 0: - self.show_prompt() - return - command, args = words[0], words[1:] - if command == "help": - if len(args) == 0: - self.show_quick_help() - self.show_prompt() - return - if args[0] in self.command_handlers: - self.sendLine(self.command_handlers[args[0]].full_help) - self.show_prompt() - return - if args[0] == "help-all": - self.sendLine("Show the full list of available commands!") - self.show_prompt() - return - self.sendLine("Can't help you with '%s'. Sorry!" % args[0]) - self.show_prompt() - return - elif command == "help-all": - self.show_full_help() - self.show_prompt() - return - if command in self.command_handlers: - command_handler = self.command_handlers[command] - else: - candidates = [k for k in self.command_handlers.keys() if k.startswith(command)] - if len(candidates) == 0: - self.sendLine("Unknown command. Type 'help' for a list of commands.") - self.show_prompt() - return - if len(candidates) >= 2: - l = "Ambiguous command. Matches: " - for candidate in candidates: - l += candidate - l += ", " - l = l[:-2] - l += l - self.sendLine(l) - self.show_prompt() - return - else: - command_handler = self.command_handlers[candidates[0]] - try: - self.current_handler = command_handler.get_handler(self) - except: - self.current_handler = None - import traceback - self.sendLine(traceback.format_exc()) - log.error(traceback.format_exc()) - self.show_prompt() - return - try: - self.current_handler.start(*args) - except TypeError: - self.current_handler = None - self.sendLine("Invalid arguments. Type 'help ' for the argument list.") - import traceback - log.error(traceback.format_exc()) - self.show_prompt() - return - except: - self.current_handler = None - import traceback - self.sendLine(traceback.format_exc()) - log.error(traceback.format_exc()) - self.show_prompt() - return - self.current_handler.finished_deferred.addCallbacks(lambda _: self.handler_done(), - self.handler_failed) - else: - try: - self.current_handler.handle_line(line) - except Exception as e: - self.current_handler = None - import traceback - self.sendLine(traceback.format_exc()) - log.error(traceback.format_exc()) - self.show_prompt() - return \ No newline at end of file diff --git a/lbrynet/lbrynet_console/ControlHandlers.py b/lbrynet/lbrynet_console/ControlHandlers.py deleted file mode 100644 index 547b1ef3a..000000000 --- a/lbrynet/lbrynet_console/ControlHandlers.py +++ /dev/null @@ -1,2626 +0,0 @@ -import logging - -from zope.interface import implements -from lbrynet.core.PaymentRateManager import PaymentRateManager -from lbrynet.lbryfilemanager.EncryptedFileCreator import create_lbry_file -from lbrynet.lbryfilemanager.EncryptedFileDownloader import ManagedEncryptedFileDownloader -from lbrynet.lbryfile.StreamDescriptor import publish_sd_blob, create_plain_sd -from lbrynet.lbrynet_console.interfaces import ICommandHandler, ICommandHandlerFactory -from lbrynet.core.StreamDescriptor import download_sd_blob -from lbrynet.core.Error import UnknownNameError, InvalidBlobHashError, InsufficientFundsError -from lbrynet.core.Error import InvalidStreamInfoError -from lbrynet.core.utils import is_valid_blobhash -from twisted.internet import defer, threads -import datetime -import os - - -log = logging.getLogger(__name__) - - -class InvalidChoiceError(Exception): - pass - - -class InvalidValueError(Exception): - pass - - -#class ControlHandlerFactory(object): -# implements(IControlHandlerFactory) - -# control_handler_class = None - -# def get_prompt_description(self): -# return self.control_handler_class.prompt_description - -# def __init__(self, *args): -# self.args = args - -# def get_handler(self): -# args = self.args -# return self.control_handler_class(*args) - - -#class ControlHandler(object): -# implements(IControlHandler) - -# prompt_description = None - - -def get_log_file(): - log_file = "console.log" - logging_handlers = logging.getLogger().handlers - if len(logging_handlers): - log_file = logging_handlers[0].baseFilename - return log_file - - -class RoundedTime(object): - SECOND = 0 - MINUTE = 1 - HOUR = 2 - DAY = 3 - WEEK = 4 - units = ['second', 'minute', 'hour', 'day', 'week'] - - def __init__(self, unit, val): - assert unit < len(self.units) - self.unit = unit - self.val = val - - def __str__(self): - assert self.unit < len(self.units) - unit_str = self.units[self.unit] - if self.val != 1: - unit_str += "s" - return "%d %s" % (self.val, unit_str) - - -def get_time_behind_blockchain(best_block_time): - best_time = datetime.datetime.utcfromtimestamp(best_block_time) - diff = datetime.datetime.utcnow() - best_time - if diff.days > 0: - if diff.days >= 7: - val = diff.days // 7 - unit = RoundedTime.WEEK - else: - val = diff.days - unit = RoundedTime.DAY - elif diff.seconds >= 60 * 60: - val = diff.seconds // (60 * 60) - unit = RoundedTime.HOUR - elif diff.seconds >= 60: - val = diff.seconds // 60 - unit = RoundedTime.MINUTE - else: - val = diff.seconds - unit = RoundedTime.SECOND - return RoundedTime(unit, val) - - -class CommandHandlerFactory(object): - implements(ICommandHandlerFactory) - priority = 0 - short_help = "This should be overridden" - full_help = "This should really be overridden" - command = "this-must-be-overridden" - control_handler_class = None - - def __init__(self, *args): - self.args = args - - def get_prompt_description(self): - return self.control_handler_class.prompt_description - - def get_handler(self, console): - return self.control_handler_class(console, *self.args) # pylint: disable=not-callable - - -class CommandHandler(object): - implements(ICommandHandler) - - prompt_description = None - - def __init__(self, console): - self.console = console - self.finished_deferred = defer.Deferred() - - def start(self): - pass - - def handle_line(self, line): - pass - - -def get_shortcuts_for_options(option_names): - shortcut_keys = [] - names_with_shortcuts = [] - for option_name in option_names: - name_with_shortcut = '' - found_shortcut = False - for c in option_name: - if not found_shortcut and not c.lower() in shortcut_keys: - name_with_shortcut += '[' + c.lower() + ']' - shortcut_keys.append(c.lower()) - found_shortcut = True - else: - name_with_shortcut += c - if found_shortcut is False: - shortcut_keys.append("") - names_with_shortcuts.append(name_with_shortcut) - return shortcut_keys, names_with_shortcuts - - -class RecursiveCommandHandler(CommandHandler): - - def __init__(self, console, exit_after_one_done=False, reset_after_each_done=False): - CommandHandler.__init__(self, console) - self.current_handler = None - self.exit_after_one_done = exit_after_one_done - self.reset_after_each_done = reset_after_each_done - self._set_control_handlers() - - def _get_control_handler_factories(self): - raise NotImplementedError() - - def _set_control_handlers(self): - self.control_handlers = {i + 1: handler for i, handler in enumerate(self._get_control_handler_factories())} - - def start(self): - self._show_prompt() - - def handler_finished(self): - self.current_handler = None - if self.exit_after_one_done is True: - self.finished_deferred.callback(None) - else: - if self.reset_after_each_done: - self._set_control_handlers() - self._show_prompt() - - def handler_failed(self, err): - log.error("An error occurred in some handler: %s", err.getTraceback()) - self.finished_deferred.callback(None) - - def handle_line(self, line): - if self.current_handler is None: - if line is None: - num = None - else: - try: - num = int(line) - except ValueError: - num = None - if num == 0: - self.finished_deferred.callback(None) - return - if num in self.control_handlers: - self.current_handler = self.control_handlers[num].get_handler(self.console) - self.current_handler.finished_deferred.addCallbacks(lambda _: self.handler_finished(), - self.handler_failed) - self.current_handler.start() - return - if self.current_handler is not None: - self.current_handler.handle_line(line) - return - if self.current_handler is None: - self._show_prompt() - - def _show_prompt(self): - prompt_string = "Options:\n" - prompt_string += "[0] Exit this menu\n" - for num, handler in self.control_handlers.iteritems(): - prompt_string += "[" + str(num) + "] " + handler.get_prompt_description() + "\n" - self.console.sendLine(prompt_string) - - -class ModifyPaymentRate(CommandHandler): - - def __init__(self, console): - CommandHandler.__init__(self, console) - self._prompt_choices = {'cancel': (self._cancel, "Don't change anything")} - self.got_input = False - - def start(self): - self._show_prompt_string() - - def handle_line(self, line): - if self.got_input is False: - self.got_input = True - if line.lower() in self._prompt_choices: - d = self._prompt_choices[line.lower()][0]() - d.addCallback(self._choice_made) - else: - try: - rate = float(line) - except ValueError: - self.console.sendLine("Rate must be a number") - self.finished_deferred.callback(None) - return - d = self._set_rate(rate) - - d.addCallback(lambda _: self._choice_made("Successfully set the rate")) - - @staticmethod - def _cancel(): - return defer.succeed("No change was made") - - def _set_rate(self, rate): - pass - - def _get_current_status(self): - pass - - def _choice_made(self, result=None): - if result is not None: - self.console.sendLine(result) - self.finished_deferred.callback(None) - - def _show_prompt_string(self): - prompt_string = self._get_current_status() + "\n" - for prompt_choice, (func, help_string) in self._prompt_choices.iteritems(): - prompt_string += prompt_choice + ": " + help_string + "\n" - prompt_string += "To change the current rate, enter the desired rate\n" - prompt_string += "Then hit enter\n" - self.console.sendLine(prompt_string) - - -class ApplicationStatus(CommandHandler): - #prompt_description = "Application Status" - - def __init__(self, console, rate_limiter, dht_node): - CommandHandler.__init__(self, console) - self.rate_limiter = rate_limiter - self.dht_node = dht_node - - def start(self): - d = self._show_status() - d.chainDeferred(self.finished_deferred) - return d - - def _show_status(self): - status = "Total bytes uploaded: " + str(self.rate_limiter.total_ul_bytes) + "\n" - status += "Total bytes downloaded: " + str(self.rate_limiter.total_dl_bytes) + "\n" - if self.dht_node is not None: - status += "Approximate number of nodes in DHT: " + str(self.dht_node.getApproximateTotalDHTNodes()) + "\n" - status += "Approximate number of blobs in DHT: " + str(self.dht_node.getApproximateTotalHashes()) + "\n" - self.console.sendLine(status) - return defer.succeed(None) - - -class ApplicationStatusFactory(CommandHandlerFactory): - control_handler_class = ApplicationStatus - command = "application-status" - short_help = "Show application status" - full_help = "Show total bytes uploaded to other peers, total bytes downloaded from peers," \ - " approximate number of nodes in the DHT, and approximate number of hashes" \ - " in the DHT" - - -class GetWalletBalances(CommandHandler): - #prompt_description = "Show wallet point balances" - - def __init__(self, console, wallet): - CommandHandler.__init__(self, console) - self.wallet = wallet - - def start(self): - d = self._get_wallet_balances() - d.chainDeferred(self.finished_deferred) - return d - - #def handle_line(self, line): - # assert line is None, "Show wallet balances should not be passed any arguments" - # return True, self._get_wallet_balances() - - def _show_time_behind_blockchain(self, rounded_time): - if rounded_time.unit >= RoundedTime.HOUR: - self.console.sendLine("\n\nYour balance may be out of date. This application\n" - "is %s behind the LBC blockchain. It may take a few minutes to\n" - "catch up the first time you run this early version of LBRY.\n" - "Please be patient =).\n\n" % str(rounded_time)) - else: - self.console.sendLine("") - - def _log_recent_blocktime_error(self, err): - log.error("An error occurred looking up the most recent blocktime: %s", err.getTraceback()) - self.console.sendLine("") - - def _get_wallet_balances(self): - d = self.wallet.get_balance() - - def format_balance(balance): - if balance == 0: - balance = 0 - balance_string = "balance: " + str(balance) + " LBC" - self.console.sendLine(balance_string) - d = self.wallet.get_most_recent_blocktime() - d.addCallback(get_time_behind_blockchain) - d.addCallback(self._show_time_behind_blockchain) - d.addErrback(self._log_recent_blocktime_error) - return d - - d.addCallback(format_balance) - return d - - -class GetWalletBalancesFactory(CommandHandlerFactory): - control_handler_class = GetWalletBalances - priority = 10 - command = "balance" - short_help = "Show LBRYcrd balance" - full_help = "Show the LBRYcrd balance of the wallet to which this application is connected" - - -class GetNewWalletAddress(CommandHandler): - #prompt_description = "Get a new LBRYcrd address" - - def __init__(self, console, wallet): - CommandHandler.__init__(self, console) - self.wallet = wallet - - def start(self): - d = self._get_new_address() - d.chainDeferred(self.finished_deferred) - return d - - def _get_new_address(self): - #assert line is None, "Get new LBRYcrd address should not be passed any arguments" - d = self.wallet.get_new_address() - - def show_address(address): - self.console.sendLine(str(address)) - - d.addCallback(show_address) - return d - - -class GetNewWalletAddressFactory(CommandHandlerFactory): - control_handler_class = GetNewWalletAddress - command = "get-new-address" - short_help = "Get a new LBRYcrd address" - full_help = "Get a new LBRYcrd address from the wallet to which this application is connected" - - -class ShutDown(CommandHandler): - #prompt_description = "Shut down" - - def __init__(self, console, lbry_service): - CommandHandler.__init__(self, console) - self.lbry_service = lbry_service - - def start(self): - d = self._shut_down() - return d - - #def handle_line(self, line): - # assert line is None, "Shut down should not be passed any arguments" - # return True, self._shut_down() - - def _shut_down(self): - #d = self.lbry_service.shut_down() - - #def stop_reactor(): - from twisted.internet import reactor - self.console.sendLine("Shutting down.") - reactor.stop() - - #d.addBoth(lambda _: stop_reactor()) - return defer.succeed(True) - - -class ShutDownFactory(CommandHandlerFactory): - control_handler_class = ShutDown - priority = 5 - command = "exit" - short_help = "Shut down" - full_help = "Shut down" - - -class EncryptedFileStatus(CommandHandler): - #prompt_description = "Print status information for all LBRY Files" - - def __init__(self, console, lbry_file_manager): - CommandHandler.__init__(self, console) - self.lbry_file_manager = lbry_file_manager - - def start(self): - d = self.lbry_file_manager.get_lbry_file_status_reports() - d.addCallback(self._show_statuses) - d.chainDeferred(self.finished_deferred) - return d - - #def handle_line(self, line): - # assert line is None, "print status should not be passed any arguments" - # d = self.lbry_file_manager.get_lbry_file_status_reports() - # d.addCallback(self.format_statuses) - # return True, d - - def _show_statuses(self, status_reports): - status_strings = [] - for status_report in status_reports: - s = status_report.name + " status: " + status_report.running_status + "\n" - s += str(status_report.num_completed) + " completed out of " + str(status_report.num_known) + "\n" - status_strings.append(s) - self.console.sendLine(''.join(status_strings)) - - -class EncryptedFileStatusFactory(CommandHandlerFactory): - control_handler_class = EncryptedFileStatus - command = "lbryfile-status" - short_help = "Print status information for LBRY files" - full_help = "Print the status information for all streams that are being saved to disk." \ - "This includes whether the stream is currently downloading and the progress" \ - "of the download." - - -class AddStream(CommandHandler): - #prompt_description = None - #line_prompt = None - cancel_prompt = "Trying to locate the stream's metadata. Type \"cancel\" to cancel..." - canceled_message = "Canceled downloading." - - def __init__(self, console, sd_identifier, base_payment_rate_manager, wallet): - CommandHandler.__init__(self, console) - self.sd_identifier = sd_identifier - self.wallet = wallet - self.loading_metadata_deferred = None - self.metadata = None - self.factory = None - self.factory_choice_strings = None # (command, command_string, shortcut) - self.factory_choices = None # {command: factory} - self.download_options = [] - self.options_left = [] - self.options_chosen = [] - self.current_option = None - self.current_choice = None - self.got_options_response = False - self.loading_failed = False - self.payment_rate_manager = PaymentRateManager(base_payment_rate_manager) - - def start(self): - self.console.sendLine(self.cancel_prompt) - 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) - - def handle_line(self, line): - # first, print that metadata is being looked up. give the option to cancel, and - # listen for the word cancel - # when that's done, present the metadata, how to change options, how to cancel, - # and list the ways to download - # - # - #if line is None: - # return False, defer.succeed(self.line_prompt) - #if self.loading_failed is True: - # return True, None - if self.loading_metadata_deferred is not None: - if line.lower() == "cancel": - self.loading_metadata_deferred.cancel() - self.loading_metadata_deferred = None - else: - self.console.sendLine(self.cancel_prompt) - return - - #if self.metadata is None: - # self.loading_metadata_deferred = self._load_metadata(line) - # cancel_prompt_d = defer.succeed(self.cancel_prompt) - # self.loading_metadata_deferred.addCallback(self._choose_factory) - # self.loading_metadata_deferred.addErrback(self._handle_load_canceled) - # self.loading_metadata_deferred.addErrback(self._handle_load_failed) - # return False, cancel_prompt_d, self.loading_metadata_deferred - - if self.current_option is not None: - if self.current_choice is None: - try: - self.current_choice = self._get_choice_from_input(line) - except InvalidChoiceError: - self.console.sendLine(self._get_next_option_prompt(invalid_choice=True)) - return - choice = self.current_option.option_types[self.current_choice] - if choice.value == float or choice.value == bool: - self.console.sendLine(self._get_choice_value_prompt()) - return - else: - value = choice.value - else: - try: - value = self._get_value_for_choice(line) - except InvalidValueError: - self.console.sendLine(self._get_choice_value_prompt(invalid_value=True)) - return - self.options_chosen.append(value) - self.current_choice = None - self.current_option = None - self.options_left = self.options_left[1:] - if self.options_left: - self.console.sendLine(self._get_next_option_prompt()) - return - else: - self.current_option = None - self._show_factory_choices() - return - if self.factory_choice_strings is not None: - command = self._get_factory_choice_command(line) - if command == "cancel": - self.console.sendLine(self.canceled_message) - self.finished_deferred.callback(None) - elif command == "options": - self.options_left = self.download_options[:] - self.options_chosen = [] - self.console.sendLine(self._get_next_option_prompt()) - else: - if command in self.factory_choices: - self.factory = self.factory_choices[command] - self._start_download() - self.console.sendLine("Downloading in the background. Use the command 'status'\n" - "to check the status of the download.") - self.finished_deferred.callback(None) - else: - self._show_factory_choices() - return - - #if self.factory is None: - # try: - # choice = int(line) - # except ValueError: - # return False, defer.succeed(self._show_factory_choices()) - # if choice in xrange(len(self.metadata.factories)): - # self.factory = self.metadata.factories[choice] - # return False, defer.succeed(self._show_info_and_options()) - # else: - # return False, defer.succeed(self._show_factory_choices()) - #if self.got_options_response is False: - # self.got_options_response = True - # if line == 'y' or line == 'Y' and self.options_left: - # return False, defer.succeed(self._get_next_option_prompt()) - # else: - # self.options_chosen = [option.default_value for option in self.options_left] - # self.options_left = [] - # return False, defer.succeed(self.line_prompt3) - - #if line == 'y' or line == 'Y': - # d = self._start_download() - #else: - # d = defer.succeed("Download cancelled") - #return True, d - - def _get_choice_from_input(self, line): - try: - choice_num = int(line) - except ValueError: - raise InvalidChoiceError() - if 0 <= choice_num < len(self.current_option.option_types): - return choice_num - raise InvalidChoiceError() - - def _get_factory_choice_command(self, line): - for command, printed_command, shortcut in self.factory_choice_strings: - if line == command or line == shortcut: - return command - - def _load_metadata(self, sd_file): - return defer.fail(NotImplementedError()) - - def _handle_load_canceled(self, err): - err.trap(defer.CancelledError) - self.console.sendLine(self.canceled_message) - self.finished_deferred.callback(None) - - def _handle_load_failed(self, err): - self.loading_failed = True - log.error("An exception occurred attempting to load the stream descriptor: %s", err.getTraceback()) - log_file = get_log_file() - self.console.sendLine("An unexpected error occurred attempting to load the stream's metadata.\n" - "See %s for further details.\n\n" % log_file) - self.finished_deferred.callback(None) - - def _handle_metadata(self, metadata): - self.loading_metadata_deferred = None - self.metadata = metadata - self.factory_choices = {} - for factory in self.metadata.factories: - self.factory_choices[factory.get_description()] = factory - self.download_options = self.metadata.options.get_downloader_options(self.metadata.validator, - self.payment_rate_manager) - self.options_chosen = [option.default_value for option in self.download_options] - self.factory_choice_strings = [] - factory_choice_names = ['cancel'] - if self.download_options: - factory_choice_names.append('options') - factory_choice_names += self.factory_choices.keys() - shortcuts, names_with_shortcuts = get_shortcuts_for_options(factory_choice_names) - self.factory_choice_strings = zip(factory_choice_names, names_with_shortcuts, shortcuts) - #if len(self.metadata.factories) == 1: - # self.factory = self.metadata.factories[0] - # return self._show_info_and_options() - self._show_info_and_options() - return self._show_factory_choices() - - def _get_estimated_cost_string(self): - estimated_cost_string = "unknown LBC" - for option, option_value in zip(self.download_options, self.options_chosen): - if option.short_description == "data payment rate": - if option_value == None: - rate = 0.0 - else: - rate = option_value - stream_size = None - for field, val in self.metadata.validator.info_to_show(): - if field == "stream_size": - stream_size = int(val) - if stream_size is not None and rate is not None: - estimated_cost_string = str(stream_size * 1.0 / 2**20 * rate) + " LBC" - return estimated_cost_string - - def _show_factory_choices(self): - prompt = "\n" - prompt += "Estimated cost: " + self._get_estimated_cost_string() - prompt += "\n\n" - for factory_choice_string in self.factory_choice_strings: - prompt += factory_choice_string[1] + '\n' - self.console.sendLine(str(prompt)) - - def _show_info_and_options(self): - #self.download_options = self.metadata.options.get_downloader_options(self.metadata.validator, - # self.payment_rate_manager) - prompt = "Stream info:\n" - for field_name, value in self._get_info_to_show(): - if field_name == "stream_size": - value = str(self._get_formatted_stream_size(int(value))) - prompt += field_name + ": " + value + "\n" - prompt += "\nOptions:\n" - for option in self.download_options: - prompt += option.long_description + ": " + str(option.default_value_description) + "\n" - self.console.sendLine(str(prompt)) - - @staticmethod - def _get_formatted_stream_size(stream_size): - if isinstance(stream_size, (int, long)): - if stream_size >= 2**40: - units = "TB" - factor = 2**40 - elif stream_size >= 2**30: - units = "GB" - factor = 2**30 - elif stream_size >= 2**20: - units = "MB" - factor = 2**20 - elif stream_size >= 2**10: - units = "KB" - factor = 2**10 - else: - return str(stream_size) + " B" - return "%.1f %s" % (round((stream_size * 1.0 / factor), 1), units) - return stream_size - - def _get_info_to_show(self): - return self.metadata.validator.info_to_show() - - def _get_list_of_option_types(self): - options_string = "" - for i, option_type in enumerate(self.current_option.option_types): - options_string += "[%s] %s\n" % (str(i), option_type.long_description) - options_string += "Enter choice:" - return options_string - - def _get_choice_value_prompt(self, invalid_value=False): - choice = self.current_option.option_types[self.current_choice] - choice_string = "" - if invalid_value is True: - "Invalid value entered. Try again.\n" - if choice.short_description is not None: - choice_string += choice.short_description + "\n" - if choice.value == float: - choice_string += "Enter floating point number (e.g. 1.0):" - elif choice.value == bool: - true_string = "Yes" - false_string = "No" - if choice.bool_options_description is not None: - true_string, false_string = choice.bool_options_description - choice_string += "[0] %s\n[1] %s\nEnter choice:" % (true_string, false_string) - else: - NotImplementedError() - return choice_string - - def _get_value_for_choice(self, choice_input): - choice = self.current_option.option_types[self.current_choice] - if choice.value == float: - try: - return float(choice_input) - except ValueError: - raise InvalidValueError() - elif choice.value == bool: - if choice_input == "0": - return True - elif choice_input == "1": - return False - raise InvalidValueError() - raise NotImplementedError() - - def _get_next_option_prompt(self, invalid_choice=False): - assert len(self.options_left), "Something went wrong. There were no options left" - self.current_option = self.options_left[0] - choice_string = "" - if invalid_choice is True: - choice_string += "Invalid response entered. Try again.\n" - - choice_string += self.current_option.long_description + "\n" - if len(self.current_option.option_types) > 1: - choice_string += self._get_list_of_option_types() - elif len(self.current_option.option_types) == 1: - self.current_choice = 0 - choice_string += self._get_choice_value_prompt() - return choice_string - - def _start_download(self): - d = self._make_downloader() - - def do_download(stream_downloader): - d = stream_downloader.start() - d.addCallback(lambda result: self._download_succeeded(stream_downloader, result)) - return d - - d.addCallback(do_download) - d.addErrback(self._handle_download_error) - return d - - def _download_succeeded(self, stream_downloader, result): - self.console.sendLine("%s: %s." % (str(stream_downloader), str(result))) - - def _handle_download_error(self, err): - if err.check(InsufficientFundsError): - self.console.sendLine("Download stopped due to insufficient funds.") - d = self.wallet.get_most_recent_blocktime() - 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() - self.console.sendLine("An unexpected error has caused the download to stop:\n%s\n\nSee %s for further details." % (err.getErrorMessage(), log_file)) - - def _make_downloader(self): - return self.factory.make_downloader(self.metadata, self.options_chosen, - self.payment_rate_manager) - - def _show_time_behind_blockchain_download(self, rounded_time): - if rounded_time.unit >= RoundedTime.HOUR: - self.console.sendLine("\nThis application is %s behind the LBC blockchain, so some of your\n" - "funds may not be available. Use 'get-blockchain-status' to check if\n" - "your application is up to date with the blockchain.\n\n" - "It may take a few minutes to catch up the first time you run this\n" - "early version of LBRY. Please be patient =).\n\n" % str(rounded_time)) - - 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" - #line_prompt = "Stream descriptor file name:" - - def start(self, sd_file): - self.loading_metadata_deferred = self.sd_identifier.get_metadata_for_sd_file(sd_file) - return AddStream.start(self) - - -class AddStreamFromSDFactory(CommandHandlerFactory): - control_handler_class = AddStreamFromSD - command = "get-sd" - short_help = "Download a stream from a plaintext stream descriptor file" - full_help = "Download a stream from a plaintext stream descriptor file.\n" \ - "Takes one argument, the filename of the stream descriptor.\n\n" \ - "get-sd " - - -class AddStreamFromHash(AddStream): - #prompt_description = "Add a stream from a hash" - #line_prompt = "Stream descriptor hash:" - - def __init__(self, console, sd_identifier, session, wallet): - AddStream.__init__(self, console, sd_identifier, session.base_payment_rate_manager, wallet) - self.session = session - - def start(self, sd_hash): - self.loading_metadata_deferred = download_sd_blob(self.session, sd_hash, - self.payment_rate_manager) - self.loading_metadata_deferred.addCallback(self.sd_identifier.get_metadata_for_sd_blob) - AddStream.start(self) - - def _handle_load_failed(self, err): - self.loading_failed = True - if err.check(InvalidBlobHashError): - self.console.sendLine("The hash you entered is invalid. It must be 96 characters long" - " and contain only hex characters.\n\n") - self.finished_deferred.callback(None) - return - if err.check(InsufficientFundsError): - self.console.sendLine("Insufficient funds to download the metadata blob.") - d = self.wallet.get_most_recent_blocktime() - 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 - return AddStream._handle_load_failed(self, err) - - -class AddStreamFromHashFactory(CommandHandlerFactory): - control_handler_class = AddStreamFromHash - command = "get-hash" - short_help = "Download a stream from a hash" - full_help = "Download a stream from the hash of the stream descriptor. The stream " \ - "descriptor file will be downloaded from LBRYnet and then read.\n" \ - "Takes one argument, the sha384 hashsum of the stream descriptor.\n\n" \ - "get-hash " - - -class AddStreamFromLBRYcrdName(AddStreamFromHash): - #prompt_description = "Add a stream from a short name" - #line_prompt = "Short name:" - - def __init__(self, console, sd_identifier, session, wallet): - AddStreamFromHash.__init__(self, console, sd_identifier, session, wallet) - self.wallet = wallet - self.resolved_name = None - self.description = None - self.key_fee = None - self.key_fee_address = None - self.name = None - - def start(self, name): - self.name = name - self.loading_metadata_deferred = self._resolve_name(name) - self.loading_metadata_deferred.addCallback(lambda stream_hash: download_sd_blob(self.session, - stream_hash, - self.payment_rate_manager)) - self.loading_metadata_deferred.addCallback(self.sd_identifier.get_metadata_for_sd_blob) - AddStream.start(self) - - def _resolve_name(self, name): - def get_name_from_info(stream_info): - if 'stream_hash' not in stream_info: - raise InvalidStreamInfoError(name, stream_info) - self.resolved_name = stream_info.get('name', None) - self.description = stream_info.get('description', None) - try: - if 'key_fee' in stream_info: - self.key_fee = float(stream_info['key_fee']) - except ValueError: - self.key_fee = None - self.key_fee_address = stream_info.get('key_fee_address', None) - return stream_info['stream_hash'] - d = self.wallet.get_most_recent_blocktime() - d.addCallback(get_time_behind_blockchain) - d.addCallback(self._show_time_behind_blockchain_resolve) - d.addErrback(self._log_recent_blockchain_time_error_resolve) - d.addCallback(lambda _: self.wallet.get_stream_info_for_name(name)) - d.addCallback(get_name_from_info) - return d - - def _show_time_behind_blockchain_resolve(self, rounded_time): - if rounded_time.unit >= RoundedTime.HOUR: - self.console.sendLine("\nThis application is %s behind the LBC blockchain, which may be\n" - "preventing this name from being resolved correctly. Use 'get-blockchain-status'\n" - "to check if your application is up to date with the blockchain.\n\n" - "It may take a few minutes to catch up the first time you run\n" - "this early version of LBRY. Please be patient =).\n\n" % str(rounded_time)) - else: - self.console.sendLine("\n") - - def _log_recent_blockchain_time_error_resolve(self, err): - log.error("An error occurred trying to look up the most recent blocktime: %s", err.getTraceback()) - - def _handle_load_failed(self, err): - self.loading_failed = True - if err.check(UnknownNameError): - if is_valid_blobhash(self.name): - self.loading_failed = False - self.loading_metadata_deferred = None - AddStreamFromHash.start(self, self.name) - return - else: - self.console.sendLine("The name %s could not be found." % err.getErrorMessage()) - self.finished_deferred.callback(True) - return - elif err.check(InvalidBlobHashError): - self.console.sendLine("The metadata for this name is invalid. The stream cannot be downloaded.\n\n") - self.finished_deferred.callback(None) - return - return AddStreamFromHash._handle_load_failed(self, err) - - def _start_download(self): - d = self._pay_key_fee() - d.addCallback(lambda _: AddStream._start_download(self)) - return d - - 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) - return defer.succeed(True) - - def _get_info_to_show(self): - i = AddStream._get_info_to_show(self) - if self.description is not None: - 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: - i.append(("decryption key fee", str(self.key_fee))) - i.append(("address to pay key fee", str(self.key_fee_address))) - return i - - -class AddStreamFromLBRYcrdNameFactory(CommandHandlerFactory): - control_handler_class = AddStreamFromLBRYcrdName - priority = 100 - command = "get" - short_help = "Download a stream from a name" - full_help = "Download a stream associated with a name on the LBRYcrd blockchain. The name will be" \ - " looked up on the blockchain, and if it is associated with a stream descriptor hash," \ - " that stream descriptor will be downloaded and read. If the given name is itself a valid " \ - "hash, and the name doesn't exist on the blockchain, then the name will be used as the " \ - "stream descriptor hash as in get-hash. Use get-hash if you want no ambiguity.\n" \ - "Takes one argument, the name.\n\n" \ - "Usage: get " - - -class EncryptedFileChooser(RecursiveCommandHandler): - - def __init__(self, console, lbry_file_manager, factory_class, *args, **kwargs): - """ - @param lbry_file_manager: - - @param factory_class: - - @param args: all arguments that will be passed to the factory - - @param kwargs: all arguments that will be passed to the superclass' __init__ - - @return: - """ - self.lbry_file_manager = lbry_file_manager - self.factory_class = factory_class - self.args = args - RecursiveCommandHandler.__init__(self, console, **kwargs) - - def _get_control_handler_factories(self): - control_handler_factories = [] - for lbry_file in self.lbry_file_manager.lbry_files: - control_handler_factories.append(self.factory_class(self.console, lbry_file, *self.args)) - return control_handler_factories - - -class EncryptedFileChooserFactory(CommandHandlerFactory): - def get_prompt_description(self): - lbry_file = self.args[0] - return lbry_file.file_name - - -class DeleteEncryptedFileChooser(EncryptedFileChooser): - #prompt_description = "Delete LBRY File" - - def __init__(self, console, stream_info_manager, blob_manager, lbry_file_manager): - EncryptedFileChooser.__init__(self, console, lbry_file_manager, DeleteEncryptedFileFactory, - stream_info_manager, blob_manager, lbry_file_manager, - exit_after_one_done=True) - - -class DeleteEncryptedFileChooserFactory(CommandHandlerFactory): - control_handler_class = DeleteEncryptedFileChooser - command = "delete-lbryfile" - short_help = "Delete an LBRY file" - full_help = "Delete an LBRY file which has been downloaded or created by this application.\n" \ - "\nGives the option to also delete the encrypted chunks of data associated with " \ - "the file. If they are deleted, they will all have to be downloaded again if " \ - "lbrynet-console is asked to download that file again, and lbrynet-console will " \ - "not be able to upload those chunks of data to other peers on LBRYnet." - - -class DeleteEncryptedFile(CommandHandler): - #prompt_description = "Delete LBRY File" - delete_data_prompt = "Also delete data? (y/n): " - confirm_prompt = "Are you sure? (y/n): " - - def __init__(self, console, lbry_file, stream_info_manager, blob_manager, lbry_file_manager): - CommandHandler.__init__(self, console) - self.lbry_file = lbry_file - self.stream_info_manager = stream_info_manager - self.blob_manager = blob_manager - self.lbry_file_manager = lbry_file_manager - self.got_delete_data = False - self.delete_data = False - self.got_confirmation = False - - def start(self): - self.console.send(self.delete_data_prompt) - - def handle_line(self, line): - #if line is None: - # return False, defer.succeed(self.line_prompt) - if self.got_delete_data is False: - self.got_delete_data = True - if line.lower() in ['y', 'yes']: - self.delete_data = True - self.console.send(self.confirm_prompt) - return - if self.got_confirmation is False: - self.got_confirmation = True - if line.lower() in ['y', 'yes']: - d = self._delete_lbry_file() - - def show_done(): - self.console.sendLine("Successfully deleted " + str(self.lbry_file.stream_name)) - - def delete_failed(err): - self.console.sendLine("Deletion unsuccessful. Reason: %s" % err.getErrorMessage()) - - d.addCallbacks(lambda _: show_done(), delete_failed) - d.chainDeferred(self.finished_deferred) - else: - self.console.sendLine("Canceled deletion.") - self.finished_deferred.callback(None) - - def _delete_lbry_file(self): - d = self.lbry_file_manager.delete_lbry_file(self.lbry_file) - - def finish_deletion(): - if self.delete_data is True: - d = self.lbry_file.delete_data() - else: - d = defer.succeed(True) - d.addCallback(lambda _: self._delete_stream_data()) - return d - - d.addCallback(lambda _: finish_deletion()) - return d - - def _delete_stream_data(self): - s_h = self.lbry_file.stream_hash - d = self.lbry_file_manager.get_count_for_stream_hash(s_h) - # TODO: could possibly be a timing issue here - d.addCallback(lambda c: self.stream_info_manager.delete_stream(s_h) if c == 0 else True) - return d - - -class DeleteEncryptedFileFactory(EncryptedFileChooserFactory): - control_handler_class = DeleteEncryptedFile - - -class ToggleEncryptedFileRunningChooser(EncryptedFileChooser): - #prompt_description = "Toggle whether an LBRY File is running" - - def __init__(self, console, lbry_file_manager): - EncryptedFileChooser.__init__(self, console, lbry_file_manager, ToggleEncryptedFileRunningFactory, - lbry_file_manager, exit_after_one_done=True) - - -class ToggleEncryptedFileRunningChooserFactory(CommandHandlerFactory): - control_handler_class = ToggleEncryptedFileRunningChooser - command = "toggle-running" - short_help = "Toggle whether an LBRY file is running" - full_help = "Toggle whether an LBRY file, which is being saved by this application," \ - "is currently being downloaded." - - -class ToggleEncryptedFileRunning(CommandHandler): - #prompt_description = "Toggle whether an LBRY File is running" - - def __init__(self, console, lbry_file, lbry_file_manager): - CommandHandler.__init__(self, console) - self.lbry_file = lbry_file - self.lbry_file_manager = lbry_file_manager - - def start(self): - d = self.lbry_file_manager.toggle_lbry_file_running(self.lbry_file) - d.addErrback(self._handle_download_error) - self.finished_deferred.callback(None) - - @staticmethod - def _handle_download_error(err): - if err.check(InsufficientFundsError): - return "Download stopped due to insufficient funds." - else: - log.error("An unexpected error occurred due to toggling an LBRY file running. %s", err.getTraceback()) - log_file = "console.log" - if len(log.handlers): - log_file = log.handlers[0].baseFilename - return "An unexpected error occurred. See %s for details." % log_file - - -class ToggleEncryptedFileRunningFactory(EncryptedFileChooserFactory): - control_handler_class = ToggleEncryptedFileRunning - - -class CreateEncryptedFile(CommandHandler): - #prompt_description = "Create an LBRY File from file" - line_prompt = "File name: " - - def __init__(self, console, session, lbry_file_manager): - CommandHandler.__init__(self, console) - self.session = session - self.lbry_file_manager = lbry_file_manager - - def start(self, file_name): - d = create_lbry_file(self.session, self.lbry_file_manager, file_name, open(file_name)) - d.addCallback(self.add_to_lbry_files) - d.addCallback(lambda _: self.console.sendLine("Successfully created " + str(file_name))) - self.console.sendLine("Creating an LBRY file from " + str(file_name) + " in the background.") - self.finished_deferred.callback(None) - - def add_to_lbry_files(self, stream_hash): - prm = PaymentRateManager(self.session.base_payment_rate_manager) - d = self.lbry_file_manager.add_lbry_file(stream_hash, prm) - d.addCallback(self.set_status) - return d - - def set_status(self, lbry_file_downloader): - d = self.lbry_file_manager.change_lbry_file_status(lbry_file_downloader, - ManagedEncryptedFileDownloader.STATUS_FINISHED) - d.addCallback(lambda _: lbry_file_downloader.restore()) - return d - - -class CreateEncryptedFileFactory(CommandHandlerFactory): - control_handler_class = CreateEncryptedFile - command = "create-lbryfile" - short_help = "LBRYize a file" - full_help = "Encrypt a file, split it into chunks, and make those chunks available on LBRYnet. Also " \ - "create a 'stream descriptor file' which contains all of the metadata needed to download " \ - "the encrypted chunks from LBRYnet and put them back together. This plain stream descriptor " \ - "can be passed around via other file sharing methods like email. Additionally, this " \ - "application can publish the stream descriptor to LBRYnet so that the LBRY file can be " \ - "downloaded via the hash of the stream descriptor." - - -class PublishStreamDescriptorChooser(EncryptedFileChooser): - #prompt_description = "Publish a stream descriptor file to the DHT for an LBRY File" - - def __init__(self, console, stream_info_manager, blob_manager, lbry_file_manager): - EncryptedFileChooser.__init__(self, console, lbry_file_manager, PublishStreamDescriptorFactory, - stream_info_manager, blob_manager, lbry_file_manager, - exit_after_one_done=True) - - -class PublishStreamDescriptorChooserFactory(CommandHandlerFactory): - control_handler_class = PublishStreamDescriptorChooser - command = "release-lbryfile" - short_help = "Put a stream descriptor onto LBRYnet" - full_help = "Make a stream descriptor available on LBRYnet at its sha384 hashsum. If the stream " \ - "descriptor is made available on LBRYnet, anyone will be able to download it via its " \ - "hash via LBRYnet, and the LBRY file can then be downloaded if it is available." - - -class PublishStreamDescriptor(CommandHandler): - #prompt_description = "Publish a stream descriptor file to the DHT for an LBRY File" - - def __init__(self, console, lbry_file, stream_info_manager, blob_manager): - CommandHandler.__init__(self, console) - self.lbry_file = lbry_file - self.stream_info_manager = stream_info_manager - self.blob_manager = blob_manager - - def start(self): - d = publish_sd_blob(self.stream_info_manager, self.blob_manager, self.lbry_file.stream_hash) - d.addCallback(lambda sd_hash: self.console.sendLine(sd_hash)) - d.chainDeferred(self.finished_deferred) - - #def _publish_sd_blob(self): - # descriptor_writer = BlobStreamDescriptorWriter(self.blob_manager) - - # d = get_sd_info(self.stream_info_manager, self.lbry_file.stream_hash, True) - # d.addCallback(descriptor_writer.create_descriptor) - - # def add_sd_blob_to_stream(sd_blob_hash): - # d = self.stream_info_manager.save_sd_blob_hash_to_stream(self.lbry_file.stream_hash, sd_blob_hash) - # d.addCallback(lambda _: sd_blob_hash) - # return d - - # d.addCallback(add_sd_blob_to_stream) - # return d - - -class PublishStreamDescriptorFactory(EncryptedFileChooserFactory): - control_handler_class = PublishStreamDescriptor - - -class ShowPublishedSDHashesChooser(EncryptedFileChooser): - #prompt_description = "Show published stream descriptors for an LBRY File" - - def __init__(self, console, stream_info_manager, lbry_file_manager): - EncryptedFileChooser.__init__(self, console, lbry_file_manager, ShowPublishedSDHashesFactory, - stream_info_manager, lbry_file_manager) - - -class ShowPublishedSDHashesChooserFactory(CommandHandlerFactory): - control_handler_class = ShowPublishedSDHashesChooser - command = "show-lbryfile-sd-hashes" - short_help = "Show the published stream descriptor files associated with an LBRY file" - full_help = "Show the published stream descriptor files associated with an LBRY file. " \ - "These files contain the metadata for LBRY files. These files can be accessed " \ - "on lbrynet via their hash. From that, lbrynet-console can download the LBRY file " \ - "if it is available on lbrynet." - - -class ShowPublishedSDHashes(CommandHandler): - #prompt_description = "Show published stream descriptors for an LBRY File" - - def __init__(self, console, lbry_file, stream_info_manager, lbry_file_manager): - CommandHandler.__init__(self, console) - self.lbry_file = lbry_file - self.stream_info_manager = stream_info_manager - self.lbry_file_manager = lbry_file_manager - - def start(self): - d = self._show_sd_hashes() - d.chainDeferred(self.finished_deferred) - - def _show_sd_hashes(self): - d = self.stream_info_manager.get_sd_blob_hashes_for_stream(self.lbry_file.stream_hash) - - def format_blob_hashes(sd_blob_hashes): - self.console.sendLine("\n".join([str(b) for b in sd_blob_hashes])) - - d.addCallback(format_blob_hashes) - return d - - -class ShowPublishedSDHashesFactory(EncryptedFileChooserFactory): - control_handler_class = ShowPublishedSDHashes - - -class CreatePlainStreamDescriptorChooser(EncryptedFileChooser): - #prompt_description = "Create a plain stream descriptor file for an LBRY File" - - def __init__(self, console, lbry_file_manager): - EncryptedFileChooser.__init__(self, console, lbry_file_manager, - CreatePlainStreamDescriptorFactory, lbry_file_manager, - exit_after_one_done=True) - - -class CreatePlainStreamDescriptorChooserFactory(CommandHandlerFactory): - control_handler_class = CreatePlainStreamDescriptorChooser - command = "create-stream-descriptor" - short_help = "Create a plaintext stream descriptor file for an LBRY file" - full_help = "Create a plaintext stream descriptor file for an LBRY file. This file, " \ - "which traditionally has the file extension .cryptsd, can be shared " \ - "through a variety of means, including email and file transfer. Anyone " \ - "possessing this file will be able to download the LBRY file if it is " \ - "available on lbrynet." - - -class CreatePlainStreamDescriptor(CommandHandler): - prompt_description = "Create a plain stream descriptor file for an LBRY File" - - def __init__(self, console, lbry_file, lbry_file_manager): - CommandHandler.__init__(self, console) - self.lbry_file = lbry_file - self.lbry_file_manager = lbry_file_manager - self.sd_file_name = None - self.overwrite_old = False - - def start(self): - self.console.sendLine(self._get_file_name_prompt()) - - def handle_line(self, line): - if self.sd_file_name is None: - self.sd_file_name = line - d = self._get_file_name() - d.addCallback(lambda file_name: create_plain_sd(self.lbry_file_manager.stream_info_manager, - self.lbry_file.stream_hash, file_name, - self.overwrite_old)) - d.addCallback(lambda sd_file_name: self.console.sendLine("Wrote stream metadata to " + sd_file_name)) - d.chainDeferred(self.finished_deferred) - - def _get_file_name_prompt(self): - file_name = self.lbry_file.file_name - if not file_name: - file_name = "_" - file_name += ".cryptsd" - return "Stream Descriptor file name (blank for default, %s):" % file_name - - def _get_file_name(self): - if self.sd_file_name: - file_name = self.sd_file_name - self.overwrite_old = True - else: - file_name = self.lbry_file.file_name - file_name += ".cryptsd" - return defer.succeed(file_name) - - -class CreatePlainStreamDescriptorFactory(EncryptedFileChooserFactory): - control_handler_class = CreatePlainStreamDescriptor - - -class ShowEncryptedFileStreamHashChooser(EncryptedFileChooser): - #prompt_description = "Show an LBRY File's stream hash (not usually what you want)" - - def __init__(self, console, lbry_file_manager): - EncryptedFileChooser.__init__(self, console, lbry_file_manager, ShowEncryptedFileStreamHashFactory) - - -class ShowEncryptedFileStreamHashChooserFactory(CommandHandlerFactory): - control_handler_class = ShowEncryptedFileStreamHashChooser - command = "lbryfile-streamhash" - short_help = "Show an LBRY file's stream hash" - full_help = "Show the stream hash of an LBRY file, which is how the LBRY file is referenced internally" \ - " by this application and therefore not usually what you want to see." - - -class ShowEncryptedFileStreamHash(CommandHandler): - #prompt_description = "Show an LBRY File's stream hash (not usually what you want)" - - def __init__(self, console, lbry_file): - CommandHandler.__init__(self, console) - self.lbry_file = lbry_file - - def start(self): - self.console.sendLine(str(self.lbry_file.stream_hash)) - self.finished_deferred.callback(None) - - -class ShowEncryptedFileStreamHashFactory(EncryptedFileChooserFactory): - control_handler_class = ShowEncryptedFileStreamHash - - -class ModifyEncryptedFileDataPaymentRate(ModifyPaymentRate): - prompt_description = "Modify LBRY File data payment rate" - - def __init__(self, console, lbry_file, lbry_file_manager): - ModifyPaymentRate.__init__(self, console) - self._prompt_choices['unset'] = (self._unset, "Use the default LBRY file data rate") - self.lbry_file = lbry_file - self.lbry_file_manager = lbry_file_manager - self.payment_rate_manager = lbry_file.payment_rate_manager - - def _unset(self): - d = self._set_rate(None) - d.addCallback(lambda _: "Using the default LBRY file data rate") - return d - - def _set_rate(self, rate): - self.payment_rate_manager.min_blob_data_payment_rate = rate - return self.lbry_file_manager.set_lbry_file_data_payment_rate(self.lbry_file, rate) - - def _get_current_status(self): - status = "The LBRY file's current data payment rate is " - effective_rate = self.payment_rate_manager.get_effective_min_blob_data_payment_rate() - if self.payment_rate_manager.min_blob_data_payment_rate is None: - status += "set to use the default LBRY file data payment rate, " - status += str(effective_rate) - return status - - -class ModifyEncryptedFileDataPaymentRateFactory(CommandHandlerFactory): - control_handler_class = ModifyEncryptedFileDataPaymentRate - - -class ModifyEncryptedFileOptionsChooser(EncryptedFileChooser): - #prompt_description = "Modify an LBRY File's options" - - def __init__(self, console, lbry_file_manager): - EncryptedFileChooser.__init__(self, console, lbry_file_manager, ModifyEncryptedFileOptionsFactory, lbry_file_manager) - - -class ModifyEncryptedFileOptionsChooserFactory(CommandHandlerFactory): - control_handler_class = ModifyEncryptedFileOptionsChooser - command = "modify-lbryfile-options" - short_help = "Modify an LBRY file's options" - full_help = "Modify an LBRY file's options. Options include, and are limited to, " \ - "changing the rate that the application will pay for data related to " \ - "this LBRY file." - - -class ModifyEncryptedFileOptions(RecursiveCommandHandler): - #prompt_description = "Modify an LBRY File's options" - - def __init__(self, console, lbry_file, lbry_file_manager): - self.lbry_file = lbry_file - self.lbry_file_manager = lbry_file_manager - RecursiveCommandHandler.__init__(self, console) - - def _get_control_handler_factories(self): - factories = [] - factories.append(ModifyEncryptedFileDataPaymentRateFactory(self.lbry_file, self.lbry_file_manager)) - return factories - - -class ModifyEncryptedFileOptionsFactory(EncryptedFileChooserFactory): - control_handler_class = ModifyEncryptedFileOptions - - -class ClaimName(CommandHandler): - #prompt_description = "Publish to an lbry:// address" - other_hash_prompt = "Enter the hash you would like to publish:" - short_desc_prompt = "Enter a short description:" - #sd_failure_message = "Unable to find a stream descriptor for that file." - requested_price_prompt = "Enter the fee others should pay for the decryption key for this stream. Leave blank for no fee:" - lbrycrd_address_prompt = "Enter the LBRYcrd address to which the key fee should be sent. If left blank a new address will be used from the wallet:" - bid_amount_prompt = "Enter the number of credits you wish to use to support your bid for the name:" - choose_name_prompt = "Enter the name to which you would like to publish:" - - def __init__(self, console, wallet, lbry_file_manager, blob_manager): - CommandHandler.__init__(self, console) - self.wallet = wallet - self.lbry_file_manager = lbry_file_manager - self.blob_manager = blob_manager - self.file_type_options = [] - self.file_type_chosen = None - self.lbry_file_list = [] - self.sd_hash = None - self.key_fee = None - self.key_fee_chosen = False - self.need_address = True - self.chosen_address = None - self.bid_amount = None - self.chosen_name = None - self.short_description = None - self.verified = False - - def start(self): - self.console.sendLine(self._get_file_type_options()) - - def handle_line(self, line): - #if line is None: - # return False, defer.succeed(self._get_file_type_options()) - #if self.failed is True: - # return True, defer.succeed(None) - if self.file_type_chosen is None: - try: - choice = int(line) - except ValueError: - choice = -1 - if choice < 0 or choice >= len(self.file_type_options): - self.console.sendLine("You must enter a valid number.\n\n%s" % self._get_file_type_options()) - return - if self.file_type_options[choice][0] is None: - self.console.sendLine("Publishing canceled.") - self.finished_deferred.callback(None) - return - self.file_type_chosen = self.file_type_options[choice][0] - if self.file_type_chosen == "hash": - self.console.sendLine(self.other_hash_prompt) - return - else: - self._set_sd_hash_and_get_desc_prompt() - return - if self.sd_hash is None: - self.sd_hash = line - self.console.sendLine(self.short_desc_prompt) - return - if self.short_description is None: - self.short_description = line - self.console.sendLine(self.requested_price_prompt) - return - if self.key_fee_chosen is False: - if line: - try: - self.key_fee = float(line) - except ValueError: - self.console.sendLine("Leave blank or enter a floating point number.\n\n%s" % self.requested_price_prompt) - return - self.key_fee_chosen = True - if self.key_fee is None or self.key_fee <= 0: - self.need_address = False - self.console.sendLine(self.bid_amount_prompt) - return - self.console.sendLine(self.lbrycrd_address_prompt) - return - if self.need_address is True: - if line: - self.chosen_address = line - d = defer.succeed(None) - else: - d = self._get_new_address() - self.need_address = False - d.addCallback(lambda _: self.console.sendLine(self.bid_amount_prompt)) - return - if self.bid_amount is None: - try: - self.bid_amount = float(line) - except ValueError: - self.console.sendLine("Must be a floating point number.\n\n%s" % self.bid_amount_prompt) - return - self.console.sendLine(self.choose_name_prompt) - return - if self.chosen_name is None: - self.chosen_name = line - self.console.sendLine(self._get_verification_prompt()) - return - if self.verified is False: - if line.lower() == "yes": - d = self._claim_name() - else: - d = defer.succeed("Claim canceled") - d.chainDeferred(self.finished_deferred) - - def _get_file_type_options(self): - options = [] - pattern = "[%d] %s\n" - prompt_string = "What would you like to publish?\n" - prompt_string += "LBRY Files:\n" - i = 0 - for lbry_file in self.lbry_file_manager.lbry_files: - options.append((lbry_file, lbry_file.file_name)) - prompt_string += pattern % (i, lbry_file.file_name) - i += 1 - prompt_string += "Other:\n" - options.append(("hash", "Enter a hash")) - prompt_string += pattern % (i, "Enter a hash") - i += 1 - options.append((None, "Cancel")) - prompt_string += pattern % (i, "Cancel") - self.file_type_options = options - return prompt_string - - def _choose_sd(self, sd_blob_hashes): - if not sd_blob_hashes: - return publish_sd_blob(self.lbry_file_manager.stream_info_manager, self.blob_manager, - self.file_type_chosen.stream_hash) - - else: - return defer.succeed(sd_blob_hashes[0]) - - def _set_sd_hash_and_get_desc_prompt(self): - d = self.lbry_file_manager.stream_info_manager.get_sd_blob_hashes_for_stream(self.file_type_chosen.stream_hash) - d.addCallback(self._choose_sd) - - def set_sd_hash(sd_hash): - self.sd_hash = sd_hash - self.console.sendLine(self.short_desc_prompt) - - def sd_hash_failed(err): - self.console.sendLine("An error occurred getting the stream descriptor hash: %s" % err.getErrorMessage()) - self.finished_deferred.callback(None) - - d.addCallback(set_sd_hash) - d.addErrback(sd_hash_failed) - return d - - def _get_new_address(self): - d = self.wallet.get_new_address() - - def set_address(address): - self.chosen_address = address - - d.addCallback(set_address) - return d - - def _get_verification_prompt(self): - v_string = "Ensure the following details are correct:\n" - if self.file_type_chosen != "hash": - v_string += "File name: %s\n" % str(self.file_type_chosen.file_name) - v_string += "Hash: %s\n" % str(self.sd_hash) - v_string += "Description: %s\n" % str(self.short_description) - v_string += "Key fee: %s\n" % str(self.key_fee) - if self.chosen_address is not None: - v_string += "Key fee address: %s\n" % str(self.chosen_address) - v_string += "Bid amount: %s\n" % str(self.bid_amount) - v_string += "Name: %s\n" % str(self.chosen_name) - v_string += "\nIf this is correct, type 'yes'. Otherwise, type 'no' and the bid will be aborted:" - return v_string - - def _claim_name(self): - d = self.wallet.claim_name(self.chosen_name, self.sd_hash, float(self.bid_amount), - description=self.short_description, key_fee=self.key_fee, - key_fee_address=self.chosen_address) - d.addCallback(lambda response: self.console.sendLine(response)) - return d - - -class ClaimNameFactory(CommandHandlerFactory): - control_handler_class = ClaimName - command = "claim" - short_help = "Dedicate some LBC toward an lbry:// address" - full_help = "Dedicate some LBY toward associate an LBRY file, or any hash, with " \ - "an lbry:// address. On lbry, whoever dedicates the most credits to an " \ - "lbry:// address controls that address. This command will let you choose " \ - "to associate either on LBRY file or any given value with the address.\n" \ - "This command will ask for a few additional fields, explained here:\n\n" \ - "The title will be presented to users before they download the file.\n" \ - "The bid amount is the number of LBC that will be dedicated toward " \ - "the lbry://address being registered. On lbry, whoever dedicates the most " \ - "credits to the address controls that address.\n" \ - "The decryption key fee is the amount of LBC that users will be charged " \ - "when consuming this file. The fees will be sent to the provided key fee address.\n" \ - "The description will be presented to users before they download the file.\n" - - -class Publish(CommandHandler): - couldnt_read_file_error = "Unable to read %s. The file must exist and you must have permission to read it." - bid_amount_not_number = "Bid amount must be a number (e.g. 5 or 10.0)" - key_fee_not_number = "Decryption key fee must be a number (e.g. 5 or 10.0)" - - def __init__(self, console, session, lbry_file_manager, wallet): - CommandHandler.__init__(self, console) - self.session = session - self.lbry_file_manager = lbry_file_manager - self.wallet = wallet - self.received_file_name = False - self.file_path = None - self.file_name = None - self.title = None - self.publish_name = None - self.bid_amount = None - self.key_fee = None - self.key_fee_address = None - self.key_fee_address_chosen = False - self.description = None - self.verified = False - self.lbry_file = None - self.sd_hash = None - self.tx_hash = None - - def start(self, file_name=None):#, title=None, publish_name=None, bid_amount=None, - # key_fee=None, key_fee_address=None): - - #def set_other_fields(): - # self.title = title - # self.publish_name = publish_name - # if bid_amount is not None: - # try: - # self.bid_amount = float(bid_amount) - # except ValueError: - # self.console.sendLine(self.bid_amount_not_number) - # self.finished_deferred.callback(None) - # return - # if key_fee is not None: - # try: - # self.key_fee = float(key_fee) - # except ValueError: - # self.console.sendLine(self.key_fee_not_number) - # self.finished_deferred.callback(None) - # return - # if key_fee_address is not None: - # self.key_fee_address = key_fee_address - # self.key_fee_address_chosen = True - # self._send_next_prompt() - - def handle_error(err): - if err.check(IOError): - self.console.sendLine(self.couldnt_read_file_error % str(file_name)) - else: - self.console.sendLine("An unexpected error occurred: %s" % str(err.getErrorMessage())) - self.finished_deferred.callback(None) - - if file_name is not None: - self.received_file_name = True - d = self._check_file_path(file_name) - #d.addCallback(lambda _: set_other_fields()) - d.addCallbacks(lambda _: self._send_next_prompt(), handle_error) - else: - self._send_next_prompt() - - def handle_line(self, line): - d = defer.succeed(True) - if self.file_name is None: - if self.received_file_name is False: - self.received_file_name = True - d = self._check_file_path(line) - - def file_name_failed(err): - err.trap(IOError) - self.console.sendLine(self.couldnt_read_file_error % line) - self.finished_deferred.callback(None) - return False - - d.addErrback(file_name_failed) - elif self.title is None: - self.title = line - elif self.publish_name is None: - self.publish_name = line - elif self.bid_amount is None: - try: - self.bid_amount = float(line) - except ValueError: - self.console.sendLine(self.bid_amount_not_number) - elif self.key_fee is None: - try: - self.key_fee = float(line) - except ValueError: - self.console.sendLine(self.key_fee_not_number) - elif self.key_fee_address_chosen is False and self.key_fee > 0: - if line: - self.key_fee_address = line - else: - d = self._get_new_address() - self.key_fee_address_chosen = True - elif self.description is None: - self.description = line - elif self.verified is False: - if line.lower() in ['yes', 'y']: - self._do_publish() - self.console.sendLine("Publishing in the background.") - else: - self.console.sendLine("Canceled.") - self.finished_deferred.callback(None) - return - else: - return - d.addCallbacks(lambda s: self._send_next_prompt() if s is True else None, - self.finished_deferred.errback) - - def _check_file_path(self, file_path): - def check_file_threaded(): - f = open(file_path) - f.close() - self.file_path = file_path - self.file_name = os.path.basename(self.file_path) - return True - return threads.deferToThread(check_file_threaded) - - def _get_new_address(self): - d = self.wallet.get_new_address() - - def set_address(address): - self.key_fee_address = address - return True - - d.addCallback(set_address) - return d - - def _send_next_prompt(self): - prompt = None - if self.file_name is None: - prompt = "Path to file: " - elif self.title is None: - prompt = "Title: " - elif self.publish_name is None: - prompt = "Publish to: lbry://" - elif self.bid_amount is None: - prompt = "Bid amount for published name in LBC: " - elif self.key_fee is None: - prompt = "Decryption key fee in LBC: " - elif self.key_fee_address_chosen is False and self.key_fee > 0: - prompt = "Decryption key fee sent to (leave blank for a new address): " - elif self.description is None: - prompt = "Description: " - elif self.verified is False: - prompt = self._get_verification_prompt() - if prompt is not None: - self.console.send(prompt) - - def _get_verification_prompt(self): - v_string = "\nPlease review the following details.\n\n" - v_string += "Path to file: %s\n" % str(self.file_path) - v_string += "File name: %s\n" % str(self.file_name) - v_string += "Title: %s\n" % str(self.title) - v_string += "Published to: lbry://%s\n" % str(self.publish_name) - v_string += "Bid amount: %s LBC\n" % str(self.bid_amount) - v_string += "Fee for decryption key: %s LBC\n" % str(self.key_fee) - if self.key_fee > 0: - v_string += "Decryption key address: %s\n" % str(self.key_fee_address) - v_string += "Description: %s\n" % str(self.description) - v_string += "Is this correct? (y/n): " - return v_string - - def set_status(self, lbry_file_downloader): - self.lbry_file = lbry_file_downloader - d = self.lbry_file_manager.change_lbry_file_status(self.lbry_file, - ManagedEncryptedFileDownloader.STATUS_FINISHED) - d.addCallback(lambda _: lbry_file_downloader.restore()) - return d - - def add_to_lbry_files(self, stream_hash): - prm = PaymentRateManager(self.session.base_payment_rate_manager) - d = self.lbry_file_manager.add_lbry_file(stream_hash, prm) - d.addCallback(self.set_status) - return d - - def _create_sd_blob(self): - d = publish_sd_blob(self.lbry_file_manager.stream_info_manager, self.session.blob_manager, - self.lbry_file.stream_hash) - - def set_sd_hash(sd_hash): - self.sd_hash = sd_hash - - d.addCallback(set_sd_hash) - return d - - def _claim_name(self): - d = self.wallet.claim_name(self.publish_name, self.sd_hash, self.bid_amount, - description=self.description, key_fee=self.key_fee, - key_fee_address=self.key_fee_address) - - def set_tx_hash(tx_hash): - self.tx_hash = tx_hash - - d.addCallback(set_tx_hash) - return d - - def _show_result(self): - message = "Finished publishing %s to %s. The txid of the LBRYcrd claim is %s." - self.console.sendLine(message % (str(self.file_name), str(self.publish_name), str(self.tx_hash))) - - def _show_time_behind_blockchain(self, rounded_time): - if rounded_time.unit >= RoundedTime.HOUR: - self.console.sendLine("This application is %s behind the LBC blockchain\n" - "and therefore may not have all of the funds you expect\n" - "available at this time. It may take a few minutes to\n" - "catch up the first time you run this early version of LBRY.\n" - "Please be patient =).\n" % str(rounded_time)) - - 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): - d = self.wallet.get_most_recent_blocktime() - 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) - error_message = err.getErrorMessage() - self.console.sendLine(message % (str(self.file_name), str(self.publish_name), error_message)) - log.error(message, str(self.file_name), str(self.publish_name), err.getTraceback()) - return d - - def _do_publish(self): - d = create_lbry_file(self.session, self.lbry_file_manager, self.file_name, open(self.file_path)) - d.addCallback(self.add_to_lbry_files) - d.addCallback(lambda _: self._create_sd_blob()) - d.addCallback(lambda _: self._claim_name()) - d.addCallbacks(lambda _: self._show_result(), self._show_publish_error) - return d - - -class PublishFactory(CommandHandlerFactory): - control_handler_class = Publish - priority = 90 - command = "publish" - short_help = "Publish a file to lbrynet" - full_help = "Publish a file to lbrynet.\n\n" \ - "Usage: publish [file_name]\n\n" \ - "This command takes (or prompts) for a file, prompts for additional " \ - "information about that file, and then makes that file available on " \ - "lbrynet via an lbry:// address.\n" \ - "The file given must exist or publish will fail.\n" \ - "The title will be presented to users before they download the file.\n" \ - "The bid amount is the number of LBC that will be dedicated toward " \ - "the lbry://address being registered. On lbry, whoever dedicates the most " \ - "credits to the address controls that address.\n" \ - "The decryption key fee is the amount of LBC that users will be charged " \ - "when consuming this file. The fees will be sent to the provided key fee address.\n" \ - "The description will be presented to users before they download the file.\n" - - -class ModifyDefaultDataPaymentRate(ModifyPaymentRate): - prompt_description = "Modify default data payment rate" - - def __init__(self, console, payment_rate_manager, settings): - ModifyPaymentRate.__init__(self, console) - self.settings = settings - self.payment_rate_manager = payment_rate_manager - - def _set_rate(self, rate): - self.payment_rate_manager.min_blob_data_payment_rate = rate - return self.settings.save_default_data_payment_rate(rate) - - def _get_current_status(self): - status = "The current default data payment rate is " - status += str(self.payment_rate_manager.min_blob_data_payment_rate) - return status - - -class ModifyDefaultDataPaymentRateFactory(CommandHandlerFactory): - control_handler_class = ModifyDefaultDataPaymentRate - - -class ForceCheckBlobFileConsistency(CommandHandler): - prompt_description = "Verify consistency of stored chunks" - - def __init__(self, console, blob_manager): - CommandHandler.__init__(self, console) - self.blob_manager = blob_manager - - def start(self): - self._check_consistency() - self.console.sendLine("Checking consistency in the background.") - self.finished_deferred.callback(None) - - def _check_consistency(self): - d = self.blob_manager.check_consistency() - d.addCallback(lambda _: self.console.sendLine("Finished checking stored blobs")) - return d - - -class ForceCheckBlobFileConsistencyFactory(CommandHandlerFactory): - control_handler_class = ForceCheckBlobFileConsistency - - -class ModifyApplicationDefaults(RecursiveCommandHandler): - #prompt_description = "Modify application settings" - - def __init__(self, console, lbry_service): - self.lbry_service = lbry_service - RecursiveCommandHandler.__init__(self, console) - - def _get_control_handler_factories(self): - return [ModifyDefaultDataPaymentRateFactory(self.lbry_service.session.base_payment_rate_manager, - self.lbry_service.settings), - ForceCheckBlobFileConsistencyFactory(self.lbry_service.session.blob_manager)] - - -class ModifyApplicationDefaultsFactory(CommandHandlerFactory): - control_handler_class = ModifyApplicationDefaults - command = "modify-application-defaults" - short_help = "Modify application settings" - full_help = "Either change the default rate to pay for data downloads or check " \ - "that the chunks of data on disk match up with the chunks of data " \ - "the application thinks are on disk." - - -class ShowServerStatus(CommandHandler): - #prompt_description = "Show the status of the server" - - def __init__(self, console, lbry_service): - CommandHandler.__init__(self, console) - self.lbry_service = lbry_service - - def start(self): - #assert line is None, "Show server status should not be passed any arguments" - d = self._get_status() - d.chainDeferred(self.finished_deferred) - - def _get_status(self): - status_string = "Server status:\n" - status_string += "Port: " + str(self.lbry_service.peer_port) + "\n" - status_string += "Running: " + str(self.lbry_service.lbry_server_port is not None) + "\n" - if self.lbry_service.blob_request_payment_rate_manager is not None: - rate = self.lbry_service.blob_request_payment_rate_manager.get_effective_min_blob_data_payment_rate() - status_string += "Min blob data payment rate: " - if self.lbry_service.blob_request_payment_rate_manager.min_blob_data_payment_rate is None: - status_string += "Using application default (" + str(rate) + ")\n" - else: - status_string += str(rate) - status_string += "\n" - #status_string += "Min crypt info payment rate: " - #status_string += str(self.lbry_service._server_payment_rate_manager.get_min_live_blob_info_payment_rate()) - #status_string += "\n" - self.console.sendLine(status_string) - return defer.succeed(None) - - -class ShowServerStatusFactory(CommandHandlerFactory): - control_handler_class = ShowServerStatus - command = "server-status" - short_help = "Show the server's status" - full_help = "Show the port on which the server is running, whether the server is running, and the" \ - " payment rate which the server accepts for data uploads" - - -class StartServer(CommandHandler): - prompt_description = "Start the server" - - def __init__(self, console, lbry_service): - CommandHandler.__init__(self, console) - self.lbry_service = lbry_service - - def start(self): - #assert line is None, "Start server should not be passed any arguments" - d = self.lbry_service.start_server() - d.addCallback(lambda _: self.lbry_service.settings.save_server_running_status(running=True)) - d.addCallback(lambda _: self.console.sendLine("Successfully started the server")) - d.chainDeferred(self.finished_deferred) - #return True, d - - -class StartServerFactory(CommandHandlerFactory): - control_handler_class = StartServer - - -class StopServer(CommandHandler): - prompt_description = "Stop the server" - - def __init__(self, console, lbry_service): - CommandHandler.__init__(self, console) - self.lbry_service = lbry_service - - def start(self): - #assert line is None, "Stop server should not be passed any arguments" - d = self.lbry_service.stop_server() - d.addCallback(lambda _: self.lbry_service.settings.save_server_running_status(running=False)) - d.addCallback(lambda _: self.console.sendLine("Successfully stopped the server")) - d.chainDeferred(self.finished_deferred) - #return True, d - - -class StopServerFactory(CommandHandlerFactory): - control_handler_class = StopServer - - -class ModifyServerDataPaymentRate(ModifyPaymentRate): - prompt_description = "Modify server data payment rate" - - def __init__(self, console, payment_rate_manager, settings): - ModifyPaymentRate.__init__(self, console) - self._prompt_choices['unset'] = (self._unset, "Use the application default data rate") - self.settings = settings - self.payment_rate_manager = payment_rate_manager - - def _unset(self): - d = self._set_rate(None) - d.addCallback(lambda _: "Using the application default data rate") - return d - - def _set_rate(self, rate): - self.payment_rate_manager.min_blob_data_payment_rate = rate - return self.settings.save_server_data_payment_rate(rate) - - def _get_current_status(self): - effective_rate = self.payment_rate_manager.get_effective_min_blob_data_payment_rate() - status = "The current server data payment rate is " - if self.payment_rate_manager.min_blob_data_payment_rate is None: - status += "set to use the application default, " - status += str(effective_rate) - return status - - -class ModifyServerDataPaymentRateFactory(CommandHandlerFactory): - control_handler_class = ModifyServerDataPaymentRate - - -# class ModifyServerCryptInfoPaymentRate(ModifyPaymentRate): -# prompt_description = "Modify server live stream metadata payment rate" -# -# def __init__(self, payment_rate_manager, settings): -# ModifyPaymentRate.__init__(self) -# self._prompt_choices['unset'] = (self._unset, -# "Use the application default live stream metadata rate") -# self.settings = settings -# self.payment_rate_manager = payment_rate_manager -# -# def _unset(self): -# d = self._set_rate(None) -# d.addCallback(lambda _: "Using the application default live stream metadata rate") -# return True, d -# -# def _set_rate(self, rate): -# self.payment_rate_manager.min_live_blob_info_payment_rate = rate -# return self.settings.save_server_crypt_info_payment_rate(rate) -# -# def _get_current_status(self): -# effective_rate = self.payment_rate_manager.get_effective_min_live_blob_info_payment_rate() -# status = "The current server live stream metadata payment rate is " -# if self.payment_rate_manager.get_min_blob_data_payment_rate() is None: -# status += "set to use the application default, " -# status += str(effective_rate) -# else: -# status += str(effective_rate) -# return status -# -# -# class ModifyServerCryptInfoPaymentRateFactory(ControlHandlerFactory): -# control_handler_class = ModifyServerCryptInfoPaymentRate - - -class DisableQueryHandler(CommandHandler): - def __init__(self, console, query_handlers, query_handler, settings): - CommandHandler.__init__(self, console) - self.query_handlers = query_handlers - self.query_handler = query_handler - self.settings = settings - - def start(self): - #assert line is None, "DisableQueryHandler should not be passed any arguments" - self.query_handlers[self.query_handler] = False - d = self.settings.disable_query_handler(self.query_handler.get_primary_query_identifier()) - d.addCallback(lambda _: self.console.sendLine("Disabled the query handler")) - d.chainDeferred(self.finished_deferred) - - -class DisableQueryHandlerFactory(CommandHandlerFactory): - control_handler_class = DisableQueryHandler - - def get_prompt_description(self): - query_handler = self.args[1] - return "Disable " + str(query_handler.get_description()) - - -class EnableQueryHandler(CommandHandler): - def __init__(self, console, query_handlers, query_handler, settings): - CommandHandler.__init__(self, console) - self.query_handlers = query_handlers - self.query_handler = query_handler - self.settings = settings - - def start(self): - #assert line is None, "EnableQueryHandler should not be passed any arguments" - self.query_handlers[self.query_handler] = True - d = self.settings.enable_query_handler(self.query_handler.get_primary_query_identifier()) - d.addCallback(lambda _: self.console.sendLine("Enabled the query handler")) - d.chainDeferred(self.finished_deferred) - - -class EnableQueryHandlerFactory(CommandHandlerFactory): - control_handler_class = EnableQueryHandler - - def get_prompt_description(self): - query_handler = self.args[1] - return "Enable " + str(query_handler.get_description()) - - -class ModifyServerEnabledQueries(RecursiveCommandHandler): - prompt_description = "Modify which queries the server will respond to" - - def __init__(self, console, query_handlers, settings): - self.query_handlers = query_handlers - self.settings = settings - RecursiveCommandHandler.__init__(self, console, reset_after_each_done=True) - - def _get_control_handler_factories(self): - factories = [] - for query_handler, enabled in self.query_handlers.iteritems(): - if enabled: - factories.append(DisableQueryHandlerFactory(self.query_handlers, query_handler, self.settings)) - else: - factories.append(EnableQueryHandlerFactory(self.query_handlers, query_handler, self.settings)) - return factories - - -class ModifyServerEnabledQueriesFactory(CommandHandlerFactory): - control_handler_class = ModifyServerEnabledQueries - - -class ImmediateAnnounceAllBlobs(CommandHandler): - prompt_description = "Immediately announce all hashes to the DHT" - - def __init__(self, console, blob_manager): - CommandHandler.__init__(self, console) - self.blob_manager = blob_manager - - def start(self): - #assert line is None, "Immediate Announce should not be passed any arguments" - d = self.blob_manager.immediate_announce_all_blobs() - d.addCallback(lambda _: self.console.sendLine("Done announcing")) - d.chainDeferred(self.finished_deferred) - - -class ImmediateAnnounceAllBlobsFactory(CommandHandlerFactory): - control_handler_class = ImmediateAnnounceAllBlobs - command = "announce-blobs" - short_help = "Announce all blobs to the dht" - full_help = "Immediately re-broadcast all hashes associated with the server to " \ - "the distributed hash table." - - -class ModifyServerSettings(RecursiveCommandHandler): - #prompt_description = "Modify server settings" - - def __init__(self, console, lbry_service): - self.lbry_service = lbry_service - RecursiveCommandHandler.__init__(self, console, reset_after_each_done=True) - - def _get_control_handler_factories(self): - factories = [] - if self.lbry_service.lbry_server_port is not None: - factories.append(StopServerFactory(self.lbry_service)) - else: - factories.append(StartServerFactory(self.lbry_service)) - factories.append( - ModifyServerDataPaymentRateFactory( - self.lbry_service.blob_request_payment_rate_manager, - self.lbry_service.settings - ) - ) - #factories.append(ModifyServerCryptInfoPaymentRateFactory(self.lbry_service._server_payment_rate_manager, - # self.lbry_service.settings)) - factories.append(ModifyServerEnabledQueriesFactory(self.lbry_service.query_handlers, - self.lbry_service.settings)) - factories.append(ImmediateAnnounceAllBlobsFactory(self.lbry_service.session.blob_manager)) - return factories - - -class ModifyServerSettingsFactory(CommandHandlerFactory): - control_handler_class = ModifyServerSettings - command = "modify-server-settings" - short_help = "Modify server settings" - full_help = "Modify server settings. Settings that can be modified:\n\n" \ - "1) Queries that the server will answer from other peers. For example, " \ - "stop the server from responding to requests for metadata, or stop " \ - "the server from uploading data.\n" \ - "2) Change whether the server is running at all.\n" \ - "3) Change the minimum rate the server will accept for data uploads.\n" \ - "4) Immediately re-broadcast all hashes associated with the server to " \ - "the distributed hash table." - - -class PeerChooser(RecursiveCommandHandler): - - def __init__(self, console, peer_manager, factory_class, *args, **kwargs): - """ - @param peer_manager: - - @param factory_class: - - @param args: all arguments that will be passed to the factory - - @param kwargs: all arguments that will be passed to the superclass' __init__ - - @return: - """ - self.peer_manager = peer_manager - self.factory_class = factory_class - self.args = args - RecursiveCommandHandler.__init__(self, console, **kwargs) - - def _get_control_handler_factories(self): - control_handler_factories = [] - for peer in self.peer_manager.peers: - control_handler_factories.append(self.factory_class(peer, *self.args)) - return control_handler_factories - - -class PeerChooserFactory(CommandHandlerFactory): - def get_prompt_description(self): - peer = self.args[0] - return str(peer) - - -class ShowPeerStats(CommandHandler): - prompt_description = "Show the peer's stats" - - def __init__(self, console, peer): - CommandHandler.__init__(self, console) - self.peer = peer - - def start(self): - self.console.sendLine(self._get_peer_stats_string()) - self.finished_deferred.callback(None) - - def _get_peer_stats_string(self): - stats = "Statistics for " + str(self.peer) + '\n' - stats += " current_score: " + str(self.peer.score) + '\n' - stats += " is_available: " + str(self.peer.is_available()) + '\n' - for stat_type, amount in self.peer.stats.iteritems(): - stats += " " + stat_type + ": " + str(amount) + "\n" - return stats - - -class ShowPeerStatsFactory(CommandHandlerFactory): - control_handler_class = ShowPeerStats - - -class PeerStatsAndSettings(RecursiveCommandHandler): - def __init__(self, console, peer): - self.peer = peer - RecursiveCommandHandler.__init__(self, console, reset_after_each_done=True) - - def _get_control_handler_factories(self): - factories = [] - factories.append(ShowPeerStatsFactory(self.peer)) - return factories - - -class PeerStatsAndSettingsFactory(PeerChooserFactory): - control_handler_class = PeerStatsAndSettings - - -class PeerStatsAndSettingsChooser(PeerChooser): - #prompt_description = "View peer stats and modify peer settings" - - def __init__(self, console, peer_manager): - PeerChooser.__init__(self, console, peer_manager, PeerStatsAndSettingsFactory) - - -class PeerStatsAndSettingsChooserFactory(CommandHandlerFactory): - control_handler_class = PeerStatsAndSettingsChooser - command = "peer-stats" - short_help = "Show some peer statistics" - full_help = "Show the list of peers that this application has been " \ - "in contact with. Give the option to show further details " \ - "for each peer including the number of bytes transferred " \ - "and the 'score' of the peer which is used in deciding " \ - "which peers to connect to." - - -class EncryptedFileStatusModifier(CommandHandler): - def __init__(self, console, lbry_file, stream_info_manager, blob_manager, lbry_file_manager): - CommandHandler.__init__(self, console) - self.lbry_file = lbry_file - self.stream_info_manager = stream_info_manager - self.blob_manager = blob_manager - self.lbry_file_manager = lbry_file_manager - self.current_handler = None - - def start(self): - d = self.lbry_file.status() - d.addCallback(self._show_prompt) - - def handle_line(self, line): - if self.current_handler is None: - if line: - if line.lower() == 'd': - self.current_handler = DeleteEncryptedFile(self.console, self.lbry_file, - self.stream_info_manager, self.blob_manager, - self.lbry_file_manager) - elif line.lower() == 't': - self.current_handler = ToggleEncryptedFileRunning(self.console, self.lbry_file, - self.lbry_file_manager) - else: - self.console.sendLine("Invalid selection\n") - self.finished_deferred.callback(None) - return - else: - self.console.sendLine("") - self.finished_deferred.callback(None) - return - try: - self.current_handler.start() - except Exception as e: - self.console.sendLine("Operation failed. Error: %s\n" % str(e)) - import traceback - log.error(traceback.format_exc()) - self.finished_deferred.callback(None) - return - self.current_handler.finished_deferred.chainDeferred(self.finished_deferred) - else: - try: - self.current_handler.handle_line(line) - except Exception as e: - self.console.sendLine("Operation failed. Error: %s\n" % str(e)) - import traceback - log.error(traceback.format_exc()) - self.finished_deferred.callback(None) - - def _show_prompt(self, status_report): - self.console.sendLine("\n%s - %d chunks downloaded out of %d - %s" % (str(status_report.name), - status_report.num_completed, - status_report.num_known, - str(status_report.running_status))) - self.console.sendLine("\nTo delete this file, type 'd'. To toggle its running status, type 't'. " - "Then hit enter. To do nothing, just hit enter.") - self.console.send("Choice: ") - - -class Status(CommandHandler): - lbry_file_status_format = "[%d] %s - %s bytes - %s - %s - %s%% - %s" - - def __init__(self, console, lbry_service, rate_limiter, lbry_file_manager, blob_manager, wallet=None): - CommandHandler.__init__(self, console) - self.lbry_service = lbry_service - self.rate_limiter = rate_limiter - self.lbry_file_manager = lbry_file_manager - self.blob_manager = blob_manager - self.wallet = wallet - self.chosen_lbry_file = None - self.current_handler = None - - def start(self): - d = self._show_general_status() - d.addCallback(lambda _: self._show_lbry_file_status()) - d.addCallback(lambda _: self._show_prompt()) - - def handle_line(self, line): - if self.current_handler is None: - if line: - try: - index = int(line) - except ValueError: - self.console.sendLine("Choice must be a number.\n") - self.finished_deferred.callback(None) - return - if index < 0 or index >= len(self.lbry_files): - self.console.sendLine("Invalid choice.\n") - self.finished_deferred.callback(None) - return - self.current_handler = EncryptedFileStatusModifier(self.console, self.lbry_files[index], - self.lbry_file_manager.stream_info_manager, - self.blob_manager, self.lbry_file_manager) - try: - self.current_handler.start() - except Exception as e: - self.console.sendLine("Selection failed. Error: %s\n" % str(e)) - import traceback - log.error(traceback.format_exc()) - self.finished_deferred.callback(None) - return - self.current_handler.finished_deferred.chainDeferred(self.finished_deferred) - else: - self.console.sendLine("") - self.finished_deferred.callback(None) - else: - try: - self.current_handler.handle_line(line) - except Exception as e: - self.console.sendLine("Operation failed. Error: %s\n" % str(e)) - import traceback - log.error(traceback.format_exc()) - self.finished_deferred.callback(None) - - def _show_general_status(self): - #self.console.sendLine("Total bytes uploaded: %s" % str(self.rate_limiter.total_ul_bytes)) - #self.console.sendLine("Total bytes downloaded: %s" % str(self.rate_limiter.total_dl_bytes)) - #self.console.sendLine("Server running: %s" % str(self.lbry_service.lbry_server_port is not None)) - #self.console.sendLine("Server port: %s" % str(self.lbry_service.peer_port)) - return defer.succeed(True) - - def _get_name_and_validity_for_lbry_file(self, lbry_file): - if self.wallet is None: - return defer.succeed(None) - d = self.lbry_file_manager.stream_info_manager.get_sd_blob_hashes_for_stream(lbry_file.stream_hash) - d.addCallback(lambda sd_blob_hashes: self.wallet.get_name_and_validity_for_sd_hash(sd_blob_hashes[0]) if len(sd_blob_hashes) else None) - return d - - def _show_lbry_file_status(self): - self.lbry_files = self.lbry_file_manager.lbry_files - status_ds = map(lambda lbry_file: lbry_file.status(), self.lbry_files) - status_dl = defer.DeferredList(status_ds) - - size_ds = map(lambda lbry_file: lbry_file.get_total_bytes(), self.lbry_files) - size_dl = defer.DeferredList(size_ds) - - name_validity_ds = map(self._get_name_and_validity_for_lbry_file, self.lbry_files) - name_validity_dl = defer.DeferredList(name_validity_ds) - - dl = defer.DeferredList([status_dl, size_dl, name_validity_dl]) - - def show_statuses(statuses): - status_reports = statuses[0][1] - sizes = statuses[1][1] - name_validities = statuses[2][1] - for i, (lbry_file, (succ1, status), (succ2, size), (succ3, name_validity)) in enumerate(zip(self.lbry_files, status_reports, sizes, name_validities)): - percent_done = "unknown" - name = lbry_file.file_name - claimed_name = "" - claimed_name_valid = "" - if succ3 and name_validity: - validity = name_validity[1] - if validity == "valid": - claimed_name_valid = "" - else: - claimed_name_valid = "(" + validity + ")" - claimed_name = name_validity[0] - total_bytes = "unknown" - running_status = "unknown" - if succ1: - percent_done = "0" - if status.num_known > 0: - percent = 100.0 * status.num_completed / status.num_known - percent_done = "%.2f" % percent - running_status = status.running_status - if succ2: - total_bytes = "%d" % size - self.console.sendLine(self.lbry_file_status_format % (i, str(name), total_bytes, - str(claimed_name_valid), - str(claimed_name), - percent_done, str(running_status))) - - dl.addCallback(show_statuses) - return dl - - def _show_prompt(self): - self.console.sendLine("\n\nTo alter the status of any file shown above, type the number next to it " - "and then hit 'enter'. Otherwise, just hit 'enter'.") - self.console.send("Choice: ") - - -class StatusFactory(CommandHandlerFactory): - control_handler_class = Status - priority = 20 - command = "status" - short_help = "Show or alter status of files being downloaded" - full_help = "Show or alter status of files being downloaded\n\n" \ - "Show the list of files that are currently downloading " \ - "or have been downloaded, and give the option to " \ - "toggle whether the file is actively downloading or " \ - "to remove the file." - - -# class AutoFetcherStart(CommandHandler): -# def __init__(self, console, autofetcher): -# CommandHandler.__init__(self, console) -# self.autofetcher = autofetcher -# -# def start(self): -# self.autofetcher.start(self.console) -# self.finished_deferred.callback(None) -# -# -# class AutoFetcherStop(CommandHandler): -# def __init__(self, console, autofetcher): -# CommandHandler.__init__(self, console) -# self.autofetcher = autofetcher -# -# def start(self): -# self.autofetcher.stop(self.console) -# self.finished_deferred.callback(None) -# -# -# class AutoFetcherStatus(CommandHandler): -# def __init__(self, console, autofetcher): -# CommandHandler.__init__(self, console) -# self.autofetcher = autofetcher -# -# def start(self): -# self.autofetcher.check_if_running(self.console) -# self.finished_deferred.callback(None) - - -# class AutoFetcherStartFactory(CommandHandlerFactory): -# control_handler_class = AutoFetcherStart -# command = "start-autofetcher" -# short_help = "Start downloading all lbry files as they are published" -# -# -# class AutoFetcherStopFactory(CommandHandlerFactory): -# control_handler_class = AutoFetcherStop -# command = "stop-autofetcher" -# short_help = "Stop downloading all lbry files as they are published" -# -# -# class AutoFetcherStatusFactory(CommandHandlerFactory): -# control_handler_class = AutoFetcherStatus -# command = "autofetcher-status" -# short_help = "Check autofetcher status" - - -class BlockchainStatus(CommandHandler): - def __init__(self, console, wallet=None): - CommandHandler.__init__(self, console) - self.wallet = wallet - - def start(self): - d = self.wallet.get_most_recent_blocktime() - d.addCallback(get_time_behind_blockchain) - d.addCallbacks(self._show_time_behind_blockchain, self._show_error) - d.chainDeferred(self.finished_deferred) - return d - - def _show_time_behind_blockchain(self, rounded_time): - if rounded_time.unit >= RoundedTime.HOUR: - self.console.sendLine("This application is %s behind the LBC blockchain. It\n" - "should only take a few minutes to catch up." % str(rounded_time)) - else: - self.console.sendLine("This application is up to date with the LBC blockchain.") - - def _show_error(self, err): - log.error(err.getTraceback()) - self.console.sendLine("Unable to determine the status of the blockchain.") - - -class BlockchainStatusFactory(CommandHandlerFactory): - control_handler_class = BlockchainStatus - command = "get-blockchain-status" - short_help = "Show whether this application has caught up with the LBC blockchain" - full_help = "Show whether this applications has caught up with the LBC blockchain" diff --git a/lbrynet/lbrynet_console/Plugin.py b/lbrynet/lbrynet_console/Plugin.py deleted file mode 100644 index 06f11e456..000000000 --- a/lbrynet/lbrynet_console/Plugin.py +++ /dev/null @@ -1,13 +0,0 @@ -from yapsy.IPlugin import IPlugin - - -class Plugin(IPlugin): - - def __init__(self): - IPlugin.__init__(self) - - def setup(self, lbry_console): - raise NotImplementedError - - def stop(self): - raise NotImplementedError \ No newline at end of file diff --git a/lbrynet/lbrynet_console/__init__.py b/lbrynet/lbrynet_console/__init__.py deleted file mode 100644 index 5cbf600c2..000000000 --- a/lbrynet/lbrynet_console/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -""" -A plugin-enabled console application for interacting with the LBRY network called lbrynet-console. - -lbrynet-console can be used to download and upload LBRY Files and includes plugins for streaming -LBRY Files to an external application and to download unknown chunks of data for the purpose of -re-uploading them. It gives the user some control over how much will be paid for data and -metadata and also what types of queries from clients. -""" \ No newline at end of file diff --git a/lbrynet/lbrynet_console/interfaces.py b/lbrynet/lbrynet_console/interfaces.py deleted file mode 100644 index 26d55bf3e..000000000 --- a/lbrynet/lbrynet_console/interfaces.py +++ /dev/null @@ -1,24 +0,0 @@ -from zope.interface import Interface - - -class IControlHandlerFactory(Interface): - def get_prompt_description(self): - pass - - def get_handler(self): - pass - - -class IControlHandler(Interface): - def handle_line(self, line): - pass - - -class ICommandHandlerFactory(Interface): - def get_handler(self): - pass - - -class ICommandHandler(Interface): - def handle_line(self, line): - pass \ No newline at end of file diff --git a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindBlobHandler.py b/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindBlobHandler.py deleted file mode 100644 index dd0f981f5..000000000 --- a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindBlobHandler.py +++ /dev/null @@ -1,15 +0,0 @@ -from zope.interface import implements -from lbrynet.interfaces import IBlobHandler -from twisted.internet import defer - - -class BlindBlobHandler(object): - implements(IBlobHandler) - - def __init__(self): - pass - - ######### IBlobHandler ######### - - def handle_blob(self, blob, blob_info): - return defer.succeed(True) \ No newline at end of file diff --git a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindInfoManager.py b/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindInfoManager.py deleted file mode 100644 index 61051065c..000000000 --- a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindInfoManager.py +++ /dev/null @@ -1,78 +0,0 @@ -from twisted.internet import defer -from ValuableBlobInfo import ValuableBlobInfo -import os -import sqlite3 -from twisted.enterprise import adbapi -from lbrynet.core.sqlite_helpers import rerun_if_locked - - -class BlindInfoManager(object): - - def __init__(self, db_dir, peer_manager): - self.db_dir = db_dir - self.db_conn = None - self.peer_manager = peer_manager - - def setup(self): - # check_same_thread=False is solely to quiet a spurious error that appears to be due - # to a bug in twisted, where the connection is closed by a different thread than the - # one that opened it. The individual connections in the pool are not used in multiple - # threads. - self.db_conn = adbapi.ConnectionPool('sqlite3', os.path.join(self.db_dir, "blind_info.db"), - check_same_thread=False) - - def set_up_table(transaction): - transaction.execute("create table if not exists valuable_blobs (" + - " blob_hash text primary key, " + - " blob_length integer, " + - " reference text, " + - " peer_host text, " + - " peer_port integer, " + - " peer_score text" + - ")") - return self.db_conn.runInteraction(set_up_table) - - def stop(self): - self.db = None - return defer.succeed(True) - - def get_all_blob_infos(self): - d = self._get_all_blob_infos() - - def make_blob_infos(blob_data): - blob_infos = [] - for blob in blob_data: - blob_hash, length, reference, peer_host, peer_port, peer_score = blob - peer = self.peer_manager.get_peer(peer_host, peer_port) - blob_info = ValuableBlobInfo(blob_hash, length, reference, peer, peer_score) - blob_infos.append(blob_info) - return blob_infos - d.addCallback(make_blob_infos) - return d - - def save_blob_infos(self, blob_infos): - blobs = [] - for blob_info in blob_infos: - blob_hash = blob_info.blob_hash - length = blob_info.length - reference = blob_info.reference - peer_host = blob_info.peer.host - peer_port = blob_info.peer.port - peer_score = blob_info.peer_score - blobs.append((blob_hash, length, reference, peer_host, peer_port, peer_score)) - return self._save_blob_infos(blobs) - - @rerun_if_locked - def _get_all_blob_infos(self): - return self.db_conn.runQuery("select * from valuable_blobs") - - @rerun_if_locked - def _save_blob_infos(self, blobs): - def save_infos(transaction): - for blob in blobs: - try: - transaction.execute("insert into valuable_blobs values (?, ?, ?, ?, ?, ?)", - blob) - except sqlite3.IntegrityError: - pass - return self.db_conn.runInteraction(save_infos) \ No newline at end of file diff --git a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindMetadataHandler.py b/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindMetadataHandler.py deleted file mode 100644 index c66c94c6d..000000000 --- a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindMetadataHandler.py +++ /dev/null @@ -1,321 +0,0 @@ -from zope.interface import implements -from lbrynet.interfaces import IMetadataHandler, IRequestCreator -from lbrynet.core.client.ClientRequest import ClientRequest, ClientPaidRequest -from lbrynet.core.Error import InsufficientFundsError, InvalidResponseError, RequestCanceledError -from lbrynet.core.Error import NoResponseError, ConnectionClosedBeforeResponseError -from ValuableBlobInfo import ValuableBlobInfo -import datetime -import logging -import random -from twisted.internet import defer -from twisted.python.failure import Failure -from collections import defaultdict - - -log = logging.getLogger(__name__) - - -class BlindMetadataHandler(object): - implements(IMetadataHandler, IRequestCreator) - - def __init__(self, info_manager, peers, peer_finder, approved_peers, payment_rate_manager, wallet, - download_manager): - self.info_manager = info_manager - self.payment_rate_manager = payment_rate_manager - self.wallet = wallet - self.download_manager = download_manager - self._peers = peers # {Peer: score} - self.peer_finder = peer_finder - self.approved_peers = approved_peers - self._valuable_protocol_prices = {} - self._info_protocol_prices = {} - self._price_disagreements = [] # [Peer] - self._incompatible_peers = [] # [Peer] - self._last_blob_hashes_from_peers = {} # {Peer: (blob_hash, expire_time)} - self._valuable_hashes = {} # {blob_hash: (peer score, reference, peer)} - self._blob_infos = {} # {blob_hash: ValuableBlobInfo} - self._peer_search_results = defaultdict(list) # {peer: [blob_hash]} - - ######### IMetadataHandler ######### - - def get_initial_blobs(self): - d = self.info_manager.get_all_blob_infos() - return d - - def final_blob_num(self): - return None - - ######### IRequestCreator ######### - - def send_next_request(self, peer, protocol): - # Basic idea: - # If the peer has been sending us blob hashes to download recently (10 minutes?), - # send back an example of one (the most recent?) so that it can - # keep sending us more like it. Otherwise, just ask for - # valuable blobs - sent_request = False - if self._should_send_request_to(peer): - v_r = self._get_valuable_blob_request(peer) - if v_r is not None: - v_p_r = self._get_valuable_price_request(peer, protocol) - reserved_points = self._reserve_points_valuable(peer, protocol, v_r.max_pay_units) - if reserved_points is not None: - d1 = protocol.add_request(v_r) - d1.addCallback(self._handle_valuable_blob_response, peer, v_r) - d1.addBoth(self._pay_or_cancel_payment, protocol, reserved_points, - self._info_protocol_prices) - d1.addErrback(self._request_failed, "valuable blob request", peer) - sent_request = True - if v_p_r is not None: - d2 = protocol.add_request(v_p_r) - d2.addCallback(self._handle_valuable_price_response, peer, v_p_r, protocol) - d2.addErrback(self._request_failed, "valuable price request", peer) - else: - return defer.fail(InsufficientFundsError()) - i_r = self._get_info_request(peer) - if i_r is not None: - i_p_r = self._get_info_price_request(peer, protocol) - reserved_points = self._reserve_points_info(peer, protocol, i_r.max_pay_units) - if reserved_points is not None: - d3 = protocol.add_request(i_r) - d3.addCallback(self._handle_info_response, peer, i_r, protocol, reserved_points) - d3.addBoth(self._pay_or_cancel_payment, protocol, reserved_points, - self._valuable_protocol_prices) - d3.addErrback(self._request_failed, "info request", peer, reserved_points) - sent_request = True - if i_p_r is not None: - d4 = protocol.add_request(i_p_r) - d4.addCallback(self._handle_info_price_response, peer, i_p_r, protocol) - d4.addErrback(self._request_failed, "info price request", peer) - else: - return defer.fail(InsufficientFundsError()) - return defer.succeed(sent_request) - - def get_new_peers(self): - peers = None - if self._peer_search_results: - peers = self._peer_search_results.keys() - elif len(self.approved_peers) != 0: - peers = random.sample(self.approved_peers, len(self.approved_peers)) - return defer.succeed(peers) - - ######### internal ######### - - def _should_send_request_to(self, peer): - if peer in self._incompatible_peers: - return False - if self._peers[peer] >= 0: - return True - return False - - def _get_valuable_blob_request(self, peer): - blob_hash = None - if peer in self._last_blob_hashes_from_peers: - h, expire_time = self._last_blob_hashes_from_peers[peer] - if datetime.datetime.now() > expire_time: - del self._last_blob_hashes_from_peers[peer] - else: - blob_hash = h - r_dict = {'valuable_blob_hashes': {'reference': blob_hash, 'max_blob_hashes': 20}} - response_identifier = 'valuable_blob_hashes' - request = ClientPaidRequest(r_dict, response_identifier, 20) - return request - - def _get_valuable_price_request(self, peer, protocol): - request = None - if not protocol in self._valuable_protocol_prices: - self._valuable_protocol_prices[protocol] = self.payment_rate_manager.get_rate_valuable_blob_hash(peer) - request_dict = {'valuable_blob_payment_rate': self._valuable_protocol_prices[protocol]} - request = ClientRequest(request_dict, 'valuable_blob_payment_rate') - return request - - def _get_info_request(self, peer): - if peer in self._peer_search_results: - blob_hashes = self._peer_search_results[peer] - del self._peer_search_results[peer] - references = [] - for blob_hash in blob_hashes: - if blob_hash in self._valuable_hashes: - references.append(self._valuable_hashes[blob_hash][1]) - hashes_to_search = [h for h, (s, r, p) in self._valuable_hashes.iteritems() if r in references] - if hashes_to_search: - r_dict = {'blob_length': {'blob_hashes': hashes_to_search}} - response_identifier = 'blob_length' - request = ClientPaidRequest(r_dict, response_identifier, len(hashes_to_search)) - return request - if not self._peer_search_results: - self._search_for_peers() - return None - - def _get_info_price_request(self, peer, protocol): - request = None - if not protocol in self._info_protocol_prices: - self._info_protocol_prices[protocol] = self.payment_rate_manager.get_rate_valuable_blob_info(peer) - request_dict = {'blob_length_payment_rate': self._info_protocol_prices[protocol]} - request = ClientRequest(request_dict, 'blob_length_payment_rate') - return request - - def _update_local_score(self, peer, amount): - self._peers[peer] += amount - - def _reserve_points_valuable(self, peer, protocol, max_units): - return self._reserve_points(peer, protocol, max_units, self._valuable_protocol_prices) - - def _reserve_points_info(self, peer, protocol, max_units): - return self._reserve_points(peer, protocol, max_units, self._info_protocol_prices) - - def _reserve_points(self, peer, protocol, max_units, prices): - assert protocol in prices - points_to_reserve = 1.0 * max_units * prices[protocol] / 1000.0 - return self.wallet.reserve_points(peer, points_to_reserve) - - def _pay_or_cancel_payment(self, arg, protocol, reserved_points, protocol_prices): - if isinstance(arg, Failure) or arg == 0: - self._cancel_points(reserved_points) - else: - self._pay_peer(protocol, arg, reserved_points, protocol_prices) - return arg - - def _pay_peer(self, protocol, num_units, reserved_points, prices): - assert num_units != 0 - assert protocol in prices - point_amount = 1.0 * num_units * prices[protocol] / 1000.0 - self.wallet.send_points(reserved_points, point_amount) - - def _cancel_points(self, reserved_points): - self.wallet.cancel_point_reservation(reserved_points) - - def _handle_valuable_blob_response(self, response_dict, peer, request): - if not request.response_identifier in response_dict: - return InvalidResponseError("response identifier not in response") - response = response_dict[request.response_identifier] - if 'error' in response: - if response['error'] == "RATE_UNSET": - return 0 - else: - return InvalidResponseError("Got an unknown error from the peer: %s" % - (response['error'],)) - if not 'valuable_blob_hashes' in response: - return InvalidResponseError("Missing the required field 'valuable_blob_hashes'") - hashes = response['valuable_blob_hashes'] - log.info("Handling %s valuable blob hashes from %s", str(len(hashes)), str(peer)) - expire_time = datetime.datetime.now() + datetime.timedelta(minutes=10) - reference = None - unique_hashes = set() - if 'reference' in response: - reference = response['reference'] - for blob_hash, peer_score in hashes: - if reference is None: - reference = blob_hash - self._last_blob_hashes_from_peers[peer] = (blob_hash, expire_time) - if not (blob_hash in self._valuable_hashes or blob_hash in self._blob_infos): - self._valuable_hashes[blob_hash] = (peer_score, reference, peer) - unique_hashes.add(blob_hash) - - if len(unique_hashes): - self._update_local_score(peer, len(unique_hashes)) - peer.update_stats('downloaded_valuable_blob_hashes', len(unique_hashes)) - peer.update_score(len(unique_hashes)) - else: - self._update_local_score(peer, -.0001) - return len(unique_hashes) - - def _handle_info_response(self, response_dict, peer, request): - if not request.response_identifier in response_dict: - return InvalidResponseError("response identifier not in response") - response = response_dict[request.response_identifier] - if 'error' in response: - if response['error'] == 'RATE_UNSET': - return 0 - else: - return InvalidResponseError("Got an unknown error from the peer: %s" % - (response['error'],)) - if not 'blob_lengths' in response: - return InvalidResponseError("Missing the required field 'blob_lengths'") - raw_blob_lengths = response['blob_lengths'] - log.info("Handling %s blob lengths from %s", str(len(raw_blob_lengths)), str(peer)) - log.debug("blobs: %s", str(raw_blob_lengths)) - infos = [] - unique_hashes = set() - for blob_hash, length in raw_blob_lengths: - if blob_hash in self._valuable_hashes: - peer_score, reference, peer = self._valuable_hashes[blob_hash] - del self._valuable_hashes[blob_hash] - infos.append(ValuableBlobInfo(blob_hash, length, reference, peer, peer_score)) - unique_hashes.add(blob_hash) - elif blob_hash in request.request_dict['blob_length']['blob_hashes']: - unique_hashes.add(blob_hash) - d = self.info_manager.save_blob_infos(infos) - d.addCallback(lambda _: self.download_manager.add_blobs_to_download(infos)) - - def pay_or_penalize_peer(): - if len(unique_hashes): - self._update_local_score(peer, len(unique_hashes)) - peer.update_stats('downloaded_valuable_blob_infos', len(unique_hashes)) - peer.update_score(len(unique_hashes)) - else: - self._update_local_score(peer, -.0001) - return len(unique_hashes) - - d.addCallback(lambda _: pay_or_penalize_peer()) - - return d - - def _handle_valuable_price_response(self, response_dict, peer, request, protocol): - if not request.response_identifier in response_dict: - return InvalidResponseError("response identifier not in response") - assert protocol in self._valuable_protocol_prices - response = response_dict[request.response_identifier] - if response == "RATE_ACCEPTED": - return True - else: - del self._valuable_protocol_prices[protocol] - self._price_disagreements.append(peer) - return True - - def _handle_info_price_response(self, response_dict, peer, request, protocol): - if not request.response_identifier in response_dict: - return InvalidResponseError("response identifier not in response") - assert protocol in self._info_protocol_prices - response = response_dict[request.response_identifier] - if response == "RATE_ACCEPTED": - return True - else: - del self._info_protocol_prices[protocol] - self._price_disagreements.append(peer) - return True - - def _request_failed(self, reason, request_type, peer): - if reason.check(RequestCanceledError): - return - if reason.check(NoResponseError): - self._incompatible_peers.append(peer) - log.warning("Valuable blob info requester: a request of type %s has failed. Reason: %s", - str(request_type), str(reason.getErrorMessage())) - self._update_local_score(peer, -10.0) - peer.update_score(-5.0) - if reason.check(ConnectionClosedBeforeResponseError): - return - return reason - - def _search_for_peers(self): - references_with_sources = set() - for h_list in self._peer_search_results.itervalues(): - for h in h_list: - if h in self._valuable_hashes: - references_with_sources.add(self._valuable_hashes[h][1]) - hash_to_search = None - used_references = [] - for h, (s, r, p) in self._valuable_hashes.iteritems(): - if not r in used_references: - used_references.append(r) - hash_to_search = h - if not r in references_with_sources: - break - if hash_to_search: - d = self.peer_finder.find_peers_for_blob(hash_to_search) - d.addCallback(self._set_peer_search_results, hash_to_search) - - def _set_peer_search_results(self, peers, searched_hash): - for peer in peers: - self._peer_search_results[peer].append(searched_hash) \ No newline at end of file diff --git a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindProgressManager.py b/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindProgressManager.py deleted file mode 100644 index e603dae35..000000000 --- a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindProgressManager.py +++ /dev/null @@ -1,93 +0,0 @@ -from zope.interface import implements -from lbrynet.interfaces import IProgressManager -from twisted.internet import defer - - -class BlindProgressManager(object): - implements(IProgressManager) - - def __init__(self, blob_manager, peers, max_space, blob_scorers, download_manager): - self.blob_manager = blob_manager - self.peers = peers - self.max_space = max_space - self.blob_scorers = blob_scorers - self.download_manager = download_manager - self.paused = True - self.blobs_to_download = [] - self._next_manage_downloaded_blobs = None - - def set_max_space(self, max_space): - self.max_space = max_space - - ######### IProgressManager ######### - - def start(self): - from twisted.internet import reactor - - self.paused = False - self._next_manage_downloaded_blobs = reactor.callLater(0, self._manage_downloaded_blobs) - return defer.succeed(True) - - def stop(self): - self.paused = True - if self._next_manage_downloaded_blobs is not None and self._next_manage_downloaded_blobs.active(): - self._next_manage_downloaded_blobs.cancel() - self._next_manage_downloaded_blobs = None - return defer.succeed(True) - - def stream_position(self): - return 0 - - def needed_blobs(self): - needed_blobs = [b for b in self.blobs_to_download if not b.is_validated()] - return sorted(needed_blobs, key=lambda x: x.is_downloading(), reverse=True)[:20] - - ######### internal ######### - - def _manage_downloaded_blobs(self): - - self._next_manage_downloaded_blobs = None - - from twisted.internet import reactor - - blobs = self.download_manager.blobs - blob_infos = self.download_manager.blob_infos - - blob_hashes = [b.blob_hash for b in blobs] - - blobs_to_score = [(blobs[blob_hash], blob_infos[blob_hash]) for blob_hash in blob_hashes] - - scores = self._score_blobs(blobs_to_score) - - from future_builtins import zip - - scored_blobs = zip(blobs_to_score, scores) - ranked_blobs = sorted(scored_blobs, key=lambda x: x[1], reverse=True) - - space_so_far = 0 - blobs_to_delete = [] - blobs_to_download = [] - - for (blob, blob_info), score in ranked_blobs: - space_so_far += blob.blob_length - if blob.is_validated() and space_so_far >= self.max_space: - blobs_to_delete.append(blob) - elif not blob.is_validated() and space_so_far < self.max_space: - blobs_to_download.append(blob) - - self.blob_manager.delete_blobs(blobs_to_delete) - self.blobs_to_download = blobs_to_download - - self._next_manage_downloaded_blobs = reactor.callLater(30, self._manage_downloaded_blobs) - - def _score_blobs(self, blobs): - scores = [] - for blob, blob_info in blobs: - summands = [] - multiplicands = [] - for blob_scorer in self.blob_scorers: - s, m = blob_scorer.score_blob(blob, blob_info) - summands.append(s) - multiplicands.append(m) - scores.append(1.0 * sum(summands) * reduce(lambda x, y: x * y, multiplicands, 1)) - return scores \ No newline at end of file diff --git a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindRepeater.py b/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindRepeater.py deleted file mode 100644 index 4bc9d08f1..000000000 --- a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindRepeater.py +++ /dev/null @@ -1,113 +0,0 @@ -from twisted.internet import defer -from twisted.python.failure import Failure -from lbrynet.core.client.BlobRequester import BlobRequester -from lbrynet.core.client.ConnectionManager import ConnectionManager -from lbrynet.core.client.DownloadManager import DownloadManager -from BlindMetadataHandler import BlindMetadataHandler -from BlindProgressManager import BlindProgressManager -from BlindBlobHandler import BlindBlobHandler -from collections import defaultdict -from interfaces import IBlobScorer -from zope.interface import implements - - -class PeerScoreBasedScorer(object): - implements(IBlobScorer) - - def __init__(self): - pass - - def score_blob(self, blob, blob_info): - return blob_info.peer_score, 1 - - -class LengthBasedScorer(object): - implements(IBlobScorer) - - def __init__(self): - pass - - def score_blob(self, blob, blob_info): - return 0, 1.0 * blob.get_length() / 2**21 - - -class BlindRepeater(object): - def __init__(self, peer_finder, rate_limiter, blob_manager, info_manager, wallet, payment_rate_manager): - self.peer_finder = peer_finder - self.rate_limiter = rate_limiter - self.blob_manager = blob_manager - self.info_manager = info_manager - self.wallet = wallet - self.payment_rate_manager = payment_rate_manager - self.download_manager = None - self.progress_manager = None - self.max_space = 0 - self.peers = defaultdict(int) - self.approved_peers = set() - self.stopped = True - - def setup(self): - return defer.succeed(True) - - def start(self): - if self.stopped is True: - return self._start() - else: - return defer.fail(Failure(ValueError("The repeater is already running"))) - - def stop(self): - if self.stopped is False: - return self._stop() - else: - return defer.fail(Failure(ValueError("The repeater is not running"))) - - def status(self): - if self.stopped is True: - return "stopped" - else: - return "running" - - def set_max_space(self, max_space): - self.max_space = max_space - if self.progress_manager is not None: - self.progress_manager.set_max_space(self.max_space) - - def add_approved_peer(self, peer): - self.approved_peers.add(peer) - - def remove_approved_peer(self, peer): - self.approved_peers.remove(peer) - - def _start(self): - self.download_manager = DownloadManager(self.blob_manager, True) - info_finder = BlindMetadataHandler(self.info_manager, self.peers, self.peer_finder, - self.approved_peers, self.payment_rate_manager, - self.wallet, self.download_manager) - self.download_manager.blob_info_finder = info_finder - blob_requester = BlobRequester(self.blob_manager, self.peer_finder, self.payment_rate_manager, - self.wallet, self.download_manager) - self.download_manager.blob_requester = blob_requester - self.progress_manager = BlindProgressManager(self.blob_manager, self.peers, self.max_space, - [PeerScoreBasedScorer(), LengthBasedScorer()], - self.download_manager) - self.download_manager.progress_manager = self.progress_manager - self.download_manager.blob_handler = BlindBlobHandler() - wallet_info_exchanger = self.wallet.get_info_exchanger() - self.download_manager.wallet_info_exchanger = wallet_info_exchanger - connection_manager = ConnectionManager(self, self.rate_limiter, [info_finder, blob_requester], - [wallet_info_exchanger]) - self.download_manager.connection_manager = connection_manager - d = defer.maybeDeferred(self.download_manager.start_downloading) - d.addCallback(lambda _: self._update_status(stopped=False)) - return d - - def _stop(self): - d = defer.maybeDeferred(self.download_manager.stop_downloading) - d.addCallback(lambda _: self._update_status(stopped=True)) - return d - - def _update_status(self, stopped=True): - self.stopped = stopped - - def insufficient_funds(self, err): - return self.stop() \ No newline at end of file diff --git a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindRepeaterControlHandlers.py b/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindRepeaterControlHandlers.py deleted file mode 100644 index db88d58ae..000000000 --- a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindRepeaterControlHandlers.py +++ /dev/null @@ -1,335 +0,0 @@ -from lbrynet.lbrynet_console.ControlHandlers import CommandHandler, CommandHandlerFactory -from lbrynet.lbrynet_console.ControlHandlers import RecursiveCommandHandler, ModifyPaymentRate -from twisted.internet import defer - - -class StartRepeater(CommandHandler): - prompt_description = "Start the blind repeater" - - def __init__(self, console, repeater, settings): - CommandHandler.__init__(self, console) - self.repeater = repeater - self.settings = settings - - def start(self): - #assert line is None, "Start repeater should not be passed any arguments" - d = self.settings.save_repeater_status(running=True) - d.addCallback(lambda _: self.repeater.start()) - d.addCallback(lambda _: self.console.sendLine("Started the repeater")) - d.chainDeferred(self.finished_deferred) - - -class StartRepeaterFactory(CommandHandlerFactory): - control_handler_class = StartRepeater - - -class StopRepeater(CommandHandler): - prompt_description = "Stop the blind repeater" - - def __init__(self, console, repeater, settings): - CommandHandler.__init__(self, console) - self.repeater = repeater - self.settings = settings - - def start(self): - #assert line is None, "Stop repeater should not be passed any arguments" - d = self.settings.save_repeater_status(running=False) - d.addCallback(lambda _: self.repeater.stop()) - d.addCallback(lambda _: self.console.sendLine("Stopped the repeater")) - d.chainDeferred(self.finished_deferred) - - -class StopRepeaterFactory(CommandHandlerFactory): - control_handler_class = StopRepeater - - -class UpdateMaxSpace(CommandHandler): - prompt_description = "Set the maximum space to be used by the blind repeater" - line_prompt = "Maximum space (in bytes):" - - def __init__(self, console, repeater, settings): - CommandHandler.__init__(self, console) - self.repeater = repeater - self.settings = settings - - def start(self): - self.console.sendLine(self.line_prompt) - - def handle_line(self, line): - d = self._set_max_space(line) - d.chainDeferred(self.finished_deferred) - - def _set_max_space(self, line): - max_space = int(line) - d = self.settings.save_max_space(max_space) - d.addCallback(lambda _: self.repeater.set_max_space(max_space)) - d.addCallback(lambda _: self.console.sendLine("Set the maximum space to " + str(max_space) + " bytes")) - return d - - -class UpdateMaxSpaceFactory(CommandHandlerFactory): - control_handler_class = UpdateMaxSpace - - -class AddApprovedPeer(CommandHandler): - prompt_description = "Add a peer to the approved list of peers to check for valuable blob hashes" - host_prompt = "Peer host in dotted quad (e.g. 127.0.0.1)" - port_prompt = "Peer port (e.g. 4444)" - - def __init__(self, console, repeater, peer_manager, settings): - CommandHandler.__init__(self, console) - self.repeater = repeater - self.peer_manager = peer_manager - self.settings = settings - self.host_to_add = None - - def start(self): - self.console.sendLine(self.host_prompt) - - def handle_line(self, line): - #if line is None: - # return False, defer.succeed(self.host_prompt) - if self.host_to_add is None: - self.host_to_add = line - self.console.sendLine(self.port_prompt) - else: - self.host_to_add, host = None, self.host_to_add - d = self._add_peer(host, line) - d.chainDeferred(self.finished_deferred) - - def _add_peer(self, host, port): - peer = self.peer_manager.get_peer(host, int(port)) - d = self.settings.save_approved_peer(host, int(port)) - d.addCallback(lambda _: self.repeater.add_approved_peer(peer)) - d.addCallback(lambda _: self.console.sendLine("Successfully added peer")) - return d - - -class AddApprovedPeerFactory(CommandHandlerFactory): - control_handler_class = AddApprovedPeer - - -class ApprovedPeerChooser(RecursiveCommandHandler): - - def __init__(self, console, repeater, factory_class, *args, **kwargs): - self.repeater = repeater - self.factory_class = factory_class - self.args = args - RecursiveCommandHandler.__init__(self, console, **kwargs) - - def _get_control_handler_factories(self): - control_handler_factories = [] - for peer in self.repeater.approved_peers: - control_handler_factories.append(self.factory_class(peer, *self.args)) - return control_handler_factories - - -class ApprovedPeerChooserFactory(CommandHandlerFactory): - def get_prompt_description(self): - peer = self.args[0] - return str(peer) - - -class DeleteApprovedPeerChooser(ApprovedPeerChooser): - prompt_description = "Remove a peer from the approved list of peers to check for valuable blob hashes" - - def __init__(self, console, repeater, settings): - ApprovedPeerChooser.__init__(self, console, repeater, DeleteApprovedPeerFactory, repeater, - settings, exit_after_one_done=True) - - -class DeleteApprovedPeerChooserFactory(CommandHandlerFactory): - control_handler_class = DeleteApprovedPeerChooser - - -class DeleteApprovedPeer(CommandHandler): - prompt_description = "Remove a peer from the approved list of peers to check for valuable blob hashes" - - def __init__(self, console, peer, repeater, settings): - CommandHandler.__init__(self, console) - self.repeater = repeater - self.settings = settings - self.peer_to_remove = peer - - def start(self): - d = self._remove_peer() - d.chainDeferred(self.finished_deferred) - - def _remove_peer(self): - d = self.settings.remove_approved_peer(self.peer_to_remove.host, int(self.peer_to_remove.port)) - d.addCallback(lambda _: self.repeater.remove_approved_peer(self.peer_to_remove)) - d.addCallback(lambda _: self.console.sendLine("Successfully removed peer")) - return d - - -class DeleteApprovedPeerFactory(ApprovedPeerChooserFactory): - control_handler_class = DeleteApprovedPeer - - -class ShowApprovedPeers(CommandHandler): - prompt_description = "Show the list of peers approved to be checked for valuable blob hashes" - - def __init__(self, console, repeater): - CommandHandler.__init__(self, console) - self.repeater = repeater - - def start(self): - #assert line is None, "Show approved peers should not be passed any arguments" - d = self._show_peers() - d.chainDeferred(self.finished_deferred) - - def _show_peers(self): - peer_string = "Approved peers:\n" - for peer in self.repeater.approved_peers: - peer_string += str(peer) + "\n" - self.console.sendLine(peer_string) - return defer.succeed(None) - - -class ShowApprovedPeersFactory(CommandHandlerFactory): - control_handler_class = ShowApprovedPeers - - -class RepeaterStatus(CommandHandler): - prompt_description = "Show the repeater's status" - - def __init__(self, console, repeater): - CommandHandler.__init__(self, console) - self.repeater = repeater - - def start(self): - #assert line is None, "Show repeater status should not be passed any arguments" - self._show_status() - self.finished_deferred.callback(None) - - def _show_status(self): - status_string = "Repeater status: " + self.repeater.status() + "\n" - - if self.repeater.stopped is False: - max_space = self.repeater.progress_manager.max_space - space_used = 0 - for blob in self.repeater.download_manager.blobs: - if blob.is_validated(): - space_used += blob.get_length() - - status_string += "Maximum space: " + str(max_space) + " bytes\n" - status_string += "Space used: " + str(space_used) + " bytes\n" - self.console.sendLine(status_string) - - -class RepeaterStatusFactory(CommandHandlerFactory): - control_handler_class = RepeaterStatus - - -class ModifyDataPaymentRate(ModifyPaymentRate): - prompt_description = "Modify Blind Repeater data payment rate" - - def __init__(self, console, repeater, settings): - ModifyPaymentRate.__init__(self, console) - self._prompt_choices['unset'] = (self._unset, "Use the application default data rate") - self.payment_rate_manager = repeater.payment_rate_manager - self.settings = settings - - def _unset(self): - self._set_rate(None) - return defer.succeed("Using the application default data rate") - - def _set_rate(self, rate): - - def set_data_payment_rate(rate): - self.payment_rate_manager.min_blob_data_payment_rate = rate - - d = self.settings.save_data_payment_rate(rate) - d.addCallback(lambda _: set_data_payment_rate(rate)) - return d - - def _get_current_status(self): - effective_rate = self.payment_rate_manager.get_effective_min_blob_data_payment_rate() - if self.payment_rate_manager.min_blob_data_payment_rate is None: - status = "The current data payment rate is set to use the application default, " - status += str(effective_rate) - else: - status = "The current data payment rate is " - status += str(effective_rate) - return status - - -class ModifyDataPaymentRateFactory(CommandHandlerFactory): - control_handler_class = ModifyDataPaymentRate - - -class ModifyInfoPaymentRate(ModifyPaymentRate): - prompt_description = "Modify Blind Repeater valuable info payment rate" - - def __init__(self, console, repeater, settings): - ModifyPaymentRate.__init__(self, console) - self.payment_rate_manager = repeater.payment_rate_manager - self.settings = settings - - def _set_rate(self, rate): - - def set_info_payment_rate(rate): - self.payment_rate_manager.min_valuable_blob_info_payment_rate = rate - - d = self.settings.save_valuable_info_payment_rate(rate) - d.addCallback(lambda _: set_info_payment_rate(rate)) - return d - - def _get_current_status(self): - status = "The current valuable blob info payment rate is " - status += str(self.payment_rate_manager.min_valuable_blob_info_payment_rate) - return status - - -class ModifyInfoPaymentRateFactory(CommandHandlerFactory): - control_handler_class = ModifyInfoPaymentRate - - -class ModifyHashPaymentRate(ModifyPaymentRate): - prompt_description = "Modify Blind Repeater valuable hash payment rate" - - def __init__(self, console, repeater, settings): - ModifyPaymentRate.__init__(self, console) - self.payment_rate_manager = repeater.payment_rate_manager - self.settings = settings - - def _set_rate(self, rate): - - def set_hash_payment_rate(rate): - self.payment_rate_manager.min_valuable_blob_hash_payment_rate = rate - - d = self.settings.save_valuable_hash_payment_rate(rate) - d.addCallback(lambda _: set_hash_payment_rate(rate)) - return d - - def _get_current_status(self): - status = "The current valuable blob hash payment rate is " - status += str(self.payment_rate_manager.min_valuable_blob_hash_payment_rate) - return status - - -class ModifyHashPaymentRateFactory(CommandHandlerFactory): - control_handler_class = ModifyHashPaymentRate - - -class ModifyRepeaterOptions(RecursiveCommandHandler): - prompt_description = "Modify Blind Repeater options" - - def __init__(self, console, repeater, lbry_session, settings): - self.repeater = repeater - self.lbry_session = lbry_session - self.settings = settings - RecursiveCommandHandler.__init__(self, console) - - def _get_control_handler_factories(self): - return [ModifyDataPaymentRateFactory(self.repeater, self.settings), - ModifyInfoPaymentRateFactory(self.repeater, self.settings), - ModifyHashPaymentRateFactory(self.repeater, self.settings), - UpdateMaxSpaceFactory(self.repeater, self.settings), - AddApprovedPeerFactory(self.repeater, self.lbry_session.peer_manager, self.settings), - DeleteApprovedPeerChooserFactory(self.repeater, self.settings), - ] - - -class ModifyRepeaterOptionsFactory(CommandHandlerFactory): - control_handler_class = ModifyRepeaterOptions \ No newline at end of file diff --git a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindRepeaterSettings.py b/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindRepeaterSettings.py deleted file mode 100644 index c20402b6f..000000000 --- a/lbrynet/lbrynet_console/plugins/BlindRepeater/BlindRepeaterSettings.py +++ /dev/null @@ -1,106 +0,0 @@ -from twisted.internet import threads, defer -import json -import unqlite -import os -from twisted.enterprise import adbapi -from lbrynet.core.sqlite_helpers import rerun_if_locked - -class BlindRepeaterSettings(object): - - def __init__(self, db_dir): - self.db_dir = db_dir - self.unq_db = None - self.sql_db = None - - def setup(self): - self.unq_db = unqlite.UnQLite(os.path.join(self.db_dir, "blind_settings.db")) - # check_same_thread=False is solely to quiet a spurious error that appears to be due - # to a bug in twisted, where the connection is closed by a different thread than the - # one that opened it. The individual connections in the pool are not used in multiple - # threads. - self.sql_db = adbapi.ConnectionPool('sqlite3', os.path.join(self.db_dir, "blind_peers.db"), - check_same_thread=False) - - return self.sql_db.runQuery("create table if not exists approved_peers (" + - " ip_address text, " + - " port integer" + - ")") - - def stop(self): - self.unq_db = None - self.sql_db = None - return defer.succeed(True) - - def save_repeater_status(self, running): - def save_status(): - self.unq_db["running"] = json.dumps(running) - - return threads.deferToThread(save_status) - - def get_repeater_saved_status(self): - def get_status(): - if "running" in self.unq_db: - return json.loads(self.unq_db['running']) - else: - return False - - return threads.deferToThread(get_status) - - def save_max_space(self, max_space): - def save_space(): - self.unq_db['max_space'] = json.dumps(max_space) - - return threads.deferToThread(save_space) - - def get_saved_max_space(self): - def get_space(): - if 'max_space' in self.unq_db: - return json.loads(self.unq_db['max_space']) - else: - return 0 - - return threads.deferToThread(get_space) - - @rerun_if_locked - def save_approved_peer(self, host, port): - return self.sql_db.runQuery("insert into approved_peers values (?, ?)", - (host, port)) - - @rerun_if_locked - def remove_approved_peer(self, host, port): - return self.sql_db.runQuery("delete from approved_peers where ip_address = ? and port = ?", - (host, port)) - - @rerun_if_locked - def get_approved_peers(self): - return self.sql_db.runQuery("select * from approved_peers") - - def get_data_payment_rate(self): - return threads.deferToThread(self._get_rate, "data_payment_rate") - - def save_data_payment_rate(self, rate): - return threads.deferToThread(self._save_rate, "data_payment_rate", rate) - - def get_valuable_info_payment_rate(self): - return threads.deferToThread(self._get_rate, "valuable_info_rate") - - def save_valuable_info_payment_rate(self, rate): - return threads.deferToThread(self._save_rate, "valuable_info_rate", rate) - - def get_valuable_hash_payment_rate(self): - return threads.deferToThread(self._get_rate, "valuable_hash_rate") - - def save_valuable_hash_payment_rate(self, rate): - return threads.deferToThread(self._save_rate, "valuable_hash_rate", rate) - - def _get_rate(self, rate_type): - if rate_type in self.unq_db: - return json.loads(self.unq_db[rate_type]) - else: - return None - - def _save_rate(self, rate_type, rate): - if rate is not None: - self.unq_db[rate_type] = json.dumps(rate) - elif rate_type in self.unq_db: - del self.unq_db[rate_type] \ No newline at end of file diff --git a/lbrynet/lbrynet_console/plugins/BlindRepeater/PaymentRateManager.py b/lbrynet/lbrynet_console/plugins/BlindRepeater/PaymentRateManager.py deleted file mode 100644 index 9f149f0c2..000000000 --- a/lbrynet/lbrynet_console/plugins/BlindRepeater/PaymentRateManager.py +++ /dev/null @@ -1,20 +0,0 @@ -from lbrynet.core.PaymentRateManager import PaymentRateManager - - -class BlindRepeaterPaymentRateManager(PaymentRateManager): - def __init__(self, base, valuable_info_rate, valuable_hash_rate, blob_data_rate=None): - PaymentRateManager.__init__(self, base, blob_data_rate) - self.min_valuable_blob_info_payment_rate = valuable_info_rate - self.min_valuable_blob_hash_payment_rate = valuable_hash_rate - - def get_rate_valuable_blob_info(self, peer): - return self.min_valuable_blob_info_payment_rate - - def accept_rate_valuable_blob_info(self, peer, payment_rate): - return payment_rate >= self.min_valuable_blob_info_payment_rate - - def get_rate_valuable_blob_hash(self, peer): - return self.min_valuable_blob_hash_payment_rate - - def accept_rate_valuable_blob_hash(self, peer, payment_rate): - return payment_rate >= self.min_valuable_blob_hash_payment_rate \ No newline at end of file diff --git a/lbrynet/lbrynet_console/plugins/BlindRepeater/ValuableBlobInfo.py b/lbrynet/lbrynet_console/plugins/BlindRepeater/ValuableBlobInfo.py deleted file mode 100644 index 453365c0a..000000000 --- a/lbrynet/lbrynet_console/plugins/BlindRepeater/ValuableBlobInfo.py +++ /dev/null @@ -1,9 +0,0 @@ -from lbrynet.core.BlobInfo import BlobInfo - - -class ValuableBlobInfo(BlobInfo): - def __init__(self, blob_hash, length, reference, peer, peer_score): - BlobInfo.__init__(self, blob_hash, blob_hash, length) - self.reference = reference - self.peer = peer - self.peer_score = peer_score diff --git a/lbrynet/lbrynet_console/plugins/BlindRepeater/ValuableBlobQueryHandler.py b/lbrynet/lbrynet_console/plugins/BlindRepeater/ValuableBlobQueryHandler.py deleted file mode 100644 index d8dd0009e..000000000 --- a/lbrynet/lbrynet_console/plugins/BlindRepeater/ValuableBlobQueryHandler.py +++ /dev/null @@ -1,202 +0,0 @@ -from lbrynet.interfaces import IQueryHandlerFactory, IQueryHandler -from zope.interface import implements -from twisted.internet import defer -import logging - - -log = logging.getLogger(__name__) - - -class ValuableQueryHandler(object): - implements(IQueryHandler) - - def __init__(self, wallet, payment_rate_manager): - self.wallet = wallet - self.payment_rate_manager = payment_rate_manager - self.peer = None - self.payment_rate = None - self.query_identifiers = [] - - ######### IQueryHandler ######### - - def register_with_request_handler(self, request_handler, peer): - self.peer = peer - request_handler.register_query_handler(self, self.query_identifiers) - - def handle_queries(self, queries): - pass - - -class ValuableBlobHashQueryHandlerFactory(object): - implements(IQueryHandlerFactory) - - def __init__(self, peer_finder, wallet, payment_rate_manager): - self.peer_finder = peer_finder - self.wallet = wallet - self.payment_rate_manager = payment_rate_manager - - ######### IQueryHandlerFactory ######### - - def build_query_handler(self): - q_h = ValuableBlobHashQueryHandler(self.wallet, self.payment_rate_manager, self.peer_finder) - return q_h - - def get_primary_query_identifier(self): - return 'valuable_blob_hashes' - - def get_description(self): - return "Valuable Hashes - Hashes of blobs that it may be valuable to repeat" - - -class ValuableBlobHashQueryHandler(ValuableQueryHandler): - implements(IQueryHandler) - - def __init__(self, wallet, payment_rate_manager, peer_finder): - ValuableQueryHandler.__init__(self, wallet, payment_rate_manager) - self.peer_finder = peer_finder - self.query_identifiers = ['valuable_blob_hashes', 'valuable_blob_payment_rate'] - self.valuable_blob_hash_payment_rate = None - self.blob_length_payment_rate = None - - ######### IQueryHandler ######### - - def handle_queries(self, queries): - response = {} - - def set_fields(fields): - response.update(fields) - - if self.query_identifiers[1] in queries: - d = self._handle_valuable_blob_payment_rate(queries[self.query_identifiers[1]]) - d.addCallback(set_fields) - else: - d = defer.succeed(True) - - if self.query_identifiers[0] in queries: - d.addCallback(lambda _: self._handle_valuable_blob_hashes(queries[self.query_identifiers[0]])) - d.addCallback(set_fields) - - d.addCallback(lambda _: response) - return d - - ######### internal ######### - - def _handle_valuable_blob_payment_rate(self, requested_payment_rate): - if not self.payment_rate_manager.accept_rate_valuable_blob_hash(self.peer, "VALUABLE_BLOB_HASH", - requested_payment_rate): - r = "RATE_TOO_LOW" - else: - self.valuable_blob_hash_payment_rate = requested_payment_rate - r = "RATE_ACCEPTED" - return defer.succeed({'valuable_blob_payment_rate': r}) - - def _handle_valuable_blob_hashes(self, request): - # TODO: eventually, look at the request and respond appropriately given the 'reference' field - if self.valuable_blob_hash_payment_rate is not None: - max_hashes = 20 - if 'max_blob_hashes' in request: - max_hashes = int(request['max_blob_hash']) - valuable_hashes = self.peer_finder.get_most_popular_blobs(max_hashes) - hashes_and_scores = [] - for blob_hash, count in valuable_hashes: - hashes_and_scores.append((blob_hash, 1.0 * count / 10.0)) - if len(hashes_and_scores) != 0: - log.info("Responding to a valuable blob hashes request with %s blob hashes", - str(len(hashes_and_scores))) - expected_payment = 1.0 * len(hashes_and_scores) * self.valuable_blob_hash_payment_rate / 1000.0 - self.wallet.add_expected_payment(self.peer, expected_payment) - self.peer.update_stats('uploaded_valuable_blob_hashes', len(hashes_and_scores)) - return defer.succeed({'valuable_blob_hashes': {'blob_hashes': hashes_and_scores}}) - return defer.succeed({'valuable_blob_hashes': {'error': "RATE_UNSET"}}) - - -class ValuableBlobLengthQueryHandlerFactory(object): - implements(IQueryHandlerFactory) - - def __init__(self, wallet, payment_rate_manager, blob_manager): - self.blob_manager = blob_manager - self.wallet = wallet - self.payment_rate_manager = payment_rate_manager - - ######### IQueryHandlerFactory ######### - - def build_query_handler(self): - q_h = ValuableBlobLengthQueryHandler(self.wallet, self.payment_rate_manager, self.blob_manager) - return q_h - - def get_primary_query_identifier(self): - return 'blob_length' - - def get_description(self): - return "Valuable Blob Lengths - Lengths of blobs that it may be valuable to repeat" - - -class ValuableBlobLengthQueryHandler(ValuableQueryHandler): - - def __init__(self, wallet, payment_rate_manager, blob_manager): - ValuableQueryHandler.__init__(self, wallet, payment_rate_manager) - self.blob_manager = blob_manager - self.query_identifiers = ['blob_length', 'blob_length_payment_rate'] - self.valuable_blob_hash_payment_rate = None - self.blob_length_payment_rate = None - - ######## IQueryHandler ######### - - def handle_queries(self, queries): - response = {} - - def set_fields(fields): - response.update(fields) - - if self.query_identifiers[1] in queries: - d = self._handle_blob_length_payment_rate(queries[self.query_identifiers[1]]) - d.addCallback(set_fields) - else: - d = defer.succeed(True) - - if self.query_identifiers[0] in queries: - d.addCallback(lambda _: self._handle_blob_length(queries[self.query_identifiers[0]])) - d.addCallback(set_fields) - - d.addCallback(lambda _: response) - return d - - ######### internal ######### - - def _handle_blob_length_payment_rate(self, requested_payment_rate): - if not self.payment_rate_manager.accept_rate_valuable_blob_info(self.peer, "VALUABLE_BLOB_INFO", - requested_payment_rate): - r = "RATE_TOO_LOW" - else: - self.blob_length_payment_rate = requested_payment_rate - r = "RATE_ACCEPTED" - return defer.succeed({'blob_length_payment_rate': r}) - - def _handle_blob_length(self, request): - if self.blob_length_payment_rate is not None: - assert 'blob_hashes' in request - ds = [] - - def make_response_pair(length, blob_hash): - return blob_hash, length - - for blob_hash in request['blob_hashes']: - d = self.blob_manager.get_blob_length(blob_hash) - d.addCallback(make_response_pair, blob_hash) - ds.append(d) - - dl = defer.DeferredList(ds) - - def make_response(response_pairs): - lengths = [] - for success, response_pair in response_pairs: - if success is True: - lengths.append(response_pair) - if len(lengths) > 0: - log.info("Responding with %s blob lengths", str(len(lengths))) - expected_payment = 1.0 * len(lengths) * self.blob_length_payment_rate / 1000.0 - self.wallet.add_expected_payment(self.peer, expected_payment) - self.peer.update_stats('uploaded_valuable_blob_infos', len(lengths)) - return {'blob_length': {'blob_lengths': lengths}} - - dl.addCallback(make_response) diff --git a/lbrynet/lbrynet_console/plugins/BlindRepeater/__init__.py b/lbrynet/lbrynet_console/plugins/BlindRepeater/__init__.py deleted file mode 100644 index 44966fea5..000000000 --- a/lbrynet/lbrynet_console/plugins/BlindRepeater/__init__.py +++ /dev/null @@ -1,130 +0,0 @@ -from lbrynet.lbrynet_console import Plugin -from twisted.internet import defer -from lbrynet.conf import settings -from BlindRepeater import BlindRepeater -from BlindInfoManager import BlindInfoManager -from BlindRepeaterSettings import BlindRepeaterSettings -from BlindRepeaterControlHandlers import StartRepeaterFactory, StopRepeaterFactory, UpdateMaxSpaceFactory -from BlindRepeaterControlHandlers import AddApprovedPeerFactory, DeleteApprovedPeerFactory, RepeaterStatusFactory -from BlindRepeaterControlHandlers import ShowApprovedPeersFactory, ModifyRepeaterOptionsFactory -from ValuableBlobQueryHandler import ValuableBlobLengthQueryHandlerFactory -from ValuableBlobQueryHandler import ValuableBlobHashQueryHandlerFactory - -from PaymentRateManager import BlindRepeaterPaymentRateManager - - -class BlindRepeaterPlugin(Plugin.Plugin): - - def __init__(self): - Plugin.Plugin.__init__(self) - self.enabled = False - self.blind_info_manager = None - self.valuable_blob_length_query_handler = None - self.valuable_blob_hash_query_handler = None - self.repeater = None - self.control_handlers = None - self.payment_rate_manager = None - self.settings = None - - def setup(self, lbry_console): - if not self.enabled: - return defer.succeed(True) - lbry_session = lbry_console.session - d = self._setup_settings(lbry_session.db_dir) - d.addCallback(lambda _: self._get_payment_rate_manager(lbry_session.base_payment_rate_manager)) - d.addCallback(lambda _: self._setup_blind_info_manager(lbry_session.peer_manager, lbry_session.db_dir)) - d.addCallback(lambda _: self._setup_blind_repeater(lbry_session)) - d.addCallback(lambda _: self._setup_valuable_blob_query_handler(lbry_session)) - d.addCallback(lambda _: self._create_control_handlers(lbry_session)) - d.addCallback(lambda _: self._restore_repeater_status(lbry_session)) - d.addCallback(lambda _: self._add_to_lbry_console(lbry_console)) - return d - - def stop(self): - if self.settings is not None: - return self.settings.stop() - return defer.succeed(True) - - def _setup_settings(self, db_dir): - self.settings = BlindRepeaterSettings(db_dir) - return self.settings.setup() - - def _get_payment_rate_manager(self, default_payment_rate_manager): - d1 = self.settings.get_data_payment_rate() - d2 = self.settings.get_valuable_info_payment_rate() - d3 = self.settings.get_valuable_hash_payment_rate() - - dl = defer.DeferredList([d1, d2, d3]) - - def get_payment_rate_manager(rates): - data_rate = rates[0][1] if rates[0][0] is True else None - info_rate = rates[1][1] if rates[1][0] is True else None - info_rate = info_rate if info_rate is not None else settings.min_valuable_info_rate - hash_rate = rates[2][1] if rates[2][0] is True else None - hash_rate = hash_rate if hash_rate is not None else settings.min_valuable_hash_rate - self.payment_rate_manager = BlindRepeaterPaymentRateManager(default_payment_rate_manager, - info_rate, hash_rate, - blob_data_rate=data_rate) - - dl.addCallback(get_payment_rate_manager) - return dl - - def _setup_blind_info_manager(self, peer_manager, db_dir): - self.blind_info_manager = BlindInfoManager(db_dir, peer_manager) - return self.blind_info_manager.setup() - - def _setup_valuable_blob_query_handler(self, lbry_session): - self.valuable_blob_length_query_handler = ValuableBlobLengthQueryHandlerFactory(lbry_session.blob_manager, - lbry_session.wallet, - self.payment_rate_manager) - self.valuable_blob_hash_query_handler = ValuableBlobHashQueryHandlerFactory(lbry_session.peer_finder, - lbry_session.wallet, - self.payment_rate_manager) - - def _setup_blind_repeater(self, lbry_session): - self.repeater = BlindRepeater(lbry_session.peer_finder, lbry_session.rate_limiter, - lbry_session.blob_manager, self.blind_info_manager, - lbry_session.wallet, self.payment_rate_manager) - return self.repeater.setup() - - def _restore_repeater_status(self, lbry_session): - d = self.settings.get_saved_max_space() - - def set_max_space(max_space): - self.repeater.set_max_space(max_space) - - d.addCallback(set_max_space) - - d.addCallback(lambda _: self.settings.get_approved_peers()) - - def set_approved_peers(peers): - for host, port in peers: - peer = lbry_session.peer_manager.get_peer(host, int(port)) - self.repeater.add_approved_peer(peer) - - d.addCallback(set_approved_peers) - - d.addCallback(lambda _: self.settings.get_repeater_saved_status()) - - def restore_running(running): - if running: - return self.repeater.start() - else: - return defer.succeed(True) - - d.addCallback(restore_running) - return d - - def _create_control_handlers(self, lbry_session): - category = "Blind Repeater" - control_handlers = [StartRepeaterFactory(self.repeater, self.settings), - StopRepeaterFactory(self.repeater, self.settings), - RepeaterStatusFactory(self.repeater), - ShowApprovedPeersFactory(self.repeater), - ModifyRepeaterOptionsFactory(self.repeater, lbry_session, self.settings)] - self.control_handlers = zip([category] * len(control_handlers), control_handlers) - - def _add_to_lbry_console(self, lbry_console): - lbry_console.add_control_handlers(self.control_handlers) - lbry_console.add_query_handlers([self.valuable_blob_length_query_handler, - self.valuable_blob_hash_query_handler]) \ No newline at end of file diff --git a/lbrynet/lbrynet_console/plugins/BlindRepeater/interfaces.py b/lbrynet/lbrynet_console/plugins/BlindRepeater/interfaces.py deleted file mode 100644 index 812051e9b..000000000 --- a/lbrynet/lbrynet_console/plugins/BlindRepeater/interfaces.py +++ /dev/null @@ -1,6 +0,0 @@ -from zope.interface import Interface - - -class IBlobScorer(Interface): - def score_blob(self, blob, blob_info): - pass \ No newline at end of file diff --git a/lbrynet/lbrynet_console/plugins/__init__.py b/lbrynet/lbrynet_console/plugins/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/lbrynet/lbrynet_console/plugins/blindrepeater.yapsy-plugin b/lbrynet/lbrynet_console/plugins/blindrepeater.yapsy-plugin deleted file mode 100644 index 1092f3518..000000000 --- a/lbrynet/lbrynet_console/plugins/blindrepeater.yapsy-plugin +++ /dev/null @@ -1,8 +0,0 @@ -[Core] -Name = BlindRepeater -Module = BlindRepeater - -[Documentation] -Author = LBRY -Version = 0.1 -Description = A client which blindly downloads data it judges valuable so that it can be re-uploaded for profit \ No newline at end of file diff --git a/lbrynet/lbrynet_daemon/Daemon.py b/lbrynet/lbrynet_daemon/Daemon.py index 9edc154f5..c6e609be8 100644 --- a/lbrynet/lbrynet_daemon/Daemon.py +++ b/lbrynet/lbrynet_daemon/Daemon.py @@ -32,7 +32,7 @@ from lbrynet.lbryfile.EncryptedFileMetadataManager import DBEncryptedFileMetadat from lbrynet.lbryfile.EncryptedFileMetadataManager import TempEncryptedFileMetadataManager from lbrynet.lbryfile.StreamDescriptor import EncryptedFileStreamType from lbrynet.lbryfilemanager.EncryptedFileManager import EncryptedFileManager -from lbrynet.lbrynet_console.Settings import Settings +from lbrynet.lbrynet_daemon.Settings import Settings from lbrynet.lbrynet_daemon.UIManager import UIManager from lbrynet.lbrynet_daemon.Downloader import GetStream from lbrynet.lbrynet_daemon.Publisher import Publisher diff --git a/lbrynet/lbrynet_console/Settings.py b/lbrynet/lbrynet_daemon/Settings.py similarity index 100% rename from lbrynet/lbrynet_console/Settings.py rename to lbrynet/lbrynet_daemon/Settings.py