Merge branch 'master' into Carlinhos027-patch-2

This commit is contained in:
Aleksandr Statciuk 2025-04-16 03:16:44 +03:00 committed by GitHub
commit c99694aa7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
225 changed files with 4063 additions and 3092 deletions

View file

@ -6,9 +6,9 @@ labels: ['streams:add']
body: body:
- type: input - type: input
attributes: attributes:
label: Channel ID (required) label: Stream ID (required)
description: Unique channel ID from [iptv-org.github.io](https://iptv-org.github.io/). If you can't find the channel you want in the list, please let us know through this [form](https://github.com/iptv-org/database/issues/new?assignees=&labels=channels%3Aadd&projects=&template=channels_add.yml&title=Add%3A+) before posting your request. description: "ID of the stream consisting of `<channel_id>` or `<channel_id>@<feed_id>`. Full list of supported channels with corresponding ID could be found on [iptv-org.github.io](https://iptv-org.github.io/). If you can't find the channel you want in the list, please let us know through this [form](https://github.com/iptv-org/database/issues/new?assignees=&labels=channels%3Aadd&projects=&template=channels_add.yml&title=Add%3A+) before posting your request."
placeholder: 'BBCAmericaEast.us' placeholder: 'BBCAmerica.us@East'
validations: validations:
required: true required: true
@ -28,9 +28,12 @@ body:
- 2160p - 2160p
- 1280p - 1280p
- 1080p - 1080p
- 1080i
- 720p - 720p
- 576p - 576p
- 576i
- 480p - 480p
- 480i
- 360p - 360p
- type: dropdown - type: dropdown

View file

@ -19,9 +19,9 @@ body:
- type: input - type: input
attributes: attributes:
label: Channel ID label: Stream ID
description: Channel ID from [iptv-org.github.io](https://iptv-org.github.io/). description: "ID of the stream consisting of `<channel_id>` or `<channel_id>@<feed_id>`. Full list of supported channels with corresponding ID could be found on [iptv-org.github.io](https://iptv-org.github.io/). If you can't find the channel you want in the list, please let us know through this [form](https://github.com/iptv-org/database/issues/new?assignees=&labels=channels%3Aadd&projects=&template=channels_add.yml&title=Add%3A+) before posting your request."
placeholder: 'BBCAmericaEast.us' placeholder: 'BBCAmerica.us@East'
- type: dropdown - type: dropdown
attributes: attributes:
@ -31,9 +31,12 @@ body:
- 2160p - 2160p
- 1280p - 1280p
- 1080p - 1080p
- 1080i
- 720p - 720p
- 576p - 576p
- 576i
- 480p - 480p
- 480i
- 360p - 360p
- '~' - '~'

View file

@ -1,7 +1,7 @@
name: 🚧 Report broken stream name: 🚧 Report broken stream
description: Report a broken or unstable stream description: Report a broken or unstable stream
title: 'Broken: ' title: 'Broken: '
labels: ['broken stream'] labels: ['broken stream', 'streams:remove']
body: body:
- type: markdown - type: markdown

View file

@ -22,7 +22,7 @@
| News | Programming is mostly news | | News | Programming is mostly news |
| Outdoor | Programming related to outdoor activities like fishing, hunting, etc. | | Outdoor | Programming related to outdoor activities like fishing, hunting, etc. |
| Relax | Programming is calm sounding and beautiful views | | Relax | Programming is calm sounding and beautiful views |
| Religious | Religious Programming | | Religious | Religious programming |
| Science | Science and Technology | | Science | Science and Technology |
| Series | Channels that only show series | | Series | Channels that only show series |
| Shop | Programming is for shopping | | Shop | Programming is for shopping |

View file

@ -1,30 +0,0 @@
## Supported Regions
| Code | Description |
| ------------------------------------------------------------------------ | -------------------------------------- |
| [AFR](https://en.wikipedia.org/wiki/Africa) | Africa |
| [AMER](https://en.wikipedia.org/wiki/Americas) | Americas |
| [APAC](https://en.wikipedia.org/wiki/Asia-Pacific) | Asia-Pacific |
| [ARAB](https://en.wikipedia.org/wiki/Arab_world) | Arab world |
| [ASEAN](https://en.wikipedia.org/wiki/ASEAN) | Association of Southeast Asian Nations |
| [ASIA](https://en.wikipedia.org/wiki/Asia) | Asia |
| [CARIB](https://en.wikipedia.org/wiki/Caribbean) | Caribbean |
| [CAS](https://en.wikipedia.org/wiki/Central_Asia) | Central Asia |
| [CENAMER](https://en.wikipedia.org/wiki/Central_America) | Central America |
| [CIS](https://en.wikipedia.org/wiki/Commonwealth_of_Independent_States) | Commonwealth of Independent States |
| [EMEA](https://en.wikipedia.org/wiki/Europe,_the_Middle_East_and_Africa) | Europe, the Middle East and Africa |
| [EUR](https://en.wikipedia.org/wiki/Europe) | Europe |
| [HISPAM](https://en.wikipedia.org/wiki/Hispanic_America) | Hispanic America |
| [LAC](https://en.wikipedia.org/wiki/Latin_America_and_the_Caribbean) | Latin America and the Caribbean |
| [LATAM](https://en.wikipedia.org/wiki/Latin_America) | Latin America |
| [MAGHREB](https://en.wikipedia.org/wiki/Maghreb) | Maghreb |
| [MENA](https://en.wikipedia.org/wiki/MENA) | Middle East and North Africa |
| [MIDEAST](https://en.wikipedia.org/wiki/Middle_East) | Middle East |
| [NAM](https://en.wikipedia.org/wiki/Northern_America) | Northern America |
| [NORAM](https://en.wikipedia.org/wiki/North_America) | North America |
| [NORD](https://en.wikipedia.org/wiki/Nordic_countries) | Nordics |
| [OCE](https://en.wikipedia.org/wiki/Oceania) | Oceania |
| [SAS](https://en.wikipedia.org/wiki/South_Asia) | South Asia |
| [SSA](https://en.wikipedia.org/wiki/Sub-Saharan_Africa) | Sub-Saharan Africa |
| [WAFR](https://en.wikipedia.org/wiki/West_Africa) | West Africa |
| [INT](https://en.wikipedia.org/wiki/West_Africa) | Worldwide |

View file

@ -36,12 +36,12 @@ https://iptv-org.github.io/iptv/index.m3u
### Grouped by category ### Grouped by category
Playlists in which channels are grouped by category. A list of all supported categories with descriptions can be found [here](.readme/supported-categories.md).
<details> <details>
<summary>Expand</summary> <summary>Expand</summary>
<br> <br>
Playlist in which each channel has its _category_ as a group title:
``` ```
https://iptv-org.github.io/iptv/index.category.m3u https://iptv-org.github.io/iptv/index.category.m3u
``` ```
@ -55,12 +55,12 @@ Same thing, but split up into separate files:
### Grouped by language ### Grouped by language
Playlists in which channels are grouped by the language in which they are broadcast.
<details> <details>
<summary>Expand</summary> <summary>Expand</summary>
<br> <br>
Playlist in which each channel has its _language_ as a group title:
``` ```
https://iptv-org.github.io/iptv/index.language.m3u https://iptv-org.github.io/iptv/index.language.m3u
``` ```
@ -74,12 +74,12 @@ Same thing, but split up into separate files:
### Grouped by country ### Grouped by country
Playlists in which channels are grouped by country for which they are broadcasted.
<details> <details>
<summary>Expand</summary> <summary>Expand</summary>
<br> <br>
Playlist in which each channel has its _country_ as a group title:
``` ```
https://iptv-org.github.io/iptv/index.country.m3u https://iptv-org.github.io/iptv/index.country.m3u
``` ```
@ -97,7 +97,7 @@ Same thing, but split up into separate files:
<summary>Expand</summary> <summary>Expand</summary>
<br> <br>
Playlist in which each channel has its _region_ as a group title: Playlists in which channels are grouped by the region for which they are broadcasted.
``` ```
https://iptv-org.github.io/iptv/index.region.m3u https://iptv-org.github.io/iptv/index.region.m3u

View file

@ -20,15 +20,23 @@ Regardless of which option you choose, before posting your request please do the
- Make sure the link you want to add works stably. To check this, open it in one of the players (for example, [VLC player](https://www.videolan.org/vlc/index.html)) and watch the broadcast for at least a minute (some test streams are interrupted after 15-30 seconds). - Make sure the link you want to add works stably. To check this, open it in one of the players (for example, [VLC player](https://www.videolan.org/vlc/index.html)) and watch the broadcast for at least a minute (some test streams are interrupted after 15-30 seconds).
- Make sure the link is not already in the playlist. This can be done by [searching](https://github.com/search?q=repo%3Aiptv-org%2Fiptv+http%3A%2F%2Fexample.com&type=code) the repository. - Make sure the link is not already in the playlist. This can be done by [searching](https://github.com/search?q=repo%3Aiptv-org%2Fiptv+http%3A%2F%2Fexample.com&type=code) the repository.
- Find the ID of the channel you want to add in our [database](https://iptv-org.github.io/). If this particular channel is not in the database, then leave a request to add it [here](https://github.com/iptv-org/database/issues/new/choose) and wait until it is approved before continuing. - Find the ID of the channel you want on [iptv-org.github.io](https://iptv-org.github.io/). If your desired channel is not on the list you can leave a request to add it [here](https://github.com/iptv-org/database/issues/new/choose).
- Make sure the channel is not blocklisted. This can be done by checking the [blocklist.csv](https://github.com/iptv-org/database/blob/master/data/blocklist.csv) file. - Make sure the channel is not blocklisted. It can also be done through [iptv-org.github.io](https://iptv-org.github.io/).
- The link does not lead to the Xtream Codes server. [Why don't you accept links to Xtream Codes server?](FAQ.md#why-dont-you-accept-links-to-xtream-codes-server) - The link does not lead to the Xtream Codes server. [Why don't you accept links to Xtream Codes server?](FAQ.md#why-dont-you-accept-links-to-xtream-codes-server)
- If you know that the broadcast only works in certain countries or it is periodically interrupted, do not forget to indicate this in the request. - If you know that the broadcast only works in certain countries or it is periodically interrupted, do not forget to indicate this in the request.
A requests without a valid channel ID or working link to the stream will be closed immediately. A requests without a valid stream ID or working link to the stream will be closed immediately.
Note all links in playlists are sorted automatically by scripts so there is no need to sort them manually. For more info, see [Scripts](#scripts). Note all links in playlists are sorted automatically by scripts so there is no need to sort them manually. For more info, see [Scripts](#scripts).
### How to fix the stream description?
Most of the stream description (channel name, categories, languages, broadcast area, logo) we load from the [iptv-org/database](https://github.com/iptv-org/database) using the stream ID.
So first of all, make sure that the desired stream has the correct ID. A full list of all supported channels and their corresponding IDs can be found on [iptv-org.github.io](https://iptv-org.github.io/). To change the stream ID of any link in the playlist, just fill out this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=streams%3Aedit&projects=&template=2_streams_edit.yml&title=Edit%3A+).
If, however, you have found an error in the database itself, this is the place to go: [How to edit channel description?](https://github.com/iptv-org/database/blob/master/CONTRIBUTING.md#how-to-edit-channel-description)
### How to distinguish a link to an Xtream Codes server from a regular one? ### How to distinguish a link to an Xtream Codes server from a regular one?
Most of them have this form: Most of them have this form:
@ -52,6 +60,37 @@ The only thing before publishing your report is to make sure that:
An issue without a valid link will be closed immediately. An issue without a valid link will be closed immediately.
### How to find a broken stream?
For starters, you can just try to open the playlist in [VLC player](https://www.videolan.org/vlc/). The player outputs all errors to the log (Tools -> Messages) so you'll be able to determine pretty accurately why a link isn't working.
Another way to test links is to use the NPM script. To do this, first make sure you have [Node.js](https://nodejs.org/en) installed on your system. Then go to the `iptv` folder using [Console](https://en.wikipedia.org/wiki/Windows_Console) (or [Terminal](<https://en.wikipedia.org/wiki/Terminal_(macOS)>) if you have macOS) and run the command:
```sh
npm run playlist:test path/to/playlist.m3u
```
This command will run an automatic check of all links in the playlist and display their status:
```sh
npm run playlist:test streams/fr.m3u
streams/fr.m3u
┌─────┬───────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────┬───────────────────────────┐
│ │ tvg-id │ url │ status │
├─────┼───────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────────────────┤
│ 0 │ 6ter.fr │ https://origin-caf900c010ea8046.live.6cloud.fr/out/v1/29c7a579af3348b48230f76cd75699a5/dash_short... │ LOADING... │
│ 1 │ 20MinutesTV.fr │ https://lives.digiteka.com/stream/86d3e867-a272-496b-8412-f59aa0104771/index.m3u8 │ FFMPEG_STREAMS_NOT_FOUND │
│ 2 │ │ https://video1.getstreamhosting.com:1936/8420/8420/playlist.m3u8 │ OK │
│ 3 │ ADNTVPlus.fr │ https://samsunguk-adn-samsung-fre-qfrlc.amagi.tv/playlist/samsunguk-adn-samsung-fre/playlist.m3u8 │ HTTP_FORBIDDEN │
│ 4 │ Africa24.fr │ https://edge12.vedge.infomaniak.com/livecast/ik:africa24/manifest.m3u8 │ OK │
│ 5 │ Africa24English.fr │ https://edge17.vedge.infomaniak.com/livecast/ik:africa24sport/manifest.m3u8 │ OK │
│ 6 │ AfricanewsEnglish.fr │ https://37c774660687468c821a51190046facf.mediatailor.us-east-1.amazonaws.com/v1/master/04fd913bb2... │ HTTP_GATEWAY_TIMEOUT │
│ 7 │ AlpedHuezTV.fr │ https://edge.vedge.infomaniak.com/livecast/ik:adhtv/chunklist.m3u8 │ HTTP_NOT_FOUND │
```
After that, all you have to do is report any broken streams you find.
### How do I remove my channel from playlist? ### How do I remove my channel from playlist?
To request removal of a link to a channel from the repository, you need to fill out this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=removal+request&projects=&template=-removal-request.yml&title=Remove%3A+) and wait for the request to be reviewed (this usually takes no more than 1 business day). And if the request is approved, links to the channel will be immediately removed from the repository. To request removal of a link to a channel from the repository, you need to fill out this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=removal+request&projects=&template=-removal-request.yml&title=Remove%3A+) and wait for the request to be reviewed (this usually takes no more than 1 business day). And if the request is approved, links to the channel will be immediately removed from the repository.
@ -65,22 +104,22 @@ Please note that we only accept removal requests from channel owners and their o
For a stream to be approved, its description must follow this template: For a stream to be approved, its description must follow this template:
``` ```
#EXTINF:-1 tvg-id="CHANNEL_ID",CHANNEL_NAME (RESOLUTION) [LABEL] #EXTINF:-1 tvg-id="STREAM_ID",CHANNEL_NAME (QUALITY) [LABEL]
STREAM_URL STREAM_URL
``` ```
| Attribute | Description | Required | Valid values | | Attribute | Description | Required | Valid values |
| -------------- | ------------------------------------------------------------------------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------- | | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------------- |
| `CHANNEL_ID` | Channel ID. | Optional | Full list of supported channels with corresponding ID could be found on [iptv-org.github.io](https://iptv-org.github.io/). | | `STREAM_ID` | ID of the stream. Full list of supported channels with corresponding ID could be found on [iptv-org.github.io](https://iptv-org.github.io/). | Optional | `<channel_id>` or `<channel_id>@<feed_id>` |
| `CHANNEL_NAME` | Full name of the channel. May contain any characters except: `,`, `[`, `]`. | Required | - | | `CHANNEL_NAME` | Full name of the channel. May contain any characters except: `,`, `[`, `]`. | Required | - |
| `RESOLUTION` | Maximum stream resolution. | Optional | `2160p`, `1080p`, `720p`, `480p`, `360p` etc | | `QUALITY` | Maximum stream quality. | Optional | `2160p`, `1080p`, `720p`, `480p`, `360p` etc |
| `LABEL` | Specified in cases where the broadcast for some reason may not be available to some users. | Optional | `Geo-blocked` or `Not 24/7` | | `LABEL` | Specified in cases where the broadcast for some reason may not be available to some users. | Optional | `Geo-blocked` or `Not 24/7` |
| `STREAM_URL` | Stream URL. | Required | - | | `STREAM_URL` | Stream URL. | Required | - |
Example: Example:
```xml ```xml
#EXTINF:-1 tvg-id="ExampleTV.ua",Example TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="ExampleTV.ua@HD",Example TV (720p) [Not 24/7]
https://example.com/playlist.m3u8 https://example.com/playlist.m3u8
``` ```
@ -110,7 +149,6 @@ http://example.com/stream.m3u8
- `config.json`: config for the `markdown-include` package, which is used to compile everything into one `README.md` file. - `config.json`: config for the `markdown-include` package, which is used to compile everything into one `README.md` file.
- `preview.png`: image displayed in the `README.md`. - `preview.png`: image displayed in the `README.md`.
- `supported-categories.md`: list of supported categories. - `supported-categories.md`: list of supported categories.
- `supported-regions.md`: list of supported regions.
- `template.md`: template for `README.md`. - `template.md`: template for `README.md`.
- `scripts/`: contains all scripts used in the repository. - `scripts/`: contains all scripts used in the repository.
- `streams/`: contains all streams broken down by the country from which they are broadcast. - `streams/`: contains all streams broken down by the country from which they are broadcast.

696
README.md

File diff suppressed because it is too large Load diff

30
package-lock.json generated
View file

@ -10,7 +10,7 @@
"dependencies": { "dependencies": {
"@eslint/eslintrc": "^3.3.0", "@eslint/eslintrc": "^3.3.0",
"@eslint/js": "^9.21.0", "@eslint/js": "^9.21.0",
"@freearhey/core": "^0.2.1", "@freearhey/core": "^0.7.0",
"@octokit/core": "^6.1.4", "@octokit/core": "^6.1.4",
"@octokit/plugin-paginate-rest": "^11.4.3", "@octokit/plugin-paginate-rest": "^11.4.3",
"@octokit/plugin-rest-endpoint-methods": "^7.1.3", "@octokit/plugin-rest-endpoint-methods": "^7.1.3",
@ -1063,9 +1063,9 @@
} }
}, },
"node_modules/@freearhey/core": { "node_modules/@freearhey/core": {
"version": "0.2.1", "version": "0.7.0",
"resolved": "https://registry.npmjs.org/@freearhey/core/-/core-0.2.1.tgz", "resolved": "https://registry.npmjs.org/@freearhey/core/-/core-0.7.0.tgz",
"integrity": "sha512-kEdIxZClykKhGpgyCSlkwuVuSCCAWr3J5YvOUMJQDPgVAYvT5VbD8MYKPm+OwNi9T4HFmF6qqY90qwKJPoOXCA==", "integrity": "sha512-HXkKPYGY7ife7JAc1q/Qxzy0WUdSnyt3rHThCShZHgnH3rz0tpkjHFW7LNegB3he0IKn/Zc95/YSOQ97Fq8ctA==",
"dependencies": { "dependencies": {
"@types/fs-extra": "^11.0.2", "@types/fs-extra": "^11.0.2",
"@types/lodash": "^4.14.198", "@types/lodash": "^4.14.198",
@ -1078,6 +1078,7 @@
"node-gzip": "^1.1.2", "node-gzip": "^1.1.2",
"normalize-url": "^6.1.0", "normalize-url": "^6.1.0",
"object-treeify": "^2.1.1", "object-treeify": "^2.1.1",
"run-script-os": "^1.1.6",
"signale": "^1.4.0" "signale": "^1.4.0"
} }
}, },
@ -6059,6 +6060,15 @@
"queue-microtask": "^1.2.2" "queue-microtask": "^1.2.2"
} }
}, },
"node_modules/run-script-os": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/run-script-os/-/run-script-os-1.1.6.tgz",
"integrity": "sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw==",
"bin": {
"run-os": "index.js",
"run-script-os": "index.js"
}
},
"node_modules/semver": { "node_modules/semver": {
"version": "7.6.3", "version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
@ -7455,9 +7465,9 @@
} }
}, },
"@freearhey/core": { "@freearhey/core": {
"version": "0.2.1", "version": "0.7.0",
"resolved": "https://registry.npmjs.org/@freearhey/core/-/core-0.2.1.tgz", "resolved": "https://registry.npmjs.org/@freearhey/core/-/core-0.7.0.tgz",
"integrity": "sha512-kEdIxZClykKhGpgyCSlkwuVuSCCAWr3J5YvOUMJQDPgVAYvT5VbD8MYKPm+OwNi9T4HFmF6qqY90qwKJPoOXCA==", "integrity": "sha512-HXkKPYGY7ife7JAc1q/Qxzy0WUdSnyt3rHThCShZHgnH3rz0tpkjHFW7LNegB3he0IKn/Zc95/YSOQ97Fq8ctA==",
"requires": { "requires": {
"@types/fs-extra": "^11.0.2", "@types/fs-extra": "^11.0.2",
"@types/lodash": "^4.14.198", "@types/lodash": "^4.14.198",
@ -7470,6 +7480,7 @@
"node-gzip": "^1.1.2", "node-gzip": "^1.1.2",
"normalize-url": "^6.1.0", "normalize-url": "^6.1.0",
"object-treeify": "^2.1.1", "object-treeify": "^2.1.1",
"run-script-os": "^1.1.6",
"signale": "^1.4.0" "signale": "^1.4.0"
}, },
"dependencies": { "dependencies": {
@ -11122,6 +11133,11 @@
"queue-microtask": "^1.2.2" "queue-microtask": "^1.2.2"
} }
}, },
"run-script-os": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/run-script-os/-/run-script-os-1.1.6.tgz",
"integrity": "sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw=="
},
"semver": { "semver": {
"version": "7.6.3", "version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",

View file

@ -39,7 +39,7 @@
"dependencies": { "dependencies": {
"@eslint/eslintrc": "^3.3.0", "@eslint/eslintrc": "^3.3.0",
"@eslint/js": "^9.21.0", "@eslint/js": "^9.21.0",
"@freearhey/core": "^0.2.1", "@freearhey/core": "^0.7.0",
"@octokit/core": "^6.1.4", "@octokit/core": "^6.1.4",
"@octokit/plugin-paginate-rest": "^11.4.3", "@octokit/plugin-paginate-rest": "^11.4.3",
"@octokit/plugin-rest-endpoint-methods": "^7.1.3", "@octokit/plugin-rest-endpoint-methods": "^7.1.3",

View file

@ -1,21 +1,37 @@
import { Logger, Storage } from '@freearhey/core' import { Logger, Storage, Collection } from '@freearhey/core'
import { API_DIR, STREAMS_DIR } from '../../constants' import { API_DIR, STREAMS_DIR, DATA_DIR } from '../../constants'
import { PlaylistParser } from '../../core' import { PlaylistParser } from '../../core'
import { Stream } from '../../models' import { Stream, Channel, Feed } from '../../models'
import { uniqueId } from 'lodash'
async function main() { async function main() {
const logger = new Logger() const logger = new Logger()
logger.info('loading api data...')
const dataStorage = new Storage(DATA_DIR)
const channelsData = await dataStorage.json('channels.json')
const channels = new Collection(channelsData).map(data => new Channel(data))
const channelsGroupedById = channels.keyBy((channel: Channel) => channel.id)
const feedsData = await dataStorage.json('feeds.json')
const feeds = new Collection(feedsData).map(data =>
new Feed(data).withChannel(channelsGroupedById)
)
const feedsGroupedByChannelId = feeds.groupBy((feed: Feed) =>
feed.channel ? feed.channel.id : uniqueId()
)
logger.info('loading streams...') logger.info('loading streams...')
const streamsStorage = new Storage(STREAMS_DIR) const streamsStorage = new Storage(STREAMS_DIR)
const parser = new PlaylistParser({ storage: streamsStorage }) const parser = new PlaylistParser({
storage: streamsStorage,
channelsGroupedById,
feedsGroupedByChannelId
})
const files = await streamsStorage.list('**/*.m3u') const files = await streamsStorage.list('**/*.m3u')
let streams = await parser.parse(files) let streams = await parser.parse(files)
streams = streams streams = streams
.map(data => new Stream(data)) .orderBy((stream: Stream) => stream.getId())
.orderBy([(stream: Stream) => stream.channel])
.map((stream: Stream) => stream.toJSON()) .map((stream: Stream) => stream.toJSON())
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...')

View file

@ -12,7 +12,9 @@ async function main() {
client.download('countries.json'), client.download('countries.json'),
client.download('languages.json'), client.download('languages.json'),
client.download('regions.json'), client.download('regions.json'),
client.download('subdivisions.json') client.download('subdivisions.json'),
client.download('feeds.json'),
client.download('timezones.json')
] ]
await Promise.all(requests) await Promise.all(requests)

View file

@ -1,25 +1,36 @@
import { Logger, Storage, Collection } from '@freearhey/core' import { Logger, Storage, Collection } from '@freearhey/core'
import { STREAMS_DIR, DATA_DIR } from '../../constants' import { STREAMS_DIR, DATA_DIR } from '../../constants'
import { PlaylistParser } from '../../core' import { PlaylistParser } from '../../core'
import { Stream, Playlist, Channel } from '../../models' import { Stream, Playlist, Channel, Feed } from '../../models'
import { program } from 'commander' import { program } from 'commander'
import { uniqueId } from 'lodash'
program.argument('[filepath]', 'Path to file to validate').parse(process.argv) program.argument('[filepath]', 'Path to file to validate').parse(process.argv)
async function main() { async function main() {
const storage = new Storage(STREAMS_DIR) const streamsStorage = new Storage(STREAMS_DIR)
const logger = new Logger() const logger = new Logger()
logger.info('loading channels from api...') logger.info('loading data from api...')
const dataStorage = new Storage(DATA_DIR) const dataStorage = new Storage(DATA_DIR)
const channelsContent = await dataStorage.json('channels.json') const channelsData = await dataStorage.json('channels.json')
const groupedChannels = new Collection(channelsContent) const channels = new Collection(channelsData).map(data => new Channel(data))
.map(data => new Channel(data)) const channelsGroupedById = channels.keyBy((channel: Channel) => channel.id)
.keyBy((channel: Channel) => channel.id) const feedsData = await dataStorage.json('feeds.json')
const feeds = new Collection(feedsData).map(data =>
new Feed(data).withChannel(channelsGroupedById)
)
const feedsGroupedByChannelId = feeds.groupBy(feed =>
feed.channel ? feed.channel.id : uniqueId()
)
logger.info('loading streams...') logger.info('loading streams...')
const parser = new PlaylistParser({ storage }) const parser = new PlaylistParser({
const files = program.args.length ? program.args : await storage.list('**/*.m3u') storage: streamsStorage,
channelsGroupedById,
feedsGroupedByChannelId
})
const files = program.args.length ? program.args : await streamsStorage.list('**/*.m3u')
let streams = await parser.parse(files) let streams = await parser.parse(files)
logger.info(`found ${streams.count()} streams`) logger.info(`found ${streams.count()} streams`)
@ -35,8 +46,8 @@ async function main() {
logger.info('removing wrong id...') logger.info('removing wrong id...')
streams = streams.map((stream: Stream) => { streams = streams.map((stream: Stream) => {
if (groupedChannels.missing(stream.channel)) { if (!stream.channel || channelsGroupedById.missing(stream.channel.id)) {
stream.channel = '' stream.id = ''
} }
return stream return stream
@ -46,22 +57,22 @@ async function main() {
streams = streams.orderBy( streams = streams.orderBy(
[ [
(stream: Stream) => stream.name, (stream: Stream) => stream.name,
(stream: Stream) => parseInt(stream.quality.replace('p', '')), (stream: Stream) => stream.getVerticalResolution(),
(stream: Stream) => stream.label, (stream: Stream) => stream.getLabel(),
(stream: Stream) => stream.url (stream: Stream) => stream.url
], ],
['asc', 'desc', 'asc', 'asc'] ['asc', 'desc', 'asc', 'asc']
) )
logger.info('saving...') logger.info('saving...')
const groupedStreams = streams.groupBy((stream: Stream) => stream.filepath) const groupedStreams = streams.groupBy((stream: Stream) => stream.getFilepath())
for (let filepath of groupedStreams.keys()) { for (let filepath of groupedStreams.keys()) {
const streams = groupedStreams.get(filepath) || [] const streams = groupedStreams.get(filepath) || []
if (!streams.length) return if (!streams.length) return
const playlist = new Playlist(streams, { public: false }) const playlist = new Playlist(streams, { public: false })
await storage.save(filepath, playlist.toString()) await streamsStorage.save(filepath, playlist.toString())
} }
} }

View file

@ -1,14 +1,23 @@
import { Logger, Storage, Collection, File } from '@freearhey/core' import { Logger, Storage, Collection } from '@freearhey/core'
import { PlaylistParser } from '../../core' import { PlaylistParser } from '../../core'
import { Stream, Category, Channel, Language, Country, Region, Subdivision } from '../../models' import {
import _ from 'lodash' Stream,
Category,
Channel,
Language,
Country,
Region,
Subdivision,
Feed,
Timezone
} from '../../models'
import { uniqueId } from 'lodash'
import { import {
CategoriesGenerator, CategoriesGenerator,
CountriesGenerator, CountriesGenerator,
LanguagesGenerator, LanguagesGenerator,
RegionsGenerator, RegionsGenerator,
IndexGenerator, IndexGenerator,
IndexNsfwGenerator,
IndexCategoryGenerator, IndexCategoryGenerator,
IndexCountryGenerator, IndexCountryGenerator,
IndexLanguageGenerator, IndexLanguageGenerator,
@ -19,123 +28,136 @@ 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 dataStorage = new Storage(DATA_DIR)
logger.info('loading data from api...')
const channelsContent = await dataStorage.json('channels.json')
const channels = new Collection(channelsContent).map(data => new Channel(data))
const categoriesContent = await dataStorage.json('categories.json')
const categories = new Collection(categoriesContent).map(data => new Category(data))
const countriesContent = await dataStorage.json('countries.json')
const countries = new Collection(countriesContent).map(data => new Country(data))
const languagesContent = await dataStorage.json('languages.json')
const languages = new Collection(languagesContent).map(data => new Language(data))
const regionsContent = await dataStorage.json('regions.json')
const regions = new Collection(regionsContent).map(data => new Region(data))
const subdivisionsContent = await dataStorage.json('subdivisions.json')
const subdivisions = new Collection(subdivisionsContent).map(data => new Subdivision(data))
logger.info('loading streams...')
let streams = await loadStreams({ channels, categories, languages })
let totalStreams = streams.count()
streams = streams.uniqBy((stream: Stream) => (stream.channel || _.uniqueId()) + stream.timeshift)
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`)
}) })
logger.info('loading data from api...')
const categoriesData = await dataStorage.json('categories.json')
const countriesData = await dataStorage.json('countries.json')
const languagesData = await dataStorage.json('languages.json')
const regionsData = await dataStorage.json('regions.json')
const subdivisionsData = await dataStorage.json('subdivisions.json')
const timezonesData = await dataStorage.json('timezones.json')
const channelsData = await dataStorage.json('channels.json')
const feedsData = await dataStorage.json('feeds.json')
logger.info('preparing data...')
const subdivisions = new Collection(subdivisionsData).map(data => new Subdivision(data))
const subdivisionsGroupedByCode = subdivisions.keyBy(
(subdivision: Subdivision) => subdivision.code
)
const subdivisionsGroupedByCountryCode = subdivisions.groupBy(
(subdivision: Subdivision) => subdivision.countryCode
)
let regions = new Collection(regionsData).map(data =>
new Region(data).withSubdivisions(subdivisions)
)
const regionsGroupedByCode = regions.keyBy((region: Region) => region.code)
const categories = new Collection(categoriesData).map(data => new Category(data))
const categoriesGroupedById = categories.keyBy((category: Category) => category.id)
const languages = new Collection(languagesData).map(data => new Language(data))
const languagesGroupedByCode = languages.keyBy((language: Language) => language.code)
const countries = new Collection(countriesData).map(data =>
new Country(data)
.withRegions(regions)
.withLanguage(languagesGroupedByCode)
.withSubdivisions(subdivisionsGroupedByCountryCode)
)
const countriesGroupedByCode = countries.keyBy((country: Country) => country.code)
regions = regions.map((region: Region) => region.withCountries(countriesGroupedByCode))
const timezones = new Collection(timezonesData).map(data =>
new Timezone(data).withCountries(countriesGroupedByCode)
)
const timezonesGroupedById = timezones.keyBy((timezone: Timezone) => timezone.id)
const channels = new Collection(channelsData).map(data =>
new Channel(data)
.withCategories(categoriesGroupedById)
.withCountry(countriesGroupedByCode)
.withSubdivision(subdivisionsGroupedByCode)
)
const channelsGroupedById = channels.keyBy((channel: Channel) => channel.id)
const feeds = new Collection(feedsData).map(data =>
new Feed(data)
.withChannel(channelsGroupedById)
.withLanguages(languagesGroupedByCode)
.withTimezones(timezonesGroupedById)
.withBroadcastCountries(
countriesGroupedByCode,
regionsGroupedByCode,
subdivisionsGroupedByCode
)
.withBroadcastRegions(regions)
.withBroadcastSubdivisions(subdivisionsGroupedByCode)
)
const feedsGroupedByChannelId = feeds.groupBy((feed: Feed) =>
feed.channel ? feed.channel.id : uniqueId()
)
logger.info('loading streams...')
const storage = new Storage(STREAMS_DIR)
const parser = new PlaylistParser({
storage,
channelsGroupedById,
feedsGroupedByChannelId
})
const files = await storage.list('**/*.m3u')
let streams = await parser.parse(files)
const totalStreams = streams.count()
streams = streams.uniqBy((stream: Stream) =>
stream.hasId() ? stream.getChannelId() + stream.getFeedId() : uniqueId()
)
logger.info(`found ${totalStreams} streams (including ${streams.count()} unique)`)
logger.info('sorting streams...')
streams = streams.orderBy(
[
(stream: Stream) => stream.getId(),
(stream: Stream) => stream.getVerticalResolution(),
(stream: Stream) => stream.getLabel()
],
['asc', 'asc', 'desc']
)
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,
streams, streams,
regions,
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,
regions, regions,
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.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,
countries,
regions,
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()
} }
main() main()
async function loadStreams({
channels,
categories,
languages
}: {
channels: Collection
categories: Collection
languages: Collection
}) {
const groupedChannels = channels.keyBy(channel => channel.id)
const groupedCategories = categories.keyBy(category => category.id)
const groupedLanguages = languages.keyBy(language => language.code)
const storage = new Storage(STREAMS_DIR)
const parser = new PlaylistParser({ storage })
const files = await storage.list('**/*.m3u')
let streams = await parser.parse(files)
streams = streams
.orderBy(
[
(stream: Stream) => stream.channel,
(stream: Stream) => parseInt(stream.quality.replace('p', '')),
(stream: Stream) => stream.label
],
['asc', 'asc', 'desc', 'asc']
)
.map((stream: Stream) => {
const channel: Channel | undefined = groupedChannels.get(stream.channel)
if (channel) {
const channelCategories = channel.categories
.map((id: string) => groupedCategories.get(id))
.filter(Boolean)
const channelLanguages = channel.languages
.map((id: string) => groupedLanguages.get(id))
.filter(Boolean)
stream.categories = channelCategories
stream.languages = channelLanguages
stream.broadcastArea = channel.broadcastArea
stream.isNSFW = channel.isNSFW
if (channel.logo) stream.logo = channel.logo
} else {
const file = new File(stream.filepath)
const [_, countryCode] = file.name().match(/^([a-z]{2})(_|$)/) || [null, null]
const defaultBroadcastArea = countryCode ? [`c/${countryCode.toUpperCase()}`] : []
stream.broadcastArea = new Collection(defaultBroadcastArea)
}
return stream
})
return streams
}

View file

@ -1,7 +1,7 @@
import { Logger, Storage, Collection } from '@freearhey/core' import { Logger, Storage, Collection } from '@freearhey/core'
import { ROOT_DIR, STREAMS_DIR } from '../../constants' import { ROOT_DIR, STREAMS_DIR, DATA_DIR } from '../../constants'
import { PlaylistParser, StreamTester, CliTable } from '../../core' import { PlaylistParser, StreamTester, CliTable } from '../../core'
import { Stream } from '../../models' import { Stream, Feed, Channel } from '../../models'
import { program } from 'commander' import { program } from 'commander'
import { eachLimit } from 'async-es' import { eachLimit } from 'async-es'
import commandExists from 'command-exists' import commandExists from 'command-exists'
@ -38,8 +38,6 @@ const logger = new Logger()
const tester = new StreamTester() const tester = new StreamTester()
async function main() { async function main() {
const storage = new Storage(ROOT_DIR)
if (await isOffline()) { if (await isOffline()) {
logger.error(chalk.red('Internet connection is required for the script to work')) logger.error(chalk.red('Internet connection is required for the script to work'))
@ -56,9 +54,25 @@ async function main() {
return return
} }
logger.info('loading channels from api...')
const dataStorage = new Storage(DATA_DIR)
const channelsData = await dataStorage.json('channels.json')
const channels = new Collection(channelsData).map(data => new Channel(data))
const channelsGroupedById = channels.keyBy((channel: Channel) => channel.id)
const feedsData = await dataStorage.json('feeds.json')
const feeds = new Collection(feedsData).map(data =>
new Feed(data).withChannel(channelsGroupedById)
)
const feedsGroupedByChannelId = feeds.groupBy(feed => feed.channel)
logger.info('loading streams...') logger.info('loading streams...')
const parser = new PlaylistParser({ storage }) const rootStorage = new Storage(ROOT_DIR)
const files = program.args.length ? program.args : await storage.list(`${STREAMS_DIR}/*.m3u`) const parser = new PlaylistParser({
storage: rootStorage,
channelsGroupedById,
feedsGroupedByChannelId
})
const files = program.args.length ? program.args : await rootStorage.list(`${STREAMS_DIR}/*.m3u`)
streams = await parser.parse(files) streams = await parser.parse(files)
logger.info(`found ${streams.count()} streams`) logger.info(`found ${streams.count()} streams`)
@ -89,7 +103,7 @@ async function main() {
main() main()
async function runTest(stream: Stream) { async function runTest(stream: Stream) {
const key = stream.filepath + stream.channel + stream.url const key = stream.filepath + stream.getId() + stream.url
results[key] = chalk.white('LOADING...') results[key] = chalk.white('LOADING...')
const result = await tester.test(stream) const result = await tester.test(stream)
@ -125,11 +139,11 @@ function drawTable() {
] ]
}) })
streams.forEach((stream: Stream, index: number) => { streams.forEach((stream: Stream, index: number) => {
const status = results[stream.filepath + stream.channel + stream.url] || chalk.gray('PENDING') const status = results[stream.filepath + stream.getId() + stream.url] || chalk.gray('PENDING')
const row = { const row = {
'': index, '': index,
'tvg-id': stream.channel.length > 25 ? stream.channel.slice(0, 22) + '...' : stream.channel, 'tvg-id': stream.getId().length > 25 ? stream.getId().slice(0, 22) + '...' : stream.getId(),
url: stream.url.length > 100 ? stream.url.slice(0, 97) + '...' : stream.url, url: stream.url.length > 100 ? stream.url.slice(0, 97) + '...' : stream.url,
status status
} }

View file

@ -1,45 +1,63 @@
import { Logger, Storage, Collection, Dictionary } from '@freearhey/core' import { Logger, Storage, Collection, Dictionary } from '@freearhey/core'
import { DATA_DIR, STREAMS_DIR } from '../../constants' import { DATA_DIR, STREAMS_DIR } from '../../constants'
import { IssueLoader, PlaylistParser } from '../../core' import { IssueLoader, PlaylistParser } from '../../core'
import { Stream, Playlist, Channel, Issue } from '../../models' import { Stream, Playlist, Channel, Feed, Issue } from '../../models'
import validUrl from 'valid-url' import validUrl from 'valid-url'
import { uniqueId } from 'lodash'
let processedIssues = new Collection() let processedIssues = new Collection()
let streams: Collection
let groupedChannels: Dictionary
let issues: Collection
async function main() { 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 issues...') logger.info('loading issues...')
issues = await loader.load() const issues = await loader.load()
logger.info('loading channels from api...') logger.info('loading channels from api...')
const dataStorage = new Storage(DATA_DIR) const dataStorage = new Storage(DATA_DIR)
const channelsContent = await dataStorage.json('channels.json') const channelsData = await dataStorage.json('channels.json')
groupedChannels = new Collection(channelsContent) const channels = new Collection(channelsData).map(data => new Channel(data))
.map(data => new Channel(data)) const channelsGroupedById = channels.keyBy((channel: Channel) => channel.id)
.keyBy((channel: Channel) => channel.id) const feedsData = await dataStorage.json('feeds.json')
const feeds = new Collection(feedsData).map(data =>
new Feed(data).withChannel(channelsGroupedById)
)
const feedsGroupedByChannelId = feeds.groupBy((feed: Feed) =>
feed.channel ? feed.channel.id : uniqueId()
)
logger.info('loading streams...') logger.info('loading streams...')
const streamsStorage = new Storage(STREAMS_DIR) const streamsStorage = new Storage(STREAMS_DIR)
const parser = new PlaylistParser({ storage: streamsStorage }) const parser = new PlaylistParser({
storage: streamsStorage,
feedsGroupedByChannelId,
channelsGroupedById
})
const files = await streamsStorage.list('**/*.m3u') const files = await streamsStorage.list('**/*.m3u')
streams = await parser.parse(files) const streams = await parser.parse(files)
logger.info('removing broken streams...') logger.info('removing broken streams...')
await removeStreams(loader) await removeStreams({ streams, issues })
logger.info('edit stream description...') logger.info('edit stream description...')
await editStreams(loader) await editStreams({
streams,
issues,
channelsGroupedById,
feedsGroupedByChannelId
})
logger.info('add new streams...') logger.info('add new streams...')
await addStreams(loader) await addStreams({
streams,
issues,
channelsGroupedById,
feedsGroupedByChannelId
})
logger.info('saving...') logger.info('saving...')
const groupedStreams = streams.groupBy((stream: Stream) => stream.filepath) const groupedStreams = streams.groupBy((stream: Stream) => stream.getFilepath())
for (let filepath of groupedStreams.keys()) { for (let filepath of groupedStreams.keys()) {
let streams = groupedStreams.get(filepath) || [] let streams = groupedStreams.get(filepath) || []
streams = streams.filter((stream: Stream) => stream.removed === false) streams = streams.filter((stream: Stream) => stream.removed === false)
@ -54,7 +72,7 @@ async function main() {
main() main()
async function removeStreams(loader: IssueLoader) { async function removeStreams({ streams, issues }: { streams: Collection; issues: Collection }) {
const requests = issues.filter( const requests = issues.filter(
issue => issue.labels.includes('streams:remove') && issue.labels.includes('approved') issue => issue.labels.includes('streams:remove') && issue.labels.includes('approved')
) )
@ -62,10 +80,13 @@ async function removeStreams(loader: IssueLoader) {
const data = issue.data const data = issue.data
if (data.missing('brokenLinks')) return if (data.missing('brokenLinks')) return
const brokenLinks = data.getString('brokenLinks').split(/\r?\n/).filter(Boolean) const brokenLinks = data.getString('brokenLinks') || ''
let changed = false let changed = false
brokenLinks.forEach(link => { brokenLinks
.split(/\r?\n/)
.filter(Boolean)
.forEach(link => {
const found: Stream = streams.first((_stream: Stream) => _stream.url === link.trim()) const found: Stream = streams.first((_stream: Stream) => _stream.url === link.trim())
if (found) { if (found) {
found.removed = true found.removed = true
@ -77,7 +98,17 @@ async function removeStreams(loader: IssueLoader) {
}) })
} }
async function editStreams(loader: IssueLoader) { async function editStreams({
streams,
issues,
channelsGroupedById,
feedsGroupedByChannelId
}: {
streams: Collection
issues: Collection
channelsGroupedById: Dictionary
feedsGroupedByChannelId: Dictionary
}) {
const requests = issues.filter( const requests = issues.filter(
issue => issue.labels.includes('streams:edit') && issue.labels.includes('approved') issue => issue.labels.includes('streams:edit') && issue.labels.includes('approved')
) )
@ -86,59 +117,110 @@ async function editStreams(loader: IssueLoader) {
if (data.missing('streamUrl')) return if (data.missing('streamUrl')) return
let stream = streams.first( let stream: Stream = streams.first(
(_stream: Stream) => _stream.url === data.getString('streamUrl') (_stream: Stream) => _stream.url === data.getString('streamUrl')
) as Stream )
if (!stream) return if (!stream) return
if (data.has('channelId')) { const streamId = data.getString('streamId') || ''
const channel = groupedChannels.get(data.getString('channelId')) const [channelId, feedId] = streamId.split('@')
if (!channel) return if (channelId) {
stream
stream.channel = data.getString('channelId') .setChannelId(channelId)
stream.filepath = `${channel.country.toLowerCase()}.m3u` .setFeedId(feedId)
stream.line = -1 .withChannel(channelsGroupedById)
stream.name = channel.name .withFeed(feedsGroupedByChannelId)
.updateId()
.updateName()
.updateFilepath()
} }
if (data.has('label')) stream.label = data.getString('label') const label = data.getString('label') || ''
if (data.has('quality')) stream.quality = data.getString('quality') const quality = data.getString('quality') || ''
if (data.has('httpUserAgent')) stream.httpUserAgent = data.getString('httpUserAgent') const httpUserAgent = data.getString('httpUserAgent') || ''
if (data.has('httpReferrer')) stream.httpReferrer = data.getString('httpReferrer') const httpReferrer = data.getString('httpReferrer') || ''
if (data.has('label')) stream.setLabel(label)
if (data.has('quality')) stream.setQuality(quality)
if (data.has('httpUserAgent')) stream.setHttpUserAgent(httpUserAgent)
if (data.has('httpReferrer')) stream.setHttpReferrer(httpReferrer)
processedIssues.add(issue.number) processedIssues.add(issue.number)
}) })
} }
async function addStreams(loader: IssueLoader) { async function addStreams({
streams,
issues,
channelsGroupedById,
feedsGroupedByChannelId
}: {
streams: Collection
issues: Collection
channelsGroupedById: Dictionary
feedsGroupedByChannelId: Dictionary
}) {
const requests = issues.filter( const requests = issues.filter(
issue => issue.labels.includes('streams:add') && issue.labels.includes('approved') issue => issue.labels.includes('streams:add') && issue.labels.includes('approved')
) )
requests.forEach((issue: Issue) => { requests.forEach((issue: Issue) => {
const data = issue.data const data = issue.data
if (data.missing('channelId') || data.missing('streamUrl')) return if (data.missing('streamId') || data.missing('streamUrl')) return
if (streams.includes((_stream: Stream) => _stream.url === data.getString('streamUrl'))) return if (streams.includes((_stream: Stream) => _stream.url === data.getString('streamUrl'))) return
if (!validUrl.isUri(data.getString('streamUrl'))) return const stringUrl = data.getString('streamUrl') || ''
if (!isUri(stringUrl)) return
const channel = groupedChannels.get(data.getString('channelId')) const streamId = data.getString('streamId') || ''
const [channelId] = streamId.split('@')
const channel: Channel = channelsGroupedById.get(channelId)
if (!channel) return if (!channel) return
const label = data.getString('label') || ''
const quality = data.getString('quality') || ''
const httpUserAgent = data.getString('httpUserAgent') || ''
const httpReferrer = data.getString('httpReferrer') || ''
const stream = new Stream({ const stream = new Stream({
channel: data.getString('channelId'), tvg: {
url: data.getString('streamUrl'), id: streamId,
label: data.getString('label'), name: '',
quality: data.getString('quality'), url: '',
httpUserAgent: data.getString('httpUserAgent'), logo: '',
httpReferrer: data.getString('httpReferrer'), rec: '',
filepath: `${channel.country.toLowerCase()}.m3u`, shift: ''
},
name: data.getString('channelName') || channel.name,
url: stringUrl,
group: {
title: ''
},
http: {
'user-agent': httpUserAgent,
referrer: httpReferrer
},
line: -1, line: -1,
name: data.getString('channelName') || channel.name raw: '',
timeshift: '',
catchup: {
type: '',
source: '',
days: ''
}
}) })
.withChannel(channelsGroupedById)
.withFeed(feedsGroupedByChannelId)
.setLabel(label)
.setQuality(quality)
.updateName()
.updateFilepath()
streams.add(stream) streams.add(stream)
processedIssues.add(issue.number) processedIssues.add(issue.number)
}) })
} }
function isUri(string: string) {
return validUrl.isUri(encodeURI(string))
}

View file

@ -1,9 +1,9 @@
import { Logger, Storage, Collection, Dictionary } from '@freearhey/core' import { Logger, Storage, Collection, Dictionary } from '@freearhey/core'
import { PlaylistParser } from '../../core' import { PlaylistParser } from '../../core'
import { Channel, Stream, Blocked } from '../../models' import { Channel, Stream, Blocked, Feed } from '../../models'
import { program } from 'commander' import { program } from 'commander'
import chalk from 'chalk' import chalk from 'chalk'
import _ from 'lodash' import { uniqueId } from 'lodash'
import { DATA_DIR, STREAMS_DIR } from '../../constants' import { DATA_DIR, STREAMS_DIR } from '../../constants'
program.argument('[filepath]', 'Path to file to validate').parse(process.argv) program.argument('[filepath]', 'Path to file to validate').parse(process.argv)
@ -17,42 +17,53 @@ type LogItem = {
async function main() { async function main() {
const logger = new Logger() const logger = new Logger()
logger.info(`loading blocklist...`) logger.info('loading data from api...')
const dataStorage = new Storage(DATA_DIR) const dataStorage = new Storage(DATA_DIR)
const channelsContent = await dataStorage.json('channels.json') const channelsData = await dataStorage.json('channels.json')
const channels = new Collection(channelsContent).map(data => new Channel(data)) const channels = new Collection(channelsData).map(data => new Channel(data))
const channelsGroupedById = channels.keyBy((channel: Channel) => channel.id)
const feedsData = await dataStorage.json('feeds.json')
const feeds = new Collection(feedsData).map(data =>
new Feed(data).withChannel(channelsGroupedById)
)
const feedsGroupedByChannelId = feeds.groupBy((feed: Feed) =>
feed.channel ? feed.channel.id : uniqueId()
)
const blocklistContent = await dataStorage.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))
const blocklistGroupedByChannelId = blocklist.keyBy((blocked: Blocked) => blocked.channelId)
logger.info(`found ${blocklist.count()} records`)
logger.info('loading streams...') logger.info('loading streams...')
const streamsStorage = new Storage(STREAMS_DIR) const streamsStorage = new Storage(STREAMS_DIR)
const parser = new PlaylistParser({ storage: streamsStorage }) const parser = new PlaylistParser({
storage: streamsStorage,
channelsGroupedById,
feedsGroupedByChannelId
})
const files = program.args.length ? program.args : await streamsStorage.list('**/*.m3u') const files = program.args.length ? program.args : await streamsStorage.list('**/*.m3u')
const streams = await parser.parse(files) const streams = await parser.parse(files)
logger.info(`found ${streams.count()} streams`) logger.info(`found ${streams.count()} streams`)
let errors = new Collection() let errors = new Collection()
let warnings = new Collection() let warnings = new Collection()
let groupedStreams = streams.groupBy((stream: Stream) => stream.filepath) let streamsGroupedByFilepath = streams.groupBy((stream: Stream) => stream.getFilepath())
for (const filepath of groupedStreams.keys()) { for (const filepath of streamsGroupedByFilepath.keys()) {
const streams = groupedStreams.get(filepath) const streams = streamsGroupedByFilepath.get(filepath)
if (!streams) continue if (!streams) continue
const log = new Collection() const log = new Collection()
const buffer = new Dictionary() const buffer = new Dictionary()
streams.forEach((stream: Stream) => { streams.forEach((stream: Stream) => {
const invalidId = if (stream.channelId) {
stream.channel && !channels.first((channel: Channel) => channel.id === stream.channel) const channel = channelsGroupedById.get(stream.channelId)
if (invalidId) { if (!channel) {
log.add({ log.add({
type: 'warning', type: 'warning',
line: stream.line, line: stream.line,
message: `"${stream.channel}" is not in the database` message: `"${stream.id}" is not in the database`
}) })
} }
}
const duplicate = stream.url && buffer.has(stream.url) const duplicate = stream.url && buffer.has(stream.url)
if (duplicate) { if (duplicate) {
@ -65,19 +76,19 @@ async function main() {
buffer.set(stream.url, true) buffer.set(stream.url, true)
} }
const blocked = blocklist.first(blocked => stream.channel === blocked.channel) const blocked = stream.channel ? blocklistGroupedByChannelId.get(stream.channel.id) : false
if (blocked) { if (blocked) {
if (blocked.reason === 'dmca') { if (blocked.reason === 'dmca') {
log.add({ log.add({
type: 'error', type: 'error',
line: stream.line, line: stream.line,
message: `"${stream.channel}" is on the blocklist due to claims of copyright holders (${blocked.ref})` message: `"${blocked.channelId}" is on the blocklist due to claims of copyright holders (${blocked.ref})`
}) })
} else if (blocked.reason === 'nsfw') { } else if (blocked.reason === 'nsfw') {
log.add({ log.add({
type: 'error', type: 'error',
line: stream.line, line: stream.line,
message: `"${stream.channel}" is on the blocklist due to NSFW content (${blocked.ref})` message: `"${blocked.channelId}" is on the blocklist due to NSFW content (${blocked.ref})`
}) })
} }
} }

View file

@ -1,154 +1,164 @@
import { Logger, Storage, Collection, Dictionary } from '@freearhey/core' import { Logger, Storage, Collection, Dictionary } from '@freearhey/core'
import { DATA_DIR, STREAMS_DIR } from '../../constants' import { DATA_DIR, STREAMS_DIR } from '../../constants'
import { IssueLoader, PlaylistParser } from '../../core' import { IssueLoader, PlaylistParser } from '../../core'
import { Blocked, Channel, Issue, Stream } from '../../models' import { Blocked, Channel, Issue, Stream, Feed } from '../../models'
import { uniqueId } from 'lodash'
async function main() { async function main() {
const logger = new Logger() const logger = new Logger()
const loader = new IssueLoader() const loader = new IssueLoader()
let report = new Collection()
const storage = new Storage(DATA_DIR)
logger.info('loading issues...') logger.info('loading issues...')
const issues = await loader.load() const issues = await loader.load()
logger.info('loading data from api...')
const dataStorage = new Storage(DATA_DIR)
const channelsData = await dataStorage.json('channels.json')
const channels = new Collection(channelsData).map(data => new Channel(data))
const channelsGroupedById = channels.keyBy((channel: Channel) => channel.id)
const feedsData = await dataStorage.json('feeds.json')
const feeds = new Collection(feedsData).map(data =>
new Feed(data).withChannel(channelsGroupedById)
)
const feedsGroupedByChannelId = feeds.groupBy((feed: Feed) =>
feed.channel ? feed.channel.id : uniqueId()
)
const blocklistContent = await dataStorage.json('blocklist.json')
const blocklist = new Collection(blocklistContent).map(data => new Blocked(data))
const blocklistGroupedByChannelId = blocklist.keyBy((blocked: Blocked) => blocked.channelId)
logger.info('loading streams...') logger.info('loading streams...')
const streamsStorage = new Storage(STREAMS_DIR) const streamsStorage = new Storage(STREAMS_DIR)
const parser = new PlaylistParser({ storage: streamsStorage }) const parser = new PlaylistParser({
storage: streamsStorage,
channelsGroupedById,
feedsGroupedByChannelId
})
const files = await streamsStorage.list('**/*.m3u') const files = await streamsStorage.list('**/*.m3u')
const streams = await parser.parse(files) const streams = await parser.parse(files)
const streamsGroupedByUrl = streams.groupBy((stream: Stream) => stream.url) const streamsGroupedByUrl = streams.groupBy((stream: Stream) => stream.url)
const streamsGroupedByChannel = streams.groupBy((stream: Stream) => stream.channel) const streamsGroupedByChannelId = streams.groupBy((stream: Stream) => stream.channelId)
logger.info('loading channels from api...')
const channelsContent = await storage.json('channels.json')
const channelsGroupedById = new Collection(channelsContent)
.map(data => new Channel(data))
.groupBy((channel: Channel) => channel.id)
logger.info('loading blocklist from api...')
const blocklistContent = await storage.json('blocklist.json')
const blocklistGroupedByChannel = new Collection(blocklistContent)
.map(data => new Blocked(data))
.groupBy((blocked: Blocked) => blocked.channel)
let report = new Collection()
logger.info('checking streams:add requests...')
const addRequests = issues.filter(issue => issue.labels.includes('streams:add'))
const addRequestsBuffer = new Dictionary()
addRequests.forEach((issue: Issue) => {
const channelId = issue.data.getString('channelId') || undefined
const streamUrl = issue.data.getString('streamUrl')
const result = new Dictionary({
issueNumber: issue.number,
type: 'streams:add',
channelId,
streamUrl,
status: 'pending'
})
if (!channelId) result.set('status', 'missing_id')
else if (!streamUrl) result.set('status', 'missing_link')
else if (blocklistGroupedByChannel.has(channelId)) result.set('status', 'blocked')
else if (channelsGroupedById.missing(channelId)) result.set('status', 'wrong_id')
else if (streamsGroupedByUrl.has(streamUrl)) result.set('status', 'on_playlist')
else if (addRequestsBuffer.has(streamUrl)) result.set('status', 'duplicate')
else result.set('status', 'pending')
addRequestsBuffer.set(streamUrl, true)
report.add(result.data())
})
logger.info('checking streams:edit requests...')
const editRequests = issues.filter(issue => issue.labels.find(label => label === 'streams:edit'))
editRequests.forEach((issue: Issue) => {
const channelId = issue.data.getString('channelId') || undefined
const streamUrl = issue.data.getString('streamUrl') || undefined
const result = new Dictionary({
issueNumber: issue.number,
type: 'streams:edit',
channelId,
streamUrl,
status: 'pending'
})
if (!streamUrl) result.set('status', 'missing_link')
else if (streamsGroupedByUrl.missing(streamUrl)) result.set('status', 'invalid_link')
else if (channelId && channelsGroupedById.missing(channelId)) result.set('status', 'invalid_id')
report.add(result.data())
})
logger.info('checking broken streams reports...') logger.info('checking broken streams reports...')
const brokenStreamReports = issues.filter(issue => const brokenStreamReports = issues.filter(issue =>
issue.labels.find(label => label === 'broken stream') issue.labels.find((label: string) => label === 'broken stream')
) )
brokenStreamReports.forEach((issue: Issue) => { brokenStreamReports.forEach((issue: Issue) => {
const brokenLinks = issue.data.getArray('brokenLinks') || [] const brokenLinks = issue.data.getArray('brokenLinks') || []
if (!brokenLinks.length) { if (!brokenLinks.length) {
const result = new Dictionary({ const result = {
issueNumber: issue.number, issueNumber: issue.number,
type: 'broken stream', type: 'broken stream',
channelId: undefined, streamId: undefined,
streamUrl: undefined, streamUrl: undefined,
status: 'missing_link' status: 'missing_link'
}) }
report.add(result.data()) report.add(result)
} else { } else {
for (const streamUrl of brokenLinks) { for (const streamUrl of brokenLinks) {
const result = new Dictionary({ const result = {
issueNumber: issue.number, issueNumber: issue.number,
type: 'broken stream', type: 'broken stream',
channelId: undefined, streamId: undefined,
streamUrl: undefined, streamUrl: truncate(streamUrl),
status: 'pending' status: 'pending'
}) }
if (streamsGroupedByUrl.missing(streamUrl)) { if (streamsGroupedByUrl.missing(streamUrl)) {
result.set('streamUrl', streamUrl) result.status = 'wrong_link'
result.set('status', 'wrong_link')
} }
report.add(result.data()) report.add(result)
} }
} }
}) })
logger.info('checking streams:add requests...')
const addRequests = issues.filter(issue => issue.labels.includes('streams:add'))
const addRequestsBuffer = new Dictionary()
addRequests.forEach((issue: Issue) => {
const streamId = issue.data.getString('streamId') || ''
const streamUrl = issue.data.getString('streamUrl') || ''
const [channelId] = streamId.split('@')
const result = {
issueNumber: issue.number,
type: 'streams:add',
streamId: streamId || undefined,
streamUrl: truncate(streamUrl),
status: 'pending'
}
if (!channelId) result.status = 'missing_id'
else if (!streamUrl) result.status = 'missing_link'
else if (blocklistGroupedByChannelId.has(channelId)) result.status = 'blocked'
else if (channelsGroupedById.missing(channelId)) result.status = 'wrong_id'
else if (streamsGroupedByUrl.has(streamUrl)) result.status = 'on_playlist'
else if (addRequestsBuffer.has(streamUrl)) result.status = 'duplicate'
else result.status = 'pending'
addRequestsBuffer.set(streamUrl, true)
report.add(result)
})
logger.info('checking streams:edit requests...')
const editRequests = issues.filter(issue =>
issue.labels.find((label: string) => label === 'streams:edit')
)
editRequests.forEach((issue: Issue) => {
const streamId = issue.data.getString('streamId') || ''
const streamUrl = issue.data.getString('streamUrl') || ''
const [channelId] = streamId.split('@')
const result = {
issueNumber: issue.number,
type: 'streams:edit',
streamId: streamId || undefined,
streamUrl: truncate(streamUrl),
status: 'pending'
}
if (!streamUrl) result.status = 'missing_link'
else if (streamsGroupedByUrl.missing(streamUrl)) result.status = 'invalid_link'
else if (channelId && channelsGroupedById.missing(channelId)) result.status = 'invalid_id'
report.add(result)
})
logger.info('checking channel search requests...') logger.info('checking channel search requests...')
const channelSearchRequests = issues.filter(issue => const channelSearchRequests = issues.filter(issue =>
issue.labels.find(label => label === 'channel search') issue.labels.find((label: string) => label === 'channel search')
) )
const channelSearchRequestsBuffer = new Dictionary() const channelSearchRequestsBuffer = new Dictionary()
channelSearchRequests.forEach((issue: Issue) => { channelSearchRequests.forEach((issue: Issue) => {
const channelId = issue.data.getString('channelId') const streamId = issue.data.getString('channelId') || ''
const [channelId] = streamId.split('@')
const result = new Dictionary({ const result = {
issueNumber: issue.number, issueNumber: issue.number,
type: 'channel search', type: 'channel search',
channelId, streamId: streamId || undefined,
streamUrl: undefined, streamUrl: undefined,
status: 'pending' status: 'pending'
}) }
if (!channelId) result.set('status', 'missing_id') if (!channelId) result.status = 'missing_id'
else if (channelsGroupedById.missing(channelId)) result.set('status', 'invalid_id') else if (channelsGroupedById.missing(channelId)) result.status = 'invalid_id'
else if (channelSearchRequestsBuffer.has(channelId)) result.set('status', 'duplicate') else if (channelSearchRequestsBuffer.has(channelId)) result.status = 'duplicate'
else if (blocklistGroupedByChannel.has(channelId)) result.set('status', 'blocked') else if (blocklistGroupedByChannelId.has(channelId)) result.status = 'blocked'
else if (streamsGroupedByChannel.has(channelId)) result.set('status', 'fulfilled') else if (streamsGroupedByChannelId.has(channelId)) result.status = 'fulfilled'
else { else {
const channelData = channelsGroupedById.get(channelId) const channelData = channelsGroupedById.get(channelId)
if (channelData.length && channelData[0].closed) result.set('status', 'closed') if (channelData.length && channelData[0].closed) result.status = 'closed'
} }
channelSearchRequestsBuffer.set(channelId, true) channelSearchRequestsBuffer.set(channelId, true)
report.add(result.data()) report.add(result)
}) })
report = report.orderBy(item => item.issueNumber).filter(item => item.status !== 'pending') report = report.orderBy(item => item.issueNumber).filter(item => item.status !== 'pending')
@ -157,3 +167,10 @@ async function main() {
} }
main() main()
function truncate(string: string, limit: number = 100) {
if (!string) return string
if (string.length < limit) return string
return string.slice(0, limit) + '...'
}

View file

@ -41,7 +41,7 @@ export class ApiClient {
} }
async download(filename: string) { async download(filename: string) {
const stream = await this.storage.createStream(`/temp/data/${filename}`) const stream = await this.storage.createStream(`temp/data/${filename}`)
const bar = this.progressBar.create(0, 0, { filename }) const bar = this.progressBar.create(0, 0, { filename })

View file

@ -1,9 +1,10 @@
import { Table } from 'console-table-printer' import { Table } from 'console-table-printer'
import { ComplexOptions } from 'console-table-printer/dist/src/models/external-table'
export class CliTable { export class CliTable {
table: Table table: Table
constructor(options?) { constructor(options?: ComplexOptions | string[]) {
this.table = new Table(options) this.table = new Table(options)
} }

View file

@ -18,7 +18,7 @@ export class IssueData {
return Boolean(this._data.get(key)) return Boolean(this._data.get(key))
} }
getString(key: string): string { getString(key: string): string | undefined {
const deleteSymbol = '~' const deleteSymbol = '~'
return this._data.get(key) === deleteSymbol ? '' : this._data.get(key) return this._data.get(key) === deleteSymbol ? '' : this._data.get(key)

View file

@ -16,7 +16,7 @@ export class IssueLoader {
} }
let issues: object[] = [] let issues: object[] = []
if (TESTING) { if (TESTING) {
issues = (await import('../../tests/__data__/input/issues/all.js')).default issues = (await import('../../tests/__data__/input/playlist_update/issues.js')).default
} else { } else {
issues = await octokit.paginate(octokit.rest.issues.listForRepo, { issues = await octokit.paginate(octokit.rest.issues.listForRepo, {
owner: OWNER, owner: OWNER,

View file

@ -3,11 +3,10 @@ import { Issue } from '../models'
import { IssueData } from './issueData' import { IssueData } from './issueData'
const FIELDS = new Dictionary({ const FIELDS = new Dictionary({
'Stream ID': 'streamId',
'Channel ID': 'channelId', 'Channel ID': 'channelId',
'Channel ID (required)': 'channelId', 'Feed ID': 'feedId',
'Stream URL': 'streamUrl', 'Stream URL': 'streamUrl',
'Stream URL (optional)': 'streamUrl',
'Stream URL (required)': 'streamUrl',
'Broken Link': 'brokenLinks', 'Broken Link': 'brokenLinks',
'Broken Links': 'brokenLinks', 'Broken Links': 'brokenLinks',
Label: 'label', Label: 'label',
@ -18,8 +17,7 @@ const FIELDS = new Dictionary({
'HTTP Referrer': 'httpReferrer', 'HTTP Referrer': 'httpReferrer',
'What happened to the stream?': 'reason', 'What happened to the stream?': 'reason',
Reason: 'reason', Reason: 'reason',
Notes: 'notes', Notes: 'notes'
'Notes (optional)': 'notes'
}) })
export class IssueParser { export class IssueParser {
@ -30,7 +28,7 @@ export class IssueParser {
fields.forEach((field: string) => { fields.forEach((field: string) => {
const parsed = typeof field === 'string' ? field.split(/\r?\n/).filter(Boolean) : [] const parsed = typeof field === 'string' ? field.split(/\r?\n/).filter(Boolean) : []
let _label = parsed.shift() let _label = parsed.shift()
_label = _label ? _label.trim() : '' _label = _label ? _label.replace(/ \(optional\)| \(required\)/, '').trim() : ''
let _value = parsed.join('\r\n') let _value = parsed.join('\r\n')
_value = _value ? _value.trim() : '' _value = _value ? _value.trim() : ''

View file

@ -1,4 +1,5 @@
export type LogItem = { export type LogItem = {
type: string
filepath: string filepath: string
count: number count: number
} }

View file

@ -1,12 +1,22 @@
import { Collection, Storage } from '@freearhey/core' import { Collection, Storage, Dictionary } from '@freearhey/core'
import parser from 'iptv-playlist-parser' import parser from 'iptv-playlist-parser'
import { Stream } from '../models' import { Stream } from '../models'
type PlaylistPareserProps = {
storage: Storage
feedsGroupedByChannelId: Dictionary
channelsGroupedById: Dictionary
}
export class PlaylistParser { export class PlaylistParser {
storage: Storage storage: Storage
feedsGroupedByChannelId: Dictionary
channelsGroupedById: Dictionary
constructor({ storage }: { storage: Storage }) { constructor({ storage, feedsGroupedByChannelId, channelsGroupedById }: PlaylistPareserProps) {
this.storage = storage this.storage = storage
this.feedsGroupedByChannelId = feedsGroupedByChannelId
this.channelsGroupedById = channelsGroupedById
} }
async parse(files: string[]): Promise<Collection> { async parse(files: string[]): Promise<Collection> {
@ -21,41 +31,18 @@ export class PlaylistParser {
} }
async parseFile(filepath: string): Promise<Collection> { async parseFile(filepath: string): Promise<Collection> {
const streams = new Collection()
const content = await this.storage.load(filepath) const content = await this.storage.load(filepath)
const parsed: parser.Playlist = parser.parse(content) const parsed: parser.Playlist = parser.parse(content)
parsed.items.forEach((item: parser.PlaylistItem) => { const streams = new Collection(parsed.items).map((data: parser.PlaylistItem) => {
const { name, label, quality } = parseTitle(item.name) const stream = new Stream(data)
const stream = new Stream({ .withFeed(this.feedsGroupedByChannelId)
channel: item.tvg.id, .withChannel(this.channelsGroupedById)
name, .setFilepath(filepath)
label,
quality,
filepath,
line: item.line,
url: item.url,
httpReferrer: item.http.referrer,
httpUserAgent: item.http['user-agent']
})
streams.add(stream) return stream
}) })
return streams return streams
} }
} }
function parseTitle(title: string): { name: string; label: string; quality: string } {
const [, label] = title.match(/ \[(.*)\]$/) || [null, '']
title = title.replace(new RegExp(` \\[${escapeRegExp(label)}\\]$`), '')
const [, quality] = title.match(/ \(([0-9]+p)\)$/) || [null, '']
title = title.replace(new RegExp(` \\(${quality}\\)$`), '')
return { name: title, label, quality }
}
function escapeRegExp(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
}

View file

@ -11,15 +11,15 @@ export class StreamTester {
async test(stream: Stream) { async test(stream: Stream) {
if (TESTING) { if (TESTING) {
const results = (await import('../../tests/__data__/input/test_results/all.js')).default const results = (await import('../../tests/__data__/input/playlist_test/results.js')).default
return results[stream.url] return results[stream.url]
} else { } else {
return this.checker.checkStream({ return this.checker.checkStream({
url: stream.url, url: stream.url,
http: { http: {
referrer: stream.httpReferrer, referrer: stream.getHttpReferrer(),
'user-agent': stream.httpUserAgent 'user-agent': stream.getHttpUserAgent()
} }
}) })
} }

View file

@ -29,11 +29,7 @@ export class CategoriesGenerator implements Generator {
const categoryStreams = streams const categoryStreams = streams
.filter((stream: Stream) => stream.hasCategory(category)) .filter((stream: Stream) => stream.hasCategory(category))
.map((stream: Stream) => { .map((stream: Stream) => {
const streamCategories = stream.categories stream.groupTitle = stream.getCategoryNames().join(';')
.map((category: Category) => category.name)
.sort()
const groupTitle = stream.categories ? streamCategories.join(';') : ''
stream.groupTitle = groupTitle
return stream return stream
}) })
@ -41,13 +37,17 @@ export class CategoriesGenerator implements Generator {
const playlist = new Playlist(categoryStreams, { public: true }) const playlist = new Playlist(categoryStreams, { public: true })
const filepath = `categories/${category.id}.m3u` const filepath = `categories/${category.id}.m3u`
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(
JSON.stringify({ type: 'category', filepath, count: playlist.streams.count() })
)
}) })
const undefinedStreams = streams.filter((stream: Stream) => stream.noCategories()) const undefinedStreams = streams.filter((stream: Stream) => !stream.hasCategories())
const playlist = new Playlist(undefinedStreams, { public: true }) const playlist = new Playlist(undefinedStreams, { public: true })
const filepath = 'categories/undefined.m3u' const filepath = 'categories/undefined.m3u'
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(
JSON.stringify({ type: 'category', filepath, count: playlist.streams.count() })
)
} }
} }

View file

@ -1,12 +1,10 @@
import { Generator } from './generator' import { Generator } from './generator'
import { Collection, Storage, Logger } from '@freearhey/core' import { Collection, Storage, Logger } from '@freearhey/core'
import { Country, Region, Subdivision, Stream, Playlist } from '../models' import { Country, Subdivision, Stream, Playlist } from '../models'
import { PUBLIC_DIR } from '../constants' import { PUBLIC_DIR } from '../constants'
type CountriesGeneratorProps = { type CountriesGeneratorProps = {
streams: Collection streams: Collection
regions: Collection
subdivisions: Collection
countries: Collection countries: Collection
logger: Logger logger: Logger
} }
@ -14,55 +12,37 @@ type CountriesGeneratorProps = {
export class CountriesGenerator implements Generator { export class CountriesGenerator implements Generator {
streams: Collection streams: Collection
countries: Collection countries: Collection
regions: Collection
subdivisions: Collection
storage: Storage storage: Storage
logger: Logger logger: Logger
constructor({ streams, countries, regions, subdivisions, logger }: CountriesGeneratorProps) { constructor({ streams, countries, logger }: CountriesGeneratorProps) {
this.streams = streams this.streams = streams
this.countries = countries this.countries = countries
this.regions = regions
this.subdivisions = subdivisions
this.storage = new Storage(PUBLIC_DIR) this.storage = new Storage(PUBLIC_DIR)
this.logger = logger this.logger = logger
} }
async generate(): Promise<void> { async generate(): Promise<void> {
const streams = this.streams const streams = this.streams
.orderBy([stream => stream.getTitle()]) .orderBy((stream: Stream) => stream.getTitle())
.filter((stream: Stream) => stream.isSFW()) .filter((stream: Stream) => stream.isSFW())
const regions = this.regions.filter((region: Region) => region.code !== 'INT')
this.countries.forEach(async (country: Country) => { this.countries.forEach(async (country: Country) => {
const countrySubdivisions = this.subdivisions.filter( const countryStreams = streams.filter((stream: Stream) =>
(subdivision: Subdivision) => subdivision.country === country.code stream.isBroadcastInCountry(country)
) )
const countrySubdivisionsCodes = countrySubdivisions.map(
(subdivision: Subdivision) => `s/${subdivision.code}`
)
const countryAreaCodes = regions
.filter((region: Region) => region.countries.includes(country.code))
.map((region: Region) => `r/${region.code}`)
.concat(countrySubdivisionsCodes)
.add(`c/${country.code}`)
const countryStreams = streams.filter(stream =>
stream.broadcastArea.intersects(countryAreaCodes)
)
if (countryStreams.isEmpty()) return if (countryStreams.isEmpty()) return
const playlist = new Playlist(countryStreams, { public: true }) const playlist = new Playlist(countryStreams, { public: true })
const filepath = `countries/${country.code.toLowerCase()}.m3u` const filepath = `countries/${country.code.toLowerCase()}.m3u`
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(
JSON.stringify({ type: 'country', filepath, count: playlist.streams.count() })
)
countrySubdivisions.forEach(async (subdivision: Subdivision) => { country.getSubdivisions().forEach(async (subdivision: Subdivision) => {
const subdivisionStreams = streams.filter(stream => const subdivisionStreams = streams.filter((stream: Stream) =>
stream.broadcastArea.includes(`s/${subdivision.code}`) stream.isBroadcastInSubdivision(subdivision)
) )
if (subdivisionStreams.isEmpty()) return if (subdivisionStreams.isEmpty()) return
@ -70,16 +50,22 @@ export class CountriesGenerator implements Generator {
const playlist = new Playlist(subdivisionStreams, { public: true }) const playlist = new Playlist(subdivisionStreams, { public: true })
const filepath = `subdivisions/${subdivision.code.toLowerCase()}.m3u` const filepath = `subdivisions/${subdivision.code.toLowerCase()}.m3u`
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(
JSON.stringify({ type: 'subdivision', filepath, count: playlist.streams.count() })
)
}) })
}) })
const internationalStreams = streams.filter(stream => stream.isInternational()) const undefinedStreams = streams.filter((stream: Stream) => !stream.hasBroadcastArea())
if (internationalStreams.notEmpty()) { const undefinedPlaylist = new Playlist(undefinedStreams, { public: true })
const playlist = new Playlist(internationalStreams, { public: true }) const undefinedFilepath = 'countries/undefined.m3u'
const filepath = 'countries/int.m3u' await this.storage.save(undefinedFilepath, undefinedPlaylist.toString())
await this.storage.save(filepath, playlist.toString()) this.logger.info(
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) JSON.stringify({
} type: 'country',
filepath: undefinedFilepath,
count: undefinedPlaylist.streams.count()
})
)
} }
} }

View file

@ -26,14 +26,14 @@ export class IndexCategoryGenerator implements Generator {
let groupedStreams = new Collection() let groupedStreams = new Collection()
streams.forEach((stream: Stream) => { streams.forEach((stream: Stream) => {
if (stream.noCategories()) { if (!stream.hasCategories()) {
const streamClone = stream.clone() const streamClone = stream.clone()
streamClone.groupTitle = 'Undefined' streamClone.groupTitle = 'Undefined'
groupedStreams.add(streamClone) groupedStreams.add(streamClone)
return return
} }
stream.categories.forEach((category: Category) => { stream.getCategories().forEach((category: Category) => {
const streamClone = stream.clone() const streamClone = stream.clone()
streamClone.groupTitle = category.name streamClone.groupTitle = category.name
groupedStreams.push(streamClone) groupedStreams.push(streamClone)
@ -48,6 +48,6 @@ export class IndexCategoryGenerator implements Generator {
const playlist = new Playlist(groupedStreams, { public: true }) const playlist = new Playlist(groupedStreams, { public: true })
const filepath = 'index.category.m3u' const filepath = 'index.category.m3u'
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }))
} }
} }

View file

@ -1,29 +1,20 @@
import { Generator } from './generator' import { Generator } from './generator'
import { Collection, Storage, Logger } from '@freearhey/core' import { Collection, Storage, Logger } from '@freearhey/core'
import { Stream, Playlist, Country, Subdivision, Region } from '../models' import { Stream, Playlist, Country } from '../models'
import { PUBLIC_DIR } from '../constants' import { PUBLIC_DIR } from '../constants'
type IndexCountryGeneratorProps = { type IndexCountryGeneratorProps = {
streams: Collection streams: Collection
regions: Collection
countries: Collection
subdivisions: Collection
logger: Logger logger: Logger
} }
export class IndexCountryGenerator implements Generator { export class IndexCountryGenerator implements Generator {
streams: Collection streams: Collection
countries: Collection
regions: Collection
subdivisions: Collection
storage: Storage storage: Storage
logger: Logger logger: Logger
constructor({ streams, regions, countries, subdivisions, logger }: IndexCountryGeneratorProps) { constructor({ streams, logger }: IndexCountryGeneratorProps) {
this.streams = streams this.streams = streams
this.countries = countries
this.regions = regions
this.subdivisions = subdivisions
this.storage = new Storage(PUBLIC_DIR) this.storage = new Storage(PUBLIC_DIR)
this.logger = logger this.logger = logger
} }
@ -32,10 +23,10 @@ export class IndexCountryGenerator implements Generator {
let groupedStreams = new Collection() let groupedStreams = new Collection()
this.streams this.streams
.orderBy(stream => stream.getTitle()) .orderBy((stream: Stream) => stream.getTitle())
.filter(stream => stream.isSFW()) .filter((stream: Stream) => stream.isSFW())
.forEach(stream => { .forEach((stream: Stream) => {
if (stream.noBroadcastArea()) { if (!stream.hasBroadcastArea()) {
const streamClone = stream.clone() const streamClone = stream.clone()
streamClone.groupTitle = 'Undefined' streamClone.groupTitle = 'Undefined'
groupedStreams.add(streamClone) groupedStreams.add(streamClone)
@ -48,7 +39,7 @@ export class IndexCountryGenerator implements Generator {
groupedStreams.add(streamClone) groupedStreams.add(streamClone)
} }
this.getStreamBroadcastCountries(stream).forEach((country: Country) => { stream.getBroadcastCountries().forEach((country: Country) => {
const streamClone = stream.clone() const streamClone = stream.clone()
streamClone.groupTitle = country.name streamClone.groupTitle = country.name
groupedStreams.add(streamClone) groupedStreams.add(streamClone)
@ -65,40 +56,6 @@ export class IndexCountryGenerator implements Generator {
const playlist = new Playlist(groupedStreams, { public: true }) const playlist = new Playlist(groupedStreams, { public: true })
const filepath = 'index.country.m3u' const filepath = 'index.country.m3u'
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }))
}
getStreamBroadcastCountries(stream: Stream) {
const groupedRegions = this.regions.keyBy((region: Region) => region.code)
const groupedCountries = this.countries.keyBy((country: Country) => country.code)
const groupedSubdivisions = this.subdivisions.keyBy(
(subdivision: Subdivision) => subdivision.code
)
let broadcastCountries = new Collection()
stream.broadcastArea.forEach(broadcastAreaCode => {
const [type, code] = broadcastAreaCode.split('/')
switch (type) {
case 'c':
broadcastCountries.add(code)
break
case 'r':
if (code !== 'INT' && groupedRegions.has(code)) {
broadcastCountries = broadcastCountries.concat(groupedRegions.get(code).countries)
}
break
case 's':
if (groupedSubdivisions.has(code)) {
broadcastCountries.add(groupedSubdivisions.get(code).country)
}
break
}
})
return broadcastCountries
.uniq()
.map(code => groupedCountries.get(code))
.filter(Boolean)
} }
} }

View file

@ -27,6 +27,6 @@ export class IndexGenerator implements Generator {
const playlist = new Playlist(sfwStreams, { public: true }) const playlist = new Playlist(sfwStreams, { public: true })
const filepath = 'index.m3u' const filepath = 'index.m3u'
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }))
} }
} }

View file

@ -22,17 +22,17 @@ export class IndexLanguageGenerator implements Generator {
async generate(): Promise<void> { async generate(): Promise<void> {
let groupedStreams = new Collection() let groupedStreams = new Collection()
this.streams this.streams
.orderBy(stream => stream.getTitle()) .orderBy((stream: Stream) => stream.getTitle())
.filter(stream => stream.isSFW()) .filter((stream: Stream) => stream.isSFW())
.forEach(stream => { .forEach((stream: Stream) => {
if (stream.noLanguages()) { if (!stream.hasLanguages()) {
const streamClone = stream.clone() const streamClone = stream.clone()
streamClone.groupTitle = 'Undefined' streamClone.groupTitle = 'Undefined'
groupedStreams.add(streamClone) groupedStreams.add(streamClone)
return return
} }
stream.languages.forEach((language: Language) => { stream.getLanguages().forEach((language: Language) => {
const streamClone = stream.clone() const streamClone = stream.clone()
streamClone.groupTitle = language.name streamClone.groupTitle = language.name
groupedStreams.add(streamClone) groupedStreams.add(streamClone)
@ -47,6 +47,6 @@ export class IndexLanguageGenerator implements Generator {
const playlist = new Playlist(groupedStreams, { public: true }) const playlist = new Playlist(groupedStreams, { public: true })
const filepath = 'index.language.m3u' const filepath = 'index.language.m3u'
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }))
} }
} }

View file

@ -25,6 +25,6 @@ export class IndexNsfwGenerator implements Generator {
const playlist = new Playlist(allStreams, { public: true }) const playlist = new Playlist(allStreams, { public: true })
const filepath = 'index.nsfw.m3u' const filepath = 'index.nsfw.m3u'
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }))
} }
} }

View file

@ -28,14 +28,21 @@ export class IndexRegionGenerator implements Generator {
.orderBy((stream: Stream) => stream.getTitle()) .orderBy((stream: Stream) => stream.getTitle())
.filter((stream: Stream) => stream.isSFW()) .filter((stream: Stream) => stream.isSFW())
.forEach((stream: Stream) => { .forEach((stream: Stream) => {
if (stream.noBroadcastArea()) { if (stream.isInternational()) {
const streamClone = stream.clone()
streamClone.groupTitle = 'International'
groupedStreams.push(streamClone)
return
}
if (!stream.hasBroadcastArea()) {
const streamClone = stream.clone() const streamClone = stream.clone()
streamClone.groupTitle = 'Undefined' streamClone.groupTitle = 'Undefined'
groupedStreams.push(streamClone) groupedStreams.push(streamClone)
return return
} }
this.getStreamRegions(stream).forEach((region: Region) => { stream.getBroadcastRegions().forEach((region: Region) => {
const streamClone = stream.clone() const streamClone = stream.clone()
streamClone.groupTitle = region.name streamClone.groupTitle = region.name
groupedStreams.push(streamClone) groupedStreams.push(streamClone)
@ -43,41 +50,14 @@ export class IndexRegionGenerator implements Generator {
}) })
groupedStreams = groupedStreams.orderBy((stream: Stream) => { groupedStreams = groupedStreams.orderBy((stream: Stream) => {
if (stream.groupTitle === 'Undefined') return 'ZZ' if (stream.groupTitle === 'International') return 'ZZ'
if (stream.groupTitle === 'Undefined') return 'ZZZ'
return stream.groupTitle return stream.groupTitle
}) })
const playlist = new Playlist(groupedStreams, { public: true }) const playlist = new Playlist(groupedStreams, { public: true })
const filepath = 'index.region.m3u' const filepath = 'index.region.m3u'
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }))
}
getStreamRegions(stream: Stream) {
let streamRegions = new Collection()
stream.broadcastArea.forEach(broadcastAreaCode => {
const [type, code] = broadcastAreaCode.split('/')
switch (type) {
case 'r':
const groupedRegions = this.regions.keyBy((region: Region) => region.code)
streamRegions.add(groupedRegions.get(code))
break
case 's':
const [countryCode] = code.split('-')
const subdivisionRegions = this.regions.filter((region: Region) =>
region.countries.includes(countryCode)
)
streamRegions = streamRegions.concat(subdivisionRegions)
break
case 'c':
const countryRegions = this.regions.filter((region: Region) =>
region.countries.includes(code)
)
streamRegions = streamRegions.concat(countryRegions)
break
}
})
return streamRegions
} }
} }

View file

@ -18,35 +18,40 @@ export class LanguagesGenerator implements Generator {
async generate(): Promise<void> { async generate(): Promise<void> {
const streams = this.streams const streams = this.streams
.orderBy(stream => stream.getTitle()) .orderBy((stream: Stream) => stream.getTitle())
.filter(stream => stream.isSFW()) .filter((stream: Stream) => stream.isSFW())
let languages = new Collection() let languages = new Collection()
streams.forEach((stream: Stream) => { streams.forEach((stream: Stream) => {
languages = languages.concat(stream.languages) languages = languages.concat(stream.getLanguages())
}) })
languages languages
.filter(Boolean)
.uniqBy((language: Language) => language.code) .uniqBy((language: Language) => language.code)
.orderBy((language: Language) => language.name) .orderBy((language: Language) => language.name)
.forEach(async (language: Language) => { .forEach(async (language: Language) => {
const languageStreams = streams.filter(stream => stream.hasLanguage(language)) const languageStreams = streams.filter((stream: Stream) => stream.hasLanguage(language))
if (languageStreams.isEmpty()) return if (languageStreams.isEmpty()) return
const playlist = new Playlist(languageStreams, { public: true }) const playlist = new Playlist(languageStreams, { public: true })
const filepath = `languages/${language.code}.m3u` const filepath = `languages/${language.code}.m3u`
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(
JSON.stringify({ type: 'language', filepath, count: playlist.streams.count() })
)
}) })
const undefinedStreams = streams.filter(stream => stream.noLanguages()) const undefinedStreams = streams.filter((stream: Stream) => !stream.hasLanguages())
if (undefinedStreams.isEmpty()) return if (undefinedStreams.isEmpty()) return
const playlist = new Playlist(undefinedStreams, { public: true }) const playlist = new Playlist(undefinedStreams, { public: true })
const filepath = 'languages/undefined.m3u' const filepath = 'languages/undefined.m3u'
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(
JSON.stringify({ type: 'language', filepath, count: playlist.streams.count() })
)
} }
} }

View file

@ -1,53 +1,61 @@
import { Generator } from './generator' import { Generator } from './generator'
import { Collection, Storage, Logger } from '@freearhey/core' import { Collection, Storage, Logger } from '@freearhey/core'
import { Playlist, Subdivision, Region } from '../models' import { Playlist, Region, Stream } from '../models'
import { PUBLIC_DIR } from '../constants' import { PUBLIC_DIR } from '../constants'
type RegionsGeneratorProps = { type RegionsGeneratorProps = {
streams: Collection streams: Collection
regions: Collection regions: Collection
subdivisions: Collection
logger: Logger logger: Logger
} }
export class RegionsGenerator implements Generator { export class RegionsGenerator implements Generator {
streams: Collection streams: Collection
regions: Collection regions: Collection
subdivisions: Collection
storage: Storage storage: Storage
logger: Logger logger: Logger
constructor({ streams, regions, subdivisions, logger }: RegionsGeneratorProps) { constructor({ streams, regions, logger }: RegionsGeneratorProps) {
this.streams = streams this.streams = streams
this.regions = regions this.regions = regions
this.subdivisions = subdivisions
this.storage = new Storage(PUBLIC_DIR) this.storage = new Storage(PUBLIC_DIR)
this.logger = logger this.logger = logger
} }
async generate(): Promise<void> { async generate(): Promise<void> {
const streams = this.streams const streams = this.streams
.orderBy(stream => stream.getTitle()) .orderBy((stream: Stream) => stream.getTitle())
.filter(stream => stream.isSFW()) .filter((stream: Stream) => stream.isSFW())
this.regions.forEach(async (region: Region) => { this.regions.forEach(async (region: Region) => {
if (region.code === 'INT') return if (region.isWorldwide()) return
const regionSubdivisionsCodes = this.subdivisions const regionStreams = streams.filter((stream: Stream) => stream.isBroadcastInRegion(region))
.filter((subdivision: Subdivision) => region.countries.indexOf(subdivision.country) > -1)
.map((subdivision: Subdivision) => `s/${subdivision.code}`)
const regionCodes = region.countries
.map((code: string) => `c/${code}`)
.concat(regionSubdivisionsCodes)
.add(`r/${region.code}`)
const regionStreams = streams.filter(stream => stream.broadcastArea.intersects(regionCodes))
const playlist = new Playlist(regionStreams, { public: true }) const playlist = new Playlist(regionStreams, { public: true })
const filepath = `regions/${region.code.toLowerCase()}.m3u` const filepath = `regions/${region.code.toLowerCase()}.m3u`
await this.storage.save(filepath, playlist.toString()) await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() })) this.logger.info(
JSON.stringify({ type: 'region', filepath, count: playlist.streams.count() })
)
}) })
const internationalStreams = streams.filter((stream: Stream) => stream.isInternational())
const internationalPlaylist = new Playlist(internationalStreams, { public: true })
const internationalFilepath = 'regions/int.m3u'
await this.storage.save(internationalFilepath, internationalPlaylist.toString())
this.logger.info(
JSON.stringify({
type: 'region',
filepath: internationalFilepath,
count: internationalPlaylist.streams.count()
})
)
const undefinedStreams = streams.filter((stream: Stream) => !stream.hasBroadcastArea())
const playlist = new Playlist(undefinedStreams, { public: true })
const filepath = 'regions/undefined.m3u'
await this.storage.save(filepath, playlist.toString())
this.logger.info(JSON.stringify({ type: 'region', filepath, count: playlist.streams.count() }))
} }
} }

View file

@ -5,13 +5,13 @@ type BlockedProps = {
} }
export class Blocked { export class Blocked {
channel: string channelId: string
reason: string reason: string
ref: string ref: string
constructor({ ref, reason, channel }: BlockedProps) { constructor(data: BlockedProps) {
this.channel = channel this.channelId = data.channel
this.reason = reason this.reason = data.reason
this.ref = ref this.ref = data.ref
} }
} }

View file

@ -0,0 +1,11 @@
type BroadcastAreaProps = {
code: string
}
export class BroadcastArea {
code: string
constructor(data: BroadcastAreaProps) {
this.code = data.code
}
}

View file

@ -1,4 +1,4 @@
type CategoryProps = { type CategoryData = {
id: string id: string
name: string name: string
} }
@ -7,8 +7,8 @@ export class Category {
id: string id: string
name: string name: string
constructor({ id, name }: CategoryProps) { constructor(data: CategoryData) {
this.id = id this.id = data.id
this.name = name this.name = data.name
} }
} }

View file

@ -1,17 +1,16 @@
import { Collection } from '@freearhey/core' import { Collection, Dictionary } from '@freearhey/core'
import { Category, Country, Subdivision } from './index'
type ChannelProps = { type ChannelData = {
id: string id: string
name: string name: string
alt_names: string[] alt_names: string[]
network: string network: string
owners: string[] owners: Collection
country: string country: string
subdivision: string subdivision: string
city: string city: string
broadcast_area: string[] categories: Collection
languages: string[]
categories: string[]
is_nsfw: boolean is_nsfw: boolean
launched: string launched: string
closed: string closed: string
@ -24,56 +23,86 @@ export class Channel {
id: string id: string
name: string name: string
altNames: Collection altNames: Collection
network: string network?: string
owners: Collection owners: Collection
country: string countryCode: string
subdivision: string country?: Country
city: string subdivisionCode?: string
broadcastArea: Collection subdivision?: Subdivision
languages: Collection cityName?: string
categories: Collection categoryIds: Collection
categories?: Collection
isNSFW: boolean isNSFW: boolean
launched: string launched?: string
closed: string closed?: string
replacedBy: string replacedBy?: string
website: string website?: string
logo: string logo: string
constructor({ constructor(data: ChannelData) {
id, this.id = data.id
name, this.name = data.name
alt_names, this.altNames = new Collection(data.alt_names)
network, this.network = data.network || undefined
owners, this.owners = new Collection(data.owners)
country, this.countryCode = data.country
subdivision, this.subdivisionCode = data.subdivision || undefined
city, this.cityName = data.city || undefined
broadcast_area, this.categoryIds = new Collection(data.categories)
languages, this.isNSFW = data.is_nsfw
categories, this.launched = data.launched || undefined
is_nsfw, this.closed = data.closed || undefined
launched, this.replacedBy = data.replaced_by || undefined
closed, this.website = data.website || undefined
replaced_by, this.logo = data.logo
website, }
logo
}: ChannelProps) { withSubdivision(subdivisionsGroupedByCode: Dictionary): this {
this.id = id if (!this.subdivisionCode) return this
this.name = name
this.altNames = new Collection(alt_names) this.subdivision = subdivisionsGroupedByCode.get(this.subdivisionCode)
this.network = network
this.owners = new Collection(owners) return this
this.country = country }
this.subdivision = subdivision
this.city = city withCountry(countriesGroupedByCode: Dictionary): this {
this.broadcastArea = new Collection(broadcast_area) this.country = countriesGroupedByCode.get(this.countryCode)
this.languages = new Collection(languages)
this.categories = new Collection(categories) return this
this.isNSFW = is_nsfw }
this.launched = launched
this.closed = closed withCategories(groupedCategories: Dictionary): this {
this.replacedBy = replaced_by this.categories = this.categoryIds
this.website = website .map((id: string) => groupedCategories.get(id))
this.logo = logo .filter(Boolean)
return this
}
getCountry(): Country | undefined {
return this.country
}
getSubdivision(): Subdivision | undefined {
return this.subdivision
}
getCategories(): Collection {
return this.categories || new Collection()
}
hasCategories(): boolean {
return !!this.categories && this.categories.notEmpty()
}
hasCategory(category: Category): boolean {
return (
!!this.categories &&
this.categories.includes((_category: Category) => _category.id === category.id)
)
}
isSFW(): boolean {
return this.isNSFW === false
} }
} }

View file

@ -1,20 +1,58 @@
type CountryProps = { import { Collection, Dictionary } from '@freearhey/core'
import { Region, Language } from '.'
type CountryData = {
code: string code: string
name: string name: string
languages: string[] lang: string
flag: string flag: string
} }
export class Country { export class Country {
code: string code: string
name: string name: string
languages: string[]
flag: string flag: string
languageCode: string
language?: Language
subdivisions?: Collection
regions?: Collection
constructor({ code, name, languages, flag }: CountryProps) { constructor(data: CountryData) {
this.code = code this.code = data.code
this.name = name this.name = data.name
this.languages = languages this.flag = data.flag
this.flag = flag this.languageCode = data.lang
}
withSubdivisions(subdivisionsGroupedByCountryCode: Dictionary): this {
this.subdivisions = subdivisionsGroupedByCountryCode.get(this.code) || new Collection()
return this
}
withRegions(regions: Collection): this {
this.regions = regions.filter(
(region: Region) => region.code !== 'INT' && region.includesCountryCode(this.code)
)
return this
}
withLanguage(languagesGroupedByCode: Dictionary): this {
this.language = languagesGroupedByCode.get(this.languageCode)
return this
}
getLanguage(): Language | undefined {
return this.language
}
getRegions(): Collection {
return this.regions || new Collection()
}
getSubdivisions(): Collection {
return this.subdivisions || new Collection()
} }
} }

200
scripts/models/feed.ts Normal file
View file

@ -0,0 +1,200 @@
import { Collection, Dictionary } from '@freearhey/core'
import { Country, Language, Region, Channel, Subdivision } from './index'
type FeedData = {
channel: string
id: string
name: string
is_main: boolean
broadcast_area: Collection
languages: Collection
timezones: Collection
video_format: string
}
export class Feed {
channelId: string
channel?: Channel
id: string
name: string
isMain: boolean
broadcastAreaCodes: Collection
broadcastCountryCodes: Collection
broadcastCountries?: Collection
broadcastRegionCodes: Collection
broadcastRegions?: Collection
broadcastSubdivisionCodes: Collection
broadcastSubdivisions?: Collection
languageCodes: Collection
languages?: Collection
timezoneIds: Collection
timezones?: Collection
videoFormat: string
constructor(data: FeedData) {
this.channelId = data.channel
this.id = data.id
this.name = data.name
this.isMain = data.is_main
this.broadcastAreaCodes = new Collection(data.broadcast_area)
this.languageCodes = new Collection(data.languages)
this.timezoneIds = new Collection(data.timezones)
this.videoFormat = data.video_format
this.broadcastCountryCodes = new Collection()
this.broadcastRegionCodes = new Collection()
this.broadcastSubdivisionCodes = new Collection()
this.broadcastAreaCodes.forEach((areaCode: string) => {
const [type, code] = areaCode.split('/')
switch (type) {
case 'c':
this.broadcastCountryCodes.add(code)
break
case 'r':
this.broadcastRegionCodes.add(code)
break
case 's':
this.broadcastSubdivisionCodes.add(code)
break
}
})
}
withChannel(channelsGroupedById: Dictionary): this {
this.channel = channelsGroupedById.get(this.channelId)
return this
}
withLanguages(languagesGroupedByCode: Dictionary): this {
this.languages = this.languageCodes
.map((code: string) => languagesGroupedByCode.get(code))
.filter(Boolean)
return this
}
withTimezones(timezonesGroupedById: Dictionary): this {
this.timezones = this.timezoneIds
.map((id: string) => timezonesGroupedById.get(id))
.filter(Boolean)
return this
}
withBroadcastSubdivisions(subdivisionsGroupedByCode: Dictionary): this {
this.broadcastSubdivisions = this.broadcastSubdivisionCodes.map((code: string) =>
subdivisionsGroupedByCode.get(code)
)
return this
}
withBroadcastCountries(
countriesGroupedByCode: Dictionary,
regionsGroupedByCode: Dictionary,
subdivisionsGroupedByCode: Dictionary
): this {
let broadcastCountries = new Collection()
if (this.isInternational()) {
this.broadcastCountries = broadcastCountries
return this
}
this.broadcastCountryCodes.forEach((code: string) => {
broadcastCountries.add(countriesGroupedByCode.get(code))
})
this.broadcastRegionCodes.forEach((code: string) => {
const region: Region = regionsGroupedByCode.get(code)
if (region) {
region.countryCodes.forEach((countryCode: string) => {
broadcastCountries.add(countriesGroupedByCode.get(countryCode))
})
}
})
this.broadcastSubdivisionCodes.forEach((code: string) => {
const subdivision: Subdivision = subdivisionsGroupedByCode.get(code)
if (subdivision) {
broadcastCountries.add(countriesGroupedByCode.get(subdivision.countryCode))
}
})
this.broadcastCountries = broadcastCountries.uniq().filter(Boolean)
return this
}
withBroadcastRegions(regions: Collection): this {
if (!this.broadcastCountries) return this
const countriesCodes = this.broadcastCountries.map((country: Country) => country.code)
this.broadcastRegions = regions.filter((region: Region) => {
if (region.code === 'INT') return false
return region.countryCodes.intersects(countriesCodes)
})
return this
}
hasBroadcastArea(): boolean {
return (
this.isInternational() || (!!this.broadcastCountries && this.broadcastCountries.notEmpty())
)
}
getBroadcastCountries(): Collection {
return this.broadcastCountries || new Collection()
}
getBroadcastRegions(): Collection {
return this.broadcastRegions || new Collection()
}
getTimezones(): Collection {
return this.timezones || new Collection()
}
getLanguages(): Collection {
return this.languages || new Collection()
}
hasLanguages(): boolean {
return !!this.languages && this.languages.notEmpty()
}
hasLanguage(language: Language): boolean {
return (
!!this.languages &&
this.languages.includes((_language: Language) => _language.code === language.code)
)
}
isInternational(): boolean {
return this.broadcastAreaCodes.includes('r/INT')
}
isBroadcastInSubdivision(subdivision: Subdivision): boolean {
if (this.isInternational()) return false
return this.broadcastSubdivisionCodes.includes(subdivision.code)
}
isBroadcastInCountry(country: Country): boolean {
if (this.isInternational()) return false
return this.getBroadcastCountries().includes(
(_country: Country) => _country.code === country.code
)
}
isBroadcastInRegion(region: Region): boolean {
if (this.isInternational()) return false
return this.getBroadcastRegions().includes((_region: Region) => _region.code === region.code)
}
}

View file

@ -8,3 +8,6 @@ export * from './language'
export * from './country' export * from './country'
export * from './region' export * from './region'
export * from './subdivision' export * from './subdivision'
export * from './feed'
export * from './broadcastArea'
export * from './timezone'

View file

@ -1,4 +1,4 @@
type LanguageProps = { type LanguageData = {
code: string code: string
name: string name: string
} }
@ -7,8 +7,8 @@ export class Language {
code: string code: string
name: string name: string
constructor({ code, name }: LanguageProps) { constructor(data: LanguageData) {
this.code = code this.code = data.code
this.name = name this.name = data.name
} }
} }

View file

@ -1,6 +1,7 @@
import { Collection } from '@freearhey/core' import { Collection, Dictionary } from '@freearhey/core'
import { Subdivision } from '.'
type RegionProps = { type RegionData = {
code: string code: string
name: string name: string
countries: string[] countries: string[]
@ -9,11 +10,43 @@ type RegionProps = {
export class Region { export class Region {
code: string code: string
name: string name: string
countries: Collection countryCodes: Collection
countries?: Collection
subdivisions?: Collection
constructor({ code, name, countries }: RegionProps) { constructor(data: RegionData) {
this.code = code this.code = data.code
this.name = name this.name = data.name
this.countries = new Collection(countries) this.countryCodes = new Collection(data.countries)
}
withCountries(countriesGroupedByCode: Dictionary): this {
this.countries = this.countryCodes.map((code: string) => countriesGroupedByCode.get(code))
return this
}
withSubdivisions(subdivisions: Collection): this {
this.subdivisions = subdivisions.filter(
(subdivision: Subdivision) => this.countryCodes.indexOf(subdivision.countryCode) > -1
)
return this
}
getSubdivisions(): Collection {
return this.subdivisions || new Collection()
}
getCountries(): Collection {
return this.countries || new Collection()
}
includesCountryCode(code: string): boolean {
return this.countryCodes.includes((countryCode: string) => countryCode === code)
}
isWorldwide(): boolean {
return this.code === 'INT'
} }
} }

View file

@ -1,64 +1,193 @@
import { URL, Collection } from '@freearhey/core' import { URL, Collection, Dictionary } from '@freearhey/core'
import { Category, Language } from './index' import { Feed, Channel, Category, Region, Subdivision, Country, Language } from './index'
import parser from 'iptv-playlist-parser'
type StreamProps = {
name: string
url: string
filepath: string
line: number
channel?: string
httpReferrer?: string
httpUserAgent?: string
label?: string
quality?: string
}
export class Stream { export class Stream {
channel: string
filepath: string
line: number
httpReferrer: string
label: string
name: string name: string
quality: string
url: string url: string
httpUserAgent: string id?: string
logo: string
broadcastArea: Collection
categories: Collection
languages: Collection
isNSFW: boolean
groupTitle: string groupTitle: string
channelId?: string
channel?: Channel
feedId?: string
feed?: Feed
filepath?: string
line: number
label?: string
verticalResolution?: number
isInterlaced?: boolean
httpReferrer?: string
httpUserAgent?: string
removed: boolean = false removed: boolean = false
constructor({ constructor(data: parser.PlaylistItem) {
channel, if (!data.name) throw new Error('"name" property is required')
filepath, if (!data.url) throw new Error('"url" property is required')
line,
httpReferrer, const [channelId, feedId] = data.tvg.id.split('@')
label, const { name, label, quality } = parseTitle(data.name)
name, const { verticalResolution, isInterlaced } = parseQuality(quality)
quality,
url, this.id = data.tvg.id || undefined
httpUserAgent this.feedId = feedId || undefined
}: StreamProps) { this.channelId = channelId || undefined
this.channel = channel || '' this.line = data.line
this.filepath = filepath this.label = label || undefined
this.line = line
this.httpReferrer = httpReferrer || ''
this.label = label || ''
this.name = name this.name = name
this.quality = quality || '' this.verticalResolution = verticalResolution || undefined
this.url = url this.isInterlaced = isInterlaced || undefined
this.httpUserAgent = httpUserAgent || '' this.url = data.url
this.logo = '' this.httpReferrer = data.http.referrer || undefined
this.broadcastArea = new Collection() this.httpUserAgent = data.http['user-agent'] || undefined
this.categories = new Collection()
this.languages = new Collection()
this.isNSFW = false
this.groupTitle = 'Undefined' this.groupTitle = 'Undefined'
} }
withChannel(channelsGroupedById: Dictionary): this {
if (!this.channelId) return this
this.channel = channelsGroupedById.get(this.channelId)
return this
}
withFeed(feedsGroupedByChannelId: Dictionary): this {
if (!this.channelId) return this
const channelFeeds = feedsGroupedByChannelId.get(this.channelId) || []
if (this.feedId) this.feed = channelFeeds.find((feed: Feed) => feed.id === this.feedId)
if (!this.feedId && !this.feed) this.feed = channelFeeds.find((feed: Feed) => feed.isMain)
return this
}
setId(id: string): this {
this.id = id
return this
}
setChannelId(channelId: string): this {
this.channelId = channelId
return this
}
setFeedId(feedId: string | undefined): this {
this.feedId = feedId
return this
}
setLabel(label: string): this {
this.label = label
return this
}
setQuality(quality: string): this {
const { verticalResolution, isInterlaced } = parseQuality(quality)
this.verticalResolution = verticalResolution || undefined
this.isInterlaced = isInterlaced || undefined
return this
}
setHttpUserAgent(httpUserAgent: string): this {
this.httpUserAgent = httpUserAgent
return this
}
setHttpReferrer(httpReferrer: string): this {
this.httpReferrer = httpReferrer
return this
}
setFilepath(filepath: string): this {
this.filepath = filepath
return this
}
updateFilepath(): this {
if (!this.channel) return this
this.filepath = `${this.channel.countryCode.toLowerCase()}.m3u`
return this
}
getChannelId(): string {
return this.channelId || ''
}
getFeedId(): string {
if (this.feedId) return this.feedId
if (this.feed) return this.feed.id
return ''
}
getFilepath(): string {
return this.filepath || ''
}
getHttpReferrer(): string {
return this.httpReferrer || ''
}
getHttpUserAgent(): string {
return this.httpUserAgent || ''
}
getQuality(): string {
if (!this.verticalResolution) return ''
let quality = this.verticalResolution.toString()
if (this.isInterlaced) quality += 'i'
else quality += 'p'
return quality
}
hasId(): boolean {
return !!this.id
}
hasQuality(): boolean {
return !!this.verticalResolution
}
getVerticalResolution(): number {
if (!this.hasQuality()) return 0
return parseInt(this.getQuality().replace(/p|i/, ''))
}
updateName(): this {
if (!this.channel) return this
this.name = this.channel.name
if (this.feed && !this.feed.isMain) {
this.name += ` ${this.feed.name}`
}
return this
}
updateId(): this {
if (!this.channel) return this
if (this.feed) {
this.id = `${this.channel.id}@${this.feed.id}`
} else {
this.id = this.channel.id
}
return this
}
normalizeURL() { normalizeURL() {
const url = new URL(this.url) const url = new URL(this.url)
@ -81,43 +210,82 @@ export class Stream {
return !!this.channel return !!this.channel
} }
hasCategories(): boolean { getBroadcastRegions(): Collection {
return this.categories.notEmpty() return this.feed ? this.feed.getBroadcastRegions() : new Collection()
} }
noCategories(): boolean { getBroadcastCountries(): Collection {
return this.categories.isEmpty() return this.feed ? this.feed.getBroadcastCountries() : new Collection()
} }
hasCategory(category: Category): boolean { hasBroadcastArea(): boolean {
return this.categories.includes((_category: Category) => _category.id === category.id) return this.feed ? this.feed.hasBroadcastArea() : false
}
noLanguages(): boolean {
return this.languages.isEmpty()
}
hasLanguage(language: Language): boolean {
return this.languages.includes((_language: Language) => _language.code === language.code)
}
noBroadcastArea(): boolean {
return this.broadcastArea.isEmpty()
}
isInternational(): boolean {
return this.broadcastArea.includes('r/INT')
} }
isSFW(): boolean { isSFW(): boolean {
return this.isNSFW === false return this.channel ? this.channel.isSFW() : true
}
hasCategories(): boolean {
return this.channel ? this.channel.hasCategories() : false
}
hasCategory(category: Category): boolean {
return this.channel ? this.channel.hasCategory(category) : false
}
getCategoryNames(): string[] {
return this.getCategories()
.map((category: Category) => category.name)
.sort()
.all()
}
getCategories(): Collection {
return this.channel ? this.channel.getCategories() : new Collection()
}
getLanguages(): Collection {
return this.feed ? this.feed.getLanguages() : new Collection()
}
hasLanguages() {
return this.feed ? this.feed.hasLanguages() : false
}
hasLanguage(language: Language) {
return this.feed ? this.feed.hasLanguage(language) : false
}
getBroadcastAreaCodes(): Collection {
return this.feed ? this.feed.broadcastAreaCodes : new Collection()
}
isBroadcastInSubdivision(subdivision: Subdivision): boolean {
return this.feed ? this.feed.isBroadcastInSubdivision(subdivision) : false
}
isBroadcastInCountry(country: Country): boolean {
return this.feed ? this.feed.isBroadcastInCountry(country) : false
}
isBroadcastInRegion(region: Region): boolean {
return this.feed ? this.feed.isBroadcastInRegion(region) : false
}
isInternational(): boolean {
return this.feed ? this.feed.isInternational() : false
}
getLogo(): string {
return this?.channel?.logo || ''
} }
getTitle(): string { getTitle(): string {
let title = `${this.name}` let title = `${this.name}`
if (this.quality) { if (this.getQuality()) {
title += ` (${this.quality})` title += ` (${this.getQuality()})`
} }
if (this.label) { if (this.label) {
@ -127,15 +295,26 @@ export class Stream {
return title return title
} }
getLabel(): string {
return this.label || ''
}
getId(): string {
return this.id || ''
}
data() { data() {
return { return {
id: this.id,
channel: this.channel, channel: this.channel,
feed: this.feed,
filepath: this.filepath, filepath: this.filepath,
httpReferrer: this.httpReferrer,
label: this.label, label: this.label,
name: this.name, name: this.name,
quality: this.quality, verticalResolution: this.verticalResolution,
isInterlaced: this.isInterlaced,
url: this.url, url: this.url,
httpReferrer: this.httpReferrer,
httpUserAgent: this.httpUserAgent, httpUserAgent: this.httpUserAgent,
line: this.line line: this.line
} }
@ -143,18 +322,20 @@ export class Stream {
toJSON() { toJSON() {
return { return {
channel: this.channel || null, channel: this.channelId || null,
feed: this.feedId || null,
url: this.url, url: this.url,
referrer: this.httpReferrer || null, referrer: this.httpReferrer || null,
user_agent: this.httpUserAgent || null user_agent: this.httpUserAgent || null,
quality: this.getQuality() || null
} }
} }
toString(options: { public: boolean }) { toString(options: { public: boolean }) {
let output = `#EXTINF:-1 tvg-id="${this.channel}"` let output = `#EXTINF:-1 tvg-id="${this.getId()}"`
if (options.public) { if (options.public) {
output += ` tvg-logo="${this.logo}" group-title="${this.groupTitle}"` output += ` tvg-logo="${this.getLogo()}" group-title="${this.groupTitle}"`
} }
if (this.httpReferrer) { if (this.httpReferrer) {
@ -180,3 +361,29 @@ export class Stream {
return output return output
} }
} }
function parseTitle(title: string): {
name: string
label: string
quality: string
} {
const [, label] = title.match(/ \[(.*)\]$/) || [null, '']
title = title.replace(new RegExp(` \\[${escapeRegExp(label)}\\]$`), '')
const [, quality] = title.match(/ \(([0-9]+p)\)$/) || [null, '']
title = title.replace(new RegExp(` \\(${quality}\\)$`), '')
return { name: title, label, quality }
}
function escapeRegExp(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
}
function parseQuality(quality: string): { verticalResolution: number; isInterlaced: boolean } {
let [, verticalResolutionString] = quality.match(/^(\d+)/) || [null, undefined]
const isInterlaced = /i$/i.test(quality)
let verticalResolution = 0
if (verticalResolutionString) verticalResolution = parseInt(verticalResolutionString)
return { verticalResolution, isInterlaced }
}

View file

@ -1,4 +1,7 @@
type SubdivisionProps = { import { Dictionary } from '@freearhey/core'
import { Country } from '.'
type SubdivisionData = {
code: string code: string
name: string name: string
country: string country: string
@ -7,11 +10,18 @@ type SubdivisionProps = {
export class Subdivision { export class Subdivision {
code: string code: string
name: string name: string
country: string countryCode: string
country?: Country
constructor({ code, name, country }: SubdivisionProps) { constructor(data: SubdivisionData) {
this.code = code this.code = data.code
this.name = name this.name = data.name
this.country = country this.countryCode = data.country
}
withCountry(countriesGroupedByCode: Dictionary): this {
this.country = countriesGroupedByCode.get(this.countryCode)
return this
} }
} }

View file

@ -0,0 +1,30 @@
import { Collection, Dictionary } from '@freearhey/core'
type TimezoneData = {
id: string
utc_offset: string
countries: string[]
}
export class Timezone {
id: string
utcOffset: string
countryCodes: Collection
countries?: Collection
constructor(data: TimezoneData) {
this.id = data.id
this.utcOffset = data.utc_offset
this.countryCodes = new Collection(data.countries)
}
withCountries(countriesGroupedByCode: Dictionary): this {
this.countries = this.countryCodes.map((code: string) => countriesGroupedByCode.get(code))
return this
}
getCountries(): Collection {
return this.countries || new Collection()
}
}

View file

@ -11,6 +11,7 @@ export class CategoryTable implements Table {
const dataStorage = new Storage(DATA_DIR) const dataStorage = new Storage(DATA_DIR)
const categoriesContent = await dataStorage.json('categories.json') const categoriesContent = await dataStorage.json('categories.json')
const categories = new Collection(categoriesContent).map(data => new Category(data)) const categories = new Collection(categoriesContent).map(data => new Category(data))
const categoriesGroupedById = categories.keyBy((category: Category) => category.id)
const parser = new LogParser() const parser = new LogParser()
const logsStorage = new Storage(LOGS_DIR) const logsStorage = new Storage(LOGS_DIR)
@ -19,13 +20,12 @@ export class CategoryTable implements Table {
let data = new Collection() let data = new Collection()
parser parser
.parse(generatorsLog) .parse(generatorsLog)
.filter((logItem: LogItem) => logItem.filepath.includes('categories/')) .filter((logItem: LogItem) => logItem.type === 'category')
.forEach((logItem: LogItem) => { .forEach((logItem: LogItem) => {
const file = new File(logItem.filepath) const file = new File(logItem.filepath)
const categoryId = file.name() const categoryId = file.name()
const category: Category = categories.first( const category: Category = categoriesGroupedById.get(categoryId)
(category: Category) => category.id === categoryId
)
data.add([ data.add([
category ? category.name : 'ZZ', category ? category.name : 'ZZ',
category ? category.name : 'Undefined', category ? category.name : 'Undefined',

View file

@ -12,34 +12,31 @@ export class CountryTable implements Table {
const countriesContent = await dataStorage.json('countries.json') const countriesContent = await dataStorage.json('countries.json')
const countries = new Collection(countriesContent).map(data => new Country(data)) const countries = new Collection(countriesContent).map(data => new Country(data))
const countriesGroupedByCode = countries.keyBy((country: Country) => country.code)
const subdivisionsContent = await dataStorage.json('subdivisions.json') const subdivisionsContent = await dataStorage.json('subdivisions.json')
const subdivisions = new Collection(subdivisionsContent).map(data => new Subdivision(data)) const subdivisions = new Collection(subdivisionsContent).map(data => new Subdivision(data))
const subdivisionsGroupedByCode = subdivisions.keyBy(
(subdivision: Subdivision) => subdivision.code
)
const parser = new LogParser() const parser = new LogParser()
const logsStorage = new Storage(LOGS_DIR) const logsStorage = new Storage(LOGS_DIR)
const generatorsLog = await logsStorage.load('generators.log') const generatorsLog = await logsStorage.load('generators.log')
const parsed = parser.parse(generatorsLog)
let data = new Collection() let data = new Collection()
parser
.parse(generatorsLog) parsed
.filter( .filter((logItem: LogItem) => logItem.type === 'subdivision')
(logItem: LogItem) =>
logItem.filepath.includes('countries/') || logItem.filepath.includes('subdivisions/')
)
.forEach((logItem: LogItem) => { .forEach((logItem: LogItem) => {
const file = new File(logItem.filepath) const file = new File(logItem.filepath)
const code = file.name().toUpperCase() const code = file.name().toUpperCase()
const [countryCode, subdivisionCode] = code.split('-') || ['', ''] const [countryCode, subdivisionCode] = code.split('-') || ['', '']
const country = countriesGroupedByCode.get(countryCode)
if (subdivisionCode) { if (country && subdivisionCode) {
const subdivision = subdivisions.first( const subdivision = subdivisionsGroupedByCode.get(code)
(subdivision: Subdivision) => subdivision.code === code
)
if (subdivision) { if (subdivision) {
const country = countries.first(
(country: Country) => country.code === subdivision.country
)
data.add([ data.add([
`${country.name}/${subdivision.name}`, `${country.name}/${subdivision.name}`,
`&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${subdivision.name}`, `&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${subdivision.name}`,
@ -47,18 +44,28 @@ export class CountryTable implements Table {
`<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>` `<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>`
]) ])
} }
} else if (countryCode === 'INT') { }
})
parsed
.filter((logItem: LogItem) => logItem.type === 'country')
.forEach((logItem: LogItem) => {
const file = new File(logItem.filepath)
const code = file.name().toUpperCase()
const [countryCode] = code.split('-') || ['', '']
const country = countriesGroupedByCode.get(countryCode)
if (country) {
data.add([ data.add([
'ZZ', country.name,
'🌍 International', `${country.flag} ${country.name}`,
logItem.count, logItem.count,
`<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>` `<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>`
]) ])
} else { } else {
const country = countries.first((country: Country) => country.code === countryCode)
data.add([ data.add([
country.name, 'ZZ',
`${country.flag} ${country.name}`, 'Undefined',
logItem.count, logItem.count,
`<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>` `<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>`
]) ])

View file

@ -11,6 +11,7 @@ export class LanguageTable implements Table {
const dataStorage = new Storage(DATA_DIR) const dataStorage = new Storage(DATA_DIR)
const languagesContent = await dataStorage.json('languages.json') const languagesContent = await dataStorage.json('languages.json')
const languages = new Collection(languagesContent).map(data => new Language(data)) const languages = new Collection(languagesContent).map(data => new Language(data))
const languagesGroupedByCode = languages.keyBy((language: Language) => language.code)
const parser = new LogParser() const parser = new LogParser()
const logsStorage = new Storage(LOGS_DIR) const logsStorage = new Storage(LOGS_DIR)
@ -19,13 +20,11 @@ export class LanguageTable implements Table {
let data = new Collection() let data = new Collection()
parser parser
.parse(generatorsLog) .parse(generatorsLog)
.filter((logItem: LogItem) => logItem.filepath.includes('languages/')) .filter((logItem: LogItem) => logItem.type === 'language')
.forEach((logItem: LogItem) => { .forEach((logItem: LogItem) => {
const file = new File(logItem.filepath) const file = new File(logItem.filepath)
const languageCode = file.name() const languageCode = file.name()
const language: Language = languages.first( const language: Language = languagesGroupedByCode.get(languageCode)
(language: Language) => language.code === languageCode
)
data.add([ data.add([
language ? language.name : 'ZZ', language ? language.name : 'ZZ',

View file

@ -11,6 +11,7 @@ export class RegionTable implements Table {
const dataStorage = new Storage(DATA_DIR) const dataStorage = new Storage(DATA_DIR)
const regionsContent = await dataStorage.json('regions.json') const regionsContent = await dataStorage.json('regions.json')
const regions = new Collection(regionsContent).map(data => new Region(data)) const regions = new Collection(regionsContent).map(data => new Region(data))
const regionsGroupedByCode = regions.keyBy((region: Region) => region.code)
const parser = new LogParser() const parser = new LogParser()
const logsStorage = new Storage(LOGS_DIR) const logsStorage = new Storage(LOGS_DIR)
@ -19,22 +20,35 @@ export class RegionTable implements Table {
let data = new Collection() let data = new Collection()
parser parser
.parse(generatorsLog) .parse(generatorsLog)
.filter((logItem: LogItem) => logItem.filepath.includes('regions/')) .filter((logItem: LogItem) => logItem.type === 'region')
.forEach((logItem: LogItem) => { .forEach((logItem: LogItem) => {
const file = new File(logItem.filepath) const file = new File(logItem.filepath)
const regionCode = file.name().toUpperCase() const regionCode = file.name().toUpperCase()
const region: Region = regions.first((region: Region) => region.code === regionCode) const region: Region = regionsGroupedByCode.get(regionCode)
if (region) { if (region) {
data.add([ data.add([
region.name, region.name,
region.name,
logItem.count,
`<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>`
])
} else {
data.add([
'ZZZ',
'Undefined',
logItem.count, logItem.count,
`<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>` `<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>`
]) ])
} }
}) })
data = data.orderBy(item => item[0]) data = data
.orderBy(item => item[0])
.map(item => {
item.shift()
return item
})
const table = new HTMLTable(data.all(), [ const table = new HTMLTable(data.all(), [
{ name: 'Region', align: 'left' }, { name: 'Region', align: 'left' },

View file

@ -1,3 +1,5 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="AndorraTV.ad",ATV (720p) #EXTINF:-1 tvg-id="AndorraTV.ad",ATV (720p)
https://videos.rtva.ad/live/rtva/playlist.m3u8 https://videos.rtva.ad/live/rtva/playlist.m3u8
#EXTINF:-1 tvg-id="AndorraTV.ad@Web",Andorra TV (1080p)
https://live-edge-eu-1.cdn.enetres.net/56495F77FD124FECA75590A906965F2C022/live-3000/index.m3u8

View file

@ -3,9 +3,9 @@
https://vo-live.cdb.cdn.orange.com/Content/Channel/AbuDhabiChannel/HLS/index.m3u8 https://vo-live.cdb.cdn.orange.com/Content/Channel/AbuDhabiChannel/HLS/index.m3u8
#EXTINF:-1 tvg-id="AbuDhabiEmirates.ae",Abu Dhabi Emirates (1080p) #EXTINF:-1 tvg-id="AbuDhabiEmirates.ae",Abu Dhabi Emirates (1080p)
https://vo-live.cdb.cdn.orange.com/Content/Channel/EmiratesChannel/HLS/index.m3u8 https://vo-live.cdb.cdn.orange.com/Content/Channel/EmiratesChannel/HLS/index.m3u8
#EXTINF:-1 tvg-id="AbuDhabiSports1.ae",Abu Dhabi Sports 1 #EXTINF:-1 tvg-id="AbuDhabiSports1.ae",Abu Dhabi Sports 1 (1080p)
https://vo-live-media.cdb.cdn.orange.com/Content/Channel/AbuDhabiSportsChannel1/HLS/index.m3u8 https://vo-live-media.cdb.cdn.orange.com/Content/Channel/AbuDhabiSportsChannel1/HLS/index.m3u8
#EXTINF:-1 tvg-id="AbuDhabiSports2.ae",Abu Dhabi Sports 2 #EXTINF:-1 tvg-id="AbuDhabiSports2.ae",Abu Dhabi Sports 2 (1080p)
https://tr-live-route.adm.tcon.hlit.hvds.tv/Content/Channel/AbuDhabiSportsChannel2/DASH/master.mpd https://tr-live-route.adm.tcon.hlit.hvds.tv/Content/Channel/AbuDhabiSportsChannel2/DASH/master.mpd
#EXTINF:-1 tvg-id="AbuDhabiSports2.ae",Abu Dhabi Sports 2 (1080p) #EXTINF:-1 tvg-id="AbuDhabiSports2.ae",Abu Dhabi Sports 2 (1080p)
https://vo-live.cdb.cdn.orange.com/Content/Channel/AbuDhabiSportsChannel2/HLS/index.m3u8 https://vo-live.cdb.cdn.orange.com/Content/Channel/AbuDhabiSportsChannel2/HLS/index.m3u8
@ -19,6 +19,8 @@ https://mbc1-enc.edgenextcdn.net/out/v1/f5f319206ed740f9a831f2097c2ead23/index.m
https://live.alarabiya.net/alarabiapublish/aswaaq.smil/playlist.m3u8 https://live.alarabiya.net/alarabiapublish/aswaaq.smil/playlist.m3u8
#EXTINF:-1 tvg-id="AlArabiyaPrograms.ae",Al Arabiya Programs (1080p) #EXTINF:-1 tvg-id="AlArabiyaPrograms.ae",Al Arabiya Programs (1080p)
https://d1j4r34gq3qw9y.cloudfront.net/out/v1/96804f3a14864641a21c25e8ca9afb74/index.m3u8 https://d1j4r34gq3qw9y.cloudfront.net/out/v1/96804f3a14864641a21c25e8ca9afb74/index.m3u8
#EXTINF:-1 tvg-id="AlDafrahTV.ae",Al Dafrah TV (720p)
https://rtmp-live-ingest-eu-west-3-universe-dacast-com.akamaized.net/transmuxv1/streams/dbb8ac05-a020-784c-3a95-6ed027941532.m3u8
#EXTINF:-1 tvg-id="AlMashhad.ae",Al Mashhad (1080p) #EXTINF:-1 tvg-id="AlMashhad.ae",Al Mashhad (1080p)
https://bcovlive-a.akamaihd.net/20c3ca22be3c4f03b30afbf3c92cfd14/ap-south-1/6313884884001/playlist.m3u8 https://bcovlive-a.akamaihd.net/20c3ca22be3c4f03b30afbf3c92cfd14/ap-south-1/6313884884001/playlist.m3u8
#EXTINF:-1 tvg-id="AlQamarTV.ae",Al Qamar TV (1080p) #EXTINF:-1 tvg-id="AlQamarTV.ae",Al Qamar TV (1080p)
@ -31,8 +33,6 @@ https://svs.itworkscdn.net/kablatvlive/kabtv1.smil/playlist.m3u8
https://svs.itworkscdn.net/alwoustalive/alwoustatv.smil/playlist.m3u8 https://svs.itworkscdn.net/alwoustalive/alwoustatv.smil/playlist.m3u8
#EXTINF:-1 tvg-id="AlYaumTV.ae",Al Yaum TV (1080p) #EXTINF:-1 tvg-id="AlYaumTV.ae",Al Yaum TV (1080p)
https://iko-live.akamaized.net/AlyuamTV/master.m3u8 https://iko-live.akamaized.net/AlyuamTV/master.m3u8
#EXTINF:-1 tvg-id="AlYaumTV.ae",Al Yaum TV (720p)
https://alyaum-tv.akamaized.net/hls/alyaum-tv.m3u8
#EXTINF:-1 tvg-id="Alarabiya.ae",Alarabiya (1080p) #EXTINF:-1 tvg-id="Alarabiya.ae",Alarabiya (1080p)
https://d35j504z0x2vu2.cloudfront.net/v1/master/0bc8e8376bd8417a1b6761138aa41c26c7309312/al-arabiya/playlist.m3u8 https://d35j504z0x2vu2.cloudfront.net/v1/master/0bc8e8376bd8417a1b6761138aa41c26c7309312/al-arabiya/playlist.m3u8
#EXTINF:-1 tvg-id="Alarabiya.ae",Alarabiya (1080p) #EXTINF:-1 tvg-id="Alarabiya.ae",Alarabiya (1080p)
@ -63,7 +63,7 @@ https://dmieigthvllta.cdn.mgmlcdn.com/dubaitvht/smil:dubaitv.stream.smil/chunkli
https://dmiffthftl.cdn.mangomolo.com/dubaizaman/smil:dubaizaman.stream.smil/chunklist.m3u8 https://dmiffthftl.cdn.mangomolo.com/dubaizaman/smil:dubaizaman.stream.smil/chunklist.m3u8
#EXTINF:-1 tvg-id="FujairahTV.ae",Fujairah TV (720p) #EXTINF:-1 tvg-id="FujairahTV.ae",Fujairah TV (720p)
https://live.kwikmotion.com/fujairahlive/fujairah.smil/playlist.m3u8 https://live.kwikmotion.com/fujairahlive/fujairah.smil/playlist.m3u8
#EXTINF:-1 tvg-id="JustVogueTV.ae",Just Vogue TV #EXTINF:-1 tvg-id="JustVogueTV.ae",Just Vogue TV (1080p)
https://ip100.radyotelekomtv.com:3873/stream/play.m3u8 https://ip100.radyotelekomtv.com:3873/stream/play.m3u8
#EXTINF:-1 tvg-id="Majid.ae",Majid TV (1080p) #EXTINF:-1 tvg-id="Majid.ae",Majid TV (1080p)
https://vo-live.cdb.cdn.orange.com/Content/Channel/MajidChildrenChannel/HLS/index.m3u8 https://vo-live.cdb.cdn.orange.com/Content/Channel/MajidChildrenChannel/HLS/index.m3u8
@ -151,9 +151,9 @@ https://weyyak-live.akamaized.net/weyyak_mix/index.m3u8
https://weyyak-live.akamaized.net/weyyak_nawaem/index.m3u8 https://weyyak-live.akamaized.net/weyyak_nawaem/index.m3u8
#EXTINF:-1 tvg-id="YasTV.ae",Yas TV (1080p) #EXTINF:-1 tvg-id="YasTV.ae",Yas TV (1080p)
https://vo-live.cdb.cdn.orange.com/Content/Channel/YASSportsChannel/HLS/index.m3u8 https://vo-live.cdb.cdn.orange.com/Content/Channel/YASSportsChannel/HLS/index.m3u8
#EXTINF:-1 tvg-id="AlDafrahTV.ae",Al Dafrah TV (720p)
https://rtmp-live-ingest-eu-west-3-universe-dacast-com.akamaized.net/transmuxv1/streams/dbb8ac05-a020-784c-3a95-6ed027941532.m3u8
#EXTINF:-1 tvg-id="ZeeAlwan.ae",Zee Alwan (720p) [Geo-blocked]
https://weyyak-live.akamaized.net/weyyak_zee_alwan/index.m3u8
#EXTINF:-1 tvg-id="ZeeAflam.ae",Zee Aflam (720p) [Geo-blocked] #EXTINF:-1 tvg-id="ZeeAflam.ae",Zee Aflam (720p) [Geo-blocked]
https://weyyak-live.akamaized.net/weyyak_zee_aflam/index.m3u8 https://weyyak-live.akamaized.net/weyyak_zee_aflam/index.m3u8
#EXTINF:-1 tvg-id="ZeeAlwan.ae",Zee Alwan (720p) [Geo-blocked]
https://weyyak-live.akamaized.net/weyyak_zee_alwan/index.m3u8
#EXTINF:-1 tvg-id="SpacetoonArabic.ae",Spacetoon Arabic (1080p)
https://shd-gcp-live.edgenextcdn.net/live/bitmovin-spacetoon/d8382fb9ab4b2307058f12c7ea90db54/index.m3u8

View file

@ -19,6 +19,8 @@ https://live1.mediadesk.al/oranews.m3u8
http://198.244.188.94/panorama/livestream/playlist.m3u8 http://198.244.188.94/panorama/livestream/playlist.m3u8
#EXTINF:-1 tvg-id="ReportTV.al",Report TV (720p) #EXTINF:-1 tvg-id="ReportTV.al",Report TV (720p)
https://deb10stream.duckdns.org/hls/stream.m3u8 https://deb10stream.duckdns.org/hls/stream.m3u8
#EXTINF:-1 tvg-id="Syri.al",Syri (720p) [Not 24/7]
https://stream.syritv.al/SyriTV/index.m3u8
#EXTINF:-1 tvg-id="TopChannel.al",Top News (720p) #EXTINF:-1 tvg-id="TopChannel.al",Top News (720p)
https://trueodin.serv00.net/?t=topnewsal https://trueodin.serv00.net/?t=topnewsal
#EXTINF:-1 tvg-id="TropojaTelevizion.al",Tropoja TV (1080p) #EXTINF:-1 tvg-id="TropojaTelevizion.al",Tropoja TV (1080p)
@ -27,5 +29,3 @@ https://live.prostream.al/al/smil:tropojatv.smil/playlist.m3u8
https://fe.tring.al/delta/105/out/u/rdghfhsfhfshs.m3u8 https://fe.tring.al/delta/105/out/u/rdghfhsfhfshs.m3u8
#EXTINF:-1 tvg-id="ZjarrTV.al",Zjarr TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="ZjarrTV.al",Zjarr TV (720p) [Not 24/7]
https://cdn.jwplayer.com/live/events/r2qgHu7W.m3u8 https://cdn.jwplayer.com/live/events/r2qgHu7W.m3u8
#EXTINF:-1 tvg-id="Syri.al",Syri (720p) [Not 24/7]
https://stream.syritv.al/SyriTV/index.m3u8

View file

@ -5,32 +5,8 @@ http://stream01.vnet.am/AmediaPremium/mono.m3u8
http://stream02.vnet.am/Kinoman/mono.m3u8 http://stream02.vnet.am/Kinoman/mono.m3u8
#EXTINF:-1 tvg-id="FightBox.nl",FightBox #EXTINF:-1 tvg-id="FightBox.nl",FightBox
http://stream01.vnet.am/Fightbox/mono.m3u8 http://stream01.vnet.am/Fightbox/mono.m3u8
#EXTINF:-1 tvg-id="Fox.ru",Fox
https://stream01.vnet.am/Fox/mono.m3u8
#EXTINF:-1 tvg-id="Hollywood.ru",Hollywood
http://stream01.vnet.am/ParamountChannel/mono.m3u8
#EXTINF:-1 tvg-id="NationalGeographicWild.ru",National Geographic Wild
http://stream02.vnet.am/NatGeoWild/mono.m3u8
#EXTINF:-1 tvg-id="NicktoonsCIS.ru",Nicktoons
https://stream01.vnet.am/Boomerang/mono.m3u8
#EXTINF:-1 tvg-id="BoksTV.ru",Бокс ТВ
http://stream01.vnet.am/BoksTv/mono.m3u8
#EXTINF:-1 tvg-id="Detskimir.ru",Детский мир #EXTINF:-1 tvg-id="Detskimir.ru",Детский мир
http://stream01.vnet.am/CartoonNetwork/mono.m3u8 http://stream01.vnet.am/CartoonNetwork/mono.m3u8
#EXTINF:-1 tvg-id="Domkino.ru",Дом Кино
https://stream01.vnet.am/DomKino/mono.m3u8
#EXTINF:-1 tvg-id="India.ru",Индия
https://stream01.vnet.am/ZeeTV/mono.m3u8
#EXTINF:-1 tvg-id="CarouselInternational.ru",Карусель Int
http://stream02.vnet.am/Karusel/mono.m3u8
#EXTINF:-1 tvg-id="KinopremyeraHD.ru",Кинопремьера HD
http://stream02.vnet.am/Kinopremera/mono.m3u8
#EXTINF:-1 tvg-id="KukhnyaTV.ru",Кухня ТВ HD
http://stream01.vnet.am/KukhnyaTv/mono.m3u8
#EXTINF:-1 tvg-id="MuzTV.ru",Муз ТВ
http://stream01.vnet.am/MuzTv/mono.m3u8
#EXTINF:-1 tvg-id="Mult.ru",Мульт
http://stream01.vnet.am/Mult/mono.m3u8
#EXTINF:-1 tvg-id="Nauka.ru",Наука 2.0 #EXTINF:-1 tvg-id="Nauka.ru",Наука 2.0
http://stream01.vnet.am/Nauka/mono.m3u8 http://stream01.vnet.am/Nauka/mono.m3u8
#EXTINF:-1 tvg-id="NTVMir.ru",НТВ Мир #EXTINF:-1 tvg-id="NTVMir.ru",НТВ Мир
@ -41,7 +17,5 @@ http://stream01.vnet.am/Evrika/mono.m3u8
http://stream01.vnet.am/Perec/mono.m3u8 http://stream01.vnet.am/Perec/mono.m3u8
#EXTINF:-1 tvg-id="FridayInternational.ru",Пятница International #EXTINF:-1 tvg-id="FridayInternational.ru",Пятница International
https://stream01.vnet.am/Pyatnica/mono.m3u8 https://stream01.vnet.am/Pyatnica/mono.m3u8
#EXTINF:-1 tvg-id="STSkids.ru",СТС Kids
http://stream02.vnet.am/DisneyChannel/mono.m3u8
#EXTINF:-1 tvg-id="Telecafe.ru",Телекафе #EXTINF:-1 tvg-id="Telecafe.ru",Телекафе
http://stream01.vnet.am/Telekafe/mono.m3u8 http://stream01.vnet.am/Telekafe/mono.m3u8

View file

@ -16,9 +16,9 @@ https://panel.dattalive.com/6605140/smil:6605140.smil/playlist.m3u8
#EXTVLCOPT:http-user-agent=iPhone #EXTVLCOPT:http-user-agent=iPhone
https://g1.vxral-hor.transport.edge-access.net/a15/ngrp:a24-100056_all/a24-100056.m3u8 https://g1.vxral-hor.transport.edge-access.net/a15/ngrp:a24-100056_all/a24-100056.m3u8
#EXTINF:-1 tvg-id="AiredeSantaFe.ar",Aire de Santa Fe (1080p) #EXTINF:-1 tvg-id="AiredeSantaFe.ar",Aire de Santa Fe (1080p)
https://unlimited1-us.dps.live/airedesantafetv/airedesantafetv.smil/playlist.m3u8
#EXTINF:-1 tvg-id="AlternaTV.ar",Alterna TV (720p) #EXTINF:-1 tvg-id="AlternaTV.ar",Alterna TV (720p)
https://alternatv.ar/stream/hls/live.m3u8 https://alternatv.ar/stream/hls/live.m3u8
https://unlimited1-us.dps.live/airedesantafetv/airedesantafetv.smil/playlist.m3u8
#EXTINF:-1 tvg-id="Am1020.ar",Am1020 (360p) [Geo-blocked] #EXTINF:-1 tvg-id="Am1020.ar",Am1020 (360p) [Geo-blocked]
http://51.79.83.93:9998/live/am1020/playlist.m3u8 http://51.79.83.93:9998/live/am1020/playlist.m3u8
#EXTINF:-1 tvg-id="AmericaTV.ar",America TV (480p) #EXTINF:-1 tvg-id="AmericaTV.ar",America TV (480p)

View file

@ -27,6 +27,8 @@ https://bitcdn-kronehit.bitmovin.com/v2/hls/playlist.m3u8
https://streaming13.huberwebmedia.at/LiveApp/streams/985585225397790082777809.m3u8 https://streaming13.huberwebmedia.at/LiveApp/streams/985585225397790082777809.m3u8
#EXTINF:-1 tvg-id="Okto.at",Okto TV (1080p) #EXTINF:-1 tvg-id="Okto.at",Okto TV (1080p)
https://cdn3.wowza.com/1/MHFtazJReW5rOFhP/N2NWNDZ2/hls/live/playlist.m3u8 https://cdn3.wowza.com/1/MHFtazJReW5rOFhP/N2NWNDZ2/hls/live/playlist.m3u8
#EXTINF:-1 tvg-id="ORF1HD.at",ORF 1 HD
https://s6.hopslan.com/orfx11/index.m3u8
#EXTINF:-1 tvg-id="ORF1HD.at" http-referrer="https://livestreamde.com/",ORF 1 HD #EXTINF:-1 tvg-id="ORF1HD.at" http-referrer="https://livestreamde.com/",ORF 1 HD
#EXTVLCOPT:http-referrer=https://livestreamde.com/ #EXTVLCOPT:http-referrer=https://livestreamde.com/
https://strm.hdtvizlecanli.com/live/orf1.m3u8 https://strm.hdtvizlecanli.com/live/orf1.m3u8
@ -48,6 +50,8 @@ http://iptv.rtv-ooe.at/stream.m3u8
https://m317.video-stream-hosting.de/gzSoftware-live/_definst_/smil:livestream.smil/playlist.m3u8 https://m317.video-stream-hosting.de/gzSoftware-live/_definst_/smil:livestream.smil/playlist.m3u8
#EXTINF:-1 tvg-id="ServusTV.at",ServusTV (1080p) [Geo-blocked] #EXTINF:-1 tvg-id="ServusTV.at",ServusTV (1080p) [Geo-blocked]
https://stv-live.akamaized.net/hls/live/2031011/lingeoSTVATwebPri/master.m3u8 https://stv-live.akamaized.net/hls/live/2031011/lingeoSTVATwebPri/master.m3u8
#EXTINF:-1 tvg-id="SteiermarkTV.at",Steiermark TV (1080p)
https://h056.video-stream-hosting.de/easycast8-live/_definst_/mp4:livestreamhd4/playlist.m3u8?ref=
#EXTINF:-1 tvg-id="SwamijiTVAmerican.at",Swamiji TV American (1080p) [Not 24/7] #EXTINF:-1 tvg-id="SwamijiTVAmerican.at",Swamiji TV American (1080p) [Not 24/7]
https://stream.swamiji.tv/YogaIPTV/smil:YogaStreamUS.smil/playlist.m3u8 https://stream.swamiji.tv/YogaIPTV/smil:YogaStreamUS.smil/playlist.m3u8
#EXTINF:-1 tvg-id="SwamijiTVAustralian.at",Swamiji TV Australian (1080p) [Not 24/7] #EXTINF:-1 tvg-id="SwamijiTVAustralian.at",Swamiji TV Australian (1080p) [Not 24/7]
@ -64,9 +68,3 @@ http://89.187.168.245:8080/live/sUPPERchannel2/index.m3u8
https://live1.markenfunk.com/t1/ngrp:live_all/playlist.m3u8 https://live1.markenfunk.com/t1/ngrp:live_all/playlist.m3u8
#EXTINF:-1 tvg-id="W24.at",W24 (720p) [Not 24/7] #EXTINF:-1 tvg-id="W24.at",W24 (720p) [Not 24/7]
https://ms01.w24.at/W24/smil:liveevent.smil/playlist.m3u8 https://ms01.w24.at/W24/smil:liveevent.smil/playlist.m3u8
#EXTINF:-1 tvg-id="ORF1HD.at",ORF 1 HD
https://s6.hopslan.com/orfx1/index.m3u8
#EXTINF:-1 tvg-id="ORF1HD.at",ORF 1 HD
https://s6.hopslan.com/orfx11/index.m3u8
#EXTINF:-1 tvg-id="SteiermarkTV.at",Steiermark TV (1080p)
https://h056.video-stream-hosting.de/easycast8-live/_definst_/mp4:livestreamhd4/playlist.m3u8?ref=

View file

@ -3,8 +3,6 @@
https://2gblive.akamaized.net/hls/live/2033805/2GB/index.m3u8 https://2gblive.akamaized.net/hls/live/2033805/2GB/index.m3u8
#EXTINF:-1 tvg-id="3AW.au",3AW Melbourne (1080p) #EXTINF:-1 tvg-id="3AW.au",3AW Melbourne (1080p)
https://3awlive.akamaized.net/hls/live/2032295/3AW/index.m3u8 https://3awlive.akamaized.net/hls/live/2032295/3AW/index.m3u8
#EXTINF:-1 tvg-id="3TamilTV.au",3 Tamil TV (720p) [Not 24/7]
https://6n3yogbnd9ok-hls-live.5centscdn.com/threetamil/d0dbe915091d400bd8ee7f27f0791303.sdp/index.m3u8
#EXTINF:-1 tvg-id="6PR.au",6PR Perth (1080p) #EXTINF:-1 tvg-id="6PR.au",6PR Perth (1080p)
https://6prlive.akamaized.net/hls/live/2033806/6PR/index.m3u8 https://6prlive.akamaized.net/hls/live/2033806/6PR/index.m3u8
#EXTINF:-1 tvg-id="9GemSydney.au",9Gem (720p) [Geo-blocked] #EXTINF:-1 tvg-id="9GemSydney.au",9Gem (720p) [Geo-blocked]
@ -13,12 +11,8 @@ https://9now-livestreams.akamaized.net/hls/live/2008311/gem-syd/master.m3u8
https://9now-livestreams.akamaized.net/hls/live/2008312/go-syd/master.m3u8 https://9now-livestreams.akamaized.net/hls/live/2008312/go-syd/master.m3u8
#EXTINF:-1 tvg-id="9LifeSydney.au",9Life (720p) [Geo-blocked] #EXTINF:-1 tvg-id="9LifeSydney.au",9Life (720p) [Geo-blocked]
https://9now-livestreams.akamaized.net/hls/live/2008313/life-syd/master.m3u8 https://9now-livestreams.akamaized.net/hls/live/2008313/life-syd/master.m3u8
#EXTINF:-1 tvg-id="10BoldSydney.au",10 Bold (720p) [Geo-blocked]
https://i.mjh.nz/10bold-nsw.m3u8
#EXTINF:-1 tvg-id="10BoldAdelaide.au",10 Bold Adelaide (1080p) #EXTINF:-1 tvg-id="10BoldAdelaide.au",10 Bold Adelaide (1080p)
https://dce3793146fef017.mediapackage.us-west-2.amazonaws.com/out/v1/55cdf73af7894775ba6de8f57482b66a/CMAF_HLS/index.m3u8 https://dce3793146fef017.mediapackage.us-west-2.amazonaws.com/out/v1/55cdf73af7894775ba6de8f57482b66a/CMAF_HLS/index.m3u8
#EXTINF:-1 tvg-id="10PeachSydney.au",10 Peach (720p) [Geo-blocked]
https://i.mjh.nz/10peach-nsw.m3u8
#EXTINF:-1 tvg-id="ABCAustralia.au",ABC Australia #EXTINF:-1 tvg-id="ABCAustralia.au",ABC Australia
https://abc-news-dmd-streams-1.akamaized.net/out/v1/701126012d044971b3fa89406a440133/index.m3u8 https://abc-news-dmd-streams-1.akamaized.net/out/v1/701126012d044971b3fa89406a440133/index.m3u8
#EXTINF:-1 tvg-id="ABCMESydney.au",ABC Me (720p) #EXTINF:-1 tvg-id="ABCMESydney.au",ABC Me (720p)
@ -41,8 +35,6 @@ https://c.mjh.nz/abc-wa.m3u8
https://c.mjh.nz/abc-tv-plus.m3u8 https://c.mjh.nz/abc-tv-plus.m3u8
#EXTINF:-1 tvg-id="ABCTVNSW.au",ABC TV Sydney (720p) #EXTINF:-1 tvg-id="ABCTVNSW.au",ABC TV Sydney (720p)
https://c.mjh.nz/abc-nsw.m3u8 https://c.mjh.nz/abc-nsw.m3u8
#EXTINF:-1 tvg-id="AUSTamilTV.au",AUS Tamil TV (720p) [Not 24/7]
https://bk7l2pn7dx53-hls-live.5centscdn.com/austamil/fe01ce2a7fbac8fafaed7c982a04e229.sdp/playlist.m3u8
#EXTINF:-1 tvg-id="AusbizTV.au",ausbiz TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="AusbizTV.au",ausbiz TV (720p) [Not 24/7]
https://d9quh89lh7dtw.cloudfront.net/public-output/index.m3u8 https://d9quh89lh7dtw.cloudfront.net/public-output/index.m3u8
#EXTINF:-1 tvg-id="BloombergTVAustralia.au",Bloomberg TV Australia (270p) #EXTINF:-1 tvg-id="BloombergTVAustralia.au",Bloomberg TV Australia (270p)
@ -61,8 +53,6 @@ https://9now-livestreams-fhd-t.akamaized.net/u/prod/simulcast/mel/ch9/hls/r1/ind
https://9now-livestreams-fhd-t.akamaized.net/u/prod/simulcast/per/ch9/hls/r1/index.m3u8 https://9now-livestreams-fhd-t.akamaized.net/u/prod/simulcast/per/ch9/hls/r1/index.m3u8
#EXTINF:-1 tvg-id="Channel9Sydney.au",Channel 9 Sydney (720p) [Geo-blocked] #EXTINF:-1 tvg-id="Channel9Sydney.au",Channel 9 Sydney (720p) [Geo-blocked]
https://9now-livestreams-fhd-t.akamaized.net/u/prod/simulcast/syd/ch9/hls/r1/index.m3u8 https://9now-livestreams-fhd-t.akamaized.net/u/prod/simulcast/syd/ch9/hls/r1/index.m3u8
#EXTINF:-1 tvg-id="10Sydney.au",Channel 10 (720p) [Geo-blocked]
https://i.mjh.nz/10-nsw.m3u8
#EXTINF:-1 tvg-id="Channel44.au",Channel 44 (480p) #EXTINF:-1 tvg-id="Channel44.au",Channel 44 (480p)
https://d1k6kax80wecy5.cloudfront.net/WFqZJc/index.m3u8 https://d1k6kax80wecy5.cloudfront.net/WFqZJc/index.m3u8
#EXTINF:-1 tvg-id="CTBPerth.au",CTB Perth (720p) #EXTINF:-1 tvg-id="CTBPerth.au",CTB Perth (720p)
@ -73,16 +63,10 @@ https://movies.ctbperth.net.au/hls/stream.m3u8
https://news.ctbperth.net.au/hls/stream.m3u8 https://news.ctbperth.net.au/hls/stream.m3u8
#EXTINF:-1 tvg-id="ExpoChannel.au",Expo Channel (360p) #EXTINF:-1 tvg-id="ExpoChannel.au",Expo Channel (360p)
https://tvsnhlslivetest.akamaized.net/hls/live/2034711/EXPO-MSL4/master.m3u8 https://tvsnhlslivetest.akamaized.net/hls/live/2034711/EXPO-MSL4/master.m3u8
#EXTINF:-1 tvg-id="GOOD.au",GOOD.
https://i.mjh.nz/.r/good-dot.m3u8
#EXTINF:-1 tvg-id="HopeChannelAustralia.au",Hope Channel Australia (1080p) #EXTINF:-1 tvg-id="HopeChannelAustralia.au",Hope Channel Australia (1080p)
https://videodelivery.net/9fb3596948ddf463fde0ec4b85625b24/manifest/video.m3u8 https://videodelivery.net/9fb3596948ddf463fde0ec4b85625b24/manifest/video.m3u8
#EXTINF:-1 tvg-id="IndoOzTV.au",Indo Oz TV (720p) #EXTINF:-1 tvg-id="IndoOzTV.au",Indo Oz TV (720p)
https://stream.e2is.in/hls/indoztv.m3u8 https://stream.e2is.in/hls/indoztv.m3u8
#EXTINF:-1 tvg-id="JonmoBhumiTV.au",JonmoBhumi TV (720p) [Not 24/7]
https://us170.jagobd.com:447/c3VydmVyX8RpbEU9Mi8xNy8yMDE0GIDU6RgzQ6NTAgdEoaeFzbF92YWxIZTO0U0ezN1IzMyfvcGVMZEJCTEFWeVN3PTOmdFsaWRtaW51aiPhnPTI/jonmobhumitv.stream/playlist.m3u8
#EXTINF:-1 tvg-id="M4TVMalayalam.au",M4TV Malayalam (1080p) [Not 24/7]
https://app.m4stream.live/mfourmalayalamhls/live.m3u8
#EXTINF:-1 tvg-id="",Race Central TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="",Race Central TV (720p) [Not 24/7]
https://nrpus.bozztv.com/36bay2/gusa-racecentral/index.m3u8 https://nrpus.bozztv.com/36bay2/gusa-racecentral/index.m3u8
#EXTINF:-1 tvg-id="Racingcom.au",Racing.com (720p) #EXTINF:-1 tvg-id="Racingcom.au",Racing.com (720p)
@ -99,15 +83,11 @@ https://skylivetab-new.akamaized.net/hls/live/2038780/sky1/index.m3u8
https://skylivetab-new.akamaized.net/hls/live/2038781/sky2/index.m3u8 https://skylivetab-new.akamaized.net/hls/live/2038781/sky2/index.m3u8
#EXTINF:-1 tvg-id="SkyThoroughbredCentral.au",Sky Thoroughbred Central (720p) [Geo-blocked] #EXTINF:-1 tvg-id="SkyThoroughbredCentral.au",Sky Thoroughbred Central (720p) [Geo-blocked]
https://skylivetab-new.akamaized.net/hls/live/2038782/stcsd/index.m3u8 https://skylivetab-new.akamaized.net/hls/live/2038782/stcsd/index.m3u8
#EXTINF:-1 tvg-id="tickerNews.au",Ticker News (1080p)
https://cdn-uw2-prod.tsv2.amagi.tv/linear/amg01486-tickernews-tickernewsweb-ono/playlist.m3u8
#EXTINF:-1 tvg-id="",Travel & Food TV (720p) #EXTINF:-1 tvg-id="",Travel & Food TV (720p)
https://nrpus.bozztv.com/36bay2/gusa-moviemagictv/index.m3u8 https://nrpus.bozztv.com/36bay2/gusa-moviemagictv/index.m3u8
#EXTINF:-1 tvg-id="TVSN.au",TVSN (1080p) #EXTINF:-1 tvg-id="TVSN.au",TVSN (1080p)
https://tvsnhlslivetest.akamaized.net/hls/live/2034711/TVSN-MSL4/master.m3u8 https://tvsnhlslivetest.akamaized.net/hls/live/2034711/TVSN-MSL4/master.m3u8
#EXTINF:-1 tvg-id="TVSNBeauty.au",TVSN Beauty (1080p) #EXTINF:-1 tvg-id="TVSNBeauty.au",TVSN Beauty (1080p)
https://live-tvsn.simplestreamcdn.com/live12/tvsnbeauty/bitrate1.isml/.m3u8 https://live-tvsn.simplestreamcdn.com/live12/tvsnbeauty/bitrate1.isml/.m3u8
#EXTINF:-1 tvg-id="",TVSN Catchup TV (1080p)
https://tvsnshowsvod.akamaized.net/CatchUpTV/TVSN-AU/2411171630/TVSN_2411171630.m3u8
#EXTINF:-1 tvg-id="TVSNJewellery.au",TVSN Jewellery (1080p) #EXTINF:-1 tvg-id="TVSNJewellery.au",TVSN Jewellery (1080p)
https://live-tvsn.simplestreamcdn.com/live13/tvsnjewellery/bitrate1.isml/.m3u8 https://live-tvsn.simplestreamcdn.com/live13/tvsnjewellery/bitrate1.isml/.m3u8

View file

@ -1,6 +1,4 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="EuronewsEnglish.fr",Euronews English (720p)
https://euronews-euronews-world-1-au.samsung.wurl.tv/manifest/playlist.m3u8
#EXTINF:-1 tvg-id="HorseCountryTV.uk",Horse and Country (720p) #EXTINF:-1 tvg-id="HorseCountryTV.uk",Horse and Country (720p)
https://hncfree-samsungau.amagi.tv/playlist.m3u8 https://hncfree-samsungau.amagi.tv/playlist.m3u8
#EXTINF:-1 tvg-id="InsightTV.nl",Insight TV (720p) #EXTINF:-1 tvg-id="InsightTV.nl",Insight TV (720p)
@ -11,18 +9,12 @@ https://introuble-samsungau.amagi.tv/playlist.m3u8
https://inwild-samsungau.amagi.tv/playlist.m3u8 https://inwild-samsungau.amagi.tv/playlist.m3u8
#EXTINF:-1 tvg-id="InWonder.nl",InWonder (720p) #EXTINF:-1 tvg-id="InWonder.nl",InWonder (720p)
https://inwonder-samsungau.amagi.tv/playlist.m3u8 https://inwonder-samsungau.amagi.tv/playlist.m3u8
#EXTINF:-1 tvg-id="RealFamilies.au",Real Families (Australia) (720p)
https://lds-realfamilies-samsunguau.amagi.tv/playlist.m3u8
#EXTINF:-1 tvg-id="RealStories.uk",Real Stories (720p)
https://lds-realstories-samsungau.amagi.tv/playlist.m3u8
#EXTINF:-1 tvg-id="Rialto.nz",Rialto (1080p) #EXTINF:-1 tvg-id="Rialto.nz",Rialto (1080p)
https://rialto-rialto-samsungaustralia.amagi.tv/playlist.m3u8 https://rialto-rialto-samsungaustralia.amagi.tv/playlist.m3u8
#EXTINF:-1 tvg-id="RyanandFriends.us",Ryan and Friends (1080p) #EXTINF:-1 tvg-id="RyanandFriends.us",Ryan and Friends (1080p)
https://ryanandfriends-samsungau.amagi.tv/playlist.m3u8 https://ryanandfriends-samsungau.amagi.tv/playlist.m3u8
#EXTINF:-1 tvg-id="Tastemade.au",Tastemade Australia (1080p) #EXTINF:-1 tvg-id="Tastemade.au",Tastemade Australia (1080p)
https://tmint-aus-samsungau.amagi.tv/playlist.m3u8 https://tmint-aus-samsungau.amagi.tv/playlist.m3u8
#EXTINF:-1 tvg-id="Timeline.us",Time Line Australia (720p)
https://lds-timeline-samsungau.amagi.tv/playlist.m3u8
#EXTINF:-1 tvg-id="TraceSportStars.fr",Trace Sport Stars (Australia) (1080p) #EXTINF:-1 tvg-id="TraceSportStars.fr",Trace Sport Stars (Australia) (1080p)
https://lightning-tracesport-samsungau.amagi.tv/playlist.m3u8 https://lightning-tracesport-samsungau.amagi.tv/playlist.m3u8
#EXTINF:-1 tvg-id="TraceUrban.fr",Trace Urban (Australia) (1080p) #EXTINF:-1 tvg-id="TraceUrban.fr",Trace Urban (Australia) (1080p)

View file

@ -3,14 +3,10 @@
https://cdn01.setar.aw/Canal49/canal49/playlist.m3u8 https://cdn01.setar.aw/Canal49/canal49/playlist.m3u8
#EXTINF:-1 tvg-id="ArubaTVPlus.aw",ArubaTV + (1080p) #EXTINF:-1 tvg-id="ArubaTVPlus.aw",ArubaTV + (1080p)
https://livertmptwo.com:19360/atvplusrelay/atvplusrelay.m3u8 https://livertmptwo.com:19360/atvplusrelay/atvplusrelay.m3u8
#EXTINF:-1 tvg-id="BalchiTV.aw",Balchi TV (720p)
https://livertmptwo.com:19360/balchirelaytv/balchirelaytv.m3u8
#EXTINF:-1 tvg-id="CoolFM989.aw",Cool FM 98.9 (720p) #EXTINF:-1 tvg-id="CoolFM989.aw",Cool FM 98.9 (720p)
https://live2.tensila.com/cool-v-1.arubara/hls/master.m3u8 https://live2.tensila.com/cool-v-1.arubara/hls/master.m3u8
#EXTINF:-1 tvg-id="",Dushi TV (720p)
https://livertmptwo.com:19360/dushitvrelay/dushitvrelay.m3u8
#EXTINF:-1 tvg-id="HeartRadioAruba.aw",Heart Radio Aruba (720p) [Not 24/7]
https://live2.tensila.com/heart-v-1.heartar/hls/live/mystream.m3u8
#EXTINF:-1 tvg-id="Hit94FM.aw",Hit 94 FM (720p)
https://565280.gvideo.io/cmaf/565280_2069313/master.m3u8
#EXTINF:-1 tvg-id="NosIslaTV.aw" 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",Nos Isla TV (1080p) [Not 24/7] #EXTINF:-1 tvg-id="NosIslaTV.aw" 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",Nos Isla TV (1080p) [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 #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/livestream23/playlist.m3u8 https://backend-server-dot-telearuba-app.appspot.com/media/livestream23/playlist.m3u8
@ -25,3 +21,6 @@ https://backend-server-dot-telearuba-app.appspot.com/media/livestream13/playlist
https://cdn01.setar.aw/Telearuba/telearuba/playlist.m3u8 https://cdn01.setar.aw/Telearuba/telearuba/playlist.m3u8
#EXTINF:-1 tvg-id="VIPTV.aw",VIP TV (720p) #EXTINF:-1 tvg-id="VIPTV.aw",VIP TV (720p)
https://ed5ov1.live.opencaster.com/bkyqeDgfaukC/index.m3u8 https://ed5ov1.live.opencaster.com/bkyqeDgfaukC/index.m3u8
#EXTINF:-1 tvg-id="X1027FM.aw" http-referrer="https://player.castr.com/live_21e811c0d60d11eeaa1a471c2c967e4a",X 102.7 FM (720p) [Not 24/7]
#EXTVLCOPT:http-referrer=https://player.castr.com/live_21e811c0d60d11eeaa1a471c2c967e4a
https://stream.castr.com/65dee3aad6beacddbd6cd1af/live_21e811c0d60d11eeaa1a471c2c967e4a/index.m3u8

View file

@ -35,8 +35,6 @@ https://raw.githubusercontent.com/UzunMuhalefet/streams/refs/heads/main/myvideo-
https://str.yodacdn.net/medeniyyet/index.m3u8 https://str.yodacdn.net/medeniyyet/index.m3u8
#EXTINF:-1 tvg-id="",MTV TV #EXTINF:-1 tvg-id="",MTV TV
https://raw.githubusercontent.com/UzunMuhalefet/streams/refs/heads/main/myvideo-az/mtv-azerbaycan.m3u8 https://raw.githubusercontent.com/UzunMuhalefet/streams/refs/heads/main/myvideo-az/mtv-azerbaycan.m3u8
#EXTINF:-1 tvg-id="ShowPlusTV.az",Show Plus TV (720p)
https://glb.bozztv.com/glb/ssh101/showplus/index.m3u8
#EXTINF:-1 tvg-id="SpaceTV.az",Space TV #EXTINF:-1 tvg-id="SpaceTV.az",Space TV
https://raw.githubusercontent.com/UzunMuhalefet/streams/main/myvideo-az/space-tv.m3u8 https://raw.githubusercontent.com/UzunMuhalefet/streams/main/myvideo-az/space-tv.m3u8
#EXTINF:-1 tvg-id="",TMB TV #EXTINF:-1 tvg-id="",TMB TV

View file

@ -1,8 +1,6 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="AlJazeeraBalkans.ba",Al Jazeera Balkans (1080p) #EXTINF:-1 tvg-id="AlJazeeraBalkans.ba",Al Jazeera Balkans (1080p)
https://live-hls-apps-ajb-v3-fa.getaj.net/AJB/index.m3u8 https://live-hls-apps-ajb-v3-fa.getaj.net/AJB/index.m3u8
#EXTINF:-1 tvg-id="B1TV.ba",B1 TV (1080p) [Not 24/7]
http://wowza.bihnet.net:88/hls/b1-live.m3u8
#EXTINF:-1 tvg-id="BHRT.ba",BHRT (720p) [Geo-blocked] #EXTINF:-1 tvg-id="BHRT.ba",BHRT (720p) [Geo-blocked]
https://bhrtstream.bhtelecom.ba/bhrtportal.m3u8 https://bhrtstream.bhtelecom.ba/bhrtportal.m3u8
#EXTINF:-1 tvg-id="BHRT.ba",BHRT (270p) [Geo-blocked] #EXTINF:-1 tvg-id="BHRT.ba",BHRT (270p) [Geo-blocked]
@ -25,8 +23,6 @@ http://glasdrine.cutuk.net:8081/433ssdsw/GlasDrineSD/playlist.m3u8
https://prd-hometv-live-open.spectar.tv/ERO_1_083/playlist.m3u8 https://prd-hometv-live-open.spectar.tv/ERO_1_083/playlist.m3u8
#EXTINF:-1 tvg-id="RTVZenica.ba",RTV Zenica (720p) #EXTINF:-1 tvg-id="RTVZenica.ba",RTV Zenica (720p)
https://stream.rtvze.ba/live/123/123.m3u8 https://stream.rtvze.ba/live/123/123.m3u8
#EXTINF:-1 tvg-id="SevdahTV.ba",Sevdah TV (288p)
https://restreamer2.tnt.ba/hls/stream.m3u8
#EXTINF:-1 tvg-id="SuperTV.ba",Super TV Media (720p) #EXTINF:-1 tvg-id="SuperTV.ba",Super TV Media (720p)
https://mirtv.club/live/mirtv/index.m3u8 https://mirtv.club/live/mirtv/index.m3u8
#EXTINF:-1 tvg-id="Televizija5.ba",Televizija 5 (576p) #EXTINF:-1 tvg-id="Televizija5.ba",Televizija 5 (576p)
@ -37,3 +33,5 @@ https://live.tv-m.net/hls/stream.m3u8
https://restreamer1.tnt.ba/hls/tntkids.m3u8 https://restreamer1.tnt.ba/hls/tntkids.m3u8
#EXTINF:-1 tvg-id="TVSlonExtra.ba",TV Slon Extra (1080p) [Not 24/7] #EXTINF:-1 tvg-id="TVSlonExtra.ba",TV Slon Extra (1080p) [Not 24/7]
http://31.47.0.130:8082 http://31.47.0.130:8082
#EXTINF:-1 tvg-id="NTVICKakanj.ba",NTV IC Kakanj (720p)
https://lon.rtsp.me/dEqnY-myGj84bKrieCIPfA/1743271667/hls/3dH3YAD6.m3u8

View file

@ -11,14 +11,10 @@ https://www.btvlive.gov.bd/streams/ef8b8bbc-98b7-4ba7-a49d-a0adaf259d35/ES/d96eb
https://amigofx.com:1936/channelsreporter/channelsreporter/playlist.m3u8 https://amigofx.com:1936/channelsreporter/channelsreporter/playlist.m3u8
#EXTINF:-1 tvg-id="DeshiTV.ca",Deshi TV (720p) #EXTINF:-1 tvg-id="DeshiTV.ca",Deshi TV (720p)
https://deshitv.deshitv24.net/live/myStream/playlist.m3u8 https://deshitv.deshitv24.net/live/myStream/playlist.m3u8
#EXTINF:-1 tvg-id="ETenTV.bd",E Ten TV (1080p) [Not 24/7]
https://iptvbd.live/test/1080.m3u8
#EXTINF:-1 tvg-id="EkusheyTV.bd",Ekushey TV (480p) #EXTINF:-1 tvg-id="EkusheyTV.bd",Ekushey TV (480p)
https://ekusheyserver.com/etvlivesn.m3u8 https://ekusheyserver.com/etvlivesn.m3u8
#EXTINF:-1 tvg-id="JamunaTV.bd",Jamuna TV (720p) [Geo-blocked] #EXTINF:-1 tvg-id="JamunaTV.bd",Jamuna TV (720p) [Geo-blocked]
http://113.212.111.246:8080/hls/col12.m3u8 http://113.212.111.246:8080/hls/col12.m3u8
#EXTINF:-1 tvg-id="",JaTV (720p)
https://cloud2.smartsolbd.com/live/jatvbd/index.m3u8
#EXTINF:-1 tvg-id="ProbashiTVNews.ca",Probashi TV News (720p) #EXTINF:-1 tvg-id="ProbashiTVNews.ca",Probashi TV News (720p)
http://probashi.alvegroups.com:8081/probashitv/probashi/playlist.m3u8 http://probashi.alvegroups.com:8081/probashitv/probashi/playlist.m3u8
#EXTINF:-1 tvg-id="SangsadTV.bd",Sangsad TV (1080p) #EXTINF:-1 tvg-id="SangsadTV.bd",Sangsad TV (1080p)

View file

@ -7,32 +7,24 @@ https://live.zendzend.com/streams/29375_107244/playlist.m3u8
https://bel-live-hls.akamaized.net/hls/live/2038650/BEL-Live-HLS/master.m3u8 https://bel-live-hls.akamaized.net/hls/live/2038650/BEL-Live-HLS/master.m3u8
#EXTINF:-1 tvg-id="BAMTV.be",Bel'Afrika Media TV (1080p) #EXTINF:-1 tvg-id="BAMTV.be",Bel'Afrika Media TV (1080p)
https://goccn.cloud/hls/belafrikatv/index.m3u8 https://goccn.cloud/hls/belafrikatv/index.m3u8
#EXTINF:-1 tvg-id="BelgianFederalParliament.be",Belgian Federal Parliament (720p) [Not 24/7]
http://livestream.parolis.be:1935/live/PLN_NL/playlist.m3u8
#EXTINF:-1 tvg-id="Bouke.be",Bouke [Geo-blocked] #EXTINF:-1 tvg-id="Bouke.be",Bouke [Geo-blocked]
https://tvlocales-live.freecaster.com/live/95d2f70d-9229-478b-9aed-bc4fa220316d/95d2f70d-9229-478b-9aed-bc4fa220316d.isml/master.m3u8 https://tvlocales-live.freecaster.com/live/95d2f70d-9229-478b-9aed-bc4fa220316d/95d2f70d-9229-478b-9aed-bc4fa220316d.isml/master.m3u8
#EXTINF:-1 tvg-id="BX1.be",BX1 (720p) [Not 24/7] #EXTINF:-1 tvg-id="BX1.be",BX1 (720p) [Not 24/7]
https://59959724487e3.streamlock.net/stream/live/playlist.m3u8 https://59959724487e3.streamlock.net/stream/live/playlist.m3u8
#EXTINF:-1 tvg-id="CanalZoom.be",Canal Zoom [Geo-blocked] #EXTINF:-1 tvg-id="CanalZoom.be",Canal Zoom [Geo-blocked]
https://tvlocales-live.freecaster.com/live/95d2e3af-5ab8-45a9-9dc9-f544d006b5d5/95d2e3af-5ab8-45a9-9dc9-f544d006b5d5.isml/master.m3u8 https://tvlocales-live.freecaster.com/live/95d2e3af-5ab8-45a9-9dc9-f544d006b5d5/95d2e3af-5ab8-45a9-9dc9-f544d006b5d5.isml/master.m3u8
#EXTINF:-1 tvg-id="CityMusicTV.be",City Music TV (720p)
https://5592f056abba8.streamlock.net/citytv/citytv/playlist.m3u8
#EXTINF:-1 tvg-id="EbS.be",EbS (1080p) #EXTINF:-1 tvg-id="EbS.be",EbS (1080p)
https://streams.prd.commavservices.eu/live/ebs/index.m3u8 https://streams.prd.commavservices.eu/live/ebs/index.m3u8
#EXTINF:-1 tvg-id="EbSPlus.be",EbS+ (1080p) #EXTINF:-1 tvg-id="EbSPlus.be",EbS+ (1080p)
https://streams.prd.commavservices.eu/live/ebsplus/index.m3u8 https://streams.prd.commavservices.eu/live/ebsplus/index.m3u8
#EXTINF:-1 tvg-id="FunVision.be",Fun Radio Vision (720p) [Not 24/7]
https://raw.githubusercontent.com/Sphinxroot/HSL/main/DM/be/FunRadio.m3u8
#EXTINF:-1 tvg-id="HLNLive.be",HLN Live (720p) #EXTINF:-1 tvg-id="HLNLive.be",HLN Live (720p)
https://dpg-eventstreams.akamaized.net/hlnlivesrt-xmr/streamx/hlnlivesrt_720p.m3u8 https://dpg-eventstreams.akamaized.net/hlnlivesrt-xmr/streamx/hlnlivesrt_720p.m3u8
#EXTINF:-1 tvg-id="JapanimTV.be",Japanim TV (1080p) #EXTINF:-1 tvg-id="JapanimTV.be",Japanim TV (1080p)
https://foxkidstv.be:3369/stream/play.m3u8 https://foxkidstv.be:3369/stream/play.m3u8
#EXTINF:-1 tvg-id="JoeFM.be",Joe FM (720p) [Not 24/7] #EXTINF:-1 tvg-id="JoeFM.be",Joe FM (720p) [Not 24/7]
https://dpp-streamlive-plain.medialaancdn.be/joe_kijklive/plain/hls_hd.m3u8 https://dpp-streamlive-plain.medialaancdn.be/joe_kijklive/plain/hls_hd.m3u8
#EXTINF:-1 tvg-id="KetnetJunior.be",Ketnet Junior (720p) #EXTINF:-1 tvg-id="LaUne.be",La Une (1080p)
https://content.uplynk.com/channel/e11a05356cc44198977436418ad71832.m3u8 http://41.205.93.154/LA-UNE/mpegts
#EXTINF:-1 tvg-id="KetnetJunior.be",Ketnet Junior (720p)
https://content.uplynk.com/channel/e11a05356cc44198977436418ad71832.mpd
#EXTINF:-1 tvg-id="LN24.be",LN24 #EXTINF:-1 tvg-id="LN24.be",LN24
https://live-ln24.digiteka.com/1911668011/index.m3u8 https://live-ln24.digiteka.com/1911668011/index.m3u8
#EXTINF:-1 tvg-id="Matele.be",MaTele (1080p) [Not 24/7] #EXTINF:-1 tvg-id="Matele.be",MaTele (1080p) [Not 24/7]
@ -47,10 +39,6 @@ https://streaming01.divercom.be/notele_live/direct.stream/playlist.m3u8
https://live-video.dpgmedia.net/f1d26a28c95485cc/out/v1/5f60a245c110454fba652900ecf30ea2/index.m3u8 https://live-video.dpgmedia.net/f1d26a28c95485cc/out/v1/5f60a245c110454fba652900ecf30ea2/index.m3u8
#EXTINF:-1 tvg-id="RadioContact.be",Radio Contact (1080p) #EXTINF:-1 tvg-id="RadioContact.be",Radio Contact (1080p)
https://contact-live-hls.akamaized.net/hls/live/2038650/CONTACT-Live-HLS/master.m3u8 https://contact-live-hls.akamaized.net/hls/live/2038650/CONTACT-Live-HLS/master.m3u8
#EXTINF:-1 tvg-id="RadioPROS.be",Radio PROS (720p) [Not 24/7]
http://highvolume04.streampartner.nl/radiopros/livestream/playlist.m3u8
#EXTINF:-1 tvg-id="RadioPROS.be",Radio PROS (720p) [Not 24/7]
https://558bd16067b67.streamlock.net/radiopros/livestream/playlist.m3u8
#EXTINF:-1 tvg-id="",RTC Télé Liège [Geo-blocked] #EXTINF:-1 tvg-id="",RTC Télé Liège [Geo-blocked]
https://tvlocales-live.freecaster.com/live/95d2f6eb-6f01-4d1d-8543-d14966de7b04/95d2f6eb-6f01-4d1d-8543-d14966de7b04.isml/master.m3u8 https://tvlocales-live.freecaster.com/live/95d2f6eb-6f01-4d1d-8543-d14966de7b04/95d2f6eb-6f01-4d1d-8543-d14966de7b04.isml/master.m3u8
#EXTINF:-1 tvg-id="RTLTVI.be",RTL-TVI (1080p) [Not 24/7] #EXTINF:-1 tvg-id="RTLTVI.be",RTL-TVI (1080p) [Not 24/7]
@ -77,5 +65,3 @@ https://live-radio-cf-vrt.akamaized.net/groupb/live/0f394a26-c87d-475e-8590-e9c6
https://dpp-live-events.medialaancdn.be/events/hls/aes/webstream1.m3u8 https://dpp-live-events.medialaancdn.be/events/hls/aes/webstream1.m3u8
#EXTINF:-1 tvg-id="VTM2.be",VTM 2 (720p) #EXTINF:-1 tvg-id="VTM2.be",VTM 2 (720p)
https://dpp-live-events.medialaancdn.be/events/hls/aes/webstream3.m3u8 https://dpp-live-events.medialaancdn.be/events/hls/aes/webstream3.m3u8
#EXTINF:-1 tvg-id="LaUne.be",La Une (1080p)
http://41.205.93.154/LA-UNE/mpegts

View file

@ -1,13 +1,5 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="AfricanewsFrench.fr",AfricaNews Français (720p)
https://rakuten-africanews-2-be.samsung.wurl.tv/manifest/playlist.m3u8
#EXTINF:-1 tvg-id="AFVFamily.us",AFV Family #EXTINF:-1 tvg-id="AFVFamily.us",AFV Family
https://futuretoday-afv-family-2-be.samsung.wurl.tv/playlist.m3u8 https://futuretoday-afv-family-2-be.samsung.wurl.tv/playlist.m3u8
#EXTINF:-1 tvg-id="BloombergQuicktake.us",Bloomberg Quicktake #EXTINF:-1 tvg-id="BloombergQuicktake.us",Bloomberg Quicktake
https://bloomberg-quicktake-1-be.samsung.wurl.tv/playlist.m3u8 https://bloomberg-quicktake-1-be.samsung.wurl.tv/playlist.m3u8
#EXTINF:-1 tvg-id="BloombergTV.us",Bloomberg TV
https://bloomberg-bloomberg-1-be.samsung.wurl.tv/playlist.m3u8
#EXTINF:-1 tvg-id="EuronewsFrench.fr",Euronews
https://rakuten-euronews-10-be.samsung.wurl.tv/playlist.m3u8
#EXTINF:-1 tvg-id="RakutenTVFamilyMovies.fr",Rakuten Family
https://rakuten-family-16-be.samsung.wurl.tv/playlist.m3u8

View file

@ -5,20 +5,12 @@ https://ms4.sedemosmi.tv/live/M3E5ajhtdjJkaXBscmZubmUxMmh1cjN1bjZrbm5wZW8/index.
http://100automoto.tv:1935/bgtv1/autotv/playlist.m3u8 http://100automoto.tv:1935/bgtv1/autotv/playlist.m3u8
#EXTINF:-1 tvg-id="AgroTV.bg",Agro TV (480p) #EXTINF:-1 tvg-id="AgroTV.bg",Agro TV (480p)
https://restr2.bgtv.bg/agro/hls/agro.m3u8 https://restr2.bgtv.bg/agro/hls/agro.m3u8
#EXTINF:-1 tvg-id="b1bbox.bg",B1B Box (720p)
https://e105-ts.cdn.bg/b1b/fls/b1btv.stream/playlist.m3u8
#EXTINF:-1 tvg-id="BalkanikaTV.bg",Balkanika TV (270p) #EXTINF:-1 tvg-id="BalkanikaTV.bg",Balkanika TV (270p)
rtsp://stream.teracomm.bg/balkanika rtsp://stream.teracomm.bg/balkanika
#EXTINF:-1 tvg-id="CityTV.bg",City TV (576p) [Not 24/7] #EXTINF:-1 tvg-id="CityTV.bg",City TV (576p) [Not 24/7]
https://tv.city.bg/play/tshls/citytv/index.m3u8 https://tv.city.bg/play/tshls/citytv/index.m3u8
#EXTINF:-1 tvg-id="CodeFashionTV.bg",Code Fashion TV (1080p)
https://cdn3.invivo.bg/Codefashion_5500/index.m3u8
#EXTINF:-1 tvg-id="CodeHealthTV.bg",Code Health TV (1080p)
https://cdn3.invivo.bg/codehealth_test/index.m3u8
#EXTINF:-1 tvg-id="DSTV.bg",DSTV (614p) [Not 24/7] #EXTINF:-1 tvg-id="DSTV.bg",DSTV (614p) [Not 24/7]
http://46.249.95.140:8081/hls/data.m3u8 http://46.249.95.140:8081/hls/data.m3u8
#EXTINF:-1 tvg-id="EuroFolkTV.bg",EuroFolk TV (720p)
https://eurofolk.cdn.netbadgers.com/bg040/bg041/bg041.m3u8
#EXTINF:-1 tvg-id="Eurocom.bg",Evrokom (360p) #EXTINF:-1 tvg-id="Eurocom.bg",Evrokom (360p)
https://live.ecomservice.bg/hls/stream.m3u8 https://live.ecomservice.bg/hls/stream.m3u8
#EXTINF:-1 tvg-id="HopeChannelBulgaria.bg",Hope Channel Bulgaria #EXTINF:-1 tvg-id="HopeChannelBulgaria.bg",Hope Channel Bulgaria
@ -48,11 +40,7 @@ https://streamer103.neterra.tv/tiankov-orient/live.m3u8
https://streamer103.neterra.tv/travel/live.m3u8 https://streamer103.neterra.tv/travel/live.m3u8
#EXTINF:-1 tvg-id="TV1.bg",TV 1 (720p) #EXTINF:-1 tvg-id="TV1.bg",TV 1 (720p)
https://tv1.cloudcdn.bg:8081/stream.m3u8 https://tv1.cloudcdn.bg:8081/stream.m3u8
#EXTINF:-1 tvg-id="TVDarts.bg",TV Darts (576p)
https://streamer103.neterra.tv/darts/live.m3u8
#EXTINF:-1 tvg-id="TVZagora.bg",TV Zagora (576p) #EXTINF:-1 tvg-id="TVZagora.bg",TV Zagora (576p)
http://zagoratv.ddns.net:8080/tvzagora.m3u8 http://zagoratv.ddns.net:8080/tvzagora.m3u8
#EXTINF:-1 tvg-id="TVart.bg",TVart (1080p)
https://stream.osc.bg/tvart/Stream3/playlist.m3u8
#EXTINF:-1 tvg-id="TVNBulgaria.bg",TVN-Bulgaria (1080p) #EXTINF:-1 tvg-id="TVNBulgaria.bg",TVN-Bulgaria (1080p)
https://obs.friendshipchurch.eu/tvn/mystream.m3u8 https://obs.friendshipchurch.eu/tvn/mystream.m3u8

View file

@ -153,3 +153,9 @@ https://fl1004.bozztv.com/ssh101/zoytvsports4/index.m3u8
https://fl1004.bozztv.com/ssh101/zoytvsports5/index.m3u8 https://fl1004.bozztv.com/ssh101/zoytvsports5/index.m3u8
#EXTINF:-1 tvg-id="ZoyTVTurcas.bo",Zoy TV Turcas #EXTINF:-1 tvg-id="ZoyTVTurcas.bo",Zoy TV Turcas
https://fl1004.bozztv.com/ssh101/zoytvturcas/index.m3u8 https://fl1004.bozztv.com/ssh101/zoytvturcas/index.m3u8
#EXTINF:-1 tvg-id="BoliviaTV.bo",Bolivia TV (720p)
https://5fe2654d6127d.streamlock.net:443/boliviatv/videoboliviatv/playlist.m3u8
#EXTINF:-1 tvg-id="ZoyTVSports1.bo",Zoy TV Sports 1 (1080p)
https://ssh101stream.ssh101.com/akamaissh101/ssh101/zoytvsports/playlist.m3u8
#EXTINF:-1 tvg-id="ZoyTVTurcas.bo",Zoy TV Turcas (720p)
https://ssh101stream.ssh101.com/akamaissh101/ssh101/zoytvturcas/playlist.m3u8

View file

@ -9,3 +9,5 @@ https://sincerecloud.stream/loadbalancer/public/actMdyoE.m3u8
https://media.streambrothers.com:1936/8014/8014/playlist.m3u8 https://media.streambrothers.com:1936/8014/8014/playlist.m3u8
#EXTINF:-1 tvg-id="NosTVBonaire.bq",Nos TV Bonaire (1080p) #EXTINF:-1 tvg-id="NosTVBonaire.bq",Nos TV Bonaire (1080p)
http://streaming.flamingotv.net/nostv/live.m3u8 http://streaming.flamingotv.net/nostv/live.m3u8
#EXTINF:-1 tvg-id="VozDiBonaireTV.bq",Voz Di Bonaire TV (720p)
https://tv.westream.cloud/VozdiBonaireTV/VozdiBonaireTV.m3u8

View file

@ -599,3 +599,11 @@ https://video01.kshost.com.br/seap8272/seap8272/playlist.m3u8
http://painelvj.com.br/tvaguaboa2/tvaguaboa2.sdp/playlist.m3u8 http://painelvj.com.br/tvaguaboa2/tvaguaboa2.sdp/playlist.m3u8
#EXTINF:-1 tvg-id="WTVBrasil.br",WTV Brasil (720p) #EXTINF:-1 tvg-id="WTVBrasil.br",WTV Brasil (720p)
https://stmv1.srvstm.com/wtvbrasil/wtvbrasil/playlist.m3u8 https://stmv1.srvstm.com/wtvbrasil/wtvbrasil/playlist.m3u8
#EXTINF:-1 tvg-id="TVCancaoNova.br",TV Cancao Nova (720p)
https://5c65286fc6ace.streamlock.net/cancaonova/CancaoNova.stream_720p/playlist.m3u8
#EXTINF:-1 tvg-id="TVMAX.br",TV MAX (720p)
https://5cf4a2c2512a2.streamlock.net/tvmax/tvmax/playlist.m3u8
#EXTINF:-1 tvg-id="TVBrasil.br",TV Brasil (720p)
https://tvbrasil-stream.ebc.com.br/index.m3u8
#EXTINF:-1 tvg-id="RedeTV.br",Rede TV! (720p)
https://cdn.jmvstream.com/w/AVJ-15235/playlist/playlist.m3u8

View file

@ -1 +1,7 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="GuardianTalkRadio.bs",Guardian Talk Radio (1080p)
https://cdn-edge1.streamcomedia.com/abr_tngr969fm/abr-tngr969fm_streams/playlist.m3u8
#EXTINF:-1 tvg-id="IslandLuckTV.bs",Island Luck TV (1080p) [Geo-blocked]
https://islandluck-edge1.streamcomedia.com/abr_islandluck-ott/abr-islandluck-ott_streams/playlist.m3u8
#EXTINF:-1 tvg-id="TheParliamentaryChannel.bs",The Parliamentary Channel (720p) [Not 24/7]
https://zns-edge1.streamcomedia.cloud/abr_parliamentarychannel/abr-parliament_streams/playlist.m3u8

View file

@ -3,6 +3,8 @@
https://edge13.vedge.infomaniak.com/livecast/ik:alpen-wellelivestream/manifest.m3u8 https://edge13.vedge.infomaniak.com/livecast/ik:alpen-wellelivestream/manifest.m3u8
#EXTINF:-1 tvg-id="AlpenlandTV.ch",Alpenland TV (720p) #EXTINF:-1 tvg-id="AlpenlandTV.ch",Alpenland TV (720p)
https://edge14.vedge.infomaniak.com/livecast/ik:alpen-wellelivestream/playlist.m3u8 https://edge14.vedge.infomaniak.com/livecast/ik:alpen-wellelivestream/playlist.m3u8
#EXTINF:-1 tvg-id="BlueSport2.ch",Blue Sport 2 (720p)
http://62.210.211.188:2095/play/a00f
#EXTINF:-1 tvg-id="Canal9.ch",Canal 9 en Français (1080p) #EXTINF:-1 tvg-id="Canal9.ch",Canal 9 en Français (1080p)
https://livehd.vedge.infomaniak.com/livecast/livehd/master.m3u8 https://livehd.vedge.infomaniak.com/livecast/livehd/master.m3u8
#EXTINF:-1 tvg-id="CanalAlphaJura.ch",Canal Alpha Jura (1080p) #EXTINF:-1 tvg-id="CanalAlphaJura.ch",Canal Alpha Jura (1080p)
@ -77,5 +79,3 @@ https://livevideo.infomaniak.com/streaming/livecast/tvm3/playlist.m3u8
https://cdnapisec.kaltura.com/p/1719221/sp/171922100/playManifest/entryId/1_t5h46v64/format/applehttp/protocol/https/a.m3u8 https://cdnapisec.kaltura.com/p/1719221/sp/171922100/playManifest/entryId/1_t5h46v64/format/applehttp/protocol/https/a.m3u8
#EXTINF:-1 tvg-id="WedoBigStories.ch",Wedo Big Stories (1080p) #EXTINF:-1 tvg-id="WedoBigStories.ch",Wedo Big Stories (1080p)
https://weyyak-live.akamaized.net/wedo_big_stories/index.m3u8 https://weyyak-live.akamaized.net/wedo_big_stories/index.m3u8
#EXTINF:-1 tvg-id="BlueSport2.ch",Blue Sport 2 (720p)
http://62.210.211.188:2095/play/a00f

View file

@ -443,7 +443,7 @@ https://mdstrm.com/live-stream-playlist/6046495ddf98b007fa2fe807.m3u8
https://mediacpstreamchile.com:1936/8028/8028/playlist.m3u8 https://mediacpstreamchile.com:1936/8028/8028/playlist.m3u8
#EXTINF:-1 tvg-id="ZappingMusic.cl",Zapping Music (720p) #EXTINF:-1 tvg-id="ZappingMusic.cl",Zapping Music (720p)
https://zmlive.zappingtv.com/zm-free/zm.smil/playlist.m3u8 https://zmlive.zappingtv.com/zm-free/zm.smil/playlist.m3u8
#EXTINF:-1 tvg-id="ZonaPlayTV.cl",Zona Play TV (720p)
https://paneltv.online:1936/8100/8100/playlist.m3u8
#EXTINF:-1 tvg-id="ZonaLatina.cl",Zona Latina (480p) #EXTINF:-1 tvg-id="ZonaLatina.cl",Zona Latina (480p)
http://190.2.212.209:8050/play/a0oj http://190.2.212.209:8050/play/a0oj
#EXTINF:-1 tvg-id="ZonaPlayTV.cl",Zona Play TV (720p)
https://paneltv.online:1936/8100/8100/playlist.m3u8

View file

@ -1,4 +1,6 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="AndoTV.cn",Ando TV
http://stream.qhbtv.com/adws/sd/live.m3u8
#EXTINF:-1 tvg-id="AndoTV.cn",Ando TV (576p) #EXTINF:-1 tvg-id="AndoTV.cn",Ando TV (576p)
http://119.1.122.186:4022/rtp/238.255.2.189:5999 http://119.1.122.186:4022/rtp/238.255.2.189:5999
#EXTINF:-1 tvg-id="AnimationShowChannel.cn",Animation Show Channel #EXTINF:-1 tvg-id="AnimationShowChannel.cn",Animation Show Channel
@ -23,46 +25,10 @@ http://49.113.179.174:4022/udp/238.125.3.121:5140
http://gslbservzqhsw.itv.cmvideo.cn/index.m3u8?Contentid=reallive-hdcctv1&channel-id=ystenlive&livemode=1&stbId=3 http://gslbservzqhsw.itv.cmvideo.cn/index.m3u8?Contentid=reallive-hdcctv1&channel-id=ystenlive&livemode=1&stbId=3
#EXTINF:-1 tvg-id="CCTV1.cn",CCTV1 (576p) #EXTINF:-1 tvg-id="CCTV1.cn",CCTV1 (576p)
http://117.161.133.51:81/gitv_live/G_CCTV-1/G_CCTV-1.m3u8 http://117.161.133.51:81/gitv_live/G_CCTV-1/G_CCTV-1.m3u8
#EXTINF:-1 tvg-id="CCTV2.cn",CCTV2 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.102:10250
#EXTINF:-1 tvg-id="CCTV2.cn",CCTV2 (576p) #EXTINF:-1 tvg-id="CCTV2.cn",CCTV2 (576p)
http://117.161.133.51:81/gitv_live/G_CCTV-2/G_CCTV-2.m3u8 http://117.161.133.51:81/gitv_live/G_CCTV-2/G_CCTV-2.m3u8
#EXTINF:-1 tvg-id="CCTV3.cn",CCTV3 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.122:10370
#EXTINF:-1 tvg-id="",CCTV4 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.138:10466
#EXTINF:-1 tvg-id="CCTV5.cn",CCTV5 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.123:10376
#EXTINF:-1 tvg-id="CCTV5Plus.cn",CCTV5+ (1080p)
http://bl.dchwtq.asia:10000/rtp/239.254.96.234:9484
#EXTINF:-1 tvg-id="CCTV6.cn",CCTV6 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.124:10382
#EXTINF:-1 tvg-id="CCTV7.cn",CCTV7 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.103:10256
#EXTINF:-1 tvg-id="CCTV8.cn",CCTV8 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.125:10388
#EXTINF:-1 tvg-id="CCTV9.cn",CCTV9 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.104:10262
#EXTINF:-1 tvg-id="CCTV10.cn",CCTV10 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.105:10268
#EXTINF:-1 tvg-id="CCTV11.cn",CCTV11 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.154:10560
#EXTINF:-1 tvg-id="CCTV12.cn",CCTV12 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.106:10274
#EXTINF:-1 tvg-id="CCTV13.cn",CCTV13 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.254.96.161:9040
#EXTINF:-1 tvg-id="CCTV14.cn",CCTV14 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.107:10280
#EXTINF:-1 tvg-id="CCTV15.cn",CCTV15 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.155:10566
#EXTINF:-1 tvg-id="CCTV15.cn",CCTV15音乐 #EXTINF:-1 tvg-id="CCTV15.cn",CCTV15音乐
http://hwrr.jx.chinamobile.com:8080/PLTV/88888888/224/3221225641/index.m3u8 http://hwrr.jx.chinamobile.com:8080/PLTV/88888888/224/3221225641/index.m3u8
#EXTINF:-1 tvg-id="CCTV16.cn",CCTV16 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.247:11124
#EXTINF:-1 tvg-id="",CCTV16-4K (2160p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.249:11136
#EXTINF:-1 tvg-id="CCTV17.cn",CCTV17 (1080p)
http://bl.dchwtq.asia:10000/rtp/239.69.1.152:10548
#EXTINF:-1 tvg-id="",CCTV TV Guide (576p) #EXTINF:-1 tvg-id="",CCTV TV Guide (576p)
http://117.161.133.51:81/gitv_live/G_DIANSHIZN-CQ/G_DIANSHIZN-CQ.m3u8?p=GITV http://117.161.133.51:81/gitv_live/G_DIANSHIZN-CQ/G_DIANSHIZN-CQ.m3u8?p=GITV
#EXTINF:-1 tvg-id="CCTVWorldGeography.cn",CCTV 世界地理 #EXTINF:-1 tvg-id="CCTVWorldGeography.cn",CCTV 世界地理
@ -157,6 +123,8 @@ http://118.122.2.29:9999/hls/47/index.m3u8
http://1.183.141.194:8001/hls/55/index.m3u8 http://1.183.141.194:8001/hls/55/index.m3u8
#EXTINF:-1 tvg-id="NeiMonggolTV.cn",Nei Monggol TV #EXTINF:-1 tvg-id="NeiMonggolTV.cn",Nei Monggol TV
http://49.113.179.174:4022/udp/238.125.7.93:5140 http://49.113.179.174:4022/udp/238.125.7.93:5140
#EXTINF:-1 tvg-id="NeiMonggolTV.cn",Nei Monggol TV
http://110.19.156.172:9901/tsfile/live/1003_1.m3u8
#EXTINF:-1 tvg-id="NeiMonggolTV2MongolianCultureChannel.cn",Nei Monggol TV 2 Mongolian Culture Channel #EXTINF:-1 tvg-id="NeiMonggolTV2MongolianCultureChannel.cn",Nei Monggol TV 2 Mongolian Culture Channel
http://1.183.141.194:8001/hls/54/index.m3u8 http://1.183.141.194:8001/hls/54/index.m3u8
#EXTINF:-1 tvg-id="QTV1.cn",QTV-1 #EXTINF:-1 tvg-id="QTV1.cn",QTV-1
@ -227,6 +195,8 @@ http://49.113.179.174:4022/udp/238.125.7.153:5140
http://106.124.91.222:85/tsfile/live/21220_1.m3u8?authid=0&key=txiptv&playlive=1 http://106.124.91.222:85/tsfile/live/21220_1.m3u8?authid=0&key=txiptv&playlive=1
#EXTINF:-1 tvg-id="XinjiangTV12.cn",Xinjiang TV 12 #EXTINF:-1 tvg-id="XinjiangTV12.cn",Xinjiang TV 12
http://49.113.179.174:4022/udp/238.125.3.185:5140 http://49.113.179.174:4022/udp/238.125.3.185:5140
#EXTINF:-1 tvg-id="XizangTVChinese.cn",Xizang TV Chinese
http://php.jdshipin.com/xztv.php?id=ws
#EXTINF:-1 tvg-id="XizangTVTibetan.cn",Xizang TV Tibetan #EXTINF:-1 tvg-id="XizangTVTibetan.cn",Xizang TV Tibetan
http://49.113.179.174:4022/udp/238.125.3.94:5140 http://49.113.179.174:4022/udp/238.125.3.94:5140
#EXTINF:-1 tvg-id="XizangTVTibetan.cn",Xizang TV Tibetan #EXTINF:-1 tvg-id="XizangTVTibetan.cn",Xizang TV Tibetan
@ -1565,7 +1535,3 @@ http://yslk.chinashadt.com:1635/live/stream:di1.stream/playlist.m3u8
http://yslk.chinashadt.com:1635/live/stream:di2.stream/playlist.m3u8 http://yslk.chinashadt.com:1635/live/stream:di2.stream/playlist.m3u8
#EXTINF:-1 tvg-id="",龙岩综合 (540p) #EXTINF:-1 tvg-id="",龙岩综合 (540p)
http://stream.lytv.net.cn/2/sd/live.m3u8 http://stream.lytv.net.cn/2/sd/live.m3u8
#EXTINF:-1 tvg-id="AndoTV.cn",Ando TV
http://stream.qhbtv.com/adws/sd/live.m3u8
#EXTINF:-1 tvg-id="XizangTVChinese.cn",Xizang TV Chinese
http://php.jdshipin.com/xztv.php?id=ws

View file

@ -65,6 +65,8 @@ https://canaldos.internetinalambrico.com.co:1936/live/canal2.stream/playlist.m3u
https://glb.bozztv.com/glb/ssh101/infotv01/playlist.m3u8 https://glb.bozztv.com/glb/ssh101/infotv01/playlist.m3u8
#EXTINF:-1 tvg-id="CanalInstitucional.co",Canal Institucional (720p) [Not 24/7] #EXTINF:-1 tvg-id="CanalInstitucional.co",Canal Institucional (720p) [Not 24/7]
https://streaming.rtvc.gov.co/TV_CanalInstitucional_live/smil:live.smil/playlist.m3u8 https://streaming.rtvc.gov.co/TV_CanalInstitucional_live/smil:live.smil/playlist.m3u8
#EXTINF:-1 tvg-id="CanalInstitucional.co",Canal Institucional (480p)
http://190.2.212.209:8050/play/a0lw
#EXTINF:-1 tvg-id="CanalMasTelevision.co",Canal Más Televisión (720p) #EXTINF:-1 tvg-id="CanalMasTelevision.co",Canal Más Televisión (720p)
https://movil.ejeserver.com/live/teledoradahd.m3u8 https://movil.ejeserver.com/live/teledoradahd.m3u8
#EXTINF:-1 tvg-id="CanalMasTelevision.co",Canal Más Televisión (720p) #EXTINF:-1 tvg-id="CanalMasTelevision.co",Canal Más Televisión (720p)
@ -81,6 +83,8 @@ https://video.ejeserver.com/live/nets.m3u8
https://canal.mediaserver.com.co/live/oracionconson.m3u8 https://canal.mediaserver.com.co/live/oracionconson.m3u8
#EXTINF:-1 tvg-id="CanalPyC.co",Canal PyC (480p) [Not 24/7] #EXTINF:-1 tvg-id="CanalPyC.co",Canal PyC (480p) [Not 24/7]
https://glb.bozztv.com/glb/ssh101/pyctelevision/index.m3u8 https://glb.bozztv.com/glb/ssh101/pyctelevision/index.m3u8
#EXTINF:-1 tvg-id="CanalRCN.co",Canal RCN (480p)
http://190.2.212.209:8050/play/a0lt
#EXTINF:-1 tvg-id="CanalRegionalFTV.co",Canal Regional FTV (720p) [Not 24/7] #EXTINF:-1 tvg-id="CanalRegionalFTV.co",Canal Regional FTV (720p) [Not 24/7]
https://tvlatina.live:1936/8024/8024/playlist.m3u8 https://tvlatina.live:1936/8024/8024/playlist.m3u8
#EXTINF:-1 tvg-id="CanalSantaMartaTV.co",Canal Santa Marta TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="CanalSantaMartaTV.co",Canal Santa Marta TV (720p) [Not 24/7]
@ -92,6 +96,8 @@ https://play.amelbasoluciones.co:3976/live/telepalmartvlive.m3u8
#EXTINF:-1 tvg-id="CanalTRO.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Canal TRO (1080p) #EXTINF:-1 tvg-id="CanalTRO.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Canal TRO (1080p)
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160 #EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160
https://liveingesta118.cdnmedia.tv/canaltro2live/smil:live.smil/playlist.m3u8 https://liveingesta118.cdnmedia.tv/canaltro2live/smil:live.smil/playlist.m3u8
#EXTINF:-1 tvg-id="CanalTRO.co",Canal TRO (480p)
http://190.2.212.209:8050/play/a0m5
#EXTINF:-1 tvg-id="CanalTROPlus.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Canal TRO Plus (1080p) [Geo-blocked] #EXTINF:-1 tvg-id="CanalTROPlus.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Canal TRO Plus (1080p) [Geo-blocked]
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160 #EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160
https://liveingesta118.cdnmedia.tv/canaltro2live/smil:troplus.smil/playlist.m3u8 https://liveingesta118.cdnmedia.tv/canaltro2live/smil:troplus.smil/playlist.m3u8
@ -196,6 +202,8 @@ https://xhateaec.com/livestreams/19.crKOSL8FRzpid0MA.m3u8
https://stmv4.voxtvhd.com.br/psctv/psctv/playlist.m3u8 https://stmv4.voxtvhd.com.br/psctv/psctv/playlist.m3u8
#EXTINF:-1 tvg-id="",PyC Televisión (720p) [Not 24/7] #EXTINF:-1 tvg-id="",PyC Televisión (720p) [Not 24/7]
https://ssh101-fl.bozztv.com/ssh101/pyctelevision/playlist.m3u8 https://ssh101-fl.bozztv.com/ssh101/pyctelevision/playlist.m3u8
#EXTINF:-1 tvg-id="RCNNovelas.co",RCN Novelas (480p)
http://190.2.212.209:8050/play/a0ox
#EXTINF:-1 tvg-id="RCNXtra.co",RCN Xtra (1080p) #EXTINF:-1 tvg-id="RCNXtra.co",RCN Xtra (1080p)
https://latv-rcn-xtra-1-mx.tcl.wurl.tv/playlist.m3u8 https://latv-rcn-xtra-1-mx.tcl.wurl.tv/playlist.m3u8
#EXTINF:-1 tvg-id="RDMTelevision.co",RDM Televisión (720p) [Not 24/7] #EXTINF:-1 tvg-id="RDMTelevision.co",RDM Televisión (720p) [Not 24/7]
@ -212,6 +220,8 @@ https://tvlatina.live:1936/8004/8004/playlist.m3u8
https://server.asilivehd.com:3802/live/canal4live.m3u8 https://server.asilivehd.com:3802/live/canal4live.m3u8
#EXTINF:-1 tvg-id="SenalColombia.co",Señal Colombia (1080p) #EXTINF:-1 tvg-id="SenalColombia.co",Señal Colombia (1080p)
https://streaming.rtvc.gov.co/TV_Senal_Colombia_live/smil:live.smil/playlist.m3u8 https://streaming.rtvc.gov.co/TV_Senal_Colombia_live/smil:live.smil/playlist.m3u8
#EXTINF:-1 tvg-id="SinLimites.co",Sin Limites (480p)
http://190.2.212.209:8050/play/a0pa
#EXTINF:-1 tvg-id="SuramTV.co",Suram TV (1080p) #EXTINF:-1 tvg-id="SuramTV.co",Suram TV (1080p)
https://livetv.305streamhd.com:3111/live/suramtvlive.m3u8 https://livetv.305streamhd.com:3111/live/suramtvlive.m3u8
#EXTINF:-1 tvg-id="TamesisTeVe.co",Támesis TeVe (614p) [Not 24/7] #EXTINF:-1 tvg-id="TamesisTeVe.co",Támesis TeVe (614p) [Not 24/7]
@ -228,18 +238,24 @@ https://video.ejeserver.com/live/telesanjacinto.m3u8
#EXTINF:-1 tvg-id="TeleVid.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Tele Vid (1080p) #EXTINF:-1 tvg-id="TeleVid.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Tele Vid (1080p)
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160 #EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160
https://liveingesta118.cdnmedia.tv/televidtvlive/smil:dvrlive.smil/playlist.m3u8?DVR= https://liveingesta118.cdnmedia.tv/televidtvlive/smil:dvrlive.smil/playlist.m3u8?DVR=
#EXTINF:-1 tvg-id="Teleantioquia.co",Teleantioquia (480p)
http://190.2.212.209:8050/play/a0n1
#EXTINF:-1 tvg-id="Teleantioquia.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Teleantioquia (360p) [Not 24/7] #EXTINF:-1 tvg-id="Teleantioquia.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Teleantioquia (360p) [Not 24/7]
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160 #EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160
https://liveingesta118.cdnmedia.tv/teleantioquialive/smil:dvrlive.smil/playlist.m3u8 https://liveingesta118.cdnmedia.tv/teleantioquialive/smil:dvrlive.smil/playlist.m3u8
#EXTINF:-1 tvg-id="Teleantioquia2.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Teleantioquia 2 (720p) #EXTINF:-1 tvg-id="Teleantioquia2.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Teleantioquia 2 (720p)
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160 #EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160
https://liveingesta118.cdnmedia.tv/teleantioquialive/smil:live.smil/playlist.m3u8?DVR= https://liveingesta118.cdnmedia.tv/teleantioquialive/smil:live.smil/playlist.m3u8?DVR=
#EXTINF:-1 tvg-id="Telecafe.co",Telecafe (480p)
http://190.2.212.209:8050/play/a0ne
#EXTINF:-1 tvg-id="Telecafe.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Telecafé (720p) #EXTINF:-1 tvg-id="Telecafe.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Telecafé (720p)
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160 #EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160
https://liveingesta118.cdnmedia.tv/telecafelive/smil:dvrlive.smil/playlist.m3u8 https://liveingesta118.cdnmedia.tv/telecafelive/smil:dvrlive.smil/playlist.m3u8
#EXTINF:-1 tvg-id="Telecaribe.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Telecaribe (720p) #EXTINF:-1 tvg-id="Telecaribe.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Telecaribe (720p)
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160 #EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160
https://liveingesta118.cdnmedia.tv/telecaribetvlive/smil:rtmp01.smil/playlist.m3u8 https://liveingesta118.cdnmedia.tv/telecaribetvlive/smil:rtmp01.smil/playlist.m3u8
#EXTINF:-1 tvg-id="Telecaribe.co",Telecaribe (480p)
http://190.2.212.209:8050/play/a0nc
#EXTINF:-1 tvg-id="TelecaribePlus.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Telecaribe Plus (720p) #EXTINF:-1 tvg-id="TelecaribePlus.co" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160",Telecaribe Plus (720p)
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160 #EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 CrKey/1.44.191160
https://liveingesta118.cdnmedia.tv/telecaribetvlive/smil:rtmp02.smil/playlist.m3u8 https://liveingesta118.cdnmedia.tv/telecaribetvlive/smil:rtmp02.smil/playlist.m3u8
@ -247,10 +263,14 @@ https://liveingesta118.cdnmedia.tv/telecaribetvlive/smil:rtmp02.smil/playlist.m3
https://cp.panelchs.com:1936/8094/8094/playlist.m3u8 https://cp.panelchs.com:1936/8094/8094/playlist.m3u8
#EXTINF:-1 tvg-id="Teleislas.co",Teleislas (486p) [Not 24/7] #EXTINF:-1 tvg-id="Teleislas.co",Teleislas (486p) [Not 24/7]
https://5ab772334c39c.streamlock.net/live-teleislas/teleislas/playlist.m3u8 https://5ab772334c39c.streamlock.net/live-teleislas/teleislas/playlist.m3u8
#EXTINF:-1 tvg-id="Teleislas.co",Teleislas (480p)
http://190.2.212.209:8050/play/a0m6
#EXTINF:-1 tvg-id="TelemusicaTV.co",Telemúsica TV (540p) [Geo-blocked] #EXTINF:-1 tvg-id="TelemusicaTV.co",Telemúsica TV (540p) [Geo-blocked]
https://canal.mediaserver.com.co/live/telemusica.m3u8 https://canal.mediaserver.com.co/live/telemusica.m3u8
#EXTINF:-1 tvg-id="TelenetTelevision.co",Telenet Televisión (478p) #EXTINF:-1 tvg-id="TelenetTelevision.co",Telenet Televisión (478p)
https://cp.panelchs.com:1936/8058/8058/playlist.m3u8 https://cp.panelchs.com:1936/8058/8058/playlist.m3u8
#EXTINF:-1 tvg-id="Telepacifico.co",Telepacifico (480p)
http://190.2.212.209:8050/play/a0n3
#EXTINF:-1 tvg-id="Telepacifico.co",Telepacífico (1080p) [Not 24/7] #EXTINF:-1 tvg-id="Telepacifico.co",Telepacífico (1080p) [Not 24/7]
https://stream.logicideas.media/telepacifico-live/smil:live.smil/playlist.m3u8 https://stream.logicideas.media/telepacifico-live/smil:live.smil/playlist.m3u8
#EXTINF:-1 tvg-id="Telepasto.co",Telepasto (360p) [Geo-blocked] #EXTINF:-1 tvg-id="Telepasto.co",Telepasto (360p) [Geo-blocked]
@ -263,6 +283,8 @@ https://cp.panelchs.com:1936/8060/8060/playlist.m3u8
https://stream.logicideas.media/canaltrece-live/smil:live.smil/playlist.m3u8 https://stream.logicideas.media/canaltrece-live/smil:live.smil/playlist.m3u8
#EXTINF:-1 tvg-id="TrecePlus.co",Trece + (720p) #EXTINF:-1 tvg-id="TrecePlus.co",Trece + (720p)
https://stream.logicideas.media/canaltreceplus-live/smil:live1plus.smil/playlist.m3u8 https://stream.logicideas.media/canaltreceplus-live/smil:live1plus.smil/playlist.m3u8
#EXTINF:-1 tvg-id="TrecePlus.co",Trece+ (480p)
http://190.2.212.209:8050/play/a0nf
#EXTINF:-1 tvg-id="TropicalTV.co",Tropical TV (480p) [Not 24/7] #EXTINF:-1 tvg-id="TropicalTV.co",Tropical TV (480p) [Not 24/7]
https://rpn3.bozztv.com/ssh101/ssh101/estvco/playlist.m3u8 https://rpn3.bozztv.com/ssh101/ssh101/estvco/playlist.m3u8
#EXTINF:-1 tvg-id="TuKanal.co",Tu Kanal (1080p) #EXTINF:-1 tvg-id="TuKanal.co",Tu Kanal (1080p)
@ -293,30 +315,8 @@ https://video.ejeserver.com/live/veotv.m3u8
https://eu1.servers10.com:8081/vidanuevatv/index.m3u8 https://eu1.servers10.com:8081/vidanuevatv/index.m3u8
#EXTINF:-1 tvg-id="ViveTV.co",Vive TV Colombia (1080p) #EXTINF:-1 tvg-id="ViveTV.co",Vive TV Colombia (1080p)
http://192.144.113.132:1935/live/ViveTV/playlist.m3u8 http://192.144.113.132:1935/live/ViveTV/playlist.m3u8
#EXTINF:-1 tvg-id="WinSports.co",Win Sports (480p)
http://190.2.212.209:8050/play/a0n2
#EXTINF:-1 tvg-id="Zoom.co" http-referrer="https://canalzoom.org/senal-en-vivo",Zoom (1080p) #EXTINF:-1 tvg-id="Zoom.co" http-referrer="https://canalzoom.org/senal-en-vivo",Zoom (1080p)
#EXTVLCOPT:http-referrer=https://canalzoom.org/senal-en-vivo #EXTVLCOPT:http-referrer=https://canalzoom.org/senal-en-vivo
https://canalzoom.smoothcloud.co:3027/live/canalzoombr1live.m3u8 https://canalzoom.smoothcloud.co:3027/live/canalzoombr1live.m3u8
#EXTINF:-1 tvg-id="CanalRCN.co",Canal RCN (480p)
http://190.2.212.209:8050/play/a0lt
#EXTINF:-1 tvg-id="WinSports.co",Win Sports (480p)
http://190.2.212.209:8050/play/a0n2
#EXTINF:-1 tvg-id="CanalInstitucional.co",Canal Institucional (480p)
http://190.2.212.209:8050/play/a0lw
#EXTINF:-1 tvg-id="RCNNovelas.co",RCN Novelas (480p)
http://190.2.212.209:8050/play/a0ox
#EXTINF:-1 tvg-id="SinLimites.co",Sin Limites (480p)
http://190.2.212.209:8050/play/a0pa
#EXTINF:-1 tvg-id="CanalTRO.co",Canal TRO (480p)
http://190.2.212.209:8050/play/a0m5
#EXTINF:-1 tvg-id="Teleantioquia.co",Teleantioquia (480p)
http://190.2.212.209:8050/play/a0n1
#EXTINF:-1 tvg-id="Telecafe.co",Telecafe (480p)
http://190.2.212.209:8050/play/a0ne
#EXTINF:-1 tvg-id="Telecaribe.co",Telecaribe (480p)
http://190.2.212.209:8050/play/a0nc
#EXTINF:-1 tvg-id="Teleislas.co",Teleislas (480p)
http://190.2.212.209:8050/play/a0m6
#EXTINF:-1 tvg-id="Telepacifico.co",Telepacifico (480p)
http://190.2.212.209:8050/play/a0n3
#EXTINF:-1 tvg-id="TrecePlus.co",Trece+ (480p)
http://190.2.212.209:8050/play/a0nf

View file

@ -36,6 +36,10 @@ https://sc-kuzeykibrissmarttv.ercdn.net/kanalt/bantp1/playlist.m3u8
https://sc-kuzeykibrissmarttv.ercdn.net/kibristv/bant1/playlist.m3u8 https://sc-kuzeykibrissmarttv.ercdn.net/kibristv/bant1/playlist.m3u8
#EXTINF:-1 tvg-id="OmegaChannel.cy",Omega Channel (1080p) #EXTINF:-1 tvg-id="OmegaChannel.cy",Omega Channel (1080p)
http://l1.cloudskep.com/tst/omcy/playlist.m3u8 http://l1.cloudskep.com/tst/omcy/playlist.m3u8
#EXTINF:-1 tvg-id="OMONOIATV.cy",OMONOIA TV (684p)
http://62.233.57.226:8001/play/a00b00
#EXTINF:-1 tvg-id="OneChannelCyprus.cy",One Channel Cyprus (576p)
http://62.210.211.188:2095/play/a00e
#EXTINF:-1 tvg-id="RIK1.cy",RIK 1 #EXTINF:-1 tvg-id="RIK1.cy",RIK 1
http://l6.cloudskep.com/tvb6/rik1-1/mpeg.2ts http://l6.cloudskep.com/tvb6/rik1-1/mpeg.2ts
#EXTINF:-1 tvg-id="RIK2.cy",RIK 2 #EXTINF:-1 tvg-id="RIK2.cy",RIK 2
@ -60,7 +64,3 @@ https://sc-kuzeykibrissmarttv.ercdn.net/tv2020/bantp1/playlist.m3u8
https://dev.aftermind.xyz/edge-hls/unitrust/voulitv/index.m3u8?token=8TXWzhY3h6jrzqEqx https://dev.aftermind.xyz/edge-hls/unitrust/voulitv/index.m3u8?token=8TXWzhY3h6jrzqEqx
#EXTINF:-1 tvg-id="VouliTV.cy",Vouli TV (1080p) [Not 24/7] #EXTINF:-1 tvg-id="VouliTV.cy",Vouli TV (1080p) [Not 24/7]
https://dev.aftermind.xyz/hls/unitrust/voulitv/index.m3u8?token=8TXWzhY3h6jrzqEqx https://dev.aftermind.xyz/hls/unitrust/voulitv/index.m3u8?token=8TXWzhY3h6jrzqEqx
#EXTINF:-1 tvg-id="OMONOIATV.cy",OMONOIA TV (684p)
http://62.233.57.226:8001/play/a00b00
#EXTINF:-1 tvg-id="OneChannelCyprus.cy",One Channel Cyprus (576p)
http://62.210.211.188:2095/play/a00e

View file

@ -3,8 +3,6 @@
https://123tv-mx1.flex-cdn.net/index.m3u8 https://123tv-mx1.flex-cdn.net/index.m3u8
#EXTINF:-1 tvg-id="3sat.de",3sat (720p) [Geo-blocked] #EXTINF:-1 tvg-id="3sat.de",3sat (720p) [Geo-blocked]
https://zdf-hls-18.akamaized.net/hls/live/2016501/dach/high/master.m3u8 https://zdf-hls-18.akamaized.net/hls/live/2016501/dach/high/master.m3u8
#EXTINF:-1 tvg-id="AlexBerlin.de",Alex Berlin (1080p) [Not 24/7]
https://alex-stream.rosebud-media.de/live/alexlivetv40.smil/playlist.m3u8
#EXTINF:-1 tvg-id="AllgauTV.de",Allgäu TV (1080p) #EXTINF:-1 tvg-id="AllgauTV.de",Allgäu TV (1080p)
https://stream01.welocal.stream/stream/fhd-allgaeutv_25679/ngrp:stream_all/playlist.m3u8 https://stream01.welocal.stream/stream/fhd-allgaeutv_25679/ngrp:stream_all/playlist.m3u8
#EXTINF:-1 tvg-id="AltenburgTV.de",Altenburg TV (1080p) #EXTINF:-1 tvg-id="AltenburgTV.de",Altenburg TV (1080p)
@ -197,6 +195,8 @@ https://mcdn.ndr.de/ndr/hls/ndr_fs/ndr_nds/master.m3u8
https://mcdn.ndr.de/ndr/hls/ndr_fs/ndr_sh/master.m3u8 https://mcdn.ndr.de/ndr/hls/ndr_fs/ndr_sh/master.m3u8
#EXTINF:-1 tvg-id="Nickelodeon.de",Nick Germany (1080p) [Geo-blocked] #EXTINF:-1 tvg-id="Nickelodeon.de",Nick Germany (1080p) [Geo-blocked]
https://0d26a00dfbb1.airspace-cdn.cbsivideo.com/nick1999/master/nick1999.m3u8 https://0d26a00dfbb1.airspace-cdn.cbsivideo.com/nick1999/master/nick1999.m3u8
#EXTINF:-1 tvg-id="Nickelodeon.de",Nickelodeon
https://ma.anixa.tv/clips/stream/nickelodeon/playlist.php
#EXTINF:-1 tvg-id="Nickelodeon.de",Nickelodeon Deutschland [Geo-blocked] #EXTINF:-1 tvg-id="Nickelodeon.de",Nickelodeon Deutschland [Geo-blocked]
https://unilivemtveu-lh.akamaihd.net/i/nickde_1@448749/master.m3u8 https://unilivemtveu-lh.akamaihd.net/i/nickde_1@448749/master.m3u8
#EXTINF:-1 tvg-id="NiederbayernTV.de",Niederbayern TV (720p) #EXTINF:-1 tvg-id="NiederbayernTV.de",Niederbayern TV (720p)
@ -214,13 +214,7 @@ https://hls1.wtnet.de/noa4hh/apple/wifi6500.m3u8
#EXTINF:-1 tvg-id="noa4Norderstedt.de",Noa 4 Norderstedt (1080p) #EXTINF:-1 tvg-id="noa4Norderstedt.de",Noa 4 Norderstedt (1080p)
https://hls1.wtnet.de/noa4/apple/wifi6500.m3u8 https://hls1.wtnet.de/noa4/apple/wifi6500.m3u8
#EXTINF:-1 tvg-id="NRWision.de",NRWision (1080p) #EXTINF:-1 tvg-id="NRWision.de",NRWision (1080p)
https://fms.nrwision.de/live/livestreamHD.stream/playlist.m3u8 https://fms.nrwision.de/live/ngrp:livestreamHD.stream/playlist.m3u8
#EXTINF:-1 tvg-id="NRWision.de",NRWISION (1080p)
https://fms.nrwision.de/live/livestreamHD.stream_source/playlist.m3u8
#EXTINF:-1 tvg-id="NRWision.de",NRWision (720p)
https://fms.nrwision.de/live/livestreamHD.stream_1080p/playlist.m3u8
#EXTINF:-1 tvg-id="NRWision.de",NRWision (360p)
https://fms.nrwision.de/live/livestreamHD.stream_360p/playlist.m3u8
#EXTINF:-1 tvg-id="OberpfalzTV.de",Oberpfalz TV (1080p) #EXTINF:-1 tvg-id="OberpfalzTV.de",Oberpfalz TV (1080p)
https://oberpfalztv.iptv-playoutcenter.de/oberpfalztv/oberpfalztv.stream_1/playlist.m3u8 https://oberpfalztv.iptv-playoutcenter.de/oberpfalztv/oberpfalztv.stream_1/playlist.m3u8
#EXTINF:-1 tvg-id="Oeins.de",oeins (Oldenburg) (1080p) [Not 24/7] #EXTINF:-1 tvg-id="Oeins.de",oeins (Oldenburg) (1080p) [Not 24/7]
@ -371,17 +365,12 @@ https://live.creacast.com/rockland-radio/smil:rockland-radio.smil/playlist.m3u8
https://rt-ger.rttv.com/dvr/rtdeutsch/playlist.m3u8 https://rt-ger.rttv.com/dvr/rtdeutsch/playlist.m3u8
#EXTINF:-1 tvg-id="RTDE.de",RT DE (1080p) [Not 24/7] #EXTINF:-1 tvg-id="RTDE.de",RT DE (1080p) [Not 24/7]
https://rt-ger.rttv.com/live/rtdeutsch/playlist.m3u8 https://rt-ger.rttv.com/live/rtdeutsch/playlist.m3u8
#EXTINF:-1 tvg-id="RTL.de",RTL (576p)
https://s6.hopslan.com/rtlc1/tracks-v1a1/mono.m3u8
#EXTINF:-1 tvg-id="RTL.de",RTL (Germany) (576p) #EXTINF:-1 tvg-id="RTL.de",RTL (Germany) (576p)
http://178.219.128.68:64888/RTL http://178.219.128.68:64888/RTL
#EXTINF:-1 tvg-id="RTLSuper.de",RTL Super (576p) #EXTINF:-1 tvg-id="RTLSuper.de",RTL Super (576p)
http://178.219.128.68:64888/SUPERTL http://178.219.128.68:64888/SUPERTL
#EXTINF:-1 tvg-id="RTLZwei.de",RTL Zwei (1080p) #EXTINF:-1 tvg-id="RTLZwei.de",RTL Zwei (1080p)
http://178.219.128.68:64888/RTL2 http://178.219.128.68:64888/RTL2
#EXTINF:-1 tvg-id="RTLZwei.de" http-referrer="https://www.2ix2.com/rtl2-live/",RTL Zwei (576p)
#EXTVLCOPT:http-referrer=https://www.2ix2.com/rtl2-live/
https://s6.hopslan.com/rtl2x1/index.m3u8
#EXTINF:-1 tvg-id="SaarlandFernsehen1.de",Saarland Fernsehen 1 (1080p) #EXTINF:-1 tvg-id="SaarlandFernsehen1.de",Saarland Fernsehen 1 (1080p)
https://saarland1.iptv-playoutcenter.de/saarland1/saarland1.stream_1/playlist.m3u8 https://saarland1.iptv-playoutcenter.de/saarland1/saarland1.stream_1/playlist.m3u8
#EXTINF:-1 tvg-id="SaarlandFernsehen2.de",Saarland Fernsehen 2 (720p) [Not 24/7] #EXTINF:-1 tvg-id="SaarlandFernsehen2.de",Saarland Fernsehen 2 (720p) [Not 24/7]
@ -492,6 +481,8 @@ https://wdrlokalzeit.akamaized.net/hls/live/2018025-b/wdrlz_muensterland/master.
https://wdrlokalzeit.akamaized.net/hls/live/2018020-b/wdrlz_siegen/master.m3u8 https://wdrlokalzeit.akamaized.net/hls/live/2018020-b/wdrlz_siegen/master.m3u8
#EXTINF:-1 tvg-id="WDRFernsehenWuppertal.de",WDR Fernsehen Wuppertal (720p) [Geo-blocked] #EXTINF:-1 tvg-id="WDRFernsehenWuppertal.de",WDR Fernsehen Wuppertal (720p) [Geo-blocked]
https://wdrlokalzeit.akamaized.net/hls/live/2018028-b/wdrlz_wuppertal/master.m3u8 https://wdrlokalzeit.akamaized.net/hls/live/2018028-b/wdrlz_wuppertal/master.m3u8
#EXTINF:-1 tvg-id="WELT.de",WELT
https://s6.hopslan.com/n24X/index.m3u8
#EXTINF:-1 tvg-id="WeltderWunderTV.de",Welt der Wunder TV (576p) #EXTINF:-1 tvg-id="WeltderWunderTV.de",Welt der Wunder TV (576p)
https://wdw.iptv-playoutcenter.de/wdw/wdw1/playlist.m3u8 https://wdw.iptv-playoutcenter.de/wdw/wdw1/playlist.m3u8
#EXTINF:-1 tvg-id="Wir24TV.de",Wir24 TV (1080p) [Geo-blocked] #EXTINF:-1 tvg-id="Wir24TV.de",Wir24 TV (1080p) [Geo-blocked]
@ -510,7 +501,9 @@ https://zdf-hls-16.akamaized.net/hls/live/2016499/de/high/master.m3u8
https://ef56ef401101403a8b06f1dec29ef1eb.mediatailor.us-east-1.amazonaws.com/v1/master/44f73ba4d03e9607dcd9bebdcb8494d86964f1d8/Samsung-de_ZeeOne/playlist.m3u8 https://ef56ef401101403a8b06f1dec29ef1eb.mediatailor.us-east-1.amazonaws.com/v1/master/44f73ba4d03e9607dcd9bebdcb8494d86964f1d8/Samsung-de_ZeeOne/playlist.m3u8
#EXTINF:-1 tvg-id="ZweiMusicTelevision.de",ZWEI2 Music (1080p) #EXTINF:-1 tvg-id="ZweiMusicTelevision.de",ZWEI2 Music (1080p)
https://cdne.folxplay.tv/folx-trz/streams/ch-2/master.m3u8 https://cdne.folxplay.tv/folx-trz/streams/ch-2/master.m3u8
#EXTINF:-1 tvg-id="WELT.de",WELT #EXTINF:-1 tvg-id="MCTV.de",MC TV (720p)
https://s6.hopslan.com/n24X/index.m3u8 https://rrr.sz.xlcdn.com/?account=mceutv&file=mc2&type=live&service=wowza&protocol=https&output=playlist.m3u8
#EXTINF:-1 tvg-id="Nickelodeon.de",Nickelodeon #EXTINF:-1 tvg-id="RFH.de",RFH (1080p)
https://ma.anixa.tv/clips/stream/nickelodeon/playlist.php https://h056.video-stream-hosting.de/medienasa-live/_definst_/mp4:RFH_high/index.m3u8
#EXTINF:-1 tvg-id="AlexBerlin.de",Alex Berlin (1080p)
https://alex-stream.rosebud-media.de/bounce/alexlivetv50.smil/index.m3u8

View file

@ -185,6 +185,8 @@ https://ss3.domint.net:3136/gtv_str/globalhd/playlist.m3u8
https://imagenuniversaltv.net:3820/live/guacaratvlive.m3u8 https://imagenuniversaltv.net:3820/live/guacaratvlive.m3u8
#EXTINF:-1 tvg-id="",Guaymate [Not 24/7] #EXTINF:-1 tvg-id="",Guaymate [Not 24/7]
https://5790d294af2dc.streamlock.net/8100/8100/playlist.m3u8 https://5790d294af2dc.streamlock.net/8100/8100/playlist.m3u8
#EXTINF:-1 tvg-id="GuaymateTV.do",Guaymate TV (720p)
https://ssh101stream.ssh101.com/akamaissh101/ssh101/guaymatetv/playlist.m3u8
#EXTINF:-1 tvg-id="HainaVision.do",Haina Vision (720p) #EXTINF:-1 tvg-id="HainaVision.do",Haina Vision (720p)
https://cdn.streamingcpanel.com:3447/live/hainavisionlive.m3u8 https://cdn.streamingcpanel.com:3447/live/hainavisionlive.m3u8
#EXTINF:-1 tvg-id="HermanasMirabalTV.do",Hermanas Mirabal TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="HermanasMirabalTV.do",Hermanas Mirabal TV (720p) [Not 24/7]
@ -517,5 +519,3 @@ https://ss3.domint.net:3108/zol_str/vzol/playlist.m3u8
https://5790d294af2dc.streamlock.net/Zonavisiontv/Zonavisiontv/playlist.m3u8 https://5790d294af2dc.streamlock.net/Zonavisiontv/Zonavisiontv/playlist.m3u8
#EXTINF:-1 tvg-id="ZTV.do",ZTV (720p) [Not 24/7] #EXTINF:-1 tvg-id="ZTV.do",ZTV (720p) [Not 24/7]
https://lb00zdigital.streamprolive.com/mnt/hls/live.m3u8 https://lb00zdigital.streamprolive.com/mnt/hls/live.m3u8
#EXTINF:-1 tvg-id="GuaymateTV.do",Guaymate TV (720p)
https://ssh101stream.ssh101.com/akamaissh101/ssh101/guaymatetv/playlist.m3u8

View file

@ -130,8 +130,6 @@ https://ssh101-fl.bozztv.com/ssh101/scandalotv/index.m3u8
https://eu1.servers10.com:8081/8108/index.m3u8 https://eu1.servers10.com:8081/8108/index.m3u8
#EXTINF:-1 tvg-id="SonoOndaTV.ec",Sono Onda TV (720p) #EXTINF:-1 tvg-id="SonoOndaTV.ec",Sono Onda TV (720p)
https://live.obslivestream.com/sonoondatv/index.m3u8 https://live.obslivestream.com/sonoondatv/index.m3u8
#EXTINF:-1 tvg-id="Teleamazonas.ec",Teleamazonas (1080p) [Geo-blocked]
https://teleamazonas-live.cdn.vustreams.com/live/0fc97608-6057-4db8-9af7-102c21ac18af/live.isml/0fc97608-6057-4db8-9af7-102c21ac18af.m3u8
#EXTINF:-1 tvg-id="Teledigital.ec",Teledigital (240p) [Not 24/7] #EXTINF:-1 tvg-id="Teledigital.ec",Teledigital (240p) [Not 24/7]
https://tv.portalexpress.es:3182/hybrid/play.m3u8 https://tv.portalexpress.es:3182/hybrid/play.m3u8
#EXTINF:-1 tvg-id="Telerama.ec",Telerama (240p) [Not 24/7] #EXTINF:-1 tvg-id="Telerama.ec",Telerama (240p) [Not 24/7]
@ -154,3 +152,5 @@ https://cloud37.ecuatel.com/vostv/live/manifest.m3u8
https://video2.makrodigital.com/wuanplus/wuanplus/playlist.m3u8 https://video2.makrodigital.com/wuanplus/wuanplus/playlist.m3u8
#EXTINF:-1 tvg-id="ZaracayTV.ec",Zaracay TV (1080p) [Not 24/7] #EXTINF:-1 tvg-id="ZaracayTV.ec",Zaracay TV (1080p) [Not 24/7]
https://video2.makrodigital.com/zaracay/zaracay/playlist.m3u8 https://video2.makrodigital.com/zaracay/zaracay/playlist.m3u8
#EXTINF:-1 tvg-id="Teleamazonas.ec",Teleamazonas (1080p)
https://teleamazonas-live.cdn.vustreams.com/live/fd4ab346-b4e3-4628-abf0-b5a1bc192428/live.isml/playlist.m3u8

View file

@ -45,9 +45,13 @@ https://shls-masr2-ak.akamaized.net/out/v1/f683685242b549f48ea8a5171e3e993a/inde
https://nogoumtv.nrpstream.com/hls/stream.m3u8 https://nogoumtv.nrpstream.com/hls/stream.m3u8
#EXTINF:-1 tvg-id="PNCDrama.eg",PNC Drama (1080p) #EXTINF:-1 tvg-id="PNCDrama.eg",PNC Drama (1080p)
https://d35j504z0x2vu2.cloudfront.net/v1/master/0bc8e8376bd8417a1b6761138aa41c26c7309312/pnc-drama/playlist.m3u8 https://d35j504z0x2vu2.cloudfront.net/v1/master/0bc8e8376bd8417a1b6761138aa41c26c7309312/pnc-drama/playlist.m3u8
#EXTINF:-1 tvg-id="TeN.eg",TeN (720p) [Geo-blocked]
https://weyyak-live.akamaized.net/weyyak_ten_tv/index.m3u8
#EXTINF:-1 tvg-id="TheKingdomSat.eg",The Kingdom Sat (720p) #EXTINF:-1 tvg-id="TheKingdomSat.eg",The Kingdom Sat (720p)
https://bcovlive-a.akamaihd.net/0e524e1838ed411dad0a674d18e07914/eu-central-1/6415808954001/playlist_dvr.m3u8 https://bcovlive-a.akamaihd.net/0e524e1838ed411dad0a674d18e07914/eu-central-1/6415808954001/playlist_dvr.m3u8
#EXTINF:-1 tvg-id="WatanTV.eg",Watan TV (1080p) #EXTINF:-1 tvg-id="WatanTV.eg",Watan TV (1080p)
https://rp.tactivemedia.com/watantv_source/live/playlist.m3u8 https://rp.tactivemedia.com/watantv_source/live/playlist.m3u8
#EXTINF:-1 tvg-id="TeN.eg",TeN (720p) [Geo-blocked] #EXTINF:-1 tvg-id="RotanaCinemaEgypt.eg",Rotana Cinema Egypt (1080p)
https://weyyak-live.akamaized.net/weyyak_ten_tv/index.m3u8 https://rotana.hibridcdn.net/rotana/cinemamasr_net-7Y83PP5adWixDF93/playlist.m3u8
#EXTINF:-1 tvg-id="OnE.eg",On E (1080p)
https://bcovlive-a.akamaihd.net/3dc60bab470f4c9fbf00408ecb7c3d7a/eu-west-1/6057955906001/playlist_dvr.m3u8

View file

@ -52,10 +52,20 @@ https://cls.alcarria.tv/alcarriatv/livestream/playlist.m3u8
http://vegafibratv.com:8085/AMC/index.m3u8 http://vegafibratv.com:8085/AMC/index.m3u8
#EXTINF:-1 tvg-id="Antena3.es",Antena 3 (720p) #EXTINF:-1 tvg-id="Antena3.es",Antena 3 (720p)
http://185.189.225.150:85/Antena3HD/index.m3u8 http://185.189.225.150:85/Antena3HD/index.m3u8
#EXTINF:-1 tvg-id="AquiNoHayQuienViva.es",Aqui No Hay Quien Viva (720p)
https://fast-channels.atresmedia.com/648ef3951756b0e425af83cc/648ef3951756b0e425af83cc.m3u8
#EXTINF:-1 tvg-id="ArabiTV.es",Arabí TV (1080p) #EXTINF:-1 tvg-id="ArabiTV.es",Arabí TV (1080p)
https://streamtv2.elitecomunicacion.cloud:3956/live/arabitvlive.m3u8 https://streamtv2.elitecomunicacion.cloud:3956/live/arabitvlive.m3u8
#EXTINF:-1 tvg-id="AragonTV.es",Aragón TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="AragonTV.es",Aragón TV (720p) [Not 24/7]
https://cartv.streaming.aranova.es/hls/live/aragontv_canal1.m3u8 https://cartv.streaming.aranova.es/hls/live/aragontv_canal1.m3u8
#EXTINF:-1 tvg-id="AtresplayerClasicos.es",Atresplayer Clasicos (1080p)
https://fast-channels.atresmedia.com/648ef12c2bfab0e4507e0d61/648ef12c2bfab0e4507e0d61.m3u8
#EXTINF:-1 tvg-id="AtresplayerComedia.es",Atresplayer Comedia (1080p)
https://fast-channels.atresmedia.com/648ef23d2bfab0e4557e0d61/648ef23d2bfab0e4557e0d61.m3u8
#EXTINF:-1 tvg-id="AtresplayerInquietos.es",Atresplayer Inquietos (1080p)
https://fast-channels.atresmedia.com/648ef3162bfab0e4587e0d61/648ef3162bfab0e4587e0d61.m3u8
#EXTINF:-1 tvg-id="AtresplayerMulticine.es",Atresplayer Multicine (1080p)
https://fast-channels.atresmedia.com/648ef18c1756b0e41daf83cc/648ef18c1756b0e41daf83cc.m3u8
#EXTINF:-1 tvg-id="BabyTV.es",BabyTV (Spain) (1080p) #EXTINF:-1 tvg-id="BabyTV.es",BabyTV (Spain) (1080p)
http://185.189.225.150:85/BabyTV/index.m3u8 http://185.189.225.150:85/BabyTV/index.m3u8
#EXTINF:-1 tvg-id="BailenTV.es",Bailén TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="BailenTV.es",Bailén TV (720p) [Not 24/7]
@ -69,6 +79,8 @@ https://cdnapisec.kaltura.com/p/2346171/sp/234617100/playManifest/entryId/1_n644
https://cdnapisec.kaltura.com/p/2346171/sp/234617100/playManifest/entryId/1_n6442jz0/format/applehttp/protocol/https/uiConfId/42816492/a.m3u8?referrer=aHR0cHM6Ly9iZXRldmUuY2F0 https://cdnapisec.kaltura.com/p/2346171/sp/234617100/playManifest/entryId/1_n6442jz0/format/applehttp/protocol/https/uiConfId/42816492/a.m3u8?referrer=aHR0cHM6Ly9iZXRldmUuY2F0
#EXTINF:-1 tvg-id="BiosferaTV.es",Biosfera TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="BiosferaTV.es",Biosfera TV (720p) [Not 24/7]
https://tvdatta.com:3021/live/biosferatvlive.m3u8 https://tvdatta.com:3021/live/biosferatvlive.m3u8
#EXTINF:-1 tvg-id="Boing.es",Boing
http://185.189.225.150:85/boing/index.m3u8
#EXTINF:-1 tvg-id="BomCine.es",Bom Cine (576p) #EXTINF:-1 tvg-id="BomCine.es",Bom Cine (576p)
http://185.189.225.150:85/BOM/index.m3u8 http://185.189.225.150:85/BOM/index.m3u8
#EXTINF:-1 tvg-id="BonDiaTV.es",Bon Dia TV (1080p) #EXTINF:-1 tvg-id="BonDiaTV.es",Bon Dia TV (1080p)
@ -223,8 +235,12 @@ https://liveingesta318.cdnmedia.tv/9tvlive/smil:live.smil/playlist.m3u8?DVR=
https://directes-tv-cat.3catdirectes.cat/live-origin/c33-super3-hls/master.m3u8 https://directes-tv-cat.3catdirectes.cat/live-origin/c33-super3-hls/master.m3u8
#EXTINF:-1 tvg-id="El33SX3.es",El 33 SX3 (1080p) [Geo-blocked] #EXTINF:-1 tvg-id="El33SX3.es",El 33 SX3 (1080p) [Geo-blocked]
https://directes-tv-es.3catdirectes.cat/live-origin/c33-super3-hls/master.m3u8 https://directes-tv-es.3catdirectes.cat/live-origin/c33-super3-hls/master.m3u8
#EXTINF:-1 tvg-id="ElClubdelaComedia.es",El Club de la Comedia (1080p)
https://fast-channels.atresmedia.com/648f47f7a2ffb0e40aeff3ad/648f47f7a2ffb0e40aeff3ad.m3u8
#EXTINF:-1 tvg-id="ElConfidencialTV.es",El Confidencial TV (1080p) #EXTINF:-1 tvg-id="ElConfidencialTV.es",El Confidencial TV (1080p)
https://daqnsnf5phf17.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-sde7fypd1420w-prod/fast-channel-elconfidencial/fast-channel-elconfidencial.m3u8 https://daqnsnf5phf17.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-sde7fypd1420w-prod/fast-channel-elconfidencial/fast-channel-elconfidencial.m3u8
#EXTINF:-1 tvg-id="ElHormiguero.es",El Hormiguero (1080p)
https://fast-channels.atresmedia.com/648ef5882bfab0e4627e0d61/648ef5882bfab0e4627e0d61.m3u8
#EXTINF:-1 tvg-id="ElPaisTV.es",EL PAÍS TV (1080p) #EXTINF:-1 tvg-id="ElPaisTV.es",EL PAÍS TV (1080p)
https://d2xqbi89ghm9hh.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-79fx3huimw4xc-ssai-prd/fast-channel-el-pais.m3u8 https://d2xqbi89ghm9hh.cloudfront.net/v1/master/3722c60a815c199d9c0ef36c5b73da68a62b09d1/cc-79fx3huimw4xc-ssai-prd/fast-channel-el-pais.m3u8
#EXTINF:-1 tvg-id="ElToroTV.es",El Toro TV (720p) #EXTINF:-1 tvg-id="ElToroTV.es",El Toro TV (720p)
@ -233,6 +249,8 @@ https://streaming-1.eltorotv.com/lb0/eltorotv-streaming-web/index.m3u8
https://elche7tv.gestec-video.com/hls/canal2.m3u8 https://elche7tv.gestec-video.com/hls/canal2.m3u8
#EXTINF:-1 tvg-id="EmpordaTV.es",Empordà TV (1080p) #EXTINF:-1 tvg-id="EmpordaTV.es",Empordà TV (1080p)
https://video3.lhdserver.es/empordatv2/live.m3u8 https://video3.lhdserver.es/empordatv2/live.m3u8
#EXTINF:-1 tvg-id="EquipodeInvestigacion.es",Equipo de Investigacion (1080p)
https://fast-channels.atresmedia.com/648ef5551756b0e429af83cc/648ef5551756b0e429af83cc.m3u8
#EXTINF:-1 tvg-id="ErloTelebista.es",Erlo Telebista (720p) #EXTINF:-1 tvg-id="ErloTelebista.es",Erlo Telebista (720p)
https://5940924978228.streamlock.net/8159/8159/master.m3u8 https://5940924978228.streamlock.net/8159/8159/master.m3u8
#EXTINF:-1 tvg-id="Esport3.es",Esport3 (1080p) [Geo-blocked] #EXTINF:-1 tvg-id="Esport3.es",Esport3 (1080p) [Geo-blocked]
@ -261,8 +279,12 @@ https://media2.streambrothers.com:1936/8150/8150/playlist.m3u8
http://185.189.225.150:85/fdf/index.m3u8 http://185.189.225.150:85/fdf/index.m3u8
#EXTINF:-1 tvg-id="Fibwi.es",Fibwi (1080p) [Not 24/7] #EXTINF:-1 tvg-id="Fibwi.es",Fibwi (1080p) [Not 24/7]
https://hostcdn3.fibwi.com/fibwi_diario/index.fmp4.m3u8 https://hostcdn3.fibwi.com/fibwi_diario/index.fmp4.m3u8
#EXTINF:-1 tvg-id="FisicaoQuimica.es",Fisica o Quimica (1080p)
https://fast-channels.atresmedia.com/648ef50a2bfab0e4607e0d61/648ef50a2bfab0e4607e0d61.m3u8
#EXTINF:-1 tvg-id="FitelTV.es",Fitel TV (1080p) #EXTINF:-1 tvg-id="FitelTV.es",Fitel TV (1080p)
https://tv.mywifisocial.es/live.m3u8 https://tv.mywifisocial.es/live.m3u8
#EXTINF:-1 tvg-id="Flooxer.es",Flooxer (1080p)
https://fast-channels.atresmedia.com/5c1285e47ed1a861f8125285/5c1285e47ed1a861f8125285.m3u8
#EXTINF:-1 tvg-id="FuengirolaTV.es",Fuengirola TV (360p) [Not 24/7] #EXTINF:-1 tvg-id="FuengirolaTV.es",Fuengirola TV (360p) [Not 24/7]
https://secure.todostreaming.es/live/nerja-livestream.m3u8 https://secure.todostreaming.es/live/nerja-livestream.m3u8
#EXTINF:-1 tvg-id="FuerteventuraTV.es",Fuerteventura TV (1080p) #EXTINF:-1 tvg-id="FuerteventuraTV.es",Fuerteventura TV (1080p)
@ -442,6 +464,8 @@ https://tv.portalexpress.es:3731/stream/play.m3u8
https://tvmelilla-hls-rm-lw.flumotion.com/playlist.m3u8 https://tvmelilla-hls-rm-lw.flumotion.com/playlist.m3u8
#EXTINF:-1 tvg-id="RadioTelevisionMogan.es",Radio Televisión Mogán (1080p) #EXTINF:-1 tvg-id="RadioTelevisionMogan.es",Radio Televisión Mogán (1080p)
https://cloudvideo.servers10.com:8081/8028/index.m3u8 https://cloudvideo.servers10.com:8081/8028/index.m3u8
#EXTINF:-1 tvg-id="RakutenViki.es",Rakuten Viki (1080p)
https://newidco-rakutenviki-2-eu.xiaomi.wurl.tv/playlist.m3u8
#EXTINF:-1 tvg-id="RakutenViki.es",Rakuten Viki (720p) #EXTINF:-1 tvg-id="RakutenViki.es",Rakuten Viki (720p)
https://fd18f1cadd404894a31a3362c5f319bd.mediatailor.us-east-1.amazonaws.com/v1/manifest/04fd913bb278d8775298c26fdca9d9841f37601f/RakutenTV-eu_RakutenViki-1/048a962c-e84b-4a0e-aeb3-98376f4b9953/2.m3u8 https://fd18f1cadd404894a31a3362c5f319bd.mediatailor.us-east-1.amazonaws.com/v1/manifest/04fd913bb278d8775298c26fdca9d9841f37601f/RakutenTV-eu_RakutenViki-1/048a962c-e84b-4a0e-aeb3-98376f4b9953/2.m3u8
#EXTINF:-1 tvg-id="RealMadridTV.es",Real Madrid TV (404p) #EXTINF:-1 tvg-id="RealMadridTV.es",Real Madrid TV (404p)
@ -655,27 +679,13 @@ https://janus.xpbroadcasting.com:8443/hls/xptvUS.m3u8
#EXTINF:-1 tvg-id="ZafraTV.es" http-referrer="https://player.streamingconnect.com/",Zafra TV (1080p) #EXTINF:-1 tvg-id="ZafraTV.es" http-referrer="https://player.streamingconnect.com/",Zafra TV (1080p)
#EXTVLCOPT:http-referrer=https://player.streamingconnect.com/ #EXTVLCOPT:http-referrer=https://player.streamingconnect.com/
https://cloud.fastchannel.es/mic/manifiest/hls/radiotvzafra/radiotvzafra.m3u8 https://cloud.fastchannel.es/mic/manifiest/hls/radiotvzafra/radiotvzafra.m3u8
#EXTINF:-1 tvg-id="RakutenViki.es",Rakuten Viki (1080p) #EXTINF:-1 tvg-id="Atreseries.es",Atreseries (480p)
https://newidco-rakutenviki-2-eu.xiaomi.wurl.tv/playlist.m3u8 http://181.78.109.48:8000/play/a00l/index.m3u8
#EXTINF:-1 tvg-id="AtresplayerInquietos.es",Atresplayer Inquietos (1080p) #EXTINF:-1 tvg-id="Antena3.es",Antena 3 (480p)
https://fast-channels.atresmedia.com/648ef3162bfab0e4587e0d61/648ef3162bfab0e4587e0d61.m3u8 http://181.78.109.48:8000/play/a00f/index.m3u8
#EXTINF:-1 tvg-id="AtresplayerMulticine.es",Atresplayer Multicine (1080p) #EXTINF:-1 tvg-id="AXN.es",AXN (1080p)
https://fast-channels.atresmedia.com/648ef18c1756b0e41daf83cc/648ef18c1756b0e41daf83cc.m3u8 http://181.78.109.48:8000/play/a05u/index.m3u8
#EXTINF:-1 tvg-id="AtresplayerComedia.es",Atresplayer Comedia (1080p) #EXTINF:-1 tvg-id="AXN.es",AXN (480p)
https://fast-channels.atresmedia.com/648ef23d2bfab0e4557e0d61/648ef23d2bfab0e4557e0d61.m3u8 http://181.78.109.48:8000/play/a023/index.m3u8
#EXTINF:-1 tvg-id="AtresplayerClasicos.es",Atresplayer Clasicos (1080p) #EXTINF:-1 tvg-id="Nickelodeon.es",Nickelodeon (480p)
https://fast-channels.atresmedia.com/648ef12c2bfab0e4507e0d61/648ef12c2bfab0e4507e0d61.m3u8 http://181.78.109.48:8000/play/a05a/index.m3u8
#EXTINF:-1 tvg-id="Flooxer.es",Flooxer (1080p)
https://fast-channels.atresmedia.com/5c1285e47ed1a861f8125285/5c1285e47ed1a861f8125285.m3u8
#EXTINF:-1 tvg-id="FisicaoQuimica.es",Fisica o Quimica (1080p)
https://fast-channels.atresmedia.com/648ef50a2bfab0e4607e0d61/648ef50a2bfab0e4607e0d61.m3u8
#EXTINF:-1 tvg-id="EquipodeInvestigacion.es",Equipo de Investigacion (1080p)
https://fast-channels.atresmedia.com/648ef5551756b0e429af83cc/648ef5551756b0e429af83cc.m3u8
#EXTINF:-1 tvg-id="ElHormiguero.es",El Hormiguero (1080p)
https://fast-channels.atresmedia.com/648ef5882bfab0e4627e0d61/648ef5882bfab0e4627e0d61.m3u8
#EXTINF:-1 tvg-id="ElClubdelaComedia.es",El Club de la Comedia (1080p)
https://fast-channels.atresmedia.com/648f47f7a2ffb0e40aeff3ad/648f47f7a2ffb0e40aeff3ad.m3u8
#EXTINF:-1 tvg-id="AquiNoHayQuienViva.es",Aqui No Hay Quien Viva (720p)
https://fast-channels.atresmedia.com/648ef3951756b0e425af83cc/648ef3951756b0e425af83cc.m3u8
#EXTINF:-1 tvg-id="Boing.es",Boing
http://185.189.225.150:85/boing/index.m3u8

View file

@ -3,8 +3,6 @@
https://dhx-caillou-1-es.samsung.wurl.tv/playlist.m3u8 https://dhx-caillou-1-es.samsung.wurl.tv/playlist.m3u8
#EXTINF:-1 tvg-id="EuronewsSpanish.fr",Euronews en Español (720p) #EXTINF:-1 tvg-id="EuronewsSpanish.fr",Euronews en Español (720p)
https://rakuten-euronews-4-es.samsung.wurl.tv/manifest/playlist.m3u8 https://rakuten-euronews-4-es.samsung.wurl.tv/manifest/playlist.m3u8
#EXTINF:-1 tvg-id="FashionTVEurope.fr",Fashion TV (Spain) (1080p)
https://fashiontv-fashiontv-2-es.samsung.wurl.tv/manifest/playlist.m3u8
#EXTINF:-1 tvg-id="",iHola Play #EXTINF:-1 tvg-id="",iHola Play
https://rakuten-hola-2-es.samsung.wurl.tv/playlist.m3u8 https://rakuten-hola-2-es.samsung.wurl.tv/playlist.m3u8
#EXTINF:-1 tvg-id="PeopleAreAwesome.us",People are Awesome #EXTINF:-1 tvg-id="PeopleAreAwesome.us",People are Awesome

View file

@ -1,4 +1,6 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="6ter.fr",6ter
https://origin-caf900c010ea8046.live.6cloud.fr/out/v1/29c7a579af3348b48230f76cd75699a5/dash_short_cenc10_6ter_hd_index.mpd
#EXTINF:-1 tvg-id="20MinutesTV.fr",20 Minutes TV (1080p) #EXTINF:-1 tvg-id="20MinutesTV.fr",20 Minutes TV (1080p)
https://lives.digiteka.com/stream/86d3e867-a272-496b-8412-f59aa0104771/index.m3u8 https://lives.digiteka.com/stream/86d3e867-a272-496b-8412-f59aa0104771/index.m3u8
#EXTINF:-1 tvg-id="",A12 TV (720p) #EXTINF:-1 tvg-id="",A12 TV (720p)
@ -59,6 +61,8 @@ https://raw.githubusercontent.com/Paradise-91/ParaTV/main/streams/equidia/live2.
https://raw.githubusercontent.com/Paradise-91/ParaTV/main/streams/equidia/racingmag.m3u8 https://raw.githubusercontent.com/Paradise-91/ParaTV/main/streams/equidia/racingmag.m3u8
#EXTINF:-1 tvg-id="EreTV.fr",Ère TV (1080p) #EXTINF:-1 tvg-id="EreTV.fr",Ère TV (1080p)
https://mn-nl.mncdn.com/awraastv/awraastv_hd.smil/playlist.m3u8 https://mn-nl.mncdn.com/awraastv/awraastv_hd.smil/playlist.m3u8
#EXTINF:-1 tvg-id="EuronewsEnglishHD.fr",Euronews English HD (1080p)
http://stream01.vnet.am/Channel_119/mono.m3u8
#EXTINF:-1 tvg-id="FashionTVCzechSlovak.fr",FashionTV Czech&Slovak (450p) [Not 24/7] #EXTINF:-1 tvg-id="FashionTVCzechSlovak.fr",FashionTV Czech&Slovak (450p) [Not 24/7]
http://lb.streaming.sk/fashiontv/stream/playlist.m3u8 http://lb.streaming.sk/fashiontv/stream/playlist.m3u8
#EXTINF:-1 tvg-id="France2.fr",France 2 (1080p) #EXTINF:-1 tvg-id="France2.fr",France 2 (1080p)
@ -185,6 +189,8 @@ http://178.170.47.109/MTVHITS/index.m3u8
http://190.2.155.162:8080/mtvhit/mpegts http://190.2.155.162:8080/mtvhit/mpegts
#EXTINF:-1 tvg-id="MuseumTVFrench.fr",Museum TV (1080p) #EXTINF:-1 tvg-id="MuseumTVFrench.fr",Museum TV (1080p)
https://live2.creacast.com/museum-france/smil:museum-france.smil/master.m3u8 https://live2.creacast.com/museum-france/smil:museum-france.smil/master.m3u8
#EXTINF:-1 tvg-id="MuseumTVEnglish.fr",Museum TV English (1080p)
https://cdn-ue1-prod.tsv2.amagi.tv/linear/amg01492-secomsasmediart-museumtven-xiaomi/playlist.m3u8
#EXTINF:-1 tvg-id="MyZenTV.fr",MyZen TV (1080p) #EXTINF:-1 tvg-id="MyZenTV.fr",MyZen TV (1080p)
https://cdn-ue1-prod.tsv2.amagi.tv/linear/amg01255-secomcofites-my-myzen-en-plex/playlist.m3u8 https://cdn-ue1-prod.tsv2.amagi.tv/linear/amg01255-secomcofites-my-myzen-en-plex/playlist.m3u8
#EXTINF:-1 tvg-id="NancyWebTV.fr",Nancy Web TV (394p) [Not 24/7] #EXTINF:-1 tvg-id="NancyWebTV.fr",Nancy Web TV (394p) [Not 24/7]
@ -223,6 +229,10 @@ https://raw.githubusercontent.com/Paradise-91/ParaTV/main/streams/tf1plus/tf1.m3
https://raw.githubusercontent.com/Paradise-91/ParaTV/main/streams/tf1plus/tf1sf.m3u8 https://raw.githubusercontent.com/Paradise-91/ParaTV/main/streams/tf1plus/tf1sf.m3u8
#EXTINF:-1 tvg-id="TFX.fr",TFX (720p) [Geo-blocked] #EXTINF:-1 tvg-id="TFX.fr",TFX (720p) [Geo-blocked]
https://raw.githubusercontent.com/Paradise-91/ParaTV/main/streams/tf1plus/tfx.m3u8 https://raw.githubusercontent.com/Paradise-91/ParaTV/main/streams/tf1plus/tfx.m3u8
#EXTINF:-1 tvg-id="TiVi5Monde.fr",TiVi5 Monde [Geo-blocked]
https://ott.tv5monde.com/Content/HLS/Live/channel(tivi5)/variant.m3u8
#EXTINF:-1 tvg-id="TiVi5Monde.fr",TiVi5Monde (1080p)
http://154.197.91.168:7001/play/a0dz/index.m3u8
#EXTINF:-1 tvg-id="TMC.fr",TMC (720p) [Geo-blocked] #EXTINF:-1 tvg-id="TMC.fr",TMC (720p) [Geo-blocked]
https://raw.githubusercontent.com/Paradise-91/ParaTV/main/streams/tf1plus/tmc.m3u8 https://raw.githubusercontent.com/Paradise-91/ParaTV/main/streams/tf1plus/tmc.m3u8
#EXTINF:-1 tvg-id="TraceLatina.fr",Trace Latina #EXTINF:-1 tvg-id="TraceLatina.fr",Trace Latina
@ -231,8 +241,6 @@ http://185.234.217.27:8002/play/a02f/index.m3u8
https://amg01131-tracetv-amg01131c1-rakuten-us-1081.playouts.now.amagi.tv/playlist/amg01131-tracetvfast-traceurban-rakutenus/playlist.m3u8 https://amg01131-tracetv-amg01131c1-rakuten-us-1081.playouts.now.amagi.tv/playlist/amg01131-tracetvfast-traceurban-rakutenus/playlist.m3u8
#EXTINF:-1 tvg-id="TV3V.fr",TV3V (720p) #EXTINF:-1 tvg-id="TV3V.fr",TV3V (720p)
https://tv3v.hdr-tv.com/live/tv3v/livestream/master.m3u8 https://tv3v.hdr-tv.com/live/tv3v/livestream/master.m3u8
#EXTINF:-1 tvg-id="TiVi5Monde.fr",TiVi5Monde (1080p)
http://154.197.91.168:7001/play/a0dz/index.m3u8
#EXTINF:-1 tvg-id="TV5MondeAsia.fr",TV5 Monde Asia (Asie) (1080p) [Geo-blocked] #EXTINF:-1 tvg-id="TV5MondeAsia.fr",TV5 Monde Asia (Asie) (1080p) [Geo-blocked]
https://ott.tv5monde.com/Content/HLS/Live/channel(seasie)/variant.m3u8 https://ott.tv5monde.com/Content/HLS/Live/channel(seasie)/variant.m3u8
#EXTINF:-1 tvg-id="TV5MondeEurope.fr",TV5Monde Europe (1080p) [Geo-blocked] #EXTINF:-1 tvg-id="TV5MondeEurope.fr",TV5Monde Europe (1080p) [Geo-blocked]
@ -275,11 +283,3 @@ https://vosgestv.live-kd.com/live/vosgestv/vosgestv/playlist.m3u8
https://live.digiteka.com/1/WGQ1NnhEN0lzM0NU/dk1EOHhw/hls/live/playlist.m3u8 https://live.digiteka.com/1/WGQ1NnhEN0lzM0NU/dk1EOHhw/hls/live/playlist.m3u8
#EXTINF:-1 tvg-id="Weo.fr",Wéo (Picardie) (480p) [Not 24/7] #EXTINF:-1 tvg-id="Weo.fr",Wéo (Picardie) (480p) [Not 24/7]
https://live.digiteka.com/1/Zks2L0VsM2V0T242/QTBqcFly/hls/live/playlist.m3u8 https://live.digiteka.com/1/Zks2L0VsM2V0T242/QTBqcFly/hls/live/playlist.m3u8
#EXTINF:-1 tvg-id="6ter.fr",6ter
https://origin-caf900c010ea8046.live.6cloud.fr/out/v1/29c7a579af3348b48230f76cd75699a5/dash_short_cenc10_6ter_hd_index.mpd
#EXTINF:-1 tvg-id="EuronewsEnglishHD.fr",Euronews English HD (1080p)
http://stream01.vnet.am/Channel_119/mono.m3u8
#EXTINF:-1 tvg-id="MuseumTVEnglish.fr",Museum TV English (1080p)
https://cdn-ue1-prod.tsv2.amagi.tv/linear/amg01492-secomsasmediart-museumtven-xiaomi/playlist.m3u8
#EXTINF:-1 tvg-id="TiVi5Monde.fr",TiVi5 Monde [Geo-blocked]
https://ott.tv5monde.com/Content/HLS/Live/channel(tivi5)/variant.m3u8

View file

@ -1,6 +1,6 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="ETV.gp",ETV (1080p) #EXTINF:-1 tvg-id="ETV.gp",ETV (1080p)
https://edge.vedge.infomaniak.com/livecast/ik:etvgp/manifest.m3u8 https://edge12.vedge.infomaniak.com/livecast/ik:etvgp/manifest.m3u8
#EXTINF:-1 tvg-id="MadrasFMTV.gp",Madras FM TV (1080p) #EXTINF:-1 tvg-id="MadrasFMTV.gp",Madras FM TV (1080p)
https://edge12.vedge.infomaniak.com/livecast/ik:madrasfmtv/manifest.m3u8 https://edge12.vedge.infomaniak.com/livecast/ik:madrasfmtv/manifest.m3u8
#EXTINF:-1 tvg-id="RadioTVBasseTerre.gp",Radio TV Basse-Terre (720p) #EXTINF:-1 tvg-id="RadioTVBasseTerre.gp",Radio TV Basse-Terre (720p)

View file

@ -23,6 +23,10 @@ https://www.hellasnet.tv/rest2.live.hn/w2r.alf/playlist.m3u8
http://alphatvlive.siliconweb.com/1/Y2Rsd1lUcUVoajcv/UVdCN25h/hls/live/playlist.m3u8 http://alphatvlive.siliconweb.com/1/Y2Rsd1lUcUVoajcv/UVdCN25h/hls/live/playlist.m3u8
#EXTINF:-1 tvg-id="ANT1.gr",ANT1 (1080p) [Geo-blocked] #EXTINF:-1 tvg-id="ANT1.gr",ANT1 (1080p) [Geo-blocked]
http://d1nfykbwa3n98t.cloudfront.net/out/v1/6e5667da5a6843899a337dea72adb61b/antenna.m3u8 http://d1nfykbwa3n98t.cloudfront.net/out/v1/6e5667da5a6843899a337dea72adb61b/antenna.m3u8
#EXTINF:-1 tvg-id="ANT1.gr" http-referrer="http://watch.antennaplus.gr" http-user-agent="Chrome",ANT1 (1080p) [Geo-blocked]
#EXTVLCOPT:http-referrer=http://watch.antennaplus.gr
#EXTVLCOPT:http-user-agent=Chrome
https://mcdn.antennaplus.gr/live/media0/Ant1/HLS/Ant1.m3u8
#EXTINF:-1 tvg-id="ART.gr",APT (1080p) #EXTINF:-1 tvg-id="ART.gr",APT (1080p)
https://hugh.cdn.rumble.cloud/live/k5e12sb4/slot-82/fdd0-tbln/chunklist_DVR.m3u8 https://hugh.cdn.rumble.cloud/live/k5e12sb4/slot-82/fdd0-tbln/chunklist_DVR.m3u8
#EXTINF:-1 tvg-id="ARTTV.gr",ART TV (720p) #EXTINF:-1 tvg-id="ARTTV.gr",ART TV (720p)
@ -63,8 +67,6 @@ http://live.streams.ovh:1935/tvcreta/tvcreta/playlist.m3u8
http://81.171.10.42:554/liveD/DStream.sdp/playlist.m3u8 http://81.171.10.42:554/liveD/DStream.sdp/playlist.m3u8
#EXTINF:-1 tvg-id="DiavataTV.gr",Diavata TV (720p) #EXTINF:-1 tvg-id="DiavataTV.gr",Diavata TV (720p)
https://ssh101.bozztv.com/ssh101/diavatatvweb/playlist.m3u8 https://ssh101.bozztv.com/ssh101/diavatatvweb/playlist.m3u8
#EXTINF:-1 tvg-id="DiavataTV.gr",Diavata TV (720p)
https://video.streams.ovh:1936/DiavataTV/DiavataTV/playlist.m3u8
#EXTINF:-1 tvg-id="DiktyoTV.gr",Diktyo TV (576p) #EXTINF:-1 tvg-id="DiktyoTV.gr",Diktyo TV (576p)
https://5d00db0e0fcd5.streamlock.net/7322/7322/playlist.m3u8 https://5d00db0e0fcd5.streamlock.net/7322/7322/playlist.m3u8
#EXTINF:-1 tvg-id="DipsoTV.gr",Dipso TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="DipsoTV.gr",Dipso TV (720p) [Not 24/7]
@ -156,6 +158,8 @@ https://til.pp.ua:3872/live/mesogeiostvlive.m3u8
https://vod.streams.ovh:3876/stream/play.m3u8 https://vod.streams.ovh:3876/stream/play.m3u8
#EXTINF:-1 tvg-id="NaftemporikiTV.gr",Naftemporiki TV (1080p) #EXTINF:-1 tvg-id="NaftemporikiTV.gr",Naftemporiki TV (1080p)
https://naftemporiki-live.cdn.vustreams.com/live/a4b4a88a-681c-4a2d-8e74-33daa5f2cb61/live.isml/.m3u8 https://naftemporiki-live.cdn.vustreams.com/live/a4b4a88a-681c-4a2d-8e74-33daa5f2cb61/live.isml/.m3u8
#EXTINF:-1 tvg-id="NationalGeographic.gr",National Geographic (1080p)
http://62.210.211.188:2095/play/a00d
#EXTINF:-1 tvg-id="NeaTV.gr",Nea TV (720p) #EXTINF:-1 tvg-id="NeaTV.gr",Nea TV (720p)
https://live.neatv.gr:8888/hls/neatv.m3u8 https://live.neatv.gr:8888/hls/neatv.m3u8
#EXTINF:-1 tvg-id="NeaTV.gr",Nea TV (720p) #EXTINF:-1 tvg-id="NeaTV.gr",Nea TV (720p)
@ -277,9 +281,3 @@ http://live.cretetv.gr:1935/cretetv/myStream/f1tv.m3u8
https://vod.streams.ovh:3037/stream/play.m3u8 https://vod.streams.ovh:3037/stream/play.m3u8
#EXTINF:-1 tvg-id="RIKSat.cy",ΡΙΚ Sat (720p) [Not 24/7] #EXTINF:-1 tvg-id="RIKSat.cy",ΡΙΚ Sat (720p) [Not 24/7]
http://l3.cloudskep.com/cybcsat/abr/playlist.m3u8 http://l3.cloudskep.com/cybcsat/abr/playlist.m3u8
#EXTINF:-1 tvg-id="NationalGeographic.gr",National Geographic (1080p)
http://62.210.211.188:2095/play/a00d
#EXTINF:-1 tvg-id="ANT1.gr" http-referrer="http://watch.antennaplus.gr" http-user-agent="Chrome",ANT1 (1080p) [Geo-blocked]
#EXTVLCOPT:http-referrer=http://watch.antennaplus.gr
#EXTVLCOPT:http-user-agent=Chrome
https://mcdn.antennaplus.gr/live/media0/Ant1/HLS/Ant1.m3u8

View file

@ -199,12 +199,6 @@ http://194.76.186.33:8000/play/a05h/index.m3u8
http://194.76.186.33:8000/play/a02a/index.m3u8 http://194.76.186.33:8000/play/a02a/index.m3u8
#EXTINF:-1 tvg-id="RTLHarom.hu",RTL Harom (576p) #EXTINF:-1 tvg-id="RTLHarom.hu",RTL Harom (576p)
http://194.76.186.33:8000/play/a05d/index.m3u8 http://194.76.186.33:8000/play/a05d/index.m3u8
#EXTINF:-1 tvg-id="RTL.hu",RTL Hungary (1080p)
http://194.76.186.33:8000/play/a041/index.m3u8
#EXTINF:-1 tvg-id="RTL.hu",RTL Hungary (576p)
http://194.76.186.33:8000/play/a01e/index.m3u8
#EXTINF:-1 tvg-id="RTL.hu",RTL Hungary (576p)
http://194.76.186.33:8000/play/a04g/index.m3u8
#EXTINF:-1 tvg-id="RTLKetto.hu",RTL Ketto (1080p) #EXTINF:-1 tvg-id="RTLKetto.hu",RTL Ketto (1080p)
http://194.76.186.33:8000/play/a01z/index.m3u8 http://194.76.186.33:8000/play/a01z/index.m3u8
#EXTINF:-1 tvg-id="RTLKetto.hu",RTL Ketto (576p) #EXTINF:-1 tvg-id="RTLKetto.hu",RTL Ketto (576p)

View file

@ -1,12 +1,12 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="7SMusic.in",7S Music (576p) [Not 24/7] #EXTINF:-1 tvg-id="7SMusic.in",7S Music (576p) [Not 24/7]
http://103.199.161.254/Content/7smusic/Live/Channel(7smusic)/index.m3u8 http://103.199.161.254/Content/7smusic/Live/Channel(7smusic)/index.m3u8
#EXTINF:-1 tvg-id="9XJalwa.in",9X Jalwa
https://amg01281-9xmediapvtltd-9xjalwa-samsungin-goszf.amagi.tv/playlist/amg01281-9xmediapvtltd-9xjalwa-samsungin/playlist.m3u8
#EXTINF:-1 tvg-id="9XJhakaas.in",9x Jhakaas #EXTINF:-1 tvg-id="9XJhakaas.in",9x Jhakaas
https://amg01281-9xmediapvtltd-9xjhakaas-samsungin-ci2cs.amagi.tv/playlist/amg01281-9xmediapvtltd-9xjhakaas-samsungin/playlist.m3u8 https://amg01281-9xmediapvtltd-9xjhakaas-samsungin-ci2cs.amagi.tv/playlist/amg01281-9xmediapvtltd-9xjhakaas-samsungin/playlist.m3u8
#EXTINF:-1 tvg-id="9XTashan.in",9X Tashan #EXTINF:-1 tvg-id="9XTashan.in",9X Tashan
https://amg01281-9xmediapvtltd-9xtashan-samsungin-xz1sd.amagi.tv/playlist/amg01281-9xmediapvtltd-9xtashan-samsungin/playlist.m3u8 https://amg01281-9xmediapvtltd-9xtashan-samsungin-xz1sd.amagi.tv/playlist/amg01281-9xmediapvtltd-9xtashan-samsungin/playlist.m3u8
#EXTINF:-1 tvg-id="9XM.in",9XM (576p)
https://d35j504z0x2vu2.cloudfront.net/v1/manifest/0bc8e8376bd8417a1b6761138aa41c26c7309312/9xm/23886666-8fc5-470f-aab1-bd637ed607b1/3.m3u8
#EXTINF:-1 tvg-id="A1TVRajasthan.in",A1 TV Rajasthan (720p) #EXTINF:-1 tvg-id="A1TVRajasthan.in",A1 TV Rajasthan (720p)
https://5b48d7e1b4bce.streamlock.net/myapp/a1live/playlist.m3u8 https://5b48d7e1b4bce.streamlock.net/myapp/a1live/playlist.m3u8
#EXTINF:-1 tvg-id="AajTak.in",Aaj Tak #EXTINF:-1 tvg-id="AajTak.in",Aaj Tak
@ -646,6 +646,8 @@ https://yoganadam.cinesoftcdn.com/yoganadam/live/index.m3u8
https://zainabia.livebox.co.in/ZainabiaChannelhls/channel.m3u8 https://zainabia.livebox.co.in/ZainabiaChannelhls/channel.m3u8
#EXTINF:-1 tvg-id="Zee24Kalak.in",Zee 24 Kalak (720p) #EXTINF:-1 tvg-id="Zee24Kalak.in",Zee 24 Kalak (720p)
https://livetv-channels.b-cdn.net/8077/playlist.m3u8 https://livetv-channels.b-cdn.net/8077/playlist.m3u8
#EXTINF:-1 tvg-id="",Zee Alwan (576p) [Not 24/7]
https://tgn.bozztv.com/gin-dvrfl05/ga-zeealwan/index.m3u8
#EXTINF:-1 tvg-id="ZeeBiharJharkhand.in",Zee Bihar Jharkhand (720p) #EXTINF:-1 tvg-id="ZeeBiharJharkhand.in",Zee Bihar Jharkhand (720p)
https://d3dxf2v5wg5rcy.cloudfront.net/out/v1/349f643193e347609b16671d8e0bfb4a/index.m3u8 https://d3dxf2v5wg5rcy.cloudfront.net/out/v1/349f643193e347609b16671d8e0bfb4a/index.m3u8
#EXTINF:-1 tvg-id="ZeeBiharJharkhand.in",Zee Bihar Jharkhand (720p) #EXTINF:-1 tvg-id="ZeeBiharJharkhand.in",Zee Bihar Jharkhand (720p)
@ -674,7 +676,13 @@ https://livetv-channels.b-cdn.net/8076/playlist.m3u8
http://183.89.246.119:8881/play/a09a/index.m3u8 http://183.89.246.119:8881/play/a09a/index.m3u8
#EXTINF:-1 tvg-id="Zoom.in",Zoom (1080p) #EXTINF:-1 tvg-id="Zoom.in",Zoom (1080p)
http://103.81.104.118/hls/stream8.m3u8 http://103.81.104.118/hls/stream8.m3u8
#EXTINF:-1 tvg-id="ZeeAlwan.in",Zee Alwan (576p) [Not 24/7] #EXTINF:-1 tvg-id="ShowBox.in",ShowBox
https://tgn.bozztv.com/gin-dvrfl05/ga-zeealwan/index.m3u8 https://epiconvh.akamaized.net/live/showbox/master.m3u8
#EXTINF:-1 tvg-id="9XM.in",9XM (576p) #EXTINF:-1 tvg-id="RajTV.in",Raj TV
https://d35j504z0x2vu2.cloudfront.net/v1/manifest/0bc8e8376bd8417a1b6761138aa41c26c7309312/9xm/23886666-8fc5-470f-aab1-bd637ed607b1/3.m3u8 https://d3qs3d2rkhfqrt.cloudfront.net/out/v1/2839e3d1e0f84a2e821c1708d5fdfdf0/index.m3u8
#EXTINF:-1 tvg-id="DDSahyadri.in",DD Sahyadri
https://d3qs3d2rkhfqrt.cloudfront.net/out/v1/66dcc3ebe182447ba42837e746cf0c7c/index.m3u8
#EXTINF:-1 tvg-id="DDSaptagiri.in",DD Saptagiri
https://d2lk5u59tns74c.cloudfront.net/out/v1/26e915d6d12b4a06822c5e33c088ed56/index.m3u8
#EXTINF:-1 tvg-id="DDHaryana.in",DD Haryana
https://d2lk5u59tns74c.cloudfront.net/out/v1/950fc69666474351bde0a32b9600c804/index.m3u8

View file

@ -3,6 +3,8 @@
https://mediaserver.abnvideos.com/streams/abnsat.m3u8 https://mediaserver.abnvideos.com/streams/abnsat.m3u8
#EXTINF:-1 tvg-id="AfaqTV.iq",Afaq TV #EXTINF:-1 tvg-id="AfaqTV.iq",Afaq TV
http://63b03f7689049.streamlock.net:1935/live/1/playlist.m3u8 http://63b03f7689049.streamlock.net:1935/live/1/playlist.m3u8
#EXTINF:-1 tvg-id="AfarinBaxcha.iq",Afarin Baxcha (1080p)
https://5dcabf026b188.streamlock.net/afarinTV/livestream/playlist.m3u8
#EXTINF:-1 tvg-id="AfarinTV.iq",Afarin TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="AfarinTV.iq",Afarin TV (720p) [Not 24/7]
https://65f16f0fdfc51.streamlock.net/afarinTV/livestream/playlist.m3u8 https://65f16f0fdfc51.streamlock.net/afarinTV/livestream/playlist.m3u8
#EXTINF:-1 tvg-id="AlahadTV.iq",Al Ahad TV #EXTINF:-1 tvg-id="AlahadTV.iq",Al Ahad TV
@ -32,7 +34,7 @@ https://arrafidain.tvplayer.online/arrafidaintv/source2/playlist.m3u8
https://arrafidain.tvplayer.online/arrafidaintv/source/playlist.m3u8 https://arrafidain.tvplayer.online/arrafidaintv/source/playlist.m3u8
#EXTINF:-1 tvg-id="AlRasheedTV.iq",Al Rasheed TV (1080p) [Not 24/7] #EXTINF:-1 tvg-id="AlRasheedTV.iq",Al Rasheed TV (1080p) [Not 24/7]
https://media1.livaat.com/static/AL-RASHEED-HD/playlist.m3u8 https://media1.livaat.com/static/AL-RASHEED-HD/playlist.m3u8
#EXTINF:-1 tvg-id="AlShabab.iq",Al Shabab TV (1080p) #EXTINF:-1 tvg-id="",Al Shabab TV (1080p)
http://149.100.11.244:8001/play/a07n/index.m3u8 http://149.100.11.244:8001/play/a07n/index.m3u8
#EXTINF:-1 tvg-id="AlAimmaTV.iq" http-referrer="https://alaimma.tv",Al-Aimma TV (1080p) #EXTINF:-1 tvg-id="AlAimmaTV.iq" http-referrer="https://alaimma.tv",Al-Aimma TV (1080p)
#EXTVLCOPT:http-referrer=https://alaimma.tv #EXTVLCOPT:http-referrer=https://alaimma.tv
@ -138,6 +140,8 @@ http://stream.nubar.tv:1935/private/NUBARtv/playlist.m3u8
https://media2.streambrothers.com:1936/8218/8218/playlist.m3u8 https://media2.streambrothers.com:1936/8218/8218/playlist.m3u8
#EXTINF:-1 tvg-id="RudawTV.iq",Rudaw TV (1080p) #EXTINF:-1 tvg-id="RudawTV.iq",Rudaw TV (1080p)
https://svs.itworkscdn.net/rudawlive/rudawlive.smil/playlist.m3u8 https://svs.itworkscdn.net/rudawlive/rudawlive.smil/playlist.m3u8
#EXTINF:-1 tvg-id="ShamsTV.iq",Shams TV (1080p)
https://stream.shams.tv/hls/stream.m3u8
#EXTINF:-1 tvg-id="UTV.iq",UTV (1080p) #EXTINF:-1 tvg-id="UTV.iq",UTV (1080p)
https://mn-nl.mncdn.com/utviraqi2/64c80359/index.m3u8 https://mn-nl.mncdn.com/utviraqi2/64c80359/index.m3u8
#EXTINF:-1 tvg-id="WaarTV.iq",Waar TV #EXTINF:-1 tvg-id="WaarTV.iq",Waar TV
@ -146,7 +150,3 @@ https://ca-rt.onetv.app/Waar/index-0.m3u8
https://5a3ed7a72ed4b.streamlock.net/zagrostv/SMIL:myStream.smil/playlist.m3u8 https://5a3ed7a72ed4b.streamlock.net/zagrostv/SMIL:myStream.smil/playlist.m3u8
#EXTINF:-1 tvg-id="",Zarok TV Sorani (720p) #EXTINF:-1 tvg-id="",Zarok TV Sorani (720p)
https://zindisorani.zaroktv.com.tr/hls/stream.m3u8 https://zindisorani.zaroktv.com.tr/hls/stream.m3u8
#EXTINF:-1 tvg-id="AfarinBaxcha.iq",Afarin Baxcha (1080p)
https://5dcabf026b188.streamlock.net/afarinTV/livestream/playlist.m3u8
#EXTINF:-1 tvg-id="ShamsTV.iq",Shams TV (1080p)
https://stream.shams.tv/hls/stream.m3u8

View file

@ -71,3 +71,5 @@ https://hls.nejat.live/hls/stream.m3u8
https://hls.vox1.live/hls/stream.m3u8 https://hls.vox1.live/hls/stream.m3u8
#EXTINF:-1 tvg-id="YourTimeTV.ir",YourTime TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="YourTimeTV.ir",YourTime TV (720p) [Not 24/7]
https://hls.yourtime.live/hls/stream.m3u8 https://hls.yourtime.live/hls/stream.m3u8
#EXTINF:-1 tvg-id="VarzeshTV.ir",Varzesh TV (480p)
https://stream.sainaertebat.com/hls2/varzeshtest.m3u8

View file

@ -37,6 +37,8 @@ https://59d7d6f47d7fc.streamlock.net/auroraarte/auroraarte/playlist.m3u8
https://ed05.top-ix.org/avtvlive/azzurra/streaming/playlist.m3u8 https://ed05.top-ix.org/avtvlive/azzurra/streaming/playlist.m3u8
#EXTINF:-1 tvg-id="BikeChannel.it",Bike (720p) #EXTINF:-1 tvg-id="BikeChannel.it",Bike (720p)
http://backup.superstreaming.inaria.me/BikeSmartMobilityDTT/playlist.m3u8 http://backup.superstreaming.inaria.me/BikeSmartMobilityDTT/playlist.m3u8
#EXTINF:-1 tvg-id="Boing.it",Boing (720p)
https://liveturner.akamaized.net/75a4d1a90e744fa5b9901a1853d2c47f/eu-central-1/6284318116001/playlist.m3u8
#EXTINF:-1 tvg-id="Boing.it",Boing Italy [Geo-blocked] #EXTINF:-1 tvg-id="Boing.it",Boing Italy [Geo-blocked]
https://live2.msf.cdn.mediaset.net/content/hls_h0_clr_vos/live/channel(kb)/index.m3u8 https://live2.msf.cdn.mediaset.net/content/hls_h0_clr_vos/live/channel(kb)/index.m3u8
#EXTINF:-1 tvg-id="BomChannel.it",Bom Channel #EXTINF:-1 tvg-id="BomChannel.it",Bom Channel
@ -314,6 +316,9 @@ https://mediapolisevent.rai.it/relinker/relinkerServlet.htm?cont=2606803
https://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=308718 https://mediapolis.rai.it/relinker/relinkerServlet.htm?cont=308718
#EXTINF:-1 tvg-id="Rai2.it",Rai 2 (302p) [Geo-blocked] #EXTINF:-1 tvg-id="Rai2.it",Rai 2 (302p) [Geo-blocked]
http://stream.tvtap.net:8081/live/it-rai2.stream/playlist.m3u8 http://stream.tvtap.net:8081/live/it-rai2.stream/playlist.m3u8
#EXTINF:-1 tvg-id="Rai2HD.it" http-referrer="https://babaktv.com/",Rai 2 HD
#EXTVLCOPT:http-referrer=https://babaktv.com/
https://m3u.iranvids.com/rai02/output.m3u8
#EXTINF:-1 tvg-id="Rai3.it",Rai 3 (720p) #EXTINF:-1 tvg-id="Rai3.it",Rai 3 (720p)
https://dash2.antik.sk/live/test_rai_tre_tizen/playlist.m3u8 https://dash2.antik.sk/live/test_rai_tre_tizen/playlist.m3u8
#EXTINF:-1 tvg-id="Rai3.it",Rai 3 (720p) [Not 24/7] #EXTINF:-1 tvg-id="Rai3.it",Rai 3 (720p) [Not 24/7]
@ -662,8 +667,11 @@ https://stream.cp.ets-sistemi.it:1936/profservtv/profservtv/playlist.m3u8
https://5f22d76e220e1.streamlock.net/canale5/canale5/playlist.m3u8 https://5f22d76e220e1.streamlock.net/canale5/canale5/playlist.m3u8
#EXTINF:-1 tvg-id="ZerounoTVNews.it",Zerouno TV News (720p) #EXTINF:-1 tvg-id="ZerounoTVNews.it",Zerouno TV News (720p)
https://5db313b643fd8.streamlock.net/ZerounoTVEventi/ZerounoTVEventi/playlist.m3u8 https://5db313b643fd8.streamlock.net/ZerounoTVEventi/ZerounoTVEventi/playlist.m3u8
#EXTINF:-1 tvg-id="Boing.it",Boing (720p) #EXTINF:-1 tvg-id="Telenova.it",Telenova (720p)
https://liveturner.akamaized.net/75a4d1a90e744fa5b9901a1853d2c47f/eu-central-1/6284318116001/playlist.m3u8 https://64b16f23efbee.streamlock.net/telenova/telenova/playlist.m3u8
#EXTINF:-1 tvg-id="Rai2HD.it" http-referrer="https://babaktv.com/",Rai 2 HD #EXTINF:-1 tvg-id="TeleQuattro.it",Tele Quattro (720p)
#EXTVLCOPT:http-referrer=https://babaktv.com/ https://59d7d6f47d7fc.streamlock.net/telequattro/telequattro/playlist.m3u8
https://m3u.iranvids.com/rai02/output.m3u8 #EXTINF:-1 tvg-id="7RadioVisione.it",7 RadioVisione (720p)
https://stream10.xdevel.com/video1s976543-1932/stream/playlist.m3u8
#EXTINF:-1 tvg-id="RTV38.it",RTV38 (576p)
https://streamcdne1-845d8509d2cb4f249dd0b2ae5755b6c2.msvdn.net/rtv38/rtv38_live_main/mainabr/rtv38_live_main/main_576/chunks_dvr.m3u8

View file

@ -32,10 +32,6 @@ https://cdn.skygo.mn/live/disk1/NHK_World_Premium/HLSv3-FTA/NHK_World_Premium.m3
https://master.nhkworld.jp/nhkworld-tv/playlist/live.m3u8 https://master.nhkworld.jp/nhkworld-tv/playlist/live.m3u8
#EXTINF:-1 tvg-id="JOAXDTV.jp",Nippon TV (540p) [Not 24/7] #EXTINF:-1 tvg-id="JOAXDTV.jp",Nippon TV (540p) [Not 24/7]
https://ntv4.mov3.co/hls/ntv.m3u8 https://ntv4.mov3.co/hls/ntv.m3u8
#EXTINF:-1 tvg-id="NTVNEWS24.jp",NTV News24 (480p)
https://n24-cdn-live.ntv.co.jp/ch01/index.m3u8
#EXTINF:-1 tvg-id="NTVNEWS24.jp",NTV News24 (480p)
https://n24-cdn-live.ntv.co.jp/ch02/index.m3u8
#EXTINF:-1 tvg-id="QVC.jp",QVC Japan (720p) #EXTINF:-1 tvg-id="QVC.jp",QVC Japan (720p)
https://cdn-live1.qvc.jp/iPhone/1501/1501.m3u8 https://cdn-live1.qvc.jp/iPhone/1501/1501.m3u8
#EXTINF:-1 tvg-id="ShopChannel.jp",Shop Channel (1080p) [Not 24/7] #EXTINF:-1 tvg-id="ShopChannel.jp",Shop Channel (1080p) [Not 24/7]

View file

@ -17,8 +17,6 @@ http://cdns.jp-primehome.com:8000/zhongying/live/playlist.m3u8?cid=bs04&isp=4
http://cdns.jp-primehome.com:8000/zhongying/live/playlist.m3u8?cid=bs05&isp=4 http://cdns.jp-primehome.com:8000/zhongying/live/playlist.m3u8?cid=bs05&isp=4
#EXTINF:-1 tvg-id="ChannelGinga.jp",Channel Ginga (1080p) #EXTINF:-1 tvg-id="ChannelGinga.jp",Channel Ginga (1080p)
http://cdns.jp-primehome.com:8000/zhongying/live/playlist.m3u8?cid=cs29&isp=4 http://cdns.jp-primehome.com:8000/zhongying/live/playlist.m3u8?cid=cs29&isp=4
#EXTINF:-1 tvg-id="CNNj.jp",CNNj (544p)
http://cdns.jp-primehome.com:8000/zhongying/live/playlist.m3u8?cid=cs16&isp=4
#EXTINF:-1 tvg-id="DisneyChannel.jp",Disney Channel Japan (544p) #EXTINF:-1 tvg-id="DisneyChannel.jp",Disney Channel Japan (544p)
http://cdns.jp-primehome.com:8000/zhongying/live/playlist.m3u8?cid=bs24&isp=4 http://cdns.jp-primehome.com:8000/zhongying/live/playlist.m3u8?cid=bs24&isp=4
#EXTINF:-1 tvg-id="EiseiGekijo.jp",Eisei Gekijo (544p) #EXTINF:-1 tvg-id="EiseiGekijo.jp",Eisei Gekijo (544p)

View file

@ -17,6 +17,8 @@ https://streaming.freshnewsasia.com/live/ngrp:myStream_all/playlist.m3u8
http://clive.malisresidences.com:1935/hm_hdtv/_definst_/smil:HMHDTV.smil/playlist.m3u8 http://clive.malisresidences.com:1935/hm_hdtv/_definst_/smil:HMHDTV.smil/playlist.m3u8
#EXTINF:-1 tvg-id="iTVHD.kh",iTV HD #EXTINF:-1 tvg-id="iTVHD.kh",iTV HD
http://43.252.18.195:5080/live/streams/itv.khmeretv.m3u8 http://43.252.18.195:5080/live/streams/itv.khmeretv.m3u8
#EXTINF:-1 tvg-id="KomsanTV.kh",Komsan TV [Not 24/7]
http://tv.cootel.com.kh:8077/streams/d/Komsan/playlist.m3u8
#EXTINF:-1 tvg-id="MSJTV.kh" http-referrer="https://www.iptvservice.site/",MSJ TV (1080p) #EXTINF:-1 tvg-id="MSJTV.kh" http-referrer="https://www.iptvservice.site/",MSJ TV (1080p)
#EXTVLCOPT:http-referrer=https://www.iptvservice.site/ #EXTVLCOPT:http-referrer=https://www.iptvservice.site/
https://live-ali7.tv360.metfone.com.kh/live/myStream/playlist.m3u8 https://live-ali7.tv360.metfone.com.kh/live/myStream/playlist.m3u8
@ -38,10 +40,14 @@ https://fmseatv.netlinkbroadcaster.com/hls/test.m3u8
https://live-evg13.tv360.metfone.com.kh/live/towntv.m3u8 https://live-evg13.tv360.metfone.com.kh/live/towntv.m3u8
#EXTINF:-1 tvg-id="TownTV.kh",Town TV (720p) #EXTINF:-1 tvg-id="TownTV.kh",Town TV (720p)
https://live.kh.malimarcdn.com/live/towntv.stream/playlist.m3u8 https://live.kh.malimarcdn.com/live/towntv.stream/playlist.m3u8
#EXTINF:-1 tvg-id="TV3.kh",TV 3
http://206.189.93.160:1935/live/myStream_720p/playlist.m3u8
#EXTINF:-1 tvg-id="TV3.kh",TV 3 (720p) #EXTINF:-1 tvg-id="TV3.kh",TV 3 (720p)
https://edge6a.v2h-cdn.com/tv3cam/tv3cam.stream/playlist.m3u8 https://edge6a.v2h-cdn.com/tv3cam/tv3cam.stream/playlist.m3u8
#EXTINF:-1 tvg-id="TV5Cambodia.kh",TV5 Cambodia #EXTINF:-1 tvg-id="TV5Cambodia.kh",TV5 Cambodia
http://live.happywatch99.com/livehd14/77bbe9df6a93cf229cd40f1400af00fa.sdp/playlist.m3u8 http://live.happywatch99.com/livehd14/77bbe9df6a93cf229cd40f1400af00fa.sdp/playlist.m3u8
#EXTINF:-1 tvg-id="TV5Cambodia.kh",TV5 Cambodia (1080p)
https://es1-p1-netcdn.metfone.com.kh/netcdn-live-36/36/output/playlist.m3u8
#EXTINF:-1 tvg-id="TV5Cambodia.kh",TV5 Cambodia (720p) #EXTINF:-1 tvg-id="TV5Cambodia.kh",TV5 Cambodia (720p)
https://live-evg3.tv360.metfone.com.kh/live/tv5.m3u8 https://live-evg3.tv360.metfone.com.kh/live/tv5.m3u8
#EXTINF:-1 tvg-id="TVK.kh",TVK (720p) #EXTINF:-1 tvg-id="TVK.kh",TVK (720p)
@ -50,9 +56,7 @@ https://live.kh.malimarcdn.com/live/tvk.stream/playlist.m3u8
https://live.kh.malimarcdn.com/live/tvk2.stream/playlist.m3u8 https://live.kh.malimarcdn.com/live/tvk2.stream/playlist.m3u8
#EXTINF:-1 tvg-id="WikiTV.kh",WIKI TV (720p) #EXTINF:-1 tvg-id="WikiTV.kh",WIKI TV (720p)
https://stream.wikitv.asia/live/ngrp:myStream_all/playlist.m3u8 https://stream.wikitv.asia/live/ngrp:myStream_all/playlist.m3u8
#EXTINF:-1 tvg-id="TV5Cambodia.kh",TV5 Cambodia (1080p) #EXTINF:-1 tvg-id="MyTV.kh",My TV
https://es1-p1-netcdn.metfone.com.kh/netcdn-live-36/36/output/playlist.m3u8 http://43.252.18.195:5080/live/streams/mytv.m3u8
#EXTINF:-1 tvg-id="KomsanTV.kh",Komsan TV [Not 24/7] #EXTINF:-1 tvg-id="CTN.kh",CTN (480p)
http://tv.cootel.com.kh:8077/streams/d/Komsan/playlist.m3u8 http://43.252.18.195:5080/live/streams/ctntv.m3u8
#EXTINF:-1 tvg-id="TV3.kh",TV 3
http://206.189.93.160:1935/live/myStream_720p/playlist.m3u8

View file

@ -35,6 +35,8 @@ https://btn.nowcdn.co.kr/btn/btnlive2m/playlist.m3u8
https://du35ivadp6cxj.cloudfront.net/out/v1/81781d23cbbf490990b2aa9181d4ce19/CGNWebLiveKR.m3u8 https://du35ivadp6cxj.cloudfront.net/out/v1/81781d23cbbf490990b2aa9181d4ce19/CGNWebLiveKR.m3u8
#EXTINF:-1 tvg-id="ChannelA.kr",Channel A [Geo-blocked] #EXTINF:-1 tvg-id="ChannelA.kr",Channel A [Geo-blocked]
http://channelalive.ktcdn.co.kr/chalivepc/_definst_/atv2/playlist.m3u8 http://channelalive.ktcdn.co.kr/chalivepc/_definst_/atv2/playlist.m3u8
#EXTINF:-1 tvg-id="ChannelA.kr",Channel A (360p)
http://www.hwado.net/webtv/catv/52_440DDPPJ.php
#EXTINF:-1 tvg-id="CJOnStyle.kr",CJ OnStyle (540p) #EXTINF:-1 tvg-id="CJOnStyle.kr",CJ OnStyle (540p)
https://live-ch1.cjonstyle.net/cjmalllive/stream2/playlist.m3u8 https://live-ch1.cjonstyle.net/cjmalllive/stream2/playlist.m3u8
#EXTINF:-1 tvg-id="CJOnStylePlus.kr",CJ OnStyle Plus (540p) #EXTINF:-1 tvg-id="CJOnStylePlus.kr",CJ OnStyle Plus (540p)
@ -86,8 +88,6 @@ https://live.jobplustv.or.kr/live/wowtvlive1.sdp/playlist.m3u8
#EXTINF:-1 tvg-id="KBS1TV.kr",KBS 1TV [Not 24/7] #EXTINF:-1 tvg-id="KBS1TV.kr",KBS 1TV [Not 24/7]
http://mytv.dothome.co.kr/ch/public/1.php http://mytv.dothome.co.kr/ch/public/1.php
#EXTINF:-1 tvg-id="KBS1TV.kr",KBS 1 UHD (720p) #EXTINF:-1 tvg-id="KBS1TV.kr",KBS 1 UHD (720p)
http://202.60.106.14:8080/200/playlist.m3u8
#EXTINF:-1 tvg-id="KBS1TV.kr",KBS 1 UHD (720p)
http://202.60.106.14:21585/200/playlist.m3u8 http://202.60.106.14:21585/200/playlist.m3u8
#EXTINF:-1 tvg-id="KBS2TV.kr",KBS 2TV [Not 24/7] #EXTINF:-1 tvg-id="KBS2TV.kr",KBS 2TV [Not 24/7]
http://mytv.dothome.co.kr/ch/public/3.php http://mytv.dothome.co.kr/ch/public/3.php
@ -105,8 +105,6 @@ http://kbs-dokdo.gscdn.com/dokdo_300/dokdo_300.stream/playlist.m3u8
http://mytv.dothome.co.kr/ch/catv/4.php http://mytv.dothome.co.kr/ch/catv/4.php
#EXTINF:-1 tvg-id="KBSWorld.kr",KBS World #EXTINF:-1 tvg-id="KBSWorld.kr",KBS World
http://mytv.dothome.co.kr/ch/catv/7.php http://mytv.dothome.co.kr/ch/catv/7.php
#EXTINF:-1 tvg-id="KBSWorld.kr",KBS World (Vietnamese Subtitles) (720p)
https://livecdn.fptplay.net/sdb/kbs_hls.smil/playlist.m3u8
#EXTINF:-1 tvg-id="KCTV.kr",KCTV 광주 CH05 (720p) [Not 24/7] #EXTINF:-1 tvg-id="KCTV.kr",KCTV 광주 CH05 (720p) [Not 24/7]
http://119.77.96.184:1935/chn05/chn05/playlist.m3u8 http://119.77.96.184:1935/chn05/chn05/playlist.m3u8
#EXTINF:-1 tvg-id="KTV.kr",Korea TV (1080p) #EXTINF:-1 tvg-id="KTV.kr",Korea TV (1080p)
@ -147,6 +145,8 @@ https://5ee9633b25727.streamlock.net/jmbc_tv/_definst_/jmbc_tv.stream/playlist.m
http://vod.mpmbc.co.kr:1935/live/encoder-tv/playlist.m3u8 http://vod.mpmbc.co.kr:1935/live/encoder-tv/playlist.m3u8
#EXTINF:-1 tvg-id="MBCNet.kr",MBC Net (480p) [Geo-blocked] #EXTINF:-1 tvg-id="MBCNet.kr",MBC Net (480p) [Geo-blocked]
http://mytv.dothome.co.kr/ch/catv/28.php http://mytv.dothome.co.kr/ch/catv/28.php
#EXTINF:-1 tvg-id="MBCTV.kr",MBC TV (720p)
http://www.hwado.net/webtv/catv/503_CFEA7803.php
#EXTINF:-1 tvg-id="HLATDTV.kr",MBC Yeosu (여수 MBC) (1080p) [Not 24/7] #EXTINF:-1 tvg-id="HLATDTV.kr",MBC Yeosu (여수 MBC) (1080p) [Not 24/7]
https://5c3639aa99149.streamlock.net/live_TV/tv/playlist.m3u8 https://5c3639aa99149.streamlock.net/live_TV/tv/playlist.m3u8
#EXTINF:-1 tvg-id="MTN.kr",MTN (720p) #EXTINF:-1 tvg-id="MTN.kr",MTN (720p)
@ -173,6 +173,8 @@ https://live.knou.ac.kr/knou1/live1/playlist.m3u8
https://rtv-stream2.a04f922e9e85c8d25ebfeae3dfd22a67.com/rtv/rtv.m3u8 https://rtv-stream2.a04f922e9e85c8d25ebfeae3dfd22a67.com/rtv/rtv.m3u8
#EXTINF:-1 tvg-id="RUTCTV.kr",RUTC TV (720p) #EXTINF:-1 tvg-id="RUTCTV.kr",RUTC TV (720p)
http://d26sxnc75smwvh.cloudfront.net/livehttporigin/rutclive_720p2.stream/playlist.m3u8 http://d26sxnc75smwvh.cloudfront.net/livehttporigin/rutclive_720p2.stream/playlist.m3u8
#EXTINF:-1 tvg-id="SBS.kr",SBS (480p)
http://www.hwado.net/webtv/catv/502_76142D8F.php
#EXTINF:-1 tvg-id="HLDRDTV.kr",SBS CJB (540p) [Not 24/7] #EXTINF:-1 tvg-id="HLDRDTV.kr",SBS CJB (540p) [Not 24/7]
http://1.222.207.80:1935/live/cjbtv/playlist.m3u8 http://1.222.207.80:1935/live/cjbtv/playlist.m3u8
#EXTINF:-1 tvg-id="HLCGDTV.kr",SBS G1 (360p) [Not 24/7] #EXTINF:-1 tvg-id="HLCGDTV.kr",SBS G1 (360p) [Not 24/7]
@ -221,9 +223,3 @@ http://157.245.196.186/live/livestream.m3u8
http://202.60.106.14:8080/214/playlist.m3u8 http://202.60.106.14:8080/214/playlist.m3u8
#EXTINF:-1 tvg-id="YTN.kr",YTN (720p) #EXTINF:-1 tvg-id="YTN.kr",YTN (720p)
http://202.60.106.14:21585/214/playlist.m3u8 http://202.60.106.14:21585/214/playlist.m3u8
#EXTINF:-1 tvg-id="SBS.kr",SBS (480p)
http://www.hwado.net/webtv/catv/502_76142D8F.php
#EXTINF:-1 tvg-id="ChannelA.kr",Channel A (360p)
http://www.hwado.net/webtv/catv/52_440DDPPJ.php
#EXTINF:-1 tvg-id="MBCTV.kr",MBC TV (720p)
http://www.hwado.net/webtv/catv/503_CFEA7803.php

View file

@ -31,8 +31,6 @@ https://stream.kaztrk.kz/regional/kokshetautv/index.m3u8
http://212.42.111.152:8080/hls/manas.m3u8 http://212.42.111.152:8080/hls/manas.m3u8
#EXTINF:-1 tvg-id="Mangystay.kz",Mańǵystaý (540p) [Not 24/7] #EXTINF:-1 tvg-id="Mangystay.kz",Mańǵystaý (540p) [Not 24/7]
https://stream.kaztrk.kz/regional/mangystautv/index.m3u8 https://stream.kaztrk.kz/regional/mangystautv/index.m3u8
#EXTINF:-1 tvg-id="MuzzOne.kz",MuzzOne (1080p)
https://muzzone-stream.daitsuna.net/muzzondvr/muzzone/playlist_dvr.m3u8
#EXTINF:-1 tvg-id="Ontustik.kz",Ontústik (360p) #EXTINF:-1 tvg-id="Ontustik.kz",Ontústik (360p)
https://stream.kaztrk.kz/regional/shymkenttv/index.m3u8 https://stream.kaztrk.kz/regional/shymkenttv/index.m3u8
#EXTINF:-1 tvg-id="Qazaqstan.kz",Qazaqstan TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="Qazaqstan.kz",Qazaqstan TV (720p) [Not 24/7]
@ -63,3 +61,5 @@ https://tvcdn01.oktv.kz/tv/mtrk/playlist.m3u8
http://serv25.vintera.tv:8081/novoetv/nov_tv/playlist.m3u8 http://serv25.vintera.tv:8081/novoetv/nov_tv/playlist.m3u8
#EXTINF:-1 tvg-id="ChannelOneEurasia.kz",Первый канал Евразия (720p) #EXTINF:-1 tvg-id="ChannelOneEurasia.kz",Первый канал Евразия (720p)
https://1tvkz-stream.daitsuna.net/1tvkz/1tvkz/playlist.m3u8 https://1tvkz-stream.daitsuna.net/1tvkz/1tvkz/playlist.m3u8
#EXTINF:-1 tvg-id="MuzzOne.kz",MuzzOne (1080p)
https://streams.qazcdn.net/muzzone/muzzone/playlist_dvr.m3u8

View file

@ -3,8 +3,6 @@
https://tv.hiruhost.com:1936/8012/8012/playlist.m3u8 https://tv.hiruhost.com:1936/8012/8012/playlist.m3u8
#EXTINF:-1 tvg-id="ImaiTV.lk",Imai TV (720p) #EXTINF:-1 tvg-id="ImaiTV.lk",Imai TV (720p)
https://rpn3.bozztv.com/ssh101/ssh101/imaitv/playlist.m3u8 https://rpn3.bozztv.com/ssh101/ssh101/imaitv/playlist.m3u8
#EXTINF:-1 tvg-id="ITN.lk",ITN (720p) [Not 24/7]
https://j78dp2pnlq5r-hls-live.comcities.net/ITNDigital/cf467ddf13ba30dd3c71435cafa6fd6e.sdp/playlist_dvr.m3u8
#EXTINF:-1 tvg-id="MonaraTV.lk",Monara TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="MonaraTV.lk",Monara TV (720p) [Not 24/7]
https://jk3lz8xklw79-hls-live.5centscdn.com/lpl/d0dbe915091d400bd8ee7f27f0791303.sdp/playlist.m3u8 https://jk3lz8xklw79-hls-live.5centscdn.com/lpl/d0dbe915091d400bd8ee7f27f0791303.sdp/playlist.m3u8
#EXTINF:-1 tvg-id="Rupavahini.lk",Rupavahini (480p) #EXTINF:-1 tvg-id="Rupavahini.lk",Rupavahini (480p)
@ -19,3 +17,7 @@ https://jk3lz8xklw79-hls-live.5centscdn.com/live/6226f7cbe59e99a90b5cef6f94f966f
https://j78dp2pnlq5r-hls-live.comcities.net/ITNDigital/20a317b0496a4930b375290505e5d628.sdp/playlist_dvr.m3u8 https://j78dp2pnlq5r-hls-live.comcities.net/ITNDigital/20a317b0496a4930b375290505e5d628.sdp/playlist_dvr.m3u8
#EXTINF:-1 tvg-id="VerbumTV.lk",Verbum TV (414p) [Not 24/7] #EXTINF:-1 tvg-id="VerbumTV.lk",Verbum TV (414p) [Not 24/7]
https://verbumtv.livebox.co.in/verbumtvhls/live.m3u8 https://verbumtv.livebox.co.in/verbumtvhls/live.m3u8
#EXTINF:-1 tvg-id="VasanthamTV.lk",Vasantham TV (720p)
https://222103-hls.akamaized.net/668828a00bf80aa436254876/live_2cdb4ef03c1311efadcf7986aa245789/rewind-3600.m3u8
#EXTINF:-1 tvg-id="ITN.lk",ITN (1080p)
https://222103-hls.akamaized.net/668828a00bf80aa436254876/live_aabd3d003af211efadcf7986aa245789/rewind-3600.m3u8

View file

@ -3,36 +3,26 @@
#EXTVLCOPT:http-referrer=https://2m.ma #EXTVLCOPT:http-referrer=https://2m.ma
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0 #EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0
https://cdn-globecast.akamaized.net/live/eds/2m_monde/hls_video_ts_tuhawxpiemz257adfc/2m_monde.m3u8 https://cdn-globecast.akamaized.net/live/eds/2m_monde/hls_video_ts_tuhawxpiemz257adfc/2m_monde.m3u8
#EXTINF:-1 tvg-id="2MNational.ma",2M National (1080p)
http://154.197.91.168:7001/play/a0fn/index.m3u8
#EXTINF:-1 tvg-id="AlAoulaInter.ma",Al Aoula International (1080p)
http://154.197.91.168:7001/play/a0f5/index.m3u8
#EXTINF:-1 tvg-id="AlAoulaInter.ma",Al Aoula International (480p) #EXTINF:-1 tvg-id="AlAoulaInter.ma",Al Aoula International (480p)
https://cdn.live.easybroadcast.io/abr_corp/73_aloula_w1dqfwm/playlist_dvr.m3u8 https://cdn.live.easybroadcast.io/abr_corp/73_aloula_w1dqfwm/playlist_dvr.m3u8
#EXTINF:-1 tvg-id="AlAoula.ma",Al Aoula Laâyoune (1080p) #EXTINF:-1 tvg-id="LaayouneTV.ma",Al Aoula Laâyoune (480p)
http://154.197.91.168:7001/play/a0f6/index.m3u8
#EXTINF:-1 tvg-id="AlAoula.ma",Al Aoula Laâyoune (480p)
https://cdn.live.easybroadcast.io/abr_corp/73_laayoune_pgagr52/playlist_dvr.m3u8 https://cdn.live.easybroadcast.io/abr_corp/73_laayoune_pgagr52/playlist_dvr.m3u8
#EXTINF:-1 tvg-id="AlMaghribia.ma",Al Maghribia (1080p)
http://154.197.91.168:7001/play/a0f9/index.m3u8
#EXTINF:-1 tvg-id="AlMaghribia.ma",Al Maghribia (480p) #EXTINF:-1 tvg-id="AlMaghribia.ma",Al Maghribia (480p)
https://cdn.live.easybroadcast.io/abr_corp/73_almaghribia_83tz85q/playlist_dvr.m3u8 https://cdn.live.easybroadcast.io/abr_corp/73_almaghribia_83tz85q/playlist_dvr.m3u8
#EXTINF:-1 tvg-id="",Al Rahman (480p) #EXTINF:-1 tvg-id="",Al Rahman (480p)
http://149.100.11.244:8001/play/a06j/index.m3u8 http://149.100.11.244:8001/play/a06j/index.m3u8
#EXTINF:-1 tvg-id="Arryadia.ma",Arryadia (1080p)
http://154.197.91.168:7001/play/a0f7/index.m3u8
#EXTINF:-1 tvg-id="Arryadia.ma",Arryadia (480p) #EXTINF:-1 tvg-id="Arryadia.ma",Arryadia (480p)
https://cdn.live.easybroadcast.io/abr_corp/73_arryadia_k2tgcj0/playlist_dvr.m3u8 https://cdn.live.easybroadcast.io/abr_corp/73_arryadia_k2tgcj0/playlist_dvr.m3u8
#EXTINF:-1 tvg-id="Arryadia.ma",Arryadia (1080p)
http://154.197.91.168:7001/play/a0fa/index.m3u8
#EXTINF:-1 tvg-id="Assadissa.ma",Assadissa (480p) #EXTINF:-1 tvg-id="Assadissa.ma",Assadissa (480p)
https://cdn.live.easybroadcast.io/abr_corp/73_assadissa_7b7u5n1/playlist_dvr.m3u8 https://cdn.live.easybroadcast.io/abr_corp/73_assadissa_7b7u5n1/playlist_dvr.m3u8
#EXTINF:-1 tvg-id="Athaqafia.ma",Athaqafia (1080p)
http://154.197.91.168:7001/play/a0f8/index.m3u8
#EXTINF:-1 tvg-id="Athaqafia.ma",Athaqafia (480p) #EXTINF:-1 tvg-id="Athaqafia.ma",Athaqafia (480p)
https://cdn.live.easybroadcast.io/abr_corp/73_arrabia_hthcj4p/playlist_dvr.m3u8 https://cdn.live.easybroadcast.io/abr_corp/73_arrabia_hthcj4p/playlist_dvr.m3u8
#EXTINF:-1 tvg-id="ChadaTV.ma",Chada TV (720p) #EXTINF:-1 tvg-id="ChadaTV.ma",Chada TV (720p)
https://chadatv.vedge.infomaniak.com/livecast/chadatv/playlist.m3u8 https://chadatv.vedge.infomaniak.com/livecast/chadatv/playlist.m3u8
#EXTINF:-1 tvg-id="ChadaTV.ma",Chada TV (720p)
https://edge19.vedge.infomaniak.com/livecast/ik:chadatv/playlist.m3u8
#EXTINF:-1 tvg-id="M24TV.ma",M24 TV (1080p)
https://67aac8c668349.streamlock.net/live/ngrp:Live2.stream_all/playlist.m3u8
#EXTINF:-1 tvg-id="Medi1TVAfrique.ma",Medi 1 TV Afrique (1080p) [Not 24/7] #EXTINF:-1 tvg-id="Medi1TVAfrique.ma",Medi 1 TV Afrique (1080p) [Not 24/7]
https://streaming1.medi1tv.com/live/smil:medi1fr.smil/playlist.m3u8 https://streaming1.medi1tv.com/live/smil:medi1fr.smil/playlist.m3u8
#EXTINF:-1 tvg-id="Medi1TVAfrique.ma",Medi 1 TV Afrique (1080p) [Not 24/7] #EXTINF:-1 tvg-id="Medi1TVAfrique.ma",Medi 1 TV Afrique (1080p) [Not 24/7]
@ -45,7 +35,9 @@ https://streaming2.medi1tv.com/live/smil:medi1ar.smil/playlist.m3u8
https://streaming1.medi1tv.com/live/smil:medi1tv.smil/playlist.m3u8 https://streaming1.medi1tv.com/live/smil:medi1tv.smil/playlist.m3u8
#EXTINF:-1 tvg-id="Medi1TVMaghreb.ma",Medi 1 TV Maghreb (1080p) [Not 24/7] #EXTINF:-1 tvg-id="Medi1TVMaghreb.ma",Medi 1 TV Maghreb (1080p) [Not 24/7]
https://streaming2.medi1tv.com/live/smil:medi1tv.smil/playlist.m3u8 https://streaming2.medi1tv.com/live/smil:medi1tv.smil/playlist.m3u8
#EXTINF:-1 tvg-id="TamazightTV.ma",Tamazight (1080p)
http://154.197.91.168:7001/play/a0fb/index.m3u8
#EXTINF:-1 tvg-id="TamazightTV.ma",Tamazight (480p) #EXTINF:-1 tvg-id="TamazightTV.ma",Tamazight (480p)
https://cdn.live.easybroadcast.io/abr_corp/73_tamazight_tccybxt/playlist_dvr.m3u8 https://cdn.live.easybroadcast.io/abr_corp/73_tamazight_tccybxt/playlist_dvr.m3u8
#EXTINF:-1 tvg-id="2MMonde.ma",2M Monde (720p)
https://d3g87jnubafe6a.cloudfront.net/out/v1/1fa0fb3c8dec402994a6f7a7f6492b82/index.m3u8
#EXTINF:-1 tvg-id="TeleMaroc.ma",Tele Maroc (720p)
https://raw.githubusercontent.com/ipstreet312/freeiptv/master/ressources/kuw/telmar.m3u8

View file

@ -1,7 +1,7 @@
#EXTM3U #EXTM3U
#EXTINF:-1 tvg-id="MonacoInfo.mc",Monaco Info (720p) [Not 24/7]
https://webtvmonacoinfo.mc/live/prod_720/index.m3u8
#EXTINF:-1 tvg-id="SuperyachtTV.mc",Superyacht TV (1080p) #EXTINF:-1 tvg-id="SuperyachtTV.mc",Superyacht TV (1080p)
https://sy.wns.live/hls/stream.m3u8 https://sy.wns.live/hls/stream.m3u8
#EXTINF:-1 tvg-id="TVMonaco.mc",TV Monaco (1080p) #EXTINF:-1 tvg-id="TVMonaco.mc",TV Monaco (1080p)
https://production-fast-mcrtv.content.okast.tv/channels/2116dc08-1959-465d-857f-3619daefb66b/b702b2b9-aebd-436c-be69-2118f56f3d86/2024/media.m3u8 https://production-fast-mcrtv.content.okast.tv/channels/2116dc08-1959-465d-857f-3619daefb66b/b702b2b9-aebd-436c-be69-2118f56f3d86/2024/media.m3u8
#EXTINF:-1 tvg-id="MonacoInfo.mc",Monaco Info (1080p)
https://webtv.monacoinfo.com/live/prod/index.m3u8

View file

@ -3,29 +3,61 @@
http://hls.protv.md/acasatv/acasatv.m3u8 http://hls.protv.md/acasatv/acasatv.m3u8
#EXTINF:-1 tvg-id="BaltiTV.md",Bălţi TV (1080p) [Geo-blocked] #EXTINF:-1 tvg-id="BaltiTV.md",Bălţi TV (1080p) [Geo-blocked]
http://77.89.199.174:8000/play/1024/index.m3u8 http://77.89.199.174:8000/play/1024/index.m3u8
#EXTINF:-1 tvg-id="BusuiocTV.md",Busuioc TV (1080p)
http://62.233.57.226:8001/play/a005
#EXTINF:-1 tvg-id="BusuiocTV.md",Busuioc TV (540p) [Not 24/7] #EXTINF:-1 tvg-id="BusuiocTV.md",Busuioc TV (540p) [Not 24/7]
https://busuioctv.iforward.eu/hls/busuioc.m3u8 https://busuioctv.iforward.eu/hls/busuioc.m3u8
#EXTINF:-1 tvg-id="Cinema1.md",Cinema 1 (1080p)
http://62.233.57.226:8001/play/a00l00
#EXTINF:-1 tvg-id="DrochiaTV.md",Drochia TV (1080p) [Not 24/7] #EXTINF:-1 tvg-id="DrochiaTV.md",Drochia TV (1080p) [Not 24/7]
https://hls.drochia.tv/tv/web.m3u8 https://hls.drochia.tv/tv/web.m3u8
#EXTINF:-1 tvg-id="DuniaSinema.my",Dunia Sinema (1080p) #EXTINF:-1 tvg-id="DuniaSinema.my",Dunia Sinema (1080p)
https://unifi-live05.secureswiftcontent.com/UnifiHD/live27-1080FHD.m3u8 https://unifi-live05.secureswiftcontent.com/UnifiHD/live27-1080FHD.m3u8
#EXTINF:-1 tvg-id="ExclusivTV.md",Exclusiv TV (1080p)
http://62.233.57.226:8001/play/a00f
#EXTINF:-1 tvg-id="GRT.md",GRT (1080p)
http://62.233.57.226:8001/play/a00f00
#EXTINF:-1 tvg-id="JurnalTV.md",Jurnal TV (1080p)
http://62.233.57.226:8001/play/a00i
#EXTINF:-1 tvg-id="Moldova1.md",Moldova 1 (1080p)
https://v0.trm.md/static/streaming-playlists/hls/9b79338b-1870-4cd7-91d4-0f6ce5cac7ca/master.m3u8
#EXTINF:-1 tvg-id="Moldova2.md",Moldova 2 (1080p)
https://v0.trm.md/static/streaming-playlists/hls/d5fafab0-9c37-4746-9e7a-b2d6c0427015/master.m3u8
#EXTINF:-1 tvg-id="Moldova2.md",Moldova 2 (1080p)
http://62.233.57.226:8001/play/a00a
#EXTINF:-1 tvg-id="MoldovaTV.md",Moldova TV (576p) [Not 24/7] #EXTINF:-1 tvg-id="MoldovaTV.md",Moldova TV (576p) [Not 24/7]
http://89.38.8.130:39435 http://89.38.8.130:39435
#EXTINF:-1 tvg-id="N4.md",N4 (1080p)
http://62.233.57.226:8001/play/a007
#EXTINF:-1 tvg-id="N4.md",N4 (360p) [Not 24/7] #EXTINF:-1 tvg-id="N4.md",N4 (360p) [Not 24/7]
https://web.sats.gstv.tech/cpl11/da8df281-1165-440a-8c86-959f71b695b6/N4web.m3u8 https://web.sats.gstv.tech/cpl11/da8df281-1165-440a-8c86-959f71b695b6/N4web.m3u8
#EXTINF:-1 tvg-id="NextTV.md",Next TV (1080p)
http://62.233.57.226:8001/play/a00h
#EXTINF:-1 tvg-id="NorocTV.md",Noroc TV (1080p)
http://62.233.57.226:8001/play/a00i00
#EXTINF:-1 tvg-id="NorocTV.md",Noroc TV (576p) [Not 24/7] #EXTINF:-1 tvg-id="NorocTV.md",Noroc TV (576p) [Not 24/7]
https://live.noroc.tv/noroc/noroc.m3u8 https://live.noroc.tv/noroc/noroc.m3u8
#EXTINF:-1 tvg-id="NTSTV.md",NTS TV (1080p)
http://62.233.57.226:8001/play/a00d
#EXTINF:-1 tvg-id="PremieraTV.md",Premiera TV (1080p)
http://62.233.57.226:8001/play/a009
#EXTINF:-1 tvg-id="PrivescEuTV.md",Privesc.Eu TV (2160p) #EXTINF:-1 tvg-id="PrivescEuTV.md",Privesc.Eu TV (2160p)
https://cachestar.privesc.eu/liniar/moldova/playlist.m3u8 https://cachestar.privesc.eu/liniar/moldova/playlist.m3u8
#EXTINF:-1 tvg-id="PROTVChisinau.md",PRO TV Chisinau (1080p)
http://62.233.57.226:8001/play/a00g
#EXTINF:-1 tvg-id="PublikaTV.md",Publika TV (720p) #EXTINF:-1 tvg-id="PublikaTV.md",Publika TV (720p)
https://livebeta.publika.press/LIVE/P/6810.m3u8 https://livebeta.publika.press/LIVE/P/6810.m3u8
#EXTINF:-1 tvg-id="RealitateaTV.md",Rlive TV (406p) #EXTINF:-1 tvg-id="RealitateaTV.md",Rlive TV (406p)
https://realitatealive.md/tv/rlive.m3u8 https://realitatealive.md/tv/rlive.m3u8
#EXTINF:-1 tvg-id="SorTV.md",Sor TV (720p) #EXTINF:-1 tvg-id="SorTV.md",Sor TV (720p)
http://188.237.212.16:8888/live/cameraFeed.m3u8 http://188.237.212.16:8888/live/cameraFeed.m3u8
#EXTINF:-1 tvg-id="StarTV.md",Star TV (1080p)
http://62.233.57.226:8001/play/a008
#EXTINF:-1 tvg-id="TeleM.md",TeleM (576p) #EXTINF:-1 tvg-id="TeleM.md",TeleM (576p)
https://tv.streambox.ro/hls/telem/index.m3u8 https://tv.streambox.ro/hls/telem/index.m3u8
#EXTINF:-1 tvg-id="TezaurTV.md",Tezaur TV (1080p) #EXTINF:-1 tvg-id="TezaurTV.md",Tezaur TV (1080p)
http://62.233.57.226:8001/play/a00j
#EXTINF:-1 tvg-id="TezaurTV.md",Tezaur TV (1080p)
https://tezaurtv.md/wp-content/uploads/live/index.m3u8 https://tezaurtv.md/wp-content/uploads/live/index.m3u8
#EXTINF:-1 tvg-id="TVNord.md",TV-Nord (1080p) #EXTINF:-1 tvg-id="TVNord.md",TV-Nord (1080p)
https://6065d3147e895.streamlock.net:4444/npcl/live/playlist.m3u8 https://6065d3147e895.streamlock.net:4444/npcl/live/playlist.m3u8
@ -33,33 +65,5 @@ https://6065d3147e895.streamlock.net:4444/npcl/live/playlist.m3u8
https://tvr-tvrmoldova.cdn.zitec.com/live/tvrmoldova/main.m3u8 https://tvr-tvrmoldova.cdn.zitec.com/live/tvrmoldova/main.m3u8
#EXTINF:-1 tvg-id="VoceaBasarabieiTV.md",Vocea Basarabiei TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="VoceaBasarabieiTV.md",Vocea Basarabiei TV (720p) [Not 24/7]
https://storage.voceabasarabiei.md/vocea/vocea.m3u8 https://storage.voceabasarabiei.md/vocea/vocea.m3u8
#EXTINF:-1 tvg-id="ExclusivTV.md",Exclusiv TV (1080p)
http://62.233.57.226:8001/play/a00f
#EXTINF:-1 tvg-id="TezaurTV.md",Tezaur TV (1080p)
http://62.233.57.226:8001/play/a00j
#EXTINF:-1 tvg-id="StarTV.md",Star TV (1080p)
http://62.233.57.226:8001/play/a008
#EXTINF:-1 tvg-id="ZonaM.md",Zona M (576p) #EXTINF:-1 tvg-id="ZonaM.md",Zona M (576p)
http://62.233.57.226:8001/play/a00e http://62.233.57.226:8001/play/a00e
#EXTINF:-1 tvg-id="PROTVChisinau.md",PRO TV Chisinau (1080p)
http://62.233.57.226:8001/play/a00g
#EXTINF:-1 tvg-id="PremieraTV.md",Premiera TV (1080p)
http://62.233.57.226:8001/play/a009
#EXTINF:-1 tvg-id="NTSTV.md",NTS TV (1080p)
http://62.233.57.226:8001/play/a00d
#EXTINF:-1 tvg-id="NorocTV.md",Noroc TV (1080p)
http://62.233.57.226:8001/play/a00i00
#EXTINF:-1 tvg-id="NextTV.md",Next TV (1080p)
http://62.233.57.226:8001/play/a00h
#EXTINF:-1 tvg-id="N4.md",N4 (1080p)
http://62.233.57.226:8001/play/a007
#EXTINF:-1 tvg-id="Moldova2.md",Moldova 2 (1080p)
http://62.233.57.226:8001/play/a00a
#EXTINF:-1 tvg-id="JurnalTV.md",Jurnal TV (1080p)
http://62.233.57.226:8001/play/a00i
#EXTINF:-1 tvg-id="GRT.md",GRT (1080p)
http://62.233.57.226:8001/play/a00f00
#EXTINF:-1 tvg-id="Cinema1.md",Cinema 1 (1080p)
http://62.233.57.226:8001/play/a00l00
#EXTINF:-1 tvg-id="BusuiocTV.md",Busuioc TV (1080p)
http://62.233.57.226:8001/play/a005

View file

@ -14,18 +14,20 @@ http://210.210.155.35/dr9445/h/h04/index.m3u8
http://210.210.155.37/uq2663/h/h22/index.m3u8 http://210.210.155.37/uq2663/h/h22/index.m3u8
#EXTINF:-1 tvg-id="MaahTV.my",Maah TV (720p) [Not 24/7] #EXTINF:-1 tvg-id="MaahTV.my",Maah TV (720p) [Not 24/7]
https://hls.maahtv.live/hls/stream.m3u8 https://hls.maahtv.live/hls/stream.m3u8
#EXTINF:-1 tvg-id="Okey.my" http-referrer="https://rtm-player.glueapi.io/",Okey RTM [Geo-blocked] #EXTINF:-1 tvg-id="Okey.my" http-referrer="https://rtm-player.glueapi.io/",Okey [Geo-blocked]
#EXTVLCOPT:http-referrer=https://rtm-player.glueapi.io/ #EXTVLCOPT:http-referrer=https://rtm-player.glueapi.io/
https://d25tgymtnqzu8s.cloudfront.net/smil:okey/playlist.m3u8?id=3 https://d25tgymtnqzu8s.cloudfront.net/smil:okey/playlist.m3u8?id=3
#EXTINF:-1 tvg-id="ParlimenMalaysia.my" http-referrer="https://rtm-player.glueapi.io/",RTM Parlimen (Dewan Negara) [Geo-blocked] #EXTINF:-1 tvg-id="RTMASEAN.my",RTM ASEAN
https://d25tgymtnqzu8s.cloudfront.net/event/smil:event1/chunklist_b2596000_slENG.m3u8
#EXTINF:-1 tvg-id="RTMParlimenDewanNegara.my" http-referrer="https://rtm-player.glueapi.io/",RTM Parlimen (Dewan Negara) [Geo-blocked]
#EXTVLCOPT:http-referrer=https://rtm-player.glueapi.io/ #EXTVLCOPT:http-referrer=https://rtm-player.glueapi.io/
https://d25tgymtnqzu8s.cloudfront.net/smil:negara/playlist.m3u8?id=8 https://d25tgymtnqzu8s.cloudfront.net/smil:negara/playlist.m3u8?id=8
#EXTINF:-1 tvg-id="ParlimenMalaysia.my" http-referrer="https://rtm-player.glueapi.io/",RTM Parlimen (Dewan Rakyat) [Geo-blocked] #EXTINF:-1 tvg-id="RTMParlimenDewanRakyat.my" http-referrer="https://rtm-player.glueapi.io/",RTM Parlimen (Dewan Rakyat) [Geo-blocked]
#EXTVLCOPT:http-referrer=https://rtm-player.glueapi.io/ #EXTVLCOPT:http-referrer=https://rtm-player.glueapi.io/
https://d25tgymtnqzu8s.cloudfront.net/smil:rakyat/playlist.m3u8?id=7 https://d25tgymtnqzu8s.cloudfront.net/smil:rakyat/playlist.m3u8?id=7
#EXTINF:-1 tvg-id="TV1.my",RTM TV 1 [Geo-blocked] #EXTINF:-1 tvg-id="TV1.my",TV1 [Geo-blocked]
https://d25tgymtnqzu8s.cloudfront.net/smil:tv1/manifest.mpd https://d25tgymtnqzu8s.cloudfront.net/smil:tv1/manifest.mpd
#EXTINF:-1 tvg-id="TV2.my",RTM TV 2 [Geo-blocked] #EXTINF:-1 tvg-id="TV2.my",TV2 [Geo-blocked]
https://d25tgymtnqzu8s.cloudfront.net/smil:tv2/manifest.mpd https://d25tgymtnqzu8s.cloudfront.net/smil:tv2/manifest.mpd
#EXTINF:-1 tvg-id="SukanRTM.my",Sukan RTM [Geo-blocked] #EXTINF:-1 tvg-id="SukanRTM.my",Sukan RTM [Geo-blocked]
https://d25tgymtnqzu8s.cloudfront.net/smil:sukan/manifest.mpd https://d25tgymtnqzu8s.cloudfront.net/smil:sukan/manifest.mpd
@ -42,7 +44,9 @@ https://tonton-live-switch-ssar.akamaized.net/stream-tv3/master.m3u8?bpkio_servi
https://d25tgymtnqzu8s.cloudfront.net/smil:tv6/playlist.m3u8?id=6 https://d25tgymtnqzu8s.cloudfront.net/smil:tv6/playlist.m3u8?id=6
#EXTINF:-1 tvg-id="TV9.my",TV9 #EXTINF:-1 tvg-id="TV9.my",TV9
https://tonton-live-switch-ssar.akamaized.net/stream-tv9/master.m3u8?bpkio_serviceid=6c0958d82a830a02ca0936d9cfab8311 https://tonton-live-switch-ssar.akamaized.net/stream-tv9/master.m3u8?bpkio_serviceid=6c0958d82a830a02ca0936d9cfab8311
#EXTINF:-1 tvg-id="8TV.my",8TV
https://tonton-live-switch-ssar.akamaized.net/stream-8tv/master.m3u8?bpkio_serviceid=6c0958d82a830a02ca0936d9cfab8311
#EXTINF:-1 tvg-id="NTV7.my",NTV7
https://tonton-live-switch-ssar.akamaized.net/stream-ntv7/master.m3u8?bpkio_serviceid=6c0958d82a830a02ca0936d9cfab8311
#EXTINF:-1 tvg-id="TVIKIM.my",TVIKIM #EXTINF:-1 tvg-id="TVIKIM.my",TVIKIM
https://edge-sg1.vediostream.com/abr/tvikim/playlist.m3u8 https://edge-sg1.vediostream.com/abr/tvikim/playlist.m3u8
#EXTINF:-1 tvg-id="RTMASEAN.my",RTM ASEAN
https://d25tgymtnqzu8s.cloudfront.net/event/smil:event1/chunklist_b2596000_slENG.m3u8

Some files were not shown because too many files have changed in this diff Show more