Merge pull request #586 from lbryio/lbryschema_2
Lbryschema integration
This commit is contained in:
commit
6f909f9654
16 changed files with 132 additions and 102 deletions
|
@ -14,7 +14,7 @@ at anytime.
|
||||||
*
|
*
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
*
|
* Use lbryschema library for metadata
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ Install [xcode command line tools](https://developer.xamarin.com/guides/testclou
|
||||||
Remaining dependencies can then be installed by running:
|
Remaining dependencies can then be installed by running:
|
||||||
|
|
||||||
```
|
```
|
||||||
brew install mpfr libmpc
|
brew install mpfr libmpc protobuf
|
||||||
sudo easy_install pip
|
sudo easy_install pip
|
||||||
sudo pip install virtualenv
|
sudo pip install virtualenv
|
||||||
```
|
```
|
||||||
|
@ -26,7 +26,7 @@ On Ubuntu (we recommend 16.04), install the following:
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo apt-get install libgmp3-dev build-essential python2.7 python2.7-dev \
|
sudo apt-get install libgmp3-dev build-essential python2.7 python2.7-dev \
|
||||||
python-pip git python-virtualenv libssl-dev libffi-dev
|
python-pip git python-virtualenv libssl-dev libffi-dev python-protobuf
|
||||||
```
|
```
|
||||||
|
|
||||||
If you're running another Linux flavor, install the equivalent of the above packages for your system.
|
If you're running another Linux flavor, install the equivalent of the above packages for your system.
|
||||||
|
|
|
@ -10,7 +10,7 @@ def get_sd_hash(stream_info):
|
||||||
if not stream_info:
|
if not stream_info:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
return stream_info['sources']['lbry_sd_hash']
|
return stream_info['stream']['source']['source']
|
||||||
except (KeyError, TypeError, ValueError):
|
except (KeyError, TypeError, ValueError):
|
||||||
log.debug('Failed to get sd_hash from %s', stream_info, exc_info=True)
|
log.debug('Failed to get sd_hash from %s', stream_info, exc_info=True)
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -182,7 +182,7 @@ ADJUSTABLE_SETTINGS = {
|
||||||
#
|
#
|
||||||
# TODO: writing json on the cmd line is a pain, come up with a nicer
|
# TODO: writing json on the cmd line is a pain, come up with a nicer
|
||||||
# parser for this data structure. (maybe MAX_KEY_FEE': USD:25
|
# parser for this data structure. (maybe MAX_KEY_FEE': USD:25
|
||||||
'max_key_fee': (json.loads, {'USD': {'amount': 25.0, 'address': ''}}),
|
'max_key_fee': (json.loads, {'currency':'USD', 'amount': 25.0, 'address':''}),
|
||||||
|
|
||||||
'max_search_results': (int, 25),
|
'max_search_results': (int, 25),
|
||||||
'max_upload': (float, 0.0),
|
'max_upload': (float, 0.0),
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from twisted.internet import threads, reactor, defer, task
|
from twisted.internet import threads, reactor, defer, task
|
||||||
|
@ -8,7 +7,6 @@ from twisted.python.failure import Failure
|
||||||
from twisted.enterprise import adbapi
|
from twisted.enterprise import adbapi
|
||||||
from collections import defaultdict, deque
|
from collections import defaultdict, deque
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
from jsonschema import ValidationError
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from lbryum import SimpleConfig, Network
|
from lbryum import SimpleConfig, Network
|
||||||
|
@ -16,13 +14,17 @@ from lbryum.lbrycrd import COIN, RECOMMENDED_CLAIMTRIE_HASH_CONFIRMS
|
||||||
import lbryum.wallet
|
import lbryum.wallet
|
||||||
from lbryum.commands import known_commands, Commands
|
from lbryum.commands import known_commands, Commands
|
||||||
|
|
||||||
|
from lbryschema.claim import ClaimDict
|
||||||
|
from lbryschema.decode import smart_decode
|
||||||
|
from lbryschema.error import DecodeError
|
||||||
|
|
||||||
|
from lbrynet.core import utils
|
||||||
from lbrynet.core.sqlite_helpers import rerun_if_locked
|
from lbrynet.core.sqlite_helpers import rerun_if_locked
|
||||||
from lbrynet.interfaces import IRequestCreator, IQueryHandlerFactory, IQueryHandler, IWallet
|
from lbrynet.interfaces import IRequestCreator, IQueryHandlerFactory, IQueryHandler, IWallet
|
||||||
from lbrynet.core.client.ClientRequest import ClientRequest
|
from lbrynet.core.client.ClientRequest import ClientRequest
|
||||||
from lbrynet.core.Error import (UnknownNameError, InvalidStreamInfoError, RequestCanceledError,
|
from lbrynet.core.Error import (UnknownNameError, InvalidStreamInfoError, RequestCanceledError,
|
||||||
InsufficientFundsError)
|
InsufficientFundsError)
|
||||||
from lbrynet.db_migrator.migrate1to2 import UNSET_NOUT
|
from lbrynet.db_migrator.migrate1to2 import UNSET_NOUT
|
||||||
from lbrynet.metadata.Metadata import Metadata
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -479,7 +481,8 @@ class Wallet(object):
|
||||||
assert k in r, "getvalueforname response missing field %s" % k
|
assert k in r, "getvalueforname response missing field %s" % k
|
||||||
|
|
||||||
def _log_success(claim_id):
|
def _log_success(claim_id):
|
||||||
log.debug("lbry://%s complies with %s, claimid: %s", name, metadata.version, claim_id)
|
log.debug("lbry://%s complies with %s, claimid: %s",
|
||||||
|
name, claim_dict.claim_dict['version'], claim_id)
|
||||||
return defer.succeed(None)
|
return defer.succeed(None)
|
||||||
|
|
||||||
if 'error' in result:
|
if 'error' in result:
|
||||||
|
@ -487,15 +490,17 @@ class Wallet(object):
|
||||||
return Failure(UnknownNameError(name))
|
return Failure(UnknownNameError(name))
|
||||||
_check_result_fields(result)
|
_check_result_fields(result)
|
||||||
try:
|
try:
|
||||||
metadata = Metadata(json.loads(result['value']))
|
claim_dict = smart_decode(result['value'].decode('hex'))
|
||||||
except (TypeError, ValueError, ValidationError):
|
except (TypeError, ValueError, DecodeError):
|
||||||
return Failure(InvalidStreamInfoError(name, result['value']))
|
return Failure(InvalidStreamInfoError(name, result['value']))
|
||||||
sd_hash = metadata['sources']['lbry_sd_hash']
|
#TODO: what if keys don't exist here,
|
||||||
|
# probablly need get_sd_hash() function fro ClaimDict
|
||||||
|
sd_hash = utils.get_sd_hash(claim_dict.claim_dict)
|
||||||
claim_outpoint = ClaimOutpoint(result['txid'], result['nout'])
|
claim_outpoint = ClaimOutpoint(result['txid'], result['nout'])
|
||||||
d = self._save_name_metadata(name, claim_outpoint, sd_hash)
|
d = self._save_name_metadata(name, claim_outpoint, sd_hash)
|
||||||
d.addCallback(lambda _: self.get_claimid(name, result['txid'], result['nout']))
|
d.addCallback(lambda _: self.get_claimid(name, result['txid'], result['nout']))
|
||||||
d.addCallback(lambda cid: _log_success(cid))
|
d.addCallback(lambda cid: _log_success(cid))
|
||||||
d.addCallback(lambda _: metadata)
|
d.addCallback(lambda _: claim_dict.claim_dict)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def get_claim(self, name, claim_id):
|
def get_claim(self, name, claim_id):
|
||||||
|
@ -529,7 +534,7 @@ class Wallet(object):
|
||||||
def _get_claim_for_return(claim):
|
def _get_claim_for_return(claim):
|
||||||
if not claim:
|
if not claim:
|
||||||
return False
|
return False
|
||||||
claim['value'] = json.loads(claim['value'])
|
claim['value'] = smart_decode(claim['value'].decode('hex')).claim_dict
|
||||||
return claim
|
return claim
|
||||||
|
|
||||||
def _get_my_unspent_claim(claims):
|
def _get_my_unspent_claim(claims):
|
||||||
|
@ -554,10 +559,11 @@ class Wallet(object):
|
||||||
d.addCallback(lambda r: self._get_claim_info(name, ClaimOutpoint(r['txid'], r['nout'])))
|
d.addCallback(lambda r: self._get_claim_info(name, ClaimOutpoint(r['txid'], r['nout'])))
|
||||||
else:
|
else:
|
||||||
d = self._get_claim_info(name, ClaimOutpoint(txid, nout))
|
d = self._get_claim_info(name, ClaimOutpoint(txid, nout))
|
||||||
|
# TODO: this catches every exception, fix this
|
||||||
d.addErrback(lambda _: False)
|
d.addErrback(lambda _: False)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _format_claim_for_return(self, name, claim, metadata=None, meta_version=None):
|
def _format_claim_for_return(self, name, claim, claim_dict, meta_version):
|
||||||
result = {}
|
result = {}
|
||||||
result['claim_id'] = claim['claim_id']
|
result['claim_id'] = claim['claim_id']
|
||||||
result['amount'] = claim['effective_amount']
|
result['amount'] = claim['effective_amount']
|
||||||
|
@ -565,28 +571,27 @@ class Wallet(object):
|
||||||
result['name'] = name
|
result['name'] = name
|
||||||
result['txid'] = claim['txid']
|
result['txid'] = claim['txid']
|
||||||
result['nout'] = claim['nout']
|
result['nout'] = claim['nout']
|
||||||
result['value'] = metadata if metadata else json.loads(claim['value'])
|
result['value'] = claim_dict
|
||||||
result['supports'] = [
|
result['supports'] = [
|
||||||
{'txid': support['txid'], 'nout': support['nout']} for support in claim['supports']]
|
{'txid': support['txid'], 'nout': support['nout']} for support in claim['supports']]
|
||||||
result['meta_version'] = (
|
result['meta_version'] = meta_version
|
||||||
meta_version if meta_version else result['value'].get('ver', '0.0.1'))
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _get_claim_info(self, name, claim_outpoint):
|
def _get_claim_info(self, name, claim_outpoint):
|
||||||
def _build_response(claim):
|
def _build_response(claim):
|
||||||
try:
|
try:
|
||||||
metadata = Metadata(json.loads(claim['value']))
|
claim_dict = smart_decode(claim['value'].decode('hex')).claim_dict
|
||||||
meta_ver = metadata.version
|
meta_ver = claim_dict['stream']['metadata']['version']
|
||||||
sd_hash = metadata['sources']['lbry_sd_hash']
|
sd_hash = utils.get_sd_hash(claim_dict)
|
||||||
d = self._save_name_metadata(name, claim_outpoint, sd_hash)
|
d = self._save_name_metadata(name, claim_outpoint, sd_hash)
|
||||||
except (TypeError, ValueError, ValidationError):
|
except (TypeError, ValueError, KeyError, DecodeError):
|
||||||
metadata = claim['value']
|
claim_dict = claim['value']
|
||||||
meta_ver = "Non-compliant"
|
meta_ver = "Non-compliant"
|
||||||
d = defer.succeed(None)
|
d = defer.succeed(None)
|
||||||
|
|
||||||
d.addCallback(lambda _: self._format_claim_for_return(name,
|
d.addCallback(lambda _: self._format_claim_for_return(name,
|
||||||
claim,
|
claim,
|
||||||
metadata=metadata,
|
claim_dict=claim_dict,
|
||||||
meta_version=meta_ver))
|
meta_version=meta_ver))
|
||||||
log.info(
|
log.info(
|
||||||
"get claim info lbry://%s metadata: %s, claimid: %s",
|
"get claim info lbry://%s metadata: %s, claimid: %s",
|
||||||
|
@ -622,8 +627,7 @@ class Wallet(object):
|
||||||
fee - transaction fee paid to make claim
|
fee - transaction fee paid to make claim
|
||||||
claim_id - claim id of the claim
|
claim_id - claim id of the claim
|
||||||
"""
|
"""
|
||||||
|
claim_dict = ClaimDict.load_dict(metadata)
|
||||||
_metadata = Metadata(metadata)
|
|
||||||
my_claim = yield self.get_my_claim(name)
|
my_claim = yield self.get_my_claim(name)
|
||||||
|
|
||||||
if my_claim:
|
if my_claim:
|
||||||
|
@ -632,13 +636,13 @@ class Wallet(object):
|
||||||
raise InsufficientFundsError()
|
raise InsufficientFundsError()
|
||||||
old_claim_outpoint = ClaimOutpoint(my_claim['txid'], my_claim['nout'])
|
old_claim_outpoint = ClaimOutpoint(my_claim['txid'], my_claim['nout'])
|
||||||
claim = yield self._send_name_claim_update(name, my_claim['claim_id'],
|
claim = yield self._send_name_claim_update(name, my_claim['claim_id'],
|
||||||
old_claim_outpoint, _metadata, bid)
|
old_claim_outpoint, claim_dict.serialized, bid)
|
||||||
claim['claim_id'] = my_claim['claim_id']
|
claim['claim_id'] = my_claim['claim_id']
|
||||||
else:
|
else:
|
||||||
log.info("Making a new claim")
|
log.info("Making a new claim")
|
||||||
if self.get_balance() < bid:
|
if self.get_balance() < bid:
|
||||||
raise InsufficientFundsError()
|
raise InsufficientFundsError()
|
||||||
claim = yield self._send_name_claim(name, _metadata, bid)
|
claim = yield self._send_name_claim(name, claim_dict.serialized, bid)
|
||||||
|
|
||||||
if not claim['success']:
|
if not claim['success']:
|
||||||
msg = 'Claim to name {} failed: {}'.format(name, claim['reason'])
|
msg = 'Claim to name {} failed: {}'.format(name, claim['reason'])
|
||||||
|
@ -647,8 +651,8 @@ class Wallet(object):
|
||||||
claim = self._process_claim_out(claim)
|
claim = self._process_claim_out(claim)
|
||||||
claim_outpoint = ClaimOutpoint(claim['txid'], claim['nout'])
|
claim_outpoint = ClaimOutpoint(claim['txid'], claim['nout'])
|
||||||
log.info("Saving metadata for claim %s %d", claim['txid'], claim['nout'])
|
log.info("Saving metadata for claim %s %d", claim['txid'], claim['nout'])
|
||||||
|
yield self._save_name_metadata(name, claim_outpoint,
|
||||||
yield self._save_name_metadata(name, claim_outpoint, _metadata['sources']['lbry_sd_hash'])
|
utils.get_sd_hash(claim_dict.claim_dict))
|
||||||
defer.returnValue(claim)
|
defer.returnValue(claim)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@ -1015,26 +1019,26 @@ class LBRYumWallet(Wallet):
|
||||||
return self._run_cmd_as_defer_to_thread('getclaimsforname', name)
|
return self._run_cmd_as_defer_to_thread('getclaimsforname', name)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def _send_name_claim(self, name, val, amount):
|
def _send_name_claim(self, name, value, amount):
|
||||||
broadcast = False
|
broadcast = False
|
||||||
log.debug("Name claim %s %s %f", name, val, amount)
|
log.debug("Name claim %s %f", name, amount)
|
||||||
tx = yield self._run_cmd_as_defer_succeed('claim', name, json.dumps(val), amount, broadcast)
|
tx = yield self._run_cmd_as_defer_succeed('claim', name, value, amount, broadcast)
|
||||||
claim_out = yield self._broadcast_claim_transaction(tx)
|
claim_out = yield self._broadcast_claim_transaction(tx)
|
||||||
defer.returnValue(claim_out)
|
defer.returnValue(claim_out)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def _send_name_claim_update(self, name, claim_id, claim_outpoint, value, amount):
|
def _send_name_claim_update(self, name, claim_id, claim_outpoint, value, amount):
|
||||||
metadata = json.dumps(value)
|
log.debug("Update %s %d %f %s %s", claim_outpoint['txid'], claim_outpoint['nout'],
|
||||||
log.debug("Update %s %d %f %s %s '%s'", claim_outpoint['txid'], claim_outpoint['nout'],
|
amount, name, claim_id)
|
||||||
amount, name, claim_id, metadata)
|
|
||||||
broadcast = False
|
broadcast = False
|
||||||
tx = yield self._run_cmd_as_defer_succeed(
|
tx = yield self._run_cmd_as_defer_succeed(
|
||||||
'update', claim_outpoint['txid'], claim_outpoint['nout'],
|
'update', claim_outpoint['txid'], claim_outpoint['nout'],
|
||||||
name, claim_id, metadata, amount, broadcast
|
name, claim_id, value, amount, broadcast
|
||||||
)
|
)
|
||||||
claim_out = yield self._broadcast_claim_transaction(tx)
|
claim_out = yield self._broadcast_claim_transaction(tx)
|
||||||
defer.returnValue(claim_out)
|
defer.returnValue(claim_out)
|
||||||
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def _abandon_claim(self, claim_outpoint):
|
def _abandon_claim(self, claim_outpoint):
|
||||||
log.debug("Abandon %s %s" % (claim_outpoint['txid'], claim_outpoint['nout']))
|
log.debug("Abandon %s %s" % (claim_outpoint['txid'], claim_outpoint['nout']))
|
||||||
|
|
|
@ -112,7 +112,7 @@ def short_hash(hash_str):
|
||||||
def get_sd_hash(stream_info):
|
def get_sd_hash(stream_info):
|
||||||
if not stream_info:
|
if not stream_info:
|
||||||
return None
|
return None
|
||||||
return stream_info['sources']['lbry_sd_hash']
|
return stream_info['stream']['source']['source']
|
||||||
|
|
||||||
|
|
||||||
def json_dumps_pretty(obj, **kwargs):
|
def json_dumps_pretty(obj, **kwargs):
|
||||||
|
|
|
@ -24,7 +24,8 @@ from lbrynet.conf import LBRYCRD_WALLET, LBRYUM_WALLET, PTC_WALLET
|
||||||
from lbrynet.reflector import reupload
|
from lbrynet.reflector import reupload
|
||||||
from lbrynet.reflector import ServerFactory as reflector_server_factory
|
from lbrynet.reflector import ServerFactory as reflector_server_factory
|
||||||
from lbrynet.metadata.Fee import FeeValidator
|
from lbrynet.metadata.Fee import FeeValidator
|
||||||
from lbrynet.metadata.Metadata import verify_name_characters, Metadata
|
from lbrynet.metadata.Metadata import verify_name_characters
|
||||||
|
from lbryschema.decode import smart_decode
|
||||||
from lbrynet.lbryfile.client.EncryptedFileDownloader import EncryptedFileSaverFactory
|
from lbrynet.lbryfile.client.EncryptedFileDownloader import EncryptedFileSaverFactory
|
||||||
from lbrynet.lbryfile.client.EncryptedFileDownloader import EncryptedFileOpenerFactory
|
from lbrynet.lbryfile.client.EncryptedFileDownloader import EncryptedFileOpenerFactory
|
||||||
from lbrynet.lbryfile.client.EncryptedFileOptions import add_lbry_file_to_sd_identifier
|
from lbrynet.lbryfile.client.EncryptedFileOptions import add_lbry_file_to_sd_identifier
|
||||||
|
@ -710,15 +711,16 @@ class Daemon(AuthJSONRPCServer):
|
||||||
defer.returnValue((sd_hash, file_path))
|
defer.returnValue((sd_hash, file_path))
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def _publish_stream(self, name, bid, metadata, file_path=None):
|
def _publish_stream(self, name, bid, claim_dict, file_path=None):
|
||||||
|
|
||||||
publisher = Publisher(self.session, self.lbry_file_manager, self.session.wallet)
|
publisher = Publisher(self.session, self.lbry_file_manager, self.session.wallet)
|
||||||
verify_name_characters(name)
|
verify_name_characters(name)
|
||||||
if bid <= 0.0:
|
if bid <= 0.0:
|
||||||
raise Exception("Invalid bid")
|
raise Exception("Invalid bid")
|
||||||
if not file_path:
|
if not file_path:
|
||||||
claim_out = yield publisher.update_stream(name, bid, metadata)
|
claim_out = yield publisher.publish_stream(name, bid, claim_dict)
|
||||||
else:
|
else:
|
||||||
claim_out = yield publisher.publish_stream(name, file_path, bid, metadata)
|
claim_out = yield publisher.create_and_publish_stream(name, bid, claim_dict, file_path)
|
||||||
if conf.settings['reflect_uploads']:
|
if conf.settings['reflect_uploads']:
|
||||||
d = reupload.reflect_stream(publisher.lbry_file)
|
d = reupload.reflect_stream(publisher.lbry_file)
|
||||||
d.addCallbacks(lambda _: log.info("Reflected new publication to lbry://%s", name),
|
d.addCallbacks(lambda _: log.info("Reflected new publication to lbry://%s", name),
|
||||||
|
@ -827,7 +829,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _get_est_cost_from_metadata(self, metadata, name):
|
def _get_est_cost_from_metadata(self, metadata, name):
|
||||||
d = self.get_est_cost_from_sd_hash(metadata['sources']['lbry_sd_hash'])
|
d = self.get_est_cost_from_sd_hash(utils.get_sd_hash(metadata))
|
||||||
|
|
||||||
def _handle_err(err):
|
def _handle_err(err):
|
||||||
if isinstance(err, Failure):
|
if isinstance(err, Failure):
|
||||||
|
@ -888,7 +890,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
lbry_file.txid,
|
lbry_file.txid,
|
||||||
lbry_file.nout)
|
lbry_file.nout)
|
||||||
try:
|
try:
|
||||||
metadata = claim['value']
|
metadata = smart_decode(claim['value']).claim_dict
|
||||||
except:
|
except:
|
||||||
metadata = None
|
metadata = None
|
||||||
try:
|
try:
|
||||||
|
@ -1425,9 +1427,10 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _get_claim(_claim_id, _claims):
|
def _get_claim(_claim_id, _claims):
|
||||||
|
#TODO: do this in Wallet class
|
||||||
for claim in _claims['claims']:
|
for claim in _claims['claims']:
|
||||||
if claim['claim_id'] == _claim_id:
|
if claim['claim_id'] == _claim_id:
|
||||||
return Metadata(json.loads(claim['value']))
|
return smart_decode(claim['value']).claim_dict
|
||||||
|
|
||||||
log.info("Received request to get %s", name)
|
log.info("Received request to get %s", name)
|
||||||
|
|
||||||
|
@ -1476,9 +1479,11 @@ class Daemon(AuthJSONRPCServer):
|
||||||
result = yield self._get_lbry_file_dict(self.streams[name].downloader,
|
result = yield self._get_lbry_file_dict(self.streams[name].downloader,
|
||||||
full_status=True)
|
full_status=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# TODO: should reraise here, instead of returning e.message
|
||||||
log.warning('Failed to get %s', name)
|
log.warning('Failed to get %s', name)
|
||||||
self.analytics_manager.send_download_errored(download_id, name, stream_info)
|
self.analytics_manager.send_download_errored(download_id, name, stream_info)
|
||||||
result = e.message
|
result = e.message
|
||||||
|
|
||||||
response = yield self._render_response(result)
|
response = yield self._render_response(result)
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@ -1672,17 +1677,25 @@ class Daemon(AuthJSONRPCServer):
|
||||||
metadata['preview'] = preview
|
metadata['preview'] = preview
|
||||||
if nsfw is not None:
|
if nsfw is not None:
|
||||||
metadata['nsfw'] = bool(nsfw)
|
metadata['nsfw'] = bool(nsfw)
|
||||||
if sources is not None:
|
|
||||||
metadata['sources'] = sources
|
|
||||||
|
|
||||||
# add address to fee if unspecified
|
metadata['version'] = '_0_1_0'
|
||||||
|
|
||||||
|
# original format {'currency':{'address','amount'}}
|
||||||
|
# add address to fee if unspecified {'version': ,'currency', 'address' , 'amount'}
|
||||||
if 'fee' in metadata:
|
if 'fee' in metadata:
|
||||||
|
new_fee_dict = {}
|
||||||
assert len(metadata['fee']) == 1, "Too many fees"
|
assert len(metadata['fee']) == 1, "Too many fees"
|
||||||
for currency in metadata['fee']:
|
currency, fee_dict = metadata['fee'].items()[0]
|
||||||
if 'address' not in metadata['fee'][currency]:
|
if 'address' not in fee_dict:
|
||||||
new_address = yield self.session.wallet.get_new_address()
|
address = yield self.session.wallet.get_new_address()
|
||||||
metadata['fee'][currency]['address'] = new_address
|
else:
|
||||||
metadata['fee'] = FeeValidator(metadata['fee'])
|
address = fee_dict['address']
|
||||||
|
new_fee_dict = {
|
||||||
|
'version':'_0_0_1',
|
||||||
|
'currency': currency,
|
||||||
|
'address':address,
|
||||||
|
'amount':fee_dict['amount']}
|
||||||
|
metadata['fee'] = new_fee_dict
|
||||||
|
|
||||||
log.info("Publish: %s", {
|
log.info("Publish: %s", {
|
||||||
'name': name,
|
'name': name,
|
||||||
|
@ -1692,7 +1705,15 @@ class Daemon(AuthJSONRPCServer):
|
||||||
'fee': fee,
|
'fee': fee,
|
||||||
})
|
})
|
||||||
|
|
||||||
result = yield self._publish_stream(name, bid, metadata, file_path)
|
claim_dict = {
|
||||||
|
'version':'_0_0_1',
|
||||||
|
'claimType':'streamType',
|
||||||
|
'stream':{'metadata':metadata, 'version':'_0_0_1'}}
|
||||||
|
|
||||||
|
if sources is not None:
|
||||||
|
claim_dict['stream']['source'] = sources
|
||||||
|
|
||||||
|
result = yield self._publish_stream(name, bid, claim_dict, file_path)
|
||||||
response = yield self._render_response(result)
|
response = yield self._render_response(result)
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import os
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
from twisted.internet.task import LoopingCall
|
from twisted.internet.task import LoopingCall
|
||||||
|
|
||||||
|
from lbrynet.core import utils
|
||||||
from lbrynet.core.Error import InsufficientFundsError, KeyFeeAboveMaxAllowed
|
from lbrynet.core.Error import InsufficientFundsError, KeyFeeAboveMaxAllowed
|
||||||
from lbrynet.core.StreamDescriptor import download_sd_blob
|
from lbrynet.core.StreamDescriptor import download_sd_blob
|
||||||
from lbrynet.metadata.Fee import FeeValidator
|
from lbrynet.metadata.Fee import FeeValidator
|
||||||
|
@ -158,9 +159,9 @@ class GetStream(object):
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def download(self, stream_info, name):
|
def download(self, stream_info, name):
|
||||||
self.set_status(INITIALIZING_CODE, name)
|
self.set_status(INITIALIZING_CODE, name)
|
||||||
self.sd_hash = stream_info['sources']['lbry_sd_hash']
|
self.sd_hash = utils.get_sd_hash(stream_info)
|
||||||
if 'fee' in stream_info:
|
if 'fee' in stream_info['stream']['metadata']:
|
||||||
fee = self.check_fee(stream_info['fee'])
|
fee = self.check_fee(stream_info['stream']['metadata']['fee'])
|
||||||
else:
|
else:
|
||||||
fee = None
|
fee = None
|
||||||
|
|
||||||
|
|
|
@ -193,11 +193,10 @@ class ExchangeRateManager(object):
|
||||||
fee_in = fee
|
fee_in = fee
|
||||||
|
|
||||||
return FeeValidator({
|
return FeeValidator({
|
||||||
fee_in.currency_symbol: {
|
'currency':fee_in.currency_symbol,
|
||||||
'amount': self.convert_currency(fee_in.currency_symbol, "LBC", fee_in.amount),
|
'amount': self.convert_currency(fee_in.currency_symbol, "LBC", fee_in.amount),
|
||||||
'address': fee_in.address
|
'address': fee_in.address
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
class DummyBTCLBCFeed(MarketFeed):
|
class DummyBTCLBCFeed(MarketFeed):
|
||||||
|
@ -252,8 +251,7 @@ class DummyExchangeRateManager(object):
|
||||||
fee_in = fee
|
fee_in = fee
|
||||||
|
|
||||||
return FeeValidator({
|
return FeeValidator({
|
||||||
fee_in.currency_symbol: {
|
'currency':fee_in.currency_symbol,
|
||||||
'amount': self.convert_currency(fee_in.currency_symbol, "LBC", fee_in.amount),
|
'amount': self.convert_currency(fee_in.currency_symbol, "LBC", fee_in.amount),
|
||||||
'address': fee_in.address
|
'address': fee_in.address
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
|
@ -3,10 +3,10 @@ import mimetypes
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
|
||||||
from lbrynet.core import file_utils
|
from lbrynet.core import file_utils
|
||||||
from lbrynet.lbryfilemanager.EncryptedFileCreator import create_lbry_file
|
from lbrynet.lbryfilemanager.EncryptedFileCreator import create_lbry_file
|
||||||
from lbrynet.lbryfile.StreamDescriptor import publish_sd_blob
|
from lbrynet.lbryfile.StreamDescriptor import publish_sd_blob
|
||||||
from lbrynet.metadata.Metadata import Metadata
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -19,8 +19,11 @@ class Publisher(object):
|
||||||
self.wallet = wallet
|
self.wallet = wallet
|
||||||
self.lbry_file = None
|
self.lbry_file = None
|
||||||
|
|
||||||
|
"""
|
||||||
|
Create lbry file and make claim
|
||||||
|
"""
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def publish_stream(self, name, file_path, bid, metadata):
|
def create_and_publish_stream(self, name, bid, claim_dict, file_path):
|
||||||
log.info('Starting publish for %s', name)
|
log.info('Starting publish for %s', name)
|
||||||
file_name = os.path.basename(file_path)
|
file_name = os.path.basename(file_path)
|
||||||
with file_utils.get_read_handle(file_path) as read_handle:
|
with file_utils.get_read_handle(file_path) as read_handle:
|
||||||
|
@ -30,30 +33,30 @@ class Publisher(object):
|
||||||
self.lbry_file = yield self.lbry_file_manager.add_lbry_file(stream_hash, prm)
|
self.lbry_file = yield self.lbry_file_manager.add_lbry_file(stream_hash, prm)
|
||||||
sd_hash = yield publish_sd_blob(self.lbry_file_manager.stream_info_manager,
|
sd_hash = yield publish_sd_blob(self.lbry_file_manager.stream_info_manager,
|
||||||
self.session.blob_manager, self.lbry_file.stream_hash)
|
self.session.blob_manager, self.lbry_file.stream_hash)
|
||||||
if 'sources' not in metadata:
|
if 'source' not in claim_dict['stream']:
|
||||||
metadata['sources'] = {}
|
claim_dict['stream']['source'] = {}
|
||||||
metadata['sources']['lbry_sd_hash'] = sd_hash
|
claim_dict['stream']['source']['source'] = sd_hash
|
||||||
metadata['content_type'] = get_content_type(file_path)
|
claim_dict['stream']['source']['sourceType'] = 'lbry_sd_hash'
|
||||||
metadata['ver'] = Metadata.current_version
|
claim_dict['stream']['source']['contentType'] = get_content_type(file_path)
|
||||||
claim_out = yield self.make_claim(name, bid, metadata)
|
claim_dict['stream']['source']['version'] = "_0_0_1" # need current version here
|
||||||
|
|
||||||
|
claim_out = yield self.make_claim(name, bid, claim_dict)
|
||||||
self.lbry_file.completed = True
|
self.lbry_file.completed = True
|
||||||
yield self.lbry_file.load_file_attributes()
|
yield self.lbry_file.load_file_attributes()
|
||||||
yield self.lbry_file.save_status()
|
yield self.lbry_file.save_status()
|
||||||
defer.returnValue(claim_out)
|
defer.returnValue(claim_out)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Make a claim without creating a lbry file
|
||||||
|
"""
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def update_stream(self, name, bid, metadata):
|
def publish_stream(self, name, bid, claim_dict):
|
||||||
my_claim = yield self.wallet.get_my_claim(name)
|
claim_out = yield self.make_claim(name, bid, claim_dict)
|
||||||
updated_metadata = my_claim['value']
|
|
||||||
for meta_key in metadata:
|
|
||||||
updated_metadata[meta_key] = metadata[meta_key]
|
|
||||||
claim_out = yield self.make_claim(name, bid, updated_metadata)
|
|
||||||
defer.returnValue(claim_out)
|
defer.returnValue(claim_out)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def make_claim(self, name, bid, metadata):
|
def make_claim(self, name, bid, claim_dict):
|
||||||
validated_metadata = Metadata(metadata)
|
claim_out = yield self.wallet.claim_name(name, bid, claim_dict)
|
||||||
claim_out = yield self.wallet.claim_name(name, bid, validated_metadata)
|
|
||||||
defer.returnValue(claim_out)
|
defer.returnValue(claim_out)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,12 @@ class FeeValidator(StructuredDict):
|
||||||
|
|
||||||
StructuredDict.__init__(self, fee, fee.get('ver', '0.0.1'))
|
StructuredDict.__init__(self, fee, fee.get('ver', '0.0.1'))
|
||||||
|
|
||||||
self.currency_symbol = self.keys()[0]
|
self.currency_symbol = self['currency']
|
||||||
self.amount = self._get_amount()
|
self.amount = self._get_amount()
|
||||||
self.address = self[self.currency_symbol]['address']
|
self.address = self['address']
|
||||||
|
|
||||||
def _get_amount(self):
|
def _get_amount(self):
|
||||||
amt = self[self.currency_symbol]['amount']
|
amt = self['amount']
|
||||||
try:
|
try:
|
||||||
return float(amt)
|
return float(amt)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
|
|
@ -11,6 +11,7 @@ jsonrpc==1.2
|
||||||
jsonrpclib==0.1.7
|
jsonrpclib==0.1.7
|
||||||
jsonschema==2.5.1
|
jsonschema==2.5.1
|
||||||
git+https://github.com/lbryio/lbryum.git
|
git+https://github.com/lbryio/lbryum.git
|
||||||
|
git+https://github.com/lbryio/lbryschema.git
|
||||||
miniupnpc==1.9
|
miniupnpc==1.9
|
||||||
pbkdf2==1.3
|
pbkdf2==1.3
|
||||||
protobuf==3.0.0
|
protobuf==3.0.0
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -20,6 +20,7 @@ requires = [
|
||||||
'jsonrpc',
|
'jsonrpc',
|
||||||
'jsonschema',
|
'jsonschema',
|
||||||
'lbryum>=2.7.6',
|
'lbryum>=2.7.6',
|
||||||
|
'lbryschema',
|
||||||
'miniupnpc',
|
'miniupnpc',
|
||||||
'pycrypto',
|
'pycrypto',
|
||||||
'pyyaml',
|
'pyyaml',
|
||||||
|
|
|
@ -8,19 +8,21 @@ from lbrynet.core.Wallet import Wallet, ReservedPoints
|
||||||
|
|
||||||
test_metadata = {
|
test_metadata = {
|
||||||
'license': 'NASA',
|
'license': 'NASA',
|
||||||
'fee': {'USD': {'amount': 0.01, 'address': 'baBYSK7CqGSn5KrEmNmmQwAhBSFgo6v47z'}},
|
'version': '_0_1_0',
|
||||||
'ver': '0.0.3',
|
|
||||||
'description': 'test',
|
'description': 'test',
|
||||||
'language': 'en',
|
'language': 'en',
|
||||||
'author': 'test',
|
'author': 'test',
|
||||||
'title': 'test',
|
'title': 'test',
|
||||||
'sources': {
|
|
||||||
'lbry_sd_hash': '8655f713819344980a9a0d67b198344e2c462c90f813e86f0c63789ab0868031f25c54d0bb31af6658e997e2041806eb'},
|
|
||||||
'nsfw': False,
|
'nsfw': False,
|
||||||
'content_type': 'video/mp4',
|
|
||||||
'thumbnail': 'test'
|
'thumbnail': 'test'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_claim_dict = {
|
||||||
|
'version':'_0_0_1',
|
||||||
|
'claimType':'streamType',
|
||||||
|
'stream':{'metadata':test_metadata, 'version':'_0_0_1','source':{'source':'8655f713819344980a9a0d67b198344e2c462c90f813e86f0c63789ab0868031f25c54d0bb31af6658e997e2041806eb','sourceType':'lbry_sd_hash','contentType':'video/mp4','version':'_0_0_1'},
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
class MocLbryumWallet(Wallet):
|
class MocLbryumWallet(Wallet):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -42,7 +44,7 @@ class WalletTest(unittest.TestCase):
|
||||||
return claim_out
|
return claim_out
|
||||||
MocLbryumWallet._send_name_claim = not_enough_funds_send_name_claim
|
MocLbryumWallet._send_name_claim = not_enough_funds_send_name_claim
|
||||||
wallet = MocLbryumWallet()
|
wallet = MocLbryumWallet()
|
||||||
d = wallet.claim_name('test', 1, test_metadata)
|
d = wallet.claim_name('test', 1, test_claim_dict)
|
||||||
self.assertFailure(d,Exception)
|
self.assertFailure(d,Exception)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@ -67,7 +69,7 @@ class WalletTest(unittest.TestCase):
|
||||||
|
|
||||||
MocLbryumWallet._send_name_claim = success_send_name_claim
|
MocLbryumWallet._send_name_claim = success_send_name_claim
|
||||||
wallet = MocLbryumWallet()
|
wallet = MocLbryumWallet()
|
||||||
d = wallet.claim_name('test', 1, test_metadata)
|
d = wallet.claim_name('test', 1, test_claim_dict)
|
||||||
d.addCallback(lambda claim_out: check_out(claim_out))
|
d.addCallback(lambda claim_out: check_out(claim_out))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@ -169,7 +171,7 @@ class WalletTest(unittest.TestCase):
|
||||||
d = wallet.update_balance()
|
d = wallet.update_balance()
|
||||||
d.addCallback(lambda _: self.assertEqual(5, wallet.get_balance()))
|
d.addCallback(lambda _: self.assertEqual(5, wallet.get_balance()))
|
||||||
d.addCallback(lambda _: wallet.reserve_points('testid',2))
|
d.addCallback(lambda _: wallet.reserve_points('testid',2))
|
||||||
d.addCallback(lambda _: wallet.claim_name('test', 4, test_metadata))
|
d.addCallback(lambda _: wallet.claim_name('test', 4, test_claim_dict))
|
||||||
self.assertFailure(d,InsufficientFundsError)
|
self.assertFailure(d,InsufficientFundsError)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ def get_test_daemon(data_rate=None, generous=True, with_fee=False):
|
||||||
}
|
}
|
||||||
if with_fee:
|
if with_fee:
|
||||||
metadata.update(
|
metadata.update(
|
||||||
{"fee": {"USD": {"address": "bQ6BGboPV2SpTMEP7wLNiAcnsZiH8ye6eA", "amount": 0.75}}})
|
{"fee": {"currency":"USD", "address":"bQ6BGboPV2SpTMEP7wLNiAcnsZiH8ye6eA", "amount": 0.75}})
|
||||||
daemon._resolve_name = lambda _: defer.succeed(metadata)
|
daemon._resolve_name = lambda _: defer.succeed(metadata)
|
||||||
return daemon
|
return daemon
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,13 @@ from tests import util
|
||||||
class FeeFormatTest(unittest.TestCase):
|
class FeeFormatTest(unittest.TestCase):
|
||||||
def test_fee_created_with_correct_inputs(self):
|
def test_fee_created_with_correct_inputs(self):
|
||||||
fee_dict = {
|
fee_dict = {
|
||||||
'USD': {
|
'currency':'USD',
|
||||||
'amount': 10.0,
|
'amount': 10.0,
|
||||||
'address': "bRcHraa8bYJZL7vkh5sNmGwPDERFUjGPP9"
|
'address': "bRcHraa8bYJZL7vkh5sNmGwPDERFUjGPP9"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fee = Fee.FeeValidator(fee_dict)
|
fee = Fee.FeeValidator(fee_dict)
|
||||||
self.assertEqual(10.0, fee['USD']['amount'])
|
self.assertEqual(10.0, fee['amount'])
|
||||||
|
self.assertEqual('USD', fee['currency'])
|
||||||
|
|
||||||
class FeeTest(unittest.TestCase):
|
class FeeTest(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -26,11 +25,11 @@ class FeeTest(unittest.TestCase):
|
||||||
|
|
||||||
def test_fee_converts_to_lbc(self):
|
def test_fee_converts_to_lbc(self):
|
||||||
fee_dict = {
|
fee_dict = {
|
||||||
'USD': {
|
'currency':'USD',
|
||||||
'amount': 10.0,
|
'amount': 10.0,
|
||||||
'address': "bRcHraa8bYJZL7vkh5sNmGwPDERFUjGPP9"
|
'address': "bRcHraa8bYJZL7vkh5sNmGwPDERFUjGPP9"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
rates = {
|
rates = {
|
||||||
'BTCLBC': {'spot': 3.0, 'ts': util.DEFAULT_ISO_TIME + 1},
|
'BTCLBC': {'spot': 3.0, 'ts': util.DEFAULT_ISO_TIME + 1},
|
||||||
'USDBTC': {'spot': 2.0, 'ts': util.DEFAULT_ISO_TIME + 2}
|
'USDBTC': {'spot': 2.0, 'ts': util.DEFAULT_ISO_TIME + 2}
|
||||||
|
|
Loading…
Reference in a new issue