1281 lines
No EOL
47 KiB
Python
1281 lines
No EOL
47 KiB
Python
import logging
|
|
from zope.interface import implements
|
|
from lbrynet.core.StreamDescriptor import PlainStreamDescriptorWriter, BlobStreamDescriptorWriter
|
|
from lbrynet.core.PaymentRateManager import PaymentRateManager
|
|
from lbrynet.lbryfilemanager.LBRYFileCreator import create_lbry_file
|
|
from lbrynet.lbryfile.StreamDescriptor import get_sd_info
|
|
from lbrynet.lbrynet_console.interfaces import IControlHandler, IControlHandlerFactory
|
|
from lbrynet.core.StreamDescriptor import download_sd_blob
|
|
from twisted.internet import defer
|
|
|
|
|
|
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
|
|
|
|
|
|
class RecursiveControlHandler(ControlHandler):
|
|
|
|
def __init__(self, exit_after_one_done=False, reset_after_each_done=False):
|
|
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):
|
|
pass
|
|
|
|
def _set_control_handlers(self):
|
|
self.control_handlers = {i + 1: handler for i, handler in enumerate(self._get_control_handler_factories())}
|
|
|
|
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:
|
|
return True, None
|
|
if num in self.control_handlers:
|
|
self.current_handler = self.control_handlers[num].get_handler()
|
|
line = None
|
|
ds = []
|
|
if self.current_handler is not None:
|
|
r = self.current_handler.handle_line(line)
|
|
done, ds = r[0], list(r[1:])
|
|
if done is True:
|
|
self.current_handler = None
|
|
if self.exit_after_one_done is True:
|
|
return r
|
|
if self.reset_after_each_done:
|
|
self._set_control_handlers()
|
|
if self.current_handler is None:
|
|
ds += [self.get_prompt()]
|
|
return (False,) + tuple(ds)
|
|
|
|
def get_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"
|
|
return defer.succeed(prompt_string)
|
|
|
|
|
|
class ModifyPaymentRate(ControlHandler):
|
|
|
|
def __init__(self):
|
|
self._prompt_choices = {'cancel': (self._cancel, "Don't change anything")}
|
|
|
|
def handle_line(self, line):
|
|
if line is None:
|
|
return False, defer.succeed(self._get_prompt_string())
|
|
elif line.lower() in self._prompt_choices:
|
|
return self._prompt_choices[line.lower()][0]()
|
|
else:
|
|
try:
|
|
rate = float(line)
|
|
except ValueError:
|
|
return True, defer.succeed("Rate must be a number")
|
|
d = self._set_rate(rate)
|
|
d.addCallback(lambda _: "Successfully set the rate")
|
|
return True, d
|
|
|
|
def _cancel(self):
|
|
return True, defer.succeed("No change was made")
|
|
|
|
def _set_rate(self, rate):
|
|
pass
|
|
|
|
def _get_current_status(self):
|
|
pass
|
|
|
|
def _get_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"
|
|
return prompt_string
|
|
|
|
|
|
class ApplicationStatus(ControlHandler):
|
|
prompt_description = "Application Status"
|
|
|
|
def __init__(self, rate_limiter, dht_node):
|
|
self.rate_limiter = rate_limiter
|
|
self.dht_node = dht_node
|
|
|
|
def handle_line(self, line):
|
|
assert line is None, "Application status should not be passed any arguments"
|
|
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"
|
|
return True, defer.succeed(status)
|
|
|
|
|
|
class ApplicationStatusFactory(ControlHandlerFactory):
|
|
control_handler_class = ApplicationStatus
|
|
|
|
|
|
class GetWalletBalances(ControlHandler):
|
|
prompt_description = "Show wallet point balances"
|
|
|
|
def __init__(self, wallet):
|
|
self.wallet = wallet
|
|
|
|
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 _get_wallet_balances(self):
|
|
d = self.wallet.get_balance()
|
|
|
|
def format_balance(balance):
|
|
balance_string = "id: 1\n"
|
|
balance_string += "balance: " + str(balance) + "\n"
|
|
return balance_string
|
|
|
|
d.addCallback(format_balance)
|
|
return d
|
|
|
|
|
|
class GetWalletBalancesFactory(ControlHandlerFactory):
|
|
control_handler_class = GetWalletBalances
|
|
|
|
|
|
class ShutDown(ControlHandler):
|
|
prompt_description = "Shut down"
|
|
|
|
def __init__(self, lbry_service):
|
|
self.lbry_service = lbry_service
|
|
|
|
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
|
|
reactor.stop()
|
|
|
|
d.addBoth(lambda _: stop_reactor())
|
|
|
|
d.addCallback(lambda _: "Shut down successfully")
|
|
return d
|
|
|
|
|
|
class ShutDownFactory(ControlHandlerFactory):
|
|
control_handler_class = ShutDown
|
|
|
|
|
|
class LBRYFileStatus(ControlHandler):
|
|
prompt_description = "Print status information for all LBRY Files"
|
|
|
|
def __init__(self, lbry_file_manager):
|
|
self.lbry_file_manager = lbry_file_manager
|
|
|
|
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 format_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)
|
|
return ''.join(status_strings)
|
|
|
|
|
|
class LBRYFileStatusFactory(ControlHandlerFactory):
|
|
control_handler_class = LBRYFileStatus
|
|
|
|
|
|
class AddStream(ControlHandler):
|
|
prompt_description = None
|
|
line_prompt = None
|
|
cancel_prompt = "Trying to locate the stream descriptor. Type \"cancel\" to cancel."
|
|
canceled_message = "Canceled locating the stream descriptor"
|
|
line_prompt2 = "Modify options? (y/n)"
|
|
line_prompt3 = "Start download? (y/n)"
|
|
|
|
def __init__(self, sd_identifier, base_payment_rate_manager):
|
|
self.sd_identifier = sd_identifier
|
|
self.loading_info_and_factories_deferred = None
|
|
self.factories = None
|
|
self.factory = None
|
|
self.info_validator = None
|
|
self.options = None
|
|
self.options_left = []
|
|
self.options_chosen = []
|
|
self.current_option = None
|
|
self.current_choice = None
|
|
self.downloader = None
|
|
self.got_options_response = False
|
|
self.loading_failed = False
|
|
self.payment_rate_manager = PaymentRateManager(base_payment_rate_manager)
|
|
|
|
def handle_line(self, line):
|
|
if line is None:
|
|
return False, defer.succeed(self.line_prompt)
|
|
if self.loading_failed is True:
|
|
return True, None
|
|
if self.loading_info_and_factories_deferred is not None:
|
|
if line.lower() == "cancel":
|
|
self.loading_info_and_factories_deferred.cancel()
|
|
self.loading_info_and_factories_deferred = None
|
|
return True, None
|
|
else:
|
|
return False, defer.succeed(self.cancel_prompt)
|
|
if self.factories is None:
|
|
self.loading_info_and_factories_deferred = self._load_info_and_factories(line)
|
|
cancel_prompt_d = defer.succeed(self.cancel_prompt)
|
|
self.loading_info_and_factories_deferred.addCallback(self._choose_factory)
|
|
self.loading_info_and_factories_deferred.addErrback(self._handle_load_canceled)
|
|
self.loading_info_and_factories_deferred.addErrback(self._handle_load_failed)
|
|
return False, cancel_prompt_d, self.loading_info_and_factories_deferred
|
|
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.factories)):
|
|
self.factory = self.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 self.current_option is not None:
|
|
if self.current_choice is None:
|
|
try:
|
|
self.current_choice = self._get_choice_from_input(line)
|
|
except InvalidChoiceError:
|
|
return False, defer.succeed(self._get_next_option_prompt(invalid_choice=True))
|
|
choice = self.current_option.option_types[self.current_choice]
|
|
if choice.value == float or choice.value == bool:
|
|
return False, defer.succeed(self._get_choice_value_prompt())
|
|
else:
|
|
value = choice.value
|
|
else:
|
|
try:
|
|
value = self._get_value_for_choice(line)
|
|
except InvalidValueError:
|
|
return False, defer.succeed(self._get_choice_value_prompt(invalid_value=True))
|
|
self.options_chosen.append(value)
|
|
self.current_choice = None
|
|
self.current_option = None
|
|
self.options_left = self.options_left[1:]
|
|
if self.options_left:
|
|
return False, defer.succeed(self._get_next_option_prompt())
|
|
else:
|
|
self.current_option = None
|
|
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 _load_info_and_factories(self, sd_file):
|
|
return defer.fail(NotImplementedError())
|
|
|
|
def _handle_load_canceled(self, err):
|
|
err.trap(defer.CancelledError)
|
|
return defer.succeed(self.canceled_message)
|
|
|
|
def _handle_load_failed(self, err):
|
|
self.loading_failed = True
|
|
log.error("An exception occurred attempting to load the stream descriptor: %s", err.getTraceback())
|
|
return defer.succeed("Encountered a problem while loading the stream descriptor: %s\n"
|
|
"See console.log for further details.\n"
|
|
"Press enter to continue" % err.getErrorMessage())
|
|
|
|
def _choose_factory(self, info_and_factories):
|
|
self.loading_info_and_factories_deferred = None
|
|
self.info_validator, self.options, self.factories = info_and_factories
|
|
if len(self.factories) == 1:
|
|
self.factory = self.factories[0]
|
|
return self._show_info_and_options()
|
|
return self._show_factory_choices()
|
|
|
|
def _show_factory_choices(self):
|
|
prompt = "Choose what to do with the file:\n"
|
|
for i, factory in enumerate(self.factories):
|
|
prompt += "[" + str(i) + "] " + factory.get_description() + '\n'
|
|
return str(prompt)
|
|
|
|
def _show_info_and_options(self):
|
|
self.options_left = self.options.get_downloader_options(self.info_validator,
|
|
self.payment_rate_manager)
|
|
prompt = "Stream info:\n"
|
|
for info_line in self.info_validator.info_to_show():
|
|
prompt += info_line[0] + ": " + info_line[1] + "\n"
|
|
prompt += "\nOptions:\n"
|
|
for option in self.options_left:
|
|
prompt += option.long_description + ": " + str(option.default_value_description) + "\n"
|
|
prompt += "\nModify options? (y/n)"
|
|
return str(prompt)
|
|
|
|
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, input):
|
|
choice = self.current_option.option_types[self.current_choice]
|
|
if choice.value == float:
|
|
try:
|
|
return float(input)
|
|
except ValueError:
|
|
raise InvalidValueError()
|
|
elif choice.value == bool:
|
|
if input == "0":
|
|
return True
|
|
elif 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()
|
|
d.addCallback(lambda stream_downloader: stream_downloader.start())
|
|
return d
|
|
|
|
def _make_downloader(self):
|
|
return self.factory.make_downloader(self.info_validator, self.options_chosen,
|
|
self.payment_rate_manager)
|
|
|
|
|
|
class AddStreamFromSD(AddStream):
|
|
prompt_description = "Add a stream from a stream descriptor file"
|
|
line_prompt = "Stream descriptor file name:"
|
|
|
|
def _load_info_and_factories(self, sd_file):
|
|
return self.sd_identifier.get_info_and_factories_for_sd_file(sd_file)
|
|
|
|
|
|
class AddStreamFromSDFactory(ControlHandlerFactory):
|
|
control_handler_class = AddStreamFromSD
|
|
|
|
|
|
class AddStreamFromHash(AddStream):
|
|
prompt_description = "Add a stream from a hash"
|
|
line_prompt = "Stream descriptor hash:"
|
|
|
|
def __init__(self, sd_identifier, session):
|
|
AddStream.__init__(self, sd_identifier, session.base_payment_rate_manager)
|
|
self.session = session
|
|
|
|
def _load_info_and_factories(self, sd_hash):
|
|
d = download_sd_blob(self.session, sd_hash, self.payment_rate_manager)
|
|
d.addCallback(self.sd_identifier.get_info_and_factories_for_sd_blob)
|
|
return d
|
|
|
|
|
|
class AddStreamFromHashFactory(ControlHandlerFactory):
|
|
control_handler_class = AddStreamFromHash
|
|
|
|
|
|
class AddStreamFromLBRYcrdName(AddStreamFromHash):
|
|
prompt_description = "Add a stream from a short name"
|
|
line_prompt = "Short name:"
|
|
|
|
def __init__(self, sd_identifier, session, name_resolver):
|
|
AddStreamFromHash.__init__(self, sd_identifier, session)
|
|
self.name_resolver = name_resolver
|
|
|
|
def _load_info_and_factories(self, name):
|
|
d = self._resolve_name(name)
|
|
d.addCallback(lambda stream_hash: AddStreamFromHash._load_info_and_factories(self, stream_hash))
|
|
return d
|
|
|
|
def _resolve_name(self, name):
|
|
def get_name_from_info(stream_info):
|
|
return stream_info['stream_hash']
|
|
d = self.name_resolver.get_stream_info_for_name(name)
|
|
d.addCallback(get_name_from_info)
|
|
return d
|
|
|
|
|
|
class AddStreamFromLBRYcrdNameFactory(ControlHandlerFactory):
|
|
control_handler_class = AddStreamFromLBRYcrdName
|
|
|
|
|
|
class LBRYFileChooser(RecursiveControlHandler):
|
|
|
|
def __init__(self, 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
|
|
RecursiveControlHandler.__init__(self, **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(lbry_file, *self.args))
|
|
return control_handler_factories
|
|
|
|
|
|
class LBRYFileChooserFactory(ControlHandlerFactory):
|
|
def get_prompt_description(self):
|
|
lbry_file = self.args[0]
|
|
return lbry_file.file_name
|
|
|
|
|
|
class DeleteLBRYFileChooser(LBRYFileChooser):
|
|
prompt_description = "Delete LBRY File"
|
|
|
|
def __init__(self, stream_info_manager, blob_manager, lbry_file_manager):
|
|
LBRYFileChooser.__init__(self, lbry_file_manager, DeleteLBRYFileFactory, stream_info_manager,
|
|
blob_manager, lbry_file_manager, exit_after_one_done=True)
|
|
|
|
|
|
class DeleteLBRYFileChooserFactory(ControlHandlerFactory):
|
|
control_handler_class = DeleteLBRYFileChooser
|
|
|
|
|
|
class DeleteLBRYFile(ControlHandler):
|
|
prompt_description = "Delete LBRY File"
|
|
line_prompt = "Also delete data? (y/n):"
|
|
|
|
def __init__(self, lbry_file, stream_info_manager, blob_manager, lbry_file_manager):
|
|
self.lbry_file = lbry_file
|
|
self.stream_info_manager = stream_info_manager
|
|
self.blob_manager = blob_manager
|
|
self.lbry_file_manager = lbry_file_manager
|
|
|
|
def handle_line(self, line):
|
|
if line is None:
|
|
return False, defer.succeed(self.line_prompt)
|
|
delete_data = False
|
|
if line == 'y' or line == 'Y':
|
|
delete_data = True
|
|
d = self._delete_lbry_file(delete_data)
|
|
d.addCallback(lambda _: "Successfully deleted " + str(self.lbry_file.stream_name))
|
|
return True, d
|
|
|
|
def _delete_lbry_file(self, delete_data):
|
|
d = self.lbry_file_manager.delete_lbry_file(self.lbry_file.stream_hash)
|
|
|
|
def finish_deletion():
|
|
if delete_data is True:
|
|
d = self._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_data(self):
|
|
d1 = self.stream_info_manager.get_blobs_for_stream(self.lbry_file.stream_hash)
|
|
|
|
def get_blob_hashes(blob_infos):
|
|
return [b[0] for b in blob_infos if b[0] is not None]
|
|
|
|
d1.addCallback(get_blob_hashes)
|
|
d2 = self.stream_info_manager.get_sd_blob_hashes_for_stream(self.lbry_file.stream_hash)
|
|
|
|
def combine_blob_hashes(results):
|
|
blob_hashes = []
|
|
for success, result in results:
|
|
if success is True:
|
|
blob_hashes.extend(result)
|
|
return blob_hashes
|
|
|
|
def delete_blobs(blob_hashes):
|
|
self.blob_manager.delete_blobs(blob_hashes)
|
|
return True
|
|
|
|
dl = defer.DeferredList([d1, d2], fireOnOneErrback=True)
|
|
dl.addCallback(combine_blob_hashes)
|
|
dl.addCallback(delete_blobs)
|
|
return dl
|
|
|
|
def _delete_stream_data(self):
|
|
return self.stream_info_manager.delete_stream(self.lbry_file.stream_hash)
|
|
|
|
|
|
class DeleteLBRYFileFactory(LBRYFileChooserFactory):
|
|
control_handler_class = DeleteLBRYFile
|
|
|
|
|
|
class ToggleLBRYFileRunningChooser(LBRYFileChooser):
|
|
prompt_description = "Toggle whether an LBRY File is running"
|
|
|
|
def __init__(self, lbry_file_manager):
|
|
LBRYFileChooser.__init__(self, lbry_file_manager, ToggleLBRYFileRunningFactory, lbry_file_manager,
|
|
exit_after_one_done=True)
|
|
|
|
|
|
class ToggleLBRYFileRunningChooserFactory(ControlHandlerFactory):
|
|
control_handler_class = ToggleLBRYFileRunningChooser
|
|
|
|
|
|
class ToggleLBRYFileRunning(ControlHandler):
|
|
prompt_description = "Toggle whether an LBRY File is running"
|
|
|
|
def __init__(self, lbry_file, lbry_file_manager):
|
|
self.lbry_file = lbry_file
|
|
self.lbry_file_manager = lbry_file_manager
|
|
|
|
def handle_line(self, line):
|
|
d = self.lbry_file_manager.toggle_lbry_file_running(self.lbry_file.stream_hash)
|
|
return True, d
|
|
|
|
|
|
class ToggleLBRYFileRunningFactory(LBRYFileChooserFactory):
|
|
control_handler_class = ToggleLBRYFileRunning
|
|
|
|
|
|
class CreateLBRYFile(ControlHandler):
|
|
prompt_description = "Create an LBRY File from file"
|
|
line_prompt = "File name: "
|
|
|
|
def __init__(self, session, lbry_file_manager):
|
|
self.session = session
|
|
self.lbry_file_manager = lbry_file_manager
|
|
|
|
def handle_line(self, line):
|
|
if line is None:
|
|
return False, defer.succeed(self.line_prompt)
|
|
else:
|
|
d = create_lbry_file(self.session, self.lbry_file_manager, line, open(line))
|
|
d.addCallback(self.add_to_lbry_files)
|
|
d.addCallback(lambda _: "Successfully created " + str(line))
|
|
return True, 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(lambda lbry_file_downloader: lbry_file_downloader.restore())
|
|
return d
|
|
|
|
|
|
class CreateLBRYFileFactory(ControlHandlerFactory):
|
|
control_handler_class = CreateLBRYFile
|
|
|
|
|
|
class PublishStreamDescriptorChooser(LBRYFileChooser):
|
|
prompt_description = "Publish a stream descriptor file to the DHT for an LBRY File"
|
|
|
|
def __init__(self, stream_info_manager, blob_manager, lbry_file_manager):
|
|
LBRYFileChooser.__init__(self, lbry_file_manager, PublishStreamDescriptorFactory, stream_info_manager,
|
|
blob_manager, lbry_file_manager, exit_after_one_done=True)
|
|
|
|
|
|
class PublishStreamDescriptorChooserFactory(ControlHandlerFactory):
|
|
control_handler_class = PublishStreamDescriptorChooser
|
|
|
|
|
|
class PublishStreamDescriptor(ControlHandler):
|
|
prompt_description = "Publish a stream descriptor file to the DHT for an LBRY File"
|
|
|
|
def __init__(self, lbry_file, stream_info_manager, blob_manager, lbry_file_manager):
|
|
self.lbry_file = lbry_file
|
|
self.stream_info_manager = stream_info_manager
|
|
self.blob_manager = blob_manager
|
|
self.lbry_file_manager = lbry_file_manager
|
|
|
|
def handle_line(self, line):
|
|
return True, self._publish_sd_blob()
|
|
|
|
def _publish_sd_blob(self):
|
|
descriptor_writer = BlobStreamDescriptorWriter(self.blob_manager)
|
|
|
|
d = get_sd_info(self.lbry_file_manager.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(LBRYFileChooserFactory):
|
|
control_handler_class = PublishStreamDescriptor
|
|
|
|
|
|
class ShowPublishedSDHashesChooser(LBRYFileChooser):
|
|
prompt_description = "Show published stream descriptors for an LBRY File"
|
|
|
|
def __init__(self, stream_info_manager, lbry_file_manager):
|
|
LBRYFileChooser.__init__(self, lbry_file_manager, ShowPublishedSDHashesFactory, stream_info_manager,
|
|
lbry_file_manager)
|
|
|
|
|
|
class ShowPublishedSDHashesChooserFactory(ControlHandlerFactory):
|
|
control_handler_class = ShowPublishedSDHashesChooser
|
|
|
|
|
|
class ShowPublishedSDHashes(ControlHandler):
|
|
prompt_description = "Show published stream descriptors for an LBRY File"
|
|
|
|
def __init__(self, lbry_file, stream_info_manager, lbry_file_manager):
|
|
self.lbry_file = lbry_file
|
|
self.stream_info_manager = stream_info_manager
|
|
self.lbry_file_manager = lbry_file_manager
|
|
|
|
def handle_line(self, line):
|
|
return True, self._show_sd_hashes()
|
|
|
|
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):
|
|
return "\n".join([str(b) for b in sd_blob_hashes])
|
|
|
|
d.addCallback(format_blob_hashes)
|
|
return d
|
|
|
|
|
|
class ShowPublishedSDHashesFactory(LBRYFileChooserFactory):
|
|
control_handler_class = ShowPublishedSDHashes
|
|
|
|
|
|
class CreatePlainStreamDescriptorChooser(LBRYFileChooser):
|
|
prompt_description = "Create a plain stream descriptor file for an LBRY File"
|
|
|
|
def __init__(self, lbry_file_manager):
|
|
LBRYFileChooser.__init__(self, lbry_file_manager, CreatePlainStreamDescriptorFactory, lbry_file_manager,
|
|
exit_after_one_done=True)
|
|
|
|
|
|
class CreatePlainStreamDescriptorChooserFactory(ControlHandlerFactory):
|
|
control_handler_class = CreatePlainStreamDescriptorChooser
|
|
|
|
|
|
class CreatePlainStreamDescriptor(ControlHandler):
|
|
prompt_description = "Create a plain stream descriptor file for an LBRY File"
|
|
line_prompt = "Stream Descriptor file name (blank for default):"
|
|
|
|
def __init__(self, lbry_file, lbry_file_manager):
|
|
self.lbry_file = lbry_file
|
|
self.lbry_file_manager = lbry_file_manager
|
|
self.sd_file_name = None
|
|
|
|
def handle_line(self, line):
|
|
if line is None:
|
|
return False, defer.succeed(self.line_prompt)
|
|
self.sd_file_name = line
|
|
return True, self._create_sd()
|
|
|
|
def _create_sd(self):
|
|
if not self.sd_file_name:
|
|
self.sd_file_name = None
|
|
descriptor_writer = PlainStreamDescriptorWriter(self.sd_file_name)
|
|
d = get_sd_info(self.lbry_file_manager.stream_info_manager, self.lbry_file.stream_hash, True)
|
|
d.addCallback(descriptor_writer.create_descriptor)
|
|
return d
|
|
|
|
|
|
class CreatePlainStreamDescriptorFactory(LBRYFileChooserFactory):
|
|
control_handler_class = CreatePlainStreamDescriptor
|
|
|
|
|
|
class ShowLBRYFileStreamHashChooser(LBRYFileChooser):
|
|
prompt_description = "Show an LBRY File's stream hash (not usually what you want)"
|
|
|
|
def __init__(self, lbry_file_manager):
|
|
LBRYFileChooser.__init__(self, lbry_file_manager, ShowLBRYFileStreamHashFactory)
|
|
|
|
|
|
class ShowLBRYFileStreamHashChooserFactory(ControlHandlerFactory):
|
|
control_handler_class = ShowLBRYFileStreamHashChooser
|
|
|
|
|
|
class ShowLBRYFileStreamHash(ControlHandler):
|
|
prompt_description = "Show an LBRY File's stream hash (not usually what you want)"
|
|
|
|
def __init__(self, lbry_file):
|
|
self.lbry_file = lbry_file
|
|
|
|
def handle_line(self, line):
|
|
return True, defer.succeed(str(self.lbry_file.stream_hash))
|
|
|
|
|
|
class ShowLBRYFileStreamHashFactory(LBRYFileChooserFactory):
|
|
control_handler_class = ShowLBRYFileStreamHash
|
|
|
|
|
|
class ModifyLBRYFileDataPaymentRate(ModifyPaymentRate):
|
|
prompt_description = "Modify LBRY File data payment rate"
|
|
|
|
def __init__(self, lbry_file, lbry_file_manager):
|
|
ModifyPaymentRate.__init__(self)
|
|
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 True, 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.stream_hash, 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 ModifyLBRYFileDataPaymentRateFactory(ControlHandlerFactory):
|
|
control_handler_class = ModifyLBRYFileDataPaymentRate
|
|
|
|
|
|
class ModifyLBRYFileOptionsChooser(LBRYFileChooser):
|
|
prompt_description = "Modify an LBRY File's options"
|
|
|
|
def __init__(self, lbry_file_manager):
|
|
LBRYFileChooser.__init__(self, lbry_file_manager, ModifyLBRYFileOptionsFactory, lbry_file_manager)
|
|
|
|
|
|
class ModifyLBRYFileOptionsChooserFactory(ControlHandlerFactory):
|
|
control_handler_class = ModifyLBRYFileOptionsChooser
|
|
|
|
|
|
class ModifyLBRYFileOptions(RecursiveControlHandler):
|
|
prompt_description = "Modify an LBRY File's options"
|
|
|
|
def __init__(self, lbry_file, lbry_file_manager):
|
|
self.lbry_file = lbry_file
|
|
self.lbry_file_manager = lbry_file_manager
|
|
RecursiveControlHandler.__init__(self)
|
|
|
|
def _get_control_handler_factories(self):
|
|
factories = []
|
|
factories.append(ModifyLBRYFileDataPaymentRateFactory(self.lbry_file, self.lbry_file_manager))
|
|
return factories
|
|
|
|
|
|
class ModifyLBRYFileOptionsFactory(LBRYFileChooserFactory):
|
|
control_handler_class = ModifyLBRYFileOptions
|
|
|
|
|
|
class ClaimName(ControlHandler):
|
|
prompt_description = "Associate a short name with a stream descriptor hash"
|
|
line_prompt = "Stream descriptor hash:"
|
|
line_prompt_2 = "Short name:"
|
|
line_prompt_3 = "Amount:"
|
|
|
|
def __init__(self, name_resolver):
|
|
self.name_resolver = name_resolver
|
|
self.sd_hash = None
|
|
self.short_name = None
|
|
self.amount = None
|
|
|
|
def handle_line(self, line):
|
|
if line is None:
|
|
return False, defer.succeed(self.line_prompt)
|
|
if self.sd_hash is None:
|
|
self.sd_hash = line
|
|
return False, defer.succeed(self.line_prompt_2)
|
|
if self.short_name is None:
|
|
self.short_name = line
|
|
return False, defer.succeed(self.line_prompt_3)
|
|
self.amount = line
|
|
return True, self._claim_name()
|
|
|
|
def _claim_name(self):
|
|
return self.name_resolver.claim_name(self.sd_hash, self.short_name, float(self.amount))
|
|
|
|
|
|
class ClaimNameFactory(ControlHandlerFactory):
|
|
control_handler_class = ClaimName
|
|
|
|
|
|
class ModifyDefaultDataPaymentRate(ModifyPaymentRate):
|
|
prompt_description = "Modify default data payment rate"
|
|
|
|
def __init__(self, payment_rate_manager, settings):
|
|
ModifyPaymentRate.__init__(self)
|
|
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(ControlHandlerFactory):
|
|
control_handler_class = ModifyDefaultDataPaymentRate
|
|
|
|
|
|
class ForceCheckBlobFileConsistency(ControlHandler):
|
|
prompt_description = "Verify consistency of stored blobs"
|
|
|
|
def __init__(self, blob_manager):
|
|
self.blob_manager = blob_manager
|
|
|
|
def handle_line(self, line):
|
|
assert line is None, "Check consistency should not be passed any arguments"
|
|
return True, self._check_consistency()
|
|
|
|
def _check_consistency(self):
|
|
d = self.blob_manager.check_consistency()
|
|
d.addCallback(lambda _: "Finished checking stored blobs")
|
|
return d
|
|
|
|
|
|
class ForceCheckBlobFileConsistencyFactory(ControlHandlerFactory):
|
|
control_handler_class = ForceCheckBlobFileConsistency
|
|
|
|
|
|
class ModifyApplicationDefaults(RecursiveControlHandler):
|
|
prompt_description = "Modify application settings"
|
|
|
|
def __init__(self, lbry_service):
|
|
self.lbry_service = lbry_service
|
|
RecursiveControlHandler.__init__(self)
|
|
|
|
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(ControlHandlerFactory):
|
|
control_handler_class = ModifyApplicationDefaults
|
|
|
|
|
|
class ShowServerStatus(ControlHandler):
|
|
prompt_description = "Show the status of the server"
|
|
|
|
def __init__(self, lbry_service):
|
|
self.lbry_service = lbry_service
|
|
|
|
def handle_line(self, line):
|
|
assert line is None, "Show server status should not be passed any arguments"
|
|
return True, self._get_status()
|
|
|
|
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"
|
|
return defer.succeed(status_string)
|
|
|
|
|
|
class ShowServerStatusFactory(ControlHandlerFactory):
|
|
control_handler_class = ShowServerStatus
|
|
|
|
|
|
class StartServer(ControlHandler):
|
|
prompt_description = "Start the server"
|
|
|
|
def __init__(self, lbry_service):
|
|
self.lbry_service = lbry_service
|
|
|
|
def handle_line(self, line):
|
|
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 _: "Successfully started the server")
|
|
return True, d
|
|
|
|
|
|
class StartServerFactory(ControlHandlerFactory):
|
|
control_handler_class = StartServer
|
|
|
|
|
|
class StopServer(ControlHandler):
|
|
prompt_description = "Stop the server"
|
|
|
|
def __init__(self, lbry_service):
|
|
self.lbry_service = lbry_service
|
|
|
|
def handle_line(self, line):
|
|
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 _: "Successfully stopped the server")
|
|
return True, d
|
|
|
|
|
|
class StopServerFactory(ControlHandlerFactory):
|
|
control_handler_class = StopServer
|
|
|
|
|
|
class ModifyServerDataPaymentRate(ModifyPaymentRate):
|
|
prompt_description = "Modify server data payment rate"
|
|
|
|
def __init__(self, payment_rate_manager, settings):
|
|
ModifyPaymentRate.__init__(self)
|
|
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 True, 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(ControlHandlerFactory):
|
|
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(ControlHandler):
|
|
def __init__(self, query_handlers, query_handler, settings):
|
|
self.query_handlers = query_handlers
|
|
self.query_handler = query_handler
|
|
self.settings = settings
|
|
|
|
def handle_line(self, line):
|
|
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 _: "Disabled the query handler")
|
|
return True, d
|
|
|
|
|
|
class DisableQueryHandlerFactory(ControlHandlerFactory):
|
|
control_handler_class = DisableQueryHandler
|
|
|
|
def get_prompt_description(self):
|
|
query_handler = self.args[1]
|
|
return "Disable " + str(query_handler.get_description())
|
|
|
|
|
|
class EnableQueryHandler(ControlHandler):
|
|
def __init__(self, query_handlers, query_handler, settings):
|
|
self.query_handlers = query_handlers
|
|
self.query_handler = query_handler
|
|
self.settings = settings
|
|
|
|
def handle_line(self, line):
|
|
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 _: "Enabled the query handler")
|
|
return True, d
|
|
|
|
|
|
class EnableQueryHandlerFactory(ControlHandlerFactory):
|
|
control_handler_class = EnableQueryHandler
|
|
|
|
def get_prompt_description(self):
|
|
query_handler = self.args[1]
|
|
return "Enable " + str(query_handler.get_description())
|
|
|
|
|
|
class ModifyServerEnabledQueries(RecursiveControlHandler):
|
|
prompt_description = "Modify which queries the server will respond to"
|
|
|
|
def __init__(self, query_handlers, settings):
|
|
self.query_handlers = query_handlers
|
|
self.settings = settings
|
|
RecursiveControlHandler.__init__(self, 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(ControlHandlerFactory):
|
|
control_handler_class = ModifyServerEnabledQueries
|
|
|
|
|
|
class ImmediateAnnounceAllBlobs(ControlHandler):
|
|
prompt_description = "Immediately announce all blob hashes to the DHT"
|
|
|
|
def __init__(self, blob_manager):
|
|
self.blob_manager = blob_manager
|
|
|
|
def handle_line(self, line):
|
|
assert line is None, "Immediate Announce should not be passed any arguments"
|
|
d = self.blob_manager.immediate_announce_all_blobs()
|
|
d.addCallback(lambda _: "Done announcing")
|
|
return True, d
|
|
|
|
|
|
class ImmediateAnnounceAllBlobsFactory(ControlHandlerFactory):
|
|
control_handler_class = ImmediateAnnounceAllBlobs
|
|
|
|
|
|
class ModifyServerSettings(RecursiveControlHandler):
|
|
prompt_description = "Modify server settings"
|
|
|
|
def __init__(self, lbry_service):
|
|
self.lbry_service = lbry_service
|
|
RecursiveControlHandler.__init__(self, 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(ControlHandlerFactory):
|
|
control_handler_class = ModifyServerSettings
|
|
|
|
|
|
class PeerChooser(RecursiveControlHandler):
|
|
|
|
def __init__(self, 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
|
|
RecursiveControlHandler.__init__(self, **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(ControlHandlerFactory):
|
|
def get_prompt_description(self):
|
|
peer = self.args[0]
|
|
return str(peer)
|
|
|
|
|
|
class ShowPeerStats(ControlHandler):
|
|
prompt_description = "Show the peer's stats"
|
|
|
|
def __init__(self, peer):
|
|
self.peer = peer
|
|
|
|
def handle_line(self, line):
|
|
return True, defer.succeed(self._get_peer_stats_string())
|
|
|
|
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(ControlHandlerFactory):
|
|
control_handler_class = ShowPeerStats
|
|
|
|
|
|
class PeerStatsAndSettings(RecursiveControlHandler):
|
|
def __init__(self, peer):
|
|
self.peer = peer
|
|
RecursiveControlHandler.__init__(self, 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, peer_manager):
|
|
PeerChooser.__init__(self, peer_manager, PeerStatsAndSettingsFactory)
|
|
|
|
|
|
class PeerStatsAndSettingsChooserFactory(ControlHandlerFactory):
|
|
control_handler_class = PeerStatsAndSettingsChooser |