Merge branch 'master' into pr/14244

pull/14244/head
freearhey 2 years ago
commit a63f30db54

@ -0,0 +1,62 @@
name: format
on:
workflow_dispatch:
# pull_request:
# types:
# - closed
jobs:
main:
# if: ${{ github.event.pull_request.merged == true }}
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- uses: getsentry/action-github-app-token@v2
if: ${{ !env.ACT }}
id: create-app-token
with:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}
- uses: actions/checkout@v3
if: ${{ !env.ACT }}
with:
fetch-depth: 2
token: ${{ steps.create-app-token.outputs.token }}
- name: setup git
run: |
git config user.name "iptv-bot[bot]"
git config user.email "84861620+iptv-bot[bot]@users.noreply.github.com"
- uses: tj-actions/changed-files@v35
id: files
with:
files: streams/*.m3u
- name: download data from api
run: |
mkdir -p temp/data
curl -L -o temp/data/blocklist.json https://iptv-org.github.io/api/blocklist.json
curl -L -o temp/data/channels.json https://iptv-org.github.io/api/channels.json
- uses: actions/setup-node@v3
if: ${{ !env.ACT }}
with:
node-version: 18
cache: 'npm'
- name: install dependencies
run: npm install
- name: format internal playlists
run: npm run playlist:format
- name: check internal playlists
run: |
npm run playlist:lint
npm run playlist:validate
- run: git status
- name: commit changes to /streams
run: |
git add streams
git status
git commit -m "[Bot] Format /streams" -m "Committed by [iptv-bot](https://github.com/apps/iptv-bot) via [format](https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }}) workflow." --no-verify
- name: push all changes to the repository
if: ${{ !env.ACT && github.ref == 'refs/heads/master' }}
run: git push

@ -6,11 +6,9 @@ on:
jobs: jobs:
main: main:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: write
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: getsentry/action-github-app-token@v2 - uses: tibdex/github-app-token@v2
if: ${{ !env.ACT }} if: ${{ !env.ACT }}
id: create-app-token id: create-app-token
with: with:
@ -33,8 +31,6 @@ jobs:
run: npm install run: npm install
- name: load api data - name: load api data
run: npm run api:load run: npm run api:load
- name: setup database
run: npm run db:create
- name: update internal playlists - name: update internal playlists
run: npm run playlist:update --silent >> $GITHUB_OUTPUT run: npm run playlist:update --silent >> $GITHUB_OUTPUT
id: playlist-update id: playlist-update

@ -123,21 +123,22 @@ For scripts to work, you must have [Node.js](https://nodejs.org/en) installed on
To run scripts use the `npm run <script-name>` command. To run scripts use the `npm run <script-name>` command.
- `act:check`: allows to run the [check](https://github.com/iptv-org/iptv/blob/master/.github/workflows/check.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act). - `act:check`: allows to run the [check](https://github.com/iptv-org/iptv/blob/master/.github/workflows/check.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act).
- `act:format`: allows to test the [format](https://github.com/iptv-org/iptv/blob/master/.github/workflows/update.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act).
- `act:update`: allows to test the [update](https://github.com/iptv-org/iptv/blob/master/.github/workflows/update.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act). - `act:update`: allows to test the [update](https://github.com/iptv-org/iptv/blob/master/.github/workflows/update.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act).
- `api:load`: downloads the latest channel and stream data from the [iptv-org/api](https://github.com/iptv-org/api). - `api:load`: downloads the latest channel and stream data from the [iptv-org/api](https://github.com/iptv-org/api).
- `api:generate`: generates a JSON file with all streams for the [iptv-org/api](https://github.com/iptv-org/api) repository. - `api:generate`: generates a JSON file with all streams for the [iptv-org/api](https://github.com/iptv-org/api) repository.
- `api:deploy`: allows to manually upload a JSON file created via `api:generate` to the [iptv-org/api](https://github.com/iptv-org/api) repository. To run the script you must provide your [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with write access to the repository. - `api:deploy`: allows to manually upload a JSON file created via `api:generate` to the [iptv-org/api](https://github.com/iptv-org/api) repository. To run the script you must provide your [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with write access to the repository.
- `db:create`: сreates a temporary file `temp/database/streams.db` containing all links from the [/streams]() folder. - `playlist:format`: formats internal playlists. The process includes [URL normalization](https://en.wikipedia.org/wiki/URI_normalization), duplicate removal, removing invalid id's and sorting links by channel name, quality, and label.
- `playlist:update`: triggers an update of internal playlists. The process involves processing approved requests from issues, URL normalization, and sorting links by channel name, quality, and label. - `playlist:update`: triggers an update of internal playlists. The process involves processing approved requests from issues.
- `playlist:generate`: generates all public playlists.
- `playlist:validate`: сhecks ids and links in internal playlists for errors. - `playlist:validate`: сhecks ids and links in internal playlists for errors.
- `playlist:lint`: сhecks internal playlists for syntax errors. - `playlist:lint`: сhecks internal playlists for syntax errors.
- `playlist:generate`: generates all public playlists.
- `playlist:deploy`: allows to manually publish all generated via `playlist:generate` playlists. To run the script you must provide your [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with write access to the repository. - `playlist:deploy`: allows to manually publish all generated via `playlist:generate` playlists. To run the script you must provide your [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with write access to the repository.
- `readme:update`: updates the list of playlists in [README.md](README.md). - `readme:update`: updates the list of playlists in [README.md](README.md).
- `report:create`: shows a list of all current requests and their status. - `report:create`: shows a list of all current requests and their status.
- `format`: (shorthand) sequentially runs the `db:create` and `db:create` commands. - `format`: (shorthand) sequentially runs the `api:load` and `playlist:format` commands.
- `check`: (shorthand) sequentially runs the `api:load`, `playlist:lint` and `playlist:validate` commands. - `check`: (shorthand) sequentially runs the `api:load`, `playlist:lint` and `playlist:validate` commands.
- `update`: (shorthand) sequentially runs the `api:load`, `db:create`, `playlist:generate`, `api:generate` and `readme:update` commands. - `update`: (shorthand) sequentially runs the `api:load`, `playlist:generate`, `api:generate` and `readme:update` commands.
- `deploy`: (shorthand) sequentially runs the `playlist:deploy` and `api:deploy` commands. - `deploy`: (shorthand) sequentially runs the `playlist:deploy` and `api:deploy` commands.
- `report`: (shorthand) sequentially runs the `api:load` and `report:create` commands. - `report`: (shorthand) sequentially runs the `api:load` and `report:create` commands.
- `test`: runs a test of all the scripts described above. - `test`: runs a test of all the scripts described above.
@ -148,5 +149,6 @@ To automate the run of the scripts described above, we use the [GitHub Actions w
Each workflow includes its own set of scripts that can be run either manually or in response to an event. Each workflow includes its own set of scripts that can be run either manually or in response to an event.
- `check`: sequentially runs the `playlist:check` and `playlist:validate` scripts when a new pull request appears, and blocks the merge if it detects an error in it. - `check`: sequentially runs the `api:load`, `playlist:check` and `playlist:validate` scripts when a new pull request appears, and blocks the merge if it detects an error in it.
- `update`: every day at 0:00 UTC sequentially runs `api:load`, `db:create`, `playlist:update`, `playlist:lint`, `playlist:validate`, `playlist:generate`, `api:generate` and `readme:update` scripts and deploys the output files if successful. - `format`: sequentially runs `api:load`, `playlist:format`, `playlist:lint` and `playlist:validate` scripts.
- `update`: every day at 0:00 UTC sequentially runs `api:load`, `playlist:update`, `playlist:lint`, `playlist:validate`, `playlist:generate`, `api:generate` and `readme:update` scripts and deploys the output files if successful.

@ -59,35 +59,35 @@ Same thing, but split up into separate files:
<tr><th align="left">Category</th><th align="left">Channels</th><th align="left">Playlist</th></tr> <tr><th align="left">Category</th><th align="left">Channels</th><th align="left">Playlist</th></tr>
</thead> </thead>
<tbody> <tbody>
<tr><td>Auto</td><td align="right">15</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/auto.m3u</code></td></tr>
<tr><td>Animation</td><td align="right">50</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/animation.m3u</code></td></tr> <tr><td>Animation</td><td align="right">50</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/animation.m3u</code></td></tr>
<tr><td>Auto</td><td align="right">15</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/auto.m3u</code></td></tr>
<tr><td>Business</td><td align="right">57</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/business.m3u</code></td></tr> <tr><td>Business</td><td align="right">57</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/business.m3u</code></td></tr>
<tr><td>Classic</td><td align="right">55</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/classic.m3u</code></td></tr> <tr><td>Classic</td><td align="right">55</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/classic.m3u</code></td></tr>
<tr><td>Comedy</td><td align="right">57</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/comedy.m3u</code></td></tr> <tr><td>Comedy</td><td align="right">57</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/comedy.m3u</code></td></tr>
<tr><td>Cooking</td><td align="right">23</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/cooking.m3u</code></td></tr> <tr><td>Cooking</td><td align="right">23</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/cooking.m3u</code></td></tr>
<tr><td>Culture</td><td align="right">76</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/culture.m3u</code></td></tr> <tr><td>Culture</td><td align="right">79</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/culture.m3u</code></td></tr>
<tr><td>Documentary</td><td align="right">64</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/documentary.m3u</code></td></tr> <tr><td>Documentary</td><td align="right">64</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/documentary.m3u</code></td></tr>
<tr><td>Education</td><td align="right">116</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/education.m3u</code></td></tr> <tr><td>Education</td><td align="right">116</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/education.m3u</code></td></tr>
<tr><td>Entertainment</td><td align="right">354</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/entertainment.m3u</code></td></tr> <tr><td>Entertainment</td><td align="right">356</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/entertainment.m3u</code></td></tr>
<tr><td>Family</td><td align="right">40</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/family.m3u</code></td></tr> <tr><td>Family</td><td align="right">40</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/family.m3u</code></td></tr>
<tr><td>General</td><td align="right">1101</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/general.m3u</code></td></tr> <tr><td>General</td><td align="right">1123</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/general.m3u</code></td></tr>
<tr><td>Kids</td><td align="right">182</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/kids.m3u</code></td></tr> <tr><td>Kids</td><td align="right">182</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/kids.m3u</code></td></tr>
<tr><td>Legislative</td><td align="right">166</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/legislative.m3u</code></td></tr> <tr><td>Legislative</td><td align="right">167</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/legislative.m3u</code></td></tr>
<tr><td>Lifestyle</td><td align="right">79</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/lifestyle.m3u</code></td></tr> <tr><td>Lifestyle</td><td align="right">79</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/lifestyle.m3u</code></td></tr>
<tr><td>Movies</td><td align="right">274</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/movies.m3u</code></td></tr> <tr><td>Movies</td><td align="right">275</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/movies.m3u</code></td></tr>
<tr><td>Music</td><td align="right">483</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/music.m3u</code></td></tr> <tr><td>Music</td><td align="right">486</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/music.m3u</code></td></tr>
<tr><td>News</td><td align="right">705</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/news.m3u</code></td></tr> <tr><td>News</td><td align="right">707</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/news.m3u</code></td></tr>
<tr><td>Outdoor</td><td align="right">44</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/outdoor.m3u</code></td></tr> <tr><td>Outdoor</td><td align="right">44</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/outdoor.m3u</code></td></tr>
<tr><td>Relax</td><td align="right">16</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/relax.m3u</code></td></tr> <tr><td>Relax</td><td align="right">16</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/relax.m3u</code></td></tr>
<tr><td>Religious</td><td align="right">438</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/religious.m3u</code></td></tr> <tr><td>Religious</td><td align="right">441</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/religious.m3u</code></td></tr>
<tr><td>Series</td><td align="right">160</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/series.m3u</code></td></tr>
<tr><td>Science</td><td align="right">25</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/science.m3u</code></td></tr> <tr><td>Science</td><td align="right">25</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/science.m3u</code></td></tr>
<tr><td>Series</td><td align="right">160</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/series.m3u</code></td></tr>
<tr><td>Shop</td><td align="right">74</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/shop.m3u</code></td></tr> <tr><td>Shop</td><td align="right">74</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/shop.m3u</code></td></tr>
<tr><td>Sports</td><td align="right">205</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/sports.m3u</code></td></tr> <tr><td>Sports</td><td align="right">207</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/sports.m3u</code></td></tr>
<tr><td>Travel</td><td align="right">30</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/travel.m3u</code></td></tr> <tr><td>Travel</td><td align="right">30</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/travel.m3u</code></td></tr>
<tr><td>Weather</td><td align="right">14</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/weather.m3u</code></td></tr> <tr><td>Weather</td><td align="right">14</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/weather.m3u</code></td></tr>
<tr><td>XXX</td><td align="right">46</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/xxx.m3u</code></td></tr> <tr><td>XXX</td><td align="right">46</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/xxx.m3u</code></td></tr>
<tr><td>Undefined</td><td align="right">5262</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/undefined.m3u</code></td></tr> <tr><td>Undefined</td><td align="right">5263</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/undefined.m3u</code></td></tr>
</tbody> </tbody>
</table> </table>
@ -118,7 +118,7 @@ Same thing, but split up into separate files:
<tr><td align="left">Albanian</td><td align="right">58</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/sqi.m3u</code></td></tr> <tr><td align="left">Albanian</td><td align="right">58</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/sqi.m3u</code></td></tr>
<tr><td align="left">Alemannic</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/gsw.m3u</code></td></tr> <tr><td align="left">Alemannic</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/gsw.m3u</code></td></tr>
<tr><td align="left">Amharic</td><td align="right">5</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/amh.m3u</code></td></tr> <tr><td align="left">Amharic</td><td align="right">5</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/amh.m3u</code></td></tr>
<tr><td align="left">Arabic</td><td align="right">379</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/ara.m3u</code></td></tr> <tr><td align="left">Arabic</td><td align="right">380</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/ara.m3u</code></td></tr>
<tr><td align="left">Armenian</td><td align="right">29</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/hye.m3u</code></td></tr> <tr><td align="left">Armenian</td><td align="right">29</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/hye.m3u</code></td></tr>
<tr><td align="left">Assamese</td><td align="right">7</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/asm.m3u</code></td></tr> <tr><td align="left">Assamese</td><td align="right">7</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/asm.m3u</code></td></tr>
<tr><td align="left">Assyrian Neo-Aramaic</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/aii.m3u</code></td></tr> <tr><td align="left">Assyrian Neo-Aramaic</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/aii.m3u</code></td></tr>
@ -142,28 +142,28 @@ Same thing, but split up into separate files:
<tr><td align="left">Dholuo</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/luo.m3u</code></td></tr> <tr><td align="left">Dholuo</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/luo.m3u</code></td></tr>
<tr><td align="left">Dimili</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/zza.m3u</code></td></tr> <tr><td align="left">Dimili</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/zza.m3u</code></td></tr>
<tr><td align="left">Dutch</td><td align="right">191</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/nld.m3u</code></td></tr> <tr><td align="left">Dutch</td><td align="right">191</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/nld.m3u</code></td></tr>
<tr><td align="left">English</td><td align="right">2177</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/eng.m3u</code></td></tr> <tr><td align="left">English</td><td align="right">2181</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/eng.m3u</code></td></tr>
<tr><td align="left">Estonian</td><td align="right">8</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/est.m3u</code></td></tr> <tr><td align="left">Estonian</td><td align="right">9</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/est.m3u</code></td></tr>
<tr><td align="left">Ewe</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/ewe.m3u</code></td></tr> <tr><td align="left">Ewe</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/ewe.m3u</code></td></tr>
<tr><td align="left">Faroese</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/fao.m3u</code></td></tr> <tr><td align="left">Faroese</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/fao.m3u</code></td></tr>
<tr><td align="left">Fataleka</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/far.m3u</code></td></tr> <tr><td align="left">Fataleka</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/far.m3u</code></td></tr>
<tr><td align="left">Filipino</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/fil.m3u</code></td></tr> <tr><td align="left">Filipino</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/fil.m3u</code></td></tr>
<tr><td align="left">Finnish</td><td align="right">25</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/fin.m3u</code></td></tr> <tr><td align="left">Finnish</td><td align="right">25</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/fin.m3u</code></td></tr>
<tr><td align="left">French</td><td align="right">364</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/fra.m3u</code></td></tr> <tr><td align="left">French</td><td align="right">378</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/fra.m3u</code></td></tr>
<tr><td align="left">Galician</td><td align="right">12</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/glg.m3u</code></td></tr> <tr><td align="left">Galician</td><td align="right">12</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/glg.m3u</code></td></tr>
<tr><td align="left">Galolen</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/gal.m3u</code></td></tr> <tr><td align="left">Galolen</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/gal.m3u</code></td></tr>
<tr><td align="left">Georgian</td><td align="right">8</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kat.m3u</code></td></tr> <tr><td align="left">Georgian</td><td align="right">8</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kat.m3u</code></td></tr>
<tr><td align="left">German</td><td align="right">281</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/deu.m3u</code></td></tr> <tr><td align="left">German</td><td align="right">281</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/deu.m3u</code></td></tr>
<tr><td align="left">Gikuyu</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kik.m3u</code></td></tr> <tr><td align="left">Gikuyu</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kik.m3u</code></td></tr>
<tr><td align="left">Goan Konkani</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/gom.m3u</code></td></tr> <tr><td align="left">Goan Konkani</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/gom.m3u</code></td></tr>
<tr><td align="left">Greek</td><td align="right">124</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/ell.m3u</code></td></tr> <tr><td align="left">Greek</td><td align="right">125</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/ell.m3u</code></td></tr>
<tr><td align="left">Greenlandic</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kal.m3u</code></td></tr> <tr><td align="left">Greenlandic</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kal.m3u</code></td></tr>
<tr><td align="left">Gujarati</td><td align="right">10</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/guj.m3u</code></td></tr> <tr><td align="left">Gujarati</td><td align="right">10</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/guj.m3u</code></td></tr>
<tr><td align="left">Haitian</td><td align="right">5</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/hat.m3u</code></td></tr> <tr><td align="left">Haitian</td><td align="right">5</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/hat.m3u</code></td></tr>
<tr><td align="left">Hausa</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/hau.m3u</code></td></tr> <tr><td align="left">Hausa</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/hau.m3u</code></td></tr>
<tr><td align="left">Hebrew</td><td align="right">13</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/heb.m3u</code></td></tr> <tr><td align="left">Hebrew</td><td align="right">13</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/heb.m3u</code></td></tr>
<tr><td align="left">Hindi</td><td align="right">163</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/hin.m3u</code></td></tr> <tr><td align="left">Hindi</td><td align="right">163</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/hin.m3u</code></td></tr>
<tr><td align="left">Hungarian</td><td align="right">111</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/hun.m3u</code></td></tr> <tr><td align="left">Hungarian</td><td align="right">112</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/hun.m3u</code></td></tr>
<tr><td align="left">Icelandic</td><td align="right">5</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/isl.m3u</code></td></tr> <tr><td align="left">Icelandic</td><td align="right">5</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/isl.m3u</code></td></tr>
<tr><td align="left">Indonesian</td><td align="right">182</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/ind.m3u</code></td></tr> <tr><td align="left">Indonesian</td><td align="right">182</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/ind.m3u</code></td></tr>
<tr><td align="left">Inuktitut</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/iku.m3u</code></td></tr> <tr><td align="left">Inuktitut</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/iku.m3u</code></td></tr>
@ -178,11 +178,11 @@ Same thing, but split up into separate files:
<tr><td align="left">Kirghiz</td><td align="right">7</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kir.m3u</code></td></tr> <tr><td align="left">Kirghiz</td><td align="right">7</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kir.m3u</code></td></tr>
<tr><td align="left">Konkani (macrolanguage)</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kok.m3u</code></td></tr> <tr><td align="left">Konkani (macrolanguage)</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kok.m3u</code></td></tr>
<tr><td align="left">Korean</td><td align="right">112</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kor.m3u</code></td></tr> <tr><td align="left">Korean</td><td align="right">112</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kor.m3u</code></td></tr>
<tr><td align="left">Kurdish</td><td align="right">23</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kur.m3u</code></td></tr> <tr><td align="left">Kurdish</td><td align="right">24</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/kur.m3u</code></td></tr>
<tr><td align="left">Lahnda</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/lah.m3u</code></td></tr> <tr><td align="left">Lahnda</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/lah.m3u</code></td></tr>
<tr><td align="left">Lao</td><td align="right">9</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/lao.m3u</code></td></tr> <tr><td align="left">Lao</td><td align="right">9</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/lao.m3u</code></td></tr>
<tr><td align="left">Latin</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/lat.m3u</code></td></tr> <tr><td align="left">Latin</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/lat.m3u</code></td></tr>
<tr><td align="left">Latvian</td><td align="right">9</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/lav.m3u</code></td></tr> <tr><td align="left">Latvian</td><td align="right">10</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/lav.m3u</code></td></tr>
<tr><td align="left">Letzeburgesch</td><td align="right">3</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/ltz.m3u</code></td></tr> <tr><td align="left">Letzeburgesch</td><td align="right">3</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/ltz.m3u</code></td></tr>
<tr><td align="left">Lithuanian</td><td align="right">8</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/lit.m3u</code></td></tr> <tr><td align="left">Lithuanian</td><td align="right">8</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/lit.m3u</code></td></tr>
<tr><td align="left">Macedonian</td><td align="right">34</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/mkd.m3u</code></td></tr> <tr><td align="left">Macedonian</td><td align="right">34</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/mkd.m3u</code></td></tr>
@ -203,11 +203,11 @@ Same thing, but split up into separate files:
<tr><td align="left">Parsi-Dari</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/prd.m3u</code></td></tr> <tr><td align="left">Parsi-Dari</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/prd.m3u</code></td></tr>
<tr><td align="left">Pashto</td><td align="right">18</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/pus.m3u</code></td></tr> <tr><td align="left">Pashto</td><td align="right">18</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/pus.m3u</code></td></tr>
<tr><td align="left">Persian</td><td align="right">135</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/fas.m3u</code></td></tr> <tr><td align="left">Persian</td><td align="right">135</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/fas.m3u</code></td></tr>
<tr><td align="left">Polish</td><td align="right">53</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/pol.m3u</code></td></tr> <tr><td align="left">Polish</td><td align="right">54</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/pol.m3u</code></td></tr>
<tr><td align="left">Portuguese</td><td align="right">363</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/por.m3u</code></td></tr> <tr><td align="left">Portuguese</td><td align="right">364</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/por.m3u</code></td></tr>
<tr><td align="left">Romanian</td><td align="right">117</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/ron.m3u</code></td></tr> <tr><td align="left">Romanian</td><td align="right">117</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/ron.m3u</code></td></tr>
<tr><td align="left">Romany</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/rom.m3u</code></td></tr> <tr><td align="left">Romany</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/rom.m3u</code></td></tr>
<tr><td align="left">Russian</td><td align="right">301</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/rus.m3u</code></td></tr> <tr><td align="left">Russian</td><td align="right">302</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/rus.m3u</code></td></tr>
<tr><td align="left">Saint Lucian Creole French</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/acf.m3u</code></td></tr> <tr><td align="left">Saint Lucian Creole French</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/acf.m3u</code></td></tr>
<tr><td align="left">Santali</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/sat.m3u</code></td></tr> <tr><td align="left">Santali</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/sat.m3u</code></td></tr>
<tr><td align="left">Serbian</td><td align="right">82</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/srp.m3u</code></td></tr> <tr><td align="left">Serbian</td><td align="right">82</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/srp.m3u</code></td></tr>
@ -217,12 +217,12 @@ Same thing, but split up into separate files:
<tr><td align="left">Slovak</td><td align="right">44</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/slk.m3u</code></td></tr> <tr><td align="left">Slovak</td><td align="right">44</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/slk.m3u</code></td></tr>
<tr><td align="left">Slovenian</td><td align="right">16</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/slv.m3u</code></td></tr> <tr><td align="left">Slovenian</td><td align="right">16</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/slv.m3u</code></td></tr>
<tr><td align="left">Somali</td><td align="right">8</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/som.m3u</code></td></tr> <tr><td align="left">Somali</td><td align="right">8</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/som.m3u</code></td></tr>
<tr><td align="left">Spanish</td><td align="right">1830</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/spa.m3u</code></td></tr> <tr><td align="left">Spanish</td><td align="right">1853</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/spa.m3u</code></td></tr>
<tr><td align="left">Swahili</td><td align="right">14</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/swa.m3u</code></td></tr> <tr><td align="left">Swahili</td><td align="right">14</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/swa.m3u</code></td></tr>
<tr><td align="left">Swedish</td><td align="right">20</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/swe.m3u</code></td></tr> <tr><td align="left">Swedish</td><td align="right">19</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/swe.m3u</code></td></tr>
<tr><td align="left">Tagalog</td><td align="right">14</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/tgl.m3u</code></td></tr> <tr><td align="left">Tagalog</td><td align="right">14</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/tgl.m3u</code></td></tr>
<tr><td align="left">Tajik</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/tgk.m3u</code></td></tr> <tr><td align="left">Tajik</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/tgk.m3u</code></td></tr>
<tr><td align="left">Tamil</td><td align="right">62</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/tam.m3u</code></td></tr> <tr><td align="left">Tamil</td><td align="right">63</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/tam.m3u</code></td></tr>
<tr><td align="left">Telugu</td><td align="right">31</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/tel.m3u</code></td></tr> <tr><td align="left">Telugu</td><td align="right">31</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/tel.m3u</code></td></tr>
<tr><td align="left">Tetum</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/tet.m3u</code></td></tr> <tr><td align="left">Tetum</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/tet.m3u</code></td></tr>
<tr><td align="left">Thai</td><td align="right">83</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/tha.m3u</code></td></tr> <tr><td align="left">Thai</td><td align="right">83</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/tha.m3u</code></td></tr>
@ -238,7 +238,7 @@ Same thing, but split up into separate files:
<tr><td align="left">Wolof</td><td align="right">3</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/wol.m3u</code></td></tr> <tr><td align="left">Wolof</td><td align="right">3</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/wol.m3u</code></td></tr>
<tr><td align="left">Yucatec Maya</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/yua.m3u</code></td></tr> <tr><td align="left">Yucatec Maya</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/yua.m3u</code></td></tr>
<tr><td align="left">Yue Chinese</td><td align="right">10</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/yue.m3u</code></td></tr> <tr><td align="left">Yue Chinese</td><td align="right">10</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/yue.m3u</code></td></tr>
<tr><td align="left">Undefined</td><td align="right">1283</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/undefined.m3u</code></td></tr> <tr><td align="left">Undefined</td><td align="right">1277</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/undefined.m3u</code></td></tr>
</tbody> </tbody>
</table> </table>
@ -264,15 +264,15 @@ Same thing, but split up into separate files:
<tr><th align="left">Country</th><th align="left">Channels</th><th align="left">Playlist</th></tr> <tr><th align="left">Country</th><th align="left">Channels</th><th align="left">Playlist</th></tr>
</thead> </thead>
<tbody> <tbody>
<tr><td>🇦🇫 Afghanistan</td><td align="right">31</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/af.m3u</code></td></tr> <tr><td>🇦🇫 Afghanistan</td><td align="right">32</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/af.m3u</code></td></tr>
<tr><td>🇦🇱 Albania</td><td align="right">30</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/al.m3u</code></td></tr> <tr><td>🇦🇱 Albania</td><td align="right">30</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/al.m3u</code></td></tr>
<tr><td>🇩🇿 Algeria</td><td align="right">51</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/dz.m3u</code></td></tr> <tr><td>🇩🇿 Algeria</td><td align="right">52</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/dz.m3u</code></td></tr>
<tr><td>🇦🇸 American Samoa</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/as.m3u</code></td></tr> <tr><td>🇦🇸 American Samoa</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/as.m3u</code></td></tr>
<tr><td>🇦🇩 Andorra</td><td align="right">17</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ad.m3u</code></td></tr> <tr><td>🇦🇩 Andorra</td><td align="right">17</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ad.m3u</code></td></tr>
<tr><td>🇦🇴 Angola</td><td align="right">14</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ao.m3u</code></td></tr> <tr><td>🇦🇴 Angola</td><td align="right">14</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ao.m3u</code></td></tr>
<tr><td>🇦🇮 Anguilla</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ai.m3u</code></td></tr> <tr><td>🇦🇮 Anguilla</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ai.m3u</code></td></tr>
<tr><td>🇦🇬 Antigua and Barbuda</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ag.m3u</code></td></tr> <tr><td>🇦🇬 Antigua and Barbuda</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ag.m3u</code></td></tr>
<tr><td>🇦🇷 Argentina</td><td align="right">313</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ar.m3u</code></td></tr> <tr><td>🇦🇷 Argentina</td><td align="right">316</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ar.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Buenos Aires</td><td align="right">30</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ar-b.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Buenos Aires</td><td align="right">30</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ar-b.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Catamarca</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ar-k.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Catamarca</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ar-k.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Chaco</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ar-h.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Chaco</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ar-h.m3u</code></td></tr>
@ -302,24 +302,24 @@ Same thing, but split up into separate files:
<tr><td>🇦🇹 Austria</td><td align="right">48</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/at.m3u</code></td></tr> <tr><td>🇦🇹 Austria</td><td align="right">48</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/at.m3u</code></td></tr>
<tr><td>🇦🇿 Azerbaijan</td><td align="right">33</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/az.m3u</code></td></tr> <tr><td>🇦🇿 Azerbaijan</td><td align="right">33</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/az.m3u</code></td></tr>
<tr><td>🇧🇸 Bahamas</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bs.m3u</code></td></tr> <tr><td>🇧🇸 Bahamas</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bs.m3u</code></td></tr>
<tr><td>🇧🇭 Bahrain</td><td align="right">37</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bh.m3u</code></td></tr> <tr><td>🇧🇭 Bahrain</td><td align="right">38</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bh.m3u</code></td></tr>
<tr><td>🇧🇩 Bangladesh</td><td align="right">53</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bd.m3u</code></td></tr> <tr><td>🇧🇩 Bangladesh</td><td align="right">54</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bd.m3u</code></td></tr>
<tr><td>🇧🇧 Barbados</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bb.m3u</code></td></tr> <tr><td>🇧🇧 Barbados</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bb.m3u</code></td></tr>
<tr><td>🇧🇾 Belarus</td><td align="right">42</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/by.m3u</code></td></tr> <tr><td>🇧🇾 Belarus</td><td align="right">42</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/by.m3u</code></td></tr>
<tr><td>🇧🇪 Belgium</td><td align="right">56</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/be.m3u</code></td></tr> <tr><td>🇧🇪 Belgium</td><td align="right">56</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/be.m3u</code></td></tr>
<tr><td>🇧🇿 Belize</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bz.m3u</code></td></tr> <tr><td>🇧🇿 Belize</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bz.m3u</code></td></tr>
<tr><td>🇧🇯 Benin</td><td align="right">19</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bj.m3u</code></td></tr> <tr><td>🇧🇯 Benin</td><td align="right">19</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bj.m3u</code></td></tr>
<tr><td>🇧🇲 Bermuda</td><td align="right">4</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bm.m3u</code></td></tr> <tr><td>🇧🇲 Bermuda</td><td align="right">4</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bm.m3u</code></td></tr>
<tr><td>🇧🇹 Bhutan</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bt.m3u</code></td></tr> <tr><td>🇧🇹 Bhutan</td><td align="right">8</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bt.m3u</code></td></tr>
<tr><td>🇧🇴 Bolivia</td><td align="right">83</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bo.m3u</code></td></tr> <tr><td>🇧🇴 Bolivia</td><td align="right">94</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bo.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cochabamba</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/bo-c.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cochabamba</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/bo-c.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;La Paz</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/bo-l.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;La Paz</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/bo-l.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Oruro</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/bo-o.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Oruro</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/bo-o.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Santa Cruz</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/bo-s.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Santa Cruz</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/bo-s.m3u</code></td></tr>
<tr><td>🇧🇦 Bosnia and Herzegovina</td><td align="right">31</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ba.m3u</code></td></tr> <tr><td>🇧🇦 Bosnia and Herzegovina</td><td align="right">31</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ba.m3u</code></td></tr>
<tr><td>🇧🇼 Botswana</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bw.m3u</code></td></tr> <tr><td>🇧🇼 Botswana</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bw.m3u</code></td></tr>
<tr><td>🇧🇻 Bouvet Island</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bv.m3u</code></td></tr> <tr><td>🇧🇻 Bouvet Island</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bv.m3u</code></td></tr>
<tr><td>🇧🇷 Brazil</td><td align="right">321</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/br.m3u</code></td></tr> <tr><td>🇧🇷 Brazil</td><td align="right">322</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/br.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alagoas</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/br-al.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alagoas</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/br-al.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Amazonas</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/br-am.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Amazonas</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/br-am.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bahia</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/br-ba.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bahia</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/br-ba.m3u</code></td></tr>
@ -366,7 +366,7 @@ Same thing, but split up into separate files:
<tr><td>🇰🇾 Cayman Islands</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ky.m3u</code></td></tr> <tr><td>🇰🇾 Cayman Islands</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ky.m3u</code></td></tr>
<tr><td>🇨🇫 Central African Republic</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cf.m3u</code></td></tr> <tr><td>🇨🇫 Central African Republic</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cf.m3u</code></td></tr>
<tr><td>🇹🇩 Chad</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/td.m3u</code></td></tr> <tr><td>🇹🇩 Chad</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/td.m3u</code></td></tr>
<tr><td>🇨🇱 Chile</td><td align="right">256</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cl.m3u</code></td></tr> <tr><td>🇨🇱 Chile</td><td align="right">259</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cl.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Biobio</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cl-bi.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Biobio</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cl-bi.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Coquimbo</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cl-co.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Coquimbo</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cl-co.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;La Araucania</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cl-ar.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;La Araucania</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cl-ar.m3u</code></td></tr>
@ -376,8 +376,7 @@ Same thing, but split up into separate files:
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Nuble</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cl-nb.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Nuble</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cl-nb.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Valparaiso</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cl-vs.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Valparaiso</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cl-vs.m3u</code></td></tr>
<tr><td>🇨🇳 China</td><td align="right">562</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cn.m3u</code></td></tr> <tr><td>🇨🇳 China</td><td align="right">562</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cn.m3u</code></td></tr>
<tr><td>🇨🇴 Colombia</td><td align="right">134</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/co.m3u</code></td></tr> <tr><td>🇨🇴 Colombia</td><td align="right">137</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/co.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;San Andres, Providencia y Santa Catalina</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-sap.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Antioquia</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-ant.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Antioquia</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-ant.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Atlantico</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-atl.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Atlantico</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-atl.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bolivar</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-bol.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bolivar</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-bol.m3u</code></td></tr>
@ -391,23 +390,24 @@ Same thing, but split up into separate files:
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Norte de Santander</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-nsa.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Norte de Santander</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-nsa.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quindio</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-qui.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quindio</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-qui.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Risaralda</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-ris.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Risaralda</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-ris.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;San Andres, Providencia y Santa Catalina</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-sap.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tolima</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-tol.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tolima</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-tol.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Valle del Cauca</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-vac.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Valle del Cauca</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/co-vac.m3u</code></td></tr>
<tr><td>🇰🇲 Comoros</td><td align="right">40</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/km.m3u</code></td></tr> <tr><td>🇰🇲 Comoros</td><td align="right">41</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/km.m3u</code></td></tr>
<tr><td>🇨🇰 Cook Islands</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ck.m3u</code></td></tr> <tr><td>🇨🇰 Cook Islands</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ck.m3u</code></td></tr>
<tr><td>🇨🇷 Costa Rica</td><td align="right">94</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cr.m3u</code></td></tr> <tr><td>🇨🇷 Costa Rica</td><td align="right">97</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cr.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Puntarenas</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cr-p.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Puntarenas</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cr-p.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;San Jose</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cr-sj.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;San Jose</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cr-sj.m3u</code></td></tr>
<tr><td>🇭🇷 Croatia</td><td align="right">27</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/hr.m3u</code></td></tr> <tr><td>🇭🇷 Croatia</td><td align="right">27</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/hr.m3u</code></td></tr>
<tr><td>🇨🇺 Cuba</td><td align="right">49</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cu.m3u</code></td></tr> <tr><td>🇨🇺 Cuba</td><td align="right">53</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cu.m3u</code></td></tr>
<tr><td>🇨🇼 Curacao</td><td align="right">10</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cw.m3u</code></td></tr> <tr><td>🇨🇼 Curacao</td><td align="right">10</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cw.m3u</code></td></tr>
<tr><td>🇨🇾 Cyprus</td><td align="right">41</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cy.m3u</code></td></tr> <tr><td>🇨🇾 Cyprus</td><td align="right">41</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cy.m3u</code></td></tr>
<tr><td>🇨🇿 Czech Republic</td><td align="right">43</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cz.m3u</code></td></tr> <tr><td>🇨🇿 Czech Republic</td><td align="right">43</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cz.m3u</code></td></tr>
<tr><td>🇨🇩 Democratic Republic of the Congo</td><td align="right">33</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cd.m3u</code></td></tr> <tr><td>🇨🇩 Democratic Republic of the Congo</td><td align="right">33</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cd.m3u</code></td></tr>
<tr><td>🇩🇰 Denmark</td><td align="right">34</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/dk.m3u</code></td></tr> <tr><td>🇩🇰 Denmark</td><td align="right">34</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/dk.m3u</code></td></tr>
<tr><td>🇩🇯 Djibouti</td><td align="right">45</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/dj.m3u</code></td></tr> <tr><td>🇩🇯 Djibouti</td><td align="right">46</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/dj.m3u</code></td></tr>
<tr><td>🇩🇲 Dominica</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/dm.m3u</code></td></tr> <tr><td>🇩🇲 Dominica</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/dm.m3u</code></td></tr>
<tr><td>🇩🇴 Dominican Republic</td><td align="right">205</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/do.m3u</code></td></tr> <tr><td>🇩🇴 Dominican Republic</td><td align="right">208</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/do.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Distrito Nacional (Santo Domingo)</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/do-01.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Distrito Nacional (Santo Domingo)</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/do-01.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;La Altagracia</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/do-11.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;La Altagracia</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/do-11.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;La Vega</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/do-13.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;La Vega</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/do-13.m3u</code></td></tr>
@ -417,23 +417,23 @@ Same thing, but split up into separate files:
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Santiago</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/do-25.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Santiago</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/do-25.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Valverde</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/do-27.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Valverde</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/do-27.m3u</code></td></tr>
<tr><td>🇹🇱 East Timor</td><td align="right">27</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tl.m3u</code></td></tr> <tr><td>🇹🇱 East Timor</td><td align="right">27</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tl.m3u</code></td></tr>
<tr><td>🇪🇨 Ecuador</td><td align="right">79</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ec.m3u</code></td></tr> <tr><td>🇪🇨 Ecuador</td><td align="right">82</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ec.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Azuay</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ec-a.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Azuay</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ec-a.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Loja</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ec-l.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Loja</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ec-l.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Orellana</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ec-d.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Orellana</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ec-d.m3u</code></td></tr>
<tr><td>🇪🇬 Egypt</td><td align="right">76</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/eg.m3u</code></td></tr> <tr><td>🇪🇬 Egypt</td><td align="right">77</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/eg.m3u</code></td></tr>
<tr><td>🇸🇻 El Salvador</td><td align="right">64</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sv.m3u</code></td></tr> <tr><td>🇸🇻 El Salvador</td><td align="right">67</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sv.m3u</code></td></tr>
<tr><td>🇬🇶 Equatorial Guinea</td><td align="right">14</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gq.m3u</code></td></tr> <tr><td>🇬🇶 Equatorial Guinea</td><td align="right">14</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gq.m3u</code></td></tr>
<tr><td>🇪🇷 Eritrea</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/er.m3u</code></td></tr> <tr><td>🇪🇷 Eritrea</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/er.m3u</code></td></tr>
<tr><td>🇪🇪 Estonia</td><td align="right">23</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ee.m3u</code></td></tr> <tr><td>🇪🇪 Estonia</td><td align="right">24</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ee.m3u</code></td></tr>
<tr><td>🇪🇹 Ethiopia</td><td align="right">18</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/et.m3u</code></td></tr> <tr><td>🇪🇹 Ethiopia</td><td align="right">18</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/et.m3u</code></td></tr>
<tr><td>🇫🇰 Falkland Islands</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/fk.m3u</code></td></tr> <tr><td>🇫🇰 Falkland Islands</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/fk.m3u</code></td></tr>
<tr><td>🇫🇴 Faroe Islands</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/fo.m3u</code></td></tr> <tr><td>🇫🇴 Faroe Islands</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/fo.m3u</code></td></tr>
<tr><td>🇫🇯 Fiji</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/fj.m3u</code></td></tr> <tr><td>🇫🇯 Fiji</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/fj.m3u</code></td></tr>
<tr><td>🇫🇮 Finland</td><td align="right">40</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/fi.m3u</code></td></tr> <tr><td>🇫🇮 Finland</td><td align="right">41</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/fi.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Keski-Suomi</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/fi-08.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Keski-Suomi</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/fi-08.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pohjanmaa</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/fi-12.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pohjanmaa</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/fi-12.m3u</code></td></tr>
<tr><td>🇫🇷 France</td><td align="right">242</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/fr.m3u</code></td></tr> <tr><td>🇫🇷 France</td><td align="right">256</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/fr.m3u</code></td></tr>
<tr><td>🇬🇫 French Guiana</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gf.m3u</code></td></tr> <tr><td>🇬🇫 French Guiana</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gf.m3u</code></td></tr>
<tr><td>🇵🇫 French Polynesia</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pf.m3u</code></td></tr> <tr><td>🇵🇫 French Polynesia</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pf.m3u</code></td></tr>
<tr><td>🇹🇫 French Southern Territories</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tf.m3u</code></td></tr> <tr><td>🇹🇫 French Southern Territories</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tf.m3u</code></td></tr>
@ -442,12 +442,12 @@ Same thing, but split up into separate files:
<tr><td>🇬🇪 Georgia</td><td align="right">20</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ge.m3u</code></td></tr> <tr><td>🇬🇪 Georgia</td><td align="right">20</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ge.m3u</code></td></tr>
<tr><td>🇩🇪 Germany</td><td align="right">266</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/de.m3u</code></td></tr> <tr><td>🇩🇪 Germany</td><td align="right">266</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/de.m3u</code></td></tr>
<tr><td>🇬🇭 Ghana</td><td align="right">36</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gh.m3u</code></td></tr> <tr><td>🇬🇭 Ghana</td><td align="right">36</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gh.m3u</code></td></tr>
<tr><td>🇬🇷 Greece</td><td align="right">117</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gr.m3u</code></td></tr> <tr><td>🇬🇷 Greece</td><td align="right">118</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gr.m3u</code></td></tr>
<tr><td>🇬🇱 Greenland</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gl.m3u</code></td></tr> <tr><td>🇬🇱 Greenland</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gl.m3u</code></td></tr>
<tr><td>🇬🇩 Grenada</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gd.m3u</code></td></tr> <tr><td>🇬🇩 Grenada</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gd.m3u</code></td></tr>
<tr><td>🇬🇵 Guadeloupe</td><td align="right">9</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gp.m3u</code></td></tr> <tr><td>🇬🇵 Guadeloupe</td><td align="right">9</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gp.m3u</code></td></tr>
<tr><td>🇬🇺 Guam</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gu.m3u</code></td></tr> <tr><td>🇬🇺 Guam</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gu.m3u</code></td></tr>
<tr><td>🇬🇹 Guatemala</td><td align="right">100</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gt.m3u</code></td></tr> <tr><td>🇬🇹 Guatemala</td><td align="right">104</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gt.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Escuintla</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/gt-05.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Escuintla</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/gt-05.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Izabal</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/gt-18.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Izabal</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/gt-18.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quiche</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/gt-14.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quiche</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/gt-14.m3u</code></td></tr>
@ -461,11 +461,11 @@ Same thing, but split up into separate files:
<tr><td>🇬🇼 Guinea-Bissau</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gw.m3u</code></td></tr> <tr><td>🇬🇼 Guinea-Bissau</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gw.m3u</code></td></tr>
<tr><td>🇬🇾 Guyana</td><td align="right">4</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gy.m3u</code></td></tr> <tr><td>🇬🇾 Guyana</td><td align="right">4</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gy.m3u</code></td></tr>
<tr><td>🇭🇹 Haiti</td><td align="right">40</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ht.m3u</code></td></tr> <tr><td>🇭🇹 Haiti</td><td align="right">40</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ht.m3u</code></td></tr>
<tr><td>🇭🇳 Honduras</td><td align="right">107</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/hn.m3u</code></td></tr> <tr><td>🇭🇳 Honduras</td><td align="right">110</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/hn.m3u</code></td></tr>
<tr><td>🇭🇰 Hong Kong</td><td align="right">21</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/hk.m3u</code></td></tr> <tr><td>🇭🇰 Hong Kong</td><td align="right">21</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/hk.m3u</code></td></tr>
<tr><td>🇭🇺 Hungary</td><td align="right">117</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/hu.m3u</code></td></tr> <tr><td>🇭🇺 Hungary</td><td align="right">118</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/hu.m3u</code></td></tr>
<tr><td>🇮🇸 Iceland</td><td align="right">16</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/is.m3u</code></td></tr> <tr><td>🇮🇸 Iceland</td><td align="right">16</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/is.m3u</code></td></tr>
<tr><td>🇮🇳 India</td><td align="right">438</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/in.m3u</code></td></tr> <tr><td>🇮🇳 India</td><td align="right">439</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/in.m3u</code></td></tr>
<tr><td>🇮🇩 Indonesia</td><td align="right">207</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/id.m3u</code></td></tr> <tr><td>🇮🇩 Indonesia</td><td align="right">207</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/id.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Aceh</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-ac.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Aceh</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-ac.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bali</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-ba.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bali</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-ba.m3u</code></td></tr>
@ -483,8 +483,8 @@ Same thing, but split up into separate files:
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Kalimantan Timur</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-ki.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Kalimantan Timur</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-ki.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Kepulauan Bangka Belitung</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-bb.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Kepulauan Bangka Belitung</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-bb.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Lampung</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-la.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Lampung</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-la.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Maluku Utara</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-mu.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Maluku</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-ml.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Maluku</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-ml.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Maluku Utara</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-mu.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Nusa Tenggara Barat</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-nb.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Nusa Tenggara Barat</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-nb.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Nusa Tenggara Timur</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-nt.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Nusa Tenggara Timur</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-nt.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Papua</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-pp.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Papua</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-pp.m3u</code></td></tr>
@ -498,42 +498,42 @@ Same thing, but split up into separate files:
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Yogyakarta</td><td align="right">4</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-yo.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Yogyakarta</td><td align="right">4</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/id-yo.m3u</code></td></tr>
<tr><td>🇮🇷 Iran</td><td align="right">129</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ir.m3u</code></td></tr> <tr><td>🇮🇷 Iran</td><td align="right">129</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ir.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tehran</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ir-23.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tehran</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ir-23.m3u</code></td></tr>
<tr><td>🇮🇶 Iraq</td><td align="right">126</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/iq.m3u</code></td></tr> <tr><td>🇮🇶 Iraq</td><td align="right">127</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/iq.m3u</code></td></tr>
<tr><td>🇮🇪 Ireland</td><td align="right">22</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ie.m3u</code></td></tr> <tr><td>🇮🇪 Ireland</td><td align="right">22</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ie.m3u</code></td></tr>
<tr><td>🇮🇱 Israel</td><td align="right">21</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/il.m3u</code></td></tr> <tr><td>🇮🇱 Israel</td><td align="right">21</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/il.m3u</code></td></tr>
<tr><td>🇮🇹 Italy</td><td align="right">409</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/it.m3u</code></td></tr> <tr><td>🇮🇹 Italy</td><td align="right">409</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/it.m3u</code></td></tr>
<tr><td>🇨🇮 Ivory Coast</td><td align="right">30</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ci.m3u</code></td></tr> <tr><td>🇨🇮 Ivory Coast</td><td align="right">30</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ci.m3u</code></td></tr>
<tr><td>🇯🇲 Jamaica</td><td align="right">11</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/jm.m3u</code></td></tr> <tr><td>🇯🇲 Jamaica</td><td align="right">11</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/jm.m3u</code></td></tr>
<tr><td>🇯🇵 Japan</td><td align="right">48</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/jp.m3u</code></td></tr> <tr><td>🇯🇵 Japan</td><td align="right">48</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/jp.m3u</code></td></tr>
<tr><td>🇯🇴 Jordan</td><td align="right">61</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/jo.m3u</code></td></tr> <tr><td>🇯🇴 Jordan</td><td align="right">62</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/jo.m3u</code></td></tr>
<tr><td>🇰🇿 Kazakhstan</td><td align="right">51</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/kz.m3u</code></td></tr> <tr><td>🇰🇿 Kazakhstan</td><td align="right">51</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/kz.m3u</code></td></tr>
<tr><td>🇰🇪 Kenya</td><td align="right">54</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ke.m3u</code></td></tr> <tr><td>🇰🇪 Kenya</td><td align="right">54</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ke.m3u</code></td></tr>
<tr><td>🇰🇮 Kiribati</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ki.m3u</code></td></tr> <tr><td>🇰🇮 Kiribati</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ki.m3u</code></td></tr>
<tr><td>🇽🇰 Kosovo</td><td align="right">25</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/xk.m3u</code></td></tr> <tr><td>🇽🇰 Kosovo</td><td align="right">25</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/xk.m3u</code></td></tr>
<tr><td>🇰🇼 Kuwait</td><td align="right">46</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/kw.m3u</code></td></tr> <tr><td>🇰🇼 Kuwait</td><td align="right">47</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/kw.m3u</code></td></tr>
<tr><td>🇰🇬 Kyrgyzstan</td><td align="right">9</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/kg.m3u</code></td></tr> <tr><td>🇰🇬 Kyrgyzstan</td><td align="right">9</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/kg.m3u</code></td></tr>
<tr><td>🇱🇦 Laos</td><td align="right">44</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/la.m3u</code></td></tr> <tr><td>🇱🇦 Laos</td><td align="right">44</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/la.m3u</code></td></tr>
<tr><td>🇱🇻 Latvia</td><td align="right">24</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/lv.m3u</code></td></tr> <tr><td>🇱🇻 Latvia</td><td align="right">25</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/lv.m3u</code></td></tr>
<tr><td>🇱🇧 Lebanon</td><td align="right">56</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/lb.m3u</code></td></tr> <tr><td>🇱🇧 Lebanon</td><td align="right">57</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/lb.m3u</code></td></tr>
<tr><td>🇱🇸 Lesotho</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ls.m3u</code></td></tr> <tr><td>🇱🇸 Lesotho</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ls.m3u</code></td></tr>
<tr><td>🇱🇷 Liberia</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/lr.m3u</code></td></tr> <tr><td>🇱🇷 Liberia</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/lr.m3u</code></td></tr>
<tr><td>🇱🇾 Libya</td><td align="right">56</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ly.m3u</code></td></tr> <tr><td>🇱🇾 Libya</td><td align="right">57</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ly.m3u</code></td></tr>
<tr><td>🇱🇮 Liechtenstein</td><td align="right">16</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/li.m3u</code></td></tr> <tr><td>🇱🇮 Liechtenstein</td><td align="right">16</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/li.m3u</code></td></tr>
<tr><td>🇱🇹 Lithuania</td><td align="right">18</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/lt.m3u</code></td></tr> <tr><td>🇱🇹 Lithuania</td><td align="right">19</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/lt.m3u</code></td></tr>
<tr><td>🇱🇺 Luxembourg</td><td align="right">22</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/lu.m3u</code></td></tr> <tr><td>🇱🇺 Luxembourg</td><td align="right">22</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/lu.m3u</code></td></tr>
<tr><td>🇲🇴 Macao</td><td align="right">8</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mo.m3u</code></td></tr> <tr><td>🇲🇴 Macao</td><td align="right">8</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mo.m3u</code></td></tr>
<tr><td>🇲🇬 Madagascar</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mg.m3u</code></td></tr> <tr><td>🇲🇬 Madagascar</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mg.m3u</code></td></tr>
<tr><td>🇲🇼 Malawi</td><td align="right">14</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mw.m3u</code></td></tr> <tr><td>🇲🇼 Malawi</td><td align="right">14</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mw.m3u</code></td></tr>
<tr><td>🇲🇾 Malaysia</td><td align="right">61</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/my.m3u</code></td></tr> <tr><td>🇲🇾 Malaysia</td><td align="right">61</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/my.m3u</code></td></tr>
<tr><td>🇲🇻 Maldives</td><td align="right">9</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mv.m3u</code></td></tr> <tr><td>🇲🇻 Maldives</td><td align="right">10</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mv.m3u</code></td></tr>
<tr><td>🇲🇱 Mali</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ml.m3u</code></td></tr> <tr><td>🇲🇱 Mali</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ml.m3u</code></td></tr>
<tr><td>🇲🇹 Malta</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mt.m3u</code></td></tr> <tr><td>🇲🇹 Malta</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mt.m3u</code></td></tr>
<tr><td>🇲🇭 Marshall Islands</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mh.m3u</code></td></tr> <tr><td>🇲🇭 Marshall Islands</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mh.m3u</code></td></tr>
<tr><td>🇲🇶 Martinique</td><td align="right">10</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mq.m3u</code></td></tr> <tr><td>🇲🇶 Martinique</td><td align="right">10</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mq.m3u</code></td></tr>
<tr><td>🇲🇷 Mauritania</td><td align="right">42</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mr.m3u</code></td></tr> <tr><td>🇲🇷 Mauritania</td><td align="right">43</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mr.m3u</code></td></tr>
<tr><td>🇲🇺 Mauritius</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mu.m3u</code></td></tr> <tr><td>🇲🇺 Mauritius</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mu.m3u</code></td></tr>
<tr><td>🇾🇹 Mayotte</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/yt.m3u</code></td></tr> <tr><td>🇾🇹 Mayotte</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/yt.m3u</code></td></tr>
<tr><td>🇲🇽 Mexico</td><td align="right">207</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mx.m3u</code></td></tr> <tr><td>🇲🇽 Mexico</td><td align="right">210</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mx.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Aguascalientes</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/mx-agu.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Aguascalientes</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/mx-agu.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Baja California</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/mx-bcn.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Baja California</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/mx-bcn.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Chihuahua</td><td align="right">4</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/mx-chh.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Chihuahua</td><td align="right">4</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/mx-chh.m3u</code></td></tr>
@ -562,16 +562,16 @@ Same thing, but split up into separate files:
<tr><td>🇲🇪 Montenegro</td><td align="right">18</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/me.m3u</code></td></tr> <tr><td>🇲🇪 Montenegro</td><td align="right">18</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/me.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ulcinj</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/me-20.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ulcinj</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/me-20.m3u</code></td></tr>
<tr><td>🇲🇸 Montserrat</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ms.m3u</code></td></tr> <tr><td>🇲🇸 Montserrat</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ms.m3u</code></td></tr>
<tr><td>🇲🇦 Morocco</td><td align="right">59</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ma.m3u</code></td></tr> <tr><td>🇲🇦 Morocco</td><td align="right">60</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ma.m3u</code></td></tr>
<tr><td>🇲🇿 Mozambique</td><td align="right">15</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mz.m3u</code></td></tr> <tr><td>🇲🇿 Mozambique</td><td align="right">15</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mz.m3u</code></td></tr>
<tr><td>🇲🇲 Myanmar (Burma)</td><td align="right">47</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mm.m3u</code></td></tr> <tr><td>🇲🇲 Myanmar (Burma)</td><td align="right">47</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mm.m3u</code></td></tr>
<tr><td>🇳🇦 Namibia</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/na.m3u</code></td></tr> <tr><td>🇳🇦 Namibia</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/na.m3u</code></td></tr>
<tr><td>🇳🇷 Nauru</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/nr.m3u</code></td></tr> <tr><td>🇳🇷 Nauru</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/nr.m3u</code></td></tr>
<tr><td>🇳🇵 Nepal</td><td align="right">21</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/np.m3u</code></td></tr> <tr><td>🇳🇵 Nepal</td><td align="right">22</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/np.m3u</code></td></tr>
<tr><td>🇳🇱 Netherlands</td><td align="right">201</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/nl.m3u</code></td></tr> <tr><td>🇳🇱 Netherlands</td><td align="right">201</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/nl.m3u</code></td></tr>
<tr><td>🇳🇨 New Caledonia</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/nc.m3u</code></td></tr> <tr><td>🇳🇨 New Caledonia</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/nc.m3u</code></td></tr>
<tr><td>🇳🇿 New Zealand</td><td align="right">32</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/nz.m3u</code></td></tr> <tr><td>🇳🇿 New Zealand</td><td align="right">32</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/nz.m3u</code></td></tr>
<tr><td>🇳🇮 Nicaragua</td><td align="right">59</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ni.m3u</code></td></tr> <tr><td>🇳🇮 Nicaragua</td><td align="right">62</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ni.m3u</code></td></tr>
<tr><td>🇳🇪 Niger</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ne.m3u</code></td></tr> <tr><td>🇳🇪 Niger</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ne.m3u</code></td></tr>
<tr><td>🇳🇬 Nigeria</td><td align="right">55</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ng.m3u</code></td></tr> <tr><td>🇳🇬 Nigeria</td><td align="right">55</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ng.m3u</code></td></tr>
<tr><td>🇳🇺 Niue</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/nu.m3u</code></td></tr> <tr><td>🇳🇺 Niue</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/nu.m3u</code></td></tr>
@ -580,21 +580,21 @@ Same thing, but split up into separate files:
<tr><td>🇲🇰 North Macedonia</td><td align="right">48</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mk.m3u</code></td></tr> <tr><td>🇲🇰 North Macedonia</td><td align="right">48</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mk.m3u</code></td></tr>
<tr><td>🇲🇵 Northern Mariana Islands</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mp.m3u</code></td></tr> <tr><td>🇲🇵 Northern Mariana Islands</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/mp.m3u</code></td></tr>
<tr><td>🇳🇴 Norway</td><td align="right">24</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/no.m3u</code></td></tr> <tr><td>🇳🇴 Norway</td><td align="right">24</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/no.m3u</code></td></tr>
<tr><td>🇴🇲 Oman</td><td align="right">39</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/om.m3u</code></td></tr> <tr><td>🇴🇲 Oman</td><td align="right">40</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/om.m3u</code></td></tr>
<tr><td>🇵🇰 Pakistan</td><td align="right">75</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pk.m3u</code></td></tr> <tr><td>🇵🇰 Pakistan</td><td align="right">76</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pk.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Islamabad</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pk-is.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Islamabad</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pk-is.m3u</code></td></tr>
<tr><td>🇵🇼 Palau</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pw.m3u</code></td></tr> <tr><td>🇵🇼 Palau</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pw.m3u</code></td></tr>
<tr><td>🇵🇸 Palestine</td><td align="right">59</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ps.m3u</code></td></tr> <tr><td>🇵🇸 Palestine</td><td align="right">60</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ps.m3u</code></td></tr>
<tr><td>🇵🇦 Panama</td><td align="right">62</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pa.m3u</code></td></tr> <tr><td>🇵🇦 Panama</td><td align="right">69</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pa.m3u</code></td></tr>
<tr><td>🇵🇬 Papua New Guinea</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pg.m3u</code></td></tr> <tr><td>🇵🇬 Papua New Guinea</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pg.m3u</code></td></tr>
<tr><td>🇵🇾 Paraguay</td><td align="right">86</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/py.m3u</code></td></tr> <tr><td>🇵🇾 Paraguay</td><td align="right">88</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/py.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alto Parana</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/py-10.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alto Parana</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/py-10.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Boqueron</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/py-19.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Boqueron</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/py-19.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Caaguazu</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/py-5.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Caaguazu</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/py-5.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Central</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/py-11.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Central</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/py-11.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Itapua</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/py-7.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Itapua</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/py-7.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Presidente Hayes</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/py-15.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Presidente Hayes</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/py-15.m3u</code></td></tr>
<tr><td>🇵🇪 Peru</td><td align="right">197</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pe.m3u</code></td></tr> <tr><td>🇵🇪 Peru</td><td align="right">201</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pe.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Amazonas</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-ama.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Amazonas</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-ama.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ancash</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-anc.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ancash</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-anc.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Apurimac</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-apu.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Apurimac</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-apu.m3u</code></td></tr>
@ -606,20 +606,20 @@ Same thing, but split up into separate files:
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Loreto</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-lor.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Loreto</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-lor.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Moquegua</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-moq.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Moquegua</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-moq.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Puno</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-pun.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Puno</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-pun.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;San Martin</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-sam.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;San Martin</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/pe-sam.m3u</code></td></tr>
<tr><td>🇵🇭 Philippines</td><td align="right">50</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ph.m3u</code></td></tr> <tr><td>🇵🇭 Philippines</td><td align="right">50</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ph.m3u</code></td></tr>
<tr><td>🇵🇳 Pitcairn Islands</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pn.m3u</code></td></tr> <tr><td>🇵🇳 Pitcairn Islands</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pn.m3u</code></td></tr>
<tr><td>🇵🇱 Poland</td><td align="right">64</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pl.m3u</code></td></tr> <tr><td>🇵🇱 Poland</td><td align="right">66</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pl.m3u</code></td></tr>
<tr><td>🇵🇹 Portugal</td><td align="right">54</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pt.m3u</code></td></tr> <tr><td>🇵🇹 Portugal</td><td align="right">54</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pt.m3u</code></td></tr>
<tr><td>🇵🇷 Puerto Rico</td><td align="right">83</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pr.m3u</code></td></tr> <tr><td>🇵🇷 Puerto Rico</td><td align="right">86</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/pr.m3u</code></td></tr>
<tr><td>🇶🇦 Qatar</td><td align="right">37</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/qa.m3u</code></td></tr> <tr><td>🇶🇦 Qatar</td><td align="right">38</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/qa.m3u</code></td></tr>
<tr><td>🇨🇬 Republic of the Congo</td><td align="right">16</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cg.m3u</code></td></tr> <tr><td>🇨🇬 Republic of the Congo</td><td align="right">16</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cg.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Brazzaville</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cg-bzv.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Brazzaville</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/cg-bzv.m3u</code></td></tr>
<tr><td>🇷🇪 Réunion</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/re.m3u</code></td></tr>
<tr><td>🇷🇴 Romania</td><td align="right">110</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ro.m3u</code></td></tr> <tr><td>🇷🇴 Romania</td><td align="right">110</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ro.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gorj</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ro-gj.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gorj</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ro-gj.m3u</code></td></tr>
<tr><td>🇷🇺 Russia</td><td align="right">326</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ru.m3u</code></td></tr> <tr><td>🇷🇺 Russia</td><td align="right">326</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ru.m3u</code></td></tr>
<tr><td>🇷🇼 Rwanda</td><td align="right">24</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/rw.m3u</code></td></tr> <tr><td>🇷🇼 Rwanda</td><td align="right">24</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/rw.m3u</code></td></tr>
<tr><td>🇷🇪 Réunion</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/re.m3u</code></td></tr>
<tr><td>🇧🇱 Saint Barthélemy</td><td align="right">8</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bl.m3u</code></td></tr> <tr><td>🇧🇱 Saint Barthélemy</td><td align="right">8</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/bl.m3u</code></td></tr>
<tr><td>🇸🇭 Saint Helena</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sh.m3u</code></td></tr> <tr><td>🇸🇭 Saint Helena</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sh.m3u</code></td></tr>
<tr><td>🇰🇳 Saint Kitts and Nevis</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/kn.m3u</code></td></tr> <tr><td>🇰🇳 Saint Kitts and Nevis</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/kn.m3u</code></td></tr>
@ -629,7 +629,8 @@ Same thing, but split up into separate files:
<tr><td>🇻🇨 Saint Vincent and the Grenadines</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/vc.m3u</code></td></tr> <tr><td>🇻🇨 Saint Vincent and the Grenadines</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/vc.m3u</code></td></tr>
<tr><td>🇼🇸 Samoa</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ws.m3u</code></td></tr> <tr><td>🇼🇸 Samoa</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ws.m3u</code></td></tr>
<tr><td>🇸🇲 San Marino</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sm.m3u</code></td></tr> <tr><td>🇸🇲 San Marino</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sm.m3u</code></td></tr>
<tr><td>🇸🇦 Saudi Arabia</td><td align="right">73</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sa.m3u</code></td></tr> <tr><td>🇸🇹 São Tomé and Príncipe</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/st.m3u</code></td></tr>
<tr><td>🇸🇦 Saudi Arabia</td><td align="right">74</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sa.m3u</code></td></tr>
<tr><td>🇸🇳 Senegal</td><td align="right">30</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sn.m3u</code></td></tr> <tr><td>🇸🇳 Senegal</td><td align="right">30</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sn.m3u</code></td></tr>
<tr><td>🇷🇸 Serbia</td><td align="right">89</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/rs.m3u</code></td></tr> <tr><td>🇷🇸 Serbia</td><td align="right">89</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/rs.m3u</code></td></tr>
<tr><td>🇸🇨 Seychelles</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sc.m3u</code></td></tr> <tr><td>🇸🇨 Seychelles</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sc.m3u</code></td></tr>
@ -639,7 +640,7 @@ Same thing, but split up into separate files:
<tr><td>🇸🇰 Slovakia</td><td align="right">62</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sk.m3u</code></td></tr> <tr><td>🇸🇰 Slovakia</td><td align="right">62</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sk.m3u</code></td></tr>
<tr><td>🇸🇮 Slovenia</td><td align="right">37</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/si.m3u</code></td></tr> <tr><td>🇸🇮 Slovenia</td><td align="right">37</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/si.m3u</code></td></tr>
<tr><td>🇸🇧 Solomon Islands</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sb.m3u</code></td></tr> <tr><td>🇸🇧 Solomon Islands</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sb.m3u</code></td></tr>
<tr><td>🇸🇴 Somalia</td><td align="right">61</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/so.m3u</code></td></tr> <tr><td>🇸🇴 Somalia</td><td align="right">62</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/so.m3u</code></td></tr>
<tr><td>🇿🇦 South Africa</td><td align="right">36</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/za.m3u</code></td></tr> <tr><td>🇿🇦 South Africa</td><td align="right">36</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/za.m3u</code></td></tr>
<tr><td>🇬🇸 South Georgia and the South Sandwich Islands</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gs.m3u</code></td></tr> <tr><td>🇬🇸 South Georgia and the South Sandwich Islands</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/gs.m3u</code></td></tr>
<tr><td>🇰🇷 South Korea</td><td align="right">112</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/kr.m3u</code></td></tr> <tr><td>🇰🇷 South Korea</td><td align="right">112</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/kr.m3u</code></td></tr>
@ -658,13 +659,9 @@ Same thing, but split up into separate files:
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ulsan-gwangyeoksi</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/kr-31.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ulsan-gwangyeoksi</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/kr-31.m3u</code></td></tr>
<tr><td>🇸🇸 South Sudan</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ss.m3u</code></td></tr> <tr><td>🇸🇸 South Sudan</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ss.m3u</code></td></tr>
<tr><td>🇪🇸 Spain</td><td align="right">326</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/es.m3u</code></td></tr> <tr><td>🇪🇸 Spain</td><td align="right">326</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/es.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Asturias, Principado de</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-as.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Madrid, Comunidad de</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-md.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Murcia, Region de</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-mc.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Navarra, Comunidad Foral de</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-nc.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Valenciana, Comunidad</td><td align="right">15</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-vc.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Andalucia</td><td align="right">38</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-an.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Andalucia</td><td align="right">38</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-an.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Aragon</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-ar.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Aragon</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-ar.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Asturias, Principado de</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-as.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Canarias</td><td align="right">11</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-cn.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Canarias</td><td align="right">11</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-cn.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Castilla y Leon</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-cl.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Castilla y Leon</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-cl.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Castilla-La Mancha</td><td align="right">17</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-cm.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Castilla-La Mancha</td><td align="right">17</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-cm.m3u</code></td></tr>
@ -673,15 +670,18 @@ Same thing, but split up into separate files:
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Galicia</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-ga.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Galicia</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-ga.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Illes Balears</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-ib.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Illes Balears</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-ib.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;La Rioja</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-ri.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;La Rioja</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-ri.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Madrid, Comunidad de</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-md.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Murcia, Region de</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-mc.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Navarra, Comunidad Foral de</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-nc.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pais Vasco</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-pv.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pais Vasco</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-pv.m3u</code></td></tr>
<tr><td>🇱🇰 Sri Lanka</td><td align="right">18</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/lk.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Valenciana, Comunidad</td><td align="right">15</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/es-vc.m3u</code></td></tr>
<tr><td>🇸🇩 Sudan</td><td align="right">49</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sd.m3u</code></td></tr> <tr><td>🇱🇰 Sri Lanka</td><td align="right">20</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/lk.m3u</code></td></tr>
<tr><td>🇸🇩 Sudan</td><td align="right">50</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sd.m3u</code></td></tr>
<tr><td>🇸🇷 Suriname</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sr.m3u</code></td></tr> <tr><td>🇸🇷 Suriname</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sr.m3u</code></td></tr>
<tr><td>🇸🇿 Swaziland</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sz.m3u</code></td></tr> <tr><td>🇸🇿 Swaziland</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sz.m3u</code></td></tr>
<tr><td>🇸🇪 Sweden</td><td align="right">44</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/se.m3u</code></td></tr> <tr><td>🇸🇪 Sweden</td><td align="right">43</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/se.m3u</code></td></tr>
<tr><td>🇨🇭 Switzerland</td><td align="right">71</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ch.m3u</code></td></tr> <tr><td>🇨🇭 Switzerland</td><td align="right">71</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ch.m3u</code></td></tr>
<tr><td>🇸🇾 Syria</td><td align="right">45</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sy.m3u</code></td></tr> <tr><td>🇸🇾 Syria</td><td align="right">46</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/sy.m3u</code></td></tr>
<tr><td>🇸🇹 São Tomé and Príncipe</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/st.m3u</code></td></tr>
<tr><td>🇹🇼 Taiwan</td><td align="right">69</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tw.m3u</code></td></tr> <tr><td>🇹🇼 Taiwan</td><td align="right">69</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tw.m3u</code></td></tr>
<tr><td>🇹🇯 Tajikistan</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tj.m3u</code></td></tr> <tr><td>🇹🇯 Tajikistan</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tj.m3u</code></td></tr>
<tr><td>🇹🇿 Tanzania</td><td align="right">23</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tz.m3u</code></td></tr> <tr><td>🇹🇿 Tanzania</td><td align="right">23</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tz.m3u</code></td></tr>
@ -690,7 +690,7 @@ Same thing, but split up into separate files:
<tr><td>🇹🇰 Tokelau</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tk.m3u</code></td></tr> <tr><td>🇹🇰 Tokelau</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tk.m3u</code></td></tr>
<tr><td>🇹🇴 Tonga</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/to.m3u</code></td></tr> <tr><td>🇹🇴 Tonga</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/to.m3u</code></td></tr>
<tr><td>🇹🇹 Trinidad and Tobago</td><td align="right">8</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tt.m3u</code></td></tr> <tr><td>🇹🇹 Trinidad and Tobago</td><td align="right">8</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tt.m3u</code></td></tr>
<tr><td>🇹🇳 Tunisia</td><td align="right">53</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tn.m3u</code></td></tr> <tr><td>🇹🇳 Tunisia</td><td align="right">54</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tn.m3u</code></td></tr>
<tr><td>🇹🇷 Turkey</td><td align="right">226</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tr.m3u</code></td></tr> <tr><td>🇹🇷 Turkey</td><td align="right">226</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tr.m3u</code></td></tr>
<tr><td>🇹🇲 Turkmenistan</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tm.m3u</code></td></tr> <tr><td>🇹🇲 Turkmenistan</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tm.m3u</code></td></tr>
<tr><td>🇹🇨 Turks and Caicos Islands</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tc.m3u</code></td></tr> <tr><td>🇹🇨 Turks and Caicos Islands</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/tc.m3u</code></td></tr>
@ -698,10 +698,10 @@ Same thing, but split up into separate files:
<tr><td>🇻🇮 U.S. Virgin Islands</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/vi.m3u</code></td></tr> <tr><td>🇻🇮 U.S. Virgin Islands</td><td align="right">5</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/vi.m3u</code></td></tr>
<tr><td>🇺🇬 Uganda</td><td align="right">26</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ug.m3u</code></td></tr> <tr><td>🇺🇬 Uganda</td><td align="right">26</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ug.m3u</code></td></tr>
<tr><td>🇺🇦 Ukraine</td><td align="right">87</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ua.m3u</code></td></tr> <tr><td>🇺🇦 Ukraine</td><td align="right">87</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ua.m3u</code></td></tr>
<tr><td>🇦🇪 United Arab Emirates</td><td align="right">75</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ae.m3u</code></td></tr> <tr><td>🇦🇪 United Arab Emirates</td><td align="right">76</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ae.m3u</code></td></tr>
<tr><td>🇬🇧 United Kingdom</td><td align="right">194</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/uk.m3u</code></td></tr> <tr><td>🇬🇧 United Kingdom</td><td align="right">194</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/uk.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Wales</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/gb-wls.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Wales</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/gb-wls.m3u</code></td></tr>
<tr><td>🇺🇸 United States</td><td align="right">1889</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/us.m3u</code></td></tr> <tr><td>🇺🇸 United States</td><td align="right">1892</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/us.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alabama</td><td align="right">4</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/us-al.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alabama</td><td align="right">4</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/us-al.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alaska</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/us-ak.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alaska</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/us-ak.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Arizona</td><td align="right">14</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/us-az.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Arizona</td><td align="right">14</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/us-az.m3u</code></td></tr>
@ -753,17 +753,17 @@ Same thing, but split up into separate files:
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Washington</td><td align="right">8</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/us-wa.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Washington</td><td align="right">8</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/us-wa.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Wisconsin</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/us-wi.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Wisconsin</td><td align="right">7</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/us-wi.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Wyoming</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/us-wy.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Wyoming</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/us-wy.m3u</code></td></tr>
<tr><td>🇺🇾 Uruguay</td><td align="right">58</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/uy.m3u</code></td></tr> <tr><td>🇺🇾 Uruguay</td><td align="right">60</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/uy.m3u</code></td></tr>
<tr><td>🇺🇿 Uzbekistan</td><td align="right">9</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/uz.m3u</code></td></tr> <tr><td>🇺🇿 Uzbekistan</td><td align="right">9</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/uz.m3u</code></td></tr>
<tr><td>🇻🇺 Vanuatu</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/vu.m3u</code></td></tr> <tr><td>🇻🇺 Vanuatu</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/vu.m3u</code></td></tr>
<tr><td>🇻🇦 Vatican City</td><td align="right">19</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/va.m3u</code></td></tr> <tr><td>🇻🇦 Vatican City</td><td align="right">19</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/va.m3u</code></td></tr>
<tr><td>🇻🇪 Venezuela</td><td align="right">104</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ve.m3u</code></td></tr> <tr><td>🇻🇪 Venezuela</td><td align="right">107</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ve.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Aragua</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ve-d.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Aragua</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ve-d.m3u</code></td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Lara</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ve-k.m3u</code></td></tr> <tr><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Lara</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ve-k.m3u</code></td></tr>
<tr><td>🇻🇳 Vietnam</td><td align="right">125</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/vn.m3u</code></td></tr> <tr><td>🇻🇳 Vietnam</td><td align="right">125</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/vn.m3u</code></td></tr>
<tr><td>🇼🇫 Wallis and Futuna</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/wf.m3u</code></td></tr> <tr><td>🇼🇫 Wallis and Futuna</td><td align="right">6</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/wf.m3u</code></td></tr>
<tr><td>🇪🇭 Western Sahara</td><td align="right">17</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/eh.m3u</code></td></tr> <tr><td>🇪🇭 Western Sahara</td><td align="right">17</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/eh.m3u</code></td></tr>
<tr><td>🇾🇪 Yemen</td><td align="right">43</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ye.m3u</code></td></tr> <tr><td>🇾🇪 Yemen</td><td align="right">44</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ye.m3u</code></td></tr>
<tr><td>🇿🇲 Zambia</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/zm.m3u</code></td></tr> <tr><td>🇿🇲 Zambia</td><td align="right">13</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/zm.m3u</code></td></tr>
<tr><td>🇿🇼 Zimbabwe</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/zw.m3u</code></td></tr> <tr><td>🇿🇼 Zimbabwe</td><td align="right">12</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/zw.m3u</code></td></tr>
<tr><td>🌍 International</td><td align="right">73</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/int.m3u</code></td></tr> <tr><td>🌍 International</td><td align="right">73</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/int.m3u</code></td></tr>
@ -793,37 +793,37 @@ Same thing, but split up into separate files:
</thead> </thead>
<tbody> <tbody>
<tr><td align="left">Africa</td><td align="right">424</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/afr.m3u</code></td></tr> <tr><td align="left">Africa</td><td align="right">424</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/afr.m3u</code></td></tr>
<tr><td align="left">Americas</td><td align="right">3801</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/amer.m3u</code></td></tr> <tr><td align="left">Americas</td><td align="right">3817</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/amer.m3u</code></td></tr>
<tr><td align="left">Asia-Pacific</td><td align="right">1918</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/apac.m3u</code></td></tr> <tr><td align="left">Arab world</td><td align="right">428</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/arab.m3u</code></td></tr>
<tr><td align="left">Arab world</td><td align="right">427</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/arab.m3u</code></td></tr> <tr><td align="left">Asia</td><td align="right">2962</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/asia.m3u</code></td></tr>
<tr><td align="left">Asia-Pacific</td><td align="right">1919</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/apac.m3u</code></td></tr>
<tr><td align="left">Association of Southeast Asian Nations</td><td align="right">472</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/asean.m3u</code></td></tr> <tr><td align="left">Association of Southeast Asian Nations</td><td align="right">472</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/asean.m3u</code></td></tr>
<tr><td align="left">Asia</td><td align="right">2961</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/asia.m3u</code></td></tr>
<tr><td align="left">Benelux</td><td align="right">240</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/benelux.m3u</code></td></tr> <tr><td align="left">Benelux</td><td align="right">240</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/benelux.m3u</code></td></tr>
<tr><td align="left">Caribbean</td><td align="right">252</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/carib.m3u</code></td></tr> <tr><td align="left">Caribbean</td><td align="right">253</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/carib.m3u</code></td></tr>
<tr><td align="left">Central America</td><td align="right">206</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/cenamer.m3u</code></td></tr>
<tr><td align="left">Central and Eastern Europe</td><td align="right">1022</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/cee.m3u</code></td></tr>
<tr><td align="left">Central Asia</td><td align="right">64</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/cas.m3u</code></td></tr> <tr><td align="left">Central Asia</td><td align="right">64</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/cas.m3u</code></td></tr>
<tr><td align="left">Central and Eastern Europe</td><td align="right">1019</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/cee.m3u</code></td></tr>
<tr><td align="left">Central America</td><td align="right">201</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/cenamer.m3u</code></td></tr>
<tr><td align="left">Commonwealth of Independent States</td><td align="right">461</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/cis.m3u</code></td></tr> <tr><td align="left">Commonwealth of Independent States</td><td align="right">461</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/cis.m3u</code></td></tr>
<tr><td align="left">Europe, the Middle East and Africa</td><td align="right">4046</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/emea.m3u</code></td></tr> <tr><td align="left">Europe</td><td align="right">3246</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/eur.m3u</code></td></tr>
<tr><td align="left">Europe</td><td align="right">3227</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/eur.m3u</code></td></tr> <tr><td align="left">Europe, the Middle East and Africa</td><td align="right">4065</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/emea.m3u</code></td></tr>
<tr><td align="left">Hispanic America</td><td align="right">1458</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/hispam.m3u</code></td></tr> <tr><td align="left">Hispanic America</td><td align="right">1474</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/hispam.m3u</code></td></tr>
<tr><td align="left">Latin America and the Caribbean</td><td align="right">1793</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/lac.m3u</code></td></tr> <tr><td align="left">Latin America</td><td align="right">1785</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/latam.m3u</code></td></tr>
<tr><td align="left">Latin America</td><td align="right">1771</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/latam.m3u</code></td></tr> <tr><td align="left">Latin America and the Caribbean</td><td align="right">1807</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/lac.m3u</code></td></tr>
<tr><td align="left">Maghreb</td><td align="right">59</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/maghreb.m3u</code></td></tr> <tr><td align="left">Maghreb</td><td align="right">59</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/maghreb.m3u</code></td></tr>
<tr><td align="left">Middle East and North Africa</td><td align="right">755</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/mena.m3u</code></td></tr>
<tr><td align="left">Middle East</td><td align="right">705</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/mideast.m3u</code></td></tr> <tr><td align="left">Middle East</td><td align="right">705</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/mideast.m3u</code></td></tr>
<tr><td align="left">Northern America</td><td align="right">2023</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/nam.m3u</code></td></tr> <tr><td align="left">Middle East and North Africa</td><td align="right">755</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/mena.m3u</code></td></tr>
<tr><td align="left">Northern Europe</td><td align="right">125</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/neur.m3u</code></td></tr>
<tr><td align="left">North America</td><td align="right">2619</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/noram.m3u</code></td></tr>
<tr><td align="left">Nordics</td><td align="right">97</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/nord.m3u</code></td></tr> <tr><td align="left">Nordics</td><td align="right">97</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/nord.m3u</code></td></tr>
<tr><td align="left">North America</td><td align="right">2627</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/noram.m3u</code></td></tr>
<tr><td align="left">Northern America</td><td align="right">2026</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/nam.m3u</code></td></tr>
<tr><td align="left">Northern Europe</td><td align="right">126</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/neur.m3u</code></td></tr>
<tr><td align="left">Oceania</td><td align="right">55</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/oce.m3u</code></td></tr> <tr><td align="left">Oceania</td><td align="right">55</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/oce.m3u</code></td></tr>
<tr><td align="left">South Asia</td><td align="right">596</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/sas.m3u</code></td></tr> <tr><td align="left">South America</td><td align="right">1195</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/southam.m3u</code></td></tr>
<tr><td align="left">South Asia</td><td align="right">598</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/sas.m3u</code></td></tr>
<tr><td align="left">Southeast Asia</td><td align="right">493</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/sea.m3u</code></td></tr> <tr><td align="left">Southeast Asia</td><td align="right">493</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/sea.m3u</code></td></tr>
<tr><td align="left">Southern Europe</td><td align="right">1103</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/ser.m3u</code></td></tr> <tr><td align="left">Southern Europe</td><td align="right">1104</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/ser.m3u</code></td></tr>
<tr><td align="left">South America</td><td align="right">1187</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/southam.m3u</code></td></tr>
<tr><td align="left">Sub-Saharan Africa</td><td align="right">341</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/ssa.m3u</code></td></tr> <tr><td align="left">Sub-Saharan Africa</td><td align="right">341</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/ssa.m3u</code></td></tr>
<tr><td align="left">West Africa</td><td align="right">140</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/wafr.m3u</code></td></tr> <tr><td align="left">West Africa</td><td align="right">140</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/wafr.m3u</code></td></tr>
<tr><td align="left">Western Europe</td><td align="right">983</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/wer.m3u</code></td></tr> <tr><td align="left">Western Europe</td><td align="right">997</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/regions/wer.m3u</code></td></tr>
</tbody> </tbody>
</table> </table>

@ -0,0 +1,5 @@
{
"pull_request": {
"merged": true
}
}

370
package-lock.json generated

@ -11,7 +11,6 @@
"@octokit/plugin-paginate-rest": "^7.1.2", "@octokit/plugin-paginate-rest": "^7.1.2",
"@octokit/plugin-rest-endpoint-methods": "^7.1.3", "@octokit/plugin-rest-endpoint-methods": "^7.1.3",
"@octokit/types": "^11.1.0", "@octokit/types": "^11.1.0",
"@seald-io/nedb": "^4.0.2",
"@types/fs-extra": "^11.0.1", "@types/fs-extra": "^11.0.1",
"@types/glob": "^8.1.0", "@types/glob": "^8.1.0",
"@types/jest": "^29.5.4", "@types/jest": "^29.5.4",
@ -1338,21 +1337,6 @@
"node": ">=14" "node": ">=14"
} }
}, },
"node_modules/@seald-io/binary-search-tree": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@seald-io/binary-search-tree/-/binary-search-tree-1.0.3.tgz",
"integrity": "sha512-qv3jnwoakeax2razYaMsGI/luWdliBLHTdC6jU55hQt1hcFqzauH/HsBollQ7IR4ySTtYhT+xyHoijpA16C+tA=="
},
"node_modules/@seald-io/nedb": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@seald-io/nedb/-/nedb-4.0.2.tgz",
"integrity": "sha512-gJ91fT1sgh2cLXYVcTSh7khZ8LdemI8+SojCdpZ5wy+DUQ4fSrEwGqOwbdV49NDs2BBO6GeBpSb8CnhG2IW1rw==",
"dependencies": {
"@seald-io/binary-search-tree": "^1.0.3",
"localforage": "^1.9.0",
"util": "^0.12.4"
}
},
"node_modules/@sinclair/typebox": { "node_modules/@sinclair/typebox": {
"version": "0.27.8", "version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@ -1658,17 +1642,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/available-typed-arrays": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/babel-jest": { "node_modules/babel-jest": {
"version": "29.6.4", "version": "29.6.4",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.4.tgz", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.4.tgz",
@ -1855,18 +1828,6 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"peer": true "peer": true
}, },
"node_modules/call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"dependencies": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/callsites": { "node_modules/callsites": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@ -2318,14 +2279,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"dependencies": {
"is-callable": "^1.1.3"
}
},
"node_modules/foreground-child": { "node_modules/foreground-child": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
@ -2395,7 +2348,8 @@
"node_modules/function-bind": { "node_modules/function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"peer": true
}, },
"node_modules/gensync": { "node_modules/gensync": {
"version": "1.0.0-beta.2", "version": "1.0.0-beta.2",
@ -2414,20 +2368,6 @@
"node": "6.* || 8.* || >= 10.*" "node": "6.* || 8.* || >= 10.*"
} }
}, },
"node_modules/get-intrinsic": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
"integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
"dependencies": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-package-type": { "node_modules/get-package-type": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
@ -2595,17 +2535,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"dependencies": {
"get-intrinsic": "^1.1.3"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/graceful-fs": { "node_modules/graceful-fs": {
"version": "4.2.9", "version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
@ -2615,6 +2544,7 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"peer": true,
"dependencies": { "dependencies": {
"function-bind": "^1.1.1" "function-bind": "^1.1.1"
}, },
@ -2630,42 +2560,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/has-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"dependencies": {
"has-symbols": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/html-escaper": { "node_modules/html-escaper": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
@ -2681,11 +2575,6 @@
"node": ">=10.17.0" "node": ">=10.17.0"
} }
}, },
"node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
},
"node_modules/import-local": { "node_modules/import-local": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
@ -2737,32 +2626,6 @@
"validator": "^13.7.0" "validator": "^13.7.0"
} }
}, },
"node_modules/is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-core-module": { "node_modules/is-core-module": {
"version": "2.13.0", "version": "2.13.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
@ -2800,20 +2663,6 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/is-generator-function": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
"integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
"dependencies": {
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-glob": { "node_modules/is-glob": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
@ -2864,20 +2713,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/is-typed-array": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
"integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
"dependencies": {
"which-typed-array": "^1.1.11"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-valid-path": { "node_modules/is-valid-path": {
"version": "0.1.1", "version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz", "resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz",
@ -3808,14 +3643,6 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
"dependencies": {
"immediate": "~3.0.5"
}
},
"node_modules/lines-and-columns": { "node_modules/lines-and-columns": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@ -3856,14 +3683,6 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/localforage": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
"dependencies": {
"lie": "3.1.1"
}
},
"node_modules/locate-path": { "node_modules/locate-path": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@ -5117,18 +4936,6 @@
"node": ">= 4.0.0" "node": ">= 4.0.0"
} }
}, },
"node_modules/util": {
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
"integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
"dependencies": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
"is-generator-function": "^1.0.7",
"is-typed-array": "^1.1.3",
"which-typed-array": "^1.1.2"
}
},
"node_modules/v8-compile-cache-lib": { "node_modules/v8-compile-cache-lib": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
@ -5191,24 +4998,6 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/which-typed-array": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz",
"integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==",
"dependencies": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"for-each": "^0.3.3",
"gopd": "^1.0.1",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/wrap-ansi": { "node_modules/wrap-ansi": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@ -6319,21 +6108,6 @@
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"optional": true "optional": true
}, },
"@seald-io/binary-search-tree": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@seald-io/binary-search-tree/-/binary-search-tree-1.0.3.tgz",
"integrity": "sha512-qv3jnwoakeax2razYaMsGI/luWdliBLHTdC6jU55hQt1hcFqzauH/HsBollQ7IR4ySTtYhT+xyHoijpA16C+tA=="
},
"@seald-io/nedb": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@seald-io/nedb/-/nedb-4.0.2.tgz",
"integrity": "sha512-gJ91fT1sgh2cLXYVcTSh7khZ8LdemI8+SojCdpZ5wy+DUQ4fSrEwGqOwbdV49NDs2BBO6GeBpSb8CnhG2IW1rw==",
"requires": {
"@seald-io/binary-search-tree": "^1.0.3",
"localforage": "^1.9.0",
"util": "^0.12.4"
}
},
"@sinclair/typebox": { "@sinclair/typebox": {
"version": "0.27.8", "version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@ -6608,11 +6382,6 @@
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
"integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==" "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q=="
}, },
"available-typed-arrays": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
},
"babel-jest": { "babel-jest": {
"version": "29.6.4", "version": "29.6.4",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.4.tgz", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.4.tgz",
@ -6761,15 +6530,6 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"peer": true "peer": true
}, },
"call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
}
},
"callsites": { "callsites": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@ -7089,14 +6849,6 @@
"path-exists": "^4.0.0" "path-exists": "^4.0.0"
} }
}, },
"for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"requires": {
"is-callable": "^1.1.3"
}
},
"foreground-child": { "foreground-child": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
@ -7145,7 +6897,8 @@
"function-bind": { "function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"peer": true
}, },
"gensync": { "gensync": {
"version": "1.0.0-beta.2", "version": "1.0.0-beta.2",
@ -7158,17 +6911,6 @@
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
}, },
"get-intrinsic": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
"integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3"
}
},
"get-package-type": { "get-package-type": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
@ -7293,14 +7035,6 @@
} }
} }
}, },
"gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"requires": {
"get-intrinsic": "^1.1.3"
}
},
"graceful-fs": { "graceful-fs": {
"version": "4.2.9", "version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
@ -7310,6 +7044,7 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"peer": true,
"requires": { "requires": {
"function-bind": "^1.1.1" "function-bind": "^1.1.1"
} }
@ -7319,24 +7054,6 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
}, },
"has-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg=="
},
"has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
},
"has-tostringtag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"requires": {
"has-symbols": "^1.0.2"
}
},
"html-escaper": { "html-escaper": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
@ -7349,11 +7066,6 @@
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
"peer": true "peer": true
}, },
"immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
},
"import-local": { "import-local": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
@ -7393,20 +7105,6 @@
"validator": "^13.7.0" "validator": "^13.7.0"
} }
}, },
"is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
}
},
"is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="
},
"is-core-module": { "is-core-module": {
"version": "2.13.0", "version": "2.13.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
@ -7432,14 +7130,6 @@
"integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
"peer": true "peer": true
}, },
"is-generator-function": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
"integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
"requires": {
"has-tostringtag": "^1.0.0"
}
},
"is-glob": { "is-glob": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
@ -7472,14 +7162,6 @@
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"peer": true "peer": true
}, },
"is-typed-array": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
"integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
"requires": {
"which-typed-array": "^1.1.11"
}
},
"is-valid-path": { "is-valid-path": {
"version": "0.1.1", "version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz", "resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz",
@ -8186,14 +7868,6 @@
"integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
"peer": true "peer": true
}, },
"lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
"requires": {
"immediate": "~3.0.5"
}
},
"lines-and-columns": { "lines-and-columns": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@ -8227,14 +7901,6 @@
} }
} }
}, },
"localforage": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
"requires": {
"lie": "3.1.1"
}
},
"locate-path": { "locate-path": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@ -9116,18 +8782,6 @@
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
}, },
"util": {
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
"integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
"requires": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
"is-generator-function": "^1.0.7",
"is-typed-array": "^1.1.3",
"which-typed-array": "^1.1.2"
}
},
"v8-compile-cache-lib": { "v8-compile-cache-lib": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
@ -9180,18 +8834,6 @@
"isexe": "^2.0.0" "isexe": "^2.0.0"
} }
}, },
"which-typed-array": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz",
"integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==",
"requires": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"for-each": "^0.3.3",
"gopd": "^1.0.1",
"has-tostringtag": "^1.0.0"
}
},
"wrap-ansi": { "wrap-ansi": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",

@ -2,11 +2,12 @@
"name": "iptv", "name": "iptv",
"scripts": { "scripts": {
"act:check": "act pull_request -W .github/workflows/check.yml", "act:check": "act pull_request -W .github/workflows/check.yml",
"act:format": "act workflow_dispatch -W .github/workflows/format.yml",
"act:update": "act workflow_dispatch -W .github/workflows/update.yml", "act:update": "act workflow_dispatch -W .github/workflows/update.yml",
"api:load": "./scripts/commands/api/load.sh", "api:load": "./scripts/commands/api/load.sh",
"api:generate": "npm run ts-node scripts/commands/api/generate.ts", "api:generate": "npm run ts-node scripts/commands/api/generate.ts",
"api:deploy": "npx gh-pages-clean && npx gh-pages -a -m \"Deploy to iptv-org/api\" -d .api -r https://$GITHUB_TOKEN@github.com/iptv-org/api.git", "api:deploy": "npx gh-pages-clean && npx gh-pages -a -m \"Deploy to iptv-org/api\" -d .api -r https://$GITHUB_TOKEN@github.com/iptv-org/api.git",
"db:create": "npm run ts-node scripts/commands/database/create.ts", "playlist:format": "npm run ts-node scripts/commands/playlist/format.ts",
"playlist:update": "npm run ts-node scripts/commands/playlist/update.ts", "playlist:update": "npm run ts-node scripts/commands/playlist/update.ts",
"playlist:generate": "npm run ts-node scripts/commands/playlist/generate.ts", "playlist:generate": "npm run ts-node scripts/commands/playlist/generate.ts",
"playlist:validate": "npm run ts-node scripts/commands/playlist/validate.ts", "playlist:validate": "npm run ts-node scripts/commands/playlist/validate.ts",
@ -14,9 +15,9 @@
"playlist:deploy": "npx gh-pages-clean && npx gh-pages -m \"Deploy to GitHub Pages\" -d .gh-pages -r https://$GITHUB_TOKEN@github.com/iptv-org/iptv.git", "playlist:deploy": "npx gh-pages-clean && npx gh-pages -m \"Deploy to GitHub Pages\" -d .gh-pages -r https://$GITHUB_TOKEN@github.com/iptv-org/iptv.git",
"readme:update": "npm run ts-node scripts/commands/readme/update.ts", "readme:update": "npm run ts-node scripts/commands/readme/update.ts",
"report:create": "npm run ts-node scripts/commands/report/create.ts", "report:create": "npm run ts-node scripts/commands/report/create.ts",
"format": "npm run db:create && npm run playlist:format", "format": "npm run api:load && npm run playlist:format",
"check": "npm run api:load && npm run playlist:lint && npm run playlist:validate", "check": "npm run api:load && npm run playlist:lint && npm run playlist:validate",
"update": "npm run api:load && npm run db:create && npm run playlist:generate && npm run api:generate && npm run readme:update", "update": "npm run api:load && npm run playlist:generate && npm run api:generate && npm run readme:update",
"deploy": "npm run playlist:deploy && npm run api:deploy", "deploy": "npm run playlist:deploy && npm run api:deploy",
"report": "npm run api:load && npm run report:create", "report": "npm run api:load && npm run report:create",
"test": "jest --runInBand", "test": "jest --runInBand",
@ -45,7 +46,6 @@
"@octokit/plugin-paginate-rest": "^7.1.2", "@octokit/plugin-paginate-rest": "^7.1.2",
"@octokit/plugin-rest-endpoint-methods": "^7.1.3", "@octokit/plugin-rest-endpoint-methods": "^7.1.3",
"@octokit/types": "^11.1.0", "@octokit/types": "^11.1.0",
"@seald-io/nedb": "^4.0.2",
"@types/fs-extra": "^11.0.1", "@types/fs-extra": "^11.0.1",
"@types/glob": "^8.1.0", "@types/glob": "^8.1.0",
"@types/jest": "^29.5.4", "@types/jest": "^29.5.4",

@ -1,16 +1,16 @@
import { API_DIR, DB_DIR } from '../../constants' import { API_DIR, STREAMS_DIR } from '../../constants'
import { Logger, Database, Collection, Storage } from '../../core' import { Logger, PlaylistParser, Storage } from '../../core'
import { Stream } from '../../models' import { Stream } from '../../models'
async function main() { async function main() {
const logger = new Logger() const logger = new Logger()
logger.info(`loading streams...`) logger.info('loading streams...')
const db = new Database(DB_DIR) const streamsStorage = new Storage(STREAMS_DIR)
const dbStreams = await db.load('streams.db') const parser = new PlaylistParser({ storage: streamsStorage })
const docs = await dbStreams.find({}) const files = await streamsStorage.list('**/*.m3u')
let streams = await parser.parse(files)
const streams = new Collection(docs as any[]) streams = streams
.map(data => new Stream(data)) .map(data => new Stream(data))
.orderBy((stream: Stream) => stream.channel) .orderBy((stream: Stream) => stream.channel)
.map((stream: Stream) => stream.toJSON()) .map((stream: Stream) => stream.toJSON())
@ -18,8 +18,8 @@ async function main() {
logger.info(`found ${streams.count()} streams`) logger.info(`found ${streams.count()} streams`)
logger.info('saving to .api/streams.json...') logger.info('saving to .api/streams.json...')
const storage = new Storage(API_DIR) const apiStorage = new Storage(API_DIR)
await storage.save('streams.json', streams.toJSON()) await apiStorage.save('streams.json', streams.toJSON())
} }
main() main()

@ -4,7 +4,6 @@ mkdir -p temp/data
curl -L -o temp/data/blocklist.json https://iptv-org.github.io/api/blocklist.json curl -L -o temp/data/blocklist.json https://iptv-org.github.io/api/blocklist.json
curl -L -o temp/data/categories.json https://iptv-org.github.io/api/categories.json curl -L -o temp/data/categories.json https://iptv-org.github.io/api/categories.json
curl -L -o temp/data/channels.json https://iptv-org.github.io/api/channels.json curl -L -o temp/data/channels.json https://iptv-org.github.io/api/channels.json
curl -L -o temp/data/streams.json https://iptv-org.github.io/api/streams.json
curl -L -o temp/data/countries.json https://iptv-org.github.io/api/countries.json curl -L -o temp/data/countries.json https://iptv-org.github.io/api/countries.json
curl -L -o temp/data/languages.json https://iptv-org.github.io/api/languages.json curl -L -o temp/data/languages.json https://iptv-org.github.io/api/languages.json
curl -L -o temp/data/regions.json https://iptv-org.github.io/api/regions.json curl -L -o temp/data/regions.json https://iptv-org.github.io/api/regions.json

@ -1,33 +0,0 @@
import { Storage, Logger, PlaylistParser, Collection, Database } from '../../core'
import { Stream, Playlist } from '../../models'
import { STREAMS_DIR, DB_DIR } from '../../constants'
async function main() {
const logger = new Logger()
logger.info(`looking for streams...`)
const storage = new Storage(STREAMS_DIR)
const parser = new PlaylistParser({
storage
})
const files = await storage.list(`**/*.m3u`)
let streams = new Collection()
for (let filepath of files) {
const playlist: Playlist = await parser.parse(filepath)
streams = streams.concat(playlist.streams)
}
logger.info(`found ${streams.count()} streams`)
logger.info('clean up the storage...')
const dbStorage = new Storage(DB_DIR)
await dbStorage.clear('streams.db')
logger.info('saving streams to the database...')
const db = new Database(DB_DIR)
const dbStreams = await db.load('streams.db')
const data = streams.map((stream: Stream) => stream.data()).all()
await dbStreams.insert(data)
}
main()

@ -0,0 +1,67 @@
import { STREAMS_DIR, DATA_DIR } from '../../constants'
import { Storage, Logger, PlaylistParser, Collection } from '../../core'
import { Stream, Playlist, Channel } from '../../models'
import { program } from 'commander'
program.argument('[filepath]', 'Path to file to validate').parse(process.argv)
async function main() {
const storage = new Storage(STREAMS_DIR)
const logger = new Logger()
logger.info('loading channels from api...')
const dataStorage = new Storage(DATA_DIR)
const channelsContent = await dataStorage.json('channels.json')
const groupedChannels = new Collection(channelsContent)
.map(data => new Channel(data))
.keyBy((channel: Channel) => channel.id)
logger.info('loading streams...')
const parser = new PlaylistParser({ storage })
const files = program.args.length ? program.args : await storage.list('**/*.m3u')
let streams = await parser.parse(files)
logger.info(`found ${streams.count()} streams`)
logger.info('normalizing links...')
streams = streams.map(stream => {
stream.normalizeURL()
return stream
})
logger.info('removing duplicates...')
streams = streams.uniqBy(stream => stream.url)
logger.info('removing wrong id...')
streams = streams.map((stream: Stream) => {
if (groupedChannels.missing(stream.channel)) {
stream.channel = ''
}
return stream
})
logger.info('sorting links...')
streams = streams.orderBy(
[
(stream: Stream) => stream.name,
(stream: Stream) => parseInt(stream.quality.replace('p', '')),
(stream: Stream) => stream.label,
(stream: Stream) => stream.url
],
['asc', 'desc', 'asc', 'asc']
)
logger.info('saving...')
const groupedStreams = streams.groupBy((stream: Stream) => stream.filepath)
for (let filepath of groupedStreams.keys()) {
const streams = groupedStreams.get(filepath) || []
if (!streams.length) return
const playlist = new Playlist(streams, { public: false })
await storage.save(filepath, playlist.toString())
}
}
main()

@ -1,6 +1,5 @@
import { File, Storage } from '../../core' import { File, PlaylistParser, Storage } from '../../core'
import { Stream, Category, Channel, Language, Country, Region, Subdivision } from '../../models' import { Stream, Category, Channel, Language, Country, Region, Subdivision } from '../../models'
import { Database } from '../../core/database'
import { Collection } from '../../core/collection' import { Collection } from '../../core/collection'
import { Logger } from '../../core/logger' import { Logger } from '../../core/logger'
import _ from 'lodash' import _ from 'lodash'
@ -16,32 +15,31 @@ import {
IndexLanguageGenerator, IndexLanguageGenerator,
IndexRegionGenerator IndexRegionGenerator
} from '../../generators' } from '../../generators'
import { DATA_DIR, DB_DIR, LOGS_DIR } from '../../constants' import { DATA_DIR, LOGS_DIR, STREAMS_DIR } from '../../constants'
async function main() { async function main() {
const logger = new Logger() const logger = new Logger()
const dataStorage = new Storage(DATA_DIR)
const storage = new Storage(DATA_DIR) logger.info('loading data from api...')
const channelsContent = await dataStorage.json('channels.json')
const channelsContent = await storage.json('channels.json')
const channels = new Collection(channelsContent).map(data => new Channel(data)) const channels = new Collection(channelsContent).map(data => new Channel(data))
const categoriesContent = await dataStorage.json('categories.json')
const categoriesContent = await storage.json('categories.json')
const categories = new Collection(categoriesContent).map(data => new Category(data)) const categories = new Collection(categoriesContent).map(data => new Category(data))
const countriesContent = await dataStorage.json('countries.json')
const countriesContent = await storage.json('countries.json')
const countries = new Collection(countriesContent).map(data => new Country(data)) const countries = new Collection(countriesContent).map(data => new Country(data))
const languagesContent = await dataStorage.json('languages.json')
const languagesContent = await storage.json('languages.json')
const languages = new Collection(languagesContent).map(data => new Language(data)) const languages = new Collection(languagesContent).map(data => new Language(data))
const regionsContent = await dataStorage.json('regions.json')
const regionsContent = await storage.json('regions.json')
const regions = new Collection(regionsContent).map(data => new Region(data)) const regions = new Collection(regionsContent).map(data => new Region(data))
const subdivisionsContent = await dataStorage.json('subdivisions.json')
const subdivisionsContent = await storage.json('subdivisions.json')
const subdivisions = new Collection(subdivisionsContent).map(data => new Subdivision(data)) const subdivisions = new Collection(subdivisionsContent).map(data => new Subdivision(data))
const streams = await loadStreams({ channels, categories, languages }) logger.info('loading streams...')
let streams = await loadStreams({ channels, categories, languages })
let totalStreams = streams.count()
streams = streams.uniqBy((stream: Stream) => stream.channel || _.uniqueId())
logger.info(`found ${totalStreams} streams (including ${streams.count()} unique)`)
const generatorsLogger = new Logger({ const generatorsLogger = new Logger({
stream: await new Storage(LOGS_DIR).createStream(`generators.log`) stream: await new Storage(LOGS_DIR).createStream(`generators.log`)
@ -49,7 +47,6 @@ async function main() {
logger.info('generating categories/...') logger.info('generating categories/...')
await new CategoriesGenerator({ categories, streams, logger: generatorsLogger }).generate() await new CategoriesGenerator({ categories, streams, logger: generatorsLogger }).generate()
logger.info('generating countries/...') logger.info('generating countries/...')
await new CountriesGenerator({ await new CountriesGenerator({
countries, countries,
@ -58,10 +55,8 @@ async function main() {
subdivisions, subdivisions,
logger: generatorsLogger logger: generatorsLogger
}).generate() }).generate()
logger.info('generating languages/...') logger.info('generating languages/...')
await new LanguagesGenerator({ streams, logger: generatorsLogger }).generate() await new LanguagesGenerator({ streams, logger: generatorsLogger }).generate()
logger.info('generating regions/...') logger.info('generating regions/...')
await new RegionsGenerator({ await new RegionsGenerator({
streams, streams,
@ -69,16 +64,12 @@ async function main() {
subdivisions, subdivisions,
logger: generatorsLogger logger: generatorsLogger
}).generate() }).generate()
logger.info('generating index.m3u...') logger.info('generating index.m3u...')
await new IndexGenerator({ streams, logger: generatorsLogger }).generate() await new IndexGenerator({ streams, logger: generatorsLogger }).generate()
logger.info('generating index.nsfw.m3u...') logger.info('generating index.nsfw.m3u...')
await new IndexNsfwGenerator({ streams, logger: generatorsLogger }).generate() await new IndexNsfwGenerator({ streams, logger: generatorsLogger }).generate()
logger.info('generating index.category.m3u...') logger.info('generating index.category.m3u...')
await new IndexCategoryGenerator({ streams, logger: generatorsLogger }).generate() await new IndexCategoryGenerator({ streams, logger: generatorsLogger }).generate()
logger.info('generating index.country.m3u...') logger.info('generating index.country.m3u...')
await new IndexCountryGenerator({ await new IndexCountryGenerator({
streams, streams,
@ -87,10 +78,8 @@ async function main() {
subdivisions, subdivisions,
logger: generatorsLogger logger: generatorsLogger
}).generate() }).generate()
logger.info('generating index.language.m3u...') logger.info('generating index.language.m3u...')
await new IndexLanguageGenerator({ streams, logger: generatorsLogger }).generate() await new IndexLanguageGenerator({ streams, logger: generatorsLogger }).generate()
logger.info('generating index.region.m3u...') logger.info('generating index.region.m3u...')
await new IndexRegionGenerator({ streams, regions, logger: generatorsLogger }).generate() await new IndexRegionGenerator({ streams, regions, logger: generatorsLogger }).generate()
} }
@ -110,13 +99,13 @@ async function loadStreams({
const groupedCategories = categories.keyBy(category => category.id) const groupedCategories = categories.keyBy(category => category.id)
const groupedLanguages = languages.keyBy(language => language.code) const groupedLanguages = languages.keyBy(language => language.code)
const db = new Database(DB_DIR) const storage = new Storage(STREAMS_DIR)
const dbStreams = await db.load('streams.db') const parser = new PlaylistParser({ storage })
const docs = await dbStreams.find({}) const files = await storage.list('**/*.m3u')
const streams = new Collection(docs as any[]) let streams = await parser.parse(files)
.map((data: any) => new Stream(data))
streams = streams
.orderBy([(stream: Stream) => stream.channel, (stream: Stream) => stream.url], ['asc', 'asc']) .orderBy([(stream: Stream) => stream.channel, (stream: Stream) => stream.url], ['asc', 'asc'])
.uniqBy((stream: Stream) => stream.channel || _.uniqueId())
.map((stream: Stream) => { .map((stream: Stream) => {
const channel: Channel | undefined = groupedChannels.get(stream.channel) const channel: Channel | undefined = groupedChannels.get(stream.channel)

@ -1,6 +1,6 @@
import { DB_DIR, DATA_DIR, STREAMS_DIR } from '../../constants' import { DATA_DIR, STREAMS_DIR } from '../../constants'
import { Database, Storage, Logger, Collection, Dictionary, IssueLoader } from '../../core' import { Storage, Logger, Collection, Dictionary, IssueLoader, PlaylistParser } from '../../core'
import { Stream, Playlist, Channel } from '../../models' import { Stream, Playlist, Channel, Issue } from '../../models'
let processedIssues = new Collection() let processedIssues = new Collection()
let streams: Collection let streams: Collection
@ -10,19 +10,19 @@ async function main() {
const logger = new Logger({ disabled: true }) const logger = new Logger({ disabled: true })
const loader = new IssueLoader() const loader = new IssueLoader()
logger.info('loading streams...') logger.info('loading channels from api...')
const db = new Database(DB_DIR) const dataStorage = new Storage(DATA_DIR)
const docs = await db.load('streams.db') const channelsContent = await dataStorage.json('channels.json')
const dbStreams = await docs.find({})
streams = new Collection(dbStreams as any[]).map(data => new Stream(data))
const storage = new Storage(DATA_DIR)
const channelsContent = await storage.json('channels.json')
groupedChannels = new Collection(channelsContent) groupedChannels = new Collection(channelsContent)
.map(data => new Channel(data)) .map(data => new Channel(data))
.keyBy((channel: Channel) => channel.id) .keyBy((channel: Channel) => channel.id)
logger.info('loading streams...')
const streamsStorage = new Storage(STREAMS_DIR)
const parser = new PlaylistParser({ storage: streamsStorage })
const files = await streamsStorage.list('**/*.m3u')
streams = await parser.parse(files)
logger.info('removing broken streams...') logger.info('removing broken streams...')
await removeStreams(loader) await removeStreams(loader)
@ -32,25 +32,7 @@ async function main() {
logger.info('add new streams...') logger.info('add new streams...')
await addStreams(loader) await addStreams(loader)
logger.info('normalizing links...')
streams = streams.map(stream => {
stream.normalizeURL()
return stream
})
logger.info('sorting links...')
streams = streams.orderBy(
[
(stream: Stream) => stream.name,
(stream: Stream) => parseInt(stream.quality.replace('p', '')),
(stream: Stream) => stream.label,
(stream: Stream) => stream.url
],
['asc', 'desc', 'asc', 'asc']
)
logger.info('saving...') logger.info('saving...')
const streamsStorage = new Storage(STREAMS_DIR)
const groupedStreams = streams.groupBy((stream: Stream) => stream.filepath) const groupedStreams = streams.groupBy((stream: Stream) => stream.filepath)
for (let filepath of groupedStreams.keys()) { for (let filepath of groupedStreams.keys()) {
const streams = groupedStreams.get(filepath) || [] const streams = groupedStreams.get(filepath) || []
@ -69,19 +51,22 @@ main()
async function removeStreams(loader: IssueLoader) { async function removeStreams(loader: IssueLoader) {
const issues = await loader.load({ labels: ['streams:remove', 'approved'] }) const issues = await loader.load({ labels: ['streams:remove', 'approved'] })
issues.forEach((data: Dictionary) => { issues.forEach((issue: Issue) => {
const data = issue.data
if (data.missing('stream_url')) return if (data.missing('stream_url')) return
const removed = streams.remove((_stream: Stream) => _stream.url === data.get('stream_url')) const removed = streams.remove((_stream: Stream) => _stream.url === data.get('stream_url'))
if (removed.notEmpty()) { if (removed.notEmpty()) {
processedIssues.add(data.get('issue_number')) processedIssues.add(issue.number)
} }
}) })
} }
async function editStreams(loader: IssueLoader) { async function editStreams(loader: IssueLoader) {
const issues = await loader.load({ labels: ['streams:edit', 'approved'] }) const issues = await loader.load({ labels: ['streams:edit', 'approved'] })
issues.forEach((data: Dictionary) => { issues.forEach((issue: Issue) => {
const data = issue.data
if (data.missing('stream_url')) return if (data.missing('stream_url')) return
let stream = streams.first( let stream = streams.first(
@ -111,13 +96,14 @@ async function editStreams(loader: IssueLoader) {
streams.remove((_stream: Stream) => _stream.channel === stream.channel) streams.remove((_stream: Stream) => _stream.channel === stream.channel)
streams.add(stream) streams.add(stream)
processedIssues.add(data.get('issue_number')) processedIssues.add(issue.number)
}) })
} }
async function addStreams(loader: IssueLoader) { async function addStreams(loader: IssueLoader) {
const issues = await loader.load({ labels: ['streams:add', 'approved'] }) const issues = await loader.load({ labels: ['streams:add', 'approved'] })
issues.forEach((data: Dictionary) => { issues.forEach((issue: Issue) => {
const data = issue.data
if (data.missing('channel_id') || data.missing('stream_url')) return if (data.missing('channel_id') || data.missing('stream_url')) return
if (streams.includes((_stream: Stream) => _stream.url === data.get('stream_url'))) return if (streams.includes((_stream: Stream) => _stream.url === data.get('stream_url'))) return
@ -138,6 +124,6 @@ async function addStreams(loader: IssueLoader) {
}) })
streams.add(stream) streams.add(stream)
processedIssues.add(data.get('issue_number')) processedIssues.add(issue.number)
}) })
} }

@ -5,7 +5,6 @@ import chalk from 'chalk'
import { transliterate } from 'transliteration' import { transliterate } from 'transliteration'
import _ from 'lodash' import _ from 'lodash'
import { DATA_DIR, STREAMS_DIR } from '../../constants' import { DATA_DIR, STREAMS_DIR } from '../../constants'
import path from 'path'
program.argument('[filepath]', 'Path to file to validate').parse(process.argv) program.argument('[filepath]', 'Path to file to validate').parse(process.argv)
@ -19,73 +18,70 @@ async function main() {
const logger = new Logger() const logger = new Logger()
logger.info(`loading blocklist...`) logger.info(`loading blocklist...`)
const storage = new Storage(DATA_DIR) const dataStorage = new Storage(DATA_DIR)
const channelsContent = await storage.json('channels.json') const channelsContent = await dataStorage.json('channels.json')
const channels = new Collection(channelsContent).map(data => new Channel(data)) const channels = new Collection(channelsContent).map(data => new Channel(data))
const blocklistContent = await storage.json('blocklist.json') const blocklistContent = await dataStorage.json('blocklist.json')
const blocklist = new Collection(blocklistContent).map(data => new Blocked(data)) const blocklist = new Collection(blocklistContent).map(data => new Blocked(data))
logger.info(`found ${blocklist.count()} records`) logger.info(`found ${blocklist.count()} records`)
let errors = new Collection() logger.info('loading streams...')
let warnings = new Collection()
const streamsStorage = new Storage(STREAMS_DIR) const streamsStorage = new Storage(STREAMS_DIR)
const parser = new PlaylistParser({ storage: streamsStorage }) const parser = new PlaylistParser({ storage: streamsStorage })
const files = program.args.length ? program.args : await streamsStorage.list('**/*.m3u') const files = program.args.length ? program.args : await streamsStorage.list('**/*.m3u')
for (const filepath of files) { const streams = await parser.parse(files)
const file = new File(filepath)
if (file.extension() !== 'm3u') continue
logger.info(`found ${streams.count()} streams`)
let errors = new Collection()
let warnings = new Collection()
let groupedStreams = streams.groupBy((stream: Stream) => stream.filepath)
for (const filepath of groupedStreams.keys()) {
const streams = groupedStreams.get(filepath)
if (!streams) continue
const file = new File(filepath)
const [, countryCode] = file.basename().match(/([a-z]{2})(|_.*)\.m3u/i) || [null, ''] const [, countryCode] = file.basename().match(/([a-z]{2})(|_.*)\.m3u/i) || [null, '']
const log = new Collection() const log = new Collection()
const buffer = new Dictionary() const buffer = new Dictionary()
try { streams.forEach((stream: Stream) => {
const relativeFilepath = filepath.replace(path.normalize(STREAMS_DIR), '') const channelNotInDatabase =
const playlist = await parser.parse(relativeFilepath) stream.channel && !channels.first((channel: Channel) => channel.id === stream.channel)
playlist.streams.forEach((stream: Stream) => { if (channelNotInDatabase) {
const channelNotInDatabase = log.add({
stream.channel && !channels.first((channel: Channel) => channel.id === stream.channel) type: 'warning',
if (channelNotInDatabase) { line: stream.line,
log.add({ message: `"${stream.channel}" is not in the database`
type: 'warning', })
line: stream.line, }
message: `"${stream.channel}" is not in the database`
}) const alreadyOnPlaylist = stream.url && buffer.has(stream.url)
} if (alreadyOnPlaylist) {
log.add({
const alreadyOnPlaylist = stream.url && buffer.has(stream.url) type: 'warning',
if (alreadyOnPlaylist) { line: stream.line,
log.add({ message: `"${stream.url}" is already on the playlist`
type: 'warning', })
line: stream.line, } else {
message: `"${stream.url}" is already on the playlist` buffer.set(stream.url, true)
}) }
} else {
buffer.set(stream.url, true) const channelId = generateChannelId(stream.name, countryCode)
} const blocked = blocklist.first(
blocked =>
const channelId = generateChannelId(stream.name, countryCode) stream.channel.toLowerCase() === blocked.channel.toLowerCase() ||
const blocked = blocklist.first( channelId.toLowerCase() === blocked.channel.toLowerCase()
blocked => )
stream.channel.toLowerCase() === blocked.channel.toLowerCase() || if (blocked) {
channelId.toLowerCase() === blocked.channel.toLowerCase() log.add({
) type: 'error',
if (blocked) { line: stream.line,
log.add({ message: `"${stream.name}" is on the blocklist due to claims of copyright holders (${blocked.ref})`
type: 'error', })
line: stream.line, }
message: `"${stream.name}" is on the blocklist due to claims of copyright holders (${blocked.ref})` })
})
}
})
} catch (error) {
log.add({
type: 'error',
line: 0,
message: error.message.toLowerCase()
})
}
if (log.notEmpty()) { if (log.notEmpty()) {
logger.info(`\n${chalk.underline(filepath)}`) logger.info(`\n${chalk.underline(filepath)}`)

@ -1,36 +1,43 @@
import { DATA_DIR } from '../../constants' import { DATA_DIR, STREAMS_DIR } from '../../constants'
import { Collection, Dictionary, IssueLoader, Storage } from '../../core' import { Collection, Dictionary, IssueLoader, Storage, Logger, PlaylistParser } from '../../core'
import { Blocked, Channel, Stream } from '../../models' import { Blocked, Channel, Issue, Stream } from '../../models'
async function main() { async function main() {
const logger = new Logger()
const loader = new IssueLoader() const loader = new IssueLoader()
const storage = new Storage(DATA_DIR) const storage = new Storage(DATA_DIR)
logger.info('loading channels from api...')
const channelsContent = await storage.json('channels.json') const channelsContent = await storage.json('channels.json')
const groupedChannels = new Collection(channelsContent) const groupedChannels = new Collection(channelsContent)
.map(data => new Channel(data)) .map(data => new Channel(data))
.groupBy((channel: Channel) => channel.id) .groupBy((channel: Channel) => channel.id)
const streamsContent = await storage.json('streams.json') logger.info('loading blocklist from api...')
const groupedStreams = new Collection(streamsContent)
.map(data => new Stream(data))
.groupBy((stream: Stream) => stream.url)
const blocklistContent = await storage.json('blocklist.json') const blocklistContent = await storage.json('blocklist.json')
const groupedBlocklist = new Collection(blocklistContent) const groupedBlocklist = new Collection(blocklistContent)
.map(data => new Blocked(data)) .map(data => new Blocked(data))
.groupBy((blocked: Blocked) => blocked.channel) .groupBy((blocked: Blocked) => blocked.channel)
logger.info('loading streams...')
const streamsStorage = new Storage(STREAMS_DIR)
const parser = new PlaylistParser({ storage: streamsStorage })
const files = await streamsStorage.list('**/*.m3u')
const streams = await parser.parse(files)
const groupedStreams = streams.groupBy((stream: Stream) => stream.url)
logger.info('loading issue from github...')
const issues = await loader.load({ labels: ['streams:add'] }) const issues = await loader.load({ labels: ['streams:add'] })
logger.info('creating report...')
const buffer = new Dictionary() const buffer = new Dictionary()
const report = issues.map(data => { const report = issues.map((issue: Issue) => {
const channelId = data.get('channel_id') || undefined const channelId = issue.data.get('channel_id') || undefined
const streamUrl = data.get('stream_url') || undefined const streamUrl = issue.data.get('stream_url') || undefined
const result = new Dictionary({ const result = new Dictionary({
issueNumber: data.get('issue_number'), issueNumber: issue.number,
channelId, channelId,
status: undefined status: undefined
}) })

@ -5,7 +5,6 @@ export const README_DIR = process.env.README_DIR || './.readme'
export const API_DIR = process.env.API_DIR || './.api' export const API_DIR = process.env.API_DIR || './.api'
export const DATA_DIR = process.env.DATA_DIR || './temp/data' export const DATA_DIR = process.env.DATA_DIR || './temp/data'
export const LOGS_DIR = process.env.LOGS_DIR || './temp/logs' export const LOGS_DIR = process.env.LOGS_DIR || './temp/logs'
export const DB_DIR = process.env.DB_DIR || './temp/database'
export const TESTING = process.env.NODE_ENV === 'test' ? true : false export const TESTING = process.env.NODE_ENV === 'test' ? true : false
export const OWNER = 'iptv-org' export const OWNER = 'iptv-org'
export const REPO = 'iptv' export const REPO = 'iptv'

@ -1,22 +0,0 @@
import Datastore from '@seald-io/nedb'
import * as path from 'path'
export class Database {
rootDir: string
constructor(rootDir: string) {
this.rootDir = rootDir
}
async load(filepath: string) {
const absFilepath = path.join(this.rootDir, filepath)
return new Datastore({
filename: path.resolve(absFilepath),
autoload: true,
onload: (error: Error): any => {
if (error) console.error(error.message)
}
})
}
}

@ -1,4 +1,3 @@
export * from './database'
export * from './logger' export * from './logger'
export * from './playlistParser' export * from './playlistParser'
export * from './numberParser' export * from './numberParser'

@ -1,33 +1,31 @@
import { Dictionary } from './' import { Dictionary } from './'
import { Issue } from '../models'
import _ from 'lodash'
const FIELDS = new Dictionary({
'Channel ID': 'channel_id',
'Channel ID (required)': 'channel_id',
'Broken Link': 'stream_url',
'Stream URL': 'stream_url',
'Stream URL (optional)': 'stream_url',
'Stream URL (required)': 'stream_url',
Label: 'label',
Quality: 'quality',
'Channel Name': 'channel_name',
'HTTP User-Agent': 'user_agent',
'HTTP Referrer': 'http_referrer',
Reason: 'reason',
'What happened to the stream?': 'reason',
'Possible Replacement (optional)': 'possible_replacement',
Notes: 'notes',
'Notes (optional)': 'notes'
})
export class IssueParser { export class IssueParser {
parse(issue: any): Dictionary { parse(issue: any): Issue {
const data = new Dictionary()
data.set('issue_number', issue.number)
const idDict = new Dictionary({
'Channel ID': 'channel_id',
'Channel ID (required)': 'channel_id',
'Broken Link': 'stream_url',
'Stream URL': 'stream_url',
'Stream URL (optional)': 'stream_url',
'Stream URL (required)': 'stream_url',
Label: 'label',
Quality: 'quality',
'Channel Name': 'channel_name',
'HTTP User-Agent': 'user_agent',
'HTTP Referrer': 'http_referrer',
Reason: 'reason',
'What happened to the stream?': 'reason',
'Possible Replacement (optional)': 'possible_replacement',
Notes: 'notes',
'Notes (optional)': 'notes'
})
const fields = issue.body.split('###') const fields = issue.body.split('###')
if (!fields.length) return data const data = new Dictionary()
fields.forEach((field: string) => { fields.forEach((field: string) => {
let [_label, , _value] = field.split(/\r?\n/) let [_label, , _value] = field.split(/\r?\n/)
_label = _label ? _label.trim() : '' _label = _label ? _label.trim() : ''
@ -35,7 +33,7 @@ export class IssueParser {
if (!_label || !_value) return data if (!_label || !_value) return data
const id: string = idDict.get(_label) const id: string = FIELDS.get(_label)
const value: string = _value === '_No response_' || _value === 'None' ? '' : _value const value: string = _value === '_No response_' || _value === 'None' ? '' : _value
if (!id) return if (!id) return
@ -43,6 +41,6 @@ export class IssueParser {
data.set(id, value) data.set(id, value)
}) })
return data return new Issue({ number: issue.number, data })
} }
} }

@ -1,6 +1,8 @@
import parser from 'iptv-playlist-parser' import parser from 'iptv-playlist-parser'
import { Playlist, Stream } from '../models' import { Stream } from '../models'
import { Collection, Storage } from './' import { Collection, Storage } from './'
import path from 'path'
import { STREAMS_DIR } from '../constants'
export class PlaylistParser { export class PlaylistParser {
storage: Storage storage: Storage
@ -9,7 +11,19 @@ export class PlaylistParser {
this.storage = storage this.storage = storage
} }
async parse(filepath: string): Promise<Playlist> { async parse(files: string[]): Promise<Collection> {
let streams = new Collection()
for (let filepath of files) {
const relativeFilepath = filepath.replace(path.normalize(STREAMS_DIR), '')
const _streams: Collection = await this.parseFile(relativeFilepath)
streams = streams.concat(_streams)
}
return streams
}
async parseFile(filepath: string): Promise<Collection> {
const streams = new Collection() const streams = new Collection()
const content = await this.storage.read(filepath) const content = await this.storage.read(filepath)
@ -32,7 +46,7 @@ export class PlaylistParser {
streams.add(stream) streams.add(stream)
}) })
return new Playlist(streams) return streams
} }
} }

@ -10,10 +10,12 @@ export class Storage {
this.rootDir = path.normalize(rootDir || './') this.rootDir = path.normalize(rootDir || './')
} }
list(pattern: string): Promise<string[]> { async list(pattern: string): Promise<string[]> {
return glob(pattern, { const files = await glob(pattern, {
cwd: this.rootDir cwd: this.rootDir
}) })
return files.sort()
} }
async createDir(dir: string): Promise<void> { async createDir(dir: string): Promise<void> {

@ -1,3 +1,4 @@
export * from './issue'
export * from './playlist' export * from './playlist'
export * from './blocked' export * from './blocked'
export * from './stream' export * from './stream'

@ -0,0 +1,16 @@
import { Dictionary } from '../core'
type IssueProps = {
number: number
data: Dictionary
}
export class Issue {
number: number
data: Dictionary
constructor({ number, data }: IssueProps) {
this.number = number
this.data = data
}
}

@ -641,3 +641,5 @@ https://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8
https://5ad482a77183d.streamlock.net/sbtsbtmt.com/sbtsbtmt.com/playlist.m3u8 https://5ad482a77183d.streamlock.net/sbtsbtmt.com/sbtsbtmt.com/playlist.m3u8
#EXTINF:-1 tvg-id="TVCorreio.br",TV Correio (720p) [Not 24/7] #EXTINF:-1 tvg-id="TVCorreio.br",TV Correio (720p) [Not 24/7]
https://ythls.onrender.com/channel/UCJ4uxK_mo6gNoqk9cyvgWkw.m3u8 https://ythls.onrender.com/channel/UCJ4uxK_mo6gNoqk9cyvgWkw.m3u8
#EXTINF:-1 tvg-id="RecordTV.br",RecordTV
https://cdn.jmvstream.com/w/LVW-10842/LVW10842_513N26MDBL/chunklist.m3u8

@ -17,3 +17,5 @@ https://le02.euddn.net/6487956abb8faf0706d8c4c2465f54cb3625b812fec8e13d11668907f
https://ythls.onrender.com/channel/UCQGN5-eIjRRy6MGcHKDE_6g.m3u8 https://ythls.onrender.com/channel/UCQGN5-eIjRRy6MGcHKDE_6g.m3u8
#EXTINF:-1 tvg-id="TVN.ee",TVN (1080p) #EXTINF:-1 tvg-id="TVN.ee",TVN (1080p)
https://s4.telset.ee/tvn/index.m3u8?filter.tracks=v1a1&token=tvn_token https://s4.telset.ee/tvn/index.m3u8?filter.tracks=v1a1&token=tvn_token
#EXTINF:-1 tvg-id="Kanal7.ee",Kanal 7
http://89.254.128.5:22280/duo7_hd/index.m3u8

@ -337,3 +337,33 @@ https://tv3v.hdr-tv.com/live/tv3v/livestream/master.m3u8
https://static.lefigaro.fr/secom/tnt.m3u8 https://static.lefigaro.fr/secom/tnt.m3u8
#EXTINF:-1 tvg-id="",LE FIGARO IDF #EXTINF:-1 tvg-id="",LE FIGARO IDF
https://figarotv-live.freecaster.com/live/freecaster/figarotv.m3u8 https://figarotv-live.freecaster.com/live/freecaster/figarotv.m3u8
#EXTINF:-1 tvg-id="TFX.fr",TFX
http://livetv.ktv.zone/13/play.m3u8
#EXTINF:-1 tvg-id="TMC.fr",TMC
http://livetv.ktv.zone/12/play.m3u8
#EXTINF:-1 tvg-id="TF1SeriesFilms.fr",TF1 Series Films
http://livetv.ktv.zone/22/play.m3u8
#EXTINF:-1 tvg-id="TF1.fr",TF 1
http://livetv.ktv.zone/3/play.m3u8
#EXTINF:-1 tvg-id="France3RhoneAlpes.fr",France 3 Rhone-Alpes
http://livetv.ktv.zone/233/play.m3u8
#EXTINF:-1 tvg-id="France3ProvenceAlpes.fr",France 3 Provence-Alpes
http://livetv.ktv.zone/232/play.m3u8
#EXTINF:-1 tvg-id="France3NouvelleAquitaine.fr",France 3 Nouvelle-Aquitaine
http://livetv.ktv.zone/231/play.m3u8
#EXTINF:-1 tvg-id="France3NouvelleAquitaine.fr",France 3 Nouvelle-Aquitaine
http://livetv.ktv.zone/224/play.m3u8
#EXTINF:-1 tvg-id="France3CotedAzur.fr",France 3 Cote d'Azur
http://livetv.ktv.zone/220/play.m3u8
#EXTINF:-1 tvg-id="France3Bretagne.fr",France 3 Bretagne
http://livetv.ktv.zone/216/play.m3u8
#EXTINF:-1 tvg-id="France3Auvergne.fr",France 3 Auvergne
http://livetv.ktv.zone/213/play.m3u8
#EXTINF:-1 tvg-id="France3Aquitaine.fr",France 3 Aquitaine
http://livetv.ktv.zone/212/play.m3u8
#EXTINF:-1 tvg-id="France5.fr",France 5
http://livetv.ktv.zone/107/play.m3u8
#EXTINF:-1 tvg-id="France3.fr",France 3
http://livetv.ktv.zone/105/play.m3u8
#EXTINF:-1 tvg-id="France2.fr",France 2
http://livetv.ktv.zone/104/play.m3u8

@ -235,5 +235,6 @@ http://d1nfykbwa3n98t.cloudfront.net/out/v1/6e5667da5a6843899a337dea72adb61b/ant
http://ovh-edge-h.evrideo.com:8080/23e234f2-aec8-4804-b694-4cdd71d2d48d_MONITORING_HLS/video_240p_WEBRTC_MONITORING.m3u8 http://ovh-edge-h.evrideo.com:8080/23e234f2-aec8-4804-b694-4cdd71d2d48d_MONITORING_HLS/video_240p_WEBRTC_MONITORING.m3u8
#EXTINF:-1 tvg-id="AigaioTV.gr",Aigaio TV (360p) #EXTINF:-1 tvg-id="AigaioTV.gr",Aigaio TV (360p)
https://250weu.bozztv.com/ssh101/ssh101/aigaiotv/playlist.m3u8 https://250weu.bozztv.com/ssh101/ssh101/aigaiotv/playlist.m3u8
#EXTINF:-1 tvg-id="AstraTV.gr",Astra TV (480p) #EXTINF:-1 tvg-id="AstraTV.gr",Astra TV (480p) [Not 24/7]
#EXTVLCOPT:http-referrer=https://astratv.gr
https://ssh101.bozztv.com/ssh101/astratv/playlist.m3u8 https://ssh101.bozztv.com/ssh101/astratv/playlist.m3u8

@ -293,3 +293,5 @@ http://194.76.186.33:8000/play/a012/index.m3u8
https://stream.medialive.hu/gran/grantvlive/playlist.m3u8 https://stream.medialive.hu/gran/grantvlive/playlist.m3u8
#EXTINF:-1 tvg-id="LadanyTV.hu",Ladány TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="LadanyTV.hu",Ladány TV (720p) [Not 24/7]
https://ythls.onrender.com/channel/UCnG322MGBA4q5QWwDzUTh0Q.m3u8 https://ythls.onrender.com/channel/UCnG322MGBA4q5QWwDzUTh0Q.m3u8
#EXTINF:-1 tvg-id="Match4.hu",Match4
http://194.76.186.33:8000/play/a04d/index.m3u8

@ -929,3 +929,7 @@ https://mntv.livebox.co.in/mntvhls/live.m3u8
https://mntv.livebox.co.in/musichls/live.m3u8 https://mntv.livebox.co.in/musichls/live.m3u8
#EXTINF:-1 tvg-id="ReporterTV.in",Reporter TV #EXTINF:-1 tvg-id="ReporterTV.in",Reporter TV
https://ythls.onrender.com/channel/UCFx1nseXKTc1Culiu3neeSQ.m3u8 https://ythls.onrender.com/channel/UCFx1nseXKTc1Culiu3neeSQ.m3u8
#EXTINF:-1 tvg-id="ManoramaNews.in",Manorama News
https://ythls.onrender.com/channel/UCP0uG-mcMImgKnJz-VjJZmQ.m3u8
#EXTINF:-1 tvg-id="AajTak.in",Aaj Tak
https://feeds.intoday.in/aajtak/api/aajtakhd/master.m3u8

@ -115,3 +115,5 @@ https://cdn.nhkworld.jp/www11/nhkworld-tv/bmcc-live/fr/playlist.m3u8
https://cdn.nhkworld.jp/www11/nhkworld-tv/bmcc-live/pt/playlist.m3u8 https://cdn.nhkworld.jp/www11/nhkworld-tv/bmcc-live/pt/playlist.m3u8
#EXTINF:-1 tvg-id="NHKGeneralTV.jp",NHK G (360p) [Not 24/7] #EXTINF:-1 tvg-id="NHKGeneralTV.jp",NHK G (360p) [Not 24/7]
https://newssimul-stream.nhk.jp/hls/live/2010561/nhknewssimul/master.m3u8 https://newssimul-stream.nhk.jp/hls/live/2010561/nhknewssimul/master.m3u8
#EXTINF:-1 tvg-id="Weathernews.jp",Weathernews
https://ythls.onrender.com/channel/UCNsidkYpIAQ4QaufptQBPHQ.m3u8

@ -15,3 +15,5 @@ http://onlinetv.ktrk.kg:1935/live/myStream2/playlist.m3u8
http://onlinetv.ktrk.kg:1935/live/myStream/playlist.m3u8 http://onlinetv.ktrk.kg:1935/live/myStream/playlist.m3u8
#EXTINF:-1 tvg-id="KTRKSport.kg",KTRK Sport (576p) #EXTINF:-1 tvg-id="KTRKSport.kg",KTRK Sport (576p)
http://onlinetv.ktrk.kg:1935/live/myStream4/playlist.m3u8 http://onlinetv.ktrk.kg:1935/live/myStream4/playlist.m3u8
#EXTINF:-1 tvg-id="Balastan.kg",Balastan
https://64e5ed58c00d4.streamlock.net/live/smil:balastan.smil/playlist.m3u8

@ -25,3 +25,5 @@ https://ythls.onrender.com/channel/UC37lrcLuvJmWDoooxwiPXXA.m3u8
https://ythls.onrender.com/channel/UC1WREaxq8LRhdOOmzSFg2pA.m3u8 https://ythls.onrender.com/channel/UC1WREaxq8LRhdOOmzSFg2pA.m3u8
#EXTINF:-1 tvg-id="AdaDerana24x7.lk",Ada Derana News (720p) [Not 24/7] #EXTINF:-1 tvg-id="AdaDerana24x7.lk",Ada Derana News (720p) [Not 24/7]
https://ythls.onrender.com/channel/UCCK3OZi788Ok44K97WAhLKQ.m3u8 https://ythls.onrender.com/channel/UCCK3OZi788Ok44K97WAhLKQ.m3u8
#EXTINF:-1 tvg-id="MethTV.lk",Meth TV
https://ythls.onrender.com/channel/UC7kBHRaynsJMB6JcooGLTmA.m3u8

@ -72,3 +72,5 @@ https://d25tgymtnqzu8s.cloudfront.net/smil:tv2/playlist.m3u8?id=2
https://d25tgymtnqzu8s.cloudfront.net/smil:tv6/playlist.m3u8?id=6 https://d25tgymtnqzu8s.cloudfront.net/smil:tv6/playlist.m3u8?id=6
#EXTINF:-1 tvg-id="",TVIKIM #EXTINF:-1 tvg-id="",TVIKIM
https://edge-sg1.vediostream.com/abr/tvikim/playlist.m3u8 https://edge-sg1.vediostream.com/abr/tvikim/playlist.m3u8
#EXTINF:-1 tvg-id="TV3.my",TV3
https://live-streams-ssai-01.tonton.com.my/live/2dd2b7cd-1b34-4871-b669-57b5c9beca23/live.isml/.m3u8

@ -293,3 +293,5 @@ https://live.obslivestream.com/vivatv/index.m3u8
https://live.obslivestream.com/wtv/index.m3u8 https://live.obslivestream.com/wtv/index.m3u8
#EXTINF:-1 tvg-id="CumoTV.pe",Cumo TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="CumoTV.pe",Cumo TV (720p) [Not 24/7]
https://live.obslivestream.com/cumo/index.m3u8 https://live.obslivestream.com/cumo/index.m3u8
#EXTINF:-1 tvg-id="ATVPlus.pe",ATV+
https://linear-258.frequency.stream/dist/vix/258/hls/master/playlist.m3u8

@ -184,3 +184,7 @@ http://183.89.246.119:8010/play/a00c/index.m3u8
http://183.89.246.119:8010/play/a00u/index.m3u8 http://183.89.246.119:8010/play/a00u/index.m3u8
#EXTINF:-1 tvg-id="TopNews.th",Top News (480p) #EXTINF:-1 tvg-id="TopNews.th",Top News (480p)
https://live.topnews.co.th/hls/topnews.m3u8 https://live.topnews.co.th/hls/topnews.m3u8
#EXTINF:-1 tvg-id="AmarinTV.th",Amarin TV
https://cdn6.goprimetime.info/feed/202306140918/chamarin/index.m3u8
#EXTINF:-1 tvg-id="MCOTHD.th",MCOT HD
https://cdn6.goprimetime.info/feed/202306140918/chmcothd/index.m3u8

@ -19,3 +19,5 @@ https://ythls.onrender.com/channel/UCdvWVsmQBROkgcGzVep73oA.m3u8
http://live.watania2.tn:1935/live/watanya2.stream/playlist.m3u8 http://live.watania2.tn:1935/live/watanya2.stream/playlist.m3u8
#EXTINF:-1 tvg-id="Watania2.tn",Watania 2 (480p) #EXTINF:-1 tvg-id="Watania2.tn",Watania 2 (480p)
https://ythls.onrender.com/channel/UCJW9gatYczI191TunQxMGbA.m3u8 https://ythls.onrender.com/channel/UCJW9gatYczI191TunQxMGbA.m3u8
#EXTINF:-1 tvg-id="EssaidaTV.tn",Essaida TV
https://app.rtvli.com/hls/stream/index.m3u8

@ -495,3 +495,21 @@ https://win29.yayin.com.tr/erzurumwebtv/erzurumwebtv/iptvdelisi.m3u8
https://ythls.onrender.com/channel/UCqq-1-YntK4Gq53Ka9PaVlg.m3u8 https://ythls.onrender.com/channel/UCqq-1-YntK4Gq53Ka9PaVlg.m3u8
#EXTINF:-1 tvg-id="MinikaGo.tr",Minika Go (576p) [Not 24/7] #EXTINF:-1 tvg-id="MinikaGo.tr",Minika Go (576p) [Not 24/7]
https://ythls.onrender.com/channel/UCVbCXWXWd0WCNhdBnmP_TmA.m3u8 https://ythls.onrender.com/channel/UCVbCXWXWd0WCNhdBnmP_TmA.m3u8
#EXTINF:-1 tvg-id="PowerTurkTV.tr",PowerTurk TV
https://powerturk.blutv.com/blutv_powerturk/powerturk_sd.smil/playlist.m3u8
#EXTINF:-1 tvg-id="BloombergHT.tr",Bloomberg HT
https://bloomberght2dvr.blutv.com/blutv_bloomberght_dvr/live.m3u8
#EXTINF:-1 tvg-id="24TV.tr",24 TV
https://kanal24.blutv.com/blutv_kanal24_live/live.m3u8
#EXTINF:-1 tvg-id="Ekoturk.tr",Ekoturk
https://ekoturk.blutv.com/blutv_ekoturk2/live.m3u8
#EXTINF:-1 tvg-id="HaberGlobal.tr",Haber Global
https://haberglobaldvr.blutv.com/blutv_haberglobal_dvr/live.m3u8
#EXTINF:-1 tvg-id="TRT2.tr",TRT 2
https://trt2.blutv.com/blutv_trt2/live.m3u8
#EXTINF:-1 tvg-id="TRTTurk.tr",TRT Turk
https://trtturk.blutv.com/blutv_trtturk2/live.m3u8
#EXTINF:-1 tvg-id="ShowTurk.tr",Show Turk
https://showturk.blutv.com/blutv_showturk2/live.m3u8
#EXTINF:-1 tvg-id="ShowTV.tr",Show TV
https://showtv.blutv.com/blutv_showtv_live/live.m3u8

@ -205,3 +205,7 @@ https://a.jsrdn.com/broadcast/22680_3BR3zocwi9/-0500/c.m3u8
https://ap02.iqplay.tv:8082/iqb8002/ka1s0n/playlist.m3u8 https://ap02.iqplay.tv:8082/iqb8002/ka1s0n/playlist.m3u8
#EXTINF:-1 tvg-id="LollyKids.uk",Lolly Kids (480p) #EXTINF:-1 tvg-id="LollyKids.uk",Lolly Kids (480p)
http://45.225.95.170:8000/play/a0ei/index.m3u8 http://45.225.95.170:8000/play/a0ei/index.m3u8
#EXTINF:-1 tvg-id="BBCWorldNewsSouthAsia.uk",BBC World News South Asia
http://103.199.161.254/Content/bbcworld/Live/Channel%28BBCworld%29/Stream%2801%29/index.m3u8
#EXTINF:-1 tvg-id="BeanoTV.uk",Beano TV
https://a5b4bacecd47433dad06d3189fc7422e.mediatailor.us-east-1.amazonaws.com/v1/manifest/04fd913bb278d8775298c26fdca9d9841f37601f/RakutenTV-eu_BeanoTV/b1f233d5-847c-437d-aa4f-f73e67a85323/2.m3u8

@ -1100,3 +1100,15 @@ https://rtmp2.abnvideos.com/hls/abnurdu.m3u8
https://rtmp2.abnvideos.com/hls/abnbiblemovies.m3u8 https://rtmp2.abnvideos.com/hls/abnbiblemovies.m3u8
#EXTINF:-1 tvg-id="DNews.us",DNews (1080p) [Not 24/7] #EXTINF:-1 tvg-id="DNews.us",DNews (1080p) [Not 24/7]
https://ythls.onrender.com/channel/UC4dWvSKVWJ36tJyhjDQCCaQ.m3u8 https://ythls.onrender.com/channel/UC4dWvSKVWJ36tJyhjDQCCaQ.m3u8
#EXTINF:-1 tvg-id="TropicalMoonUrbanTV.us",Tropical Moon Urban TV
https://srv.tropicalmoonmedia.com/urbantvnetott/urbantvnetott/playlist.m3u8
#EXTINF:-1 tvg-id="TropicalMoonEventosTV.us",Tropical Moon Eventos TV
https://srv2.tropicalmoonmedia.com/eventostv/eventostv/playlist.m3u8
#EXTINF:-1 tvg-id="TropicalMoonSalsaTV.us",Tropical Moon Salsa TV
https://srv.tropicalmoonmedia.com/musictv/musictv/playlist.m3u8
#EXTINF:-1 tvg-id="TUTV.us",TUTV
https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8
#EXTINF:-1 tvg-id="StarTrek2.us",Star Trek 2
https://service-stitcher.clusters.pluto.tv/v1/stitch/embed/hls/channel/634dacf51d90320007fcd5fa/master.m3u8?advertisingId=channel&appName=rokuchannel&appVersion=1.0&bmodel=bm1&channel_id=channel&content=channel&content_rating=ROKU_ADS_CONTENT_RATING&content_type=livefeed&coppa=false&deviceDNT=1&deviceId=channel&deviceMake=rokuChannel&deviceModel=web&deviceType=rokuChannel&deviceVersion=1.0&embedPartner=rokuChannel&genre=ROKU_ADS_CONTENT_GENRE&is_lat=1&platform=web&rdid=channel&studio_id=viacom&tags=ROKU_CONTENT_TAGS
#EXTINF:-1 tvg-id="FastTV.us",Fast TV
https://3fa797d5.wurl.com/manifest/f36d25e7e52f1ba8d7e56eb859c636563214f541/T05PX01vdG9yVHJlbmRGYXN0VFZfSExT/b5e5e0e2-12b3-4312-93c9-c0a7c50b41ca/4.m3u8

@ -625,7 +625,7 @@ http://trn03.tulix.tv/teleup-nbc-wgal-new1/playlist.m3u8
http://trn03.tulix.tv/teleup-cw-whp/playlist.m3u8 http://trn03.tulix.tv/teleup-cw-whp/playlist.m3u8
#EXTINF:-1 tvg-id="WJLADT1.us",ABC 7 Washington DC (WJLA) (720p) #EXTINF:-1 tvg-id="WJLADT1.us",ABC 7 Washington DC (WJLA) (720p)
https://content.uplynk.com/40cec2bf074c40f08932da03ab4510be.m3u8 https://content.uplynk.com/40cec2bf074c40f08932da03ab4510be.m3u8
#EXTINF:-1 tvg-id="WLCT96.us",Wolcott Governmental TV (720p) (Wolcott CT) #EXTINF:-1 tvg-id="WLCT96.us",Wolcott Governmental TV (Wolcott CT) (720p)
https://5a5c57d042315.streamlock.net/live11704001/ngrp:government_all/playlist.m3u8 https://5a5c57d042315.streamlock.net/live11704001/ngrp:government_all/playlist.m3u8
#EXTINF:-1 tvg-id="WLIIDT1.us",TeleOnce (WLII-DT) (1080p) #EXTINF:-1 tvg-id="WLIIDT1.us",TeleOnce (WLII-DT) (1080p)
https://univision-live.cdn.vustreams.com/live/ce88b839-6376-4494-a2ee-83d66bc7cfc1/live.isml/ce88b839-6376-4494-a2ee-83d66bc7cfc1.m3u8 https://univision-live.cdn.vustreams.com/live/ce88b839-6376-4494-a2ee-83d66bc7cfc1/live.isml/ce88b839-6376-4494-a2ee-83d66bc7cfc1.m3u8

@ -1 +1 @@
[{"channel":"AndorraTV.ad","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http_referrer":"http://imn.iq","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148"},{"channel":"BBCNews.uk","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","http_referrer":null,"user_agent":null},{"channel":"BBCNewsHD.uk","url":"https://master.starmena-cloud.com/hls/bbc.m3u8","http_referrer":null,"user_agent":null},{"channel":"KayhanTV.af","url":"http://208.93.117.113/live/Stream1/playlist.m3u8","http_referrer":null,"user_agent":null},{"channel":"LDPRTV.ru","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http_referrer":null,"user_agent":null},{"channel":"LibyasChannel.ly","url":"https://master.starmena-cloud.com/hls/libyas.m3u8","http_referrer":null,"user_agent":null},{"channel":"Sharq.af","url":"https://forerunnerrtmp.livestreamingcdn.com/output18/output18.stream/playlist.m3u8","http_referrer":null,"user_agent":null}] [{"channel":"","url":"http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8","http_referrer":null,"user_agent":null},{"channel":"","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8","http_referrer":"http://imn.iq","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148"},{"channel":"AndorraTV.ad","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http_referrer":null,"user_agent":null},{"channel":"BBCNews.uk","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","http_referrer":null,"user_agent":null},{"channel":"LDPRTV.ru","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8","http_referrer":null,"user_agent":null},{"channel":"MeteoMedia.ca","url":"http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8","http_referrer":null,"user_agent":null},{"channel":"VisitXTV.nl","url":"https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8","http_referrer":null,"user_agent":null},{"channel":"Zoo.ad","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/zoo","http_referrer":null,"user_agent":null}]

@ -1,5 +0,0 @@
#EXTM3U
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
#EXTVLCOPT:http-referrer=http://imn.iq
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8

@ -9,9 +9,9 @@ http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Russia",ЛДПР ТВ (1080p) #EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Russia",ЛДПР ТВ (1080p)
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="United Kingdom" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="International",BBC News HD
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
#EXTVLCOPT:http-referrer=http://imn.iq #EXTVLCOPT:http-referrer=http://imn.iq
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 #EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8 http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="International",BBC News HD
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8

@ -9,20 +9,12 @@ http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Commonwealth of Independent States",ЛДПР ТВ (1080p) #EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Commonwealth of Independent States",ЛДПР ТВ (1080p)
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Europe" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
#EXTVLCOPT:http-referrer=http://imn.iq
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="" group-title="Europe",ATV #EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="" group-title="Europe",ATV
https://iptv-all.lanesh4d0w.repl.co/andorra/atv https://iptv-all.lanesh4d0w.repl.co/andorra/atv
#EXTINF:-1 tvg-id="Zoo.ad" tvg-logo="" group-title="Europe",Zoo (720p) #EXTINF:-1 tvg-id="Zoo.ad" tvg-logo="" group-title="Europe",Zoo (720p)
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Europe",ЛДПР ТВ (1080p) #EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Europe",ЛДПР ТВ (1080p)
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Europe, the Middle East and Africa" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
#EXTVLCOPT:http-referrer=http://imn.iq
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="" group-title="Europe, the Middle East and Africa",ATV #EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="" group-title="Europe, the Middle East and Africa",ATV
https://iptv-all.lanesh4d0w.repl.co/andorra/atv https://iptv-all.lanesh4d0w.repl.co/andorra/atv
#EXTINF:-1 tvg-id="Zoo.ad" tvg-logo="" group-title="Europe, the Middle East and Africa",Zoo (720p) #EXTINF:-1 tvg-id="Zoo.ad" tvg-logo="" group-title="Europe, the Middle East and Africa",Zoo (720p)
@ -35,10 +27,6 @@ http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="South Asia",Daawah TV #EXTINF:-1 tvg-id="" tvg-logo="" group-title="South Asia",Daawah TV
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Worldwide" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
#EXTVLCOPT:http-referrer=http://imn.iq
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="" group-title="Worldwide",ATV #EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="" group-title="Worldwide",ATV
https://iptv-all.lanesh4d0w.repl.co/andorra/atv https://iptv-all.lanesh4d0w.repl.co/andorra/atv
#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="Worldwide",BBC News HD #EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="Worldwide",BBC News HD
@ -51,3 +39,7 @@ http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Worldwide",ЛДПР ТВ (1080p) #EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Worldwide",ЛДПР ТВ (1080p)
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
#EXTVLCOPT:http-referrer=http://imn.iq
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8

@ -1,8 +1,4 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
#EXTVLCOPT:http-referrer=http://imn.iq
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="" group-title="Undefined",ATV #EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="" group-title="Undefined",ATV
https://iptv-all.lanesh4d0w.repl.co/andorra/atv https://iptv-all.lanesh4d0w.repl.co/andorra/atv
#EXTINF:-1 tvg-id="Zoo.ad" tvg-logo="" group-title="Undefined",Zoo (720p) #EXTINF:-1 tvg-id="Zoo.ad" tvg-logo="" group-title="Undefined",Zoo (720p)

@ -1,8 +1,4 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
#EXTVLCOPT:http-referrer=http://imn.iq
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="" group-title="Undefined",ATV #EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="" group-title="Undefined",ATV
https://iptv-all.lanesh4d0w.repl.co/andorra/atv https://iptv-all.lanesh4d0w.repl.co/andorra/atv
#EXTINF:-1 tvg-id="Zoo.ad" tvg-logo="" group-title="Undefined",Zoo (720p) #EXTINF:-1 tvg-id="Zoo.ad" tvg-logo="" group-title="Undefined",Zoo (720p)

@ -1,7 +0,0 @@
{"line":2,"channel":"ATV.ad","quality":"720p","label":"Offline","name":"ATV","filepath":"ad.m3u","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","httpReferrer":"http://imn.iq","userAgent":"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","_id":"k4XpZHQAyqyTbcf0"}
{"line":2,"channel":"LibyasChannel.ly","quality":"","label":"","name":"Libyas Channel","filepath":"ly.m3u","url":"https://master.starmena-cloud.com/hls/libyas.m3u8","httpReferrer":"","userAgent":"","_id":"ki4YjAoNNoIY8sSm"}
{"line":2,"channel":"","quality":"720p","label":"","name":"1A Network","filepath":"unsorted.m3u","url":"https://simultv.s.llnwi.net/n4s4/2ANetwork/interlink.m3u8","httpReferrer":"","userAgent":"","_id":"IZpCJjjWPaBYh7Dr"}
{"line":2,"channel":"","quality":"720p","label":"","name":"Fox Sports 2 Asia (Thai)","filepath":"us_blocked.m3u","url":"https://example.com/playlist.m3u8","httpReferrer":"","userAgent":"","_id":"6c4J4vs8K69wMJ7S"}
{"line":4,"channel":"","quality":"","label":"","name":"TVN","filepath":"us_blocked.m3u","url":"https://example.com/playlist2.m3u8","httpReferrer":"","userAgent":"","_id":"xEmbX384v3t3F5Wg"}
{"line":6,"channel":"EverydayHeroes.us","quality":"720p","label":"","name":"Everyday Heroes","filepath":"us_blocked.m3u","url":"https://a.jsrdn.com/broadcast/7b1451fa52/+0000/c.m3u8","httpReferrer":"","userAgent":"","_id":"BZsRPt8VS4kIJnfi"}
{"line":2,"channel":"qib22lAq1L.us","quality":"720p","label":"","name":"ABC","filepath":"wrong_id.m3u","url":"https://example.com/playlist2.m3u8","httpReferrer":"","userAgent":"","_id":"eFUlUnST5zJSBWAF"}

@ -32,14 +32,13 @@
{"filepath":"subdivisions/ca-on.m3u","count":1} {"filepath":"subdivisions/ca-on.m3u","count":1}
{"filepath":"countries/in.m3u","count":1} {"filepath":"countries/in.m3u","count":1}
{"filepath":"countries/ru.m3u","count":1} {"filepath":"countries/ru.m3u","count":1}
{"filepath":"countries/uk.m3u","count":1}
{"filepath":"countries/int.m3u","count":1} {"filepath":"countries/int.m3u","count":1}
{"filepath":"index.category.m3u","count":8} {"filepath":"index.category.m3u","count":8}
{"filepath":"index.country.m3u","count":7} {"filepath":"index.country.m3u","count":7}
{"filepath":"index.language.m3u","count":7} {"filepath":"index.language.m3u","count":7}
{"filepath":"index.m3u","count":7} {"filepath":"index.m3u","count":7}
{"filepath":"index.nsfw.m3u","count":8} {"filepath":"index.nsfw.m3u","count":8}
{"filepath":"index.region.m3u","count":23} {"filepath":"index.region.m3u","count":21}
{"filepath":"languages/eng.m3u","count":1} {"filepath":"languages/eng.m3u","count":1}
{"filepath":"languages/rus.m3u","count":1} {"filepath":"languages/rus.m3u","count":1}
{"filepath":"languages/cat.m3u","count":1} {"filepath":"languages/cat.m3u","count":1}
@ -54,8 +53,8 @@
{"filepath":"regions/cas.m3u","count":0} {"filepath":"regions/cas.m3u","count":0}
{"filepath":"regions/cenamer.m3u","count":0} {"filepath":"regions/cenamer.m3u","count":0}
{"filepath":"regions/cis.m3u","count":1} {"filepath":"regions/cis.m3u","count":1}
{"filepath":"regions/emea.m3u","count":4} {"filepath":"regions/emea.m3u","count":3}
{"filepath":"regions/eur.m3u","count":4} {"filepath":"regions/eur.m3u","count":3}
{"filepath":"regions/hispam.m3u","count":0} {"filepath":"regions/hispam.m3u","count":0}
{"filepath":"regions/lac.m3u","count":0} {"filepath":"regions/lac.m3u","count":0}
{"filepath":"regions/latam.m3u","count":0} {"filepath":"regions/latam.m3u","count":0}

@ -1,5 +0,0 @@
#EXTM3U
#EXTINF:-1 tvg-id="AndorraTV.ad" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",ATV (720p) [Offline]
#EXTVLCOPT:http-referrer=http://imn.iq
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
https://iptv-all.lanesh4d0w.repl.co/andorra/atv

@ -1,5 +0,0 @@
#EXTM3U
#EXTINF:-1 tvg-id="KayhanTV.af",Kayhan TV
http://208.93.117.113/live/Stream1/playlist.m3u8
#EXTINF:-1 tvg-id="Sharq.af",Sharq
http://51.210.199.50/hls/stream.m3u8

@ -1,6 +0,0 @@
#EXTM3U
#EXTINF:-1 tvg-id="Telearuba.aw",Telearuba (720p)
http://cdn.setar.aw:1935/Telearuba/smil:telearuba.smil/playlist.m3u8
#EXTINF:-1 tvg-id="Telearuba.aw" user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36",Telearuba (480p) [Not 24/7]
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36
https://backend-server-dot-telearuba-app.appspot.com/media/livestream13/playlist.m3u8

@ -1,7 +0,0 @@
#EXTM3U
#EXTINF:-1 tvg-id="",Caillou
https://dhx-caillou-1-es.samsung.wurl.tv/playlist.m3u8
#EXTINF:-1 tvg-id="",iHola Play
https://rakuten-hola-2-es.samsung.wurl.tv/playlist.m3u8
#EXTINF:-1 tvg-id="",Planeta Junior TV
https://deaplaneta-planetakidz-1-es.samsung.wurl.tv/playlist.m3u8

@ -1,9 +0,0 @@
#EXTM3U
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
https://service-stitcher.clusters.pluto.tv/stitch/hls/channel/5ca525b650be2571e3943c63/master.m3u8?advertisingId=&appName=web&deviceId=5ca525b650be2571e3943c63

@ -0,0 +1,3 @@
#EXTM3U
#EXTINF:-1 tvg-id="",Manorama News
https://ythls.onrender.com/channel/UCP0uG-mcMImgKnJz-VjJZmQ.m3u8

@ -1,8 +1,4 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="NPO1.nl",NPO 1 (1080p) [Geo-blocked]
http://stream.tvtap.net:8081/live/nl-npo1.stream/30fps.m3u8
#EXTINF:-1 tvg-id="NPO1.nl",NPO 1 (1080p) [Geo-blocked]
http://stream.tvtap.net:8081/live/nl-npo1.stream/60fps.m3u8
#EXTINF:-1 tvg-id="NPO1.nl",NPO 1 (342p) [Geo-blocked] #EXTINF:-1 tvg-id="NPO1.nl",NPO 1 (342p) [Geo-blocked]
http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo1/npo1.isml/.m3u8 http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo1/npo1.isml/.m3u8
#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (342p) #EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (342p)

@ -1 +0,0 @@
[{"channel":"TUTV.us","url":"https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8","http_referrer":null,"user_agent":null}]

@ -1,7 +0,0 @@
{"line": 2,"quality":null,"label":null,"name":"ЛДПР ТВ","channel":"LDPRTV.ru","filepath":"ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","httpReferrer":null,"userAgent":null,"cluster_id":1,"_id":"2ST8btby3mmsgPF0","status":"error"}
{"line": 2,"quality":null,"label":null,"name":"BBC News HD","channel":"BBCNews.uk","filepath":"uk.m3u","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","httpReferrer":null,"userAgent":null,"cluster_id":3,"_id":"3TbieV1ptnZVCIdn","status":"blocked"}
{"line": 2,"quality":null,"label":null,"name":"ATV","channel":"AndorraTV.ad","filepath":"ad.m3u","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","httpReferrer":"http://imn.iq","userAgent":"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","cluster_id":1,"_id":"I6cjG2xCBRFFP4sz","status":"error"}
{"line": 2,"quality":null,"label":null,"name":"BBC News HD","channel":"BBCNewsHD.uk","filepath":"uk.m3u","url":"https://master.starmena-cloud.com/hls/bbc.m3u8","httpReferrer":null,"userAgent":null,"cluster_id":3,"_id":"WTbieV1ptnXVCIdn","status":"online","bitrate":0,"frame_rate":25,"width":1024,"height":576}
{"line": 2,"quality":null,"label":null,"name":"Kayhan TV","channel":"KayhanTV.af","filepath":"channels/af.m3u","url":"http://208.93.117.113/live/Stream1/playlist.m3u8","httpReferrer":null,"userAgent":null,"cluster_id":1,"_id":"cFFpFVzSn6xFMUF3","status":"error"}
{"line": 2,"quality":null,"label":null,"name":"Sharq","channel":"Sharq.af","filepath":"channels/af.m3u","bitrate":2226543,"frame_rate":25,"width":1280,"height":720,"url":"https://forerunnerrtmp.livestreamingcdn.com/output18/output18.stream/playlist.m3u8","httpReferrer":null,"userAgent":null,"cluster_id":1,"_id":"u7iyA6cjtf1iWWAZ","status":"online"}
{"line": 2,"quality":null,"label":null,"name":"Libyas Channel","channel":"LibyasChannel.ly","filepath":"ly.m3u","url":"https://master.starmena-cloud.com/hls/libyas.m3u8","httpReferrer":null,"userAgent":null,"cluster_id":3,"_id":"WTbieV1ptnZVCIdn","status":"online","bitrate":0,"frame_rate":25,"width":1024,"height":576}

@ -1,14 +0,0 @@
{"line": 2,"quality":"1080p","label":null,"name":"ЛДПР ТВ","channel":"LDPRTV.ru","filepath":"ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8","httpReferrer":null,"userAgent":null,"_id":"2ST8btby3mmsgPF0"}
{"line": 2,"quality":"1080p","label":null,"name":"ЛДПР ТВ","channel":"LDPRTV.ru","filepath":"ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/timeout.m3u8","httpReferrer":null,"userAgent":null,"_id":"2ST8btby3mmsgPF1"}
{"line": 2,"quality":"1080p","label":null,"name":"ЛДПР ТВ","channel":"LDPRTV.ru","filepath":"ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"2ST8btby3mmsgPF2"}
{"line": 2,"quality":"1080p","label":null,"name":"ЛДПР ТВ","channel":"LDPRTV.ru","filepath":"ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/error.m3u8","httpReferrer":null,"userAgent":null,"_id":"2ST8btby3mmsgPF3"}
{"line": 2,"quality":"720p","label":"Geo-blocked","name":"BBC News HD","channel":"BBCNews.uk","filepath":"uk.m3u","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"3TbieV1ptnZVCId5"}
{"line": 2,"quality":null,"label":null,"name":"BBC News HD","channel":"BBCNews.uk","filepath":"uk.m3u","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","httpReferrer":null,"userAgent":null,"_id":"3TbieV1ptnZVCIdn"}
{"line": 2,"quality":null,"label":null,"name":"ATV","channel":"AndorraTV.ad","filepath":"ad.m3u","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","httpReferrer":null,"userAgent":null,"_id":"I6cjG2xCBRFFP44z"}
{"line": 2,"quality":"720p","label":"Not 24/7","name":"Andorra TV","channel":"","filepath":"uk.m3u","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8","httpReferrer":"http://imn.iq","userAgent":"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","_id":"WTbieV1ptnZVCIdn"}
{"line": 2,"quality":null,"label":null,"name":"Visit-X TV","channel":"VisitXTV.nl","filepath":"nl.m3u","url":"https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8","httpReferrer":null,"userAgent":null,"_id":"2ST8btby3mmsgPF5"}
{"line": 2,"quality":null,"label":null,"name":"Visit-X TV","channel":"VisitXTV.nl","filepath":"nl.m3u","url":"https://stream.visit-x.tv/vxtv/ngrp:live_all/60fps.m3u8","httpReferrer":null,"userAgent":null,"_id":"2ST8btby3mmsgPF6"}
{"line": 2,"quality":null,"label":null,"name":"Daawah TV","channel":"","filepath":"in.m3u","url":"http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"2ST8btby3mmsgPF9"}
{"line": 2,"quality":null,"label":null,"name":"Meteomedia","channel":"MeteoMedia.ca","filepath":"in.m3u","url":"http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"2ST8btby3mmsgP49"}
{"line": 2,"quality":"480p","label":null,"name":"Zoo","channel":"Zoo.ad","filepath":"ad.m3u","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/zoo?480","httpReferrer":null,"userAgent":null,"_id":"I6cjG2xCBRFFP4s3"}
{"line": 2,"quality":"720p","label":null,"name":"Zoo","channel":"Zoo.ad","filepath":"ad.m3u","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/zoo","httpReferrer":null,"userAgent":null,"_id":"I6cjG2xCBRFFP4sz"}

@ -1,21 +0,0 @@
{"line": 2,"name":"ЛДПР ТВ","quality":"1080p","label":null,"channel":"LDPRTV.ru","filepath":"ru.m3u","url":"https://service-stitcher.clusters.pluto.tv/stitch/hls/channel/5ca525b650be2571e3943c63/master.m3u8?deviceId=5ca525b650be2571e3943c63&appName=web&advertisingId=","httpReferrer":null,"userAgent":null,"_id":"2ST8btby3mmsgPF3"}
{"line": 2,"name":"ЛДПР ТВ","quality":"1080p","label":null,"channel":"LDPRTV.ru","filepath":"ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"2ST8btby3mmsgPF0"}
{"line": 2,"name":"ЛДПР ТВ","quality":"1080p","label":null,"channel":"LDPRTV.ru","filepath":"ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"2ST8btby3mmsgPF1"}
{"line": 2,"name":"ЛДПР ТВ","quality":"1080p","label":null,"channel":"LDPRTV.ru","filepath":"ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"2ST8btby3mmsgPF2"}
{"line": 2,"name":"BBC News HD","quality":"720p","label":"Not 24/7","channel":"BBCNews.uk","filepath":"uk.m3u","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","httpReferrer":null,"userAgent":null,"_id":"3TbieV1ptnZVCIdn"}
{"line": 2,"quality":"720p","label":"Offline","name":"ATV","channel":"AndorraTV.ad","filepath":"ad.m3u","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","httpReferrer":"http://imn.iq","userAgent":"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","_id":"I6cjG2xCBRFFP4sz"}
{"line": 2,"quality":"480p","label":"Geo-blocked","name":"BBC News HD","channel":"BBCNews.uk","filepath":"uk.m3u","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"WTbieV1ptnZVCIdn"}
{"line": 2,"quality":null,"label":null,"name":"Kayhan TV","channel":"KayhanTV.af","filepath":"af.m3u","url":"http://208.93.117.113/live/Stream1/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"cFFpFVzSn6xFMUF3"}
{"line": 2,"quality":null,"label":null,"name":"Sharq","channel":"Sharq.af","filepath":"af.m3u","url":"http://51.210.199.50/hls/stream.m3u8","httpReferrer":null,"userAgent":null,"_id":"u7iyA6cjtf1iWWAZ"}
{"line": 2,"quality":"342p","label":"Geo-blocked","channel":"NPO1.nl","name":"NPO 1","filepath":"nl.m3u","url":"http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo1/npo1.isml/.m3u8","httpReferrer":null,"userAgent":null,"_id":"mvUyDVuS5gc8gLJV"}
{"line": 2,"quality":"1080p","label":"Geo-blocked","channel":"NPO1.nl","name":"NPO 1","filepath":"nl.m3u","url":"http://stream.tvtap.net:8081/live/nl-npo1.stream/30fps.m3u8","httpReferrer":null,"userAgent":null,"_id":"8WVbsxsYeOL7kHQl"}
{"line": 2,"quality":"1080p","label":"Geo-blocked","channel":"NPO1.nl","name":"NPO 1","filepath":"nl.m3u","url":"http://stream.tvtap.net:8081/live/nl-npo1.stream/60fps.m3u8","httpReferrer":null,"userAgent":null,"_id":"8WVbsxsYeOL7kHQB"}
{"line": 2,"quality":"342p","label":null,"channel":"NPO2.nl","name":"NPO 2","filepath":"nl.m3u","url":"http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8","httpReferrer":null,"userAgent":null,"_id":"2p1TNGO0mF0MJOGy"}
{"line": 2,"quality":"302p","label":"Geo-blocked","channel":"NPO2.nl","name":"NPO 2","filepath":"nl.m3u","url":"http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"nhL85BL7YM5OR7cn"}
{"line": 2,"quality":null,"label":null,"name":"Tele 2000","channel":"Tele2000.pe","filepath":"pe.m3u","url":"https://servilive.com:3126/live/tele2000live.m3u8","httpReferrer":"https://example2.com/","userAgent":null,"_id":"cF0pFVzSn6xFMUF3"}
{"line": 2,"quality":null,"label":null,"name":"Planeta Junior TV","channel":"","filepath":"es.m3u","url":"https://deaplaneta-planetakidz-1-es.samsung.wurl.tv/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"1BT8btby3mmsgPF0"}
{"line": 2,"quality":null,"label":null,"name":"Caillou","channel":"","filepath":"es.m3u","url":"https://dhx-caillou-1-es.samsung.wurl.tv/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"3BT8btby3mmsgPF0"}
{"line": 2,"quality":null,"label":null,"name":"iHola Play","channel":"","filepath":"es.m3u","url":"https://rakuten-hola-2-es.samsung.wurl.tv/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"2BT8btby3mmsgPF0"}
{"line": 2,"quality":"720p","label":null,"name":"Telearuba","channel":"Telearuba.aw","filepath":"aw.m3u","url":"http://cdn.setar.aw:1935/Telearuba/smil:telearuba.smil/playlist.m3u8","httpReferrer":null,"userAgent":null,"_id":"6BT8btby3mmsgPF0"}
{"line": 2,"quality":"480p","label":"Not 24/7","name":"Telearuba","channel":"Telearuba.aw","filepath":"aw.m3u","url":"https://backend-server-dot-telearuba-app.appspot.com/media/livestream13/playlist.m3u8","httpReferrer":null,"userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36","_id":"4BT8btby3mmsgPF0"}
{"line": 2,"quality":"","label":"","name":"Telearuba","channel":"","filepath":"bg.m3u","url":"https://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajgm3u8","httpReferrer":null,"userAgent":null,"_id":"4BT8btby3mmsgSF0"}

@ -1,5 +0,0 @@
#EXTM3U
#EXTINF:-1 tvg-id="ATV.ad" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",ATV (720p) [Offline]
#EXTVLCOPT:http-referrer=http://imn.iq
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
https://iptv-all.lanesh4d0w.repl.co/andorra/atv

@ -1,3 +0,0 @@
#EXTM3U
#EXTINF:-1 tvg-id="LibyasChannel.ly",Libyas Channel
https://master.starmena-cloud.com/hls/libyas.m3u8

@ -1,3 +0,0 @@
#EXTM3U
#EXTINF:-1 tvg-id="",1A Network (720p)
https://simultv.s.llnwi.net/n4s4/2ANetwork/interlink.m3u8

@ -0,0 +1,3 @@
#EXTM3U
#EXTINF:-1 tvg-id="mn.in",Manorama News
https://ythls.onrender.com/channel/UCP0uG-mcMImgKnJz-VjJZmQ.m3u8

@ -0,0 +1,9 @@
#EXTM3U
#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (302p) [Geo-blocked]
http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8?
#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (342p)
http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8
#EXTINF:-1 tvg-id="NPO1.nl",NPO 1 (342p) [Geo-blocked]
http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo1/npo1.isml/.m3u8
#EXTINF:-1 tvg-id="",NPO 2 (Duplicate)
http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8

@ -0,0 +1,5 @@
#EXTM3U
#EXTINF:-1 tvg-id="Zoo.ad",Zoo (720p)
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
#EXTINF:-1 tvg-id="AndorraTV.ad",ATV
https://iptv-all.lanesh4d0w.repl.co/andorra/atv

@ -0,0 +1,3 @@
#EXTM3U
#EXTINF:-1 tvg-id="MeteoMedia.ca",Meteomedia
http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8

@ -0,0 +1,3 @@
#EXTM3U
#EXTINF:-1 tvg-id="",Daawah TV
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8

@ -0,0 +1,3 @@
#EXTM3U
#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8

@ -0,0 +1,9 @@
#EXTM3U
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
#EXTINF:-1 tvg-id="VisitXTV.nl",Visit-X TV
https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8
#EXTINF:-1 tvg-id="" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
#EXTVLCOPT:http-referrer=http://imn.iq
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8

@ -0,0 +1,3 @@
#EXTM3U
#EXTINF:-1 tvg-id="",TUTV
https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8

@ -0,0 +1,6 @@
#EXTM3U
#EXTINF:-1 tvg-id="",VTV
https://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajgm3u8
#EXTINF:-1 tvg-id="",Tele2000
#EXTVLCOPT:http-referrer=https://example2.com/
https://servilive.com:3126/live/tele2000live.m3u8

@ -0,0 +1,5 @@
#EXTM3U
#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (720p) [Not 24/7]
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8
#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (480p) [Geo-blocked]
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8

@ -3,14 +3,9 @@ import fs from 'fs-extra'
beforeEach(() => { beforeEach(() => {
fs.emptyDirSync('tests/__data__/output') fs.emptyDirSync('tests/__data__/output')
fs.mkdirSync('tests/__data__/output/database')
fs.copyFileSync(
'tests/__data__/input/database/api_generate.streams.db',
'tests/__data__/output/database/streams.db'
)
const stdout = execSync( const stdout = execSync(
'DB_DIR=tests/__data__/output/database API_DIR=tests/__data__/output/.api npm run api:generate', 'STREAMS_DIR=tests/__data__/input/streams_generate API_DIR=tests/__data__/output/.api npm run api:generate',
{ encoding: 'utf8' } { encoding: 'utf8' }
) )
}) })

@ -1,45 +0,0 @@
import * as fs from 'fs-extra'
import * as path from 'path'
import { execSync } from 'child_process'
import * as _ from 'lodash'
beforeEach(() => {
fs.emptyDirSync('tests/__data__/output')
fs.mkdirSync('tests/__data__/output/database')
const stdout = execSync(
'DB_DIR=tests/__data__/output/database DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/input/streams npm run db:create',
{ encoding: 'utf8' }
)
})
it('can create database', () => {
let output = content('tests/__data__/output/database/streams.db')
let expected = content('tests/__data__/expected/database/db_create.streams.db')
output = output.map(i => {
i._id = null
return i
})
expected = expected.map(i => {
i._id = null
return i
})
expect(_.orderBy(output, 'name')).toMatchObject(
expect.arrayContaining(_.orderBy(expected, 'name'))
)
})
function content(filepath: string) {
const data = fs.readFileSync(path.resolve(filepath), {
encoding: 'utf8'
})
return data
.split('\n')
.filter(l => l)
.map(l => {
return JSON.parse(l)
})
}

@ -0,0 +1,30 @@
import { execSync } from 'child_process'
import * as fs from 'fs-extra'
import { glob } from 'glob'
beforeEach(() => {
fs.emptyDirSync('tests/__data__/output')
fs.copySync('tests/__data__/input/streams_format', 'tests/__data__/output/streams')
})
it('can format playlists', () => {
const stdout = execSync('STREAMS_DIR=tests/__data__/output/streams npm run playlist:format', {
encoding: 'utf8'
})
const files = glob
.sync('tests/__data__/expected/streams_format/*.m3u')
.map(f => f.replace('tests/__data__/expected/streams_format/', ''))
files.forEach(filepath => {
expect(content(`output/streams/${filepath}`), filepath).toBe(
content(`expected/streams_format/${filepath}`)
)
})
})
function content(filepath: string) {
return fs.readFileSync(`tests/__data__/${filepath}`, {
encoding: 'utf8'
})
}

@ -4,13 +4,9 @@ import * as glob from 'glob'
beforeEach(() => { beforeEach(() => {
fs.emptyDirSync('tests/__data__/output') fs.emptyDirSync('tests/__data__/output')
fs.copyFileSync(
'tests/__data__/input/database/playlist_generate.streams.db',
'tests/__data__/output/streams.db'
)
const stdout = execSync( const stdout = execSync(
'DB_DIR=tests/__data__/output DATA_DIR=tests/__data__/input/data PUBLIC_DIR=tests/__data__/output/.gh-pages LOGS_DIR=tests/__data__/output/logs npm run playlist:generate', 'STREAMS_DIR=tests/__data__/input/streams_generate DATA_DIR=tests/__data__/input/data PUBLIC_DIR=tests/__data__/output/.gh-pages LOGS_DIR=tests/__data__/output/logs npm run playlist:generate',
{ encoding: 'utf8' } { encoding: 'utf8' }
) )
}) })

@ -4,15 +4,12 @@ import { glob } from 'glob'
beforeEach(() => { beforeEach(() => {
fs.emptyDirSync('tests/__data__/output') fs.emptyDirSync('tests/__data__/output')
fs.copyFileSync( fs.copySync('tests/__data__/input/streams_update', 'tests/__data__/output/streams')
'tests/__data__/input/database/playlist_update.streams.db',
'tests/__data__/output/streams.db'
)
}) })
it('can format playlists', () => { it('can format playlists', () => {
const stdout = execSync( const stdout = execSync(
'DEBUG=true DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/output/streams DB_DIR=tests/__data__/output npm run playlist:update --silent', 'DEBUG=true DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/output/streams npm run playlist:update --silent',
{ {
encoding: 'utf8' encoding: 'utf8'
} }
@ -21,11 +18,13 @@ it('can format playlists', () => {
expect(stdout).toBe(`OUTPUT=closes #14151, closes #14110, closes #14179, closes #14178\n`) expect(stdout).toBe(`OUTPUT=closes #14151, closes #14110, closes #14179, closes #14178\n`)
const files = glob const files = glob
.sync('tests/__data__/expected/streams/*.m3u') .sync('tests/__data__/expected/streams_update/*.m3u')
.map(f => f.replace('tests/__data__/expected/', '')) .map(f => f.replace('tests/__data__/expected/streams_update/', ''))
files.forEach(filepath => { files.forEach(filepath => {
expect(content(`output/${filepath}`), filepath).toBe(content(`expected/${filepath}`)) expect(content(`output/streams/${filepath}`), filepath).toBe(
content(`expected/streams_update/${filepath}`)
)
}) })
}) })

@ -3,7 +3,7 @@ import { execSync } from 'child_process'
it('show an error if channel name in the blocklist', () => { it('show an error if channel name in the blocklist', () => {
try { try {
const stdout = execSync( const stdout = execSync(
'DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/input/streams npm run playlist:validate -- tests/__data__/input/streams/us_blocked.m3u', 'DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/input/streams_validate npm run playlist:validate -- us_blocked.m3u',
{ {
encoding: 'utf8' encoding: 'utf8'
} }
@ -14,7 +14,7 @@ it('show an error if channel name in the blocklist', () => {
expect(error.status).toBe(1) expect(error.status).toBe(1)
expect( expect(
error.stdout.includes( error.stdout.includes(
`loading blocklist...\nfound 4 records\n\ntests/__data__/input/streams/us_blocked.m3u\n 2 error "Fox Sports 2 Asia (Thai)" is on the blocklist due to claims of copyright holders (https://github.com/iptv-org/iptv/issues/0000)\n\n1 problems (1 errors, 0 warnings)\n` `us_blocked.m3u\n 2 error "Fox Sports 2 Asia (Thai)" is on the blocklist due to claims of copyright holders (https://github.com/iptv-org/iptv/issues/0000)\n\n1 problems (1 errors, 0 warnings)\n`
) )
).toBe(true) ).toBe(true)
} }
@ -22,7 +22,7 @@ it('show an error if channel name in the blocklist', () => {
it('show a warning if channel has wrong id', () => { it('show a warning if channel has wrong id', () => {
const stdout = execSync( const stdout = execSync(
'DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/input/streams npm run playlist:validate -- tests/__data__/input/streams/wrong_id.m3u', 'DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/input/streams_validate npm run playlist:validate -- wrong_id.m3u',
{ {
encoding: 'utf8' encoding: 'utf8'
} }
@ -30,7 +30,7 @@ it('show a warning if channel has wrong id', () => {
expect( expect(
stdout.includes( stdout.includes(
`loading blocklist...\nfound 4 records\n\ntests/__data__/input/streams/wrong_id.m3u\n 2 warning "qib22lAq1L.us" is not in the database\n\n1 problems (0 errors, 1 warnings)\n` `wrong_id.m3u\n 2 warning "qib22lAq1L.us" is not in the database\n\n1 problems (0 errors, 1 warnings)\n`
) )
).toBe(true) ).toBe(true)
}) })

@ -1,9 +1,12 @@
import { execSync } from 'child_process' import { execSync } from 'child_process'
it('can create report', () => { it('can create report', () => {
const stdout = execSync('DATA_DIR=tests/__data__/input/data npm run report:create', { const stdout = execSync(
encoding: 'utf8' 'DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/input/streams_report npm run report:create',
}) {
encoding: 'utf8'
}
)
expect( expect(
stdout.includes(` stdout.includes(`

@ -670,20 +670,6 @@
resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
"@seald-io/binary-search-tree@^1.0.3":
version "1.0.3"
resolved "https://registry.npmjs.org/@seald-io/binary-search-tree/-/binary-search-tree-1.0.3.tgz"
integrity sha512-qv3jnwoakeax2razYaMsGI/luWdliBLHTdC6jU55hQt1hcFqzauH/HsBollQ7IR4ySTtYhT+xyHoijpA16C+tA==
"@seald-io/nedb@^4.0.2":
version "4.0.2"
resolved "https://registry.npmjs.org/@seald-io/nedb/-/nedb-4.0.2.tgz"
integrity sha512-gJ91fT1sgh2cLXYVcTSh7khZ8LdemI8+SojCdpZ5wy+DUQ4fSrEwGqOwbdV49NDs2BBO6GeBpSb8CnhG2IW1rw==
dependencies:
"@seald-io/binary-search-tree" "^1.0.3"
localforage "^1.9.0"
util "^0.12.4"
"@sinclair/typebox@^0.27.8": "@sinclair/typebox@^0.27.8":
version "0.27.8" version "0.27.8"
resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz"
@ -947,11 +933,6 @@ async@^3.2.4:
resolved "https://registry.npmjs.org/async/-/async-3.2.4.tgz" resolved "https://registry.npmjs.org/async/-/async-3.2.4.tgz"
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
available-typed-arrays@^1.0.5:
version "1.0.5"
resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz"
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
babel-jest@^29.0.0, babel-jest@^29.6.4: babel-jest@^29.0.0, babel-jest@^29.6.4:
version "29.6.4" version "29.6.4"
resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.4.tgz" resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.4.tgz"
@ -1074,14 +1055,6 @@ buffer-from@^1.0.0:
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
call-bind@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz"
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
dependencies:
function-bind "^1.1.1"
get-intrinsic "^1.0.2"
callsites@^3.0.0: callsites@^3.0.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
@ -1431,13 +1404,6 @@ find-up@^4.0.0, find-up@^4.1.0:
locate-path "^5.0.0" locate-path "^5.0.0"
path-exists "^4.0.0" path-exists "^4.0.0"
for-each@^0.3.3:
version "0.3.3"
resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz"
integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==
dependencies:
is-callable "^1.1.3"
foreground-child@^3.1.0: foreground-child@^3.1.0:
version "3.1.1" version "3.1.1"
resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz" resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz"
@ -1489,16 +1455,6 @@ get-caller-file@^2.0.5:
resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
get-intrinsic@^1.0.2, get-intrinsic@^1.1.3:
version "1.2.1"
resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz"
integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==
dependencies:
function-bind "^1.1.1"
has "^1.0.3"
has-proto "^1.0.1"
has-symbols "^1.0.3"
get-package-type@^0.1.0: get-package-type@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz"
@ -1597,13 +1553,6 @@ globby@^6.1.0:
pify "^2.0.0" pify "^2.0.0"
pinkie-promise "^2.0.0" pinkie-promise "^2.0.0"
gopd@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz"
integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
dependencies:
get-intrinsic "^1.1.3"
graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9:
version "4.2.9" version "4.2.9"
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz"
@ -1619,23 +1568,6 @@ has-flag@^4.0.0:
resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
has-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz"
integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==
has-symbols@^1.0.2, has-symbols@^1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz"
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
has-tostringtag@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz"
integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
dependencies:
has-symbols "^1.0.2"
has@^1.0.3: has@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz"
@ -1653,11 +1585,6 @@ human-signals@^2.1.0:
resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
immediate@~3.0.5:
version "3.0.6"
resolved "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz"
integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
import-local@^3.0.2: import-local@^3.0.2:
version "3.1.0" version "3.1.0"
resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz" resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz"
@ -1679,7 +1606,7 @@ inflight@^1.0.4:
once "^1.3.0" once "^1.3.0"
wrappy "1" wrappy "1"
inherits@^2.0.3, inherits@2: inherits@2:
version "2.0.4" version "2.0.4"
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@ -1692,24 +1619,11 @@ iptv-playlist-parser@^0.12.3:
is-valid-path "^0.1.1" is-valid-path "^0.1.1"
validator "^13.7.0" validator "^13.7.0"
is-arguments@^1.0.4:
version "1.1.1"
resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz"
integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==
dependencies:
call-bind "^1.0.2"
has-tostringtag "^1.0.0"
is-arrayish@^0.2.1: is-arrayish@^0.2.1:
version "0.2.1" version "0.2.1"
resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-callable@^1.1.3:
version "1.2.7"
resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz"
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
is-core-module@^2.13.0: is-core-module@^2.13.0:
version "2.13.0" version "2.13.0"
resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz" resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz"
@ -1732,13 +1646,6 @@ is-generator-fn@^2.0.0:
resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz"
integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
is-generator-function@^1.0.7:
version "1.0.10"
resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz"
integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==
dependencies:
has-tostringtag "^1.0.0"
is-glob@^2.0.0: is-glob@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" resolved "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz"
@ -1768,13 +1675,6 @@ is-stream@^2.0.0:
resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
is-typed-array@^1.1.3:
version "1.1.12"
resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz"
integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==
dependencies:
which-typed-array "^1.1.11"
is-valid-path@^0.1.1: is-valid-path@^0.1.1:
version "0.1.1" version "0.1.1"
resolved "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz" resolved "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz"
@ -2272,13 +2172,6 @@ leven@^3.1.0:
resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz"
integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
lie@3.1.1:
version "3.1.1"
resolved "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz"
integrity sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=
dependencies:
immediate "~3.0.5"
lines-and-columns@^1.1.6: lines-and-columns@^1.1.6:
version "1.2.4" version "1.2.4"
resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz"
@ -2294,13 +2187,6 @@ load-json-file@^4.0.0:
pify "^3.0.0" pify "^3.0.0"
strip-bom "^3.0.0" strip-bom "^3.0.0"
localforage@^1.9.0:
version "1.10.0"
resolved "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz"
integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==
dependencies:
lie "3.1.1"
locate-path@^2.0.0: locate-path@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz"
@ -3008,17 +2894,6 @@ universalify@^2.0.0:
resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz"
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
util@^0.12.4:
version "0.12.5"
resolved "https://registry.npmjs.org/util/-/util-0.12.5.tgz"
integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==
dependencies:
inherits "^2.0.3"
is-arguments "^1.0.4"
is-generator-function "^1.0.7"
is-typed-array "^1.1.3"
which-typed-array "^1.1.2"
v8-compile-cache-lib@^3.0.1: v8-compile-cache-lib@^3.0.1:
version "3.0.1" version "3.0.1"
resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz"
@ -3058,17 +2933,6 @@ whatwg-url@^5.0.0:
tr46 "~0.0.3" tr46 "~0.0.3"
webidl-conversions "^3.0.0" webidl-conversions "^3.0.0"
which-typed-array@^1.1.11, which-typed-array@^1.1.2:
version "1.1.11"
resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz"
integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==
dependencies:
available-typed-arrays "^1.0.5"
call-bind "^1.0.2"
for-each "^0.3.3"
gopd "^1.0.1"
has-tostringtag "^1.0.0"
which@^2.0.1: which@^2.0.1:
version "2.0.2" version "2.0.2"
resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz"

Loading…
Cancel
Save