Skip to content

Update 0.7.3 #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 46 commits into from
Feb 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
1984caa
update
superolmo May 22, 2024
4d50da6
Removed test
superolmo May 22, 2024
e3b1774
Update
superolmo May 22, 2024
0e198f6
Update
superolmo May 22, 2024
3375767
Update
superolmo May 22, 2024
cfe9b19
Updated docs
superolmo May 22, 2024
16d1235
Update
superolmo May 22, 2024
155d46c
Merge branch 'main' into development
superolmo May 22, 2024
b8bff9b
Moved doc to docs
superolmo May 22, 2024
2e40260
Merge branch 'main' into development
superolmo May 22, 2024
1b989f7
Merge branch 'main' into development
superolmo Sep 2, 2024
18e3818
More adjustments
superolmo Sep 2, 2024
cf88dba
Removed commented code
superolmo Sep 2, 2024
0246a00
More fixes
superolmo Sep 2, 2024
1429cfc
Added URL
superolmo Sep 2, 2024
5b249b0
More fixes
superolmo Sep 2, 2024
c814172
Final updates
superolmo Dec 17, 2024
e933df5
Final
superolmo Dec 20, 2024
ae3da0c
Retry
superolmo Dec 20, 2024
f1ea84d
More updates
superolmo Feb 17, 2025
5ba3724
Merge commit 'e14a37a2be5cb57785867ad48dd7e4f4e193e89b' into development
superolmo Feb 17, 2025
8aac7d4
Fixed button
superolmo Feb 17, 2025
6881655
Fixed Functional Test
superolmo Feb 17, 2025
14ec4f4
Updated 0.7.3 change log
superolmo Feb 17, 2025
a62102c
Updated docs
superolmo Feb 17, 2025
9f6adce
Merge branch 'main' into development
superolmo Feb 17, 2025
4beb95f
Updated pytest workflow
superolmo Feb 17, 2025
ccf5624
Updated pytest workflow
superolmo Feb 17, 2025
57f85b0
Updated pytest workflow
superolmo Feb 17, 2025
bdd5ce2
Updated pytest workflow
superolmo Feb 17, 2025
d514f8d
Updated pytest workflow
superolmo Feb 17, 2025
eb11650
Updated pytest workflow
superolmo Feb 17, 2025
4744774
Fixed misspellings
superolmo Feb 18, 2025
87cb8bc
Updated python for testing
superolmo Feb 18, 2025
27e688f
Fixing Workflow
superolmo Feb 18, 2025
287a7b7
Multiversions of Python
superolmo Feb 18, 2025
655960c
Add flake8 checker
superolmo Feb 18, 2025
73b13ae
Fixed flake8 errors
superolmo Feb 18, 2025
68d782e
Flake8 fixes
superolmo Feb 18, 2025
2f9d7a0
Fixed yaml
superolmo Feb 18, 2025
7b248dd
More flake8 fixes
superolmo Feb 18, 2025
1c3ff8f
Added download progress
superolmo Feb 20, 2025
05c2517
Updated README.md
superolmo Feb 20, 2025
e511a87
Updated version
superolmo Feb 21, 2025
43b40f7
Documentation
superolmo Feb 23, 2025
12943bb
Updated extra info
superolmo Feb 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions .github/workflows/run_pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,24 @@ jobs:
build:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: "3.10"
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r flake8 pytest pytest-cov pdoc
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
pip install flake8 pytest pytest-cov pdoc
if [ -f test/requirements.txt ]; then pip install -r test/requirements.txt; fi
- name: Check Syntax with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
flake8 --extend-ignore=E501 pyxtream/pyxtream.py pyxtream/rest_api.py pyxtream/schemaValidator.py pyxtream/version.py pyxtream/progress.py
- name: Test with pytest
run: |
pytest --cov=pyxtream pyxtream
python3 -m pytest --cov=pyxtream test/test_pyxtream.py
4 changes: 3 additions & 1 deletion PYPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

```shell
poetry lock
poetry install --sync
poetry sync
poetry debug resolve
```

Expand Down Expand Up @@ -36,6 +36,8 @@ poetry publish -u __token__ -p <token>

# Upload to PYPI

References: https://www.digitalocean.com/community/tutorials/how-to-publish-python-packages-to-pypi-using-poetry-on-ubuntu-22-04

```shell
poetry publish
```
Expand Down
41 changes: 24 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

PyXtream loads the xtream IPTV content from a provider server. Groups, Channels, Series are all organized in dictionaries. Season and Episodes are retrieved as needed. It includes functions for searching streams and downloading.

This library was originally designed to work with Hypnotix at https://github.com/linuxmint/hypnotix
This library was originally designed to work with Hypnotix at https://github.com/linuxmint/hypnotix, so its compatibility with Hypnotix takes precedence.

# Installing

Expand Down Expand Up @@ -34,41 +34,33 @@ else:
print("Could not connect")
```

Once completed, all the data can be found in xTream.groups, xTream.channels, xTream.movies, xTream.series. Series do not contains the information for all the Seasons and Episodes. Those are loaded separately when needed by calling the following function using a Series object from xTream.series array of dictionaries.
Once completed, all the data can be found in `xTream.groups`, `xTream.channels`, `xTream.movies`, `xTream.series`. Series do not contains the information for all the Seasons and Episodes. Those are loaded separately when needed by calling the following function using a Series object from `xTream.series` array of dictionaries.

```python
xt.get_series_info_by_id(series_obj)
```

At this point, the series_obj will have both Seasons and Episodes populated.

If you have installed Flask, the REST Api will be turned ON automatically. At this point, there is no method to turn it off. Maybe in a future version.
At this point, the `series_obj` will have both Seasons and Episodes populated.

## Functional Test

Please modify the functional_test.py file with your provider information, then start the application.
Please modify the `functional_test.py` file with your provider information, then start the application.

```shell
python3 functional_test.py
```

The functional test will allow you to authenticate on startup, load and search streams. If Flask is installed, a simple website will be available at http://localhost:5000 to allow you to search and play streams.

## Interesting Work by somebody else

- xtreamPOC - https://github.com/sght500/xtreamPOC - Project is a Proof of Concept (POC) that leverages pyxtream, MPV, and NiceGUI to demonstrate the use of Xtream Portal Codes.

So far there is no ready to use Transport Stream library for playing live stream.
## Applications using PyXtream

- This is the library to convert TS to MP4
- https://github.com/videojs/mux.js/
Applications using PyXtream PYPI package

- More on above, but same problem. XMLHttpRequest waits until the whole TS file is completely loaded. It does not work for live video streams
- https://developpaper.com/play-ts-video-directly-on-the-web/
- xtreamPOC - https://github.com/sght500/xtreamPOC - Project is a Proof of Concept (POC) that leverages pyxtream, MPV, and NiceGUI to demonstrate the use of Xtream Portal Codes.

- This below will allow me to process chunks of data
- https://stackoverflow.com/questions/37402716/handle-xmlhttprequest-response-with-large-data
Applications using PyXtream files

- Hypnotix - https://github.com/linuxmint/hypnotix - Hypnotix is an IPTV streaming application with support for live TV, movies and series.

# API

Expand Down Expand Up @@ -106,6 +98,7 @@ xTream.movies[{},{},...]
- xTream.allEpg()

# Versioning
Follows the Semantic Versioning from https://semver.org/
- Increment the MAJOR version when you make incompatible API changes.
- Increment the MINOR version when you add functionality in a backwards-compatible manner.
- Increment the PATCH version when you make backwards-compatible bug fixes.
Expand All @@ -114,6 +107,7 @@ xTream.movies[{},{},...]

| Date | Version | Description |
| ----------- | -----| ----------- |
| 2025-02-17 | 0.7.3 | - Added Initial PyTest and Coverage<br>- Added timestamp field "added" to Series to match channels "added" field<br>- Added string field "url" to Series to quickly get the series download address<br>- Added new API "get_last_7days()" returns the last added streams in the last 7 days in JSON format<br>- Added new API "get_download_progress()" returns information on the current download stream in JSON format<br>- Changed internal function _load_series_info_by_id_from_provider to allow returned value to change to JSON<br>- Changed search_stream function to only search in specific collections<br>- Refactored "rest_api.py" to make it easier to extend in the future<br>- Added new rest API<br>- Changed to Poetry environment<br>- Changed Functional Test to test loading series information<br>- Changed sample index.html to test more features|
| 2024-09-02 | 0.7.2 | - Added missing request package to setup.py<br>- Refactored the search stream function and now, it can search for a specific stream type<br>- Refactored the download stream function<br>- Refactored the _get_request function and removed the call to the sleep function<br>- Added functional test to get series json output from a series_id<br>- Added functional test to get EPG for a specific stream ID<br>- Added xtream account expiration date printed on the console during authentication<br>- Improved results with the Flask HTML page and differentiating between movies and series<br>- Improved code readability|
| 2024-05-21 | 0.7.1 | - Fixed missing jsonschema package<br>- Fixed provider name in functional_test<br>- Improved print out of connection attempts<br>- Added method to read latest changes in functional_test
| 2023-11-08 | 0.7.0 | - Added Schema Validator<br>- Added Channel Age<br>- Added list of movies added in the last 30 and 7 days<br>- Updated code based on PyLint<br>- Fixed Flask package to be optional [richard-de-vos](https://github.com/richard-de-vos)|
Expand All @@ -126,3 +120,16 @@ xTream.movies[{},{},...]
| 2021-06-05 | 0.1.2 | - Fixed Server Name |
| 2021-06-04 | 0.1.1 | - Updated README.md |
| 2021-06-04 | 0.1.0 | - Initial Release |

## Interesting content that could be used for future development

So far there is no ready to use Transport Stream library for playing live stream.

- This is the library to convert TS to MP4
- https://github.com/videojs/mux.js/

- More on above, but same problem. XMLHttpRequest waits until the whole TS file is completely loaded. It does not work for live video streams
- https://developpaper.com/play-ts-video-directly-on-the-web/

- This below will allow me to process chunks of data
- https://stackoverflow.com/questions/37402716/handle-xmlhttprequest-response-with-large-data
8 changes: 4 additions & 4 deletions docs/pyxtream.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ <h1 class="modulename">

<label class="view-source-button" for="mod-pyxtream-view-source"><span>View Source</span></label>

<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos">1</span></a><span class="kn">from</span> <span class="nn">.progress</span> <span class="kn">import</span> <span class="n">progress</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos">2</span></a><span class="kn">from</span> <span class="nn">.pyxtream</span> <span class="kn">import</span> <span class="n">XTream</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos">1</span></a><span class="kn">from</span><span class="w"> </span><span class="nn">.progress</span><span class="w"> </span><span class="kn">import</span> <span class="n">progress</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos">2</span></a><span class="kn">from</span><span class="w"> </span><span class="nn">.pyxtream</span><span class="w"> </span><span class="kn">import</span> <span class="n">XTream</span><span class="p">,</span> <span class="n">Channel</span><span class="p">,</span> <span class="n">Group</span><span class="p">,</span> <span class="n">Serie</span><span class="p">,</span> <span class="n">Episode</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos">3</span></a>
</span><span id="L-4"><a href="#L-4"><span class="linenos">4</span></a><span class="k">try</span><span class="p">:</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos">5</span></a> <span class="kn">from</span> <span class="nn">.rest_api</span> <span class="kn">import</span> <span class="n">FlaskWrap</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos">5</span></a> <span class="kn">from</span><span class="w"> </span><span class="nn">.rest_api</span><span class="w"> </span><span class="kn">import</span> <span class="n">FlaskWrap</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos">6</span></a> <span class="n">USE_FLASK</span> <span class="o">=</span> <span class="kc">True</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos">7</span></a><span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
</span><span id="L-8"><a href="#L-8"><span class="linenos">8</span></a> <span class="n">USE_FLASK</span> <span class="o">=</span> <span class="kc">False</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos">9</span></a><span class="kn">from</span> <span class="nn">.version</span> <span class="kn">import</span> <span class="n">__author__</span><span class="p">,</span> <span class="n">__author_email__</span><span class="p">,</span> <span class="n">__version__</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos">9</span></a><span class="kn">from</span><span class="w"> </span><span class="nn">.version</span><span class="w"> </span><span class="kn">import</span> <span class="n">__author__</span><span class="p">,</span> <span class="n">__author_email__</span><span class="p">,</span> <span class="n">__version__</span>
</span></pre></div>


Expand Down
26 changes: 13 additions & 13 deletions docs/pyxtream/progress.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,26 +57,26 @@ <h1 class="modulename">
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos"> 1</span></a><span class="c1"># The MIT License (MIT)</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a><span class="c1"># Copyright (c) 2016 Vladimir Ignatev</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="c1">#</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="c1"># Permission is hereby granted, free of charge, to any person obtaining </span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="c1"># a copy of this software and associated documentation files (the &quot;Software&quot;), </span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="c1"># to deal in the Software without restriction, including without limitation </span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="c1"># the rights to use, copy, modify, merge, publish, distribute, sublicense, </span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="c1"># and/or sell copies of the Software, and to permit persons to whom the Software </span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="c1"># Permission is hereby granted, free of charge, to any person obtaining</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="c1"># a copy of this software and associated documentation files (the &quot;Software&quot;),</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="c1"># to deal in the Software without restriction, including without limitation</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="c1"># the rights to use, copy, modify, merge, publish, distribute, sublicense,</span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="c1"># and/or sell copies of the Software, and to permit persons to whom the Software</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="c1"># is furnished to do so, subject to the following conditions:</span>
</span><span id="L-10"><a href="#L-10"><span class="linenos">10</span></a><span class="c1"># </span>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="c1"># The above copyright notice and this permission notice shall be included </span>
</span><span id="L-10"><a href="#L-10"><span class="linenos">10</span></a><span class="c1">#</span>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="c1"># The above copyright notice and this permission notice shall be included</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a><span class="c1"># in all copies or substantial portions of the Software.</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a><span class="c1">#</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a><span class="c1"># THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, </span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a><span class="c1"># INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR </span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a><span class="c1"># THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a><span class="c1"># INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a><span class="c1"># PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a><span class="c1"># FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a><span class="c1"># OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE </span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a><span class="c1"># OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a><span class="c1"># OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a><span class="kn">import</span> <span class="nn">sys</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a><span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a><span class="k">def</span> <span class="nf">progress</span><span class="p">(</span><span class="n">count</span><span class="p">,</span> <span class="n">total</span><span class="p">,</span> <span class="n">status</span><span class="o">=</span><span class="s1">&#39;&#39;</span><span class="p">):</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a><span class="k">def</span><span class="w"> </span><span class="nf">progress</span><span class="p">(</span><span class="n">count</span><span class="p">,</span> <span class="n">total</span><span class="p">,</span> <span class="n">status</span><span class="o">=</span><span class="s1">&#39;&#39;</span><span class="p">):</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a> <span class="n">bar_len</span> <span class="o">=</span> <span class="mi">60</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a> <span class="n">filled_len</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">bar_len</span> <span class="o">*</span> <span class="n">count</span> <span class="o">/</span> <span class="nb">float</span><span class="p">(</span><span class="n">total</span><span class="p">)))</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</span></a>
Expand All @@ -100,7 +100,7 @@ <h1 class="modulename">

</div>
<a class="headerlink" href="#progress"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="progress-24"><a href="#progress-24"><span class="linenos">24</span></a><span class="k">def</span> <span class="nf">progress</span><span class="p">(</span><span class="n">count</span><span class="p">,</span> <span class="n">total</span><span class="p">,</span> <span class="n">status</span><span class="o">=</span><span class="s1">&#39;&#39;</span><span class="p">):</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="progress-24"><a href="#progress-24"><span class="linenos">24</span></a><span class="k">def</span><span class="w"> </span><span class="nf">progress</span><span class="p">(</span><span class="n">count</span><span class="p">,</span> <span class="n">total</span><span class="p">,</span> <span class="n">status</span><span class="o">=</span><span class="s1">&#39;&#39;</span><span class="p">):</span>
</span><span id="progress-25"><a href="#progress-25"><span class="linenos">25</span></a> <span class="n">bar_len</span> <span class="o">=</span> <span class="mi">60</span>
</span><span id="progress-26"><a href="#progress-26"><span class="linenos">26</span></a> <span class="n">filled_len</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">bar_len</span> <span class="o">*</span> <span class="n">count</span> <span class="o">/</span> <span class="nb">float</span><span class="p">(</span><span class="n">total</span><span class="p">)))</span>
</span><span id="progress-27"><a href="#progress-27"><span class="linenos">27</span></a>
Expand Down
Loading