update daemon

convert to jsonrpc, fix a few issues, remove hacky functions
This commit is contained in:
Jack 2016-03-14 12:30:22 -04:00
parent 5a8f5b14c1
commit 42df2fe242
8 changed files with 398 additions and 357 deletions

View file

@ -26,4 +26,14 @@ KNOWN_DHT_NODES = [('104.236.42.182', 4000)]
POINTTRADER_SERVER = 'http://ec2-54-187-192-68.us-west-2.compute.amazonaws.com:2424'
#POINTTRADER_SERVER = 'http://127.0.0.1:2424'
CRYPTSD_FILE_EXTENSION = ".cryptsd"
CRYPTSD_FILE_EXTENSION = ".cryptsd"
API_INTERFACE = "localhost"
API_ADDRESS = "lbryapi"
API_PORT = 5279
ICON_PATH = "app.icns"
APP_NAME = "LBRY"
DEFAULT_WALLET = "lbryum"
API_CONNECTION_STRING = "http://%s:%i/%s" % (API_INTERFACE, API_PORT, API_ADDRESS)
PROTOCOL_PREFIX = "lbry"

View file

@ -874,13 +874,15 @@ class LBRYumWallet(LBRYWallet):
d = defer.Deferred()
def check_stopped():
if self.network.is_connected():
return False
if self.network:
if self.network.is_connected():
return False
stop_check.stop()
self.network = None
d.callback(True)
self.network.stop()
if self.network:
self.network.stop()
stop_check = task.LoopingCall(check_stopped)
stop_check.start(.1)

View file

@ -3,9 +3,9 @@ Keep track of which LBRY Files are downloading and store their LBRY File specifi
"""
import logging
import datetime
import os
import sys
from datetime import datetime
from twisted.internet.task import LoopingCall
from twisted.enterprise import adbapi
@ -28,12 +28,13 @@ class LBRYFileManager(object):
Keeps track of currently opened LBRY Files, their options, and their LBRY File specific metadata.
"""
def __init__(self, session, stream_info_manager, sd_identifier):
def __init__(self, session, stream_info_manager, sd_identifier, delete_data=False):
self.session = session
self.stream_info_manager = stream_info_manager
self.sd_identifier = sd_identifier
self.lbry_files = []
self.sql_db = None
self.delete_data = delete_data
self.check_exists_loop = LoopingCall(self.check_files_exist)
if sys.platform.startswith("darwin"):
self.download_directory = os.path.join(os.path.expanduser("~"), 'Downloads')
@ -42,7 +43,7 @@ class LBRYFileManager(object):
log.debug("Download directory for LBRYFileManager: %s", str(self.download_directory))
def setup(self):
self.check_exists_loop.start(1)
self.check_exists_loop.start(10)
d = self._open_db()
d.addCallback(lambda _: self._add_to_sd_identifier())
@ -53,7 +54,14 @@ class LBRYFileManager(object):
def _disp(deleted_files):
if deleted_files[0][0]:
for file in bad_files:
print "[" + str(datetime.datetime.now()) + "] Detected " + file.file_name + " was deleted, removing from file manager"
log.info("[" + str(datetime.now()) + "] Detected " + file.file_name + " was deleted, removing from file manager")
def _delete_stream_data(lbry_file):
s_h = lbry_file.stream_hash
d = self.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
bad_files = [lbry_file for lbry_file in self.lbry_files
if lbry_file.completed == True and
@ -61,6 +69,9 @@ class LBRYFileManager(object):
d = defer.DeferredList([self.delete_lbry_file(lbry_file) for lbry_file in bad_files], consumeErrors=True)
d.addCallback(lambda files: _disp(files) if len(files) else defer.succeed(None))
if self.delete_data:
d2 = defer.DeferredList([_delete_stream_data(lbry_file) for lbry_file in bad_files], consumeErrors=True)
def get_lbry_file_status(self, lbry_file):
return self._get_lbry_file_status(lbry_file.rowid)

View file

@ -1,23 +1,21 @@
import locale
import os
import sys
import json
import simplejson as json
import binascii
import webbrowser
import xmlrpclib
import subprocess
import logging
import argparse
import pwd
import requests
from twisted.web import xmlrpc, server
from twisted.internet import defer, threads, reactor, error
from twisted.web import server, resource, static
from twisted.internet import defer, threads, error, reactor
from txjsonrpc.web import jsonrpc
from datetime import datetime
from decimal import Decimal
from StringIO import StringIO
from zipfile import ZipFile
from urllib import urlopen
from appdirs import user_data_dir
from lbrynet.core.PaymentRateManager import PaymentRateManager
from lbrynet.core.server.BlobAvailabilityHandler import BlobAvailabilityHandlerFactory
@ -33,6 +31,7 @@ from lbrynet.lbrynet_daemon.LBRYPublisher import Publisher
from lbrynet.core.utils import generate_id
from lbrynet.lbrynet_console.LBRYSettings import LBRYSettings
from lbrynet.conf import MIN_BLOB_DATA_PAYMENT_RATE, DEFAULT_MAX_SEARCH_RESULTS, KNOWN_DHT_NODES, DEFAULT_MAX_KEY_FEE
from lbrynet.conf import API_CONNECTION_STRING, API_PORT, API_ADDRESS
from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier, download_sd_blob
from lbrynet.core.Session import LBRYSession
from lbrynet.core.PTCWallet import PTCWallet
@ -41,28 +40,30 @@ from lbrynet.lbryfilemanager.LBRYFileManager import LBRYFileManager
from lbrynet.lbryfile.LBRYFileMetadataManager import DBLBRYFileMetadataManager, TempLBRYFileMetadataManager
log = logging.getLogger(__name__)
# logging.basicConfig(level=logging.DEBUG)
BAD_REQUEST = 400
NOT_FOUND = 404
OK_CODE = 200
# TODO add login credentials in a conf file
# functions to add:
# TODO send credits to address
# TODO alert if your copy of a lbry file is out of date with the name record
BAD_REQUEST = (400, "Bad request")
NOT_FOUND = (404, "Not found")
OK_CODE = 200
class Bunch:
def __init__(self, params):
self.__dict__.update(params)
class LBRYDaemon(xmlrpc.XMLRPC):
class LBRYDaemon(jsonrpc.JSONRPC):
"""
LBRYnet daemon
LBRYnet daemon, a jsonrpc interface to lbry functions
"""
isLeaf = True
def setup(self, wallet_type, check_for_updates):
def _set_vars(wallet_type, check_for_updates):
reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
self.fetcher = None
self.current_db_revision = 1
self.run_server = True
@ -71,7 +72,8 @@ class LBRYDaemon(xmlrpc.XMLRPC):
if sys.platform != "darwin":
self.db_dir = os.path.join(os.path.expanduser("~"), ".lbrynet")
else:
self.db_dir = os.path.join(os.path.expanduser("~"), "Library/Application Support/lbrynet")
self.db_dir = user_data_dir("LBRY")
# self.db_dir = os.path.join(os.path.expanduser("~"), "Library/Application Support/lbrynet")
self.blobfile_dir = os.path.join(self.db_dir, "blobfiles")
self.peer_port = 3333
self.dht_node_port = 4444
@ -82,7 +84,8 @@ class LBRYDaemon(xmlrpc.XMLRPC):
self.wallet_dir = os.path.join(get_path(FOLDERID.RoamingAppData, UserHandle.current), "lbrycrd")
elif sys.platform == "darwin":
self.download_directory = os.path.join(os.path.expanduser("~"), 'Downloads')
self.wallet_dir = os.path.join(os.path.expanduser("~"), "Library/Application Support/lbrycrd")
# self.wallet_dir = os.path.join(os.path.expanduser("~"), "Library/Application Support/lbrycrd")
self.wallet_dir = user_data_dir("LBRY")
else:
self.wallet_dir = os.path.join(os.path.expanduser("~"), ".lbrycrd")
self.download_directory = os.path.join(os.path.expanduser("~"), 'Downloads')
@ -129,15 +132,13 @@ class LBRYDaemon(xmlrpc.XMLRPC):
def _disp_startup():
if self.restart_message:
print self.restart_message
log.info(self.restart_message)
else:
print "Started LBRYnet daemon"
print "The daemon can be shut down by running 'stop-lbrynet-daemon' in a terminal"
log.info('[' + str(datetime.now()) + '] Started lbrynet-daemon')
log.info("[" + str(datetime.now()) + "] Started lbrynet-daemon")
return defer.succeed(None)
log.info('[' + str(datetime.now()) + '] Starting lbrynet-daemon')
log.info("[" + str(datetime.now()) + "] Starting lbrynet-daemon")
d = defer.Deferred()
d.addCallback(lambda _: _set_vars(wallet_type, check_for_updates))
@ -160,6 +161,9 @@ class LBRYDaemon(xmlrpc.XMLRPC):
return defer.succeed(None)
def _initial_setup(self):
return NotImplemented
def _update(self):
def _check_for_updater():
if os.path.isdir("/Applications/LBRY Updater.app"):
@ -323,7 +327,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
return dl
def _shutdown(self):
print 'Closing lbrynet session'
log.info("Closing lbrynet session")
d = self._stop_server()
if self.session is not None:
d.addCallback(lambda _: self.session.shut_down())
@ -339,7 +343,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
return defer.succeed(None)
def _setup_data_directory(self):
print "Loading databases..."
log.info("Loading databases...")
if self.created_data_dir:
db_revision = open(os.path.join(self.db_dir, "db_revision"), mode='w')
db_revision.write(str(self.current_db_revision))
@ -356,7 +360,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
old_revision = int(open(db_revision_file).read().strip())
if old_revision < self.current_db_revision:
from lbrynet.db_migrator import dbmigrator
print "Upgrading your databases..."
log.info("Upgrading your databases...")
d = threads.deferToThread(dbmigrator.migrate_db, self.db_dir, old_revision, self.current_db_revision)
def print_success(old_dirs):
@ -367,7 +371,7 @@ class LBRYDaemon(xmlrpc.XMLRPC):
success_string += old_dir
if i + 1 < len(old_dir):
success_string += ", "
print success_string
log.info(success_string)
d.addCallback(print_success)
return d
@ -396,7 +400,10 @@ class LBRYDaemon(xmlrpc.XMLRPC):
d = self.lbry_file_metadata_manager.setup()
def set_lbry_file_manager():
self.lbry_file_manager = LBRYFileManager(self.session, self.lbry_file_metadata_manager, self.sd_identifier)
self.lbry_file_manager = LBRYFileManager(self.session,
self.lbry_file_metadata_manager,
self.sd_identifier,
delete_data=True)
return self.lbry_file_manager.setup()
d.addCallback(lambda _: set_lbry_file_manager())
@ -407,12 +414,11 @@ class LBRYDaemon(xmlrpc.XMLRPC):
def get_default_data_rate():
d = self.settings.get_default_data_payment_rate()
d.addCallback(lambda rate: {"default_data_payment_rate": rate if rate is not None else
MIN_BLOB_DATA_PAYMENT_RATE})
MIN_BLOB_DATA_PAYMENT_RATE})
return d
def get_wallet():
if self.wallet_type == "lbrycrd":
print "Using lbrycrd wallet"
log.info("Using lbrycrd wallet")
lbrycrdd_path = None
if self.start_lbrycrdd is True:
@ -422,11 +428,9 @@ class LBRYDaemon(xmlrpc.XMLRPC):
d = defer.succeed(LBRYcrdWallet(self.db_dir, wallet_dir=self.wallet_dir, wallet_conf=self.lbrycrd_conf,
lbrycrdd_path=lbrycrdd_path))
elif self.wallet_type == "lbryum":
print "Using lbryum wallet"
log.info("Using lbryum wallet")
d = defer.succeed(LBRYumWallet(self.db_dir))
elif self.wallet_type == "ptc":
print "Using PTC wallet"
log.info("Using PTC wallet")
d = defer.succeed(PTCWallet(self.db_dir))
else:
@ -509,7 +513,6 @@ class LBRYDaemon(xmlrpc.XMLRPC):
for line in conf:
if len(line.strip()) and line.strip()[0] != "#":
self.lbrycrdd_path = line.strip()
print self.lbrycrdd_path
d.addCallback(load_lbrycrdd_path)
return d
@ -535,13 +538,13 @@ class LBRYDaemon(xmlrpc.XMLRPC):
def _download_name(self, name):
def _disp_file(file):
print '[' + str(datetime.now()) + ']' + ' Already downloaded: ' + str(file.stream_hash)
log.info("[" + str(datetime.now()) + "] Already downloaded: " + str(file.stream_hash))
d = self._path_from_lbry_file(file)
return d
def _get_stream(name):
def _disp(stream):
print '[' + str(datetime.now()) + ']' + ' Start stream: ' + stream['stream_hash']
log.info("[" + str(datetime.now()) + "] Start stream: " + stream['stream_hash'])
return stream
d = self.session.wallet.get_stream_info_for_name(name)
@ -556,12 +559,11 @@ class LBRYDaemon(xmlrpc.XMLRPC):
d = self._check_history(name)
d.addCallback(lambda lbry_file: _get_stream(name) if not lbry_file else _disp_file(lbry_file))
d.addCallback(lambda _: self._check_history(name))
d.addCallback(lambda lbry_file: (OK_CODE, {'stream_hash': lbry_file.stream_hash,
'path': os.path.join(self.download_directory,
lbry_file.file_name)})
if lbry_file else NOT_FOUND)
d.addErrback(lambda _: NOT_FOUND)
d.addCallback(lambda lbry_file: ({'stream_hash': lbry_file.stream_hash,
'path': os.path.join(self.download_directory,
lbry_file.file_name)})
if lbry_file else defer.fail(NOT_FOUND))
d.addErrback(lambda err: defer.fail(NOT_FOUND))
return d
def _resolve_name(self, name):
@ -595,11 +597,9 @@ class LBRYDaemon(xmlrpc.XMLRPC):
stream_hash = info['stream_hash']
path = os.path.join(self.blobfile_dir, stream_hash)
if os.path.isfile(path):
print "[" + str(datetime.now()) + "] Search for lbry_file, returning: " + stream_hash
log.info("[" + str(datetime.now()) + "] Search for lbry_file, returning: " + stream_hash)
return defer.succeed(_get_lbry_file(path))
else:
print "[" + str(datetime.now()) + "] Search for lbry_file didn't return anything"
log.info("[" + str(datetime.now()) + "] Search for lbry_file didn't return anything")
return defer.succeed(False)
@ -615,7 +615,6 @@ class LBRYDaemon(xmlrpc.XMLRPC):
def finish_deletion(lbry_file):
d = lbry_file.delete_data()
d.addCallback(lambda _: _delete_stream_data(lbry_file))
d.addCallback(lambda _: _delete_file(lbry_file))
return d
def _delete_stream_data(lbry_file):
@ -623,11 +622,10 @@ class LBRYDaemon(xmlrpc.XMLRPC):
d = self.lbry_file_manager.get_count_for_stream_hash(s_h)
# TODO: could possibly be a timing issue here
d.addCallback(lambda c: self.stream_info_manager.delete_stream(s_h) if c == 0 else True)
d.addCallback(lambda _: os.remove(os.path.join(self.download_directory, lbry_file.file_name)) if
os.path.isfile(os.path.join(self.download_directory, lbry_file.file_name)) else defer.succeed(None))
return d
def _delete_file(lbry_file):
os.remove(os.path.join(self.download_directory, lbry_file.file_name))
d.addCallback(lambda _: finish_deletion(lbry_file))
return d
@ -649,11 +647,9 @@ class LBRYDaemon(xmlrpc.XMLRPC):
def _get_est_cost(self, name):
def _check_est(d, name):
if type(d.result) is float:
print '[' + str(datetime.now()) + '] Cost est for lbry://' + name + ': ' + str(d.result) + 'LBC'
log.info('[' + str(datetime.now()) + '] Cost est for lbry://' + name + ': ' + str(d.result) + 'LBC')
log.info("[" + str(datetime.now()) + "] Cost est for lbry://" + name + ": " + str(d.result) + "LBC")
else:
print '[' + str(datetime.now()) + '] Timeout estimating cost for lbry://' + name + ', using key fee'
log.info('[' + str(datetime.now()) + '] Timeout estimating cost for lbry://' + name + ', using key fee')
log.info("[" + str(datetime.now()) + "] Timeout estimating cost for lbry://" + name + ", using key fee")
d.cancel()
return defer.succeed(None)
@ -674,17 +670,23 @@ class LBRYDaemon(xmlrpc.XMLRPC):
return d
def xmlrpc_is_running(self):
if self.startup_message != "" and self.announced_startup == False:
print "Startup message:", self.startup_message
self.announced_startup = True
return self.startup_message
elif self.announced_startup:
return True
else:
return False
def _render_response(self, result, code):
return json.dumps({'result': result, 'code': code})
def xmlrpc_get_settings(self):
def jsonrpc_is_running(self):
"""
Returns a startup message when the daemon starts, after which it will return True
"""
if self.startup_message != "" and self.announced_startup == False:
self.announced_startup = True
return self._render_response(self.startup_message, OK_CODE)
elif self.announced_startup:
return self._render_response(True, OK_CODE)
else:
return self._render_response(False, OK_CODE)
def jsonrpc_get_settings(self):
"""
Get LBRY payment settings
@ -694,74 +696,82 @@ class LBRYDaemon(xmlrpc.XMLRPC):
if not self.session_settings:
self.session_settings = {'data_rate': self.data_rate, 'max_key_fee': self.max_key_fee}
print '[' + str(datetime.now()) + '] Get daemon settings'
return self.session_settings
log.info("[" + str(datetime.now()) + "] Get daemon settings")
return self._render_response(self.session_settings, OK_CODE)
def xmlrpc_set_settings(self, settings):
def jsonrpc_set_settings(self, p):
"""
Set LBRY payment settings
@param settings dict: {'data_rate': float, 'max_key_fee': float}
@param settings: {'settings': {'data_rate': float, 'max_key_fee': float}}
"""
params = Bunch(p)
self.session_settings = settings
self.session_settings = params.settings
self._update_settings()
print '[' + str(datetime.now()) + '] Set daemon settings'
return 'Set'
log.info("[" + str(datetime.now()) + "] Set daemon settings")
return self._render_response(True, OK_CODE)
def xmlrpc_start_fetcher(self):
def jsonrpc_start_fetcher(self):
"""
Start autofetcher
Start automatically downloading new name claims as they happen
@return: confirmation message
"""
self.fetcher.start()
print '[' + str(datetime.now()) + '] Start autofetcher'
log.info('[' + str(datetime.now()) + '] Start autofetcher')
return 'Started autofetching'
return self._render_response("Started autofetching claims", OK_CODE)
def xmlrpc_stop_fetcher(self):
def jsonrpc_stop_fetcher(self):
"""
Stop autofetcher
Stop automatically downloading new name claims as they happen
@return: confirmation message
"""
self.fetcher.stop()
print '[' + str(datetime.now()) + '] Stop autofetcher'
log.info('[' + str(datetime.now()) + '] Stop autofetcher')
return 'Stopped autofetching'
return self._render_response("Stopped autofetching claims", OK_CODE)
def xmlrpc_fetcher_status(self):
def jsonrpc_fetcher_status(self):
"""
Start autofetcher
Get fetcher status
@return: True/False
"""
print '[' + str(datetime.now()) + '] Get fetcher status'
return str(self.fetcher.check_if_running())
log.info("[" + str(datetime.now()) + "] Get fetcher status")
return self._render_response(self.fetcher.check_if_running(), OK_CODE)
def xmlrpc_get_balance(self):
def jsonrpc_get_balance(self):
"""
Get LBC balance
@return: balance
"""
print '[' + str(datetime.now()) + '] Get balance'
return str(self.session.wallet.wallet_balance)
log.info("[" + str(datetime.now()) + "] Get balance")
return self._render_response(self.session.wallet.wallet_balance, OK_CODE)
def xmlrpc_stop(self):
def jsonrpc_stop(self):
"""
Stop lbrynet-daemon
@return: shutdown message
"""
def _disp_shutdown():
log.info('Shutting down lbrynet daemon')
print 'Shutting down lbrynet daemon'
log.info("Shutting down lbrynet daemon")
d = self._shutdown()
d.addCallback(lambda _: _disp_shutdown())
d.addCallback(lambda _: reactor.callLater(1.0, reactor.stop))
return defer.succeed('Shutting down')
return self._render_response("Shutting down", OK_CODE)
def xmlrpc_get_lbry_files(self):
def jsonrpc_get_lbry_files(self):
"""
Get LBRY files
@ -783,123 +793,83 @@ class LBRYDaemon(xmlrpc.XMLRPC):
r.append(json.dumps(t))
print '[' + str(datetime.now()) + '] Get LBRY files'
return r
log.info("[" + str(datetime.now()) + "] Get LBRY files")
return self._render_response(r, OK_CODE)
def xmlrpc_resolve_name(self, name):
def jsonrpc_resolve_name(self, p):
"""
Resolve stream info from a LBRY uri
@param: name
@param: {'name': name to look up}
@return: info for name claim
"""
params = Bunch(p)
def _disp(info):
print '[' + str(datetime.now()) + ']' + ' Resolved info: ' + str(info['stream_hash'])
return info
log.info("[" + str(datetime.now()) + "] Resolved info: " + info['stream_hash'])
return self._render_response(info, OK_CODE)
d = self._resolve_name(name)
d.addCallbacks(_disp, lambda _: str('UnknownNameError'))
d = self._resolve_name(params.name)
d.addCallbacks(_disp, lambda _: self._render_response('error', NOT_FOUND))
d.callback(None)
return d
def xmlrpc_get(self, name):
def jsonrpc_get(self, p):
"""
Download stream from a LBRY uri
@param: name
@return: {'stream_hash': hex string, 'path': path of download}
"""
params = Bunch(p)
if name:
d = self._download_name(name)
if params.name:
d = self._download_name(params.name)
d.addCallbacks(lambda message: self._render_response(message, OK_CODE),
lambda err: self._render_response('error', NOT_FOUND))
else:
d = defer.succeed(BAD_REQUEST)
d = self._render_response('error', BAD_REQUEST)
return d
def xmlrpc_stop_lbry_file(self, stream_hash):
def jsonrpc_stop_lbry_file(self, p):
params = Bunch(p)
try:
lbry_file = [f for f in self.lbry_file_manager.lbry_files if f.stream_hash == stream_hash][0]
lbry_file = [f for f in self.lbry_file_manager.lbry_files if f.stream_hash == params.stream_hash][0]
except IndexError:
return defer.fail(UnknownNameError)
if not lbry_file.stopped:
d = self.lbry_file_manager.toggle_lbry_file_running(lbry_file)
d.addCallback(lambda _: 'Stream has been stopped')
d.addErrback(lambda err: str(err))
d.addCallback(lambda _: self._render_response("Stream has been stopped", OK_CODE))
d.addErrback(lambda err: self._render_response(err.getTraceback(), ))
return d
else:
return defer.succeed('Stream was already stopped')
return json.dumps({'result': 'Stream was already stopped'})
def jsonrpc_start_lbry_file(self, p):
params = Bunch(p)
def xmlrpc_start_lbry_file(self, stream_hash):
try:
lbry_file = [f for f in self.lbry_file_manager.lbry_files if f.stream_hash == stream_hash][0]
lbry_file = [f for f in self.lbry_file_manager.lbry_files if f.stream_hash == params.stream_hash][0]
except IndexError:
return defer.fail(UnknownNameError)
if lbry_file.stopped:
d = self.lbry_file_manager.toggle_lbry_file_running(lbry_file)
d.callback(None)
return defer.succeed('Stream started')
return json.dumps({'result': 'Stream started'})
else:
return defer.succeed('Stream was already running')
return json.dumps({'result': 'Stream was already running'})
def xmlrpc_render_html(self, html):
"""
Writes html to lbry.html in the downloads directory, then opens it with the browser
@param html:
"""
def _make_file(html, path):
f = open(path, 'w')
f.write(html)
f.close()
return defer.succeed(None)
def _disp_err(err):
print str(err.getTraceback())
return err
path = os.path.join(self.download_directory, 'lbry.html')
d = defer.Deferred()
d.addCallback(lambda _: _make_file(html, path))
d.addCallback(lambda _: os.chown(path, pwd.getpwuid(os.getuid()).pw_uid, pwd.getpwuid(os.getuid()).pw_gid))
d.addCallback(lambda _: webbrowser.open('file://' + path))
d.addErrback(_disp_err)
d.callback(None)
return d
def xmlrpc_render_gui(self):
"""
Opens the lbry web ui in a browser
"""
def _disp_err(err):
print str(err.getTraceback())
return err
d = defer.Deferred()
if sys.platform == 'darwin':
d.addCallback(lambda _: webbrowser.get('safari').open(
"file://" + str(os.path.join(self.download_directory, "lbryio/view/page/gui.html"))))
else:
d.addCallback(lambda _: webbrowser.open(
"file://" + str(os.path.join(self.download_directory, "lbryio/view/page/gui.html"))))
d.addErrback(_disp_err)
d.callback(None)
return d
def xmlrpc_search_nametrie(self, search):
def jsonrpc_search_nametrie(self, p):
"""
Search the nametrie for claims beginning with search
@param search:
@return:
@param {'search': search string}
@return: List of search results
"""
params = Bunch(p)
def _clean(n):
t = []
@ -910,26 +880,6 @@ class LBRYDaemon(xmlrpc.XMLRPC):
t.append([i[1][0][1], i[1][1][1], i[1][2][1]])
return t
def _parse(results):
f = []
for chain, meta, cost_est in results:
t = {}
if 'name' in chain.keys():
t['name'] = chain['name']
if 'thumbnail' in meta.keys():
t['img'] = meta['thumbnail']
else:
t['img'] = 'File://' + str(
os.path.join(self.download_directory, "lbryio/web/img/Free-speech-flag.svg"))
if 'name' in meta.keys():
t['title'] = meta['name']
if 'description' in meta.keys():
t['description'] = meta['description']
t['cost_est'] = cost_est
f.append(t)
return f
def resolve_claims(claims):
ds = []
for claim in claims:
@ -941,148 +891,140 @@ class LBRYDaemon(xmlrpc.XMLRPC):
return defer.DeferredList(ds)
def _disp(results):
print '[' + str(datetime.now()) + '] Found ' + str(len(results)) + ' results'
log.info('[' + str(datetime.now()) + '] Search results: ')
for r in results:
log.info(str(r))
return results
return self._render_response(results, OK_CODE)
print '[' + str(datetime.now()) + '] Search nametrie: ' + search
log.info('[' + str(datetime.now()) + '] Search nametrie: ' + search)
log.info('[' + str(datetime.now()) + '] Search nametrie: ' + params.search)
d = self.session.wallet.get_nametrie()
d.addCallback(lambda trie: [claim for claim in trie if claim['name'].startswith(search) and 'txid' in claim])
d.addCallback(lambda trie: [claim for claim in trie if claim['name'].startswith(params.search) and 'txid' in claim])
d.addCallback(lambda claims: claims[:self.max_search_results])
d.addCallback(resolve_claims)
d.addCallback(_clean)
d.addCallback(_parse)
d.addCallback(_disp)
return d
def xmlrpc_delete_lbry_file(self, file_name):
def jsonrpc_delete_lbry_file(self, p):
"""
Delete a lbry file
@param {'file_name': string}
@return: confirmation message
"""
params = Bunch(p)
def _disp(file_name):
print '[' + str(datetime.now()) + '] Deleted: ' + file_name
return defer.succeed('Deleted: ' + file_name)
log.info("[" + str(datetime.now()) + "] Deleted: " + file_name)
return self._render_response("Deleted: " + file_name, OK_CODE)
lbry_files = [self._delete_lbry_file(f) for f in self.lbry_file_manager.lbry_files if file_name == f.file_name]
lbry_files = [self._delete_lbry_file(f) for f in self.lbry_file_manager.lbry_files if params.file_name == f.file_name]
d = defer.DeferredList(lbry_files)
d.addCallback(lambda _: _disp(file_name))
d.addCallback(lambda _: _disp(params.file_name))
return d
def xmlrpc_check(self, name):
d = self._check_history(name)
d.addCallback(lambda lbry_file: self._path_from_lbry_file(lbry_file) if lbry_file else 'Not found')
d.addErrback(lambda err: str(err))
def jsonrpc_publish(self, p):
"""
Make a new name claim
return d
@param:
@return:
"""
params = Bunch(p)
def xmlrpc_publish(self, metadata):
try:
metadata = json.loads(metadata)
except:
return defer.succeed(BAD_REQUEST)
metadata_fields = {"name": str, "file_path": str, "bid": float, "author": str, "title": str,
"description": str, "thumbnail": str, "key_fee": float, "key_fee_address": str,
"content_license": str}
log.info(params)
log.info(params.__dict__)
required = ['name', 'file_path', 'bid']
for k in metadata_fields.keys():
if k in params.__dict__.keys():
assert isinstance(params.__dict__[k], metadata_fields[k])
metadata_fields[k] = params.__dict__[k]
else:
metadata_fields[k] = None
for r in required:
if not r in metadata.keys():
return defer.succeed(BAD_REQUEST)
# if not os.path.isfile(metadata['file_path']):
# return defer.fail()
if not isinstance(metadata['bid'], float) and metadata['bid'] > 0.0:
return defer.fail()
name = metadata['name']
file_path = metadata['file_path']
bid = metadata['bid']
if 'title' in metadata.keys():
title = metadata['title']
else:
title = None
if 'description' in metadata.keys():
description = metadata['description']
else:
description = None
if 'thumbnail' in metadata.keys():
thumbnail = metadata['thumbnail']
else:
thumbnail = None
if 'key_fee' in metadata.keys():
if not float(metadata['key_fee']) == 0.0:
if not 'key_fee_address' in metadata.keys():
return defer.fail()
key_fee = metadata['key_fee']
else:
key_fee = 0.0
if 'key_fee_address' in metadata.keys():
key_fee_address = metadata['key_fee_address']
else:
key_fee_address = None
if 'content_license' in metadata.keys():
content_license = metadata['content_license']
else:
content_license = None
log.info('[' + str(datetime.now()) + '] Publish: ', name, file_path, bid, title, description, thumbnail,
key_fee, key_fee_address, content_license)
log.info("[" + str(datetime.now()) + "] Publish: ", metadata_fields)
p = Publisher(self.session, self.lbry_file_manager, self.session.wallet)
d = p.start(name, file_path, bid, title, description, thumbnail, key_fee, key_fee_address, content_license)
d.addCallback(lambda msg: (OK_CODE, msg))
d = p.start(metadata_fields['name'], metadata_fields['file_path'], metadata_fields['bid'],
metadata_fields['title'], metadata_fields['description'], metadata_fields['thumbnail'],
metadata_fields['key_fee'], metadata_fields['key_fee_address'], metadata_fields['content_license'])
d.addCallbacks(lambda msg: self._render_response(msg, OK_CODE),
lambda err: self._render_response(err.getTraceback(), BAD_REQUEST))
return d
def xmlrpc_abandon_name(self, txid):
def jsonrpc_abandon_name(self, p):
"""
Abandon and reclaim credits from a name claim
@param: {'txid': string}
@return: txid
"""
params = Bunch(p)
def _disp(txid, tx):
print '[' + str(datetime.now()) + '] Spent coins from claim tx ' + txid + ' --> ' + tx
return tx
log.info("[" + str(datetime.now()) + "] Abandoned name claim tx " + txid)
return self._render_response(txid, OK_CODE)
d = defer.Deferred()
d.addCallback(lambda _: self.session.wallet.abandon_name(txid))
d.addCallback(lambda tx: _disp(txid, tx))
d.addErrback(lambda err: str(err.getTraceback()))
d.addCallback(lambda _: self.session.wallet.abandon_name(params.txid))
d.addCallback(lambda tx: _disp(params.txid, tx))
d.addErrback(lambda err: self._render_response(err.getTraceback(), BAD_REQUEST))
d.callback(None)
return d
def xmlrpc_get_name_claims(self):
def jsonrpc_get_name_claims(self):
"""
Get name claims
@return: list of name claims
"""
def _clean(claims):
for c in claims:
for k in c.keys():
if isinstance(c[k], Decimal):
c[k] = float(c[k])
return claims
return self._render_response(claims, OK_CODE)
d = self.session.wallet.get_name_claims()
d.addCallback(_clean)
return d
def xmlrpc_get_time_behind_blockchain(self):
def jsonrpc_get_time_behind_blockchain(self):
"""
Get time behind blockchain
@return: time behind blockchain
"""
d = self.session.wallet.get_most_recent_blocktime()
d.addCallback(get_time_behind_blockchain)
d.addCallbacks(lambda result: self._render_response(result, OK_CODE),
lambda result: self._render_response(result, BAD_REQUEST))
return d
def xmlrpc_get_new_address(self):
def jsonrpc_get_new_address(self):
"""
Generate a new wallet address
@return: new wallet address
"""
def _disp(address):
print "[" + str(datetime.now()) + "] Got new wallet address: " + address
return address
log.info("[" + str(datetime.now()) + "] Got new wallet address: " + address)
return json.dumps(self._render_response(address, OK_CODE))
d = self.session.wallet.get_new_address()
d.addCallback(_disp)
return d
# def xmlrpc_update_name(self, metadata):
# def jsonrpc_update_name(self, metadata):
# def _disp(x):
# print x
# return x
@ -1102,15 +1044,15 @@ class LBRYDaemon(xmlrpc.XMLRPC):
#
# return d
def xmlrpc_toggle_fetcher_verbose(self):
def jsonrpc_toggle_fetcher_verbose(self):
if self.fetcher.verbose:
self.fetcher.verbose = False
else:
self.fetcher.verbose = True
return self.fetcher.verbose
return self._render_response(self.fetcher.verbose, OK_CODE)
def xmlrpc_check_for_new_version(self):
def jsonrpc_check_for_new_version(self):
def _check_for_updates(package):
git_version = subprocess.check_output("git ls-remote " + package['git'] + " | grep HEAD | cut -f 1", shell=True)
up_to_date = False
@ -1147,64 +1089,90 @@ class LBRYDaemon(xmlrpc.XMLRPC):
},
}
return [_check_for_updates(package_infos[p]) for p in package_infos.keys()]
r = [_check_for_updates(package_infos[p]) for p in package_infos.keys()]
log.info("[" + str(datetime.now()) + "] Check for new version: " + json.dumps(r))
return self._render_response(r, OK_CODE)
def xmlrpc_start_status_bar_app(self):
if sys.platform == 'darwin':
if os.path.isdir("/Applications/LBRY.app"):
# subprocess.Popen("screen -dmS lbry-status bash -c 'lbrynet-daemon-status --startdaemon=False'", shell=True)
subprocess.Popen("screen -dmS lbry-status bash -c 'open /Applications/LBRY.app'")
return "Started"
else:
return "Couldn't find LBRY.app, try running the installer"
else:
return "Status bar not implemented on non OS X"
def xmlrpc___dir__(self):
def jsonrpc___dir__(self):
return ['is_running', 'get_settings', 'set_settings', 'start_fetcher', 'stop_fetcher', 'fetcher_status',
'get_balance', 'stop', 'get_lbry_files', 'resolve_name', 'get', 'search_nametrie',
'delete_lbry_file', 'check', 'publish', 'abandon_name', 'get_name_claims',
'get_time_behind_blockchain', 'get_new_address', 'toggle_fetcher_verbose', 'check_for_new_version']
def stop():
daemon = xmlrpclib.ServerProxy("http://localhost:7080/")
try:
status = daemon.is_running()
except:
status = False
class LBRYDaemonCommandHandler(object):
def __init__(self, command):
self._api = jsonrpc.Proxy(API_CONNECTION_STRING)
self.command = command
if status:
daemon.stop()
print "LBRYnet daemon stopped"
else:
print "LBRYnet daemon wasn't running"
def run(self, params=None):
if params:
d = self._api.callRemote(self.command, params)
else:
d = self._api.callRemote(self.command)
return d
def main():
parser = argparse.ArgumentParser(description="Launch lbrynet-daemon")
parser.add_argument("--wallet",
help="lbrycrd or lbryum, default lbryum",
type=str,
default="lbryum")
parser.add_argument("--update",
help="True or false, default true",
type=str,
default="True")
class LBRYindex(resource.Resource):
isLeaf = False
args = parser.parse_args()
try:
daemon = xmlrpclib.ServerProxy("http://localhost:7080")
daemon.stop()
except:
pass
daemon = LBRYDaemon()
daemon.setup(args.wallet, args.update)
reactor.listenTCP(7080, server.Site(daemon), interface='localhost')
reactor.run()
def _delayed_render(self, request, results):
request.write(str(results))
request.finish()
if __name__ == '__main__':
main()
def render_GET(self, request):
def _disp(r):
log.info(r)
return "<html><table style='width:100%'>" + ''.join(r) + "</html>"
d = LBRYDaemonCommandHandler('__dir__').run()
d.addCallback(lambda functions: ["<tr><td><a href=/webapi?function=%s>%s</a></td></tr>" % (function, function) for function in functions])
d.addCallback(_disp)
d.addCallbacks(lambda results: self._delayed_render(request, results),
lambda err: self._delayed_render(request, err.getTraceback()))
return server.NOT_DONE_YET
class LBRYFilePage(resource.Resource):
isLeaf = False
def _delayed_render(self, request, results):
request.write(str(results))
request.finish()
h = "<tr><td><a href=/webapi?function=delete_lbry_file&file_name=%s>%s</a></td></tr>"
d = LBRYDaemonCommandHandler('get_lbry_files').run()
d.addCallback(lambda r: json.loads(r)['result'])
d.addCallback(lambda lbry_files: [h % (json.loads(lbry_file)['file_name'], json.loads(lbry_file)['file_name']) for lbry_file in lbry_files])
d.addCallback(lambda r: "<html><table style='width:100%'>" + ''.join(r) + "</html>")
d.addCallbacks(lambda results: self._delayed_render(request, results),
lambda err: self._delayed_render(request, err.getTraceback()))
return server.NOT_DONE_YET
class LBRYDaemonWeb(resource.Resource):
isLeaf = False
def _delayed_render(self, request, results):
request.write(str(results))
request.setResponseCode(json.loads(results)['code'])
request.finish()
def render_GET(self, request):
func = request.args['function'][0]
del request.args['function']
p = {}
for k in request.args.keys():
p[k] = request.args[k][0]
d = LBRYDaemonCommandHandler(func).run(p)
d.addCallbacks(lambda results: self._delayed_render(request, results),
lambda err: self._delayed_render(request, json.dumps({'message': err.getTraceback(), 'code': BAD_REQUEST})))
return server.NOT_DONE_YET

View file

@ -0,0 +1,51 @@
import argparse
import logging
from twisted.web import server
from twisted.internet import reactor, defer
from jsonrpc.proxy import JSONRPCProxy
from lbrynet.lbrynet_daemon.LBRYDaemon import LBRYDaemon, LBRYindex, LBRYDaemonWeb, LBRYFilePage
from lbrynet.conf import API_CONNECTION_STRING, API_INTERFACE, API_ADDRESS, API_PORT, DEFAULT_WALLET
log = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
def stop():
def _disp_shutdown():
log.info("Shutting down lbrynet-daemon from command line")
def _disp_not_running():
log.info("Attempt to shut down lbrynet-daemon from command line when daemon isn't running")
d = defer.Deferred(None)
d.addCallback(lambda _: JSONRPCProxy.from_url(API_CONNECTION_STRING).stop())
d.addCallbacks(lambda _: _disp_shutdown(), lambda _: _disp_not_running())
d.callback(None)
def start():
parser = argparse.ArgumentParser(description="Launch lbrynet-daemon")
parser.add_argument("--wallet",
help="lbrycrd or lbryum, default lbryum",
type=str,
default=DEFAULT_WALLET)
parser.add_argument("--update",
help="True or false, default true",
type=str,
default="True")
log.info("Starting lbrynet-daemon from command line")
args = parser.parse_args()
daemon = LBRYDaemon()
daemon.setup(args.wallet, args.update)
root = LBRYindex()
root.putChild("", root)
root.putChild("webapi", LBRYDaemonWeb())
root.putChild(API_ADDRESS, daemon)
root.putChild("myfiles", LBRYFilePage())
reactor.listenTCP(API_PORT, server.Site(root), interface=API_INTERFACE)
reactor.run()

View file

@ -49,13 +49,13 @@ class GetStream(object):
self.stream_hash = self.stream_info['stream_hash']
else:
print 'InvalidStreamInfoError'
log.error("InvalidStreamInfoError in autofetcher: ", stream_info)
raise InvalidStreamInfoError(self.stream_info)
if self.key_fee > self.max_key_fee:
if self.pay_key:
print "Key fee (" + str(self.key_fee) + ") above limit of " + str(
self.max_key_fee) + ", didn't download lbry://" + str(self.resolved_name)
log.info("Key fee (" + str(self.key_fee) + ") above limit of " + str(
self.max_key_fee) + ", didn't download lbry://" + str(self.resolved_name))
return defer.fail(None)
else:
pass
@ -78,7 +78,7 @@ class GetStream(object):
reserved_points = self.wallet.reserve_points(self.key_fee_address, self.key_fee)
if reserved_points is None:
return defer.fail(InsufficientFundsError())
print 'Key fee: ' + str(self.key_fee) + ' | ' + str(self.key_fee_address)
log.info("Key fee: " + str(self.key_fee) + " | " + str(self.key_fee_address))
return self.wallet.send_points_to_address(reserved_points, self.key_fee)
return defer.succeed(None)
@ -89,7 +89,7 @@ class GetStream(object):
downloader.start()
print "Downloading", self.stream_hash, "-->", os.path.join(downloader.download_directory, downloader.file_name)
log.info("Downloading", self.stream_hash, "-->", os.path.join(downloader.download_directory, downloader.file_name))
return d
@ -117,15 +117,16 @@ class FetcherDaemon(object):
self.is_running = True
self.search = LoopingCall(self._looped_search)
self.search.start(1)
log.info("Starting autofetcher")
else:
print "Autofetcher is already running"
log.info("Autofetcher is already running")
def stop(self):
if self.is_running:
self.search.stop()
self.is_running = False
else:
print "Autofetcher isn't running, there's nothing to stop"
log.info("Autofetcher isn't running, there's nothing to stop")
def check_if_running(self):
if self.is_running:
@ -157,19 +158,15 @@ class FetcherDaemon(object):
return d
def get_new_streams_in_tx(claims, t, blockhash):
#claims = self.wallet.get_claims_for_tx(t['txid'])
# if self.first_run:
# # claims = self.rpc_conn.getclaimsfortx("96aca2c60efded5806b7336430c5987b9092ffbea9c6ed444e3bf8e008993e11")
# # claims = self.rpc_conn.getclaimsfortx("cc9c7f5225ecb38877e6ca7574d110b23214ac3556b9d65784065ad3a85b4f74")
# self.first_run = False
rtn = []
if claims:
for claim in claims:
if claim not in self.seen:
msg = "[" + str(datetime.now()) + "] New claim | lbry://" + str(claim['name']) + \
" | stream hash: " + str(json.loads(claim['value'])['stream_hash'])
print msg
log.debug(msg)
log.info(msg)
if self.verbose:
print msg
rtn.append((claim['name'], t))
self.seen.append(claim)
else:
@ -179,8 +176,6 @@ class FetcherDaemon(object):
d.addCallback(lambda streams: defer.DeferredList(
[self.wallet.get_stream_info_from_txid(name, t) for name, t in streams]))
# if len(rtn):
# return defer.DeferredList([self.wallet.get_stream_info_for_name(name, txid=t) for name, t in rtn])
return d
def _download_claims(self, claims):
@ -204,12 +199,12 @@ class FetcherDaemon(object):
for l in conf:
if l.startswith("maxkey="):
settings["maxkey"] = float(l[7:].rstrip('\n'))
print "Autofetcher using max key price of", settings["maxkey"], ", to start call start_fetcher()"
conf.close()
else:
print "Autofetcher using default max key price of 0.0"
print "To change this create the file:"
print str(self.autofetcher_conf)
print "Example contents of conf file:"
print "maxkey=1.0"
conf = open(self.autofetcher_conf, "w")
conf.write("maxkey=10.0")
conf.close()
settings["maxkey"] = 10.0
log.info("No autofetcher conf file found, making one with max key fee of 10.0")
self.max_key_fee = settings["maxkey"]

View file

@ -40,7 +40,7 @@ class Publisher(object):
def _show_result():
message = "[" + str(datetime.now()) + "] Published " + self.file_name + " --> lbry://" + \
str(self.publish_name) + " with txid: " + str(self.tx_hash)
print message
log.info(message)
return defer.succeed(message)
self.publish_name = name
@ -122,6 +122,6 @@ class Publisher(object):
else:
d = defer.succeed(True)
error_message = err.getErrorMessage()
print message % (str(self.file_name), str(self.publish_name), error_message)
log.error(error_message)
log.error(message, str(self.file_name), str(self.publish_name), err.getTraceback())
return d

View file

@ -1,9 +1,11 @@
#!/usr/bin/env python
import ez_setup
ez_setup.use_setuptools()
from setuptools import setup, find_packages
import sys
import os
from setuptools import setup, find_packages
ez_setup.use_setuptools()
console_scripts = ['lbrynet-console = lbrynet.lbrynet_console.LBRYConsole:launch_lbry_console',
'lbrynet-stdin-uploader = lbrynet.lbrynet_console.LBRYStdinUploader:launch_stdin_uploader',
@ -15,8 +17,8 @@ console_scripts = ['lbrynet-console = lbrynet.lbrynet_console.LBRYConsole:launch
'lbrynet-gui = lbrynet.lbrynet_gui.gui:start_gui',
'lbrynet-lookup-hosts-for-hash = lbrynet.dht_scripts:get_hosts_for_hash_in_dht',
'lbrynet-announce_hash_to_dht = lbrynet.dht_scripts:announce_hash_to_dht',
'lbrynet-daemon = lbrynet.lbrynet_daemon.LBRYDaemon:main',
'stop-lbrynet-daemon = lbrynet.lbrynet_daemon.LBRYDaemon:stop']
'lbrynet-daemon = lbrynet.lbrynet_daemon.LBRYDaemonControl:start',
'stop-lbrynet-daemon = lbrynet.lbrynet_daemon.LBRYDaemonControl:stop']
if sys.platform == 'darwin':
console_scripts.append('lbrynet-daemon-status = lbrynet.lbrynet_daemon.LBRYOSXStatusBar:main')
@ -25,7 +27,9 @@ if sys.platform == 'darwin':
setup(name='lbrynet',
version='0.0.4',
packages=find_packages(),
install_requires=['six>=1.9.0', 'pycrypto', 'twisted', 'miniupnpc', 'yapsy', 'seccure', 'python-bitcoinrpc==0.1', 'txJSON-RPC', 'requests>=2.4.2', 'unqlite==0.2.0', 'leveldb', 'lbryum'],
install_requires=['six>=1.9.0', 'pycrypto', 'twisted', 'miniupnpc', 'yapsy', 'seccure',
'python-bitcoinrpc==0.1', 'txJSON-RPC', 'requests>=2.4.2', 'unqlite==0.2.0',
'leveldb', 'lbryum'],
entry_points={'console_scripts': console_scripts},
data_files=[
('lbrynet/lbrynet_console/plugins',
@ -47,4 +51,4 @@ setup(name='lbrynet',
)
],
dependency_links=['https://github.com/lbryio/lbryum/tarball/master/#egg=lbryum'],
)
)