mirror of
https://github.com/iptv-org/iptv
synced 2025-12-16 02:16:47 -05:00
Replace LF with CRLF
This commit is contained in:
@@ -1,85 +1,85 @@
|
||||
{"type":"raw","filepath":"raw/ad.m3u","count":4}
|
||||
{"type":"raw","filepath":"raw/ca.m3u","count":2}
|
||||
{"type":"raw","filepath":"raw/in.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/kg.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/uk.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/unsorted.m3u","count":4}
|
||||
{"type":"category","filepath":"categories/auto.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/animation.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/classic.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/comedy.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/culture.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/documentary.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/business.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/cooking.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/education.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/family.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/legislative.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/news.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/kids.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/lifestyle.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/movies.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/religious.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/outdoor.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/general.m3u","count":3}
|
||||
{"type":"category","filepath":"categories/relax.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/music.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/series.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/travel.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/sports.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/science.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/weather.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/shop.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/xxx.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/undefined.m3u","count":7}
|
||||
{"type":"category","filepath":"categories/entertainment.m3u","count":0}
|
||||
{"type":"language","filepath":"languages/cat.m3u","count":1}
|
||||
{"type":"language","filepath":"languages/eng.m3u","count":1}
|
||||
{"type":"language","filepath":"languages/undefined.m3u","count":8}
|
||||
{"type":"language","filepath":"languages/rus.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/ad.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/ru.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/ca.m3u","count":2}
|
||||
{"type":"country","filepath":"countries/int.m3u","count":4}
|
||||
{"type":"country","filepath":"countries/undefined.m3u","count":4}
|
||||
{"type":"subdivision","filepath":"subdivisions/ad-02.m3u","count":1}
|
||||
{"type":"city","filepath":"cities/adcan.m3u","count":1}
|
||||
{"type":"region","filepath":"regions/afr.m3u","count":2}
|
||||
{"type":"source","filepath":"sources/in.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ad-07.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-on.m3u","count":1}
|
||||
{"type":"region","filepath":"regions/amer.m3u","count":5}
|
||||
{"type":"region","filepath":"regions/apac.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/cas.m3u","count":3}
|
||||
{"type":"region","filepath":"regions/asean.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/cis.m3u","count":4}
|
||||
{"type":"region","filepath":"regions/carib.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/arab.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/emea.m3u","count":5}
|
||||
{"type":"region","filepath":"regions/asia.m3u","count":4}
|
||||
{"type":"region","filepath":"regions/cenamer.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/ww.m3u","count":7}
|
||||
{"type":"region","filepath":"regions/eur.m3u","count":5}
|
||||
{"type":"region","filepath":"regions/lac.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/maghreb.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/latam.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/hispam.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/mena.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/mideast.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/nam.m3u","count":5}
|
||||
{"type":"region","filepath":"regions/oce.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/nord.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/southam.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/noram.m3u","count":5}
|
||||
{"type":"region","filepath":"regions/wafr.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/sas.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/ssa.m3u","count":2}
|
||||
{"type":"source","filepath":"sources/unsorted.m3u","count":4}
|
||||
{"type":"source","filepath":"sources/ca.m3u","count":2}
|
||||
{"type":"source","filepath":"sources/ad.m3u","count":3}
|
||||
{"type":"source","filepath":"sources/uk.m3u","count":1}
|
||||
{"type":"source","filepath":"sources/kg.m3u","count":1}
|
||||
{"type":"index","filepath":"index.m3u","count":11}
|
||||
{"type":"index","filepath":"index.category.m3u","count":12}
|
||||
{"type":"index","filepath":"index.country.m3u","count":12}
|
||||
{"type":"index","filepath":"index.language.m3u","count":11}
|
||||
{"type":"raw","filepath":"raw/ad.m3u","count":4}
|
||||
{"type":"raw","filepath":"raw/ca.m3u","count":2}
|
||||
{"type":"raw","filepath":"raw/in.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/kg.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/uk.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/unsorted.m3u","count":4}
|
||||
{"type":"category","filepath":"categories/auto.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/animation.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/classic.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/comedy.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/culture.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/documentary.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/business.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/cooking.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/education.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/family.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/legislative.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/news.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/kids.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/lifestyle.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/movies.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/religious.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/outdoor.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/general.m3u","count":3}
|
||||
{"type":"category","filepath":"categories/relax.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/music.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/series.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/travel.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/sports.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/science.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/weather.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/shop.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/xxx.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/undefined.m3u","count":7}
|
||||
{"type":"category","filepath":"categories/entertainment.m3u","count":0}
|
||||
{"type":"language","filepath":"languages/cat.m3u","count":1}
|
||||
{"type":"language","filepath":"languages/eng.m3u","count":1}
|
||||
{"type":"language","filepath":"languages/undefined.m3u","count":8}
|
||||
{"type":"language","filepath":"languages/rus.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/ad.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/ru.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/ca.m3u","count":2}
|
||||
{"type":"country","filepath":"countries/int.m3u","count":4}
|
||||
{"type":"country","filepath":"countries/undefined.m3u","count":4}
|
||||
{"type":"subdivision","filepath":"subdivisions/ad-02.m3u","count":1}
|
||||
{"type":"city","filepath":"cities/adcan.m3u","count":1}
|
||||
{"type":"region","filepath":"regions/afr.m3u","count":2}
|
||||
{"type":"source","filepath":"sources/in.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ad-07.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-on.m3u","count":1}
|
||||
{"type":"region","filepath":"regions/amer.m3u","count":5}
|
||||
{"type":"region","filepath":"regions/apac.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/cas.m3u","count":3}
|
||||
{"type":"region","filepath":"regions/asean.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/cis.m3u","count":4}
|
||||
{"type":"region","filepath":"regions/carib.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/arab.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/emea.m3u","count":5}
|
||||
{"type":"region","filepath":"regions/asia.m3u","count":4}
|
||||
{"type":"region","filepath":"regions/cenamer.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/ww.m3u","count":7}
|
||||
{"type":"region","filepath":"regions/eur.m3u","count":5}
|
||||
{"type":"region","filepath":"regions/lac.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/maghreb.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/latam.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/hispam.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/mena.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/mideast.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/nam.m3u","count":5}
|
||||
{"type":"region","filepath":"regions/oce.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/nord.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/southam.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/noram.m3u","count":5}
|
||||
{"type":"region","filepath":"regions/wafr.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/sas.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/ssa.m3u","count":2}
|
||||
{"type":"source","filepath":"sources/unsorted.m3u","count":4}
|
||||
{"type":"source","filepath":"sources/ca.m3u","count":2}
|
||||
{"type":"source","filepath":"sources/ad.m3u","count":3}
|
||||
{"type":"source","filepath":"sources/uk.m3u","count":1}
|
||||
{"type":"source","filepath":"sources/kg.m3u","count":1}
|
||||
{"type":"index","filepath":"index.m3u","count":11}
|
||||
{"type":"index","filepath":"index.category.m3u","count":12}
|
||||
{"type":"index","filepath":"index.country.m3u","count":12}
|
||||
{"type":"index","filepath":"index.language.m3u","count":11}
|
||||
|
||||
@@ -1,177 +1,177 @@
|
||||
## Playlists
|
||||
|
||||
There are several versions of playlists that differ in the way they are grouped. As of January 30th, 2024, we have stopped distributing NSFW channels. For more information, please look at [this issue](https://github.com/iptv-org/iptv/issues/15723).
|
||||
|
||||
### Grouped by category
|
||||
|
||||
Playlists in which channels are grouped by category.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
<br>
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/index.category.m3u
|
||||
```
|
||||
|
||||
Same thing, but split up into separate files:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th align="left">Category</th><th align="left">Channels</th><th align="left">Playlist</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>Animation</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/animation.m3u</code></td></tr>
|
||||
<tr><td>Auto</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/auto.m3u</code></td></tr>
|
||||
<tr><td>Business</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/business.m3u</code></td></tr>
|
||||
<tr><td>Classic</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/classic.m3u</code></td></tr>
|
||||
<tr><td>Comedy</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/comedy.m3u</code></td></tr>
|
||||
<tr><td>Cooking</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/cooking.m3u</code></td></tr>
|
||||
<tr><td>Culture</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/culture.m3u</code></td></tr>
|
||||
<tr><td>Documentary</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/documentary.m3u</code></td></tr>
|
||||
<tr><td>Education</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/education.m3u</code></td></tr>
|
||||
<tr><td>Entertainment</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/entertainment.m3u</code></td></tr>
|
||||
<tr><td>Family</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/family.m3u</code></td></tr>
|
||||
<tr><td>General</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/general.m3u</code></td></tr>
|
||||
<tr><td>Kids</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/kids.m3u</code></td></tr>
|
||||
<tr><td>Legislative</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/legislative.m3u</code></td></tr>
|
||||
<tr><td>Lifestyle</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/lifestyle.m3u</code></td></tr>
|
||||
<tr><td>Movies</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/movies.m3u</code></td></tr>
|
||||
<tr><td>Music</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/music.m3u</code></td></tr>
|
||||
<tr><td>News</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/news.m3u</code></td></tr>
|
||||
<tr><td>Outdoor</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/outdoor.m3u</code></td></tr>
|
||||
<tr><td>Relax</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/relax.m3u</code></td></tr>
|
||||
<tr><td>Religious</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/religious.m3u</code></td></tr>
|
||||
<tr><td>Science</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/science.m3u</code></td></tr>
|
||||
<tr><td>Series</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/series.m3u</code></td></tr>
|
||||
<tr><td>Shop</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/shop.m3u</code></td></tr>
|
||||
<tr><td>Sports</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/sports.m3u</code></td></tr>
|
||||
<tr><td>Travel</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/travel.m3u</code></td></tr>
|
||||
<tr><td>Weather</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/weather.m3u</code></td></tr>
|
||||
<tr><td>XXX</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/xxx.m3u</code></td></tr>
|
||||
<tr><td>Undefined</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/undefined.m3u</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</details>
|
||||
|
||||
### Grouped by language
|
||||
|
||||
Playlists in which channels are grouped by the language in which they are broadcast.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
<br>
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/index.language.m3u
|
||||
```
|
||||
|
||||
Same thing, but split up into separate files:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th align="left">Language</th><th align="left">Channels</th><th align="left">Playlist</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td align="left">Catalan</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/cat.m3u</code></td></tr>
|
||||
<tr><td align="left">English</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/eng.m3u</code></td></tr>
|
||||
<tr><td align="left">French</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/fra.m3u</code></td></tr>
|
||||
<tr><td align="left">Russian</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/rus.m3u</code></td></tr>
|
||||
<tr><td align="left">Undefined</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/undefined.m3u</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</details>
|
||||
|
||||
### Grouped by broadcast area
|
||||
|
||||
Playlists in which channels are grouped by broadcast area.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
|
||||
#### Countries
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/index.country.m3u
|
||||
```
|
||||
|
||||
Same thing, but split up into separate files:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
- 🇦🇩 Andorra <code>https://iptv-org.github.io/iptv/countries/ad.m3u</code>
|
||||
- Canillo <code>https://iptv-org.github.io/iptv/subdivisions/ad-02.m3u</code>
|
||||
- Canillo <code>https://iptv-org.github.io/iptv/cities/adcan.m3u</code>
|
||||
- 🇨🇲 Cameroon <code>https://iptv-org.github.io/iptv/countries/cm.m3u</code>
|
||||
- 🇨🇦 Canada <code>https://iptv-org.github.io/iptv/countries/ca.m3u</code>
|
||||
- Ontario <code>https://iptv-org.github.io/iptv/subdivisions/ca-on.m3u</code>
|
||||
- 🇨🇻 Cape Verde <code>https://iptv-org.github.io/iptv/countries/cv.m3u</code>
|
||||
- 🇭🇰 Hong Kong <code>https://iptv-org.github.io/iptv/countries/hk.m3u</code>
|
||||
- Sai Kung <code>https://iptv-org.github.io/iptv/cities/hk9sk.m3u</code>
|
||||
- 🇨🇬 Republic of the Congo <code>https://iptv-org.github.io/iptv/countries/cg.m3u</code>
|
||||
- 🇷🇪 Réunion <code>https://iptv-org.github.io/iptv/countries/re.m3u</code>
|
||||
- 🇷🇴 Romania <code>https://iptv-org.github.io/iptv/countries/ro.m3u</code>
|
||||
- 🇷🇺 Russia <code>https://iptv-org.github.io/iptv/countries/ru.m3u</code>
|
||||
- 🇷🇼 Rwanda <code>https://iptv-org.github.io/iptv/countries/rw.m3u</code>
|
||||
- 🇧🇱 Saint Barthélemy <code>https://iptv-org.github.io/iptv/countries/bl.m3u</code>
|
||||
- 🇸🇭 Saint Helena <code>https://iptv-org.github.io/iptv/countries/sh.m3u</code>
|
||||
- 🇰🇳 Saint Kitts and Nevis <code>https://iptv-org.github.io/iptv/countries/kn.m3u</code>
|
||||
- 🌐 International <code>https://iptv-org.github.io/iptv/countries/int.m3u</code>
|
||||
- Undefined <code>https://iptv-org.github.io/iptv/countries/undefined.m3u</code>
|
||||
|
||||
#### Regions
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
- Africa <code>https://iptv-org.github.io/iptv/regions/afr.m3u</code>
|
||||
- Americas <code>https://iptv-org.github.io/iptv/regions/amer.m3u</code>
|
||||
- Arab world <code>https://iptv-org.github.io/iptv/regions/arab.m3u</code>
|
||||
- Asia <code>https://iptv-org.github.io/iptv/regions/asia.m3u</code>
|
||||
- Asia-Pacific <code>https://iptv-org.github.io/iptv/regions/apac.m3u</code>
|
||||
- Association of Southeast Asian Nations <code>https://iptv-org.github.io/iptv/regions/asean.m3u</code>
|
||||
- Caribbean <code>https://iptv-org.github.io/iptv/regions/carib.m3u</code>
|
||||
- Central America <code>https://iptv-org.github.io/iptv/regions/cenamer.m3u</code>
|
||||
- Central Asia <code>https://iptv-org.github.io/iptv/regions/cas.m3u</code>
|
||||
- Commonwealth of Independent States <code>https://iptv-org.github.io/iptv/regions/cis.m3u</code>
|
||||
- Europe <code>https://iptv-org.github.io/iptv/regions/eur.m3u</code>
|
||||
- Europe, the Middle East and Africa <code>https://iptv-org.github.io/iptv/regions/emea.m3u</code>
|
||||
- Hispanic America <code>https://iptv-org.github.io/iptv/regions/hispam.m3u</code>
|
||||
- Latin America <code>https://iptv-org.github.io/iptv/regions/latam.m3u</code>
|
||||
- Latin America and the Caribbean <code>https://iptv-org.github.io/iptv/regions/lac.m3u</code>
|
||||
- Maghreb <code>https://iptv-org.github.io/iptv/regions/maghreb.m3u</code>
|
||||
- Middle East <code>https://iptv-org.github.io/iptv/regions/mideast.m3u</code>
|
||||
- Middle East and North Africa <code>https://iptv-org.github.io/iptv/regions/mena.m3u</code>
|
||||
- Nordics <code>https://iptv-org.github.io/iptv/regions/nord.m3u</code>
|
||||
- North America <code>https://iptv-org.github.io/iptv/regions/noram.m3u</code>
|
||||
- Northern America <code>https://iptv-org.github.io/iptv/regions/nam.m3u</code>
|
||||
- Oceania <code>https://iptv-org.github.io/iptv/regions/oce.m3u</code>
|
||||
- South America <code>https://iptv-org.github.io/iptv/regions/southam.m3u</code>
|
||||
- South Asia <code>https://iptv-org.github.io/iptv/regions/sas.m3u</code>
|
||||
- Sub-Saharan Africa <code>https://iptv-org.github.io/iptv/regions/ssa.m3u</code>
|
||||
- West Africa <code>https://iptv-org.github.io/iptv/regions/wafr.m3u</code>
|
||||
|
||||
</details>
|
||||
|
||||
### Grouped by sources
|
||||
|
||||
Playlists in which channels are grouped by broadcast source.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
<br>
|
||||
|
||||
To use the playlist, simply replace `<FILENAME>` in the link below with the name of one of the files in the [streams](streams) folder.
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/sources/<FILENAME>.m3u
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Also, any of our internal playlists are available in raw form (without any filtering or sorting) at this link:
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/raw/<FILENAME>.m3u
|
||||
```
|
||||
## Playlists
|
||||
|
||||
There are several versions of playlists that differ in the way they are grouped. As of January 30th, 2024, we have stopped distributing NSFW channels. For more information, please look at [this issue](https://github.com/iptv-org/iptv/issues/15723).
|
||||
|
||||
### Grouped by category
|
||||
|
||||
Playlists in which channels are grouped by category.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
<br>
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/index.category.m3u
|
||||
```
|
||||
|
||||
Same thing, but split up into separate files:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th align="left">Category</th><th align="left">Channels</th><th align="left">Playlist</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>Animation</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/animation.m3u</code></td></tr>
|
||||
<tr><td>Auto</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/auto.m3u</code></td></tr>
|
||||
<tr><td>Business</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/business.m3u</code></td></tr>
|
||||
<tr><td>Classic</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/classic.m3u</code></td></tr>
|
||||
<tr><td>Comedy</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/comedy.m3u</code></td></tr>
|
||||
<tr><td>Cooking</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/cooking.m3u</code></td></tr>
|
||||
<tr><td>Culture</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/culture.m3u</code></td></tr>
|
||||
<tr><td>Documentary</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/documentary.m3u</code></td></tr>
|
||||
<tr><td>Education</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/education.m3u</code></td></tr>
|
||||
<tr><td>Entertainment</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/entertainment.m3u</code></td></tr>
|
||||
<tr><td>Family</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/family.m3u</code></td></tr>
|
||||
<tr><td>General</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/general.m3u</code></td></tr>
|
||||
<tr><td>Kids</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/kids.m3u</code></td></tr>
|
||||
<tr><td>Legislative</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/legislative.m3u</code></td></tr>
|
||||
<tr><td>Lifestyle</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/lifestyle.m3u</code></td></tr>
|
||||
<tr><td>Movies</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/movies.m3u</code></td></tr>
|
||||
<tr><td>Music</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/music.m3u</code></td></tr>
|
||||
<tr><td>News</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/news.m3u</code></td></tr>
|
||||
<tr><td>Outdoor</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/outdoor.m3u</code></td></tr>
|
||||
<tr><td>Relax</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/relax.m3u</code></td></tr>
|
||||
<tr><td>Religious</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/religious.m3u</code></td></tr>
|
||||
<tr><td>Science</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/science.m3u</code></td></tr>
|
||||
<tr><td>Series</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/series.m3u</code></td></tr>
|
||||
<tr><td>Shop</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/shop.m3u</code></td></tr>
|
||||
<tr><td>Sports</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/sports.m3u</code></td></tr>
|
||||
<tr><td>Travel</td><td align="right">0</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/travel.m3u</code></td></tr>
|
||||
<tr><td>Weather</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/weather.m3u</code></td></tr>
|
||||
<tr><td>XXX</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/xxx.m3u</code></td></tr>
|
||||
<tr><td>Undefined</td><td align="right">3</td><td nowrap><code>https://iptv-org.github.io/iptv/categories/undefined.m3u</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</details>
|
||||
|
||||
### Grouped by language
|
||||
|
||||
Playlists in which channels are grouped by the language in which they are broadcast.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
<br>
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/index.language.m3u
|
||||
```
|
||||
|
||||
Same thing, but split up into separate files:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th align="left">Language</th><th align="left">Channels</th><th align="left">Playlist</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td align="left">Catalan</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/cat.m3u</code></td></tr>
|
||||
<tr><td align="left">English</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/eng.m3u</code></td></tr>
|
||||
<tr><td align="left">French</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/fra.m3u</code></td></tr>
|
||||
<tr><td align="left">Russian</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/rus.m3u</code></td></tr>
|
||||
<tr><td align="left">Undefined</td><td align="right">2</td><td align="left" nowrap><code>https://iptv-org.github.io/iptv/languages/undefined.m3u</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</details>
|
||||
|
||||
### Grouped by broadcast area
|
||||
|
||||
Playlists in which channels are grouped by broadcast area.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
|
||||
#### Countries
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/index.country.m3u
|
||||
```
|
||||
|
||||
Same thing, but split up into separate files:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
- 🇦🇩 Andorra <code>https://iptv-org.github.io/iptv/countries/ad.m3u</code>
|
||||
- Canillo <code>https://iptv-org.github.io/iptv/subdivisions/ad-02.m3u</code>
|
||||
- Canillo <code>https://iptv-org.github.io/iptv/cities/adcan.m3u</code>
|
||||
- 🇨🇲 Cameroon <code>https://iptv-org.github.io/iptv/countries/cm.m3u</code>
|
||||
- 🇨🇦 Canada <code>https://iptv-org.github.io/iptv/countries/ca.m3u</code>
|
||||
- Ontario <code>https://iptv-org.github.io/iptv/subdivisions/ca-on.m3u</code>
|
||||
- 🇨🇻 Cape Verde <code>https://iptv-org.github.io/iptv/countries/cv.m3u</code>
|
||||
- 🇭🇰 Hong Kong <code>https://iptv-org.github.io/iptv/countries/hk.m3u</code>
|
||||
- Sai Kung <code>https://iptv-org.github.io/iptv/cities/hk9sk.m3u</code>
|
||||
- 🇨🇬 Republic of the Congo <code>https://iptv-org.github.io/iptv/countries/cg.m3u</code>
|
||||
- 🇷🇪 Réunion <code>https://iptv-org.github.io/iptv/countries/re.m3u</code>
|
||||
- 🇷🇴 Romania <code>https://iptv-org.github.io/iptv/countries/ro.m3u</code>
|
||||
- 🇷🇺 Russia <code>https://iptv-org.github.io/iptv/countries/ru.m3u</code>
|
||||
- 🇷🇼 Rwanda <code>https://iptv-org.github.io/iptv/countries/rw.m3u</code>
|
||||
- 🇧🇱 Saint Barthélemy <code>https://iptv-org.github.io/iptv/countries/bl.m3u</code>
|
||||
- 🇸🇭 Saint Helena <code>https://iptv-org.github.io/iptv/countries/sh.m3u</code>
|
||||
- 🇰🇳 Saint Kitts and Nevis <code>https://iptv-org.github.io/iptv/countries/kn.m3u</code>
|
||||
- 🌐 International <code>https://iptv-org.github.io/iptv/countries/int.m3u</code>
|
||||
- Undefined <code>https://iptv-org.github.io/iptv/countries/undefined.m3u</code>
|
||||
|
||||
#### Regions
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
- Africa <code>https://iptv-org.github.io/iptv/regions/afr.m3u</code>
|
||||
- Americas <code>https://iptv-org.github.io/iptv/regions/amer.m3u</code>
|
||||
- Arab world <code>https://iptv-org.github.io/iptv/regions/arab.m3u</code>
|
||||
- Asia <code>https://iptv-org.github.io/iptv/regions/asia.m3u</code>
|
||||
- Asia-Pacific <code>https://iptv-org.github.io/iptv/regions/apac.m3u</code>
|
||||
- Association of Southeast Asian Nations <code>https://iptv-org.github.io/iptv/regions/asean.m3u</code>
|
||||
- Caribbean <code>https://iptv-org.github.io/iptv/regions/carib.m3u</code>
|
||||
- Central America <code>https://iptv-org.github.io/iptv/regions/cenamer.m3u</code>
|
||||
- Central Asia <code>https://iptv-org.github.io/iptv/regions/cas.m3u</code>
|
||||
- Commonwealth of Independent States <code>https://iptv-org.github.io/iptv/regions/cis.m3u</code>
|
||||
- Europe <code>https://iptv-org.github.io/iptv/regions/eur.m3u</code>
|
||||
- Europe, the Middle East and Africa <code>https://iptv-org.github.io/iptv/regions/emea.m3u</code>
|
||||
- Hispanic America <code>https://iptv-org.github.io/iptv/regions/hispam.m3u</code>
|
||||
- Latin America <code>https://iptv-org.github.io/iptv/regions/latam.m3u</code>
|
||||
- Latin America and the Caribbean <code>https://iptv-org.github.io/iptv/regions/lac.m3u</code>
|
||||
- Maghreb <code>https://iptv-org.github.io/iptv/regions/maghreb.m3u</code>
|
||||
- Middle East <code>https://iptv-org.github.io/iptv/regions/mideast.m3u</code>
|
||||
- Middle East and North Africa <code>https://iptv-org.github.io/iptv/regions/mena.m3u</code>
|
||||
- Nordics <code>https://iptv-org.github.io/iptv/regions/nord.m3u</code>
|
||||
- North America <code>https://iptv-org.github.io/iptv/regions/noram.m3u</code>
|
||||
- Northern America <code>https://iptv-org.github.io/iptv/regions/nam.m3u</code>
|
||||
- Oceania <code>https://iptv-org.github.io/iptv/regions/oce.m3u</code>
|
||||
- South America <code>https://iptv-org.github.io/iptv/regions/southam.m3u</code>
|
||||
- South Asia <code>https://iptv-org.github.io/iptv/regions/sas.m3u</code>
|
||||
- Sub-Saharan Africa <code>https://iptv-org.github.io/iptv/regions/ssa.m3u</code>
|
||||
- West Africa <code>https://iptv-org.github.io/iptv/regions/wafr.m3u</code>
|
||||
|
||||
</details>
|
||||
|
||||
### Grouped by sources
|
||||
|
||||
Playlists in which channels are grouped by broadcast source.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
<br>
|
||||
|
||||
To use the playlist, simply replace `<FILENAME>` in the link below with the name of one of the files in the [streams](streams) folder.
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/sources/<FILENAME>.m3u
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Also, any of our internal playlists are available in raw form (without any filtering or sorting) at this link:
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/raw/<FILENAME>.m3u
|
||||
```
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,14 @@
|
||||
module.exports = {
|
||||
'https://query-streamlink.herokuapp.com/iptv-query?streaming-ip=https://www.twitch.tv/absliveantigua3':
|
||||
{
|
||||
url: 'https://query-streamlink.herokuapp.com/iptv-query?streaming-ip=https://www.twitch.tv/absliveantigua3',
|
||||
http: { referrer: '', 'user-agent': '' },
|
||||
status: { ok: false, code: 'HTTP_NOT_FOUND', message: 'HTTP 404 Not Found' }
|
||||
},
|
||||
'https://tego-cdn2a.sibercdn.com/Live_TV-ABSTV-10/tracks-v3a1/rewind-7200.m3u8?token=e5f61e7be8363eb781b4bdfe591bf917dd529c1a-SjY3NzRTbDZQNnFQVkZaNkZja2RxV3JKc1VBa05zQkdMNStJakRGV0VTTzNrOEVGVUlIQmxta1NLV0o3bzdVdQ-1736094545-1736008145':
|
||||
{
|
||||
url: 'https://tego-cdn2a.sibercdn.com/Live_TV-ABSTV-10/tracks-v3a1/rewind-7200.m3u8?token=e5f61e7be8363eb781b4bdfe591bf917dd529c1a-SjY3NzRTbDZQNnFQVkZaNkZja2RxV3JKc1VBa05zQkdMNStJakRGV0VTTzNrOEVGVUlIQmxta1NLV0o3bzdVdQ-1736094545-1736008145',
|
||||
http: { referrer: '', 'user-agent': '' },
|
||||
status: { ok: false, code: 'HTTP_FORBIDDEN', message: 'HTTP 403 Forbidden' }
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
'https://query-streamlink.herokuapp.com/iptv-query?streaming-ip=https://www.twitch.tv/absliveantigua3':
|
||||
{
|
||||
url: 'https://query-streamlink.herokuapp.com/iptv-query?streaming-ip=https://www.twitch.tv/absliveantigua3',
|
||||
http: { referrer: '', 'user-agent': '' },
|
||||
status: { ok: false, code: 'HTTP_NOT_FOUND', message: 'HTTP 404 Not Found' }
|
||||
},
|
||||
'https://tego-cdn2a.sibercdn.com/Live_TV-ABSTV-10/tracks-v3a1/rewind-7200.m3u8?token=e5f61e7be8363eb781b4bdfe591bf917dd529c1a-SjY3NzRTbDZQNnFQVkZaNkZja2RxV3JKc1VBa05zQkdMNStJakRGV0VTTzNrOEVGVUlIQmxta1NLV0o3bzdVdQ-1736094545-1736008145':
|
||||
{
|
||||
url: 'https://tego-cdn2a.sibercdn.com/Live_TV-ABSTV-10/tracks-v3a1/rewind-7200.m3u8?token=e5f61e7be8363eb781b4bdfe591bf917dd529c1a-SjY3NzRTbDZQNnFQVkZaNkZja2RxV3JKc1VBa05zQkdMNStJakRGV0VTTzNrOEVGVUlIQmxta1NLV0o3bzdVdQ-1736094545-1736008145',
|
||||
http: { referrer: '', 'user-agent': '' },
|
||||
status: { ok: false, code: 'HTTP_FORBIDDEN', message: 'HTTP 403 Forbidden' }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { execSync } from 'child_process'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
const ENV_VAR =
|
||||
'cross-env DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/input/api_generate API_DIR=tests/__data__/output/.api'
|
||||
|
||||
beforeEach(() => {
|
||||
fs.emptyDirSync('tests/__data__/output')
|
||||
})
|
||||
|
||||
describe('api:generate', () => {
|
||||
it('can create streams.json', () => {
|
||||
const cmd = `${ENV_VAR} npm run api:generate`
|
||||
const stdout = execSync(cmd, { encoding: 'utf8' })
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, stdout)
|
||||
|
||||
expect(content('tests/__data__/output/.api/streams.json')).toMatchObject(
|
||||
content('tests/__data__/expected/api_generate/.api/streams.json')
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
function content(filepath: string) {
|
||||
return JSON.parse(fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' }))
|
||||
}
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { execSync } from 'child_process'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
const ENV_VAR =
|
||||
'cross-env DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/input/api_generate API_DIR=tests/__data__/output/.api'
|
||||
|
||||
beforeEach(() => {
|
||||
fs.emptyDirSync('tests/__data__/output')
|
||||
})
|
||||
|
||||
describe('api:generate', () => {
|
||||
it('can create streams.json', () => {
|
||||
const cmd = `${ENV_VAR} npm run api:generate`
|
||||
const stdout = execSync(cmd, { encoding: 'utf8' })
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, stdout)
|
||||
|
||||
expect(content('tests/__data__/output/.api/streams.json')).toMatchObject(
|
||||
content('tests/__data__/expected/api_generate/.api/streams.json')
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
function content(filepath: string) {
|
||||
return JSON.parse(fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' }))
|
||||
}
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
import { execSync } from 'child_process'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
type ExecError = {
|
||||
status: number
|
||||
stdout: string
|
||||
}
|
||||
|
||||
const ENV_VAR = 'cross-env DATA_DIR=tests/__data__/input/data'
|
||||
|
||||
beforeEach(() => {
|
||||
fs.emptyDirSync('tests/__data__/output')
|
||||
fs.copySync(
|
||||
'tests/__data__/input/playlist_edit/playlist.m3u',
|
||||
'tests/__data__/output/playlist.m3u'
|
||||
)
|
||||
})
|
||||
|
||||
describe('playlist:edit', () => {
|
||||
it('shows list of options for a streams', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:edit --- tests/__data__/output/playlist.m3u`
|
||||
try {
|
||||
const stdout = execSync(cmd, { encoding: 'utf8' })
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, stdout)
|
||||
checkStdout(stdout)
|
||||
} catch (error) {
|
||||
// NOTE: for Windows only
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, error)
|
||||
checkStdout((error as ExecError).stdout)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
function checkStdout(stdout: string) {
|
||||
expect(stdout).toContain('TF1.fr (TF1, Télévision française 1)')
|
||||
expect(stdout).toContain('Type...')
|
||||
expect(stdout).toContain('Skip')
|
||||
}
|
||||
import { execSync } from 'child_process'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
type ExecError = {
|
||||
status: number
|
||||
stdout: string
|
||||
}
|
||||
|
||||
const ENV_VAR = 'cross-env DATA_DIR=tests/__data__/input/data'
|
||||
|
||||
beforeEach(() => {
|
||||
fs.emptyDirSync('tests/__data__/output')
|
||||
fs.copySync(
|
||||
'tests/__data__/input/playlist_edit/playlist.m3u',
|
||||
'tests/__data__/output/playlist.m3u'
|
||||
)
|
||||
})
|
||||
|
||||
describe('playlist:edit', () => {
|
||||
it('shows list of options for a streams', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:edit --- tests/__data__/output/playlist.m3u`
|
||||
try {
|
||||
const stdout = execSync(cmd, { encoding: 'utf8' })
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, stdout)
|
||||
checkStdout(stdout)
|
||||
} catch (error) {
|
||||
// NOTE: for Windows only
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, error)
|
||||
checkStdout((error as ExecError).stdout)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
function checkStdout(stdout: string) {
|
||||
expect(stdout).toContain('TF1.fr (TF1, Télévision française 1)')
|
||||
expect(stdout).toContain('Type...')
|
||||
expect(stdout).toContain('Skip')
|
||||
}
|
||||
|
||||
@@ -1,36 +1,37 @@
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { execSync } from 'child_process'
|
||||
import * as fs from 'fs-extra'
|
||||
import { glob } from 'glob'
|
||||
|
||||
const ENV_VAR = 'cross-env STREAMS_DIR=tests/__data__/output/streams DATA_DIR=tests/__data__/input/data'
|
||||
|
||||
beforeEach(() => {
|
||||
fs.emptyDirSync('tests/__data__/output')
|
||||
fs.copySync('tests/__data__/input/playlist_format', 'tests/__data__/output/streams')
|
||||
})
|
||||
|
||||
describe('playlist:format', () => {
|
||||
it('can format playlists', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:format`
|
||||
const stdout = execSync(cmd, { encoding: 'utf8' })
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, stdout)
|
||||
|
||||
const files = glob.sync('tests/__data__/expected/playlist_format/*.m3u').map(filepath => {
|
||||
const fileUrl = pathToFileURL(filepath).toString()
|
||||
const pathToRemove = pathToFileURL('tests/__data__/expected/playlist_format/').toString()
|
||||
|
||||
return fileUrl.replace(pathToRemove, '')
|
||||
})
|
||||
|
||||
files.forEach(filepath => {
|
||||
expect(content(`tests/__data__/output/streams/${filepath}`)).toBe(
|
||||
content(`tests/__data__/expected/playlist_format/${filepath}`)
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function content(filepath: string) {
|
||||
return fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' })
|
||||
}
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { execSync } from 'child_process'
|
||||
import * as fs from 'fs-extra'
|
||||
import { glob } from 'glob'
|
||||
|
||||
const ENV_VAR =
|
||||
'cross-env STREAMS_DIR=tests/__data__/output/streams DATA_DIR=tests/__data__/input/data'
|
||||
|
||||
beforeEach(() => {
|
||||
fs.emptyDirSync('tests/__data__/output')
|
||||
fs.copySync('tests/__data__/input/playlist_format', 'tests/__data__/output/streams')
|
||||
})
|
||||
|
||||
describe('playlist:format', () => {
|
||||
it('can format playlists', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:format`
|
||||
const stdout = execSync(cmd, { encoding: 'utf8' })
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, stdout)
|
||||
|
||||
const files = glob.sync('tests/__data__/expected/playlist_format/*.m3u').map(filepath => {
|
||||
const fileUrl = pathToFileURL(filepath).toString()
|
||||
const pathToRemove = pathToFileURL('tests/__data__/expected/playlist_format/').toString()
|
||||
|
||||
return fileUrl.replace(pathToRemove, '')
|
||||
})
|
||||
|
||||
files.forEach(filepath => {
|
||||
expect(content(`tests/__data__/output/streams/${filepath}`)).toBe(
|
||||
content(`tests/__data__/expected/playlist_format/${filepath}`)
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function content(filepath: string) {
|
||||
return fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' })
|
||||
}
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { execSync } from 'child_process'
|
||||
import { EOL } from 'node:os'
|
||||
import * as fs from 'fs-extra'
|
||||
import * as glob from 'glob'
|
||||
|
||||
const ENV_VAR =
|
||||
'cross-env STREAMS_DIR=tests/__data__/input/playlist_generate DATA_DIR=tests/__data__/input/data PUBLIC_DIR=tests/__data__/output/.gh-pages LOGS_DIR=tests/__data__/output/logs'
|
||||
|
||||
beforeEach(() => {
|
||||
fs.emptyDirSync('tests/__data__/output')
|
||||
})
|
||||
|
||||
describe('playlist:generate', () => {
|
||||
it('can generate playlists and logs', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:generate`
|
||||
const stdout = execSync(cmd, { encoding: 'utf8' })
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, stdout)
|
||||
|
||||
const playlists = glob
|
||||
.sync('tests/__data__/expected/playlist_generate/.gh-pages/**/*.m3u')
|
||||
.map(filepath => {
|
||||
const fileUrl = pathToFileURL(filepath).toString()
|
||||
const pathToRemove = pathToFileURL('tests/__data__/expected/playlist_generate/').toString()
|
||||
|
||||
return fileUrl.replace(pathToRemove, '')
|
||||
})
|
||||
|
||||
playlists.forEach((filepath: string) => {
|
||||
expect(content(`tests/__data__/output/${filepath}`), filepath).toBe(
|
||||
content(`tests/__data__/expected/playlist_generate/${filepath}`)
|
||||
)
|
||||
})
|
||||
|
||||
expect(content('tests/__data__/output/logs/generators.log').split(EOL).sort()).toStrictEqual(
|
||||
content('tests/__data__/expected/playlist_generate/logs/generators.log').split(EOL).sort()
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
function content(filepath: string) {
|
||||
return fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' })
|
||||
}
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { execSync } from 'child_process'
|
||||
import { EOL } from 'node:os'
|
||||
import * as fs from 'fs-extra'
|
||||
import * as glob from 'glob'
|
||||
|
||||
const ENV_VAR =
|
||||
'cross-env STREAMS_DIR=tests/__data__/input/playlist_generate DATA_DIR=tests/__data__/input/data PUBLIC_DIR=tests/__data__/output/.gh-pages LOGS_DIR=tests/__data__/output/logs'
|
||||
|
||||
beforeEach(() => {
|
||||
fs.emptyDirSync('tests/__data__/output')
|
||||
})
|
||||
|
||||
describe('playlist:generate', () => {
|
||||
it('can generate playlists and logs', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:generate`
|
||||
const stdout = execSync(cmd, { encoding: 'utf8' })
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, stdout)
|
||||
|
||||
const playlists = glob
|
||||
.sync('tests/__data__/expected/playlist_generate/.gh-pages/**/*.m3u')
|
||||
.map(filepath => {
|
||||
const fileUrl = pathToFileURL(filepath).toString()
|
||||
const pathToRemove = pathToFileURL('tests/__data__/expected/playlist_generate/').toString()
|
||||
|
||||
return fileUrl.replace(pathToRemove, '')
|
||||
})
|
||||
|
||||
playlists.forEach((filepath: string) => {
|
||||
expect(content(`tests/__data__/output/${filepath}`), filepath).toBe(
|
||||
content(`tests/__data__/expected/playlist_generate/${filepath}`)
|
||||
)
|
||||
})
|
||||
|
||||
expect(content('tests/__data__/output/logs/generators.log').split(EOL).sort()).toStrictEqual(
|
||||
content('tests/__data__/expected/playlist_generate/logs/generators.log').split(EOL).sort()
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
function content(filepath: string) {
|
||||
return fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' })
|
||||
}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { execSync } from 'child_process'
|
||||
|
||||
type ExecError = {
|
||||
status: number
|
||||
stdout: string
|
||||
}
|
||||
|
||||
const ENV_VAR = 'cross-env ROOT_DIR=tests/__data__/input DATA_DIR=tests/__data__/input/data'
|
||||
|
||||
describe('playlist:test', () => {
|
||||
it('shows an error if the playlist contains a broken link', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:test playlist_test/ag.m3u`
|
||||
try {
|
||||
execSync(cmd, { encoding: 'utf8' })
|
||||
} catch (error) {
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, error)
|
||||
expect((error as ExecError).stdout).toContain('playlist_test/ag.m3u')
|
||||
expect((error as ExecError).stdout).toContain('2 problems (1 errors, 1 warnings)')
|
||||
}
|
||||
})
|
||||
})
|
||||
import { execSync } from 'child_process'
|
||||
|
||||
type ExecError = {
|
||||
status: number
|
||||
stdout: string
|
||||
}
|
||||
|
||||
const ENV_VAR = 'cross-env ROOT_DIR=tests/__data__/input DATA_DIR=tests/__data__/input/data'
|
||||
|
||||
describe('playlist:test', () => {
|
||||
it('shows an error if the playlist contains a broken link', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:test playlist_test/ag.m3u`
|
||||
try {
|
||||
execSync(cmd, { encoding: 'utf8' })
|
||||
} catch (error) {
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, error)
|
||||
expect((error as ExecError).stdout).toContain('playlist_test/ag.m3u')
|
||||
expect((error as ExecError).stdout).toContain('2 problems (1 errors, 1 warnings)')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,44 +1,45 @@
|
||||
import { execSync } from 'child_process'
|
||||
|
||||
type ExecError = {
|
||||
status: number
|
||||
stdout: string
|
||||
}
|
||||
|
||||
const ENV_VAR = 'cross-env DATA_DIR=tests/__data__/input/data ROOT_DIR=tests/__data__/input/playlist_validate'
|
||||
|
||||
describe('playlist:validate', () => {
|
||||
it('show an error if channel id in the blocklist', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:validate -- us_blocked.m3u`
|
||||
try {
|
||||
execSync(cmd, { encoding: 'utf8' })
|
||||
} catch (error) {
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, error)
|
||||
expect((error as ExecError).stdout).toContain('us_blocked.m3u')
|
||||
expect((error as ExecError).stdout).toContain(
|
||||
'2 error "FoxSports2.us" is on the blocklist due to claims of copyright holders (https://github.com/iptv-org/iptv/issues/0002)'
|
||||
)
|
||||
expect((error as ExecError).stdout).toContain(
|
||||
'4 error "TVN.pl" is on the blocklist due to NSFW content (https://github.com/iptv-org/iptv/issues/0003)'
|
||||
)
|
||||
expect((error as ExecError).stdout).toContain('2 problems (2 errors, 0 warnings)')
|
||||
}
|
||||
})
|
||||
|
||||
it('show a warning if channel has wrong id', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:validate -- wrong_id.m3u`
|
||||
try {
|
||||
execSync(cmd, { encoding: 'utf8' })
|
||||
} catch (error) {
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, error)
|
||||
expect((error as ExecError).stdout).toContain(
|
||||
'wrong_id.m3u\n 2 warning "qib22lAq1L.us" is not in the database\n\n1 problems (0 errors, 1 warnings)\n'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('skip the file if it does not exist', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:validate -- missing.m3u`
|
||||
execSync(cmd, { encoding: 'utf8' })
|
||||
})
|
||||
})
|
||||
import { execSync } from 'child_process'
|
||||
|
||||
type ExecError = {
|
||||
status: number
|
||||
stdout: string
|
||||
}
|
||||
|
||||
const ENV_VAR =
|
||||
'cross-env DATA_DIR=tests/__data__/input/data ROOT_DIR=tests/__data__/input/playlist_validate'
|
||||
|
||||
describe('playlist:validate', () => {
|
||||
it('show an error if channel id in the blocklist', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:validate -- us_blocked.m3u`
|
||||
try {
|
||||
execSync(cmd, { encoding: 'utf8' })
|
||||
} catch (error) {
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, error)
|
||||
expect((error as ExecError).stdout).toContain('us_blocked.m3u')
|
||||
expect((error as ExecError).stdout).toContain(
|
||||
'2 error "FoxSports2.us" is on the blocklist due to claims of copyright holders (https://github.com/iptv-org/iptv/issues/0002)'
|
||||
)
|
||||
expect((error as ExecError).stdout).toContain(
|
||||
'4 error "TVN.pl" is on the blocklist due to NSFW content (https://github.com/iptv-org/iptv/issues/0003)'
|
||||
)
|
||||
expect((error as ExecError).stdout).toContain('2 problems (2 errors, 0 warnings)')
|
||||
}
|
||||
})
|
||||
|
||||
it('show a warning if channel has wrong id', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:validate -- wrong_id.m3u`
|
||||
try {
|
||||
execSync(cmd, { encoding: 'utf8' })
|
||||
} catch (error) {
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, error)
|
||||
expect((error as ExecError).stdout).toContain(
|
||||
'wrong_id.m3u\n 2 warning "qib22lAq1L.us" is not in the database\n\n1 problems (0 errors, 1 warnings)\n'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('skip the file if it does not exist', () => {
|
||||
const cmd = `${ENV_VAR} npm run playlist:validate -- missing.m3u`
|
||||
execSync(cmd, { encoding: 'utf8' })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { execSync } from 'child_process'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
const ENV_VAR =
|
||||
'cross-env DATA_DIR=tests/__data__/input/data LOGS_DIR=tests/__data__/input/readme_update ROOT_DIR=tests/__data__/output'
|
||||
|
||||
beforeEach(() => {
|
||||
fs.emptyDirSync('tests/__data__/output')
|
||||
})
|
||||
|
||||
describe('readme:update', () => {
|
||||
it('can update readme.md', () => {
|
||||
const cmd = `${ENV_VAR} npm run readme:update`
|
||||
const stdout = execSync(cmd, { encoding: 'utf8' })
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, stdout)
|
||||
|
||||
expect(content('tests/__data__/output/PLAYLISTS.md')).toEqual(
|
||||
content('tests/__data__/expected/readme_update/playlists.md')
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
function content(filepath: string) {
|
||||
return JSON.stringify(fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' }))
|
||||
}
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { execSync } from 'child_process'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
const ENV_VAR =
|
||||
'cross-env DATA_DIR=tests/__data__/input/data LOGS_DIR=tests/__data__/input/readme_update ROOT_DIR=tests/__data__/output'
|
||||
|
||||
beforeEach(() => {
|
||||
fs.emptyDirSync('tests/__data__/output')
|
||||
})
|
||||
|
||||
describe('readme:update', () => {
|
||||
it('can update readme.md', () => {
|
||||
const cmd = `${ENV_VAR} npm run readme:update`
|
||||
const stdout = execSync(cmd, { encoding: 'utf8' })
|
||||
if (process.env.DEBUG === 'true') console.log(cmd, stdout)
|
||||
|
||||
expect(content('tests/__data__/output/PLAYLISTS.md')).toEqual(
|
||||
content('tests/__data__/expected/readme_update/playlists.md')
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
function content(filepath: string) {
|
||||
return JSON.stringify(fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' }))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user