Merge remote-tracking branch 'mediaminister/live' into main
This commit is contained in:
commit
97d80f2115
@ -4,3 +4,11 @@ ADDON_PASSWORD=
|
||||
KODI_HOME=tests/home
|
||||
KODI_INTERACTIVE=0
|
||||
KODI_STUB_VERBOSE=1
|
||||
KODI_STUB_RPC_RESPONSES=tests/rpc
|
||||
|
||||
#HTTP_PROXY=
|
||||
#HTTPS_PROXY=
|
||||
|
||||
GH_USERNAME=
|
||||
GH_TOKEN=
|
||||
EMAIL=
|
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -6,3 +6,4 @@ tests/ export-ignore
|
||||
.pylintrc export-ignore
|
||||
Makefile export-ignore
|
||||
requirements.txt export-ignore
|
||||
scripts/ export-ignore
|
||||
|
7
.github/workflows/addon-check.yml
vendored
7
.github/workflows/addon-check.yml
vendored
@ -11,10 +11,6 @@ jobs:
|
||||
kodi-addon-checker:
|
||||
name: Addon checker
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
kodi-version: [ leia, matrix ]
|
||||
steps:
|
||||
- name: Check out ${{ github.sha }} from repository ${{ github.repository }}
|
||||
uses: actions/checkout@v2
|
||||
@ -22,6 +18,5 @@ jobs:
|
||||
- name: Run kodi-addon-checker
|
||||
uses: xbmc/action-kodi-addon-checker@v1.2
|
||||
with:
|
||||
kodi-version: ${{ matrix.kodi-version }}
|
||||
rewrite-for-matrix: ${{ matrix.kodi-version == 'matrix' }}
|
||||
kodi-version: matrix
|
||||
addon-id: ${{ github.event.repository.name }}
|
34
.github/workflows/ci.yml
vendored
34
.github/workflows/ci.yml
vendored
@ -3,10 +3,10 @@ on:
|
||||
# Run action when pushed to master, or for commits in a pull request.
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- master
|
||||
jobs:
|
||||
tests:
|
||||
name: Add-on testing
|
||||
@ -14,24 +14,22 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest ]
|
||||
python-version: [ 2.7, 3.5, 3.6, 3.7, 3.8, 3.9 ]
|
||||
os: [ ubuntu-latest, windows-latest ]
|
||||
python-version: ["3.8", "3.9", "3.10"]
|
||||
include:
|
||||
# Kodi Leia on Windows uses a bundled Python 2.7.
|
||||
- os: windows-latest
|
||||
python-version: 2.7
|
||||
|
||||
# Kodi Matrix on Windows uses a bundled Python 3.8, but we test 3.9 also to be sure.
|
||||
- os: windows-latest
|
||||
python-version: 3.8
|
||||
- os: windows-latest
|
||||
python-version: 3.9
|
||||
# End-of-life Python versions are not available anymore with ubuntu-latest
|
||||
- os: ubuntu-20.04
|
||||
python-version: "3.5"
|
||||
- os: ubuntu-20.04
|
||||
python-version: "3.6"
|
||||
- os: ubuntu-20.04
|
||||
python-version: "3.7"
|
||||
steps:
|
||||
- name: Check out ${{ github.sha }} from repository ${{ github.repository }}
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v1
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
@ -54,14 +52,14 @@ jobs:
|
||||
KODI_INTERACTIVE: 0
|
||||
KODI_STUB_RPC_RESPONSES: ${{ github.workspace }}/tests/rpc
|
||||
HTTP_PROXY: ${{ secrets.HTTP_PROXY }}
|
||||
run: pytest -v --cov=./ --cov-report=xml tests
|
||||
run: pytest -x -v --cov=./ --cov-report=xml tests
|
||||
|
||||
- name: Upload code coverage to CodeCov
|
||||
uses: codecov/codecov-action@v1
|
||||
uses: codecov/codecov-action@v3
|
||||
continue-on-error: true
|
||||
env:
|
||||
OS: ${{ matrix.os }}
|
||||
PYTHON: ${{ matrix.python-version }}
|
||||
with:
|
||||
flags: unittests
|
||||
env_vars: OS,PYTHON
|
||||
env_vars: OS,PYTHON
|
||||
|
64
.github/workflows/release.yml
vendored
64
.github/workflows/release.yml
vendored
@ -6,22 +6,13 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
name: Release plugin.video.viervijfzes
|
||||
if: startsWith(github.ref, 'refs/tags/') # prevent from running if it's not a tag
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
- name: Check out ${{ github.sha }} from repository ${{ github.repository }}
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build zip files
|
||||
id: build
|
||||
run: |
|
||||
sudo apt-get install libxml2-utils
|
||||
make multizip release=1
|
||||
echo ::set-output name=leia-filename::$(cd ..;ls plugin.video.viervijfzes*.zip | grep -v '+matrix.' | head -1)
|
||||
echo ::set-output name=matrix-filename::$(cd ..;ls plugin.video.viervijfzes*+matrix.*.zip | head -1)
|
||||
|
||||
- name: Get body
|
||||
id: get-body
|
||||
- name: Get changelog
|
||||
id: get-changelog
|
||||
run: |
|
||||
description=$(sed '1,6d;/^## /,$d' CHANGELOG.md)
|
||||
echo $description
|
||||
@ -30,47 +21,14 @@ jobs:
|
||||
description="${description//$'\r'/'%0D'}"
|
||||
echo ::set-output name=body::$description
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
- name: Generate distribution zips
|
||||
run: scripts/build.py
|
||||
|
||||
- name: Create Release on Github
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: ${{ github.ref }}
|
||||
body: ${{ steps.get-body.outputs.body }}
|
||||
body: ${{ steps.get-changelog.outputs.body }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
|
||||
- name: Upload Leia zip
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_name: ${{ steps.build.outputs.leia-filename }}
|
||||
asset_path: ../${{ steps.build.outputs.leia-filename }}
|
||||
asset_content_type: application/zip
|
||||
|
||||
- name: Upload Matrix zip
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_name: ${{ steps.build.outputs.matrix-filename }}
|
||||
asset_path: ../${{ steps.build.outputs.matrix-filename }}
|
||||
asset_content_type: application/zip
|
||||
|
||||
- name: Generate distribution zip and submit to official kodi repository
|
||||
id: kodi-addon-submitter
|
||||
uses: xbmc/action-kodi-addon-submitter@v1.2
|
||||
with:
|
||||
kodi-repository: repo-plugins
|
||||
addon-id: plugin.video.viervijfzes
|
||||
kodi-version: leia
|
||||
kodi-matrix: true
|
||||
env:
|
||||
GH_USERNAME: ${{ secrets.GH_USERNAME }}
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
EMAIL: ${{ secrets.EMAIL }}
|
||||
files: "dist/*.zip"
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -18,3 +18,5 @@ tests/home/userdata/addon_data
|
||||
|
||||
Pipfile
|
||||
Pipfile.lock
|
||||
|
||||
dist/
|
||||
|
@ -18,6 +18,8 @@ disable=
|
||||
use-maxsplit-arg,
|
||||
consider-using-from-import,
|
||||
unspecified-encoding,
|
||||
broad-exception-raised,
|
||||
|
||||
super-with-arguments, # Python 2.7 compatibility
|
||||
raise-missing-from, # Python 2.7 compatibility
|
||||
consider-using-f-string, # Python 2.7 compatibility
|
||||
|
100
CHANGELOG.md
100
CHANGELOG.md
@ -1,5 +1,76 @@
|
||||
# Changelog
|
||||
|
||||
## [v0.4.11](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.4.11) (2023-07-26)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.4.10...v0.4.11)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Add support for proxies [\#126](https://github.com/add-ons/plugin.video.viervijfzes/pull/126) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Add DRM support for all streams [\#121](https://github.com/add-ons/plugin.video.viervijfzes/pull/121) ([mediaminister](https://github.com/mediaminister))
|
||||
- Use inputstreamhelper for unprotected MPEG-DASH [\#118](https://github.com/add-ons/plugin.video.viervijfzes/pull/118) ([mediaminister](https://github.com/mediaminister))
|
||||
|
||||
## [v0.4.10](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.4.10) (2023-01-16)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.4.9...v0.4.10)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Update api [\#114](https://github.com/add-ons/plugin.video.viervijfzes/pull/114) ([mediaminister](https://github.com/mediaminister))
|
||||
|
||||
## [v0.4.9](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.4.9) (2023-01-04)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.4.8...v0.4.9)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Add support for unprotected MPEG-DASH streams [\#111](https://github.com/add-ons/plugin.video.viervijfzes/pull/111) ([mediaminister](https://github.com/mediaminister))
|
||||
- Fix clips [\#108](https://github.com/add-ons/plugin.video.viervijfzes/pull/108) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
## [v0.4.8](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.4.8) (2022-07-07)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.4.7...v0.4.8)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Fix API [\#105](https://github.com/add-ons/plugin.video.viervijfzes/pull/105) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
## [v0.4.7](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.4.7) (2022-02-04)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.4.6...v0.4.7)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Fix empty My List due to unknown items [\#102](https://github.com/add-ons/plugin.video.viervijfzes/pull/102) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
## [v0.4.6](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.4.6) (2022-02-02)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.4.5...v0.4.6)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Fix playback of DRM protected content [\#101](https://github.com/add-ons/plugin.video.viervijfzes/pull/101) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
## [v0.4.5](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.4.5) (2021-10-21)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.4.4...v0.4.5)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Remove dependency on inputstream.adaptive [\#98](https://github.com/add-ons/plugin.video.viervijfzes/pull/98) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
- Various fixes due to layout changes [\#97](https://github.com/add-ons/plugin.video.viervijfzes/pull/97) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
## [v0.4.4](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.4.4) (2021-09-15)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.4.3...v0.4.4)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Fix menu [\#93](https://github.com/add-ons/plugin.video.viervijfzes/pull/93) ([mediaminister](https://github.com/mediaminister))
|
||||
|
||||
## [v0.4.3](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.4.3) (2021-04-24)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.4.2...v0.4.3)
|
||||
@ -37,11 +108,6 @@
|
||||
|
||||
- Fix error when requesting a My List that has not been created yet. [\#73](https://github.com/add-ons/plugin.video.viervijfzes/pull/73) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Cleanup CI [\#72](https://github.com/add-ons/plugin.video.viervijfzes/pull/72) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
- Remove dependency on tox [\#70](https://github.com/add-ons/plugin.video.viervijfzes/pull/70) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
## [v0.4.0](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.4.0) (2021-02-04)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.3.1...v0.4.0)
|
||||
@ -50,12 +116,6 @@
|
||||
|
||||
- Rebranding to GoPlay [\#64](https://github.com/add-ons/plugin.video.viervijfzes/pull/64) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Make use of git archive [\#66](https://github.com/add-ons/plugin.video.viervijfzes/pull/66) ([dagwieers](https://github.com/dagwieers))
|
||||
- Run CI on Windows [\#62](https://github.com/add-ons/plugin.video.viervijfzes/pull/62) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
- Add support for Python 3.9 [\#60](https://github.com/add-ons/plugin.video.viervijfzes/pull/60) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
## [v0.3.1](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.3.1) (2020-11-28)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.3.0...v0.3.1)
|
||||
@ -64,10 +124,6 @@
|
||||
|
||||
- Fix authentication on some older Android devices [\#58](https://github.com/add-ons/plugin.video.viervijfzes/pull/58) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix CI tests [\#59](https://github.com/add-ons/plugin.video.viervijfzes/pull/59) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
## [v0.3.0](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.3.0) (2020-11-17)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.2.0...v0.3.0)
|
||||
@ -87,11 +143,6 @@
|
||||
- Opening some programs without a title could throw an error [\#45](https://github.com/add-ons/plugin.video.viervijfzes/pull/45) ([dagwieers](https://github.com/dagwieers))
|
||||
- Show message when Kodi Player fails to get the stream [\#40](https://github.com/add-ons/plugin.video.viervijfzes/pull/40) ([mediaminister](https://github.com/mediaminister))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Various fixes [\#46](https://github.com/add-ons/plugin.video.viervijfzes/pull/46) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
- Use sake for Kodi stubs [\#36](https://github.com/add-ons/plugin.video.viervijfzes/pull/36) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
## [v0.2.0](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.2.0) (2020-06-19)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/v0.1.0...v0.2.0)
|
||||
@ -116,11 +167,6 @@
|
||||
- Fix multi-line text in progress dialog [\#21](https://github.com/add-ons/plugin.video.viervijfzes/pull/21) ([mediaminister](https://github.com/mediaminister))
|
||||
- Fix token encoding in auth [\#19](https://github.com/add-ons/plugin.video.viervijfzes/pull/19) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Check for unused translations [\#24](https://github.com/add-ons/plugin.video.viervijfzes/pull/24) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
- Move test/ to tests/ [\#17](https://github.com/add-ons/plugin.video.viervijfzes/pull/17) ([dagwieers](https://github.com/dagwieers))
|
||||
|
||||
## [v0.1.0](https://github.com/add-ons/plugin.video.viervijfzes/tree/v0.1.0) (2020-03-27)
|
||||
|
||||
[Full Changelog](https://github.com/add-ons/plugin.video.viervijfzes/compare/89f55f70b017d0add645d1e1d88f0ce8192d11c4...v0.1.0)
|
||||
@ -136,11 +182,7 @@
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Improve CI tests [\#14](https://github.com/add-ons/plugin.video.viervijfzes/pull/14) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
- Small translation fixes [\#12](https://github.com/add-ons/plugin.video.viervijfzes/pull/12) ([dagwieers](https://github.com/dagwieers))
|
||||
- Various check fixes [\#11](https://github.com/add-ons/plugin.video.viervijfzes/pull/11) ([dagwieers](https://github.com/dagwieers))
|
||||
- Replace Travis with GitHub Actions [\#10](https://github.com/add-ons/plugin.video.viervijfzes/pull/10) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
- Improve code coverage [\#9](https://github.com/add-ons/plugin.video.viervijfzes/pull/9) ([michaelarnauts](https://github.com/michaelarnauts))
|
||||
|
||||
|
||||
|
||||
|
14
LICENSE
14
LICENSE
@ -1,7 +1,7 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@ -631,8 +631,8 @@ to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{one line to give the program's name and a brief idea of what it does.}
|
||||
Copyright (C) {year} {name of author}
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -645,14 +645,14 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
{project} Copyright (C) {year} {fullname}
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
|
45
Makefile
45
Makefile
@ -1,25 +1,12 @@
|
||||
export KODI_HOME := $(CURDIR)/tests/home
|
||||
export KODI_INTERACTIVE := 0
|
||||
PYTHON := python
|
||||
KODI_PYTHON_ABIS := 3.0.0 2.26.0
|
||||
|
||||
# Collect information to build as sensible package name
|
||||
name = $(shell xmllint --xpath 'string(/addon/@id)' addon.xml)
|
||||
version = $(shell xmllint --xpath 'string(/addon/@version)' addon.xml)
|
||||
git_branch = $(shell git rev-parse --abbrev-ref HEAD)
|
||||
git_hash = $(shell git rev-parse --short HEAD)
|
||||
|
||||
ifdef release
|
||||
zip_name = $(name)-$(version).zip
|
||||
else
|
||||
zip_name = $(name)-$(version)-$(git_branch)-$(git_hash).zip
|
||||
endif
|
||||
zip_dir = $(name)/
|
||||
|
||||
languages = $(filter-out en_gb, $(patsubst resources/language/resource.language.%, %, $(wildcard resources/language/*)))
|
||||
|
||||
all: check test build
|
||||
zip: build
|
||||
multizip: build
|
||||
|
||||
check: check-pylint check-translations
|
||||
|
||||
@ -30,15 +17,15 @@ check-pylint:
|
||||
check-translations:
|
||||
@printf ">>> Running translation checks\n"
|
||||
@$(foreach lang,$(languages), \
|
||||
msgcmp resources/language/resource.language.$(lang)/strings.po resources/language/resource.language.en_gb/strings.po; \
|
||||
msgcmp --use-untranslated resources/language/resource.language.$(lang)/strings.po resources/language/resource.language.en_gb/strings.po; \
|
||||
)
|
||||
@tests/check_for_unused_translations.py
|
||||
@scripts/check_for_unused_translations.py
|
||||
|
||||
check-addon: clean build
|
||||
check-addon: build
|
||||
@printf ">>> Running addon checks\n"
|
||||
$(eval TMPDIR := $(shell mktemp -d))
|
||||
@unzip ../${zip_name} -d ${TMPDIR}
|
||||
cd ${TMPDIR} && kodi-addon-checker --branch=leia
|
||||
@unzip dist/plugin.video.viervijfzes-*+matrix.1.zip -d ${TMPDIR}
|
||||
cd ${TMPDIR} && kodi-addon-checker --branch=matrix
|
||||
@rm -rf ${TMPDIR}
|
||||
|
||||
codefix:
|
||||
@ -56,17 +43,16 @@ clean:
|
||||
@find . -name '__pycache__' -type d -delete
|
||||
@rm -rf .pytest_cache/ tests/cdm tests/userdata/temp
|
||||
@rm -f *.log .coverage
|
||||
@rm -rf dist/
|
||||
|
||||
build: clean
|
||||
@printf ">>> Building package\n"
|
||||
@rm -f ../$(zip_name)
|
||||
@git archive --format zip --worktree-attributes -v -o ../$(zip_name) --prefix $(zip_dir) $(or $(shell git stash create), HEAD)
|
||||
@printf ">>> Successfully wrote package as: ../$(zip_name)\n"
|
||||
@printf ">>> Building add-on\n"
|
||||
@scripts/build.py
|
||||
@ls -lah dist/*.zip
|
||||
|
||||
# You first need to run sudo gem install github_changelog_generator for this
|
||||
release:
|
||||
ifneq ($(release),)
|
||||
@github_changelog_generator -u add-ons -p $(name) --no-issues --exclude-labels duplicate,question,invalid,wontfix release --future-release v$(release);
|
||||
docker run -it --rm --env CHANGELOG_GITHUB_TOKEN=$(GH_TOKEN) -v "$(shell pwd)":/usr/local/src/your-app githubchangeloggenerator/github-changelog-generator -u add-ons -p plugin.video.viervijfzes --no-issues --exclude-labels duplicate,question,invalid,wontfix,release,testing --future-release v$(release)
|
||||
|
||||
@printf "cd /addon/@version\nset $$release\nsave\nbye\n" | xmllint --shell addon.xml; \
|
||||
date=$(shell date '+%Y-%m-%d'); \
|
||||
@ -80,11 +66,4 @@ else
|
||||
@printf "Usage: make release release=1.0.0\n"
|
||||
endif
|
||||
|
||||
multizip: clean
|
||||
@-$(foreach abi,$(KODI_PYTHON_ABIS), \
|
||||
printf "cd /addon/requires/import[@addon='xbmc.python']/@version\nset $(abi)\nsave\nbye\n" | xmllint --shell addon.xml; \
|
||||
matrix=$(findstring $(abi), $(word 1,$(KODI_PYTHON_ABIS))); \
|
||||
if [ $$matrix ]; then version=$(version)+matrix.1; else version=$(version); fi; \
|
||||
printf "cd /addon/@version\nset $$version\nsave\nbye\n" | xmllint --shell addon.xml; \
|
||||
make build; \
|
||||
)
|
||||
.PHONY: check codefix test clean build release
|
||||
|
@ -1,5 +1,5 @@
|
||||
[![GitHub release](https://img.shields.io/github/release/add-ons/plugin.video.viervijfzes.svg?include_prereleases)](https://github.com/add-ons/plugin.video.viervijfzes/releases)
|
||||
[![Build Status](https://img.shields.io/github/workflow/status/add-ons/plugin.video.viervijfzes/CI/master)](https://github.com/add-ons/plugin.video.viervijfzes/actions?query=branch%3Amaster)
|
||||
[![GitHub release](https://img.shields.io/github/v/release/add-ons/plugin.video.viervijfzes?display_name=tag)](https://github.com/add-ons/plugin.video.viervijfzes/releases)
|
||||
[![Build Status](https://img.shields.io/github/actions/workflow/status/add-ons/plugin.video.viervijfzes/ci.yml?branch=master)](https://github.com/add-ons/plugin.video.viervijfzes/actions?query=branch%3Amaster)
|
||||
[![Codecov status](https://img.shields.io/codecov/c/github/add-ons/plugin.video.viervijfzes/master)](https://codecov.io/gh/add-ons/plugin.video.viervijfzes/branch/master)
|
||||
[![License: GPLv3](https://img.shields.io/badge/License-GPLv3-yellow.svg)](https://opensource.org/licenses/GPL-3.0)
|
||||
[![Contributors](https://img.shields.io/github/contributors/add-ons/plugin.video.viervijfzes.svg)](https://github.com/add-ons/plugin.video.viervijfzes/graphs/contributors)
|
||||
@ -11,7 +11,7 @@ account aanmaken op [goplay.be](https://www.goplay.be/).
|
||||
|
||||
Meer informatie kan je vinden op de [Wiki pagina](https://github.com/add-ons/plugin.video.viervijfzes/wiki).
|
||||
|
||||
> Let op dat er geen live-streams beschikbaar zijn op het GoPlay platform en je dus enkel kan kijken de beschikbare programma's in de catalogus.
|
||||
> Let op dat er geen live-streams beschikbaar zijn op het GoPlay platform en je dus enkel kan kijken naar de beschikbare programma's in de catalogus.
|
||||
|
||||
## Features
|
||||
|
||||
|
11
addon.xml
11
addon.xml
@ -1,13 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<addon id="plugin.video.viervijfzes" name="GoPlay" version="0.4.3" provider-name="Michaël Arnauts">
|
||||
<addon id="plugin.video.viervijfzes" name="GoPlay" version="0.4.11" provider-name="Michaël Arnauts">
|
||||
<requires>
|
||||
<import addon="xbmc.python" version="2.26.0"/>
|
||||
<import addon="xbmc.python" version="3.0.0"/>
|
||||
<import addon="script.module.dateutil" version="2.6.0"/>
|
||||
<import addon="script.module.inputstreamhelper" version="0.5.1"/>
|
||||
<import addon="script.module.pysocks" version="1.6.8" optional="true"/>
|
||||
<import addon="script.module.requests" version="2.22.0"/>
|
||||
<import addon="script.module.routing" version="0.2.0"/>
|
||||
<import addon="inputstream.adaptive" version="2.4.3"/>
|
||||
</requires>
|
||||
<extension point="xbmc.python.pluginsource" library="addon_entry.py">
|
||||
<provides>video</provides>
|
||||
@ -22,10 +21,8 @@
|
||||
<disclaimer lang="en_GB">This add-on is not officially commissioned/supported by SBS Belgium and is provided 'as is' without any warranty of any kind. The Play4, Play5 and Play6 logos are property of SBS Belgium.</disclaimer>
|
||||
<platform>all</platform>
|
||||
<license>GPL-3.0-only</license>
|
||||
<news>v0.4.3 (2021-04-24)
|
||||
- Add support for Play7.
|
||||
- Improve error handling.
|
||||
- Pass a week of EPG data to IPTV Manager.</news>
|
||||
<news>v0.4.11 (2023-07-26)
|
||||
- Fixes for DRM protected VOD.</news>
|
||||
<source>https://github.com/add-ons/plugin.video.viervijfzes</source>
|
||||
<assets>
|
||||
<icon>resources/icon.png</icon>
|
||||
|
@ -4,7 +4,9 @@ pytest
|
||||
pytest-cov
|
||||
pytest-timeout
|
||||
python-dateutil
|
||||
pysocks
|
||||
requests
|
||||
git+git://github.com/dagwieers/kodi-plugin-routing.git@setup#egg=routing
|
||||
git+https://github.com/tamland/kodi-plugin-routing@master#egg=routing
|
||||
six
|
||||
sakee
|
||||
win-inet-pton; platform_system=="Windows"
|
@ -60,6 +60,10 @@ msgstr ""
|
||||
|
||||
|
||||
### SUBMENUS
|
||||
msgctxt "#30052"
|
||||
msgid "Watch live [B]{channel}[/B]"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "#30053"
|
||||
msgid "TV Guide for [B]{channel}[/B]"
|
||||
msgstr ""
|
||||
|
@ -61,6 +61,10 @@ msgstr "Tv-gids"
|
||||
|
||||
|
||||
### SUBMENUS
|
||||
msgctxt "#30052"
|
||||
msgid "Watch live [B]{channel}[/B]"
|
||||
msgstr "Kijk live [B]{channel}[/B]"
|
||||
|
||||
msgctxt "#30053"
|
||||
msgid "TV Guide for [B]{channel}[/B]"
|
||||
msgstr "Tv-gids voor [B]{channel}[/B]"
|
||||
|
@ -160,11 +160,11 @@ def play_epg(channel, timestamp):
|
||||
|
||||
|
||||
@routing.route('/play/catalog')
|
||||
@routing.route('/play/catalog/<uuid>')
|
||||
def play_catalog(uuid=None):
|
||||
@routing.route('/play/catalog/<uuid>/<content_type>')
|
||||
def play_catalog(uuid=None, content_type=None):
|
||||
""" Play the requested item """
|
||||
from resources.lib.modules.player import Player
|
||||
Player().play(uuid)
|
||||
Player().play(uuid, content_type)
|
||||
|
||||
|
||||
@routing.route('/play/page/<page>')
|
||||
|
@ -17,19 +17,20 @@ try: # Python 3
|
||||
from html import unescape
|
||||
except ImportError: # Python 2
|
||||
from HTMLParser import HTMLParser
|
||||
|
||||
unescape = HTMLParser().unescape
|
||||
|
||||
ADDON = xbmcaddon.Addon()
|
||||
|
||||
SORT_METHODS = dict(
|
||||
unsorted=xbmcplugin.SORT_METHOD_UNSORTED,
|
||||
label=xbmcplugin.SORT_METHOD_LABEL_IGNORE_FOLDERS,
|
||||
title=xbmcplugin.SORT_METHOD_TITLE,
|
||||
episode=xbmcplugin.SORT_METHOD_EPISODE,
|
||||
duration=xbmcplugin.SORT_METHOD_DURATION,
|
||||
year=xbmcplugin.SORT_METHOD_VIDEO_YEAR,
|
||||
date=xbmcplugin.SORT_METHOD_DATE,
|
||||
)
|
||||
SORT_METHODS = {
|
||||
'unsorted': xbmcplugin.SORT_METHOD_UNSORTED,
|
||||
'label': xbmcplugin.SORT_METHOD_LABEL_IGNORE_FOLDERS,
|
||||
'title': xbmcplugin.SORT_METHOD_TITLE,
|
||||
'episode': xbmcplugin.SORT_METHOD_EPISODE,
|
||||
'duration': xbmcplugin.SORT_METHOD_DURATION,
|
||||
'year': xbmcplugin.SORT_METHOD_VIDEO_YEAR,
|
||||
'date': xbmcplugin.SORT_METHOD_DATE
|
||||
}
|
||||
DEFAULT_SORT_METHODS = [
|
||||
'unsorted', 'title'
|
||||
]
|
||||
@ -259,12 +260,17 @@ def play(stream, stream_type=STREAM_HLS, license_key=None, title=None, art_dict=
|
||||
elif stream_type == STREAM_DASH:
|
||||
play_item.setProperty('inputstream.adaptive.manifest_type', 'mpd')
|
||||
play_item.setMimeType('application/dash+xml')
|
||||
import inputstreamhelper
|
||||
if license_key is not None:
|
||||
import inputstreamhelper
|
||||
# DRM protected MPEG-DASH
|
||||
is_helper = inputstreamhelper.Helper('mpd', drm='com.widevine.alpha')
|
||||
if is_helper.check_inputstream():
|
||||
play_item.setProperty('inputstream.adaptive.license_type', 'com.widevine.alpha')
|
||||
play_item.setProperty('inputstream.adaptive.license_key', license_key)
|
||||
else:
|
||||
# Unprotected MPEG-DASH
|
||||
is_helper = inputstreamhelper.Helper('mpd')
|
||||
is_helper.check_inputstream()
|
||||
|
||||
play_item.setContentLookup(False)
|
||||
|
||||
@ -464,13 +470,74 @@ def open_settings():
|
||||
|
||||
def get_global_setting(key):
|
||||
"""Get a Kodi setting"""
|
||||
result = jsonrpc(method='Settings.GetSettingValue', params=dict(setting=key))
|
||||
result = jsonrpc(method='Settings.GetSettingValue', params={'setting': key})
|
||||
return result.get('result', {}).get('value')
|
||||
|
||||
|
||||
def set_global_setting(key, value):
|
||||
"""Set a Kodi setting"""
|
||||
return jsonrpc(method='Settings.SetSettingValue', params=dict(setting=key, value=value))
|
||||
return jsonrpc(method='Settings.SetSettingValue', params={'setting': key, 'value': value})
|
||||
|
||||
|
||||
def has_socks():
|
||||
"""Test if socks is installed, and use a static variable to remember"""
|
||||
if hasattr(has_socks, 'cached'):
|
||||
return getattr(has_socks, 'cached')
|
||||
try:
|
||||
import socks # noqa: F401; pylint: disable=unused-variable,unused-import
|
||||
except ImportError:
|
||||
has_socks.cached = False
|
||||
return None # Detect if this is the first run
|
||||
has_socks.cached = True
|
||||
return True
|
||||
|
||||
|
||||
def get_proxies():
|
||||
"""Return a usable proxies dictionary from Kodi proxy settings"""
|
||||
# Use proxy settings from environment variables
|
||||
env_http_proxy = os.environ.get('HTTP_PROXY')
|
||||
env_https_proxy = os.environ.get('HTTPS_PROXY')
|
||||
if env_http_proxy:
|
||||
return {'http': env_http_proxy, 'https': env_https_proxy or env_http_proxy}
|
||||
|
||||
usehttpproxy = get_global_setting('network.usehttpproxy')
|
||||
if usehttpproxy is not True:
|
||||
return None
|
||||
|
||||
try:
|
||||
httpproxytype = int(get_global_setting('network.httpproxytype'))
|
||||
except ValueError:
|
||||
httpproxytype = 0
|
||||
|
||||
socks_supported = has_socks()
|
||||
if httpproxytype != 0 and not socks_supported:
|
||||
# Only open the dialog the first time (to avoid multiple popups)
|
||||
if socks_supported is None:
|
||||
ok_dialog('', localize(30966)) # Requires PySocks
|
||||
return None
|
||||
|
||||
proxy_types = ['http', 'socks4', 'socks4a', 'socks5', 'socks5h']
|
||||
|
||||
proxy = {
|
||||
'scheme': proxy_types[httpproxytype] if 0 <= httpproxytype < 5 else 'http',
|
||||
'server': get_global_setting('network.httpproxyserver'),
|
||||
'port': get_global_setting('network.httpproxyport'),
|
||||
'username': get_global_setting('network.httpproxyusername'),
|
||||
'password': get_global_setting('network.httpproxypassword')
|
||||
}
|
||||
|
||||
if proxy.get('username') and proxy.get('password') and proxy.get('server') and proxy.get('port'):
|
||||
proxy_address = '{scheme}://{username}:{password}@{server}:{port}'.format(**proxy)
|
||||
elif proxy.get('username') and proxy.get('server') and proxy.get('port'):
|
||||
proxy_address = '{scheme}://{username}@{server}:{port}'.format(**proxy)
|
||||
elif proxy.get('server') and proxy.get('port'):
|
||||
proxy_address = '{scheme}://{server}:{port}'.format(**proxy)
|
||||
elif proxy.get('server'):
|
||||
proxy_address = '{scheme}://{server}'.format(**proxy)
|
||||
else:
|
||||
return None
|
||||
|
||||
return {'http': proxy_address, 'https': proxy_address}
|
||||
|
||||
|
||||
def get_cond_visibility(condition):
|
||||
|
@ -4,9 +4,6 @@
|
||||
from __future__ import absolute_import, division, unicode_literals
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
import dateutil.tz
|
||||
|
||||
from resources.lib import kodiutils
|
||||
from resources.lib.kodiutils import TitleItem
|
||||
@ -113,7 +110,7 @@ class Catalog:
|
||||
},
|
||||
info_dict={
|
||||
'tvshowtitle': program.title,
|
||||
'title': kodiutils.localize(30205, season=season.number), # Season {season}
|
||||
'title': kodiutils.localize(30205, season=season.number) if season.number else season.title, # Season {season}
|
||||
'plot': season.description or program.description,
|
||||
'set': program.title,
|
||||
}
|
||||
@ -243,7 +240,8 @@ class Catalog:
|
||||
listing = []
|
||||
for episode in episodes:
|
||||
title_item = Menu.generate_titleitem(episode)
|
||||
title_item.info_dict['title'] = episode.program_title + ' - ' + title_item.title
|
||||
if episode.program_title:
|
||||
title_item.info_dict['title'] = episode.program_title + ' - ' + title_item.title
|
||||
listing.append(title_item)
|
||||
|
||||
for program in programs:
|
||||
@ -252,22 +250,10 @@ class Catalog:
|
||||
kodiutils.show_listing(listing, 30005, content='tvshows')
|
||||
|
||||
def show_mylist(self):
|
||||
""" Show all the programs of all channels """
|
||||
try:
|
||||
mylist, _ = self._auth.get_dataset('myList', 'myList')
|
||||
except Exception as ex:
|
||||
kodiutils.notification(message=str(ex))
|
||||
raise
|
||||
""" Show the programs of My List """
|
||||
mylist = self._api.get_mylist()
|
||||
|
||||
items = []
|
||||
if mylist:
|
||||
for item in mylist:
|
||||
program = self._api.get_program_by_uuid(item.get('id'))
|
||||
if program:
|
||||
program.my_list = True
|
||||
items.append(program)
|
||||
|
||||
listing = [Menu.generate_titleitem(item) for item in items]
|
||||
listing = [Menu.generate_titleitem(item) for item in mylist]
|
||||
|
||||
# Sort items by title
|
||||
# Used for A-Z listing or when movies and episodes are mixed.
|
||||
@ -279,23 +265,7 @@ class Catalog:
|
||||
kodiutils.end_of_directory()
|
||||
return
|
||||
|
||||
mylist, sync_info = self._auth.get_dataset('myList', 'myList')
|
||||
|
||||
if not mylist:
|
||||
mylist = []
|
||||
|
||||
if uuid not in [item.get('id') for item in mylist]:
|
||||
# Python 2.7 doesn't support .timestamp(), and windows doesn't do '%s', so we need to calculate it ourself
|
||||
epoch = datetime(1970, 1, 1, tzinfo=dateutil.tz.gettz('UTC'))
|
||||
now = datetime.now(tz=dateutil.tz.gettz('UTC'))
|
||||
timestamp = int((now - epoch).total_seconds()) * 1000
|
||||
|
||||
mylist.append({
|
||||
'id': uuid,
|
||||
'timestamp': timestamp,
|
||||
})
|
||||
|
||||
self._auth.put_dataset('myList', 'myList', mylist, sync_info)
|
||||
self._api.mylist_add(uuid)
|
||||
|
||||
kodiutils.end_of_directory()
|
||||
|
||||
@ -305,12 +275,6 @@ class Catalog:
|
||||
kodiutils.end_of_directory()
|
||||
return
|
||||
|
||||
mylist, sync_info = self._auth.get_dataset('myList', 'myList')
|
||||
|
||||
if not mylist:
|
||||
mylist = []
|
||||
|
||||
new_mylist = [item for item in mylist if item.get('id') != uuid]
|
||||
self._auth.put_dataset('myList', 'myList', new_mylist, sync_info)
|
||||
self._api.mylist_del(uuid)
|
||||
|
||||
kodiutils.end_of_directory()
|
||||
|
@ -71,9 +71,27 @@ class Channels:
|
||||
|
||||
# Lookup the high resolution logo based on the channel name
|
||||
fanart = '{path}/resources/logos/{logo}'.format(path=kodiutils.addon_path(), logo=channel_info.get('background'))
|
||||
icon = '{path}/resources/logos/{logo}'.format(path=kodiutils.addon_path(), logo=channel_info.get('logo'))
|
||||
|
||||
listing = []
|
||||
|
||||
listing.append(
|
||||
TitleItem(
|
||||
title=kodiutils.localize(30052, channel=channel_info.get('name')), # Watch live {channel}
|
||||
path=kodiutils.url_for('play_live', channel=channel_info.get('name')) + '?.pvr',
|
||||
art_dict={
|
||||
'icon': icon,
|
||||
'fanart': fanart,
|
||||
},
|
||||
info_dict={
|
||||
'plot': kodiutils.localize(30052, channel=channel_info.get('name')), # Watch live {channel}
|
||||
'playcount': 0,
|
||||
'mediatype': 'video',
|
||||
},
|
||||
is_playable=True,
|
||||
)
|
||||
)
|
||||
|
||||
if channel_info.get('epg_id'):
|
||||
listing.append(
|
||||
TitleItem(
|
||||
|
@ -4,7 +4,7 @@
|
||||
from __future__ import absolute_import, division, unicode_literals
|
||||
|
||||
import logging
|
||||
from datetime import timedelta, datetime
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from resources.lib import kodiutils
|
||||
from resources.lib.viervijfzes import CHANNELS
|
||||
@ -42,17 +42,17 @@ class IPTVManager:
|
||||
streams = []
|
||||
for key, channel in CHANNELS.items():
|
||||
if channel.get('iptv_id'):
|
||||
streams.append(dict(
|
||||
id=channel.get('iptv_id'),
|
||||
name=channel.get('name'),
|
||||
logo='special://home/addons/{addon}/resources/logos/{logo}'.format(addon=kodiutils.addon_id(),
|
||||
logo=channel.get('logo')),
|
||||
preset=channel.get('iptv_preset'),
|
||||
stream='plugin://plugin.video.viervijfzes/play/live/{channel}'.format(channel=key),
|
||||
vod='plugin://plugin.video.viervijfzes/play/epg/{channel}/{{date}}'.format(channel=key)
|
||||
))
|
||||
streams.append({
|
||||
'id': channel.get('iptv_id'),
|
||||
'name': channel.get('name'),
|
||||
'logo': 'special://home/addons/{addon}/resources/logos/{logo}'.format(addon=kodiutils.addon_id(),
|
||||
logo=channel.get('logo')),
|
||||
'preset': channel.get('iptv_preset'),
|
||||
'stream': 'plugin://plugin.video.viervijfzes/play/live/{channel}'.format(channel=key),
|
||||
'vod': 'plugin://plugin.video.viervijfzes/play/epg/{channel}/{{date}}'.format(channel=key)
|
||||
})
|
||||
|
||||
return dict(version=1, streams=streams)
|
||||
return {'version': 1, 'streams': streams}
|
||||
|
||||
@via_socket
|
||||
def send_epg(): # pylint: disable=no-method-argument
|
||||
@ -78,20 +78,21 @@ class IPTVManager:
|
||||
epg = epg_api.get_epg(key, date.strftime('%Y-%m-%d'))
|
||||
|
||||
results[iptv_id].extend([
|
||||
dict(
|
||||
start=program.start.isoformat(),
|
||||
stop=(program.start + timedelta(seconds=program.duration)).isoformat(),
|
||||
title=program.program_title,
|
||||
subtitle=program.episode_title,
|
||||
description=program.description,
|
||||
episode='S%sE%s' % (program.season, program.number) if program.season and program.number else None,
|
||||
genre=program.genre,
|
||||
genre_id=program.genre_id,
|
||||
image=program.thumb,
|
||||
stream=kodiutils.url_for('play_from_page',
|
||||
channel=key,
|
||||
page=quote(program.video_url, safe='')) if program.video_url else None)
|
||||
{
|
||||
'start': program.start.isoformat(),
|
||||
'stop': (program.start + timedelta(seconds=program.duration)).isoformat(),
|
||||
'title': program.program_title,
|
||||
'subtitle': program.episode_title,
|
||||
'description': program.description,
|
||||
'episode': 'S%sE%s' % (program.season, program.number) if program.season and program.number else None,
|
||||
'genre': program.genre,
|
||||
'genre_id': program.genre_id,
|
||||
'image': program.thumb,
|
||||
'stream': kodiutils.url_for('play_from_page',
|
||||
channel=key,
|
||||
page=quote(program.video_url, safe='')) if program.video_url else None
|
||||
}
|
||||
for program in epg if program.duration
|
||||
])
|
||||
|
||||
return dict(version=1, epg=results)
|
||||
return {'version': 1, 'epg': results}
|
||||
|
@ -31,68 +31,68 @@ class Menu:
|
||||
TitleItem(
|
||||
title=kodiutils.localize(30001), # A-Z
|
||||
path=kodiutils.url_for('show_catalog'),
|
||||
art_dict=dict(
|
||||
icon='DefaultMovieTitle.png',
|
||||
fanart=kodiutils.get_addon_info('fanart'),
|
||||
),
|
||||
info_dict=dict(
|
||||
plot=kodiutils.localize(30002),
|
||||
)
|
||||
art_dict={
|
||||
'icon': 'DefaultMovieTitle.png',
|
||||
'fanart': kodiutils.get_addon_info('fanart')
|
||||
},
|
||||
info_dict={
|
||||
'plot': kodiutils.localize(30002)
|
||||
}
|
||||
),
|
||||
TitleItem(
|
||||
title=kodiutils.localize(30007), # TV Channels
|
||||
path=kodiutils.url_for('show_channels'),
|
||||
art_dict=dict(
|
||||
icon='DefaultAddonPVRClient.png',
|
||||
fanart=kodiutils.get_addon_info('fanart'),
|
||||
),
|
||||
info_dict=dict(
|
||||
plot=kodiutils.localize(30008),
|
||||
)
|
||||
art_dict={
|
||||
'icon': 'DefaultAddonPVRClient.png',
|
||||
'fanart': kodiutils.get_addon_info('fanart')
|
||||
},
|
||||
info_dict={
|
||||
'plot': kodiutils.localize(30008)
|
||||
}
|
||||
),
|
||||
TitleItem(
|
||||
title=kodiutils.localize(30003), # Catalog
|
||||
path=kodiutils.url_for('show_categories'),
|
||||
art_dict=dict(
|
||||
icon='DefaultGenre.png',
|
||||
fanart=kodiutils.get_addon_info('fanart'),
|
||||
),
|
||||
info_dict=dict(
|
||||
plot=kodiutils.localize(30004),
|
||||
)
|
||||
art_dict={
|
||||
'icon': 'DefaultGenre.png',
|
||||
'fanart': kodiutils.get_addon_info('fanart')
|
||||
},
|
||||
info_dict={
|
||||
'plot': kodiutils.localize(30004)
|
||||
}
|
||||
),
|
||||
TitleItem(
|
||||
title=kodiutils.localize(30005), # Recommendations
|
||||
path=kodiutils.url_for('show_recommendations'),
|
||||
art_dict=dict(
|
||||
icon='DefaultFavourites.png',
|
||||
fanart=kodiutils.get_addon_info('fanart'),
|
||||
),
|
||||
info_dict=dict(
|
||||
plot=kodiutils.localize(30006),
|
||||
)
|
||||
art_dict={
|
||||
'icon': 'DefaultFavourites.png',
|
||||
'fanart': kodiutils.get_addon_info('fanart')
|
||||
},
|
||||
info_dict={
|
||||
'plot': kodiutils.localize(30006)
|
||||
}
|
||||
),
|
||||
TitleItem(
|
||||
title=kodiutils.localize(30011), # My List
|
||||
path=kodiutils.url_for('show_mylist'),
|
||||
art_dict=dict(
|
||||
icon='DefaultPlaylist.png',
|
||||
fanart=kodiutils.get_addon_info('fanart'),
|
||||
),
|
||||
info_dict=dict(
|
||||
plot=kodiutils.localize(30012),
|
||||
)
|
||||
art_dict={
|
||||
'icon': 'DefaultPlaylist.png',
|
||||
'fanart': kodiutils.get_addon_info('fanart')
|
||||
},
|
||||
info_dict={
|
||||
'plot': kodiutils.localize(30012)
|
||||
}
|
||||
),
|
||||
TitleItem(
|
||||
title=kodiutils.localize(30009), # Search
|
||||
path=kodiutils.url_for('show_search'),
|
||||
art_dict=dict(
|
||||
icon='DefaultAddonsSearch.png',
|
||||
fanart=kodiutils.get_addon_info('fanart'),
|
||||
),
|
||||
info_dict=dict(
|
||||
plot=kodiutils.localize(30010),
|
||||
)
|
||||
art_dict={
|
||||
'icon': 'DefaultAddonsSearch.png',
|
||||
'fanart': kodiutils.get_addon_info('fanart')
|
||||
},
|
||||
info_dict={
|
||||
'plot': kodiutils.localize(30010)
|
||||
}
|
||||
)
|
||||
]
|
||||
|
||||
@ -183,7 +183,7 @@ class Menu:
|
||||
|
||||
if item.uuid:
|
||||
# We have an UUID and can play this item directly
|
||||
path = kodiutils.url_for('play_catalog', uuid=item.uuid)
|
||||
path = kodiutils.url_for('play_catalog', uuid=item.uuid, content_type=item.content_type)
|
||||
else:
|
||||
# We don't have an UUID, and first need to fetch the video information from the page
|
||||
path = kodiutils.url_for('play_from_page', page=quote(item.path, safe=''))
|
||||
|
@ -12,11 +12,6 @@ from resources.lib.viervijfzes.auth import AuthApi
|
||||
from resources.lib.viervijfzes.aws.cognito_idp import AuthenticationException, InvalidLoginException
|
||||
from resources.lib.viervijfzes.content import CACHE_PREVENT, ContentApi, GeoblockedException, UnavailableException
|
||||
|
||||
try: # Python 3
|
||||
from urllib.parse import quote, urlencode
|
||||
except ImportError: # Python 2
|
||||
from urllib import quote, urlencode
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -31,8 +26,7 @@ class Player:
|
||||
# Workaround for Raspberry Pi 3 and older
|
||||
kodiutils.set_global_setting('videoplayer.useomxplayer', True)
|
||||
|
||||
@staticmethod
|
||||
def live(channel):
|
||||
def live(self, channel):
|
||||
""" Play the live channel.
|
||||
:type channel: string
|
||||
"""
|
||||
@ -43,9 +37,9 @@ class Player:
|
||||
# self.play_from_page(broadcast.video_url)
|
||||
# return
|
||||
|
||||
channel_name = CHANNELS.get(channel, dict(name=channel))
|
||||
kodiutils.ok_dialog(message=kodiutils.localize(30718, channel=channel_name.get('name'))) # There is no live stream available for {channel}.
|
||||
kodiutils.end_of_directory()
|
||||
channel_url = CHANNELS.get(channel, {'url': channel}).get('url')
|
||||
|
||||
self.play_from_page(channel_url)
|
||||
|
||||
def play_from_page(self, path):
|
||||
""" Play the requested item.
|
||||
@ -74,51 +68,36 @@ class Player:
|
||||
|
||||
if episode.uuid:
|
||||
# Lookup the stream
|
||||
resolved_stream = self._resolve_stream(episode.uuid)
|
||||
resolved_stream = self._resolve_stream(episode.uuid, episode.content_type)
|
||||
_LOGGER.debug('Resolved stream: %s', resolved_stream)
|
||||
|
||||
if resolved_stream:
|
||||
titleitem = Menu.generate_titleitem(episode)
|
||||
if resolved_stream.license_url:
|
||||
# Generate license key
|
||||
license_key = self.create_license_key(resolved_stream.license_url,
|
||||
key_headers=dict(
|
||||
customdata=resolved_stream.auth,
|
||||
))
|
||||
else:
|
||||
license_key = None
|
||||
|
||||
kodiutils.play(resolved_stream.url,
|
||||
resolved_stream.stream_type,
|
||||
license_key,
|
||||
resolved_stream.license_key,
|
||||
info_dict=titleitem.info_dict,
|
||||
art_dict=titleitem.art_dict,
|
||||
prop_dict=titleitem.prop_dict)
|
||||
|
||||
def play(self, uuid):
|
||||
def play(self, uuid, content_type):
|
||||
""" Play the requested item.
|
||||
:type uuid: string
|
||||
:type content_type: string
|
||||
"""
|
||||
if not uuid:
|
||||
kodiutils.ok_dialog(message=kodiutils.localize(30712)) # The video is unavailable...
|
||||
return
|
||||
|
||||
# Lookup the stream
|
||||
resolved_stream = self._resolve_stream(uuid)
|
||||
if resolved_stream.license_url:
|
||||
# Generate license key
|
||||
license_key = self.create_license_key(resolved_stream.license_url, key_headers=dict(
|
||||
customdata=resolved_stream.auth,
|
||||
))
|
||||
else:
|
||||
license_key = None
|
||||
|
||||
kodiutils.play(resolved_stream.url, resolved_stream.stream_type, license_key)
|
||||
resolved_stream = self._resolve_stream(uuid, content_type)
|
||||
kodiutils.play(resolved_stream.url, resolved_stream.stream_type, resolved_stream.license_key)
|
||||
|
||||
@staticmethod
|
||||
def _resolve_stream(uuid):
|
||||
def _resolve_stream(uuid, content_type):
|
||||
""" Resolve the stream for the requested item
|
||||
:type uuid: string
|
||||
:type content_type: string
|
||||
"""
|
||||
try:
|
||||
# Check if we have credentials
|
||||
@ -135,7 +114,7 @@ class Player:
|
||||
auth = AuthApi(kodiutils.get_setting('username'), kodiutils.get_setting('password'), kodiutils.get_tokens_path())
|
||||
|
||||
# Get stream information
|
||||
resolved_stream = ContentApi(auth).get_stream_by_uuid(uuid)
|
||||
resolved_stream = ContentApi(auth).get_stream_by_uuid(uuid, content_type)
|
||||
return resolved_stream
|
||||
|
||||
except (InvalidLoginException, AuthenticationException) as ex:
|
||||
@ -151,26 +130,3 @@ class Player:
|
||||
except UnavailableException:
|
||||
kodiutils.ok_dialog(message=kodiutils.localize(30712)) # The video is unavailable...
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def create_license_key(key_url, key_type='R', key_headers=None, key_value=None):
|
||||
""" Create a license key string that we need for inputstream.adaptive.
|
||||
|
||||
:param str key_url:
|
||||
:param str key_type:
|
||||
:param dict[str, str] key_headers:
|
||||
:param str key_value:
|
||||
:rtype: str
|
||||
"""
|
||||
header = ''
|
||||
if key_headers:
|
||||
header = urlencode(key_headers)
|
||||
|
||||
if key_type in ('A', 'R', 'B'):
|
||||
key_value = key_type + '{SSM}'
|
||||
elif key_type == 'D':
|
||||
if 'D{SSM}' not in key_value:
|
||||
raise ValueError('Missing D{SSM} placeholder')
|
||||
key_value = quote(key_value)
|
||||
|
||||
return '%s|%s|%s|' % (key_url, header, key_value)
|
||||
|
@ -125,7 +125,7 @@ class KodiPlayer(Player):
|
||||
if not self.av_started:
|
||||
# Check stream path
|
||||
import requests
|
||||
response = requests.get(self.stream_path)
|
||||
response = requests.get(self.stream_path, timeout=5)
|
||||
if response.status_code == 403:
|
||||
message_id = 30720
|
||||
else:
|
||||
|
@ -5,68 +5,59 @@ from __future__ import absolute_import, division, unicode_literals
|
||||
from collections import OrderedDict
|
||||
|
||||
CHANNELS = OrderedDict([
|
||||
('Play4', dict(
|
||||
name='Play4',
|
||||
epg_id='vier',
|
||||
logo='play4.png',
|
||||
background='play4-background.png',
|
||||
iptv_preset=4,
|
||||
iptv_id='play4.be',
|
||||
youtube=[
|
||||
dict(
|
||||
label='GoPlay',
|
||||
logo='goplay.png',
|
||||
path='plugin://plugin.video.youtube/user/viertv/',
|
||||
),
|
||||
],
|
||||
)),
|
||||
('Play5', dict(
|
||||
name='Play5',
|
||||
epg_id='vijf',
|
||||
logo='play5.png',
|
||||
background='play5-background.png',
|
||||
iptv_preset=5,
|
||||
iptv_id='play5.be',
|
||||
youtube=[
|
||||
dict(
|
||||
label='GoPlay',
|
||||
logo='goplay.png',
|
||||
path='plugin://plugin.video.youtube/user/viertv/',
|
||||
),
|
||||
],
|
||||
)),
|
||||
('Play6', dict(
|
||||
name='Play6',
|
||||
epg_id='zes',
|
||||
logo='play6.png',
|
||||
background='play6-background.png',
|
||||
iptv_preset=6,
|
||||
iptv_id='play6.be',
|
||||
youtube=[
|
||||
dict(
|
||||
label='GoPlay',
|
||||
logo='goplay.png',
|
||||
path='plugin://plugin.video.youtube/user/viertv/',
|
||||
),
|
||||
],
|
||||
)),
|
||||
('Play7', dict(
|
||||
name='Play7',
|
||||
epg_id='zeven',
|
||||
url='https://www.goplay.be',
|
||||
logo='play7.png',
|
||||
background='play7-background.png',
|
||||
iptv_preset=17,
|
||||
iptv_id='play7.be',
|
||||
youtube=[],
|
||||
)),
|
||||
('GoPlay', dict(
|
||||
name='Go Play',
|
||||
url='https://www.goplay.be',
|
||||
logo='goplay.png',
|
||||
background='goplay-background.png',
|
||||
youtube=[],
|
||||
))
|
||||
('Play4', {
|
||||
'name': 'Play4',
|
||||
'url': 'live-kijken/play-4',
|
||||
'epg_id': 'vier',
|
||||
'logo': 'play4.png',
|
||||
'background': 'play4-background.png',
|
||||
'iptv_preset': 4,
|
||||
'iptv_id': 'play4.be',
|
||||
'youtube': [
|
||||
{'label': 'GoPlay', 'logo': 'goplay.png', 'path': 'plugin://plugin.video.youtube/user/viertv/'},
|
||||
]
|
||||
}),
|
||||
('Play5', {
|
||||
'name': 'Play5',
|
||||
'url': 'live-kijken/play-5',
|
||||
'epg_id': 'vijf',
|
||||
'logo': 'play5.png',
|
||||
'background': 'play5-background.png',
|
||||
'iptv_preset': 5,
|
||||
'iptv_id': 'play5.be',
|
||||
'youtube': [
|
||||
{'label': 'GoPlay', 'logo': 'goplay.png', 'path': 'plugin://plugin.video.youtube/user/viertv/'},
|
||||
]
|
||||
}),
|
||||
('Play6', {
|
||||
'name': 'Play6',
|
||||
'url': 'live-kijken/play-6',
|
||||
'epg_id': 'zes',
|
||||
'logo': 'play6.png',
|
||||
|