diff --git a/lbrynet/__init__.py b/lbrynet/__init__.py index 7bb1777c8..655afaa08 100644 --- a/lbrynet/__init__.py +++ b/lbrynet/__init__.py @@ -4,5 +4,5 @@ log = logging.getLogger(__name__) logging.getLogger(__name__).addHandler(logging.NullHandler()) log.setLevel(logging.ERROR) -version = (0, 2, 5) +version = (0, 2, 6) __version__ = ".".join([str(x) for x in version]) diff --git a/lbrynet/conf.py b/lbrynet/conf.py index 116a395f2..9ead15f4d 100644 --- a/lbrynet/conf.py +++ b/lbrynet/conf.py @@ -17,9 +17,9 @@ MIN_VALUABLE_BLOB_HASH_PAYMENT_RATE = .05 # points/1000 infos MAX_CONNECTIONS_PER_STREAM = 5 KNOWN_DHT_NODES = [('104.236.42.182', 4000), - ('lbryum1.lbry.io', 4444), - ('lbryum2.lbry.io', 4444), - ('lbryum3.lbry.io', 4444)] + ('lbrynet1.lbry.io', 4444), + ('lbrynet2.lbry.io', 4444), + ('lbrynet3.lbry.io', 4444)] POINTTRADER_SERVER = 'http://ec2-54-187-192-68.us-west-2.compute.amazonaws.com:2424' #POINTTRADER_SERVER = 'http://127.0.0.1:2424' @@ -35,7 +35,7 @@ API_PORT = 5279 ICON_PATH = "app.icns" APP_NAME = "LBRY" API_CONNECTION_STRING = "http://%s:%i/%s" % (API_INTERFACE, API_PORT, API_ADDRESS) -UI_ADDRESS = "http://" + API_INTERFACE + ":" + str(API_PORT) +UI_ADDRESS = "http://%s:%i" % (API_INTERFACE, API_PORT) PROTOCOL_PREFIX = "lbry" DEFAULT_WALLET = "lbryum" @@ -46,3 +46,7 @@ DEFAULT_MAX_KEY_FEE = 100.0 DEFAULT_SEARCH_TIMEOUT = 3.0 DEFAULT_CACHE_TIME = 3600 DEFAULT_UI_BRANCH = "master" + +SOURCE_TYPES = ['lbry_sd_hash', 'url', 'btih'] +BASE_METADATA_FIELDS = ['title', 'description', 'author', 'language', 'license', 'content-type'] +OPTIONAL_METADATA_FIELDS = ['thumbnail', 'preview', 'fee', 'contact', 'pubkey'] \ No newline at end of file diff --git a/lbrynet/core/LBRYcrdWallet.py b/lbrynet/core/LBRYcrdWallet.py index 8807e757c..92f8d1fdf 100644 --- a/lbrynet/core/LBRYcrdWallet.py +++ b/lbrynet/core/LBRYcrdWallet.py @@ -4,6 +4,7 @@ from lbrynet.core.client.ClientRequest import ClientRequest from lbrynet.core.Error import UnknownNameError, InvalidStreamInfoError, RequestCanceledError from lbrynet.core.Error import InsufficientFundsError from lbrynet.core.sqlite_helpers import rerun_if_locked +from lbrynet.conf import BASE_METADATA_FIELDS, SOURCE_TYPES, OPTIONAL_METADATA_FIELDS from lbryum import SimpleConfig, Network from lbryum.bitcoin import COIN, TYPE_ADDRESS @@ -318,68 +319,51 @@ class LBRYWallet(object): r_dict = {} if 'value' in result: value = result['value'] + try: value_dict = json.loads(value) except (ValueError, TypeError): return Failure(InvalidStreamInfoError(name)) - known_fields = ['stream_hash', 'name', 'description', 'key_fee', 'key_fee_address', 'thumbnail', - 'content_license', 'sources', 'fee', 'author'] - known_sources = ['lbry_sd_hash', 'btih', 'url'] - known_fee_types = {'LBC': ['amount', 'address']} - for field in known_fields: - if field in value_dict: - if field == 'sources': - for source in known_sources: - if source in value_dict[field]: - if source == 'lbry_sd_hash': - r_dict['stream_hash'] = value_dict[field][source] - else: - r_dict[source] = value_dict[field][source] - elif field == 'fee': - fee = value_dict['fee'] - if 'type' in fee: - if fee['type'] in known_fee_types: - fee_fields = known_fee_types[fee['type']] - if all([f in fee for f in fee_fields]): - r_dict['key_fee'] = fee['amount'] - r_dict['key_fee_address'] = fee['address'] - else: - for f in ['key_fee', 'key_fee_address']: - if f in r_dict: - del r_dict[f] - else: - r_dict[field] = value_dict[field] - if 'stream_hash' in r_dict and 'txid' in result: - d = self._save_name_metadata(name, r_dict['stream_hash'], str(result['txid'])) - else: - d = defer.succeed(True) + r_dict['sources'] = value_dict['sources'] + for field in BASE_METADATA_FIELDS: + r_dict[field] = value_dict[field] + for field in value_dict: + if field in OPTIONAL_METADATA_FIELDS: + r_dict[field] = value_dict[field] + + if 'txid' in result: + d = self._save_name_metadata(name, r_dict['sources']['lbry_sd_hash'], str(result['txid'])) d.addCallback(lambda _: r_dict) return d elif 'error' in result: log.warning("Got an error looking up a name: %s", result['error']) - return Failure(UnknownNameError(name)) + return Failure(UnknownNameError(name)) + else: + log.warning("Got an error looking up a name: %s", json.dumps(result)) + return Failure(UnknownNameError(name)) - def claim_name(self, name, sd_hash, amount, description=None, key_fee=None, - key_fee_address=None, thumbnail=None, content_license=None, author=None, sources=None): - value = {"sources": {'lbry_sd_hash': sd_hash}} - if description is not None: - value['description'] = description - if key_fee is not None and key_fee_address is not None: - value['fee'] = {'type': 'LBC', 'amount': key_fee, 'address': key_fee_address} - if thumbnail is not None: - value['thumbnail'] = thumbnail - if content_license is not None: - value['content_license'] = content_license - if author is not None: - value['author'] = author - if isinstance(sources, dict): - sources['lbry_sd_hash'] = sd_hash - value['sources'] = sources + def claim_name(self, name, bid, sources, metadata, fee=None): + value = {'sources': {}} + for k in SOURCE_TYPES: + if k in sources: + value['sources'][k] = sources[k] + if value['sources'] == {}: + return defer.fail("No source given") + for k in BASE_METADATA_FIELDS: + if k not in metadata: + return defer.fail("Missing required field '%s'" % k) + value[k] = metadata[k] + for k in metadata: + if k not in BASE_METADATA_FIELDS: + value[k] = metadata[k] + if fee is not None: + if "LBC" in fee: + value['fee'] = {'LBC': {'amount': fee['LBC']['amount'], 'address': fee['LBC']['address']}} - d = self._send_name_claim(name, json.dumps(value), amount) + d = self._send_name_claim(name, json.dumps(value), bid) def _save_metadata(txid): - d = self._save_name_metadata(name, sd_hash, txid) + d = self._save_name_metadata(name, value['sources']['lbry_sd_hash'], txid) d.addCallback(lambda _: txid) return d @@ -409,7 +393,7 @@ class LBRYWallet(object): def abandon(results): if results[0][0] and results[1][0]: address = results[0][1] - amount = results[1][1] + amount = float(results[1][1]) return self._send_abandon(txid, address, amount) elif results[0][0] is False: return defer.fail(Failure(ValueError("Couldn't get a new address"))) @@ -826,7 +810,7 @@ class LBRYcrdWallet(LBRYWallet): @_catch_connection_error def _send_abandon_rpc(self, txid, address, amount): rpc_conn = self._get_rpc_conn() - return rpc_conn.abandonname(txid, address, amount) + return rpc_conn.abandonclaim(txid, address, amount) @_catch_connection_error def _get_blockchain_info_rpc(self): diff --git a/lbrynet/lbrynet_daemon/LBRYDaemon.py b/lbrynet/lbrynet_daemon/LBRYDaemon.py index aa47f021d..0a90bd92b 100644 --- a/lbrynet/lbrynet_daemon/LBRYDaemon.py +++ b/lbrynet/lbrynet_daemon/LBRYDaemon.py @@ -1151,12 +1151,11 @@ class LBRYDaemon(jsonrpc.JSONRPC): def _add_key_fee(data_cost): d = self._resolve_name(name) - d.addCallback(lambda info: data_cost + info['key_fee'] if 'key_fee' in info.keys() else data_cost) + d.addCallback(lambda info: data_cost if 'fee' not in info else data_cost + info['fee']['LBC']['amount']) return d d = self._resolve_name(name) - d.addCallback(lambda info: info['stream_hash'] if isinstance(info['stream_hash'], str) - else info['stream_hash']['sd_hash']) + d.addCallback(lambda info: info['sources']['lbry_sd_hash']) d.addCallback(lambda sd_hash: download_sd_blob(self.session, sd_hash, self.blob_request_payment_rate_manager)) d.addCallback(self.sd_identifier.get_metadata_for_sd_blob) @@ -1170,10 +1169,7 @@ class LBRYDaemon(jsonrpc.JSONRPC): def _get_lbry_file_by_uri(self, name): def _get_file(stream_info): - if isinstance(stream_info['stream_hash'], str) or isinstance(stream_info['stream_hash'], unicode): - sd = stream_info['stream_hash'] - elif isinstance(stream_info['stream_hash'], dict): - sd = stream_info['stream_hash']['sd_hash'] + sd = stream_info['sources']['lbry_sd_hash'] for l in self.lbry_file_manager.lbry_files: if l.sd_hash == sd: @@ -1791,15 +1787,13 @@ class LBRYDaemon(jsonrpc.JSONRPC): for r in results: t = {} t.update(r[0]) - if 'name' in r[1].keys(): - r[1]['stream_name'] = r[1]['name'] - del r[1]['name'] + if not 'thumbnail' in r[1].keys(): + r[1]['thumbnail'] = "img/Free-speech-flag.svg" t.update(r[1]) t['cost_est'] = r[2] - if not 'thumbnail' in t.keys(): - t['thumbnail'] = "img/Free-speech-flag.svg" consolidated_results.append(t) # log.info(str(t)) + return consolidated_results log.info('[' + str(datetime.now()) + '] Search nametrie: ' + search) @@ -1845,46 +1839,30 @@ class LBRYDaemon(jsonrpc.JSONRPC): def jsonrpc_publish(self, p): """ - Make a new name claim + Make a new name claim and publish associated data to lbrynet Args: 'name': name to be claimed, string 'file_path': path to file to be associated with name, string 'bid': amount of credits to commit in this claim, float - optional 'author': author, string - optional 'title': title, description - optional 'description': content description, string - optional 'thumbnail': thumbnail image url - optional 'key_fee': key fee to be paid to publisher, float (default 0.0) - optional 'key_fee_address': address for key fee to be sent to, string (defaults on new address) - optional 'content_license': content license string - optional 'sources': alternative sources dict, keys 'lbry_sd_hash', 'btih', 'url' + 'metadata': metadata dictionary + optional 'fee' Returns: - Confirmation message + Claim txid """ - - metadata_fields = ["name", "file_path", "bid", "author", "title", - "description", "thumbnail", "key_fee", "key_fee_address", - "content_license", "sources"] - - for k in metadata_fields: - if k not in p.keys(): - p[k] = None + # start(self, name, file_path, bid, metadata, fee=None, sources=None): + name = p['name'] + bid = p['bid'] + file_path = p['file_path'] + metadata = p['metadata'] + if 'fee' in p: + fee = p['fee'] + else: + fee = None pub = Publisher(self.session, self.lbry_file_manager, self.session.wallet) - d = pub.start(p['name'], - p['file_path'], - p['bid'], - title=p['title'], - description=p['description'], - thumbnail=p['thumbnail'], - key_fee=p['key_fee'], - key_fee_address=p['key_fee_address'], - content_license=p['content_license'], - author=p['author'], - sources=p['sources']) - + d = pub.start(name, file_path, bid, metadata, fee) d.addCallbacks(lambda msg: self._render_response(msg, OK_CODE), lambda err: self._render_response(err.getTraceback(), BAD_REQUEST)) diff --git a/lbrynet/lbrynet_daemon/LBRYDownloader.py b/lbrynet/lbrynet_daemon/LBRYDownloader.py index a134c44e5..ba59227c6 100644 --- a/lbrynet/lbrynet_daemon/LBRYDownloader.py +++ b/lbrynet/lbrynet_daemon/LBRYDownloader.py @@ -42,15 +42,14 @@ log.addHandler(handler) log.setLevel(logging.INFO) class GetStream(object): - def __init__(self, sd_identifier, session, wallet, lbry_file_manager, max_key_fee, pay_key=True, data_rate=0.5, - timeout=DEFAULT_TIMEOUT, download_directory=None, file_name=None): + def __init__(self, sd_identifier, session, wallet, lbry_file_manager, max_key_fee, data_rate=0.5, + timeout=DEFAULT_TIMEOUT, download_directory=None, file_name=None): self.wallet = wallet self.resolved_name = None self.description = None self.key_fee = None self.key_fee_address = None self.data_rate = data_rate - self.pay_key = pay_key self.name = None self.file_name = file_name self.session = session @@ -79,7 +78,7 @@ class GetStream(object): self.finished.callback((self.stream_hash, self.download_path)) elif self.timeout_counter >= self.timeout: - log.info("Timeout downloading lbry://" + self.resolved_name + ", " + str(self.stream_info)) + log.info("Timeout downloading lbry://%s" % self.resolved_name) self.checker.stop() self.d.cancel() self.code = STREAM_STAGES[4] @@ -88,28 +87,24 @@ class GetStream(object): def start(self, stream_info, name): self.resolved_name = name self.stream_info = stream_info - if 'stream_hash' in self.stream_info.keys(): - self.stream_hash = self.stream_info['stream_hash'] - elif 'sources' in self.stream_info.keys(): + if 'sources' in self.stream_info: self.stream_hash = self.stream_info['sources']['lbry_sd_hash'] else: raise InvalidStreamInfoError(self.stream_info) - if 'description' in self.stream_info.keys(): + if 'description' in self.stream_info: self.description = self.stream_info['description'] - if 'key_fee' in self.stream_info.keys(): - self.key_fee = float(self.stream_info['key_fee']) - if 'key_fee_address' in self.stream_info.keys(): - self.key_fee_address = self.stream_info['key_fee_address'] + if 'fee' in self.stream_info: + if 'LBC' in self.stream_info['fee']: + self.key_fee = float(self.stream_info['fee']['LBC']['amount']) + self.key_fee_address = self.stream_info['fee']['LBC']['address'] else: self.key_fee_address = None else: self.key_fee = None self.key_fee_address = None if self.key_fee > self.max_key_fee: - if self.pay_key: - 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) + log.info("Key fee %f above limit of %f didn't download lbry://%s" % (self.key_fee, self.max_key_fee, self.resolved_name)) + return defer.fail(None) else: pass @@ -145,7 +140,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()) - log.info("Key fee: " + str(self.key_fee) + " | " + str(self.key_fee_address)) + log.info("Key fee: %f --> %s" % (self.key_fee, self.key_fee_address)) return self.wallet.send_points_to_address(reserved_points, self.key_fee) return defer.succeed(None) @@ -155,5 +150,5 @@ class GetStream(object): d = defer.Deferred() self.downloader = downloader self.download_path = os.path.join(downloader.download_directory, downloader.file_name) - d.addCallback(lambda _: log.info("[" + str(datetime.now()) + "] Downloading " + str(self.stream_hash) + " --> " + str(self.download_path))) + d.addCallback(lambda _: log.info("[%s] Downloading %s --> %s" % (datetime.now(), self.stream_hash, self.file_name))) d.addCallback(lambda _: self.downloader.start()) diff --git a/lbrynet/lbrynet_daemon/LBRYPublisher.py b/lbrynet/lbrynet_daemon/LBRYPublisher.py index f7fd64f57..084731a87 100644 --- a/lbrynet/lbrynet_daemon/LBRYPublisher.py +++ b/lbrynet/lbrynet_daemon/LBRYPublisher.py @@ -1,4 +1,5 @@ import logging +import mimetypes import os import sys @@ -36,42 +37,27 @@ class Publisher(object): self.received_file_name = False self.file_path = None self.file_name = None - self.thumbnail = 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 - self.content_license = None - self.author = None - self.sources = None + self.txid = None + self.sources = {} + self.fee = None - def start(self, name, file_path, bid, title=None, description=None, thumbnail=None, - key_fee=None, key_fee_address=None, content_license=None, author=None, sources=None): + def start(self, name, file_path, bid, metadata, fee=None, sources={}): def _show_result(): - message = "[" + str(datetime.now()) + "] Published " + self.file_name + " --> lbry://" + \ - str(self.publish_name) + " with txid: " + str(self.tx_hash) + + message = "[%s] Published %s --> lbry://%s txid: %s" % (datetime.now(), self.file_name, self.publish_name, self.txid) log.info(message) - return defer.succeed(self.tx_hash) + return defer.succeed(self.txid) self.publish_name = name self.file_path = file_path self.bid_amount = bid - self.title = title - self.description = description - self.thumbnail = thumbnail - self.key_fee = key_fee - self.key_fee_address = key_fee_address - self.content_license = content_license - self.author = author - self.sources = sources + self.fee = fee + self.metadata = metadata d = self._check_file_path(self.file_path) d.addCallback(lambda _: create_lbry_file(self.session, self.lbry_file_manager, @@ -118,20 +104,21 @@ class Publisher(object): self.lbry_file.stream_hash) def set_sd_hash(sd_hash): - self.sd_hash = sd_hash + self.sources['lbry_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, thumbnail=self.thumbnail, - content_license=self.content_license, author=self.author, - sources=self.sources) - - def set_tx_hash(tx_hash): - self.tx_hash = tx_hash + self.metadata['content-type'] = mimetypes.guess_type(os.path.join(self.lbry_file.download_directory, + self.lbry_file.file_name))[0] + d = self.wallet.claim_name(self.publish_name, + self.bid_amount, + self.sources, + self.metadata, + fee=self.fee) + def set_tx_hash(txid): + self.txid = txid d.addCallback(set_tx_hash) return d