diff --git a/.gitignore b/.gitignore index 63cca906f..23ba8568c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,7 @@ lbrynet.egg-info/PKG-INFO *.egg + +/build + +/dist diff --git a/INSTALL.md b/INSTALL.md index 325ba1779..a964c8a8f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -38,3 +38,38 @@ python setup.py install this will install all of the libraries and a few applications For running the file sharing application, see [RUNNING](RUNNING.md) + +#### On windows: + +Install [mingw32](http://www.mingw.org/) base and c++ compiler. + +Add C:\MinGW\bin to the windows PATH. + +Enable distutils to compile with mingw32 by creating a distutils.cfg file in *PYTHONPATH\Lib\distutils* containing +``` +[build] +compiler = mingw32 +``` + +If using virtualenv, copy the *PYTHONPATH\Lib\distutils* directory to the virtualenv. + +It's recommended to use [Unofficial Windows Binaries for Python Extension Packages](http://www.lfd.uci.edu/~gohlke/pythonlibs/) for as many of the required packages as possible. +Currently, available binaries include: +- Cython +- Twisted +- Zope.interface +- pywin32 +- Yapsy +- cx_Freeze +- requests +- gmpy + +Install the each of the preceding binaries with `pip install *.whl` + +Install pywin32 system files by run `python.exe Scripts\pywin32_postinstall.py -install` from an elevated command prompt. + +Install the rest of the required modules with the standard `pip install module` command + +The one module which requires additional work is [miniupnpc](https://pypi.python.org/pypi/miniupnpc/1.9). +Download the source and compile with MinGW by running `mingw32make.bat` +Then install the module by running `python setupmingw32.py install` diff --git a/lbrynet/core/LBRYcrdWallet.py b/lbrynet/core/LBRYcrdWallet.py index 3152757a5..3db07f1b3 100644 --- a/lbrynet/core/LBRYcrdWallet.py +++ b/lbrynet/core/LBRYcrdWallet.py @@ -294,7 +294,7 @@ class LBRYcrdWallet(object): return d def claim_name(self, name, sd_hash, amount, description=None, key_fee=None, - key_fee_address=None, thumbnail=None): + key_fee_address=None, thumbnail=None, content_license=None): value = {"stream_hash": sd_hash} if description is not None: value['description'] = description @@ -304,6 +304,9 @@ class LBRYcrdWallet(object): value['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 + d = threads.deferToThread(self._claim_name, name, json.dumps(value), amount) def _save_metadata(txid): @@ -314,6 +317,47 @@ class LBRYcrdWallet(object): d.addCallback(_save_metadata) return d + def abandon_name(self, txid): + address = self._get_new_address() + raw = self._get_raw_tx(txid) + transaction = self._get_decoded_tx(raw) + amount = float(transaction['vout'][1]['value']) + return self._abandon_name(txid, address, amount) + + def get_tx(self, txid): + raw = self._get_raw_tx(txid) + return self._get_decoded_tx(raw) + + def get_name_claims(self): + return threads.deferToThread(self._get_name_claims) + + def start_miner(self): + if not self._get_gen_status(): + return self._set_gen_status(True) + else: + return "Miner was already running" + + def stop_miner(self): + if self._get_gen_status(): + return self._set_gen_status(False) + else: + return "Miner wasn't running" + + def get_miner_status(self): + return self._get_gen_status() + + def get_block(self, blockhash): + return self._get_block(blockhash) + + def get_blockchain_info(self): + return self._get_blockchain_info() + + def get_claims_for_tx(self, txid): + return self._get_claims_for_tx(txid) + + def get_nametrie(self): + return self._get_nametrie() + def get_name_and_validity_for_sd_hash(self, sd_hash): d = self._get_claim_metadata_for_sd_hash(sd_hash) d.addCallback(lambda name_txid: threads.deferToThread(self._get_status_of_claim, name_txid[1], name_txid[0], sd_hash) if name_txid is not None else None) @@ -352,9 +396,6 @@ class LBRYcrdWallet(object): def _get_rpc_conn(self): return AuthServiceProxy(self.rpc_conn_string) - def get_rpc_conn_x(self): - return AuthServiceProxy(self.rpc_conn_string) - def _start_daemon(self): tries = 0 @@ -488,6 +529,60 @@ class LBRYcrdWallet(object): rpc_conn = self._get_rpc_conn() return rpc_conn.getinfo() + @_catch_connection_error + def _get_name_claims(self): + rpc_conn = self._get_rpc_conn() + return rpc_conn.listnameclaims() + + @_catch_connection_error + def _get_gen_status(self): + rpc_conn = self._get_rpc_conn() + return rpc_conn.getgenerate() + + @_catch_connection_error + def _set_gen_status(self, b): + if b: + log.info("Starting miner") + else: + log.info("Stopping miner") + rpc_conn = self._get_rpc_conn() + return rpc_conn.setgenerate(b) + + @_catch_connection_error + def _get_raw_tx(self, txid): + rpc_conn = self._get_rpc_conn() + return rpc_conn.getrawtransaction(txid) + + @_catch_connection_error + def _get_decoded_tx(self, raw): + rpc_conn = self._get_rpc_conn() + return rpc_conn.decoderawtransaction(raw) + + @_catch_connection_error + def _abandon_name(self, txid, address, amount): + rpc_conn = self._get_rpc_conn() + return rpc_conn.abandonname(txid, address, amount) + + @_catch_connection_error + def _get_blockchain_info(self): + rpc_conn = self._get_rpc_conn() + return rpc_conn.getblockchaininfo() + + @_catch_connection_error + def _get_block(self, blockhash): + rpc_conn = self._get_rpc_conn() + return rpc_conn.getblock(blockhash) + + @_catch_connection_error + def _get_claims_for_tx(self, txid): + rpc_conn = self._get_rpc_conn() + return rpc_conn.getclaimsfortx(txid) + + @_catch_connection_error + def _get_nametrie(self): + rpc_conn = self._get_rpc_conn() + return rpc_conn.getnametrie() + @_catch_connection_error def _get_wallet_balance(self): rpc_conn = self._get_rpc_conn() diff --git a/lbrynet/dht/node.py b/lbrynet/dht/node.py index 1fae2e889..a3bf56553 100644 --- a/lbrynet/dht/node.py +++ b/lbrynet/dht/node.py @@ -516,7 +516,7 @@ class Node(object): else: raise TypeError, 'No NodeID given. Therefore we can\'t store this node' - if self_store is True and self.externalIP is not None: + if self_store is True and self.externalIP: contact = Contact(self.id, self.externalIP, self.port, None, None) compact_ip = contact.compact_ip() elif '_rpcNodeContact' in kwargs: diff --git a/lbrynet/lbrynet_daemon/LBRYDaemon.py b/lbrynet/lbrynet_daemon/LBRYDaemon.py index e2582f6c7..3c4d81ad9 100644 --- a/lbrynet/lbrynet_daemon/LBRYDaemon.py +++ b/lbrynet/lbrynet_daemon/LBRYDaemon.py @@ -1,3 +1,8 @@ +from lbrynet.core.PaymentRateManager import PaymentRateManager +from lbrynet.core.server.BlobAvailabilityHandler import BlobAvailabilityHandlerFactory +from lbrynet.core.server.BlobRequestHandler import BlobRequestHandlerFactory +from lbrynet.core.server.ServerProtocol import ServerProtocolFactory +from lbrynet.lbrynet_console.ControlHandlers import get_time_behind_blockchain from lbrynet.core.Error import UnknownNameError from lbrynet.lbryfile.StreamDescriptor import LBRYFileStreamType from lbrynet.lbryfile.client.LBRYFileDownloader import LBRYFileSaverFactory, LBRYFileOpenerFactory @@ -7,14 +12,14 @@ 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 -from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier +from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier, download_sd_blob from lbrynet.core.Session import LBRYSession from lbrynet.core.PTCWallet import PTCWallet from lbrynet.core.LBRYcrdWallet import LBRYcrdWallet from lbrynet.lbryfilemanager.LBRYFileManager import LBRYFileManager from lbrynet.lbryfile.LBRYFileMetadataManager import DBLBRYFileMetadataManager, TempLBRYFileMetadataManager from twisted.web import xmlrpc, server -from twisted.internet import defer, threads, reactor +from twisted.internet import defer, threads, reactor, error from datetime import datetime import logging import os @@ -22,10 +27,10 @@ import sys import json import binascii import webbrowser +from decimal import Decimal log = logging.getLogger(__name__) - #TODO add login credentials in a conf file #issues with delete: @@ -87,7 +92,6 @@ class LBRYDaemon(xmlrpc.XMLRPC): self.wallet_type = "lbrycrd" self.lbrycrd_conf = os.path.join(self.wallet_dir, "lbrycrd.conf") self.autofetcher_conf = os.path.join(self.wallet_dir, "autofetcher.conf") - self.rpc_conn = None self.files = [] self.created_data_dir = False if not os.path.exists(self.db_dir): @@ -96,6 +100,8 @@ class LBRYDaemon(xmlrpc.XMLRPC): self.session_settings = None self.data_rate = 0.5 self.max_key_fee = 100.0 + self.query_handlers = {} + return defer.succeed(None) def _disp_startup(): @@ -114,18 +120,91 @@ class LBRYDaemon(xmlrpc.XMLRPC): d.addCallback(lambda _: self._setup_stream_identifier()) d.addCallback(lambda _: self._setup_lbry_file_manager()) d.addCallback(lambda _: self._setup_lbry_file_opener()) + d.addCallback(lambda _: self._setup_query_handlers()) + d.addCallback(lambda _: self._setup_server()) d.addCallback(lambda _: self._setup_fetcher()) d.addCallback(lambda _: _disp_startup()) d.callback(None) return defer.succeed(None) + def _start_server(self): + + if self.peer_port is not None: + + server_factory = ServerProtocolFactory(self.session.rate_limiter, + self.query_handlers, + self.session.peer_manager) + try: + self.lbry_server_port = reactor.listenTCP(self.peer_port, server_factory) + except error.CannotListenError as e: + import traceback + log.error("Couldn't bind to port %d. %s", self.peer_port, traceback.format_exc()) + raise ValueError("%s lbrynet may already be running on your computer.", str(e)) + return defer.succeed(True) + + def _stop_server(self): + if self.lbry_server_port is not None: + self.lbry_server_port, p = None, self.lbry_server_port + return defer.maybeDeferred(p.stopListening) + else: + return defer.succeed(True) + + def _setup_server(self): + + def restore_running_status(running): + if running is True: + return self._start_server() + return defer.succeed(True) + + dl = self.settings.get_server_running_status() + dl.addCallback(restore_running_status) + return dl + + def _setup_query_handlers(self): + handlers = [ + #CryptBlobInfoQueryHandlerFactory(self.lbry_file_metadata_manager, self.session.wallet, + # self._server_payment_rate_manager), + BlobAvailabilityHandlerFactory(self.session.blob_manager), + #BlobRequestHandlerFactory(self.session.blob_manager, self.session.wallet, + # self._server_payment_rate_manager), + self.session.wallet.get_wallet_info_query_handler_factory(), + ] + + def get_blob_request_handler_factory(rate): + self.blob_request_payment_rate_manager = PaymentRateManager( + self.session.base_payment_rate_manager, rate + ) + handlers.append(BlobRequestHandlerFactory(self.session.blob_manager, self.session.wallet, + self.blob_request_payment_rate_manager)) + + d1 = self.settings.get_server_data_payment_rate() + d1.addCallback(get_blob_request_handler_factory) + + dl = defer.DeferredList([d1]) + dl.addCallback(lambda _: self._add_query_handlers(handlers)) + return dl + + def _add_query_handlers(self, query_handlers): + + def _set_query_handlers(statuses): + from future_builtins import zip + for handler, (success, status) in zip(query_handlers, statuses): + if success is True: + self.query_handlers[handler] = status + + ds = [] + for handler in query_handlers: + ds.append(self.settings.get_query_handler_status(handler.get_primary_query_identifier())) + dl = defer.DeferredList(ds) + dl.addCallback(_set_query_handlers) + return dl + def _shutdown(self): print 'Closing lbrynet session' + d = self._stop_server() if self.session is not None: - d = self.session.shut_down() - else: - d = defer.succeed(True) + d.addCallback(lambda _: self.session.shut_down()) return d def _update_settings(self): @@ -175,11 +254,11 @@ class LBRYDaemon(xmlrpc.XMLRPC): def _get_settings(self): d = self.settings.start() d.addCallback(lambda _: self.settings.get_lbryid()) - d.addCallback(self.set_lbryid) + d.addCallback(self._set_lbryid) d.addCallback(lambda _: self._get_lbrycrdd_path()) return d - def set_lbryid(self, lbryid): + def _set_lbryid(self, lbryid): if lbryid is None: return self._make_lbryid() else: @@ -238,7 +317,6 @@ class LBRYDaemon(xmlrpc.XMLRPC): blob_dir=self.blobfile_dir, dht_node_port=self.dht_node_port, known_dht_nodes=self.known_dht_nodes, peer_port=self.peer_port, use_upnp=self.use_upnp, wallet=results['wallet']) - self.rpc_conn = self.session.wallet.get_rpc_conn_x() dl = defer.DeferredList([d1, d2], fireOnOneErrback=True) dl.addCallback(combine_results) @@ -332,7 +410,6 @@ class LBRYDaemon(xmlrpc.XMLRPC): return d - def _resolve_name_wc(self, name): d = defer.Deferred() d.addCallback(lambda _: self.session.wallet.get_stream_info_for_name(name)) @@ -399,9 +476,45 @@ class LBRYDaemon(xmlrpc.XMLRPC): else: return defer.fail(UnknownNameError) + 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' + else: + print '[' + str(datetime.now()) + '] Timeout estimating cost for lbry://' + name + ', using key fee' + d.cancel() + return defer.succeed(None) + + def _to_dict(r): + t = {} + for i in r: + t[i[0]] = i[1] + return t + + def _add_key_fee(data_cost): + d = self.session.wallet.get_stream_info_for_name(name) + d.addCallback(lambda info: info['key_fee'] if 'key_fee' in info.keys() else 0.0) + d.addCallback(lambda key_fee: key_fee + data_cost) + return d + + d = self.session.wallet.get_stream_info_for_name(name) + d.addCallback(lambda info: download_sd_blob(self.session, info['stream_hash'], + self.blob_request_payment_rate_manager)) + d.addCallback(self.sd_identifier.get_metadata_for_sd_blob) + d.addCallback(lambda metadata: metadata.validator.info_to_show()) + d.addCallback(_to_dict) + d.addCallback(lambda info: int(info['stream_size'])/1000000*self.data_rate) + d.addCallback(_add_key_fee) + d.addErrback(lambda _: _add_key_fee(0.0)) + reactor.callLater(3.0, _check_est, d, name) + + return d + def xmlrpc_get_settings(self): """ Get LBRY payment settings + + @return {'data_rate': float, 'max_key_fee': float} """ if not self.session_settings: @@ -411,6 +524,12 @@ class LBRYDaemon(xmlrpc.XMLRPC): return self.session_settings def xmlrpc_set_settings(self, settings): + """ + Set LBRY payment settings + + @param settings dict: {'data_rate': float, 'max_key_fee': float} + """ + self.session_settings = settings self._update_settings() @@ -428,7 +547,7 @@ class LBRYDaemon(xmlrpc.XMLRPC): def xmlrpc_stop_fetcher(self): """ - Start autofetcher + Stop autofetcher """ self.fetcher.stop() @@ -453,7 +572,7 @@ class LBRYDaemon(xmlrpc.XMLRPC): def xmlrpc_stop(self): """ - Stop the reactor + Stop lbrynet-daemon """ def _disp_shutdown(): @@ -461,16 +580,15 @@ class LBRYDaemon(xmlrpc.XMLRPC): d = self._shutdown() d.addCallback(lambda _: _disp_shutdown()) - d.addCallback(lambda _: reactor.stop()) - d.callback(None) + d.addCallback(lambda _: reactor.callLater(1.0, reactor.stop)) - return d + return defer.succeed('Shutting down') def xmlrpc_get_lbry_files(self): """ Get LBRY files - @return: Managed LBRY files + @return: List of managed LBRY files """ r = [] @@ -496,6 +614,7 @@ class LBRYDaemon(xmlrpc.XMLRPC): Resolve stream info from a LBRY uri @param: name + @return: info for name claim """ def _disp(info): @@ -513,10 +632,13 @@ class LBRYDaemon(xmlrpc.XMLRPC): Download stream from a LBRY uri @param: name + @return: {'stream_hash': hex string, 'path': path of download} """ - d = self._download_name(name) - + if name: + d = self._download_name(name) + else: + d = defer.succeed('No name provided') return d def xmlrpc_stop_lbry_file(self, stream_hash): @@ -546,8 +668,13 @@ class LBRYDaemon(xmlrpc.XMLRPC): else: return defer.succeed('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) @@ -569,6 +696,10 @@ class LBRYDaemon(xmlrpc.XMLRPC): 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 @@ -580,6 +711,13 @@ class LBRYDaemon(xmlrpc.XMLRPC): return d def xmlrpc_search_nametrie(self, search): + """ + Search the nametrie for claims beginning with search + + @param search: + @return: + """ + def _return_d(x): d = defer.Deferred() d.addCallback(lambda _: x) @@ -591,27 +729,26 @@ class LBRYDaemon(xmlrpc.XMLRPC): t = [] for i in n: if i[0]: - if i[1][0][0] and i[1][1][0]: + if i[1][0][0] and i[1][1][0] and i[1][2][0]: i[1][0][1]['value'] = str(i[1][0][1]['value']) - t.append([i[1][0][1], i[1][1][1]]) + t.append([i[1][0][1], i[1][1][1], i[1][2][1]]) return t def _parse(results): f = [] - for chain, meta in results: + 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'] - if 'key_fee' in meta.keys(): - t['cost_est'] = meta['key_fee'] - else: - t['cost_est'] = 0.0 + t['cost_est'] = cost_est f.append(t) return f @@ -622,9 +759,13 @@ class LBRYDaemon(xmlrpc.XMLRPC): print '[' + str(datetime.now()) + '] Search nametrie: ' + search - filtered_results = [n for n in self.rpc_conn.getnametrie() if n['name'].startswith(search)] + filtered_results = [n for n in self.session.wallet.get_nametrie() if n['name'].startswith(search)] + if len(filtered_results) > 25: + filtered_results = filtered_results[:25] filtered_results = [n for n in filtered_results if 'txid' in n.keys()] - resolved_results = [defer.DeferredList([_return_d(n), self._resolve_name_wc(n['name'])]) for n in filtered_results] + resolved_results = [defer.DeferredList([_return_d(n), self._resolve_name_wc(n['name']), + self._get_est_cost(n['name'])]) + for n in filtered_results] d = defer.DeferredList(resolved_results) d.addCallback(_clean) @@ -685,22 +826,61 @@ class LBRYDaemon(xmlrpc.XMLRPC): thumbnail = None if 'key_fee' in metadata.keys(): - if not 'key_fee_address' in metadata.keys(): - return defer.fail() + 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 = None + 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 + 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) + d = p.start(name, file_path, bid, title, description, thumbnail, key_fee, key_fee_address, content_license) return d + def xmlrpc_abandon_name(self, txid): + def _disp(txid, tx): + print '[' + str(datetime.now()) + '] Spent coins from claim tx ' + txid + ' --> ' + tx + return tx + + 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.callback(None) + + return d + + def xmlrpc_get_name_claims(self): + def _clean(claims): + for c in claims: + for k in c.keys(): + if type(c[k]) == Decimal: + c[k] = float(c[k]) + return claims + + d = self.session.wallet.get_name_claims() + d.addCallback(_clean) + + return d + + def xmlrpc_get_time_behind_blockchain(self): + d = self.session.wallet.get_most_recent_blocktime() + d.addCallback(get_time_behind_blockchain) + + return d + + def main(): daemon = LBRYDaemon() daemon.setup() @@ -708,4 +888,4 @@ def main(): reactor.run() if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/lbrynet/lbrynet_daemon/LBRYDownloader.py b/lbrynet/lbrynet_daemon/LBRYDownloader.py index 6895ded68..93bfbfa09 100644 --- a/lbrynet/lbrynet_daemon/LBRYDownloader.py +++ b/lbrynet/lbrynet_daemon/LBRYDownloader.py @@ -104,7 +104,6 @@ class FetcherDaemon(object): self.lbry_metadata_manager = lbry_file_metadata_manager self.seen = [] self.lastbestblock = None - self.rpc_conn = self.wallet.get_rpc_conn_x() self.search = None self.first_run = True self.is_running = False @@ -134,14 +133,14 @@ class FetcherDaemon(object): return msg def _get_names(self): - c = self.rpc_conn.getblockchaininfo() + c = self.wallet.get_blockchain_info() rtn = [] if self.lastbestblock != c: - block = self.rpc_conn.getblock(c['bestblockhash']) + block = self.wallet.get_block(c['bestblockhash']) txids = block['tx'] - transactions = [self.rpc_conn.decoderawtransaction(self.rpc_conn.getrawtransaction(t)) for t in txids] + transactions = [self.wallet.get_tx(t) for t in txids] for t in transactions: - claims = self.rpc_conn.getclaimsfortx(t['txid']) + 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") diff --git a/lbrynet/lbrynet_daemon/LBRYPublisher.py b/lbrynet/lbrynet_daemon/LBRYPublisher.py index 4856fd4e7..81a8e59e3 100644 --- a/lbrynet/lbrynet_daemon/LBRYPublisher.py +++ b/lbrynet/lbrynet_daemon/LBRYPublisher.py @@ -32,9 +32,10 @@ class Publisher(object): self.lbry_file = None self.sd_hash = None self.tx_hash = None + self.content_license = None def start(self, name, file_path, bid, title=None, description=None, thumbnail=None, - key_fee=None, key_fee_address=None): + key_fee=None, key_fee_address=None, content_license=None): def _show_result(): message = "[" + str(datetime.now()) + " ] Published " + self.file_name + " --> lbry://" + \ @@ -50,6 +51,7 @@ class Publisher(object): self.thumbnail = thumbnail self.key_fee = key_fee self.key_fee_address = key_fee_address + self.content_license = content_license d = self._check_file_path(self.file_path) d.addCallback(lambda _: create_lbry_file(self.session, self.lbry_file_manager, @@ -104,7 +106,8 @@ class Publisher(object): 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) + key_fee_address=self.key_fee_address, thumbnail=self.thumbnail, + content_license=self.content_license) def set_tx_hash(tx_hash): self.tx_hash = tx_hash diff --git a/lbrynet/lbrynet_gui/GuiApp.py b/lbrynet/lbrynet_gui/GuiApp.py index 573ac1df6..94c977759 100644 --- a/lbrynet/lbrynet_gui/GuiApp.py +++ b/lbrynet/lbrynet_gui/GuiApp.py @@ -69,7 +69,7 @@ class DownloaderApp(object): if os.name == "nt": root.iconbitmap(os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), - "lbrynet", "lbrynet_downloader_gui", "lbry-dark-icon.ico")) + "lbry-dark-icon.ico")) else: root.wm_iconbitmap("@" + os.path.join(os.path.dirname(__file__), "lbry-dark-icon.xbm")) @@ -111,8 +111,7 @@ class DownloaderApp(object): logo_file_name = "lbry-dark-242x80.gif" if os.name == "nt": - logo_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "lbrynet", - "lbrynet_downloader_gui", logo_file_name) + logo_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), logo_file_name) else: logo_file = os.path.join(os.path.dirname(__file__), logo_file_name) @@ -142,8 +141,8 @@ class DownloaderApp(object): dropdown_file_name = "drop_down.gif" if os.name == "nt": - dropdown_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "lbrynet", - "lbrynet_downloader_gui", dropdown_file_name) + dropdown_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), + dropdown_file_name) else: dropdown_file = os.path.join(os.path.dirname(__file__), dropdown_file_name) diff --git a/setup_win32.py b/setup_win32.py new file mode 100644 index 000000000..b414606a7 --- /dev/null +++ b/setup_win32.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +""" +To create local builds and distributable .msi, run the following command: +python setup_win32.py build bdist_msi +""" +import os +import sys + +from cx_Freeze import setup, Executable + + +def find_data_file(filename): + if getattr(sys, 'frozen', False): + # The application is frozen + data_dir = os.path.dirname(sys.executable) + else: + # The application is not frozen + # Change this bit to match where you store your data files: + data_dir = os.path.dirname(__file__) + return os.path.join(data_dir, filename) + +shortcut_table = [ + ('DesktopShortcut', # Shortcut + 'DesktopFolder', # Directory + 'LBRY', # Name + 'TARGETDIR', # Component + '[TARGETDIR]\LBRY.exe', # Target + None, # Arguments + None, # Description + None, # Hotkey + os.path.join('lbrynet', 'lbrynet_gui', 'lbry-dark-icon.ico'), # Icon + None, # IconIndex + None, # ShowCmd + 'TARGETDIR', # WkDir + ), + ] + +# Now create the table dictionary +msi_data = {'Shortcut': shortcut_table} + +bdist_msi_options = { + 'upgrade_code': '{66620F3A-DC3A-11E2-B341-002219E9B01F}', + 'add_to_path': False, + 'initial_target_dir': r'[LocalAppDataFolder]\LBRY', + 'data': msi_data, + } + +build_exe_options = { + 'include_msvcr': True, + 'includes': [], + 'packages': ['os', 'twisted', 'miniupnpc', 'unqlite', 'seccure', + 'requests', 'bitcoinrpc', 'txjsonrpc', 'win32api', 'Crypto', + 'gmpy', 'yapsy'], + 'excludes': ['zope.interface._zope_interface_coptimizations'], + 'include_files': [os.path.join('lbrynet', 'lbrynet_gui', 'close.gif'), + os.path.join('lbrynet', 'lbrynet_gui', 'close1.png'), + os.path.join('lbrynet', 'lbrynet_gui', 'close2.gif'), + os.path.join('lbrynet', 'lbrynet_gui', 'drop_down.gif'), + os.path.join('lbrynet', 'lbrynet_gui', 'hide_options.gif'), + os.path.join('lbrynet', 'lbrynet_gui', 'lbry-dark-242x80.gif'), + os.path.join('lbrynet', 'lbrynet_gui', 'lbry-dark-icon.ico'), + os.path.join('lbrynet', 'lbrynet_gui', 'lbry-dark-icon.xbm'), + os.path.join('lbrynet', 'lbrynet_gui', 'show_options.gif'), + os.path.join('lbrycrdd.exe'), # Not included in repo + os.path.join('lbrycrd-cli.exe'), # Not included in repo + ], + 'namespace_packages': ['zope']} + +exe = Executable( + script=os.path.join('lbrynet', 'lbrynet_gui', 'gui.py'), + base='Win32GUI', + icon=os.path.join('lbrynet', 'lbrynet_gui', 'lbry-dark-icon.ico'), + compress=True, + shortcutName='LBRY', + shortcutDir='DesktopFolder', + targetName='LBRY.exe' + # targetDir="LocalAppDataFolder" + ) + +setup( + name='LBRY', + version='0.0.4', + description='A fully decentralized network for distributing data', + url='lbry.io', + author='', + keywords='LBRY', + options={'build_exe': build_exe_options, + 'bdist_msi': bdist_msi_options}, + executables=[exe], + )