|
@ -1,11 +1,5 @@
|
||||||
version: 1.0.{build}
|
version: 1.0.{build}
|
||||||
|
|
||||||
environment:
|
|
||||||
key_pass:
|
|
||||||
secure: u6DydPcdrUJlxGL9uc7yQRYG8+5rY6aAEE9nfCSzFyNzZlX9NniOp8Uh5ZKQqX7bGEngLI6ipbLfiJvn0XFnhbn2iTkOuMqOXVJVOehvwlQ=
|
|
||||||
pfx_key:
|
|
||||||
secure: 1mwqyRy7hDqDjDK+TIAoaXyXzpNgwruFNA6TPkinUcVM7A+NLD33RQLnfnwVy+R5ovD2pUfhQ6+N0Fqebv6tZh436LIEsock+6IOdpgFwrg=
|
|
||||||
|
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
- provider: Slack
|
- provider: Slack
|
||||||
|
@ -15,51 +9,5 @@ notifications:
|
||||||
|
|
||||||
clone_folder: c:\projects\lbry
|
clone_folder: c:\projects\lbry
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
install:
|
|
||||||
- cmd: dir C:\projects\lbry\packaging\windows\
|
|
||||||
- ps: .\packaging\windows\init.ps1
|
|
||||||
- nuget install secure-file -ExcludeVersion
|
|
||||||
- secure-file\tools\secure-file -decrypt packaging\windows\certs\lbry2.pfx.enc -secret %pfx_key%
|
|
||||||
- ps: .\packaging\windows\install.ps1
|
|
||||||
|
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- ps: .\packaging\windows\build.ps1
|
- echo "Not currently building on appveyor"
|
||||||
|
|
||||||
|
|
||||||
test_script:
|
|
||||||
- ps: .\packaging\windows\test.ps1
|
|
||||||
|
|
||||||
|
|
||||||
artifacts:
|
|
||||||
- path: dist/*.msi
|
|
||||||
name: msi
|
|
||||||
- path: build/exe.win32-2.7/
|
|
||||||
name: lbry-portable
|
|
||||||
- path: packaging/windows/lbry-win32-app/LBRY-URI.reg
|
|
||||||
name: LBRY-URI
|
|
||||||
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
- provider: GitHub
|
|
||||||
release: $(APPVEYOR_REPO_TAG_NAME)
|
|
||||||
description: 'Release'
|
|
||||||
auth_token:
|
|
||||||
secure: 28gMVxQkXr2iXP4F+5kVwefUtKCfS1ePZ97PVfaSR8UDupjAvKhSJx862TnEjukb
|
|
||||||
artifact: /.*\.msi/
|
|
||||||
draft: false
|
|
||||||
prerelease: true
|
|
||||||
on:
|
|
||||||
appveyor_repo_tag: true # deploy on tag push only
|
|
||||||
- provider: S3
|
|
||||||
access_key_id:
|
|
||||||
secure: E25iHvmHiJP56GWFTe14L3pS8QKb5ZcyWZLY0zqh6BA=
|
|
||||||
secret_access_key:
|
|
||||||
secure: YwZe6fCv29akFYjMCCBJBF7LtI6mxPrxbq7SSoAbn1BPdqjATFegeteGAsqHur/C
|
|
||||||
bucket: lbrynet-master
|
|
||||||
region: us-west-2
|
|
||||||
artifact: /.*\.msi/
|
|
||||||
on:
|
|
||||||
branch: master
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 0.8.7
|
current_version = 0.9.0rc6
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)((?P<release>[a-z]+)(?P<candidate>\d+))?
|
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)((?P<release>[a-z]+)(?P<candidate>\d+))?
|
||||||
|
@ -7,18 +7,18 @@ serialize =
|
||||||
{major}.{minor}.{patch}{release}{candidate}
|
{major}.{minor}.{patch}{release}{candidate}
|
||||||
{major}.{minor}.{patch}
|
{major}.{minor}.{patch}
|
||||||
|
|
||||||
[bumpversion:file:lbrynet/__init__.py]
|
|
||||||
|
|
||||||
[bumpversion:file:packaging/ubuntu/lbry.desktop]
|
|
||||||
|
|
||||||
[bumpversion:part:release]
|
[bumpversion:part:release]
|
||||||
optional_value = production
|
optional_value = production
|
||||||
values =
|
values =
|
||||||
rc
|
rc
|
||||||
production
|
production
|
||||||
|
|
||||||
|
|
||||||
|
[bumpversion:file:lbrynet/__init__.py]
|
||||||
|
|
||||||
[bumpversion:file:CHANGELOG.md]
|
[bumpversion:file:CHANGELOG.md]
|
||||||
search = [Unreleased]
|
search = [Unreleased]
|
||||||
replace = [Unreleased]
|
replace = [Unreleased]
|
||||||
\#\# [{new_version}] - {now:%Y-%m-%d}
|
|
||||||
|
\#\# [{new_version}] - {now:%Y-%m-%d}
|
||||||
|
|
||||||
|
|
101
.travis.yml
|
@ -1,93 +1,40 @@
|
||||||
matrix:
|
os: linux
|
||||||
include:
|
dist: trusty
|
||||||
- os: linux
|
language: python
|
||||||
sudo: required
|
python: 2.7
|
||||||
dist: trusty
|
|
||||||
# dh-virtualenv requires that we use the same python interpreter
|
|
||||||
# that comes with the system, so we don't want to use anything that
|
|
||||||
# travis would try to set-up for us in python
|
|
||||||
language: generic
|
|
||||||
- os: osx
|
|
||||||
# Use generic language for osx
|
|
||||||
# python 2.7 is broken on osx on travis, so follow we have to specify the installation ourselves
|
|
||||||
# https://github.com/travis-ci/travis-ci/issues/2312#issuecomment-195620855
|
|
||||||
language: generic
|
|
||||||
osx_image: xcode7.3
|
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
slack:
|
slack:
|
||||||
secure: "Am13HPtpgCMljh0MDVuoFHvQXB8yhf4Kvf/qAeSp5N0vsHGL70CSF9Ahccw8dVPE6mbuak1OGtSUb6/UaErLHkpz3ztaRLkDa9x7CmBB3Kynnh8oO2VbB7b/2ROULqkhF4VZmAnNfwrQrbC3gs8Sybp261Nyc7y4ww15xDYBrk2fyq4ds2DCaJdRxfJUJFonrZ6KXr3fVaXosO6cjuyS8eRodcmrqsT4cCtinjNTD1hGWoH107E4ObSmpVelxQO193KhNJMRiLlEcVkvYUOqIWBtwdGHbNE/6Yeuq1TXgKJ0KeJWAmW3wTfUYNngGXNAsyCnrhul5TKNevNzfIAQZHvRsczYiWPJV6LtohHT0CcUiCXJtvEPOyahEBfwK3etY/xxFqny7N9OEmpdW2sgsEPNPX2LJynJti2rQA9SuAD1ogR3ZpDy/NXoaAZf8PTdPcuNUMULV9PGG7tVrLBecO/W1qO6hdFxwlLdgqGLxAENZgGp++v/DhPk/WvtmHj7iTbRq0nxaTWyX5uKOn2ADH+k/yfutjv6BsQU9xNyPeZEEtuEpc6X6waiYn/8G9vl9PecvKC5H0MgsZ6asAxmg7mZ3VSMFG7mo8ENeOhSZ0Oz6ZTBILL3wFccZA9uJIq7NWmqC9dRiGiuKXBB62No7sINoHg3114e2xYa9qvNmGg="
|
secure: "Am13HPtpgCMljh0MDVuoFHvQXB8yhf4Kvf/qAeSp5N0vsHGL70CSF9Ahccw8dVPE6mbuak1OGtSUb6/UaErLHkpz3ztaRLkDa9x7CmBB3Kynnh8oO2VbB7b/2ROULqkhF4VZmAnNfwrQrbC3gs8Sybp261Nyc7y4ww15xDYBrk2fyq4ds2DCaJdRxfJUJFonrZ6KXr3fVaXosO6cjuyS8eRodcmrqsT4cCtinjNTD1hGWoH107E4ObSmpVelxQO193KhNJMRiLlEcVkvYUOqIWBtwdGHbNE/6Yeuq1TXgKJ0KeJWAmW3wTfUYNngGXNAsyCnrhul5TKNevNzfIAQZHvRsczYiWPJV6LtohHT0CcUiCXJtvEPOyahEBfwK3etY/xxFqny7N9OEmpdW2sgsEPNPX2LJynJti2rQA9SuAD1ogR3ZpDy/NXoaAZf8PTdPcuNUMULV9PGG7tVrLBecO/W1qO6hdFxwlLdgqGLxAENZgGp++v/DhPk/WvtmHj7iTbRq0nxaTWyX5uKOn2ADH+k/yfutjv6BsQU9xNyPeZEEtuEpc6X6waiYn/8G9vl9PecvKC5H0MgsZ6asAxmg7mZ3VSMFG7mo8ENeOhSZ0Oz6ZTBILL3wFccZA9uJIq7NWmqC9dRiGiuKXBB62No7sINoHg3114e2xYa9qvNmGg="
|
||||||
|
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- $HOME/.cache/pip
|
- $HOME/.cache/pip
|
||||||
- $HOME/Library/Caches/pip
|
- $HOME/Library/Caches/pip
|
||||||
- $TRAVIS_BUILD_DIR/cache/wheel
|
- $TRAVIS_BUILD_DIR/cache/wheel
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- libgmp3-dev
|
||||||
|
- build-essential
|
||||||
|
- git
|
||||||
|
- libssl-dev
|
||||||
|
- libffi-dev
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" && "$TRAVIS_PULL_REQUEST" == "false" ]]; then ./packaging/travis/setup_osx.sh; fi
|
- virtualenv venv
|
||||||
- mkdir -p lbrynet/resources/ui
|
- source venv/bin/activate
|
||||||
- ./packaging/travis/setup_build.sh
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./packaging/travis/install_dependencies_and_run_tests.sh; fi
|
- pip install -U pip
|
||||||
|
- pip install -r requirements.txt
|
||||||
before_script:
|
- pip install git+https://github.com/lbryio/lbryum.git
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" && "$TRAVIS_PULL_REQUEST" == "false" ]]; then openssl aes-256-cbc -k "$ENCRYPTION_SECRET" -in packaging/osx/certs/dist.cer.enc -d -a -out packaging/osx/certs/dist.cer; fi
|
- pip install .
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" && "$TRAVIS_PULL_REQUEST" == "false" ]]; then openssl aes-256-cbc -k "$ENCRYPTION_SECRET" -in packaging/osx/certs/dist.p12.enc -d -a -out packaging/osx/certs/dist.p12; fi
|
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" && "$TRAVIS_PULL_REQUEST" == "false" ]]; then ./packaging/osx/add-key.sh; fi
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then bash packaging/ubuntu/ubuntu_package_setup.sh -t; fi
|
- pip install cython
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" && "$TRAVIS_PULL_REQUEST" == "false" ]]; then cd packaging/osx/lbry-osx-app && ./setup_app.sh && cd $TRAVIS_BUILD_DIR; fi
|
- pip install mock pylint unqlite
|
||||||
# fail the build if this is a build for a tag and we don't have the versions matching; allow tags that start with 'test' to pass
|
- ./run_pylint.sh
|
||||||
- if [[ -n "${TRAVIS_TAG}" ]]; then if [[ "${TRAVIS_TAG}" == test* ]] || [[ "v`python setup.py -V`" = "${TRAVIS_TAG}" ]]; then true; else false; fi; fi
|
- ./run_tests.sh
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then rvm use 2.3.1 && gem install danger --version '~> 4.0' && danger; fi
|
- rvm use 2.3.1 && gem install danger --version '~> 4.0' && danger
|
||||||
|
|
||||||
before_deploy:
|
|
||||||
# s3 release can only upload a folder so move the package into an upload folder
|
|
||||||
- mkdir "${TRAVIS_BUILD_DIR}/upload"
|
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" && "$TRAVIS_PULL_REQUEST" == "false" ]]; then mv "${TRAVIS_BUILD_DIR}/packaging/osx/lbry-osx-app/`python setup.py --name`.`python setup.py -V`.dmg" "${TRAVIS_BUILD_DIR}/upload"; fi
|
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then mv "${TRAVIS_BUILD_DIR}/`python setup.py --name`_`python setup.py -V`_amd64.deb" "${TRAVIS_BUILD_DIR}/upload"; fi
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
- provider: releases
|
|
||||||
file: "${TRAVIS_BUILD_DIR}/upload/`python setup.py --name`_`python setup.py -V`_amd64.deb"
|
|
||||||
skip_cleanup: true
|
|
||||||
prerelease: true
|
|
||||||
on:
|
|
||||||
tags: true
|
|
||||||
condition: "$TRAVIS_OS_NAME = linux"
|
|
||||||
# this is the oauth token for the lbry-ci user
|
|
||||||
api_key:
|
|
||||||
secure: nKdWGROnLNodx9k9nWvq2wezkPvSVL8zF63qjPXjhdOe9kCUbcLp7WnFDYpn9EJj4Pofq/ejeCHwjA+5x7JUP3Szk7SlJV61B4c/5hl64rl7oSKOoKskjdE2jaOG3CJuOUrh0yQ59U3vMMABcsnw/wJaCIuu/erdPIm8g8R+stu1YHOGtl5Y9WiW+zLJn2vc3GooV1TWtki9EnrmFfw0Vrqc4RMVMFB1ojE7ggrK1LIwcmGSbLIYzker1ZRz8SCy+84sGk4//V+2i2NNiz5AkPuG7BBGrU2twE9nD23IlruJAdVdi71P3ytAmi0kKyvxIU4VeNaqyTk9zeL5IB9J5IIgvekHgKcsKhFUZ6QcXT1Xfxl4ELftvWCTHWiewnXFdqLcG9GZiUaE6+7wdalwDAP3tqS2emiibetlBZERHR+RMR00ej+1MBYWGMlTse/0Tglndv0a2qqgAJYLKPRT02hTRYGxZ1MrJe+WGnChRmzwgLVTIgZuiDciFOahN0TYGSORk6OpnZBsxvpzSqDw5UDJx0BmbJ1xMNDFbOs8ubZ9yIpB9yNMGw66FPacOF61XNYnmA68ILC28UtOFKuuHLrUPbM5JmQkDVhtTfFbBnyHefyCLAL4MHvJJKGi1oaOXjYaJ/J095h636/kQ0cHHuVMgoWUQZOQ44xRAz7tMuc=
|
|
||||||
- provider: releases
|
|
||||||
file: "${TRAVIS_BUILD_DIR}/upload/`python setup.py --name`.`python setup.py -V`.dmg"
|
|
||||||
skip_cleanup: true
|
|
||||||
prerelease: true
|
|
||||||
on:
|
|
||||||
tags: true
|
|
||||||
condition: "$TRAVIS_OS_NAME = osx"
|
|
||||||
# this is the oauth token for the lbry-ci user
|
|
||||||
api_key:
|
|
||||||
secure: nKdWGROnLNodx9k9nWvq2wezkPvSVL8zF63qjPXjhdOe9kCUbcLp7WnFDYpn9EJj4Pofq/ejeCHwjA+5x7JUP3Szk7SlJV61B4c/5hl64rl7oSKOoKskjdE2jaOG3CJuOUrh0yQ59U3vMMABcsnw/wJaCIuu/erdPIm8g8R+stu1YHOGtl5Y9WiW+zLJn2vc3GooV1TWtki9EnrmFfw0Vrqc4RMVMFB1ojE7ggrK1LIwcmGSbLIYzker1ZRz8SCy+84sGk4//V+2i2NNiz5AkPuG7BBGrU2twE9nD23IlruJAdVdi71P3ytAmi0kKyvxIU4VeNaqyTk9zeL5IB9J5IIgvekHgKcsKhFUZ6QcXT1Xfxl4ELftvWCTHWiewnXFdqLcG9GZiUaE6+7wdalwDAP3tqS2emiibetlBZERHR+RMR00ej+1MBYWGMlTse/0Tglndv0a2qqgAJYLKPRT02hTRYGxZ1MrJe+WGnChRmzwgLVTIgZuiDciFOahN0TYGSORk6OpnZBsxvpzSqDw5UDJx0BmbJ1xMNDFbOs8ubZ9yIpB9yNMGw66FPacOF61XNYnmA68ILC28UtOFKuuHLrUPbM5JmQkDVhtTfFbBnyHefyCLAL4MHvJJKGi1oaOXjYaJ/J095h636/kQ0cHHuVMgoWUQZOQ44xRAz7tMuc=
|
|
||||||
- provider: s3
|
|
||||||
access_key_id:
|
|
||||||
secure: "gmJNW8bda2snpA2F+0gucjgO/orvZL0a348QmiffYdtXleIseyY+C4ZI9llWm+s8n2TxiqBYpc/A3Bv7JM0yIccjF0CWQb8pu4HkVT2xLT/1p28EdfxKhR0H5sLtkxOCvLIuf3ppZWac8IzRWvh9TDER1TVxbIGvbOJCtKJ+sUKGCWVkxJY6lzAy7+YHwY9sLV6GvarbkfcnbwNh0qPEROcc6JXUQRKCjWOoZLSZHx4dwxlDiXaG1GyUSm2bwtB11VbMZqaP5eO2zypcUr24J0WkzuAOFIUMDERQnY6eSR62T88BjVjL+07kQufSTtnHC49uHsylyQLwkphkwi2Ei3c/fJ5XI1gY0Med/WOHuy99LAaaHQvHxVa9Zxvrgivvu1oa2QdLir05asMCB0G6Yjgz38Fl8jzdKN/PLHs/lhgBGOJfMN+0UR7hOrLeXdJcMriVfwzYrCl6KkFgTe50rcMx8vv6SH15AqZ5sceksy+maA4O8Mxq1hEe2qJABgRdRZK3FnFKNnQOxfrlU6N9zMNsicVcRwH6WNBtoL4BK3KeMproWnorh9rXmdoSG2Fh5X636cudYhLrAbO5yaoZAXFxHqOV1n63v3tgv4MKrB999OF9V9HyYXv3ro9WZTTsH7LskLA7YmTvXtpMVgBK8SfnvqCjLim5qpVvIVPQIOY="
|
|
||||||
secret_access_key:
|
|
||||||
secure: "pS28jMSNV8HUSa8P8pReXgBtHW0OSWDZMAlZhBrtUI05goUnK6buXadvzCynZWgDiXPHuEuLZOLDVj5yL8N3eCa+sG1tEDcCjPxrBFxHisng8atgn3FaL15MBOdXn0qOBUr+vQ4jbUozsBYGqmoZQV0/Af53tU55KK5HJrotkd++SNTEQrFbWZavM+Wvhw4yJN2hmRer9II72DCZkayUjpvBq+irnGeU0g9SrX8VULCg+sqcnbqdLWd+VALHzQr+O74MaWE8mu2PA8A1GKWZZ/a+LoTh1T2bArpX94q0ueea1eEcUA154vC1azkKK5vy9hzENt5qiiEleBDE31DhbGaeEoakEXvHWrdI3DYiakD6prj0necD8aAK6VhPtqwiTtTf7E4BE9hxY4nJRDuZckvFI4LYFMvHlbdqBieeZPflStkws7VgsfrGV7EberYIbSEohUGGUBg3rdaCIPsn8W4nQAixq39Dcfm0orGo4BgargT6FFtAeDzsfYdbKBk/F8BOPMDJz9P1utAZ/ZeBexic16aeIbk7+wtaQUd0Hswm+2QUHddshvp9IzNniFb1BLvRR/lOVl0HdUkJj/haR2M8XhwcRFIKpL2oMZHwRmLW4c1kkEx+KSfAB77arjgrCzq3y5MlKUSliL5qZZMIJX0ReRQ2dcy3DCY0Fxdj014="
|
|
||||||
bucket: lbrynet-master
|
|
||||||
skip_cleanup: true
|
|
||||||
local_dir: "${TRAVIS_BUILD_DIR}/upload"
|
|
||||||
region: us-west-2
|
|
||||||
on:
|
|
||||||
branch: master
|
|
||||||
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
# needed to unlock the identity file when its on the keychain
|
|
||||||
- secure: "aqgVNHfeh6JUqTTWG5+W+tTsIJkePS6HyLkcZlq6ODYrfdGKa90EeV4q4wdGfP5IkrBbf+WBFACDGVp574E7vfMLMNKUDuUtgnGVPwqOIhjG82ud8Xa7qF7lsw50QOnRYYVd2GLlCIzk8sffT5ncjSPN2ClNVM5iTwCkC8TNSAVnEJxu6bG6hcaT4uCWWjs0m+39O1xJwxJ4vTjpE/gy+j2FTSaUR5cNavOVCyJqpeKlga9aoBVsQHWvxlYurdWbwRLwVIV7bDE+sYPnwn1nMFQpx5RZ1AX1Z2UxNFKcYzLJgcWe85OjxLyT4udX+XZ9SLsdOjm1n201OLEKsmTxmHS8yqpbu6+pKQ1rLMEVpgPGfS8DdtqZyb3z0u6q4jztpm+uBe8hnFgwQFGXO63nOQsI0n1PMR3evAnVx7jYt7y/UALs2A9yjosMwDqgql1FMhyd0OJGo8Ky8YpDsr2J5zGVvIqt2/N+lP+SOe2D1J/5EhGlY0o4tqIAFskh3q8/GR6UGm70KT2l4LJqrU1WGrGxPJ+HoOEmvG6eqLesk03fAX3v5+DgXZWErnzXMIOGDPaFVpmx+G9VZTIlmf+3Wbu9TnZE5PRwFTdP1rqjGpjUhHeF0VTc2qgNq1OfL98CBO1wLgA195+em58cELalnwDMWUTmY1Jt1kUuAtCc11U="
|
|
||||||
# used to decypt the aes decrypt the certificate and identity files
|
|
||||||
- secure: "FzftiEBFMngQIci5KZ+tpKs/BubalhWXJ9f8yogGNVa3XplLheUXYgcsNU8sYT2MJaKAHN9fSjHWb67UtKT7yXddXxeOPnW6wJ3ua/FXnpynsmeGKTfh3stvgjpzdXous67uHmCWMMklfb6z7UuDohjUMAe5n5HKw5tq1RzTKpc2kJacOC6qUT5laUOvULyCaO9E9HmbHeR5ZeXAC6pnzX2ccsSrcXvPozHzBIZ9RyothKs+CZw8PEuJo07RRL8meboegqYOUrOYuz6A2gS2mZJoy59ivZKOFxS5shEuv2Jt80RyfyxBoUpKFq8OG3Am5nAEzDiTIGzmIoKDEGKeTagk/sEtSZXiMDkzDT4GX/j1rUNLCBU87bXEFS2zfRsrfg8c1XZPIzDYBT1PY2QtLBdddF5zzDoKdPLJ3sjN+fZFE5RlnwfwnMHriVRZZlzjcdk0Z06gKTBCxUg5BZamnOOK+K8qunMJXVS+Vmi5u4RoTZZiCosUlYKnSKJ8suO9C0+znxoViusPqP4ONprNHgDoZw+UKio84QW3PrZv9h4zH/D+msDgJRZ0ceqDD+6Wz1J8Mm5ptW1GOLh/IU12TPXjxteqh0Um2vv5eIPmjK9uEK666kK7PqtPDkYhAfWvF+nmOOyPMJfbP4MW/i9WHNF4ghsIMbPKfqNhgSmfrYw="
|
|
||||||
|
|
|
@ -33,6 +33,9 @@ at anytime.
|
||||||
## [0.8.4rc0] - 2017-02-17
|
## [0.8.4rc0] - 2017-02-17
|
||||||
### Changed
|
### Changed
|
||||||
* Remove unused upload_allowed option
|
* Remove unused upload_allowed option
|
||||||
|
* Remove code related to packaging as that step is now done in the electron client
|
||||||
|
* Remove lbryum version check; use lbry-electron as version source
|
||||||
|
* Include download url in version check
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
* add misssing traceback to logging
|
* add misssing traceback to logging
|
||||||
|
|
93
README.md
|
@ -3,19 +3,30 @@
|
||||||
|
|
||||||
# LBRY
|
# LBRY
|
||||||
|
|
||||||
LBRY is a fully decentralized, open-source protocol facilitating the discovery, access, and (sometimes) purchase of data.
|
LBRY is a fully decentralized, open-source protocol facilitating the
|
||||||
|
discovery, access, and (sometimes) purchase of data.
|
||||||
|
|
||||||
## Installing LBRY
|
This repo is a reference implementation of the LBRY protocol and
|
||||||
|
provides daemon that can interact with the network via a json-rpc
|
||||||
|
interface.
|
||||||
|
|
||||||
We provide binaries for Windows, macOS, and Debian-based Linux.
|
## Installing the LBRY App
|
||||||
|
|
||||||
|
The LBRY App is a decentralized content marketplace built on top of
|
||||||
|
the LBRY protocol. We provide binaries for Windows, macOS, and
|
||||||
|
Debian-based Linux.
|
||||||
|
|
||||||
| Windows | macOS | Linux |
|
| Windows | macOS | Linux |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| [Download MSI](https://lbry.io/get/lbry.msi) | [Download DMG](https://lbry.io/get/lbry.dmg) | [Download DEB](https://lbry.io/get/lbry.deb) |
|
| [Download](https://lbry.io/get/lbry.msi) | [Download](https://lbry.io/get/lbry.dmg) | [Download](https://lbry.io/get/lbry.deb) |
|
||||||
|
|
||||||
Our [releases page](https://github.com/lbryio/lbry/releases/latest) also contains the latest release, pre-releases, and past builds.
|
Our [releases page](https://github.com/lbryio/lbry-app/releases/latest) also contains the latest release, pre-releases, and past builds.
|
||||||
|
|
||||||
|
|
||||||
|
## Using the LBRY daemon
|
||||||
|
|
||||||
|
See our quickstart guide at http://lbry.io/quickstart for details on how to install and use the `lbrynet-daemon`.
|
||||||
|
|
||||||
For instructions on building from source, see [INSTALL.md](INSTALL.md).
|
|
||||||
|
|
||||||
## What is LBRY?
|
## What is LBRY?
|
||||||
|
|
||||||
|
@ -23,61 +34,23 @@ LBRY is a fully decentralized network for distributing data. It consists of peer
|
||||||
and downloading data from other peers, possibly in exchange for payments, and a distributed hash
|
and downloading data from other peers, possibly in exchange for payments, and a distributed hash
|
||||||
table, used by peers to discover other peers.
|
table, used by peers to discover other peers.
|
||||||
|
|
||||||
On LBRY, data is broken into chunks, and each chunk is specified by its sha384 hash sum. This
|
On LBRY, data is broken into chunks, and each chunk is content
|
||||||
guarantees that peers can verify the correctness of each chunk without having to know anything
|
addressable, specified by its sha384 hash sum. This guarantees that
|
||||||
about its contents, and can confidently re-transmit the chunk to other peers. Peers wishing to
|
peers can verify the correctness of each chunk without having to know
|
||||||
transmit chunks to other peers announce to the distributed hash table that they are associated
|
anything about its contents, and can confidently re-transmit the chunk
|
||||||
with the sha384 hash sum in question. When a peer wants to download that chunk from the network,
|
to other peers. Peers wishing to transmit chunks to other peers
|
||||||
it asks the distributed hash table which peers are associated with that sha384 hash sum. The
|
announce to the distributed hash table that they are associated with
|
||||||
distributed hash table can also be used more generally. It simply stores IP addresses and
|
the sha384 hash sum in question. When a peer wants to download that
|
||||||
ports which are associated with 384-bit numbers, and can be used by any type of application to
|
chunk from the network, it asks the distributed hash table which peers
|
||||||
help peers find each other. For example, an application for which clients don't know all of the
|
are associated with that sha384 hash sum. The distributed hash table
|
||||||
necessary chunks may use some identifier, chosen by the application, to find clients which do
|
can also be used more generally. It simply stores IP addresses and
|
||||||
know all of the necessary chunks.
|
ports which are associated with 384-bit numbers, and can be used by
|
||||||
|
any type of application to help peers find each other. For example, an
|
||||||
|
application for which clients don't know all of the necessary chunks
|
||||||
|
may use some identifier, chosen by the application, to find clients
|
||||||
|
which do know all of the necessary chunks.
|
||||||
|
|
||||||
## For Developers
|
## Contributions
|
||||||
|
|
||||||
The bundled LBRY application uses the lbrynet JSONRPC api found in `lbrynet.lbrynet_daemon.LBRYDaemon`. This api allows for applications and web services like the lbry browser UI to interact with lbrynet. If you've installed lbrynet, you can run `lbrynet-daemon` without running the app. While the app or `lbrynet-daemon` is running, you can use the following to show the help for all the available commands:
|
|
||||||
|
|
||||||
```
|
|
||||||
import sys
|
|
||||||
|
|
||||||
try:
|
|
||||||
from lbrynet import conf
|
|
||||||
from lbrynet.lbrynet_daemon.auth.client import LBRYAPIClient
|
|
||||||
except ImportError:
|
|
||||||
print "You don't have lbrynet installed!"
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
conf.initialize_settings()
|
|
||||||
api = LBRYAPIClient.get_client()
|
|
||||||
|
|
||||||
try:
|
|
||||||
status = api.status()
|
|
||||||
except:
|
|
||||||
print "lbrynet-daemon isn't running!"
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
if not status['is_running']:
|
|
||||||
print "lbrynet-daemon hasn't finished starting up, here's the status message:"
|
|
||||||
print status
|
|
||||||
sys.exit(0)
|
|
||||||
else:
|
|
||||||
for cmd in api.commands():
|
|
||||||
print "%s:\n%s" % (cmd, api.help({'command': cmd}))
|
|
||||||
```
|
|
||||||
|
|
||||||
If you've installed lbrynet, it comes with a file sharing application, called `lbrynet-daemon`, which breaks
|
|
||||||
files into chunks, encrypts them with a symmetric key, computes their sha384 hash sum, generates
|
|
||||||
a special file called a 'stream descriptor' containing the hash sums and some other file metadata,
|
|
||||||
and makes the chunks available for download by other peers. A peer wishing to download the file
|
|
||||||
must first obtain the 'stream descriptor' and then may open it with his `lbrynet-daemon` client,
|
|
||||||
download all of the chunks by locating peers with the chunks via the DHT, and then combine the
|
|
||||||
chunks into the original file, according to the metadata included in the 'stream descriptor'.
|
|
||||||
|
|
||||||
For instructions on installing from source, see [INSTALL.md](INSTALL.md).
|
|
||||||
|
|
||||||
Source code: https://github.com/lbryio/lbry
|
|
||||||
|
|
||||||
To contribute, [join us on Slack](https://lbry-slackin.herokuapp.com/) or contact jeremy@lbry.io. Pull requests are also welcome.
|
To contribute, [join us on Slack](https://lbry-slackin.herokuapp.com/) or contact jeremy@lbry.io. Pull requests are also welcome.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
__version__ = "0.8.7"
|
__version__ = "0.9.0rc6"
|
||||||
version = tuple(__version__.split('.'))
|
version = tuple(__version__.split('.'))
|
||||||
|
|
||||||
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
||||||
|
|
|
@ -2,10 +2,8 @@ import base64
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
import os
|
|
||||||
import socket
|
import socket
|
||||||
import string
|
import string
|
||||||
import sys
|
|
||||||
|
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
|
|
||||||
|
@ -104,12 +102,6 @@ def check_connection(server="www.lbry.io", port=80):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def setup_certs_for_windows():
|
|
||||||
if getattr(sys, 'frozen', False) and os.name == "nt":
|
|
||||||
cert_path = os.path.join(os.path.dirname(sys.executable), "cacert.pem")
|
|
||||||
os.environ["REQUESTS_CA_BUNDLE"] = cert_path
|
|
||||||
|
|
||||||
|
|
||||||
def random_string(length=10, chars=string.ascii_lowercase):
|
def random_string(length=10, chars=string.ascii_lowercase):
|
||||||
return ''.join([random.choice(chars) for _ in range(length)])
|
return ''.join([random.choice(chars) for _ in range(length)])
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ from twisted.internet.task import LoopingCall
|
||||||
from twisted.python.failure import Failure
|
from twisted.python.failure import Failure
|
||||||
|
|
||||||
# TODO: importing this when internet is disabled raises a socket.gaierror
|
# TODO: importing this when internet is disabled raises a socket.gaierror
|
||||||
from lbryum.version import LBRYUM_VERSION as lbryum_version
|
from lbryum.version import LBRYUM_VERSION
|
||||||
from lbrynet import __version__ as lbrynet_version
|
from lbrynet import __version__ as LBRYNET_VERSION
|
||||||
from lbrynet import conf, analytics
|
from lbrynet import conf, analytics
|
||||||
from lbrynet.conf import LBRYCRD_WALLET, LBRYUM_WALLET, PTC_WALLET
|
from lbrynet.conf import LBRYCRD_WALLET, LBRYUM_WALLET, PTC_WALLET
|
||||||
from lbrynet.reflector import reupload
|
from lbrynet.reflector import reupload
|
||||||
|
@ -33,7 +33,6 @@ from lbrynet.lbryfile.StreamDescriptor import save_sd_info
|
||||||
from lbrynet.lbryfile.EncryptedFileMetadataManager import DBEncryptedFileMetadataManager
|
from lbrynet.lbryfile.EncryptedFileMetadataManager import DBEncryptedFileMetadataManager
|
||||||
from lbrynet.lbryfile.StreamDescriptor import EncryptedFileStreamType
|
from lbrynet.lbryfile.StreamDescriptor import EncryptedFileStreamType
|
||||||
from lbrynet.lbryfilemanager.EncryptedFileManager import EncryptedFileManager
|
from lbrynet.lbryfilemanager.EncryptedFileManager import EncryptedFileManager
|
||||||
from lbrynet.lbrynet_daemon.UIManager import UIManager
|
|
||||||
from lbrynet.lbrynet_daemon.Downloader import GetStream
|
from lbrynet.lbrynet_daemon.Downloader import GetStream
|
||||||
from lbrynet.lbrynet_daemon.Publisher import Publisher
|
from lbrynet.lbrynet_daemon.Publisher import Publisher
|
||||||
from lbrynet.lbrynet_daemon.ExchangeRateManager import ExchangeRateManager
|
from lbrynet.lbrynet_daemon.ExchangeRateManager import ExchangeRateManager
|
||||||
|
@ -83,11 +82,9 @@ STREAM_STAGES = [
|
||||||
]
|
]
|
||||||
|
|
||||||
CONNECTION_STATUS_CONNECTED = 'connected'
|
CONNECTION_STATUS_CONNECTED = 'connected'
|
||||||
CONNECTION_STATUS_VERSION_CHECK = 'version_check'
|
|
||||||
CONNECTION_STATUS_NETWORK = 'network_connection'
|
CONNECTION_STATUS_NETWORK = 'network_connection'
|
||||||
CONNECTION_MESSAGES = {
|
CONNECTION_MESSAGES = {
|
||||||
CONNECTION_STATUS_CONNECTED: 'No connection problems detected',
|
CONNECTION_STATUS_CONNECTED: 'No connection problems detected',
|
||||||
CONNECTION_STATUS_VERSION_CHECK: "There was a problem checking for updates on github",
|
|
||||||
CONNECTION_STATUS_NETWORK: "Your internet connection appears to have been interrupted",
|
CONNECTION_STATUS_NETWORK: "Your internet connection appears to have been interrupted",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,40 +124,55 @@ class CheckInternetConnection(object):
|
||||||
self.daemon.connected_to_internet = utils.check_connection()
|
self.daemon.connected_to_internet = utils.check_connection()
|
||||||
|
|
||||||
|
|
||||||
class CheckRemoteVersions(object):
|
class CheckRemoteVersion(object):
|
||||||
def __init__(self, daemon):
|
URL = 'https://api.github.com/repos/lbryio/lbry-electron/releases/latest'
|
||||||
self.daemon = daemon
|
def __init__(self):
|
||||||
|
self.version = None
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
d = threads.deferToThread(self._get_lbrynet_version)
|
d = threads.deferToThread(self._get_lbry_electron_client_version)
|
||||||
d.addErrback(self._trap_and_log_error, 'lbrynet')
|
d.addErrback(self._trap_and_log_error, 'lbry-electron')
|
||||||
d.addCallback(lambda _: threads.deferToThread(self._get_lbryum_version))
|
|
||||||
d.addErrback(self._trap_and_log_error, 'lbryum')
|
|
||||||
d.addErrback(log.fail(), 'Failure checking versions on github')
|
d.addErrback(log.fail(), 'Failure checking versions on github')
|
||||||
|
|
||||||
def _trap_and_log_error(self, err, module_checked):
|
def _trap_and_log_error(self, err, module_checked):
|
||||||
# KeyError is thrown by get_version_from_github
|
# KeyError is thrown by get_version_from_github
|
||||||
# It'd be better to catch the error before trying to parse the response
|
# It'd be better to catch the error before trying to parse the response
|
||||||
err.trap(requests_exceptions.RequestException, KeyError)
|
err.trap(requests_exceptions.RequestException, KeyError)
|
||||||
if err.check(requests_exceptions.RequestException, KeyError):
|
log.warning("Failed to check latest %s version from github", module_checked)
|
||||||
log.warning("Failed to check latest %s version from github", module_checked)
|
|
||||||
|
|
||||||
def _get_lbryum_version(self):
|
def _get_lbry_electron_client_version(self):
|
||||||
self.daemon.git_lbryum_version = get_lbryum_version_from_github()
|
# We'll need to ensure the lbry-electron version is in sync
|
||||||
log.info(
|
# with the lbrynet-daemon version
|
||||||
"remote lbryum %s > local lbryum %s = %s",
|
self._set_data_from_github()
|
||||||
self.daemon.git_lbryum_version, lbryum_version,
|
|
||||||
utils.version_is_greater_than(self.daemon.git_lbryum_version, lbryum_version)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_lbrynet_version(self):
|
|
||||||
self.daemon.git_lbrynet_version = get_lbrynet_version_from_github()
|
|
||||||
log.info(
|
log.info(
|
||||||
"remote lbrynet %s > local lbrynet %s = %s",
|
"remote lbrynet %s > local lbrynet %s = %s",
|
||||||
self.daemon.git_lbrynet_version, lbrynet_version,
|
self.version, LBRYNET_VERSION,
|
||||||
utils.version_is_greater_than(self.daemon.git_lbrynet_version, lbryum_version)
|
utils.version_is_greater_than(self.version, LBRYNET_VERSION)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _set_data_from_github(self):
|
||||||
|
release = self._get_release_data()
|
||||||
|
# githubs documentation claims this should never happen, but we'll check just in case
|
||||||
|
if release['prerelease']:
|
||||||
|
raise Exception('Release {} is a pre-release'.format(release['tag_name']))
|
||||||
|
self.version = self._get_version_from_release(release)
|
||||||
|
|
||||||
|
def _get_release_data(self):
|
||||||
|
response = requests.get(self.URL, timeout=20)
|
||||||
|
release = response.json()
|
||||||
|
return release
|
||||||
|
|
||||||
|
def _get_version_from_release(self, release):
|
||||||
|
"""Return the latest released version from github."""
|
||||||
|
tag = release['tag_name']
|
||||||
|
return get_version_from_tag(tag)
|
||||||
|
|
||||||
|
def is_update_available(self):
|
||||||
|
try:
|
||||||
|
return utils.version_is_greater_than(self.version, LBRYNET_VERSION)
|
||||||
|
except TypeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class AlwaysSend(object):
|
class AlwaysSend(object):
|
||||||
def __init__(self, value_generator, *args, **kwargs):
|
def __init__(self, value_generator, *args, **kwargs):
|
||||||
|
@ -200,7 +212,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
'is_running', 'is_first_run', 'get_time_behind_blockchain', 'daemon_status',
|
'is_running', 'is_first_run', 'get_time_behind_blockchain', 'daemon_status',
|
||||||
'get_start_notice',
|
'get_start_notice',
|
||||||
]
|
]
|
||||||
last_version = {'last_version': {'lbrynet': lbrynet_version, 'lbryum': lbryum_version}}
|
last_version = {'last_version': {'lbrynet': LBRYNET_VERSION, 'lbryum': LBRYUM_VERSION}}
|
||||||
conf.settings.update(last_version)
|
conf.settings.update(last_version)
|
||||||
self.db_dir = conf.settings['data_dir']
|
self.db_dir = conf.settings['data_dir']
|
||||||
self.download_directory = conf.settings['download_directory']
|
self.download_directory = conf.settings['download_directory']
|
||||||
|
@ -235,8 +247,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
self.startup_status = STARTUP_STAGES[0]
|
self.startup_status = STARTUP_STAGES[0]
|
||||||
self.connected_to_internet = True
|
self.connected_to_internet = True
|
||||||
self.connection_status_code = None
|
self.connection_status_code = None
|
||||||
self.git_lbrynet_version = None
|
|
||||||
self.git_lbryum_version = None
|
|
||||||
self.platform = None
|
self.platform = None
|
||||||
self.first_run = None
|
self.first_run = None
|
||||||
self.log_file = conf.settings.get_log_filename()
|
self.log_file = conf.settings.get_log_filename()
|
||||||
|
@ -261,16 +271,16 @@ class Daemon(AuthJSONRPCServer):
|
||||||
self.pending_claims = {}
|
self.pending_claims = {}
|
||||||
self.name_cache = {}
|
self.name_cache = {}
|
||||||
self.exchange_rate_manager = ExchangeRateManager()
|
self.exchange_rate_manager = ExchangeRateManager()
|
||||||
|
self._remote_version = CheckRemoteVersion()
|
||||||
calls = {
|
calls = {
|
||||||
Checker.INTERNET_CONNECTION: LoopingCall(CheckInternetConnection(self)),
|
Checker.INTERNET_CONNECTION: LoopingCall(CheckInternetConnection(self)),
|
||||||
Checker.VERSION: LoopingCall(CheckRemoteVersions(self)),
|
Checker.VERSION: LoopingCall(self._remote_version),
|
||||||
Checker.CONNECTION_STATUS: LoopingCall(self._update_connection_status),
|
Checker.CONNECTION_STATUS: LoopingCall(self._update_connection_status),
|
||||||
Checker.PENDING_CLAIM: LoopingCall(self._check_pending_claims),
|
Checker.PENDING_CLAIM: LoopingCall(self._check_pending_claims),
|
||||||
}
|
}
|
||||||
self.looping_call_manager = LoopingCallManager(calls)
|
self.looping_call_manager = LoopingCallManager(calls)
|
||||||
self.sd_identifier = StreamDescriptorIdentifier()
|
self.sd_identifier = StreamDescriptorIdentifier()
|
||||||
self.stream_info_manager = DBEncryptedFileMetadataManager(self.db_dir)
|
self.stream_info_manager = DBEncryptedFileMetadataManager(self.db_dir)
|
||||||
self.lbry_ui_manager = UIManager(root)
|
|
||||||
self.lbry_file_manager = None
|
self.lbry_file_manager = None
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@ -308,11 +318,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
self.looping_call_manager.start(Checker.CONNECTION_STATUS, 30)
|
self.looping_call_manager.start(Checker.CONNECTION_STATUS, 30)
|
||||||
self.exchange_rate_manager.start()
|
self.exchange_rate_manager.start()
|
||||||
|
|
||||||
if conf.settings['host_ui']:
|
|
||||||
self.lbry_ui_manager.update_checker.start(1800, now=False)
|
|
||||||
yield self.lbry_ui_manager.setup()
|
|
||||||
if launch_ui:
|
|
||||||
self.lbry_ui_manager.launch()
|
|
||||||
yield self._initial_setup()
|
yield self._initial_setup()
|
||||||
yield threads.deferToThread(self._setup_data_directory)
|
yield threads.deferToThread(self._setup_data_directory)
|
||||||
yield self._check_db_migration()
|
yield self._check_db_migration()
|
||||||
|
@ -330,7 +335,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
def _get_platform(self):
|
def _get_platform(self):
|
||||||
if self.platform is None:
|
if self.platform is None:
|
||||||
self.platform = system_info.get_platform()
|
self.platform = system_info.get_platform()
|
||||||
self.platform["ui_version"] = self.lbry_ui_manager.loaded_git_version
|
|
||||||
return self.platform
|
return self.platform
|
||||||
|
|
||||||
def _initial_setup(self):
|
def _initial_setup(self):
|
||||||
|
@ -367,9 +371,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
def _update_connection_status(self):
|
def _update_connection_status(self):
|
||||||
self.connection_status_code = CONNECTION_STATUS_CONNECTED
|
self.connection_status_code = CONNECTION_STATUS_CONNECTED
|
||||||
|
|
||||||
if not self.git_lbrynet_version or not self.git_lbryum_version:
|
|
||||||
self.connection_status_code = CONNECTION_STATUS_VERSION_CHECK
|
|
||||||
|
|
||||||
if not self.connected_to_internet:
|
if not self.connected_to_internet:
|
||||||
self.connection_status_code = CONNECTION_STATUS_NETWORK
|
self.connection_status_code = CONNECTION_STATUS_NETWORK
|
||||||
|
|
||||||
|
@ -532,8 +533,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
self.looping_call_manager.shutdown()
|
self.looping_call_manager.shutdown()
|
||||||
if self.analytics_manager:
|
if self.analytics_manager:
|
||||||
self.analytics_manager.shutdown()
|
self.analytics_manager.shutdown()
|
||||||
if self.lbry_ui_manager.update_checker.running:
|
|
||||||
self.lbry_ui_manager.update_checker.stop()
|
|
||||||
|
|
||||||
self._clean_up_temp_files()
|
self._clean_up_temp_files()
|
||||||
|
|
||||||
|
@ -1254,27 +1253,15 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
platform_info = self._get_platform()
|
platform_info = self._get_platform()
|
||||||
try:
|
|
||||||
lbrynet_update_available = utils.version_is_greater_than(
|
|
||||||
self.git_lbrynet_version, lbrynet_version)
|
|
||||||
except TypeError:
|
|
||||||
lbrynet_update_available = False
|
|
||||||
try:
|
|
||||||
lbryum_update_available = utils.version_is_greater_than(
|
|
||||||
self.git_lbryum_version, lbryum_version)
|
|
||||||
except TypeError:
|
|
||||||
lbryum_update_available = False
|
|
||||||
msg = {
|
msg = {
|
||||||
'platform': platform_info['platform'],
|
'platform': platform_info['platform'],
|
||||||
'os_release': platform_info['os_release'],
|
'os_release': platform_info['os_release'],
|
||||||
'os_system': platform_info['os_system'],
|
'os_system': platform_info['os_system'],
|
||||||
'lbrynet_version': lbrynet_version,
|
'lbrynet_version': LBRYNET_VERSION,
|
||||||
'lbryum_version': lbryum_version,
|
'lbryum_version': LBRYUM_VERSION,
|
||||||
'ui_version': platform_info['ui_version'],
|
'ui_version': platform_info['ui_version'],
|
||||||
'remote_lbrynet': self.git_lbrynet_version,
|
'remote_lbrynet': self._remote_version.version,
|
||||||
'remote_lbryum': self.git_lbryum_version,
|
'lbrynet_update_available': self._remote_version.is_update_available(),
|
||||||
'lbrynet_update_available': lbrynet_update_available,
|
|
||||||
'lbryum_update_available': lbryum_update_available
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("Get version info: " + json.dumps(msg))
|
log.info("Get version info: " + json.dumps(msg))
|
||||||
|
@ -1295,7 +1282,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
message,
|
message,
|
||||||
conf.settings.installation_id,
|
conf.settings.installation_id,
|
||||||
platform_name,
|
platform_name,
|
||||||
lbrynet_version
|
LBRYNET_VERSION
|
||||||
)
|
)
|
||||||
return self._render_response(True)
|
return self._render_response(True)
|
||||||
|
|
||||||
|
@ -2249,28 +2236,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
d.addCallback(lambda _: self._render_response(True))
|
d.addCallback(lambda _: self._render_response(True))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
@AuthJSONRPCServer.auth_required
|
|
||||||
def jsonrpc_configure_ui(self, branch=None, path=None, check_requirements=True):
|
|
||||||
"""
|
|
||||||
Configure the UI being hosted
|
|
||||||
|
|
||||||
Args, optional:
|
|
||||||
'branch': a branch name on lbryio/lbry-web-ui
|
|
||||||
'path': path to a ui folder
|
|
||||||
"""
|
|
||||||
|
|
||||||
if path is not None:
|
|
||||||
d = self.lbry_ui_manager.setup(
|
|
||||||
user_specified=path, check_requirements=check_requirements)
|
|
||||||
elif branch is not None:
|
|
||||||
d = self.lbry_ui_manager.setup(branch=branch, check_requirements=check_requirements)
|
|
||||||
else:
|
|
||||||
d = self.lbry_ui_manager.setup(check_requirements=check_requirements)
|
|
||||||
|
|
||||||
d.addCallback(lambda r: self._render_response(r))
|
|
||||||
|
|
||||||
return d
|
|
||||||
|
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def jsonrpc_open(self, sd_hash):
|
def jsonrpc_open(self, sd_hash):
|
||||||
|
@ -2548,33 +2513,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
def get_lbryum_version_from_github():
|
|
||||||
return get_version_from_github('https://api.github.com/repos/lbryio/lbryum/releases/latest')
|
|
||||||
|
|
||||||
|
|
||||||
def get_lbrynet_version_from_github():
|
|
||||||
return get_version_from_github('https://api.github.com/repos/lbryio/lbry/releases/latest')
|
|
||||||
|
|
||||||
|
|
||||||
def get_version_from_github(url):
|
|
||||||
"""Return the latest released version from github."""
|
|
||||||
response = requests.get(url, timeout=20)
|
|
||||||
release = response.json()
|
|
||||||
tag = release['tag_name']
|
|
||||||
# githubs documentation claims this should never happen, but we'll check just in case
|
|
||||||
if release['prerelease']:
|
|
||||||
raise Exception('Release {} is a pre-release'.format(tag))
|
|
||||||
return get_version_from_tag(tag)
|
|
||||||
|
|
||||||
|
|
||||||
def get_version_from_tag(tag):
|
|
||||||
match = re.match('v([\d.]+)', tag)
|
|
||||||
if match:
|
|
||||||
return match.group(1)
|
|
||||||
else:
|
|
||||||
raise Exception('Failed to parse version from tag {}'.format(tag))
|
|
||||||
|
|
||||||
|
|
||||||
def get_sd_hash(stream_info):
|
def get_sd_hash(stream_info):
|
||||||
if not stream_info:
|
if not stream_info:
|
||||||
return None
|
return None
|
||||||
|
@ -2911,3 +2849,11 @@ def get_blob_payment_rate_manager(session, payment_rate_manager=None):
|
||||||
payment_rate_manager = rate_managers[payment_rate_manager]
|
payment_rate_manager = rate_managers[payment_rate_manager]
|
||||||
log.info("Downloading blob with rate manager: %s", payment_rate_manager)
|
log.info("Downloading blob with rate manager: %s", payment_rate_manager)
|
||||||
return payment_rate_manager or session.payment_rate_manager
|
return payment_rate_manager or session.payment_rate_manager
|
||||||
|
|
||||||
|
|
||||||
|
def get_version_from_tag(tag):
|
||||||
|
match = re.match('v([\d.]+)', tag)
|
||||||
|
if match:
|
||||||
|
return match.group(1)
|
||||||
|
else:
|
||||||
|
raise Exception('Failed to parse version from tag {}'.format(tag))
|
||||||
|
|
|
@ -31,7 +31,6 @@ def stop():
|
||||||
|
|
||||||
|
|
||||||
def start():
|
def start():
|
||||||
utils.setup_certs_for_windows()
|
|
||||||
conf.initialize_settings()
|
conf.initialize_settings()
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="Launch lbrynet-daemon")
|
parser = argparse.ArgumentParser(description="Launch lbrynet-daemon")
|
||||||
|
|
|
@ -1,348 +0,0 @@
|
||||||
import os
|
|
||||||
import logging
|
|
||||||
import shutil
|
|
||||||
import json
|
|
||||||
import webbrowser
|
|
||||||
from urllib2 import urlopen
|
|
||||||
from StringIO import StringIO
|
|
||||||
from zipfile import ZipFile
|
|
||||||
|
|
||||||
import pkg_resources
|
|
||||||
from twisted.internet import defer
|
|
||||||
from twisted.internet.task import LoopingCall
|
|
||||||
|
|
||||||
from lbrynet import conf
|
|
||||||
from lbrynet.lbrynet_daemon.Resources import NoCacheStaticFile
|
|
||||||
from lbrynet import __version__ as lbrynet_version
|
|
||||||
from lbryum.version import LBRYUM_VERSION as lbryum_version
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class UIManager(object):
|
|
||||||
def __init__(self, root):
|
|
||||||
self.ui_root = os.path.join(conf.settings['data_dir'], "lbry-ui")
|
|
||||||
self.active_dir = os.path.join(self.ui_root, "active")
|
|
||||||
self.update_dir = os.path.join(self.ui_root, "update")
|
|
||||||
|
|
||||||
if not os.path.isdir(self.ui_root):
|
|
||||||
os.mkdir(self.ui_root)
|
|
||||||
if not os.path.isdir(self.active_dir):
|
|
||||||
os.mkdir(self.active_dir)
|
|
||||||
if not os.path.isdir(self.update_dir):
|
|
||||||
os.mkdir(self.update_dir)
|
|
||||||
|
|
||||||
self.config = os.path.join(self.ui_root, "active.json")
|
|
||||||
self.update_requires = os.path.join(self.update_dir, "requirements.txt")
|
|
||||||
self.requirements = {}
|
|
||||||
self.check_requirements = True
|
|
||||||
self.ui_dir = self.active_dir
|
|
||||||
self.git_version = None
|
|
||||||
self.root = root
|
|
||||||
self.branch = None
|
|
||||||
self.update_checker = LoopingCall(self.setup)
|
|
||||||
|
|
||||||
if not os.path.isfile(os.path.join(self.config)):
|
|
||||||
self.loaded_git_version = None
|
|
||||||
self.loaded_branch = None
|
|
||||||
self.loaded_requirements = None
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
f = open(self.config, "r")
|
|
||||||
loaded_ui = json.loads(f.read())
|
|
||||||
f.close()
|
|
||||||
self.loaded_git_version = loaded_ui['commit']
|
|
||||||
self.loaded_branch = loaded_ui['branch']
|
|
||||||
self.loaded_requirements = loaded_ui['requirements']
|
|
||||||
except:
|
|
||||||
self.loaded_git_version = None
|
|
||||||
self.loaded_branch = None
|
|
||||||
self.loaded_requirements = None
|
|
||||||
|
|
||||||
def setup(self, branch=None, check_requirements=None, user_specified=None):
|
|
||||||
local_ui_path = user_specified or conf.settings['local_ui_path']
|
|
||||||
|
|
||||||
self.branch = branch or conf.settings['ui_branch']
|
|
||||||
self.check_requirements = (check_requirements if check_requirements is not None
|
|
||||||
else conf.settings['check_ui_requirements'])
|
|
||||||
|
|
||||||
# Note that this currently overrides any manual setting of UI.
|
|
||||||
# It might be worth considering changing that behavior but the expectation
|
|
||||||
# is generally that any manual setting of the UI will happen during development
|
|
||||||
# and not for folks checking out the QA / RC builds that bundle the UI.
|
|
||||||
if self._check_for_bundled_ui():
|
|
||||||
return defer.succeed(True)
|
|
||||||
|
|
||||||
if local_ui_path:
|
|
||||||
if os.path.isdir(local_ui_path):
|
|
||||||
log.info("Checking user specified UI directory: " + str(local_ui_path))
|
|
||||||
self.branch = "user-specified"
|
|
||||||
self.loaded_git_version = "user-specified"
|
|
||||||
d = self.migrate_ui(source=local_ui_path)
|
|
||||||
d.addCallback(lambda _: self._load_ui())
|
|
||||||
return d
|
|
||||||
else:
|
|
||||||
log.info("User specified UI directory doesn't exist, using " + self.branch)
|
|
||||||
elif self.loaded_branch == "user-specified":
|
|
||||||
log.info("Loading user provided UI")
|
|
||||||
d = defer.maybeDeferred(self._load_ui)
|
|
||||||
return d
|
|
||||||
else:
|
|
||||||
log.info("Checking for updates for UI branch: " + self.branch)
|
|
||||||
self._git_url = "https://s3.amazonaws.com/lbry-ui/{}/data.json".format(self.branch)
|
|
||||||
self._dist_url = "https://s3.amazonaws.com/lbry-ui/{}/dist.zip".format(self.branch)
|
|
||||||
|
|
||||||
d = self._up_to_date()
|
|
||||||
d.addCallback(lambda r: self._download_ui() if not r else self._load_ui())
|
|
||||||
return d
|
|
||||||
|
|
||||||
def _check_for_bundled_ui(self):
|
|
||||||
"""Try to load a bundled UI and return True if successful, False otherwise"""
|
|
||||||
try:
|
|
||||||
bundled_path = get_bundled_ui_path()
|
|
||||||
except Exception:
|
|
||||||
log.warning('Failed to get path for bundled UI', exc_info=True)
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
bundle_manager = BundledUIManager(self.root, self.active_dir, bundled_path)
|
|
||||||
loaded = bundle_manager.setup()
|
|
||||||
if loaded:
|
|
||||||
self.loaded_git_version = bundle_manager.version()
|
|
||||||
return loaded
|
|
||||||
|
|
||||||
def _up_to_date(self):
|
|
||||||
def _get_git_info():
|
|
||||||
try:
|
|
||||||
# TODO: should this be switched to the non-blocking getPage?
|
|
||||||
response = urlopen(self._git_url)
|
|
||||||
return defer.succeed(read_sha(response))
|
|
||||||
except Exception:
|
|
||||||
return defer.fail()
|
|
||||||
|
|
||||||
def _set_git(version):
|
|
||||||
self.git_version = version.replace('\n', '')
|
|
||||||
if self.git_version == self.loaded_git_version:
|
|
||||||
log.info("UI is up to date")
|
|
||||||
return defer.succeed(True)
|
|
||||||
else:
|
|
||||||
log.info("UI updates available, checking if installation meets requirements")
|
|
||||||
return defer.succeed(False)
|
|
||||||
|
|
||||||
def _use_existing():
|
|
||||||
log.info("Failed to check for new ui version, trying to use cached ui")
|
|
||||||
return defer.succeed(True)
|
|
||||||
|
|
||||||
d = _get_git_info()
|
|
||||||
d.addCallbacks(_set_git, lambda _: _use_existing)
|
|
||||||
return d
|
|
||||||
|
|
||||||
def migrate_ui(self, source=None):
|
|
||||||
if not source:
|
|
||||||
requires_file = self.update_requires
|
|
||||||
source_dir = self.update_dir
|
|
||||||
delete_source = True
|
|
||||||
else:
|
|
||||||
requires_file = os.path.join(source, "requirements.txt")
|
|
||||||
source_dir = source
|
|
||||||
delete_source = False
|
|
||||||
|
|
||||||
def _skip_requirements():
|
|
||||||
log.info("Skipping ui requirement check")
|
|
||||||
return defer.succeed(True)
|
|
||||||
|
|
||||||
def _check_requirements():
|
|
||||||
if not os.path.isfile(requires_file):
|
|
||||||
log.info("No requirements.txt file, rejecting request to migrate this UI")
|
|
||||||
return defer.succeed(False)
|
|
||||||
requirements = Requirements(requires_file)
|
|
||||||
passed_requirements = requirements.check(lbrynet_version, lbryum_version)
|
|
||||||
return defer.succeed(passed_requirements)
|
|
||||||
|
|
||||||
def _disp_failure():
|
|
||||||
log.info("Failed to satisfy requirements for branch '%s', update was not loaded",
|
|
||||||
self.branch)
|
|
||||||
return defer.succeed(False)
|
|
||||||
|
|
||||||
def _do_migrate():
|
|
||||||
replace_dir(self.active_dir, source_dir)
|
|
||||||
if delete_source:
|
|
||||||
shutil.rmtree(source_dir)
|
|
||||||
|
|
||||||
log.info("Loaded UI update")
|
|
||||||
|
|
||||||
f = open(self.config, "w")
|
|
||||||
loaded_ui = {
|
|
||||||
'commit': self.git_version,
|
|
||||||
'branch': self.branch,
|
|
||||||
'requirements': self.requirements
|
|
||||||
}
|
|
||||||
f.write(json.dumps(loaded_ui))
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
self.loaded_git_version = loaded_ui['commit']
|
|
||||||
self.loaded_branch = loaded_ui['branch']
|
|
||||||
self.loaded_requirements = loaded_ui['requirements']
|
|
||||||
return defer.succeed(True)
|
|
||||||
|
|
||||||
d = _check_requirements() if self.check_requirements else _skip_requirements()
|
|
||||||
d.addCallback(lambda r: _do_migrate() if r else _disp_failure())
|
|
||||||
return d
|
|
||||||
|
|
||||||
def _download_ui(self):
|
|
||||||
def _delete_update_dir():
|
|
||||||
if os.path.isdir(self.update_dir):
|
|
||||||
shutil.rmtree(self.update_dir)
|
|
||||||
return defer.succeed(None)
|
|
||||||
|
|
||||||
def _dl_ui():
|
|
||||||
url = urlopen(self._dist_url)
|
|
||||||
z = ZipFile(StringIO(url.read()))
|
|
||||||
names = [i for i in z.namelist() if '.DS_exStore' not in i and '__MACOSX' not in i]
|
|
||||||
z.extractall(self.update_dir, members=names)
|
|
||||||
log.info("Downloaded files for UI commit " + str(self.git_version).replace("\n", ""))
|
|
||||||
return self.branch
|
|
||||||
|
|
||||||
d = _delete_update_dir()
|
|
||||||
d.addCallback(lambda _: _dl_ui())
|
|
||||||
d.addCallback(lambda _: self.migrate_ui())
|
|
||||||
d.addCallback(lambda _: self._load_ui())
|
|
||||||
return d
|
|
||||||
|
|
||||||
def _load_ui(self):
|
|
||||||
return load_ui(self.root, self.active_dir)
|
|
||||||
|
|
||||||
def launch(self):
|
|
||||||
webbrowser.open(conf.settings.get_ui_address())
|
|
||||||
|
|
||||||
|
|
||||||
class BundledUIManager(object):
|
|
||||||
"""Copies the UI bundled with lbrynet, if available.
|
|
||||||
|
|
||||||
For the QA and nightly builds, we include a copy of the most
|
|
||||||
recent checkout of the development UI. For production builds
|
|
||||||
nothing is bundled.
|
|
||||||
|
|
||||||
n.b: For QA and nightly builds the update check is skipped.
|
|
||||||
"""
|
|
||||||
def __init__(self, root, active_dir, bundled_ui_path):
|
|
||||||
self.root = root
|
|
||||||
self.active_dir = active_dir
|
|
||||||
self.bundled_ui_path = bundled_ui_path
|
|
||||||
self.data_path = os.path.join(bundled_ui_path, 'data.json')
|
|
||||||
self._version = None
|
|
||||||
|
|
||||||
def version(self):
|
|
||||||
if not self._version:
|
|
||||||
self._version = open_and_read_sha(self.data_path)
|
|
||||||
return self._version
|
|
||||||
|
|
||||||
def bundle_is_available(self):
|
|
||||||
return os.path.exists(self.data_path)
|
|
||||||
|
|
||||||
def setup(self):
|
|
||||||
"""Load the bundled UI if possible and necessary
|
|
||||||
|
|
||||||
Returns True if there is a bundled UI, False otherwise
|
|
||||||
"""
|
|
||||||
if not self.bundle_is_available():
|
|
||||||
log.debug('No bundled UI is available')
|
|
||||||
return False
|
|
||||||
if not self.is_active_already_bundled_ui():
|
|
||||||
replace_dir(self.active_dir, self.bundled_ui_path)
|
|
||||||
log.info('Loading the bundled UI')
|
|
||||||
load_ui(self.root, self.active_dir)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def is_active_already_bundled_ui(self):
|
|
||||||
target_data_path = os.path.join(self.active_dir, 'data.json')
|
|
||||||
if os.path.exists(target_data_path):
|
|
||||||
target_version = open_and_read_sha(target_data_path)
|
|
||||||
if self.version() == target_version:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def get_bundled_ui_path():
|
|
||||||
return pkg_resources.resource_filename('lbrynet', 'resources/ui')
|
|
||||||
|
|
||||||
|
|
||||||
def are_same_version(data_a, data_b):
|
|
||||||
"""Compare two data files and return True if they are the same version"""
|
|
||||||
with open(data_a) as a:
|
|
||||||
with open(data_b) as b:
|
|
||||||
return read_sha(a) == read_sha(b)
|
|
||||||
|
|
||||||
|
|
||||||
def open_and_read_sha(filename):
|
|
||||||
with open(filename) as f:
|
|
||||||
return read_sha(f)
|
|
||||||
|
|
||||||
|
|
||||||
def read_sha(filelike):
|
|
||||||
data = json.load(filelike)
|
|
||||||
return data['sha']
|
|
||||||
|
|
||||||
|
|
||||||
def replace_dir(active_dir, source_dir):
|
|
||||||
if os.path.isdir(active_dir):
|
|
||||||
shutil.rmtree(active_dir)
|
|
||||||
shutil.copytree(source_dir, active_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def load_ui(root, active_dir):
|
|
||||||
for name in os.listdir(active_dir):
|
|
||||||
entry = os.path.join(active_dir, name)
|
|
||||||
if os.path.isdir(entry):
|
|
||||||
root.putChild(os.path.basename(entry), NoCacheStaticFile(entry))
|
|
||||||
|
|
||||||
|
|
||||||
class Requirements(object):
|
|
||||||
def __init__(self, requires_file):
|
|
||||||
self.requires_file = requires_file
|
|
||||||
|
|
||||||
def check(self, lbrynet_version, lbryum_version):
|
|
||||||
requirements = self._read()
|
|
||||||
expected = {'lbrynet': lbrynet_version, 'lbryum': lbryum_version}
|
|
||||||
return check_requirements(requirements, expected)
|
|
||||||
|
|
||||||
def _read(self):
|
|
||||||
requirements = {}
|
|
||||||
with open(self.requires_file, "r") as f:
|
|
||||||
for requirement in [line for line in f.read().split('\n') if line]:
|
|
||||||
t = requirement.split('=')
|
|
||||||
if len(t) == 3:
|
|
||||||
requirements[t[0]] = {'version': t[1], 'operator': '=='}
|
|
||||||
elif t[0][-1] == ">":
|
|
||||||
requirements[t[0][:-1]] = {'version': t[1], 'operator': '>='}
|
|
||||||
elif t[0][-1] == "<":
|
|
||||||
requirements[t[0][:-1]] = {'version': t[1], 'operator': '<='}
|
|
||||||
return requirements
|
|
||||||
|
|
||||||
|
|
||||||
def check_requirements(expected, actual):
|
|
||||||
passed_requirements = True
|
|
||||||
for name in expected:
|
|
||||||
if name in actual:
|
|
||||||
version = actual[name]
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
log_msg = "Local version %s of %s does not meet UI requirement for version %s"
|
|
||||||
if expected[name]['operator'] == '==':
|
|
||||||
if not expected[name]['version'] == version:
|
|
||||||
passed_requirements = False
|
|
||||||
log.info(log_msg, version, name, expected[name]['version'])
|
|
||||||
else:
|
|
||||||
log.info("Local version of %s meets ui requirement" % name)
|
|
||||||
if expected[name]['operator'] == '>=':
|
|
||||||
if not expected[name]['version'] <= version:
|
|
||||||
passed_requirements = False
|
|
||||||
log.info(log_msg, version, name, expected[name]['version'])
|
|
||||||
else:
|
|
||||||
log.info("Local version of %s meets ui requirement" % name)
|
|
||||||
if expected[name]['operator'] == '<=':
|
|
||||||
if not expected[name]['version'] >= version:
|
|
||||||
passed_requirements = False
|
|
||||||
log.info(log_msg, version, name, expected[name]['version'])
|
|
||||||
else:
|
|
||||||
log.info("Local version of %s meets ui requirement" % name)
|
|
||||||
return passed_requirements
|
|
|
@ -10,7 +10,7 @@ from twisted.internet.error import ConnectionDone, ConnectionLost
|
||||||
from txjsonrpc import jsonrpclib
|
from txjsonrpc import jsonrpclib
|
||||||
|
|
||||||
from lbrynet import conf
|
from lbrynet import conf
|
||||||
from lbrynet.core.Error import InvalidAuthenticationToken, InvalidHeaderError
|
from lbrynet.core.Error import InvalidAuthenticationToken
|
||||||
from lbrynet.core import utils
|
from lbrynet.core import utils
|
||||||
from lbrynet.lbrynet_daemon.auth.util import APIKey, get_auth_message, jsonrpc_dumps_pretty
|
from lbrynet.lbrynet_daemon.auth.util import APIKey, get_auth_message, jsonrpc_dumps_pretty
|
||||||
from lbrynet.lbrynet_daemon.auth.client import LBRY_SECRET
|
from lbrynet.lbrynet_daemon.auth.client import LBRY_SECRET
|
||||||
|
@ -145,7 +145,7 @@ class AuthJSONRPCServer(AuthorizedBase):
|
||||||
|
|
||||||
def render(self, request):
|
def render(self, request):
|
||||||
time_in = utils.now()
|
time_in = utils.now()
|
||||||
assert self._check_headers(request), InvalidHeaderError
|
# assert self._check_headers(request), InvalidHeaderError
|
||||||
session = request.getSession()
|
session = request.getSession()
|
||||||
session_id = session.uid
|
session_id = session.uid
|
||||||
finished_deferred = request.notifyFinish()
|
finished_deferred = request.notifyFinish()
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
import argparse
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def main(args=None):
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('filename')
|
|
||||||
parser.add_argument('commit')
|
|
||||||
args = parser.parse_args(args)
|
|
||||||
|
|
||||||
with open(args.filename) as f:
|
|
||||||
contents = f.read()
|
|
||||||
|
|
||||||
commit = args.commit[:7]
|
|
||||||
|
|
||||||
new_contents = re.sub(
|
|
||||||
r'^__version__ = [\'"](.*)[\'"]$',
|
|
||||||
r'__version__ = "\1-{}"'.format(commit),
|
|
||||||
contents,
|
|
||||||
flags=re.MULTILINE,
|
|
||||||
)
|
|
||||||
|
|
||||||
with open(args.filename, 'w') as f:
|
|
||||||
f.write(new_contents)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
|
@ -1,25 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
# http://stackoverflow.com/a/246128
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
# adapted from https://www.objc.io/issues/6-build-tools/travis-ci/#add-scripts
|
|
||||||
|
|
||||||
KEYCHAIN_PASSWORD=travis
|
|
||||||
|
|
||||||
# Create a custom keychain
|
|
||||||
security create-keychain -p ${KEYCHAIN_PASSWORD} osx-build.keychain
|
|
||||||
|
|
||||||
# Make the custom keychain default, so xcodebuild will use it for signing
|
|
||||||
security default-keychain -s osx-build.keychain
|
|
||||||
|
|
||||||
# Unlock the keychain
|
|
||||||
security unlock-keychain -p ${KEYCHAIN_PASSWORD} osx-build.keychain
|
|
||||||
|
|
||||||
# Set keychain timeout to 1 hour for long builds
|
|
||||||
# see http://www.egeek.me/2013/02/23/jenkins-and-xcode-user-interaction-is-not-allowed/
|
|
||||||
security set-keychain-settings -t 3600 -l ~/Library/Keychains/osx-build.keychain
|
|
||||||
|
|
||||||
# Add certificates to keychain and allow codesign to access them
|
|
||||||
security import ${DIR}/certs/dist.cer -k ~/Library/Keychains/osx-build.keychain -T /usr/bin/codesign
|
|
||||||
security import ${DIR}/certs/dist.p12 -k ~/Library/Keychains/osx-build.keychain -P $KEY_PASSWORD -T /usr/bin/codesign
|
|
||||||
|
|
2
packaging/osx/certs/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
dist.cer
|
|
||||||
dist.p12
|
|
|
@ -1,30 +0,0 @@
|
||||||
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
|
|
||||||
wHO80TEZVEqyfOeJTST/jA==
|
|
|
@ -1,67 +0,0 @@
|
||||||
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
|
|
||||||
EjIMJeXgdGFW7PEdY/kROQ==
|
|
20
packaging/osx/lbry-osx-app/.gitignore
vendored
|
@ -1,20 +0,0 @@
|
||||||
|
|
||||||
*.pyc
|
|
||||||
|
|
||||||
*.pyo
|
|
||||||
|
|
||||||
*.so
|
|
||||||
|
|
||||||
*.xml
|
|
||||||
|
|
||||||
*.iml
|
|
||||||
|
|
||||||
id.conf
|
|
||||||
|
|
||||||
lbrycrd-cli
|
|
||||||
lbrycrd-osx.zip
|
|
||||||
lbrycrd-tx
|
|
||||||
lbrycrdd
|
|
||||||
|
|
||||||
lbrynet.*.dmg
|
|
||||||
LBRY.app
|
|
Before Width: | Height: | Size: 8.5 KiB |
|
@ -1,11 +0,0 @@
|
||||||
badge_icon = 'app.icns'
|
|
||||||
icon_locations = {
|
|
||||||
'LBRY.app': (115, 164),
|
|
||||||
'Applications': (387, 164)
|
|
||||||
}
|
|
||||||
background='dmg_background.png'
|
|
||||||
default_view='icon-view'
|
|
||||||
symlinks = { 'Applications': '/Applications' }
|
|
||||||
window_rect=((200, 200), (500, 320))
|
|
||||||
files = [ 'LBRY.app' ]
|
|
||||||
icon_size=128
|
|
|
@ -1,60 +0,0 @@
|
||||||
import os
|
|
||||||
import json
|
|
||||||
import webbrowser
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from time import sleep
|
|
||||||
from jsonrpc.proxy import JSONRPCProxy
|
|
||||||
|
|
||||||
API_CONNECTION_STRING = "http://localhost:5279/lbryapi"
|
|
||||||
UI_ADDRESS = "http://localhost:5279"
|
|
||||||
|
|
||||||
|
|
||||||
class LBRYURIHandler(object):
|
|
||||||
def __init__(self):
|
|
||||||
self.started_daemon = False
|
|
||||||
self.daemon = JSONRPCProxy.from_url(API_CONNECTION_STRING)
|
|
||||||
|
|
||||||
def handle_osx(self, lbry_name):
|
|
||||||
try:
|
|
||||||
status = self.daemon.is_running()
|
|
||||||
except:
|
|
||||||
os.system("open /Applications/LBRY.app")
|
|
||||||
sleep(3)
|
|
||||||
|
|
||||||
if lbry_name == "lbry" or lbry_name == "":
|
|
||||||
webbrowser.open(UI_ADDRESS)
|
|
||||||
else:
|
|
||||||
webbrowser.open(UI_ADDRESS + "/?show=" + lbry_name)
|
|
||||||
|
|
||||||
def handle_linux(self, lbry_name):
|
|
||||||
try:
|
|
||||||
status = self.daemon.is_running()
|
|
||||||
except:
|
|
||||||
cmd = r'DIR = "$( cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )"' \
|
|
||||||
r'if [-z "$(pgrep lbrynet-daemon)"]; then' \
|
|
||||||
r'echo "running lbrynet-daemon"' \
|
|
||||||
r'$DIR / lbrynet - daemon &' \
|
|
||||||
r'sleep 3 # let the daemon load before connecting' \
|
|
||||||
r'fi'
|
|
||||||
subprocess.Popen(cmd, shell=True)
|
|
||||||
|
|
||||||
if lbry_name == "lbry" or lbry_name == "":
|
|
||||||
webbrowser.open(UI_ADDRESS)
|
|
||||||
else:
|
|
||||||
webbrowser.open(UI_ADDRESS + "/?show=" + lbry_name)
|
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
|
||||||
if len(args) != 1:
|
|
||||||
args = ['lbry://lbry']
|
|
||||||
|
|
||||||
name = args[0][7:]
|
|
||||||
if sys.platform == "darwin":
|
|
||||||
LBRYURIHandler().handle_osx(lbry_name=name)
|
|
||||||
else:
|
|
||||||
LBRYURIHandler().handle_linux(lbry_name=name)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main(sys.argv[1:])
|
|
|
@ -1,71 +0,0 @@
|
||||||
import AppKit
|
|
||||||
import webbrowser
|
|
||||||
import sys
|
|
||||||
import logging
|
|
||||||
import platform
|
|
||||||
from twisted.internet import reactor
|
|
||||||
|
|
||||||
from lbrynet.lbrynet_daemon import DaemonControl
|
|
||||||
from lbrynet import analytics
|
|
||||||
from lbrynet import conf
|
|
||||||
from lbrynet.core import utils
|
|
||||||
|
|
||||||
|
|
||||||
if platform.mac_ver()[0] >= "10.10":
|
|
||||||
from LBRYNotify import LBRYNotify
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def test_internet_connection():
|
|
||||||
return utils.check_connection()
|
|
||||||
|
|
||||||
|
|
||||||
class LBRYDaemonApp(AppKit.NSApplication):
|
|
||||||
def finishLaunching(self):
|
|
||||||
self.connection = False
|
|
||||||
statusbar = AppKit.NSStatusBar.systemStatusBar()
|
|
||||||
self.statusitem = statusbar.statusItemWithLength_(AppKit.NSVariableStatusItemLength)
|
|
||||||
self.icon = AppKit.NSImage.alloc().initByReferencingFile_(conf.settings['ICON_PATH'])
|
|
||||||
self.icon.setScalesWhenResized_(True)
|
|
||||||
self.icon.setSize_((20, 20))
|
|
||||||
self.statusitem.setImage_(self.icon)
|
|
||||||
self.menubarMenu = AppKit.NSMenu.alloc().init()
|
|
||||||
self.open = AppKit.NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
|
|
||||||
"Open", "openui:", "")
|
|
||||||
self.menubarMenu.addItem_(self.open)
|
|
||||||
self.quit = AppKit.NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
|
|
||||||
"Quit", "applicationShouldTerminate:", "")
|
|
||||||
self.menubarMenu.addItem_(self.quit)
|
|
||||||
self.statusitem.setMenu_(self.menubarMenu)
|
|
||||||
self.statusitem.setToolTip_(conf.settings['APP_NAME'])
|
|
||||||
|
|
||||||
if test_internet_connection():
|
|
||||||
notify("Starting LBRY")
|
|
||||||
else:
|
|
||||||
notify("LBRY needs an internet connection to start, try again when one is available")
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
DaemonControl.start_server_and_listen(
|
|
||||||
launchui=True, use_auth=False,
|
|
||||||
analytics_manager=analytics.Manager.new_instance()
|
|
||||||
)
|
|
||||||
|
|
||||||
def openui_(self, sender):
|
|
||||||
webbrowser.open(conf.settings.get_ui_address())
|
|
||||||
|
|
||||||
# this code is from the example
|
|
||||||
# https://pythonhosted.org/pyobjc/examples/Cocoa/Twisted/WebServicesTool/index.html
|
|
||||||
def applicationShouldTerminate_(self, sender):
|
|
||||||
if reactor.running:
|
|
||||||
log.info('Stopping twisted event loop')
|
|
||||||
notify("Goodbye!")
|
|
||||||
reactor.stop()
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def notify(msg):
|
|
||||||
if platform.mac_ver()[0] >= "10.10":
|
|
||||||
LBRYNotify(msg)
|
|
|
@ -1,31 +0,0 @@
|
||||||
import Foundation
|
|
||||||
import objc
|
|
||||||
|
|
||||||
NSUserNotification = objc.lookUpClass('NSUserNotification')
|
|
||||||
NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter')
|
|
||||||
|
|
||||||
|
|
||||||
def LBRYNotify(message):
|
|
||||||
notification = NSUserNotification.alloc().init()
|
|
||||||
notification.setTitle_("LBRY")
|
|
||||||
notification.setSubtitle_("")
|
|
||||||
notification.setInformativeText_(message)
|
|
||||||
notification.setUserInfo_({})
|
|
||||||
notification.setSoundName_("NSUserNotificationDefaultSoundName")
|
|
||||||
notification.setDeliveryDate_(
|
|
||||||
Foundation.NSDate.dateWithTimeInterval_sinceDate_(0, Foundation.NSDate.date()))
|
|
||||||
NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notification)
|
|
||||||
|
|
||||||
|
|
||||||
def notify(title, subtitle, info_text, delay=0, sound=False, userInfo=None):
|
|
||||||
userInfo = userInfo or {}
|
|
||||||
notification = NSUserNotification.alloc().init()
|
|
||||||
notification.setTitle_(title)
|
|
||||||
notification.setSubtitle_(subtitle)
|
|
||||||
notification.setInformativeText_(info_text)
|
|
||||||
notification.setUserInfo_(userInfo)
|
|
||||||
if sound:
|
|
||||||
notification.setSoundName_("NSUserNotificationDefaultSoundName")
|
|
||||||
notification.setDeliveryDate_(
|
|
||||||
Foundation.NSDate.dateWithTimeInterval_sinceDate_(delay, Foundation.NSDate.date()))
|
|
||||||
NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notification)
|
|
|
@ -1,31 +0,0 @@
|
||||||
from PyObjCTools import AppHelper
|
|
||||||
from twisted.internet.cfreactor import install
|
|
||||||
install(runner=AppHelper.runEventLoop)
|
|
||||||
from twisted.internet import reactor
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from lbrynet import conf
|
|
||||||
from lbrynet.core import log_support
|
|
||||||
from LBRYApp import LBRYDaemonApp
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
conf.initialize_settings()
|
|
||||||
log_file = conf.settings.get_log_filename()
|
|
||||||
log_support.configure_logging(log_file, console=True)
|
|
||||||
app = LBRYDaemonApp.sharedApplication()
|
|
||||||
reactor.addSystemEventTrigger("after", "shutdown", shutdown)
|
|
||||||
reactor.run()
|
|
||||||
|
|
||||||
|
|
||||||
def shutdown():
|
|
||||||
log.info('Stopping event loop')
|
|
||||||
AppHelper.stopEventLoop()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,29 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import os
|
|
||||||
from setuptools import setup
|
|
||||||
from lbrynet import conf
|
|
||||||
|
|
||||||
APP = [os.path.join('lbrygui', 'main.py')]
|
|
||||||
DATA_FILES = []
|
|
||||||
DATA_FILES.append('app.icns')
|
|
||||||
|
|
||||||
OPTIONS = {
|
|
||||||
'iconfile': conf.ICON_PATH,
|
|
||||||
'plist': {
|
|
||||||
'CFBundleIdentifier': 'io.lbry.LBRY',
|
|
||||||
'LSUIElement': True,
|
|
||||||
},
|
|
||||||
'packages': [
|
|
||||||
'lbrynet', 'lbryum', 'requests', 'certifi',
|
|
||||||
'pkg_resources', 'json', 'jsonrpc', 'seccure',
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name=conf.APP_NAME,
|
|
||||||
app=APP,
|
|
||||||
options={'py2app': OPTIONS},
|
|
||||||
data_files=DATA_FILES,
|
|
||||||
)
|
|
|
@ -1,128 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -o errexit
|
|
||||||
set -o xtrace
|
|
||||||
|
|
||||||
DEST=`pwd`
|
|
||||||
tmp="${DEST}/build"
|
|
||||||
ON_TRAVIS=false
|
|
||||||
|
|
||||||
rm -rf build dist LBRY.app
|
|
||||||
|
|
||||||
echo "Updating lbrynet"
|
|
||||||
if [ -z ${TRAVIS_BUILD_DIR+x} ]; then
|
|
||||||
# building locally
|
|
||||||
mkdir -p $tmp
|
|
||||||
cd $tmp
|
|
||||||
git clone --depth 1 http://github.com/lbryio/lbry.git
|
|
||||||
cd lbry
|
|
||||||
LBRY="${tmp}/lbry"
|
|
||||||
else
|
|
||||||
# building on travis
|
|
||||||
ON_TRAVIS=true
|
|
||||||
cd ${TRAVIS_BUILD_DIR}
|
|
||||||
LBRY=${TRAVIS_BUILD_DIR}
|
|
||||||
fi
|
|
||||||
|
|
||||||
pip install wheel
|
|
||||||
MODULES="pyobjc-core==3.1.1 pyobjc-framework-Cocoa==3.1.1 pyobjc-framework-CFNetwork==3.1.1 pyobjc-framework-Quartz==3.1.1"
|
|
||||||
if [ ${ON_TRAVIS} = true ]; then
|
|
||||||
WHEEL_DIR="${TRAVIS_BUILD_DIR}/cache/wheel"
|
|
||||||
mkdir -p "${WHEEL_DIR}"
|
|
||||||
# mapping from the package name to the
|
|
||||||
# actual built wheel file is surprisingly
|
|
||||||
# hard so instead of checking for the existance
|
|
||||||
# of each wheel, we mark with a file when they've all been
|
|
||||||
# built and skip when that file exists
|
|
||||||
for MODULE in ${MODULES}; do
|
|
||||||
if [ ! -f "${WHEEL_DIR}"/${MODULE}.finished ]; then
|
|
||||||
pip wheel -w "${WHEEL_DIR}" ${MODULE}
|
|
||||||
touch "${WHEEL_DIR}"/${MODULE}.finished
|
|
||||||
pip install ${MODULE}
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
pip install $MODULES
|
|
||||||
|
|
||||||
|
|
||||||
pip install dmgbuild==1.1.0
|
|
||||||
export PATH=${PATH}:/Library/Frameworks/Python.framework/Versions/2.7/bin
|
|
||||||
|
|
||||||
# pyopenssl is needed because OSX ships an old version of openssl by default
|
|
||||||
# and python will use it without pyopenssl
|
|
||||||
pip install PyOpenSSL jsonrpc certifi
|
|
||||||
|
|
||||||
NAME=`python setup.py --name`
|
|
||||||
VERSION=`python setup.py -V`
|
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
|
|
||||||
if [ -z ${SKIP_PYLINT+x} ]; then
|
|
||||||
pip install pylint
|
|
||||||
./run_pylint.sh packaging/osx/lbry-osx-app/lbrygui/
|
|
||||||
fi
|
|
||||||
|
|
||||||
python setup.py install
|
|
||||||
|
|
||||||
echo "Building URI Handler"
|
|
||||||
cd "${DEST}"
|
|
||||||
|
|
||||||
|
|
||||||
if [ ! -d "py2app" ]; then
|
|
||||||
hg clone https://bitbucket.org/ronaldoussoren/py2app
|
|
||||||
cd py2app
|
|
||||||
hg checkout py2app-0.10
|
|
||||||
# this commit fixes a bug that should have been fixed as part of 0.10
|
|
||||||
hg graft 149c25c413420120d3f383a9e854a17bc10d96fd
|
|
||||||
pip install .
|
|
||||||
cd ..
|
|
||||||
rm -rf py2app
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
rm -rf build dist
|
|
||||||
python setup_uri_handler.py py2app
|
|
||||||
|
|
||||||
echo "Signing URI Handler"
|
|
||||||
codesign -s "${LBRY_DEVELOPER_ID}" -f "${DEST}/dist/LBRYURIHandler.app/Contents/Frameworks/Python.framework/Versions/2.7"
|
|
||||||
codesign -s "${LBRY_DEVELOPER_ID}" -f "${DEST}/dist/LBRYURIHandler.app/Contents/MacOS/python"
|
|
||||||
# not sure if --deep is appropriate here, but need to get LBRYURIHandler.app/Contents/Frameworks/libcrypto.1.0.0.dylib signed
|
|
||||||
codesign --deep -s "${LBRY_DEVELOPER_ID}" -f "${DEST}/dist/LBRYURIHandler.app/Contents/MacOS/LBRYURIHandler"
|
|
||||||
codesign -vvvv "${DEST}/dist/LBRYURIHandler.app"
|
|
||||||
|
|
||||||
# py2app will skip _cffi_backend without explicitly including it
|
|
||||||
# and without this, we will get SSL handshake errors when connecting
|
|
||||||
# to bittrex
|
|
||||||
python setup_app.py py2app -i _cffi_backend
|
|
||||||
|
|
||||||
echo "Removing i386 libraries"
|
|
||||||
|
|
||||||
remove_arch () {
|
|
||||||
if [[ `lipo "$2" -verify_arch "$1"` ]]; then
|
|
||||||
lipo -output build/lipo.tmp -remove "$1" "$2" && mv build/lipo.tmp "$2"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in `find dist/LBRY.app/Contents/Resources/lib/python2.7/lib-dynload/ -name "*.so"`; do
|
|
||||||
remove_arch i386 $i
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
echo "Moving LBRYURIHandler.app into LBRY.app"
|
|
||||||
mv "${DEST}/dist/LBRYURIHandler.app" "${DEST}/dist/LBRY.app/Contents/Resources"
|
|
||||||
|
|
||||||
echo "Signing LBRY.app"
|
|
||||||
codesign -s "${LBRY_DEVELOPER_ID}" -f "${DEST}/dist/LBRY.app/Contents/Frameworks/Python.framework/Versions/2.7"
|
|
||||||
codesign -s "${LBRY_DEVELOPER_ID}" -f "${DEST}/dist/LBRY.app/Contents/Frameworks/libgmp.10.dylib"
|
|
||||||
codesign -s "${LBRY_DEVELOPER_ID}" -f "${DEST}/dist/LBRY.app/Contents/MacOS/python"
|
|
||||||
# adding deep here as well because of subcomponent issues
|
|
||||||
codesign --deep -s "${LBRY_DEVELOPER_ID}" -f "${DEST}/dist/LBRY.app/Contents/MacOS/LBRY"
|
|
||||||
codesign -vvvv "${DEST}/dist/LBRY.app"
|
|
||||||
|
|
||||||
rm -rf $tmp
|
|
||||||
mv dist/LBRY.app LBRY.app
|
|
||||||
|
|
||||||
if [ -z ${SKIP_DMG+x} ]; then
|
|
||||||
rm -rf dist "${NAME}.${VERSION}.dmg"
|
|
||||||
dmgbuild -s dmg_settings.py "LBRY" "${NAME}.${VERSION}.dmg"
|
|
||||||
fi
|
|
|
@ -1,26 +0,0 @@
|
||||||
from setuptools import setup
|
|
||||||
import os
|
|
||||||
from lbrynet import conf
|
|
||||||
|
|
||||||
APP = [os.path.join('lbry_uri_handler', 'LBRYURIHandler.py')]
|
|
||||||
DATA_FILES = []
|
|
||||||
OPTIONS = {'argv_emulation': True,
|
|
||||||
'packages': ['jsonrpc'],
|
|
||||||
'plist': {
|
|
||||||
'LSUIElement': True,
|
|
||||||
'CFBundleIdentifier': 'io.lbry.LBRYURIHandler',
|
|
||||||
'CFBundleURLTypes': [
|
|
||||||
{
|
|
||||||
'CFBundleURLTypes': 'LBRYURIHandler',
|
|
||||||
'CFBundleURLSchemes': [conf.PROTOCOL_PREFIX]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setup(
|
|
||||||
app=APP,
|
|
||||||
data_files=DATA_FILES,
|
|
||||||
options={'py2app': OPTIONS},
|
|
||||||
setup_requires=['py2app'],
|
|
||||||
)
|
|
|
@ -1,48 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# This script is used by travis to install lbry from source
|
|
||||||
#
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
set -o xtrace
|
|
||||||
|
|
||||||
SUDO=''
|
|
||||||
if (( $EUID != 0 )); then
|
|
||||||
SUDO='sudo'
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z ${TRAVIS+x} ]; then
|
|
||||||
# if not on travis, its nice to see progress
|
|
||||||
QUIET=""
|
|
||||||
else
|
|
||||||
QUIET="-qq"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# get the required OS packages
|
|
||||||
$SUDO apt-get ${QUIET} update
|
|
||||||
$SUDO apt-get ${QUIET} install -y --no-install-recommends \
|
|
||||||
build-essential python-dev libffi-dev libssl-dev git \
|
|
||||||
libgmp3-dev wget ca-certificates python-virtualenv
|
|
||||||
|
|
||||||
# create a virtualenv so we don't muck with anything on the system
|
|
||||||
virtualenv venv
|
|
||||||
# need to unset these or else we can't activate
|
|
||||||
set +eu
|
|
||||||
source venv/bin/activate
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
# need a modern version of pip (more modern than ubuntu default)
|
|
||||||
wget https://bootstrap.pypa.io/get-pip.py
|
|
||||||
python get-pip.py
|
|
||||||
rm get-pip.py
|
|
||||||
|
|
||||||
pip install -r requirements.txt
|
|
||||||
pip install cython
|
|
||||||
pip install unqlite
|
|
||||||
|
|
||||||
pip install mock pylint coveralls
|
|
||||||
# have to do `which trial` instead of simply trial because coverage needs the full path
|
|
||||||
coverage run --source=lbrynet `which trial` tests
|
|
||||||
coveralls
|
|
||||||
|
|
||||||
./run_pylint.sh
|
|
|
@ -1,35 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# Configure build-specific things
|
|
||||||
#
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
set -o xtrace
|
|
||||||
|
|
||||||
# changes to this script also need to be added to build.ps1 for windows
|
|
||||||
add_ui() {
|
|
||||||
wget https://s3.amazonaws.com/lbry-ui/development/dist.zip -O dist.zip
|
|
||||||
unzip -oq dist.zip -d lbrynet/resources/ui
|
|
||||||
wget https://s3.amazonaws.com/lbry-ui/development/data.json -O lbrynet/resources/ui/data.json
|
|
||||||
}
|
|
||||||
|
|
||||||
set_build() {
|
|
||||||
local file="lbrynet/build_type.py"
|
|
||||||
# cannot use 'sed -i' because BSD sed and GNU sed are incompatible
|
|
||||||
sed 's/^\(BUILD = "\)[^"]\+\(".*\)$/\1'"${1}"'\2/' "$file" > tmpbuildfile
|
|
||||||
mv -- tmpbuildfile "$file"
|
|
||||||
}
|
|
||||||
|
|
||||||
IS_RC_REGEX="v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+rc[[:digit:]]+"
|
|
||||||
|
|
||||||
if [[ -z "$TRAVIS_TAG" ]]; then
|
|
||||||
python packaging/append_sha_to_version.py lbrynet/__init__.py "${TRAVIS_COMMIT}"
|
|
||||||
add_ui
|
|
||||||
set_build "qa"
|
|
||||||
elif [[ "$TRAVIS_TAG" =~ $IS_RC_REGEX ]]; then
|
|
||||||
# If the tag looks like v0.7.6rc0 then this is a tagged release candidate.
|
|
||||||
add_ui
|
|
||||||
set_build "rc"
|
|
||||||
else
|
|
||||||
set_build "release"
|
|
||||||
fi
|
|
|
@ -1,25 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
set -o xtrace
|
|
||||||
|
|
||||||
wget https://www.python.org/ftp/python/2.7.11/python-2.7.11-macosx10.6.pkg
|
|
||||||
sudo installer -pkg python-2.7.11-macosx10.6.pkg -target /
|
|
||||||
pip install -U pip
|
|
||||||
brew update
|
|
||||||
|
|
||||||
# follow this pattern to avoid failing if its already
|
|
||||||
# installed by brew:
|
|
||||||
# http://stackoverflow.com/a/20802425
|
|
||||||
if brew ls --versions gmp > /dev/null; then
|
|
||||||
echo 'gmp is already installed by brew'
|
|
||||||
else
|
|
||||||
brew install gmp
|
|
||||||
fi
|
|
||||||
|
|
||||||
if brew ls --versions openssl > /dev/null; then
|
|
||||||
echo 'openssl is already installed by brew'
|
|
||||||
else
|
|
||||||
brew install openssl
|
|
||||||
brew link --force openssl
|
|
||||||
fi
|
|
|
@ -1,5 +0,0 @@
|
||||||
# package scripts
|
|
||||||
|
|
||||||
How to build LBRY packages.
|
|
||||||
|
|
||||||
For best results, run on a fresh image.
|
|
Before Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 6.1 KiB |
|
@ -1,48 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
|
|
||||||
urlencode() {
|
|
||||||
local LANG=C
|
|
||||||
local length="${#1}"
|
|
||||||
for (( i = 0; i < length; i++ )); do
|
|
||||||
local c="${1:i:1}"
|
|
||||||
case $c in
|
|
||||||
[a-zA-Z0-9.~_-]) printf "$c" ;;
|
|
||||||
*) printf '%%%02X' "'$c" ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# find true dir of executable
|
|
||||||
SOURCE="${BASH_SOURCE[0]}"
|
|
||||||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
|
||||||
SOURCE="$(readlink "$SOURCE")"
|
|
||||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
|
||||||
done
|
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
|
||||||
|
|
||||||
|
|
||||||
if [ -z "$(pgrep lbrynet-daemon)" ]; then
|
|
||||||
echo "running lbrynet-daemon"
|
|
||||||
$DIR/lbrynet-daemon &
|
|
||||||
sleep 3 # let the daemon load before connecting
|
|
||||||
fi
|
|
||||||
|
|
||||||
ARG=${1:-}
|
|
||||||
|
|
||||||
if [ -z "$ARG" ]; then
|
|
||||||
URL=""
|
|
||||||
else
|
|
||||||
NAME=$(echo "$ARG" | cut -c 8-)
|
|
||||||
if [ -z "$NAME" -o "$NAME" == "lbry" ]; then
|
|
||||||
URL=""
|
|
||||||
else
|
|
||||||
URL="/?show=$(urlencode "$NAME")"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
/usr/bin/xdg-open "http://localhost:5279$URL"
|
|
|
@ -1,11 +0,0 @@
|
||||||
description "LBRY Daemon"
|
|
||||||
|
|
||||||
#start on (local-filesystems and net-device-up IFACE=eth0)
|
|
||||||
stop on runlevel [016]
|
|
||||||
|
|
||||||
#expect fork
|
|
||||||
|
|
||||||
respawn
|
|
||||||
respawn limit 5 20
|
|
||||||
|
|
||||||
exec /opt/venvs/lbrynet/bin/lbrynet-daemon
|
|
|
@ -1,19 +0,0 @@
|
||||||
[Desktop Entry]
|
|
||||||
Version=0.8.7
|
|
||||||
Name=LBRY
|
|
||||||
Comment=The world's first user-owned content marketplace
|
|
||||||
Icon=lbry
|
|
||||||
GenericName=Content Marketplace
|
|
||||||
Categories=Network;Internet;Filesharing
|
|
||||||
Terminal=false
|
|
||||||
Type=Application
|
|
||||||
|
|
||||||
MimeType=x-scheme-handler/lbry;
|
|
||||||
|
|
||||||
Exec=/usr/bin/lbry %U
|
|
||||||
|
|
||||||
Actions=StopDaemon;
|
|
||||||
|
|
||||||
[Desktop Action StopDaemon]
|
|
||||||
Name=Stop Daemon
|
|
||||||
Exec=/opt/venvs/lbrynet/bin/stop-lbrynet-daemon
|
|
|
@ -1,15 +0,0 @@
|
||||||
|
|
||||||
(
|
|
||||||
|
|
||||||
if hash zenity 2>/dev/null; then
|
|
||||||
sleep 3
|
|
||||||
|
|
||||||
zenity --info --icon-name="system-software-install" \
|
|
||||||
--text="\
|
|
||||||
<span size=\"xx-large\">LBRY Installed</span>\n\nLBRY has been installed.\n\n\
|
|
||||||
Please start LBRY by running <b><tt>lbry</tt></b> from the command line or selecting <b>LBRY</b> from the application menu.\n\n\
|
|
||||||
If you need help or have any questions, join us on Slack (<tt>https://slack.lbry.io</tt>) or email <tt>hello@lbry.io</tt>.\
|
|
||||||
"
|
|
||||||
|
|
||||||
fi
|
|
||||||
) &
|
|
|
@ -1,204 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
function HELP {
|
|
||||||
echo "Build a debian package for lbry"
|
|
||||||
echo "-----"
|
|
||||||
echo "When run without any arguments, this script expects the current directory"
|
|
||||||
echo "to be the main lbry repo and it builds what is in that directory"
|
|
||||||
echo
|
|
||||||
echo "Optional arguments:"
|
|
||||||
echo
|
|
||||||
echo "-c: clone a fresh copy of the repo"
|
|
||||||
echo "-b <branch>: use the specified branch of the lbry repo"
|
|
||||||
echo "-w <web-ui-branch>: set the webui branch"
|
|
||||||
echo "-d <build-dir>: specifiy the build directory"
|
|
||||||
echo "-h: show help"
|
|
||||||
echo "-t: turn trace on"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
CLONE=false
|
|
||||||
BUILD_DIR=""
|
|
||||||
BRANCH=""
|
|
||||||
WEB_UI_BRANCH="master"
|
|
||||||
|
|
||||||
while getopts :hctb:w:d: FLAG; do
|
|
||||||
case $FLAG in
|
|
||||||
c)
|
|
||||||
CLONE=true
|
|
||||||
;;
|
|
||||||
b)
|
|
||||||
BRANCH=${OPTARG}
|
|
||||||
;;
|
|
||||||
w)
|
|
||||||
WEB_UI_BRANCH=${OPTARG}
|
|
||||||
;;
|
|
||||||
d)
|
|
||||||
BUILD_DIR=${OPTARG}
|
|
||||||
;;
|
|
||||||
t)
|
|
||||||
set -o xtrace
|
|
||||||
;;
|
|
||||||
h)
|
|
||||||
HELP
|
|
||||||
;;
|
|
||||||
\?) #unrecognized option - show help
|
|
||||||
echo "Option -$OPTARG not allowed."
|
|
||||||
HELP
|
|
||||||
;;
|
|
||||||
:)
|
|
||||||
echo "Option -$OPTARG requires an argument."
|
|
||||||
HELP
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
shift $((OPTIND-1))
|
|
||||||
|
|
||||||
|
|
||||||
SUDO=''
|
|
||||||
if (( $EUID != 0 )); then
|
|
||||||
SUDO='sudo'
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$CLONE" = false ]; then
|
|
||||||
if [ `basename $PWD` != "lbry" ]; then
|
|
||||||
echo "Not currently in the lbry directory. Cowardly refusing to go forward"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
SOURCE_DIR=$PWD
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${BUILD_DIR}" ]; then
|
|
||||||
if [ "$CLONE" = true ]; then
|
|
||||||
# build in the current directory
|
|
||||||
BUILD_DIR="lbry-build-$(date +%Y%m%d-%H%M%S)"
|
|
||||||
else
|
|
||||||
BUILD_DIR="../lbry-build-$(date +%Y%m%d-%H%M%S)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p "$BUILD_DIR"
|
|
||||||
cd "$BUILD_DIR"
|
|
||||||
|
|
||||||
if [ -z ${TRAVIS+x} ]; then
|
|
||||||
# if not on travis, its nice to see progress
|
|
||||||
QUIET=""
|
|
||||||
else
|
|
||||||
QUIET="-qq"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# get the required OS packages
|
|
||||||
$SUDO apt-get ${QUIET} update
|
|
||||||
$SUDO apt-get ${QUIET} install -y --no-install-recommends software-properties-common
|
|
||||||
$SUDO add-apt-repository -y ppa:spotify-jyrki/dh-virtualenv
|
|
||||||
$SUDO apt-get ${QUIET} update
|
|
||||||
$SUDO apt-get ${QUIET} install -y --no-install-recommends \
|
|
||||||
build-essential git python-dev libffi-dev libssl-dev \
|
|
||||||
libgmp3-dev dh-virtualenv debhelper wget python-pip fakeroot
|
|
||||||
|
|
||||||
# need a modern version of pip (more modern than ubuntu default)
|
|
||||||
$SUDO pip install --upgrade pip
|
|
||||||
$SUDO pip install git+https://github.com/jobevers/make-deb
|
|
||||||
|
|
||||||
# build packages
|
|
||||||
#
|
|
||||||
# dpkg-buildpackage outputs its results into '..' so
|
|
||||||
# we need to move/clone lbry into the build directory
|
|
||||||
if [ "$CLONE" == true ]; then
|
|
||||||
git clone https://github.com/lbryio/lbry.git
|
|
||||||
else
|
|
||||||
cp -a $SOURCE_DIR lbry
|
|
||||||
fi
|
|
||||||
(
|
|
||||||
cd lbry
|
|
||||||
if [ -n "${BRANCH}" ]; then
|
|
||||||
git checkout "${BRANCH}"
|
|
||||||
fi
|
|
||||||
make-deb
|
|
||||||
dpkg-buildpackage -us -uc
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
### insert our extra files
|
|
||||||
|
|
||||||
# extract .deb
|
|
||||||
PACKAGE="$(ls | grep '.deb')"
|
|
||||||
ar vx "$PACKAGE"
|
|
||||||
mkdir control data
|
|
||||||
tar -xzf control.tar.gz --directory control
|
|
||||||
|
|
||||||
# The output of the travis build is a
|
|
||||||
# tar.gz and the output locally is tar.xz.
|
|
||||||
# Instead of having tar detect the compression used, we
|
|
||||||
# could update the config to output the same in either spot.
|
|
||||||
# Unfortunately, doing so requires editting some auto-generated
|
|
||||||
# files: http://linux.spiney.org/forcing_gzip_compression_when_building_debian_packages
|
|
||||||
tar -xf data.tar.?z --directory data
|
|
||||||
|
|
||||||
PACKAGING_DIR='lbry/packaging/ubuntu'
|
|
||||||
|
|
||||||
# set web ui branch
|
|
||||||
sed -i "s/^WEB_UI_BRANCH='[^']\+'/WEB_UI_BRANCH='$WEB_UI_BRANCH'/" "$PACKAGING_DIR/lbry"
|
|
||||||
|
|
||||||
# add files
|
|
||||||
function addfile() {
|
|
||||||
FILE="$1"
|
|
||||||
TARGET="$2"
|
|
||||||
mkdir -p "$(dirname "data/$TARGET")"
|
|
||||||
cp -d "$FILE" "data/$TARGET"
|
|
||||||
echo "$(md5sum "data/$TARGET" | cut -d' ' -f1) $TARGET" >> control/md5sums
|
|
||||||
}
|
|
||||||
|
|
||||||
function addlink() {
|
|
||||||
SRC="$1"
|
|
||||||
TARGET="$2"
|
|
||||||
TMP="$PACKAGING_DIR/lbry-temp-symlink"
|
|
||||||
ln -s "$SRC" "$TMP"
|
|
||||||
addfile "$TMP" "$TARGET"
|
|
||||||
rm "$TMP"
|
|
||||||
}
|
|
||||||
|
|
||||||
# add icons
|
|
||||||
addfile "$PACKAGING_DIR/icons/lbry32.png" usr/share/icons/hicolor/32x32/apps/lbry.png
|
|
||||||
addfile "$PACKAGING_DIR/icons/lbry48.png" usr/share/icons/hicolor/48x48/apps/lbry.png
|
|
||||||
addfile "$PACKAGING_DIR/icons/lbry96.png" usr/share/icons/hicolor/96x96/apps/lbry.png
|
|
||||||
addfile "$PACKAGING_DIR/icons/lbry128.png" usr/share/icons/hicolor/128x128/apps/lbry.png
|
|
||||||
addfile "$PACKAGING_DIR/icons/lbry256.png" usr/share/icons/hicolor/256x256/apps/lbry.png
|
|
||||||
addfile "$PACKAGING_DIR/lbry.desktop" usr/share/applications/lbry.desktop
|
|
||||||
|
|
||||||
# add lbry executable script
|
|
||||||
BINPATH=opt/venvs/lbrynet/bin
|
|
||||||
addfile "$PACKAGING_DIR/lbry" "$BINPATH/lbry"
|
|
||||||
|
|
||||||
# symlink scripts into /usr/bin
|
|
||||||
for script in "lbry" "lbrynet-daemon" "lbrynet-cli" "stop-lbrynet-daemon"; do
|
|
||||||
addlink "/$BINPATH/$script" "usr/bin/$script"
|
|
||||||
done
|
|
||||||
|
|
||||||
# add postinstall script
|
|
||||||
cat "$PACKAGING_DIR/postinst_append" >> control/postinst
|
|
||||||
|
|
||||||
# change package name from lbrynet to lbry
|
|
||||||
sed -i 's/^Package: lbrynet/Package: lbry/' control/control
|
|
||||||
echo "Conflicts: lbrynet (<< 0.3.5)" >> control/control
|
|
||||||
echo "Replaces: lbrynet (<< 0.3.5)" >> control/control
|
|
||||||
|
|
||||||
# repackage .deb
|
|
||||||
$SUDO chown -R root:root control data
|
|
||||||
tar -czf control.tar.gz -C control .
|
|
||||||
tar -cJf data.tar.xz -C data .
|
|
||||||
$SUDO chown root:root debian-binary control.tar.gz data.tar.xz
|
|
||||||
ar r "$PACKAGE" debian-binary control.tar.gz data.tar.xz
|
|
||||||
|
|
||||||
# TODO: we can append to data.tar instead of extracting it all and recompressing
|
|
||||||
|
|
||||||
if [[ ! -z "${TRAVIS_BUILD_DIR+x}" ]]; then
|
|
||||||
# move it to a consistent place so that later it can be uploaded
|
|
||||||
# to the github releases page
|
|
||||||
mv "${PACKAGE}" "${TRAVIS_BUILD_DIR}/${PACKAGE}"
|
|
||||||
# want to be able to check the size of the result in the log
|
|
||||||
ls -l "${TRAVIS_BUILD_DIR}/${PACKAGE}"
|
|
||||||
fi
|
|
|
@ -1,38 +0,0 @@
|
||||||
# this is a port of setup_build.sh used for the unix platforms
|
|
||||||
|
|
||||||
function AddUi {
|
|
||||||
wget https://s3.amazonaws.com/lbry-ui/development/dist.zip -OutFile dist.zip
|
|
||||||
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
|
|
||||||
|
|
||||||
Expand-Archive dist.zip -dest lbrynet\resources\ui
|
|
||||||
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
|
|
||||||
|
|
||||||
wget https://s3.amazonaws.com/lbry-ui/development/data.json -OutFile lbrynet\resources\ui\data.json
|
|
||||||
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
|
|
||||||
}
|
|
||||||
|
|
||||||
function SetBuild([string]$build) {
|
|
||||||
(Get-Content lbrynet\build_type.py).replace('dev', $build) | Set-Content lbrynet\build_type.py
|
|
||||||
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
|
|
||||||
}
|
|
||||||
|
|
||||||
If (${Env:APPVEYOR_REPO_TAG} -NotMatch "true") {
|
|
||||||
C:\Python27\python.exe packaging\append_sha_to_version.py lbrynet\__init__.py ${Env:APPVEYOR_REPO_COMMIT}
|
|
||||||
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
|
|
||||||
|
|
||||||
AddUi
|
|
||||||
SetBuild "qa"
|
|
||||||
}
|
|
||||||
ElseIf (${Env:APPVEYOR_REPO_TAG_NAME} -Match "v\d+\.\d+\.\d+rc\d+") {
|
|
||||||
# If the tag looks like v0.7.6rc0 then this is a tagged release candidate.
|
|
||||||
AddUi
|
|
||||||
SetBuild "rc"
|
|
||||||
}
|
|
||||||
Else {
|
|
||||||
SetBuild "release"
|
|
||||||
}
|
|
||||||
|
|
||||||
C:\Python27\python.exe setup.py build bdist_msi
|
|
||||||
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
|
|
||||||
|
|
||||||
signtool.exe sign /f packaging\windows\certs\lbry2.pfx /p %key_pass% /tr http://tsa.starfieldtech.com /td SHA256 /fd SHA256 dist\*.msi
|
|
|
@ -1,100 +0,0 @@
|
||||||
$env:Path += ";C:\MinGW\bin\"
|
|
||||||
|
|
||||||
$env:Path += ";C:\Program Files (x86)\Windows Kits\10\bin\x86\"
|
|
||||||
|
|
||||||
gcc --version
|
|
||||||
|
|
||||||
mingw32-make --version
|
|
||||||
|
|
||||||
mkdir C:\temp
|
|
||||||
|
|
||||||
Invoke-WebRequest "https://pypi.python.org/packages/55/90/e987e28ed29b571f315afea7d317b6bf4a551e37386b344190cffec60e72/miniupnpc-1.9.tar.gz" -OutFile "C:\temp\miniupnpc-1.9.tar.gz"
|
|
||||||
|
|
||||||
cd C:\temp
|
|
||||||
|
|
||||||
7z e miniupnpc-1.9.tar.gz
|
|
||||||
|
|
||||||
7z x miniupnpc-1.9.tar
|
|
||||||
|
|
||||||
cd C:\temp\miniupnpc-1.9
|
|
||||||
|
|
||||||
mingw32-make.exe -f Makefile.mingw
|
|
||||||
|
|
||||||
C:\Python27\python.exe C:\temp\miniupnpc-1.9\setupmingw32.py build --compiler=mingw32
|
|
||||||
|
|
||||||
C:\Python27\python.exe C:\temp\miniupnpc-1.9\setupmingw32.py install
|
|
||||||
|
|
||||||
Invoke-WebRequest "https://github.com/lbryio/lbry/raw/master/packaging/windows/libs/gmpy-1.17-cp27-none-win32.whl" -OutFile "C:\temp\gmpy-1.17-cp27-none-win32.whl"
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install "C:\temp\gmpy-1.17-cp27-none-win32.whl"
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install pypiwin32==219
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install six==1.9.0
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install requests==2.9.1
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install zope.interface==4.1.3
|
|
||||||
|
|
||||||
# this is a patched to allow version numbers with non-integer values
|
|
||||||
# and it is branched off of 4.3.3
|
|
||||||
C:\Python27\Scripts\pip.exe install https://bitbucket.org/jobevers/cx_freeze/get/handle-version.tar.gz
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install cython==0.24.1
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install Twisted==16.0.0
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install Yapsy==1.11.223
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install appdirs==1.4.0
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install argparse==1.2.1
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install colorama==0.3.7
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install dnspython==1.12.0
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install ecdsa==0.13
|
|
||||||
C:\Python27\Scripts\pip.exe install envparse==0.2.0
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install jsonrpc==1.2
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install jsonrpclib==0.1.7
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install loggly-python-handler==1.0.0
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install pbkdf2==1.3
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install protobuf==3.0.0
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install pycrypto==2.6.1
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install python-bitcoinrpc==0.1
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install pyyaml==3.12
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install qrcode==5.2.2
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install requests_futures==0.9.7
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install seccure==0.3.1.3
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install simplejson==3.8.2
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install slowaes==0.1a1
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install txJSON-RPC==0.5
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install unqlite==0.5.3
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install wsgiref==0.1.2
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install base58==0.2.2
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install googlefinance==0.7
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install jsonschema==2.5.1
|
|
||||||
|
|
||||||
C:\Python27\Scripts\pip.exe install git+https://github.com/lbryio/lbryum.git
|
|
||||||
|
|
||||||
cd C:\projects\lbry
|
|
|
@ -1,15 +0,0 @@
|
||||||
C:\Python27\python.exe setup.py install
|
|
||||||
|
|
||||||
# If this is a build because of a tag, make sure that
|
|
||||||
# its either a testing tag or a tag that matches the version
|
|
||||||
# specified in the source code.
|
|
||||||
If (${Env:APPVEYOR_REPO_TAG} -Match "true") {
|
|
||||||
If (${Env:APPVEYOR_REPO_TAG_NAME} -Like "test*") {
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
# non-testing tags should be in the form v1.2.3
|
|
||||||
If ("v$(C:\Python27\python.exe setup.py -V)" -Match ${Env:APPVEYOR_REPO_TAG_NAME}) {
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
exit 1
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
Windows Registry Editor Version 5.00
|
|
||||||
|
|
||||||
[HKEY_CLASSES_ROOT\lbry]
|
|
||||||
@="URL:LBRY Protocol"
|
|
||||||
"URL Protocol"=""
|
|
||||||
|
|
||||||
[HKEY_CLASSES_ROOT\lbry\DefaultIcon]
|
|
||||||
@="\"LBRY.exe,1\""
|
|
||||||
|
|
||||||
[HKEY_CLASSES_ROOT\lbry\shell]
|
|
||||||
|
|
||||||
[HKEY_CLASSES_ROOT\lbry\shell\open]
|
|
||||||
|
|
||||||
[HKEY_CLASSES_ROOT\lbry\shell\open\command]
|
|
||||||
@="\"C:\\Program Files (x86)\\LBRY\\LBRY.exe\" \"%1\""
|
|
|
@ -1,302 +0,0 @@
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import threading
|
|
||||||
import webbrowser
|
|
||||||
|
|
||||||
import win32api
|
|
||||||
import win32con
|
|
||||||
import win32gui_struct
|
|
||||||
from jsonrpc.proxy import JSONRPCProxy
|
|
||||||
from twisted.internet import reactor, error
|
|
||||||
|
|
||||||
try:
|
|
||||||
import winxpgui as win32gui
|
|
||||||
except ImportError:
|
|
||||||
import win32gui
|
|
||||||
|
|
||||||
from lbrynet import conf, analytics
|
|
||||||
from lbrynet.core import log_support
|
|
||||||
from lbrynet.core import utils
|
|
||||||
from lbrynet.lbrynet_daemon import DaemonControl
|
|
||||||
from lbrynet import conf
|
|
||||||
from uri_handler.LBRYURIHandler import LBRYURIHandler
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def test_internet_connection():
|
|
||||||
return utils.check_connection()
|
|
||||||
|
|
||||||
|
|
||||||
def non_string_iterable(obj):
|
|
||||||
try:
|
|
||||||
iter(obj)
|
|
||||||
except TypeError:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return not isinstance(obj, basestring)
|
|
||||||
|
|
||||||
|
|
||||||
class SysTrayIcon(object):
|
|
||||||
"""TODO"""
|
|
||||||
QUIT = 'QUIT'
|
|
||||||
SPECIAL_ACTIONS = [QUIT]
|
|
||||||
|
|
||||||
FIRST_ID = 1023
|
|
||||||
|
|
||||||
def __init__(self,
|
|
||||||
icon,
|
|
||||||
hover_text,
|
|
||||||
menu_options,
|
|
||||||
on_quit=None,
|
|
||||||
default_menu_index=None,
|
|
||||||
window_class_name=None, ):
|
|
||||||
|
|
||||||
self.icon = icon
|
|
||||||
self.hover_text = hover_text
|
|
||||||
self.on_quit = on_quit
|
|
||||||
|
|
||||||
menu_options = menu_options + (('Quit', None, self.QUIT),)
|
|
||||||
self._next_action_id = self.FIRST_ID
|
|
||||||
self.menu_actions_by_id = set()
|
|
||||||
self.menu_options = self._add_ids_to_menu_options(list(menu_options))
|
|
||||||
self.menu_actions_by_id = dict(self.menu_actions_by_id)
|
|
||||||
del self._next_action_id
|
|
||||||
|
|
||||||
self.default_menu_index = (default_menu_index or 0)
|
|
||||||
self.window_class_name = window_class_name or "SysTrayIconPy"
|
|
||||||
|
|
||||||
message_map = {win32gui.RegisterWindowMessage("TaskbarCreated"): self.restart,
|
|
||||||
win32con.WM_DESTROY: self.destroy,
|
|
||||||
win32con.WM_COMMAND: self.command,
|
|
||||||
win32con.WM_USER + 20: self.notify,}
|
|
||||||
# Register the Window class.
|
|
||||||
window_class = win32gui.WNDCLASS()
|
|
||||||
hinst = window_class.hInstance = win32gui.GetModuleHandle(None)
|
|
||||||
window_class.lpszClassName = self.window_class_name
|
|
||||||
window_class.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW;
|
|
||||||
window_class.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW)
|
|
||||||
window_class.hbrBackground = win32con.COLOR_WINDOW
|
|
||||||
window_class.lpfnWndProc = message_map # could also specify a wndproc.
|
|
||||||
classAtom = win32gui.RegisterClass(window_class)
|
|
||||||
# Create the Window.
|
|
||||||
style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
|
|
||||||
self.hwnd = win32gui.CreateWindow(classAtom,
|
|
||||||
self.window_class_name,
|
|
||||||
style,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
win32con.CW_USEDEFAULT,
|
|
||||||
win32con.CW_USEDEFAULT,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
hinst,
|
|
||||||
None)
|
|
||||||
win32gui.UpdateWindow(self.hwnd)
|
|
||||||
self.notify_id = None
|
|
||||||
self.refresh_icon()
|
|
||||||
|
|
||||||
win32gui.PumpMessages()
|
|
||||||
|
|
||||||
def _add_ids_to_menu_options(self, menu_options):
|
|
||||||
result = []
|
|
||||||
for menu_option in menu_options:
|
|
||||||
option_text, option_icon, option_action = menu_option
|
|
||||||
if callable(option_action) or option_action in self.SPECIAL_ACTIONS:
|
|
||||||
self.menu_actions_by_id.add((self._next_action_id, option_action))
|
|
||||||
result.append(menu_option + (self._next_action_id,))
|
|
||||||
elif non_string_iterable(option_action):
|
|
||||||
result.append((option_text,
|
|
||||||
option_icon,
|
|
||||||
self._add_ids_to_menu_options(option_action),
|
|
||||||
self._next_action_id))
|
|
||||||
else:
|
|
||||||
print 'Unknown item', option_text, option_icon, option_action
|
|
||||||
self._next_action_id += 1
|
|
||||||
return result
|
|
||||||
|
|
||||||
def refresh_icon(self):
|
|
||||||
# Try and find a custom icon
|
|
||||||
hinst = win32gui.GetModuleHandle(None)
|
|
||||||
if os.path.isfile(self.icon):
|
|
||||||
icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE
|
|
||||||
hicon = win32gui.LoadImage(hinst,
|
|
||||||
self.icon,
|
|
||||||
win32con.IMAGE_ICON,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
icon_flags)
|
|
||||||
else:
|
|
||||||
print "Can't find icon file - using default."
|
|
||||||
hicon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION)
|
|
||||||
|
|
||||||
if self.notify_id:
|
|
||||||
message = win32gui.NIM_MODIFY
|
|
||||||
else:
|
|
||||||
message = win32gui.NIM_ADD
|
|
||||||
self.notify_id = (self.hwnd,
|
|
||||||
0,
|
|
||||||
win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP,
|
|
||||||
win32con.WM_USER + 20,
|
|
||||||
hicon,
|
|
||||||
self.hover_text)
|
|
||||||
win32gui.Shell_NotifyIcon(message, self.notify_id)
|
|
||||||
|
|
||||||
def restart(self, hwnd, msg, wparam, lparam):
|
|
||||||
self.refresh_icon()
|
|
||||||
|
|
||||||
def destroy(self, hwnd, msg, wparam, lparam):
|
|
||||||
if self.on_quit: self.on_quit(self)
|
|
||||||
nid = (self.hwnd, 0)
|
|
||||||
win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid)
|
|
||||||
win32gui.PostQuitMessage(0) # Terminate the app.
|
|
||||||
|
|
||||||
def notify(self, hwnd, msg, wparam, lparam):
|
|
||||||
if lparam == win32con.WM_LBUTTONDBLCLK:
|
|
||||||
self.execute_menu_option(self.default_menu_index + self.FIRST_ID)
|
|
||||||
elif lparam == win32con.WM_RBUTTONUP:
|
|
||||||
self.show_menu()
|
|
||||||
elif lparam == win32con.WM_LBUTTONUP:
|
|
||||||
pass
|
|
||||||
return True
|
|
||||||
|
|
||||||
def show_menu(self):
|
|
||||||
menu = win32gui.CreatePopupMenu()
|
|
||||||
self.create_menu(menu, self.menu_options)
|
|
||||||
|
|
||||||
pos = win32gui.GetCursorPos()
|
|
||||||
# See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/menus_0hdi.asp
|
|
||||||
win32gui.SetForegroundWindow(self.hwnd)
|
|
||||||
win32gui.TrackPopupMenu(menu,
|
|
||||||
win32con.TPM_LEFTALIGN,
|
|
||||||
pos[0],
|
|
||||||
pos[1],
|
|
||||||
0,
|
|
||||||
self.hwnd,
|
|
||||||
None)
|
|
||||||
win32gui.PostMessage(self.hwnd, win32con.WM_NULL, 0, 0)
|
|
||||||
|
|
||||||
def create_menu(self, menu, menu_options):
|
|
||||||
for option_text, option_icon, option_action, option_id in menu_options[::-1]:
|
|
||||||
if option_icon:
|
|
||||||
option_icon = self.prep_menu_icon(option_icon)
|
|
||||||
|
|
||||||
if option_id in self.menu_actions_by_id:
|
|
||||||
item, extras = win32gui_struct.PackMENUITEMINFO(text=option_text,
|
|
||||||
hbmpItem=option_icon,
|
|
||||||
wID=option_id)
|
|
||||||
win32gui.InsertMenuItem(menu, 0, 1, item)
|
|
||||||
else:
|
|
||||||
submenu = win32gui.CreatePopupMenu()
|
|
||||||
self.create_menu(submenu, option_action)
|
|
||||||
item, extras = win32gui_struct.PackMENUITEMINFO(text=option_text,
|
|
||||||
hbmpItem=option_icon,
|
|
||||||
hSubMenu=submenu)
|
|
||||||
win32gui.InsertMenuItem(menu, 0, 1, item)
|
|
||||||
|
|
||||||
def prep_menu_icon(self, icon):
|
|
||||||
# First load the icon.
|
|
||||||
ico_x = win32api.GetSystemMetrics(win32con.SM_CXSMICON)
|
|
||||||
ico_y = win32api.GetSystemMetrics(win32con.SM_CYSMICON)
|
|
||||||
hicon = win32gui.LoadImage(
|
|
||||||
0, icon, win32con.IMAGE_ICON, ico_x, ico_y, win32con.LR_LOADFROMFILE)
|
|
||||||
|
|
||||||
hdcBitmap = win32gui.CreateCompatibleDC(0)
|
|
||||||
hdcScreen = win32gui.GetDC(0)
|
|
||||||
hbm = win32gui.CreateCompatibleBitmap(hdcScreen, ico_x, ico_y)
|
|
||||||
hbmOld = win32gui.SelectObject(hdcBitmap, hbm)
|
|
||||||
# Fill the background.
|
|
||||||
brush = win32gui.GetSysColorBrush(win32con.COLOR_MENU)
|
|
||||||
win32gui.FillRect(hdcBitmap, (0, 0, 16, 16), brush)
|
|
||||||
# unclear if brush needs to be feed. Best clue I can find is:
|
|
||||||
# "GetSysColorBrush returns a cached brush instead of allocating a new
|
|
||||||
# one." - implies no DeleteObject
|
|
||||||
# draw the icon
|
|
||||||
win32gui.DrawIconEx(hdcBitmap, 0, 0, hicon, ico_x, ico_y, 0, 0, win32con.DI_NORMAL)
|
|
||||||
win32gui.SelectObject(hdcBitmap, hbmOld)
|
|
||||||
win32gui.DeleteDC(hdcBitmap)
|
|
||||||
|
|
||||||
return hbm
|
|
||||||
|
|
||||||
def command(self, hwnd, msg, wparam, lparam):
|
|
||||||
id = win32gui.LOWORD(wparam)
|
|
||||||
self.execute_menu_option(id)
|
|
||||||
|
|
||||||
def execute_menu_option(self, id):
|
|
||||||
menu_action = self.menu_actions_by_id[id]
|
|
||||||
if menu_action == self.QUIT:
|
|
||||||
self.exit_app()
|
|
||||||
else:
|
|
||||||
menu_action(self)
|
|
||||||
|
|
||||||
def exit_app(self):
|
|
||||||
win32gui.DestroyWindow(self.hwnd)
|
|
||||||
|
|
||||||
|
|
||||||
def main(lbry_name=None):
|
|
||||||
def LBRYApp():
|
|
||||||
return SysTrayIcon(icon, hover_text, menu_options, on_quit=stop)
|
|
||||||
|
|
||||||
def openui_(sender):
|
|
||||||
webbrowser.open(conf.settings.get_ui_address())
|
|
||||||
|
|
||||||
def replyToApplicationShouldTerminate_():
|
|
||||||
try:
|
|
||||||
reactor.stop()
|
|
||||||
except error.ReactorNotRunning:
|
|
||||||
log.debug('Reactor already stopped')
|
|
||||||
|
|
||||||
def stop(sysTrayIcon):
|
|
||||||
replyToApplicationShouldTerminate_()
|
|
||||||
|
|
||||||
if getattr(sys, 'frozen', False) and os.name == "nt":
|
|
||||||
icon = os.path.join(
|
|
||||||
os.path.dirname(sys.executable), conf.settings['ICON_PATH'], 'lbry16.ico'
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
icon = os.path.join(conf.settings['ICON_PATH'], 'lbry16.ico')
|
|
||||||
|
|
||||||
hover_text = conf.settings['APP_NAME']
|
|
||||||
menu_options = (('Open', icon, openui_),)
|
|
||||||
|
|
||||||
if not test_internet_connection():
|
|
||||||
log.warn('No Internet Connection')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
systray_thread = threading.Thread(target=LBRYApp)
|
|
||||||
systray_thread.daemon = True
|
|
||||||
systray_thread.start()
|
|
||||||
|
|
||||||
DaemonControl.start_server_and_listen(
|
|
||||||
launchui=True, use_auth=False,
|
|
||||||
analytics_manager=analytics.Manager.new_instance()
|
|
||||||
)
|
|
||||||
reactor.run()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
utils.setup_certs_for_windows()
|
|
||||||
conf.initialize_settings()
|
|
||||||
|
|
||||||
log_file = conf.settings.get_log_filename()
|
|
||||||
log_support.configure_logging(log_file, console=True)
|
|
||||||
|
|
||||||
lbry_daemon = JSONRPCProxy.from_url(conf.settings.get_api_connection_string())
|
|
||||||
|
|
||||||
try:
|
|
||||||
daemon_running = lbry_daemon.is_running()
|
|
||||||
start_daemon = False
|
|
||||||
except:
|
|
||||||
start_daemon = True
|
|
||||||
|
|
||||||
try:
|
|
||||||
lbry_name = LBRYURIHandler.parse_name(sys.argv[1])
|
|
||||||
except IndexError:
|
|
||||||
lbry_name = None
|
|
||||||
start_daemon = True
|
|
||||||
if start_daemon:
|
|
||||||
main(lbry_name)
|
|
||||||
else:
|
|
||||||
LBRYURIHandler.open_address(lbry_name)
|
|
Before Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 361 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 31 KiB |
|
@ -1,6 +0,0 @@
|
||||||
C:\Python27\Scripts\pip.exe install mock
|
|
||||||
C:\Python27\Scripts\pip.exe install pylint
|
|
||||||
C:\Python27\python.exe C:\Python27\Scripts\trial.py C:\projects\lbry\tests\unit
|
|
||||||
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
|
|
||||||
C:\Python27\Scripts\pylint.exe -E --disable=inherit-non-class --disable=no-member --ignored-modules=distutils --enable=unused-import --enable=bad-whitespace --enable=line-too-long lbrynet packaging/windows/lbry-win32-app/LBRYWin32App.py
|
|
||||||
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
|
|
|
@ -1,5 +1,4 @@
|
||||||
Twisted==16.0.0
|
Twisted==16.6.0
|
||||||
Yapsy==1.11.223
|
|
||||||
appdirs==1.4.0
|
appdirs==1.4.0
|
||||||
argparse==1.2.1
|
argparse==1.2.1
|
||||||
colorama==0.3.7
|
colorama==0.3.7
|
||||||
|
@ -10,7 +9,6 @@ gmpy==1.17
|
||||||
jsonrpc==1.2
|
jsonrpc==1.2
|
||||||
jsonrpclib==0.1.7
|
jsonrpclib==0.1.7
|
||||||
jsonschema==2.5.1
|
jsonschema==2.5.1
|
||||||
https://github.com/lbryio/lbryum/tarball/master/#egg=lbryum
|
|
||||||
loggly-python-handler==1.0.0
|
loggly-python-handler==1.0.0
|
||||||
miniupnpc==1.9
|
miniupnpc==1.9
|
||||||
pbkdf2==1.3
|
pbkdf2==1.3
|
||||||
|
@ -25,7 +23,7 @@ six>=1.9.0
|
||||||
slowaes==0.1a1
|
slowaes==0.1a1
|
||||||
txJSON-RPC==0.5
|
txJSON-RPC==0.5
|
||||||
wsgiref==0.1.2
|
wsgiref==0.1.2
|
||||||
zope.interface==4.1.3
|
zope.interface==4.3.3
|
||||||
base58==0.2.2
|
base58==0.2.2
|
||||||
googlefinance==0.7
|
googlefinance==0.7
|
||||||
pyyaml==3.12
|
pyyaml==3.12
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
# Ignoring distutils because: https://github.com/PyCQA/pylint/issues/73
|
# Ignoring distutils because: https://github.com/PyCQA/pylint/issues/73
|
||||||
# TODO: as code quality improves, make pylint be more strict
|
# TODO: as code quality improves, make pylint be more strict
|
||||||
|
|
362
setup.py
|
@ -5,18 +5,6 @@ import os
|
||||||
import site
|
import site
|
||||||
from lbrynet import __version__
|
from lbrynet import __version__
|
||||||
|
|
||||||
LINUX = 1
|
|
||||||
DARWIN = 2
|
|
||||||
WINDOWS = 3
|
|
||||||
|
|
||||||
if sys.platform.startswith("linux"):
|
|
||||||
platform = LINUX
|
|
||||||
elif sys.platform.startswith("darwin"):
|
|
||||||
platform = DARWIN
|
|
||||||
elif sys.platform.startswith("win"):
|
|
||||||
platform = WINDOWS
|
|
||||||
else:
|
|
||||||
raise Exception("Unknown os: %s" % sys.platform)
|
|
||||||
|
|
||||||
base_dir = os.path.abspath(os.path.dirname(__file__))
|
base_dir = os.path.abspath(os.path.dirname(__file__))
|
||||||
package_name = "lbrynet"
|
package_name = "lbrynet"
|
||||||
|
@ -31,39 +19,38 @@ keywords = "LBRY"
|
||||||
|
|
||||||
# TODO: find a way to keep this in sync with requirements.txt
|
# TODO: find a way to keep this in sync with requirements.txt
|
||||||
requires = [
|
requires = [
|
||||||
'Twisted==16.0.0',
|
'Twisted',
|
||||||
'Yapsy==1.11.223',
|
'appdirs',
|
||||||
'appdirs==1.4.0',
|
'argparse',
|
||||||
'argparse==1.2.1',
|
'colorama',
|
||||||
'colorama==0.3.7',
|
'dnspython',
|
||||||
'dnspython==1.12.0',
|
'ecdsa',
|
||||||
'ecdsa==0.13',
|
'envparse',
|
||||||
'envparse==0.2.0',
|
'gmpy',
|
||||||
'gmpy==1.17',
|
'jsonrpc',
|
||||||
'jsonrpc==1.2',
|
'jsonrpclib',
|
||||||
'jsonrpclib==0.1.7',
|
'jsonschema',
|
||||||
'jsonschema==2.5.1',
|
'lbryum',
|
||||||
'lbryum>=2.7.5',
|
'loggly-python-handler',
|
||||||
'loggly-python-handler==1.0.0',
|
'miniupnpc',
|
||||||
'miniupnpc==1.9',
|
'pbkdf2',
|
||||||
'pbkdf2==1.3',
|
'protobuf',
|
||||||
'protobuf==3.0.0',
|
'pycrypto',
|
||||||
'pycrypto==2.6.1',
|
'qrcode',
|
||||||
'qrcode==5.2.2',
|
'requests',
|
||||||
'requests==2.9.1',
|
'requests_futures',
|
||||||
'requests_futures==0.9.7',
|
'seccure',
|
||||||
'seccure==0.3.1.3',
|
'simplejson',
|
||||||
'simplejson==3.8.2',
|
'six',
|
||||||
'six>=1.9.0',
|
'slowaes',
|
||||||
'slowaes==0.1a1',
|
'txJSON-RPC',
|
||||||
'txJSON-RPC==0.5',
|
'wsgiref',
|
||||||
'wsgiref==0.1.2',
|
'zope.interface',
|
||||||
'zope.interface==4.1.3',
|
'base58',
|
||||||
'base58==0.2.2',
|
'googlefinance',
|
||||||
'googlefinance==0.7',
|
'pyyaml',
|
||||||
'pyyaml==3.12',
|
'service_identity',
|
||||||
'service_identity==16.0.0',
|
'ndg-httpsclient',
|
||||||
'ndg-httpsclient==0.4.2',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,273 +67,22 @@ def package_files(directory):
|
||||||
yield os.path.join('..', path, filename)
|
yield os.path.join('..', path, filename)
|
||||||
|
|
||||||
|
|
||||||
if platform == LINUX:
|
from setuptools import setup, find_packages
|
||||||
import ez_setup
|
|
||||||
ez_setup.use_setuptools()
|
|
||||||
from setuptools import setup, find_packages
|
|
||||||
|
|
||||||
requires.append('service-identity')
|
|
||||||
|
|
||||||
setup(name=package_name,
|
setup(name=package_name,
|
||||||
description=description,
|
description=description,
|
||||||
version=__version__,
|
version=__version__,
|
||||||
maintainer=maintainer,
|
maintainer=maintainer,
|
||||||
maintainer_email=maintainer_email,
|
maintainer_email=maintainer_email,
|
||||||
url=url,
|
url=url,
|
||||||
author=author,
|
author=author,
|
||||||
keywords=keywords,
|
keywords=keywords,
|
||||||
packages=find_packages(base_dir),
|
packages=find_packages(base_dir),
|
||||||
install_requires=requires,
|
install_requires=requires,
|
||||||
entry_points={'console_scripts': console_scripts},
|
entry_points={'console_scripts': console_scripts},
|
||||||
package_data={
|
package_data={
|
||||||
package_name: list(package_files('lbrynet/resources/ui'))
|
package_name: list(package_files('lbrynet/resources/ui'))
|
||||||
}
|
},
|
||||||
)
|
zip_safe=False,
|
||||||
|
)
|
||||||
elif platform == DARWIN:
|
|
||||||
import ez_setup
|
|
||||||
|
|
||||||
ez_setup.use_setuptools()
|
|
||||||
from setuptools import setup, find_packages
|
|
||||||
|
|
||||||
setup(name=package_name,
|
|
||||||
description=description,
|
|
||||||
version=__version__,
|
|
||||||
maintainer=maintainer,
|
|
||||||
maintainer_email=maintainer_email,
|
|
||||||
url=url,
|
|
||||||
author=author,
|
|
||||||
keywords=keywords,
|
|
||||||
packages=find_packages(base_dir),
|
|
||||||
install_requires=requires,
|
|
||||||
entry_points={'console_scripts': console_scripts},
|
|
||||||
package_data={
|
|
||||||
package_name: list(package_files('lbrynet/resources/ui'))
|
|
||||||
},
|
|
||||||
# If this is True, setuptools tries to build an egg
|
|
||||||
# and py2app / modulegraph / imp.find_module
|
|
||||||
# doesn't like that.
|
|
||||||
zip_safe=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
elif platform == WINDOWS:
|
|
||||||
import opcode
|
|
||||||
import pkg_resources
|
|
||||||
from cx_Freeze import setup, Executable
|
|
||||||
import requests.certs
|
|
||||||
|
|
||||||
app_dir = os.path.join('packaging', 'windows', 'lbry-win32-app')
|
|
||||||
daemon_dir = os.path.join('lbrynet', 'lbrynet_daemon')
|
|
||||||
win_icon = os.path.join(app_dir, 'icons', 'lbry256.ico')
|
|
||||||
wordlist_path = pkg_resources.resource_filename('lbryum', 'wordlist')
|
|
||||||
|
|
||||||
# Allow virtualenv to find distutils of base python installation
|
|
||||||
distutils_path = os.path.join(os.path.dirname(opcode.__file__), 'distutils')
|
|
||||||
|
|
||||||
schemas = os.path.join(site.getsitepackages()[1], "jsonschema", "schemas")
|
|
||||||
onlyfiles = [f for f in os.listdir(schemas) if os.path.isfile(os.path.join(schemas, f))]
|
|
||||||
zipincludes = [(os.path.join(schemas, f), os.path.join("jsonschema", "schemas", f)) for f in onlyfiles]
|
|
||||||
|
|
||||||
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 = [
|
|
||||||
('LBRYShortcut', # Shortcut
|
|
||||||
'DesktopFolder', # Directory
|
|
||||||
'LBRY', # Name
|
|
||||||
'TARGETDIR', # Component
|
|
||||||
'[TARGETDIR]\{0}.exe'.format(dist_name), # Target
|
|
||||||
None, # Arguments
|
|
||||||
description, # Description
|
|
||||||
None, # Hotkey
|
|
||||||
None, # Icon
|
|
||||||
None, # IconIndex
|
|
||||||
None, # ShowCmd
|
|
||||||
'TARGETDIR', # WkDir
|
|
||||||
),
|
|
||||||
# ('DaemonShortcut', # Shortcut
|
|
||||||
# 'DesktopFolder', # Directory
|
|
||||||
# 'lbrynet-daemon', # Name
|
|
||||||
# 'TARGETDIR', # Component
|
|
||||||
# '[TARGETDIR]\lbrynet-daemon.exe', # Target
|
|
||||||
# '--log-to-console', # Arguments
|
|
||||||
# description, # Description
|
|
||||||
# None, # Hotkey
|
|
||||||
# None, # Icon
|
|
||||||
# None, # IconIndex
|
|
||||||
# None, # ShowCmd
|
|
||||||
# 'TARGETDIR', # WkDir
|
|
||||||
# ),
|
|
||||||
# ('DaemonCLIShortcut', # Shortcut
|
|
||||||
# 'DesktopFolder', # Directory
|
|
||||||
# 'lbrynet-cli', # Name
|
|
||||||
# 'TARGETDIR', # Component
|
|
||||||
# '[TARGETDIR]\lbrynet-cli.exe', # Target
|
|
||||||
# None, # Arguments
|
|
||||||
# description, # Description
|
|
||||||
# None, # Hotkey
|
|
||||||
# None, # Icon
|
|
||||||
# None, # IconIndex
|
|
||||||
# None, # ShowCmd
|
|
||||||
# 'TARGETDIR', # WkDir
|
|
||||||
# ),
|
|
||||||
('ProgramMenuLBRYShortcut', # Shortcut
|
|
||||||
'ProgramMenuFolder', # Directory
|
|
||||||
# r'[ProgramMenuFolder]\lbrynet', # Directory
|
|
||||||
'LBRY', # Name
|
|
||||||
'TARGETDIR', # Component
|
|
||||||
'[TARGETDIR]\{0}.exe'.format(dist_name), # Target
|
|
||||||
None, # Arguments
|
|
||||||
description, # Description
|
|
||||||
None, # Hotkey
|
|
||||||
None, # Icon
|
|
||||||
None, # IconIndex
|
|
||||||
None, # ShowCmd
|
|
||||||
'TARGETDIR', # WkDir
|
|
||||||
),
|
|
||||||
('ProgramMenuDaemonShortcut', # Shortcut
|
|
||||||
'ProgramMenuFolder', # Directory
|
|
||||||
# r'[ProgramMenuFolder]\lbrynet', # Directory
|
|
||||||
'lbrynet-daemon', # Name
|
|
||||||
'TARGETDIR', # Component
|
|
||||||
'[TARGETDIR]\lbrynet-daemon.exe', # Target
|
|
||||||
'--log-to-console', # Arguments
|
|
||||||
description, # Description
|
|
||||||
None, # Hotkey
|
|
||||||
None, # Icon
|
|
||||||
None, # IconIndex
|
|
||||||
None, # ShowCmd
|
|
||||||
'TARGETDIR', # WkDir
|
|
||||||
),
|
|
||||||
('ProgramMenuDaemonCLIShortcut', # Shortcut
|
|
||||||
'ProgramMenuFolder', # Directory
|
|
||||||
# r'[ProgramMenuFolder]\lbrynet', # Directory
|
|
||||||
'lbrynet-cli', # Name
|
|
||||||
'TARGETDIR', # Component
|
|
||||||
'[TARGETDIR]\lbrynet-cli.exe', # Target
|
|
||||||
None, # Arguments
|
|
||||||
description, # Description
|
|
||||||
None, # Hotkey
|
|
||||||
None, # Icon
|
|
||||||
None, # IconIndex
|
|
||||||
None, # ShowCmd
|
|
||||||
'TARGETDIR', # WkDir
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
msi_data = {"Shortcut": shortcut_table}
|
|
||||||
|
|
||||||
bdist_msi_options = {
|
|
||||||
'upgrade_code': '{18c0e933-ad08-44e8-a413-1d0ed624c100}',
|
|
||||||
'add_to_path': True,
|
|
||||||
# Default install path is 'C:\Program Files\' for 32-bit or 'C:\Program Files (x86)\' for 64-bit
|
|
||||||
# 'initial_target_dir': r'[LocalAppDataFolder]\{0}'.format(name),
|
|
||||||
'data': msi_data
|
|
||||||
}
|
|
||||||
|
|
||||||
build_exe_options = {
|
|
||||||
'include_msvcr': True,
|
|
||||||
'includes': [],
|
|
||||||
'packages': ['cython',
|
|
||||||
'twisted',
|
|
||||||
'yapsy',
|
|
||||||
'appdirs',
|
|
||||||
'argparse',
|
|
||||||
'base58',
|
|
||||||
'colorama',
|
|
||||||
'cx_Freeze',
|
|
||||||
'dns',
|
|
||||||
'ecdsa',
|
|
||||||
'envparse',
|
|
||||||
'gmpy',
|
|
||||||
'googlefinance',
|
|
||||||
'jsonrpc',
|
|
||||||
'jsonrpclib',
|
|
||||||
'lbryum',
|
|
||||||
'loggly',
|
|
||||||
'miniupnpc',
|
|
||||||
'pbkdf2',
|
|
||||||
'google.protobuf',
|
|
||||||
'Crypto',
|
|
||||||
'bitcoinrpc',
|
|
||||||
'win32api',
|
|
||||||
'qrcode',
|
|
||||||
'requests',
|
|
||||||
'requests_futures',
|
|
||||||
'seccure',
|
|
||||||
'simplejson',
|
|
||||||
'jsonschema',
|
|
||||||
'six',
|
|
||||||
'aes',
|
|
||||||
'txjsonrpc',
|
|
||||||
'wsgiref',
|
|
||||||
'zope.interface',
|
|
||||||
'os',
|
|
||||||
'pkg_resources',
|
|
||||||
'yaml'
|
|
||||||
],
|
|
||||||
'excludes': ['distutils', 'collections.sys', 'collections._weakref', 'collections.abc',
|
|
||||||
'Tkinter', 'tk', 'tcl', 'PyQt4', 'nose', 'mock'
|
|
||||||
'zope.interface._zope_interface_coptimizations', 'leveldb'],
|
|
||||||
'include_files': [(distutils_path, 'distutils'), (requests.certs.where(), 'cacert.pem'),
|
|
||||||
(os.path.join(app_dir, 'icons', 'lbry16.ico'), os.path.join('icons', 'lbry16.ico')),
|
|
||||||
(os.path.join(app_dir, 'icons', 'lbry256.ico'), os.path.join('icons', 'lbry256.ico')),
|
|
||||||
(os.path.join(wordlist_path, 'chinese_simplified.txt'),
|
|
||||||
os.path.join('wordlist', 'chinese_simplified.txt')),
|
|
||||||
(os.path.join(wordlist_path, 'english.txt'), os.path.join('wordlist', 'english.txt')),
|
|
||||||
(os.path.join(wordlist_path, 'japanese.txt'), os.path.join('wordlist', 'japanese.txt')),
|
|
||||||
(os.path.join(wordlist_path, 'portuguese.txt'), os.path.join('wordlist', 'portuguese.txt')),
|
|
||||||
(os.path.join(wordlist_path, 'spanish.txt'), os.path.join('wordlist', 'spanish.txt'))
|
|
||||||
],
|
|
||||||
'namespace_packages': ['zope', 'google'],
|
|
||||||
"zip_includes": zipincludes}
|
|
||||||
|
|
||||||
tray_app = Executable(
|
|
||||||
script=os.path.join(app_dir, 'LBRYWin32App.py'),
|
|
||||||
base='Win32GUI',
|
|
||||||
icon=win_icon,
|
|
||||||
targetName='{0}.exe'.format(dist_name)
|
|
||||||
)
|
|
||||||
|
|
||||||
daemon_exe = Executable(
|
|
||||||
script=os.path.join(daemon_dir, 'DaemonControl.py'),
|
|
||||||
icon=win_icon,
|
|
||||||
targetName='lbrynet-daemon.exe'
|
|
||||||
)
|
|
||||||
|
|
||||||
cli_exe = Executable(
|
|
||||||
script=os.path.join(daemon_dir, 'DaemonCLI.py'),
|
|
||||||
icon=win_icon,
|
|
||||||
targetName='lbrynet-cli.exe'
|
|
||||||
)
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name=package_name,
|
|
||||||
description=description,
|
|
||||||
version=__version__,
|
|
||||||
maintainer=maintainer,
|
|
||||||
maintainer_email=maintainer_email,
|
|
||||||
url=url,
|
|
||||||
author=author,
|
|
||||||
keywords=keywords,
|
|
||||||
data_files=[],
|
|
||||||
options={
|
|
||||||
'build_exe': build_exe_options,
|
|
||||||
'bdist_msi': bdist_msi_options
|
|
||||||
},
|
|
||||||
executables=[
|
|
||||||
tray_app,
|
|
||||||
daemon_exe,
|
|
||||||
cli_exe
|
|
||||||
],
|
|
||||||
package_data={
|
|
||||||
package_name: list(package_files('lbrynet/resources/ui'))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ from tests.mocks import mock_conf_settings, FakeNetwork
|
||||||
|
|
||||||
|
|
||||||
class MiscTests(unittest.TestCase):
|
class MiscTests(unittest.TestCase):
|
||||||
def test_get_lbrynet_version_from_github(self):
|
def test_get_lbry_electron_client_version_from_github(self):
|
||||||
response = mock.create_autospec(requests.Response)
|
response = mock.create_autospec(requests.Response)
|
||||||
# don't need to mock out the entire response from the api
|
# don't need to mock out the entire response from the api
|
||||||
# but at least need 'tag_name'
|
# but at least need 'tag_name'
|
||||||
|
@ -28,7 +28,9 @@ class MiscTests(unittest.TestCase):
|
||||||
}
|
}
|
||||||
with mock.patch('lbrynet.lbrynet_daemon.Daemon.requests') as req:
|
with mock.patch('lbrynet.lbrynet_daemon.Daemon.requests') as req:
|
||||||
req.get.return_value = response
|
req.get.return_value = response
|
||||||
self.assertEqual('0.3.8', Daemon.get_lbrynet_version_from_github())
|
rv = Daemon.CheckRemoteVersion()
|
||||||
|
rv._get_lbry_electron_client_version()
|
||||||
|
self.assertEqual('0.3.8', rv.version)
|
||||||
|
|
||||||
def test_error_is_thrown_if_prerelease(self):
|
def test_error_is_thrown_if_prerelease(self):
|
||||||
response = mock.create_autospec(requests.Response)
|
response = mock.create_autospec(requests.Response)
|
||||||
|
@ -38,8 +40,9 @@ class MiscTests(unittest.TestCase):
|
||||||
}
|
}
|
||||||
with mock.patch('lbrynet.lbrynet_daemon.Daemon.requests') as req:
|
with mock.patch('lbrynet.lbrynet_daemon.Daemon.requests') as req:
|
||||||
req.get.return_value = response
|
req.get.return_value = response
|
||||||
|
rv = Daemon.CheckRemoteVersion()
|
||||||
with self.assertRaises(Exception):
|
with self.assertRaises(Exception):
|
||||||
Daemon.get_lbrynet_version_from_github()
|
rv._get_lbry_electron_client_version()
|
||||||
|
|
||||||
def test_error_is_thrown_when_version_cant_be_parsed(self):
|
def test_error_is_thrown_when_version_cant_be_parsed(self):
|
||||||
with self.assertRaises(Exception):
|
with self.assertRaises(Exception):
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
from twisted.trial import unittest
|
|
||||||
import mock
|
|
||||||
|
|
||||||
from lbrynet.lbrynet_daemon import UIManager
|
|
||||||
|
|
||||||
|
|
||||||
class BundledUIManagerTest(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.active_dir = tempfile.mkdtemp()
|
|
||||||
self.bundled_dir = tempfile.mkdtemp()
|
|
||||||
self.manager = UIManager.BundledUIManager(mock.Mock(), self.active_dir, self.bundled_dir)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
shutil.rmtree(self.active_dir)
|
|
||||||
shutil.rmtree(self.bundled_dir)
|
|
||||||
|
|
||||||
def test_when_bundle_is_not_available(self):
|
|
||||||
result = self.manager.setup()
|
|
||||||
self.assertFalse(result)
|
|
||||||
expected = []
|
|
||||||
self.assertEqual(os.listdir(self.active_dir), expected)
|
|
||||||
|
|
||||||
def test_when_already_bundled(self):
|
|
||||||
make_data_file(self.active_dir)
|
|
||||||
make_data_file(self.bundled_dir)
|
|
||||||
result = self.manager.setup()
|
|
||||||
self.assertTrue(result)
|
|
||||||
expected = ['data.json']
|
|
||||||
self.assertEqual(os.listdir(self.active_dir), expected)
|
|
||||||
|
|
||||||
def test_bundled_files_are_copied(self):
|
|
||||||
make_data_file(self.active_dir)
|
|
||||||
make_data_file(self.bundled_dir, 'BARFOO')
|
|
||||||
touch(os.path.join(self.bundled_dir, 'test.html'))
|
|
||||||
result = self.manager.setup()
|
|
||||||
self.assertTrue(result)
|
|
||||||
self.assertEqual('BARFOO', self.manager.version())
|
|
||||||
expected = ['data.json', 'test.html']
|
|
||||||
self.assertItemsEqual(os.listdir(self.active_dir), expected)
|
|
||||||
|
|
||||||
|
|
||||||
def make_data_file(directory, sha='FOOBAR'):
|
|
||||||
with open(os.path.join(directory, 'data.json'), 'w') as f:
|
|
||||||
json.dump({'sha': sha}, f)
|
|
||||||
|
|
||||||
|
|
||||||
def touch(filename):
|
|
||||||
with open(filename, 'a') as f:
|
|
||||||
pass
|
|
|
@ -1,90 +0,0 @@
|
||||||
import os
|
|
||||||
import webbrowser
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
from lbrynet.lbrynet_daemon.auth.client import LBRYAPIClient
|
|
||||||
from lbrynet import conf
|
|
||||||
|
|
||||||
|
|
||||||
class LBRYURIHandler(object):
|
|
||||||
def __init__(self):
|
|
||||||
self.started_daemon = False
|
|
||||||
self.daemon = LBRYAPIClient.get_client()
|
|
||||||
|
|
||||||
def handle_osx(self, lbry_name):
|
|
||||||
self.check_daemon()
|
|
||||||
if not self.started_daemon:
|
|
||||||
os.system("open /Applications/LBRY.app")
|
|
||||||
sleep(3)
|
|
||||||
|
|
||||||
lbry_name = self.parse_name(lbry_name)
|
|
||||||
self.open_address(lbry_name)
|
|
||||||
|
|
||||||
def handle_linux(self, lbry_name):
|
|
||||||
self.check_daemon()
|
|
||||||
if not self.started_daemon:
|
|
||||||
cmd = r'DIR = "$( cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd )"' \
|
|
||||||
r'if [-z "$(pgrep lbrynet-daemon)"]; then' \
|
|
||||||
r'echo "running lbrynet-daemon"' \
|
|
||||||
r'$DIR / lbrynet - daemon &' \
|
|
||||||
r'sleep 3 # let the daemon load before connecting' \
|
|
||||||
r'fi'
|
|
||||||
subprocess.Popen(cmd, shell=True)
|
|
||||||
|
|
||||||
lbry_name = self.parse_name(lbry_name)
|
|
||||||
self.open_address(lbry_name)
|
|
||||||
|
|
||||||
def handle_win32(self, lbry_name):
|
|
||||||
# Opening LBRY.exe with lbry_name as arg prevents the need to
|
|
||||||
# make a separate call to open_address()
|
|
||||||
self.check_daemon()
|
|
||||||
lbry_name = self.parse_name(lbry_name)
|
|
||||||
if self.started_daemon:
|
|
||||||
self.open_address(lbry_name)
|
|
||||||
else:
|
|
||||||
lbry_path = os.path.join(os.environ["PROGRAMFILES"], "LBRY", "LBRY.exe ")
|
|
||||||
subprocess.call(lbry_path + lbry_name)
|
|
||||||
|
|
||||||
def check_daemon(self):
|
|
||||||
try:
|
|
||||||
status = self.daemon.call('status')
|
|
||||||
self.started_daemon = status['is_running']
|
|
||||||
except:
|
|
||||||
self.started_daemon = False
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def parse_name(lbry_name):
|
|
||||||
if lbry_name[:7].lower() == "lbry://":
|
|
||||||
if lbry_name[-1] == "/":
|
|
||||||
return lbry_name[7:-1]
|
|
||||||
else:
|
|
||||||
return lbry_name[7:]
|
|
||||||
else:
|
|
||||||
if lbry_name[-1] == "/":
|
|
||||||
return lbry_name[:-1]
|
|
||||||
else:
|
|
||||||
return lbry_name[:]
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def open_address(lbry_name):
|
|
||||||
if lbry_name == "lbry" or lbry_name == "" or lbry_name is None:
|
|
||||||
webbrowser.open(conf.settings.get_ui_address())
|
|
||||||
else:
|
|
||||||
webbrowser.open(conf.settings.get_ui_address() + "/?show=" + lbry_name)
|
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
|
||||||
if len(args) != 1:
|
|
||||||
args = ["lbry://lbry"]
|
|
||||||
name = args[0][7:]
|
|
||||||
if sys.platform == "darwin":
|
|
||||||
LBRYURIHandler().handle_osx(lbry_name=name)
|
|
||||||
elif os.name == "nt":
|
|
||||||
LBRYURIHandler().handle_win32(lbry_name=name)
|
|
||||||
else:
|
|
||||||
LBRYURIHandler().handle_linux(lbry_name=name)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main(sys.argv[1:])
|
|
|
@ -1,54 +0,0 @@
|
||||||
import _winreg as winreg
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import win32con
|
|
||||||
import win32gui
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
try:
|
|
||||||
install = 'remove' not in sys.argv[1]
|
|
||||||
except:
|
|
||||||
install = True
|
|
||||||
lbry_path = os.path.join(os.environ["ProgramFiles"], "LBRY", "LBRY.exe")
|
|
||||||
|
|
||||||
key_url = 'lbry'
|
|
||||||
try:
|
|
||||||
key = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, key_url, 0, winreg.KEY_ALL_ACCESS)
|
|
||||||
except:
|
|
||||||
key = winreg.CreateKey(winreg.HKEY_CLASSES_ROOT, key_url)
|
|
||||||
if install:
|
|
||||||
winreg.SetValueEx(key, None, 0, winreg.REG_SZ, "URL:LBRY Protocol")
|
|
||||||
winreg.SetValueEx(key, "URL Protocol", 0, winreg.REG_SZ, "")
|
|
||||||
else:
|
|
||||||
winreg.DeleteKey(winreg.HKEY_CLASSES_ROOT, key_url)
|
|
||||||
|
|
||||||
winreg.CloseKey(key)
|
|
||||||
|
|
||||||
key_icon = os.path.join('lbry', 'DefaultIcon')
|
|
||||||
try:
|
|
||||||
key = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, key_icon, 0, winreg.KEY_ALL_ACCESS)
|
|
||||||
except:
|
|
||||||
key = winreg.CreateKey(winreg.HKEY_CLASSES_ROOT, key_icon)
|
|
||||||
if install:
|
|
||||||
winreg.SetValueEx(key, None, 0, winreg.REG_SZ, "\"LBRY.exe,1\"")
|
|
||||||
else:
|
|
||||||
winreg.DeleteKey(winreg.HKEY_CLASSES_ROOT, key_icon)
|
|
||||||
winreg.CloseKey(key)
|
|
||||||
|
|
||||||
key_command = os.path.join('lbry', 'shell', 'open', 'command')
|
|
||||||
try:
|
|
||||||
key = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, key_command, 0, winreg.KEY_ALL_ACCESS)
|
|
||||||
except:
|
|
||||||
key = winreg.CreateKey(winreg.HKEY_CLASSES_ROOT, key_command)
|
|
||||||
if install:
|
|
||||||
winreg.SetValueEx(key, None, 0, winreg.REG_SZ, "\"{0}\" \"%1\"".format(lbry_path))
|
|
||||||
else:
|
|
||||||
winreg.DeleteKey(winreg.HKEY_CLASSES_ROOT, key_command)
|
|
||||||
winreg.CloseKey(key)
|
|
||||||
|
|
||||||
win32gui.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|