mirror of https://github.com/iptv-org/iptv
Merge pull request #24931 from iptv-org/patch-2025.07.1
Patch 2025.07.1
This commit is contained in:
commit
f378863f37
|
@ -60,6 +60,13 @@ body:
|
|||
label: HTTP Referrer
|
||||
placeholder: 'https://example.com/'
|
||||
|
||||
- type: textarea
|
||||
id: directives
|
||||
attributes:
|
||||
label: Directives
|
||||
description: 'List of directives telling players how to play the stream. Supported `#KODIPROP` and `#VLCOPT`.'
|
||||
placeholder: '#KODIPROP:inputstream=inputstream.adaptive'
|
||||
|
||||
- type: textarea
|
||||
id: notes
|
||||
attributes:
|
||||
|
|
|
@ -72,6 +72,13 @@ body:
|
|||
label: HTTP Referrer
|
||||
placeholder: 'https://example.com/'
|
||||
|
||||
- type: textarea
|
||||
id: directives
|
||||
attributes:
|
||||
label: Directives
|
||||
description: 'List of directives telling players how to play the stream. Supported `#KODIPROP` and `#VLCOPT`.'
|
||||
placeholder: '#KODIPROP:inputstream=inputstream.adaptive'
|
||||
|
||||
- type: textarea
|
||||
id: notes
|
||||
attributes:
|
||||
|
|
|
@ -110,6 +110,28 @@ Same thing, but split up into separate files:
|
|||
|
||||
</details>
|
||||
|
||||
### Grouped by sources
|
||||
|
||||
Playlists in which channels are grouped by broadcast source.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
<br>
|
||||
|
||||
To use the playlist, simply replace `<FILENAME>` in the link below with the name of one of the files in the [streams](streams) folder.
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/sources/<FILENAME>.m3u
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Also, any of our internal playlists are available in raw form (without any filtering or sorting) at this link:
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/raw/<FILENAME>.m3u
|
||||
```
|
||||
|
||||
## EPG
|
||||
|
||||
[Electronic Program Guide](https://en.wikipedia.org/wiki/Electronic_program_guide) for most of the channels can be downloaded using utilities published in the [iptv-org/epg](https://github.com/iptv-org/epg) repository.
|
||||
|
|
|
@ -114,13 +114,13 @@ For a stream to be approved, its description must follow this template:
|
|||
STREAM_URL
|
||||
```
|
||||
|
||||
| Attribute | Description | Required | Valid values |
|
||||
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------------- |
|
||||
| `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 | - |
|
||||
| `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` |
|
||||
| `STREAM_URL` | Stream URL. | Required | - |
|
||||
| Attribute | Description | Required | Valid values |
|
||||
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------------- |
|
||||
| `STREAM_ID` | Stream ID consisting of channel ID and feed ID. 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 | - |
|
||||
| `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` |
|
||||
| `STREAM_URL` | Stream URL. | Required | - |
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -136,15 +136,26 @@ Also, if necessary, you can specify custom [HTTP User-Agent](https://developer.m
|
|||
http://example.com/stream.m3u8
|
||||
```
|
||||
|
||||
or via `#EXTVLCOPT` tag:
|
||||
or use player-specific directives:
|
||||
|
||||
_VLC_
|
||||
|
||||
```xml
|
||||
#EXTINF:-1 tvg-id="ExampleTV.us",Example TV
|
||||
#EXTINF:-1 tvg-id="ExampleTV.us@VLC",Example TV
|
||||
#EXTVLCOPT:http-referrer=http://example.com/
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64)
|
||||
http://example.com/stream.m3u8
|
||||
```
|
||||
|
||||
_Kodi_
|
||||
|
||||
```xml
|
||||
#EXTINF:-1 tvg-id="ExampleTV.us@Kodi",Example TV
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.stream_headers=Referer=http://example.com/&User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64)
|
||||
http://example.com/stream.m3u8
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
- `.github/`
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"dependencies": {
|
||||
"@eslint/eslintrc": "^3.3.0",
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@freearhey/core": "^0.8.2",
|
||||
"@freearhey/core": "^0.9.0",
|
||||
"@freearhey/search-js": "^0.1.2",
|
||||
"@inquirer/prompts": "^7.4.1",
|
||||
"@octokit/core": "^6.1.4",
|
||||
|
@ -36,7 +36,7 @@
|
|||
"glob": "^11.0.2",
|
||||
"globals": "^16.0.0",
|
||||
"iptv-checker": "^0.29.1",
|
||||
"iptv-playlist-parser": "^0.13.0",
|
||||
"iptv-playlist-parser": "^0.15.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-expect-message": "^1.1.3",
|
||||
"lodash": "^4.17.21",
|
||||
|
@ -1021,9 +1021,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@freearhey/core": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@freearhey/core/-/core-0.8.2.tgz",
|
||||
"integrity": "sha512-jlb1XUbhUf3lqD3B9Wmx3c8qYG4+s1I0cr2FFQfiMpJh4nMvfUNdJr2OhH31S/dbNP12ycT6RPVoZ2j2G3+mXA==",
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@freearhey/core/-/core-0.9.0.tgz",
|
||||
"integrity": "sha512-D9/3ZNs6iLbEs0dMF6HQZoFoRM+wEYQZeMIQbby49lN6l0M4Q8hTA+wbxIX+Qh4Sj2zIY+0DFJRNLEoRmasVFg==",
|
||||
"dependencies": {
|
||||
"consola": "^3.4.2",
|
||||
"dayjs": "^1.11.13",
|
||||
|
@ -1771,6 +1771,26 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/reporters/node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"deprecated": "Glob versions prior to v9 are no longer supported",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/reporters/node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
|
@ -2725,9 +2745,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
|
@ -3052,9 +3072,9 @@
|
|||
"integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -4053,6 +4073,11 @@
|
|||
"node": ">=14.14"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
|
@ -4200,9 +4225,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
|
@ -4383,6 +4408,21 @@
|
|||
"node": ">=0.8.19"
|
||||
}
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/ip-address": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
|
||||
|
@ -4452,9 +4492,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/iptv-playlist-parser": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/iptv-playlist-parser/-/iptv-playlist-parser-0.13.0.tgz",
|
||||
"integrity": "sha512-As51+8A7AcFzV9Y8mt30TIbRkBn6l0TGuL9lIG2bPcqb+YYRVzfjsqqugz3eWbEmziEKEsLzexnqPSO7ZzQc0A==",
|
||||
"version": "0.15.0",
|
||||
"resolved": "https://registry.npmjs.org/iptv-playlist-parser/-/iptv-playlist-parser-0.15.0.tgz",
|
||||
"integrity": "sha512-9EGiQ5y95UZsV24HBSHuSyOuqzFR4YCAm7X8MqJNHlcm9jP38DHH7inYU0YJuXVq9fAttij3Yh8MJZkV1Bu/SA==",
|
||||
"dependencies": {
|
||||
"is-valid-path": "^0.1.1",
|
||||
"validator": "^13.7.0"
|
||||
|
@ -5632,6 +5672,14 @@
|
|||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/onetime": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||
|
@ -5757,6 +5805,14 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
|
@ -6462,6 +6518,26 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/test-exclude/node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"deprecated": "Glob versions prior to v9 are no longer supported",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/timer-node": {
|
||||
"version": "5.0.9",
|
||||
"resolved": "https://registry.npmjs.org/timer-node/-/timer-node-5.0.9.tgz",
|
||||
|
@ -6776,6 +6852,11 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/write-file-atomic": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
"dependencies": {
|
||||
"@eslint/eslintrc": "^3.3.0",
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@freearhey/core": "^0.8.2",
|
||||
"@freearhey/core": "^0.9.0",
|
||||
"@freearhey/search-js": "^0.1.2",
|
||||
"@inquirer/prompts": "^7.4.1",
|
||||
"@octokit/core": "^6.1.4",
|
||||
|
@ -66,7 +66,7 @@
|
|||
"glob": "^11.0.2",
|
||||
"globals": "^16.0.0",
|
||||
"iptv-checker": "^0.29.1",
|
||||
"iptv-playlist-parser": "^0.13.0",
|
||||
"iptv-playlist-parser": "^0.15.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-expect-message": "^1.1.3",
|
||||
"lodash": "^4.17.21",
|
||||
|
|
|
@ -13,13 +13,15 @@ async function main() {
|
|||
const dataStorage = new Storage(DATA_DIR)
|
||||
const dataLoader = new DataLoader({ storage: dataStorage })
|
||||
const data: DataLoaderData = await dataLoader.load()
|
||||
const { channelsKeyById, feedsGroupedByChannelId }: DataProcessorData = processor.process(data)
|
||||
const { channelsKeyById, feedsGroupedByChannelId, logosGroupedByStreamId }: DataProcessorData =
|
||||
processor.process(data)
|
||||
|
||||
logger.info('loading streams...')
|
||||
const streamsStorage = new Storage(STREAMS_DIR)
|
||||
const parser = new PlaylistParser({
|
||||
storage: streamsStorage,
|
||||
channelsKeyById,
|
||||
logosGroupedByStreamId,
|
||||
feedsGroupedByChannelId
|
||||
})
|
||||
const files = await streamsStorage.list('**/*.m3u')
|
||||
|
|
|
@ -15,6 +15,7 @@ async function main() {
|
|||
loader.download('regions.json'),
|
||||
loader.download('subdivisions.json'),
|
||||
loader.download('feeds.json'),
|
||||
loader.download('logos.json'),
|
||||
loader.download('timezones.json'),
|
||||
loader.download('guides.json'),
|
||||
loader.download('streams.json')
|
||||
|
|
|
@ -49,11 +49,20 @@ export default async function main(filepath: string) {
|
|||
const dataStorage = new Storage(DATA_DIR)
|
||||
const loader = new DataLoader({ storage: dataStorage })
|
||||
const data: DataLoaderData = await loader.load()
|
||||
const { channels, channelsKeyById, feedsGroupedByChannelId }: DataProcessorData =
|
||||
processor.process(data)
|
||||
const {
|
||||
channels,
|
||||
channelsKeyById,
|
||||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId
|
||||
}: DataProcessorData = processor.process(data)
|
||||
|
||||
logger.info('loading streams...')
|
||||
const parser = new PlaylistParser({ storage, feedsGroupedByChannelId, channelsKeyById })
|
||||
const parser = new PlaylistParser({
|
||||
storage,
|
||||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId,
|
||||
channelsKeyById
|
||||
})
|
||||
parsedStreams = await parser.parseFile(filepath)
|
||||
const streamsWithoutId = parsedStreams.filter((stream: Stream) => !stream.id)
|
||||
|
||||
|
|
|
@ -16,14 +16,16 @@ async function main() {
|
|||
const dataStorage = new Storage(DATA_DIR)
|
||||
const loader = new DataLoader({ storage: dataStorage })
|
||||
const data: DataLoaderData = await loader.load()
|
||||
const { channelsKeyById, feedsGroupedByChannelId }: DataProcessorData = processor.process(data)
|
||||
const { channelsKeyById, feedsGroupedByChannelId, logosGroupedByStreamId }: DataProcessorData =
|
||||
processor.process(data)
|
||||
|
||||
logger.info('loading streams...')
|
||||
const streamsStorage = new Storage(STREAMS_DIR)
|
||||
const parser = new PlaylistParser({
|
||||
storage: streamsStorage,
|
||||
channelsKeyById,
|
||||
feedsGroupedByChannelId
|
||||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId
|
||||
})
|
||||
const files = program.args.length ? program.args : await streamsStorage.list('**/*.m3u')
|
||||
let streams = await parser.parse(files)
|
||||
|
|
|
@ -14,7 +14,9 @@ import {
|
|||
CountriesGenerator,
|
||||
LanguagesGenerator,
|
||||
RegionsGenerator,
|
||||
IndexGenerator
|
||||
IndexGenerator,
|
||||
SourcesGenerator,
|
||||
RawGenerator
|
||||
} from '../../generators'
|
||||
|
||||
async function main() {
|
||||
|
@ -28,6 +30,7 @@ async function main() {
|
|||
const data: DataLoaderData = await loader.load()
|
||||
const {
|
||||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId,
|
||||
channelsKeyById,
|
||||
categories,
|
||||
countries,
|
||||
|
@ -39,15 +42,21 @@ async function main() {
|
|||
const parser = new PlaylistParser({
|
||||
storage: streamsStorage,
|
||||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId,
|
||||
channelsKeyById
|
||||
})
|
||||
const files = await streamsStorage.list('**/*.m3u')
|
||||
let streams = await parser.parse(files)
|
||||
const totalStreams = streams.count()
|
||||
logger.info(`found ${totalStreams} streams`)
|
||||
|
||||
logger.info('generating raw/...')
|
||||
await new RawGenerator({ streams, logFile }).generate()
|
||||
|
||||
logger.info('filtering streams...')
|
||||
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(
|
||||
|
@ -79,6 +88,9 @@ async function main() {
|
|||
logFile
|
||||
}).generate()
|
||||
|
||||
logger.info('generating sources/...')
|
||||
await new SourcesGenerator({ streams, logFile }).generate()
|
||||
|
||||
logger.info('generating index.m3u...')
|
||||
await new IndexGenerator({ streams, logFile }).generate()
|
||||
|
||||
|
|
|
@ -61,14 +61,16 @@ async function main() {
|
|||
const dataStorage = new Storage(DATA_DIR)
|
||||
const loader = new DataLoader({ storage: dataStorage })
|
||||
const data: DataLoaderData = await loader.load()
|
||||
const { channelsKeyById, feedsGroupedByChannelId }: DataProcessorData = processor.process(data)
|
||||
const { channelsKeyById, feedsGroupedByChannelId, logosGroupedByStreamId }: DataProcessorData =
|
||||
processor.process(data)
|
||||
|
||||
logger.info('loading streams...')
|
||||
const rootStorage = new Storage(ROOT_DIR)
|
||||
const parser = new PlaylistParser({
|
||||
storage: rootStorage,
|
||||
channelsKeyById,
|
||||
feedsGroupedByChannelId
|
||||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId
|
||||
})
|
||||
const files = program.args.length ? program.args : await rootStorage.list(`${STREAMS_DIR}/*.m3u`)
|
||||
streams = await parser.parse(files)
|
||||
|
|
|
@ -20,13 +20,15 @@ async function main() {
|
|||
const dataStorage = new Storage(DATA_DIR)
|
||||
const dataLoader = new DataLoader({ storage: dataStorage })
|
||||
const data: DataLoaderData = await dataLoader.load()
|
||||
const { channelsKeyById, feedsGroupedByChannelId }: DataProcessorData = processor.process(data)
|
||||
const { channelsKeyById, feedsGroupedByChannelId, logosGroupedByStreamId }: DataProcessorData =
|
||||
processor.process(data)
|
||||
|
||||
logger.info('loading streams...')
|
||||
const streamsStorage = new Storage(STREAMS_DIR)
|
||||
const parser = new PlaylistParser({
|
||||
storage: streamsStorage,
|
||||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId,
|
||||
channelsKeyById
|
||||
})
|
||||
const files = await streamsStorage.list('**/*.m3u')
|
||||
|
@ -168,6 +170,7 @@ async function addStreams({
|
|||
const quality = data.getString('quality') || null
|
||||
const httpUserAgent = data.getString('httpUserAgent') || null
|
||||
const httpReferrer = data.getString('httpReferrer') || null
|
||||
const directives = data.getArray('directives') || []
|
||||
|
||||
const stream = new Stream({
|
||||
channel: channelId,
|
||||
|
@ -176,6 +179,7 @@ async function addStreams({
|
|||
url: streamUrl,
|
||||
user_agent: httpUserAgent,
|
||||
referrer: httpReferrer,
|
||||
directives,
|
||||
quality,
|
||||
label
|
||||
})
|
||||
|
|
|
@ -26,6 +26,7 @@ async function main() {
|
|||
const {
|
||||
channelsKeyById,
|
||||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId,
|
||||
blocklistRecordsGroupedByChannelId
|
||||
}: DataProcessorData = processor.process(data)
|
||||
|
||||
|
@ -34,7 +35,8 @@ async function main() {
|
|||
const parser = new PlaylistParser({
|
||||
storage: rootStorage,
|
||||
channelsKeyById,
|
||||
feedsGroupedByChannelId
|
||||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId
|
||||
})
|
||||
const files = program.args.length ? program.args : await rootStorage.list('streams/**/*.m3u')
|
||||
const streams = await parser.parse(files)
|
||||
|
|
|
@ -21,6 +21,7 @@ async function main() {
|
|||
const {
|
||||
channelsKeyById,
|
||||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId,
|
||||
blocklistRecordsGroupedByChannelId
|
||||
}: DataProcessorData = processor.process(data)
|
||||
|
||||
|
@ -29,7 +30,8 @@ async function main() {
|
|||
const parser = new PlaylistParser({
|
||||
storage: streamsStorage,
|
||||
channelsKeyById,
|
||||
feedsGroupedByChannelId
|
||||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId
|
||||
})
|
||||
const files = await streamsStorage.list('**/*.m3u')
|
||||
const streams = await parser.parse(files)
|
||||
|
@ -151,7 +153,7 @@ async function main() {
|
|||
else if (!feedId && streamsGroupedByChannelId.has(channelId)) result.status = 'fulfilled'
|
||||
else {
|
||||
const channelData = channelsKeyById.get(channelId)
|
||||
if (channelData.length && channelData[0].closed) result.status = 'closed'
|
||||
if (channelData && channelData.isClosed) result.status = 'closed'
|
||||
}
|
||||
|
||||
channelSearchRequestsBuffer.set(streamId, true)
|
||||
|
|
|
@ -47,6 +47,7 @@ export class DataLoader {
|
|||
blocklist,
|
||||
channels,
|
||||
feeds,
|
||||
logos,
|
||||
timezones,
|
||||
guides,
|
||||
streams
|
||||
|
@ -59,6 +60,7 @@ export class DataLoader {
|
|||
this.storage.json('blocklist.json'),
|
||||
this.storage.json('channels.json'),
|
||||
this.storage.json('feeds.json'),
|
||||
this.storage.json('logos.json'),
|
||||
this.storage.json('timezones.json'),
|
||||
this.storage.json('guides.json'),
|
||||
this.storage.json('streams.json')
|
||||
|
@ -73,6 +75,7 @@ export class DataLoader {
|
|||
blocklist,
|
||||
channels,
|
||||
feeds,
|
||||
logos,
|
||||
timezones,
|
||||
guides,
|
||||
streams
|
||||
|
|
|
@ -11,7 +11,8 @@ import {
|
|||
Region,
|
||||
Stream,
|
||||
Guide,
|
||||
Feed
|
||||
Feed,
|
||||
Logo
|
||||
} from '../models'
|
||||
|
||||
export class DataProcessor {
|
||||
|
@ -21,6 +22,9 @@ export class DataProcessor {
|
|||
const categories = new Collection(data.categories).map(data => new Category(data))
|
||||
const categoriesKeyById = categories.keyBy((category: Category) => category.id)
|
||||
|
||||
const languages = new Collection(data.languages).map(data => new Language(data))
|
||||
const languagesKeyByCode = languages.keyBy((language: Language) => language.code)
|
||||
|
||||
const subdivisions = new Collection(data.subdivisions).map(data => new Subdivision(data))
|
||||
const subdivisionsKeyByCode = subdivisions.keyBy((subdivision: Subdivision) => subdivision.code)
|
||||
const subdivisionsGroupedByCountryCode = subdivisions.groupBy(
|
||||
|
@ -30,20 +34,6 @@ export class DataProcessor {
|
|||
let regions = new Collection(data.regions).map(data => new Region(data))
|
||||
const regionsKeyByCode = regions.keyBy((region: Region) => region.code)
|
||||
|
||||
const blocklistRecords = new Collection(data.blocklist).map(data => new BlocklistRecord(data))
|
||||
const blocklistRecordsGroupedByChannelId = blocklistRecords.groupBy(
|
||||
(blocklistRecord: BlocklistRecord) => blocklistRecord.channelId
|
||||
)
|
||||
|
||||
const streams = new Collection(data.streams).map(data => new Stream(data))
|
||||
const streamsGroupedById = streams.groupBy((stream: Stream) => stream.getId())
|
||||
|
||||
const guides = new Collection(data.guides).map(data => new Guide(data))
|
||||
const guidesGroupedByStreamId = guides.groupBy((guide: Guide) => guide.getStreamId())
|
||||
|
||||
const languages = new Collection(data.languages).map(data => new Language(data))
|
||||
const languagesKeyByCode = languages.keyBy((language: Language) => language.code)
|
||||
|
||||
const countries = new Collection(data.countries).map(data =>
|
||||
new Country(data)
|
||||
.withRegions(regions)
|
||||
|
@ -52,13 +42,16 @@ export class DataProcessor {
|
|||
)
|
||||
const countriesKeyByCode = countries.keyBy((country: Country) => country.code)
|
||||
|
||||
regions = regions.map((region: Region) => region.withCountries(countriesKeyByCode))
|
||||
|
||||
const timezones = new Collection(data.timezones).map(data =>
|
||||
new Timezone(data).withCountries(countriesKeyByCode)
|
||||
)
|
||||
const timezonesKeyById = timezones.keyBy((timezone: Timezone) => timezone.id)
|
||||
|
||||
const blocklistRecords = new Collection(data.blocklist).map(data => new BlocklistRecord(data))
|
||||
const blocklistRecordsGroupedByChannelId = blocklistRecords.groupBy(
|
||||
(blocklistRecord: BlocklistRecord) => blocklistRecord.channelId
|
||||
)
|
||||
|
||||
let channels = new Collection(data.channels).map(data =>
|
||||
new Channel(data)
|
||||
.withCategories(categoriesKeyById)
|
||||
|
@ -66,6 +59,7 @@ export class DataProcessor {
|
|||
.withSubdivision(subdivisionsKeyByCode)
|
||||
.withCategories(categoriesKeyById)
|
||||
)
|
||||
|
||||
const channelsKeyById = channels.keyBy((channel: Channel) => channel.id)
|
||||
|
||||
const feeds = new Collection(data.feeds).map(data =>
|
||||
|
@ -78,14 +72,32 @@ export class DataProcessor {
|
|||
.withBroadcastSubdivisions(subdivisionsKeyByCode)
|
||||
)
|
||||
const feedsGroupedByChannelId = feeds.groupBy((feed: Feed) => feed.channelId)
|
||||
const feedsGroupedById = feeds.groupBy((feed: Feed) => feed.id)
|
||||
|
||||
channels = channels.map((channel: Channel) => channel.withFeeds(feedsGroupedByChannelId))
|
||||
let logos = new Collection(data.logos).map(data => new Logo(data).withFeed(feedsGroupedById))
|
||||
const logosGroupedByChannelId = logos.groupBy((logo: Logo) => logo.channelId)
|
||||
const logosGroupedByStreamId = logos.groupBy((logo: Logo) => logo.getStreamId())
|
||||
|
||||
const streams = new Collection(data.streams).map(data =>
|
||||
new Stream(data).withLogos(logosGroupedByStreamId)
|
||||
)
|
||||
const streamsGroupedById = streams.groupBy((stream: Stream) => stream.getId())
|
||||
|
||||
const guides = new Collection(data.guides).map(data => new Guide(data))
|
||||
const guidesGroupedByStreamId = guides.groupBy((guide: Guide) => guide.getStreamId())
|
||||
|
||||
regions = regions.map((region: Region) => region.withCountries(countriesKeyByCode))
|
||||
|
||||
channels = channels.map((channel: Channel) =>
|
||||
channel.withFeeds(feedsGroupedByChannelId).withLogos(logosGroupedByChannelId)
|
||||
)
|
||||
|
||||
return {
|
||||
blocklistRecordsGroupedByChannelId,
|
||||
subdivisionsGroupedByCountryCode,
|
||||
feedsGroupedByChannelId,
|
||||
guidesGroupedByStreamId,
|
||||
logosGroupedByStreamId,
|
||||
subdivisionsKeyByCode,
|
||||
countriesKeyByCode,
|
||||
languagesKeyByCode,
|
||||
|
@ -104,7 +116,8 @@ export class DataProcessor {
|
|||
regions,
|
||||
streams,
|
||||
guides,
|
||||
feeds
|
||||
feeds,
|
||||
logos
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,9 +24,11 @@ export class IssueData {
|
|||
return this._data.get(key) === deleteSymbol ? '' : this._data.get(key)
|
||||
}
|
||||
|
||||
getArray(key: string): string[] {
|
||||
getArray(key: string): string[] | undefined {
|
||||
const deleteSymbol = '~'
|
||||
|
||||
if (this._data.missing(key)) return undefined
|
||||
|
||||
return this._data.get(key) === deleteSymbol ? [] : this._data.get(key).split('\r\n')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ export class IssueLoader {
|
|||
}
|
||||
let issues: object[] = []
|
||||
if (TESTING) {
|
||||
issues = (await import('../../tests/__data__/input/playlist_update/issues.js')).default
|
||||
issues = (await import('../../tests/__data__/input/issues.js')).default
|
||||
} else {
|
||||
issues = await octokit.paginate(octokit.rest.issues.listForRepo, {
|
||||
owner: OWNER,
|
||||
|
|
|
@ -16,7 +16,8 @@ const FIELDS = new Dictionary({
|
|||
'HTTP Referrer': 'httpReferrer',
|
||||
'What happened to the stream?': 'reason',
|
||||
Reason: 'reason',
|
||||
Notes: 'notes'
|
||||
Notes: 'notes',
|
||||
Directives: 'directives'
|
||||
})
|
||||
|
||||
export class IssueParser {
|
||||
|
|
|
@ -5,17 +5,25 @@ import { Stream } from '../models'
|
|||
type PlaylistPareserProps = {
|
||||
storage: Storage
|
||||
feedsGroupedByChannelId: Dictionary
|
||||
logosGroupedByStreamId: Dictionary
|
||||
channelsKeyById: Dictionary
|
||||
}
|
||||
|
||||
export class PlaylistParser {
|
||||
storage: Storage
|
||||
feedsGroupedByChannelId: Dictionary
|
||||
logosGroupedByStreamId: Dictionary
|
||||
channelsKeyById: Dictionary
|
||||
|
||||
constructor({ storage, feedsGroupedByChannelId, channelsKeyById }: PlaylistPareserProps) {
|
||||
constructor({
|
||||
storage,
|
||||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId,
|
||||
channelsKeyById
|
||||
}: PlaylistPareserProps) {
|
||||
this.storage = storage
|
||||
this.feedsGroupedByChannelId = feedsGroupedByChannelId
|
||||
this.logosGroupedByStreamId = logosGroupedByStreamId
|
||||
this.channelsKeyById = channelsKeyById
|
||||
}
|
||||
|
||||
|
@ -41,6 +49,7 @@ export class PlaylistParser {
|
|||
.fromPlaylistItem(data)
|
||||
.withFeed(this.feedsGroupedByChannelId)
|
||||
.withChannel(this.channelsKeyById)
|
||||
.withLogos(this.logosGroupedByStreamId)
|
||||
.setFilepath(filepath)
|
||||
|
||||
return stream
|
||||
|
|
|
@ -17,7 +17,7 @@ export class CategoriesGenerator implements Generator {
|
|||
logFile: File
|
||||
|
||||
constructor({ streams, categories, logFile }: CategoriesGeneratorProps) {
|
||||
this.streams = streams
|
||||
this.streams = streams.clone()
|
||||
this.categories = categories
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
|
@ -30,7 +30,8 @@ export class CategoriesGenerator implements Generator {
|
|||
const categoryStreams = streams
|
||||
.filter((stream: Stream) => stream.hasCategory(category))
|
||||
.map((stream: Stream) => {
|
||||
stream.groupTitle = stream.getCategoryNames().join(';')
|
||||
const groupTitle = stream.getCategoryNames().join(';')
|
||||
if (groupTitle) stream.groupTitle = groupTitle
|
||||
|
||||
return stream
|
||||
})
|
||||
|
|
|
@ -17,7 +17,7 @@ export class CountriesGenerator implements Generator {
|
|||
logFile: File
|
||||
|
||||
constructor({ streams, countries, logFile }: CountriesGeneratorProps) {
|
||||
this.streams = streams
|
||||
this.streams = streams.clone()
|
||||
this.countries = countries
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
export * from './categoriesGenerator'
|
||||
export * from './countriesGenerator'
|
||||
export * from './languagesGenerator'
|
||||
export * from './regionsGenerator'
|
||||
export * from './indexGenerator'
|
||||
export * from './indexNsfwGenerator'
|
||||
export * from './indexCategoryGenerator'
|
||||
export * from './indexCountryGenerator'
|
||||
export * from './indexGenerator'
|
||||
export * from './indexLanguageGenerator'
|
||||
export * from './indexNsfwGenerator'
|
||||
export * from './indexRegionGenerator'
|
||||
export * from './languagesGenerator'
|
||||
export * from './rawGenerator'
|
||||
export * from './regionsGenerator'
|
||||
export * from './sourcesGenerator'
|
||||
|
|
|
@ -15,7 +15,7 @@ export class IndexCategoryGenerator implements Generator {
|
|||
logFile: File
|
||||
|
||||
constructor({ streams, logFile }: IndexCategoryGeneratorProps) {
|
||||
this.streams = streams
|
||||
this.streams = streams.clone()
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ export class IndexCountryGenerator implements Generator {
|
|||
logFile: File
|
||||
|
||||
constructor({ streams, logFile }: IndexCountryGeneratorProps) {
|
||||
this.streams = streams
|
||||
this.streams = streams.clone()
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ export class IndexGenerator implements Generator {
|
|||
logFile: File
|
||||
|
||||
constructor({ streams, logFile }: IndexGeneratorProps) {
|
||||
this.streams = streams
|
||||
this.streams = streams.clone()
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
}
|
||||
|
@ -24,6 +24,12 @@ export class IndexGenerator implements Generator {
|
|||
const sfwStreams = this.streams
|
||||
.orderBy(stream => stream.getTitle())
|
||||
.filter((stream: Stream) => stream.isSFW())
|
||||
.map((stream: Stream) => {
|
||||
const groupTitle = stream.getCategoryNames().join(';')
|
||||
if (groupTitle) stream.groupTitle = groupTitle
|
||||
|
||||
return stream
|
||||
})
|
||||
|
||||
const playlist = new Playlist(sfwStreams, { public: true })
|
||||
const filepath = 'index.m3u'
|
||||
|
|
|
@ -15,7 +15,7 @@ export class IndexLanguageGenerator implements Generator {
|
|||
logFile: File
|
||||
|
||||
constructor({ streams, logFile }: IndexLanguageGeneratorProps) {
|
||||
this.streams = streams
|
||||
this.streams = streams.clone()
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ export class IndexNsfwGenerator implements Generator {
|
|||
logFile: File
|
||||
|
||||
constructor({ streams, logFile }: IndexNsfwGeneratorProps) {
|
||||
this.streams = streams
|
||||
this.streams = streams.clone()
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ export class IndexRegionGenerator implements Generator {
|
|||
logFile: File
|
||||
|
||||
constructor({ streams, regions, logFile }: IndexRegionGeneratorProps) {
|
||||
this.streams = streams
|
||||
this.streams = streams.clone()
|
||||
this.regions = regions
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
|
|
|
@ -12,7 +12,7 @@ export class LanguagesGenerator implements Generator {
|
|||
logFile: File
|
||||
|
||||
constructor({ streams, logFile }: LanguagesGeneratorProps) {
|
||||
this.streams = streams
|
||||
this.streams = streams.clone()
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import { Collection, Storage, File } from '@freearhey/core'
|
||||
import { Stream, Playlist } from '../models'
|
||||
import { PUBLIC_DIR } from '../constants'
|
||||
import { Generator } from './generator'
|
||||
import { EOL } from 'node:os'
|
||||
|
||||
type RawGeneratorProps = {
|
||||
streams: Collection
|
||||
logFile: File
|
||||
}
|
||||
|
||||
export class RawGenerator implements Generator {
|
||||
streams: Collection
|
||||
storage: Storage
|
||||
logFile: File
|
||||
|
||||
constructor({ streams, logFile }: RawGeneratorProps) {
|
||||
this.streams = streams.clone()
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
}
|
||||
|
||||
async generate() {
|
||||
const files = this.streams.groupBy((stream: Stream) => stream.getFilename())
|
||||
|
||||
for (let filename of files.keys()) {
|
||||
const streams = new Collection(files.get(filename)).map((stream: Stream) => {
|
||||
const groupTitle = stream.getCategoryNames().join(';')
|
||||
if (groupTitle) stream.groupTitle = groupTitle
|
||||
|
||||
return stream
|
||||
})
|
||||
const playlist = new Playlist(streams, { public: true })
|
||||
const filepath = `raw/${filename}`
|
||||
await this.storage.save(filepath, playlist.toString())
|
||||
this.logFile.append(
|
||||
JSON.stringify({ type: 'raw', filepath, count: playlist.streams.count() }) + EOL
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ export class RegionsGenerator implements Generator {
|
|||
logFile: File
|
||||
|
||||
constructor({ streams, regions, logFile }: RegionsGeneratorProps) {
|
||||
this.streams = streams
|
||||
this.streams = streams.clone()
|
||||
this.regions = regions
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import { Collection, Storage, File, type Dictionary } from '@freearhey/core'
|
||||
import { Stream, Playlist } from '../models'
|
||||
import { PUBLIC_DIR } from '../constants'
|
||||
import { Generator } from './generator'
|
||||
import { EOL } from 'node:os'
|
||||
|
||||
type SourcesGeneratorProps = {
|
||||
streams: Collection
|
||||
logFile: File
|
||||
}
|
||||
|
||||
export class SourcesGenerator implements Generator {
|
||||
streams: Collection
|
||||
storage: Storage
|
||||
logFile: File
|
||||
|
||||
constructor({ streams, logFile }: SourcesGeneratorProps) {
|
||||
this.streams = streams.clone()
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
}
|
||||
|
||||
async generate() {
|
||||
const files: Dictionary = this.streams.groupBy((stream: Stream) => stream.getFilename())
|
||||
|
||||
for (let filename of files.keys()) {
|
||||
if (!filename) continue
|
||||
|
||||
let streams = new Collection(files.get(filename))
|
||||
streams = streams.map((stream: Stream) => {
|
||||
const groupTitle = stream.getCategoryNames().join(';')
|
||||
if (groupTitle) stream.groupTitle = groupTitle
|
||||
|
||||
return stream
|
||||
})
|
||||
const playlist = new Playlist(streams, { public: true })
|
||||
const filepath = `sources/${filename}`
|
||||
await this.storage.save(filepath, playlist.toString())
|
||||
this.logFile.append(
|
||||
JSON.stringify({ type: 'source', filepath, count: playlist.streams.count() }) + EOL
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { Collection, Dictionary } from '@freearhey/core'
|
||||
import { Category, Country, Feed, Guide, Stream, Subdivision } from './index'
|
||||
import { Category, Country, Feed, Guide, Logo, Stream, Subdivision } from './index'
|
||||
import type { ChannelData, ChannelSearchableData, ChannelSerializedData } from '../types/channel'
|
||||
|
||||
export class Channel {
|
||||
|
@ -19,9 +19,10 @@ export class Channel {
|
|||
launched?: string
|
||||
closed?: string
|
||||
replacedBy?: string
|
||||
isClosed: boolean
|
||||
website?: string
|
||||
logo: string
|
||||
feeds?: Collection
|
||||
logos: Collection = new Collection()
|
||||
|
||||
constructor(data?: ChannelData) {
|
||||
if (!data) return
|
||||
|
@ -40,7 +41,7 @@ export class Channel {
|
|||
this.closed = data.closed || undefined
|
||||
this.replacedBy = data.replaced_by || undefined
|
||||
this.website = data.website || undefined
|
||||
this.logo = data.logo
|
||||
this.isClosed = !!data.closed || !!data.replaced_by
|
||||
}
|
||||
|
||||
withSubdivision(subdivisionsKeyByCode: Dictionary): this {
|
||||
|
@ -71,6 +72,12 @@ export class Channel {
|
|||
return this
|
||||
}
|
||||
|
||||
withLogos(logosGroupedByChannelId: Dictionary): this {
|
||||
if (this.id) this.logos = new Collection(logosGroupedByChannelId.get(this.id))
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
getCountry(): Country | undefined {
|
||||
return this.country
|
||||
}
|
||||
|
@ -142,6 +149,35 @@ export class Channel {
|
|||
return this.isNSFW === false
|
||||
}
|
||||
|
||||
getLogos(): Collection {
|
||||
function feed(logo: Logo): number {
|
||||
if (!logo.feed) return 1
|
||||
if (logo.feed.isMain) return 1
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function format(logo: Logo): number {
|
||||
const levelByFormat = { SVG: 0, PNG: 3, APNG: 1, WebP: 1, AVIF: 1, JPEG: 2, GIF: 1 }
|
||||
|
||||
return logo.format ? levelByFormat[logo.format] : 0
|
||||
}
|
||||
|
||||
function size(logo: Logo): number {
|
||||
return Math.abs(512 - logo.width) + Math.abs(512 - logo.height)
|
||||
}
|
||||
|
||||
return this.logos.orderBy([feed, format, size], ['desc', 'desc', 'asc'], false)
|
||||
}
|
||||
|
||||
getLogo(): Logo | undefined {
|
||||
return this.getLogos().first()
|
||||
}
|
||||
|
||||
hasLogo(): boolean {
|
||||
return this.getLogos().notEmpty()
|
||||
}
|
||||
|
||||
getSearchable(): ChannelSearchableData {
|
||||
return {
|
||||
id: this.id,
|
||||
|
@ -171,8 +207,7 @@ export class Channel {
|
|||
launched: this.launched,
|
||||
closed: this.closed,
|
||||
replacedBy: this.replacedBy,
|
||||
website: this.website,
|
||||
logo: this.logo
|
||||
website: this.website
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +227,6 @@ export class Channel {
|
|||
this.closed = data.closed
|
||||
this.replacedBy = data.replacedBy
|
||||
this.website = data.website
|
||||
this.logo = data.logo
|
||||
|
||||
return this
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ export * from './feed'
|
|||
export * from './guide'
|
||||
export * from './issue'
|
||||
export * from './language'
|
||||
export * from './logo'
|
||||
export * from './playlist'
|
||||
export * from './region'
|
||||
export * from './stream'
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import { Collection, type Dictionary } from '@freearhey/core'
|
||||
import type { LogoData } from '../types/logo'
|
||||
import { type Feed } from './feed'
|
||||
|
||||
export class Logo {
|
||||
channelId: string
|
||||
feedId?: string
|
||||
feed: Feed
|
||||
tags: Collection
|
||||
width: number
|
||||
height: number
|
||||
format?: string
|
||||
url: string
|
||||
|
||||
constructor(data?: LogoData) {
|
||||
if (!data) return
|
||||
|
||||
this.channelId = data.channel
|
||||
this.feedId = data.feed || undefined
|
||||
this.tags = new Collection(data.tags)
|
||||
this.width = data.width
|
||||
this.height = data.height
|
||||
this.format = data.format || undefined
|
||||
this.url = data.url
|
||||
}
|
||||
|
||||
withFeed(feedsKeyById: Dictionary): this {
|
||||
if (!this.feedId) return this
|
||||
|
||||
this.feed = feedsKeyById.get(this.feedId)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
getStreamId(): string {
|
||||
if (!this.feedId) return this.channelId
|
||||
|
||||
return `${this.channelId}@${this.feedId}`
|
||||
}
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
import { Feed, Channel, Category, Region, Subdivision, Country, Language } from './index'
|
||||
import { Feed, Channel, Category, Region, Subdivision, Country, Language, Logo } from './index'
|
||||
import { URL, Collection, Dictionary } from '@freearhey/core'
|
||||
import type { StreamData } from '../types/stream'
|
||||
import parser from 'iptv-playlist-parser'
|
||||
import { IssueData } from '../core'
|
||||
import path from 'node:path'
|
||||
|
||||
export class Stream {
|
||||
name?: string
|
||||
|
@ -12,6 +13,7 @@ export class Stream {
|
|||
channel?: Channel
|
||||
feedId?: string
|
||||
feed?: Feed
|
||||
logos: Collection = new Collection()
|
||||
filepath?: string
|
||||
line?: number
|
||||
label?: string
|
||||
|
@ -21,6 +23,7 @@ export class Stream {
|
|||
userAgent?: string
|
||||
groupTitle: string = 'Undefined'
|
||||
removed: boolean = false
|
||||
directives: Collection = new Collection()
|
||||
|
||||
constructor(data?: StreamData) {
|
||||
if (!data) return
|
||||
|
@ -38,6 +41,7 @@ export class Stream {
|
|||
this.verticalResolution = verticalResolution || undefined
|
||||
this.isInterlaced = isInterlaced || undefined
|
||||
this.label = data.label || undefined
|
||||
this.directives = new Collection(data.directives)
|
||||
}
|
||||
|
||||
update(issueData: IssueData): this {
|
||||
|
@ -46,7 +50,8 @@ export class Stream {
|
|||
quality: issueData.getString('quality'),
|
||||
httpUserAgent: issueData.getString('httpUserAgent'),
|
||||
httpReferrer: issueData.getString('httpReferrer'),
|
||||
newStreamUrl: issueData.getString('newStreamUrl')
|
||||
newStreamUrl: issueData.getString('newStreamUrl'),
|
||||
directives: issueData.getArray('directives')
|
||||
}
|
||||
|
||||
if (data.label !== undefined) this.label = data.label
|
||||
|
@ -54,11 +59,43 @@ export class Stream {
|
|||
if (data.httpUserAgent !== undefined) this.userAgent = data.httpUserAgent
|
||||
if (data.httpReferrer !== undefined) this.referrer = data.httpReferrer
|
||||
if (data.newStreamUrl !== undefined) this.url = data.newStreamUrl
|
||||
if (data.directives !== undefined) this.directives = new Collection(data.directives)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
fromPlaylistItem(data: parser.PlaylistItem): this {
|
||||
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 parseDirectives(string: string) {
|
||||
let directives = new Collection()
|
||||
|
||||
if (!string) return directives
|
||||
|
||||
const supportedDirectives = ['#EXTVLCOPT', '#KODIPROP']
|
||||
const lines = string.split('\r\n')
|
||||
const regex = new RegExp(`^${supportedDirectives.join('|')}`, 'i')
|
||||
|
||||
lines.forEach((line: string) => {
|
||||
if (regex.test(line)) {
|
||||
directives.add(line.trim())
|
||||
}
|
||||
})
|
||||
|
||||
return directives
|
||||
}
|
||||
|
||||
if (!data.name) throw new Error('"name" property is required')
|
||||
if (!data.url) throw new Error('"url" property is required')
|
||||
|
||||
|
@ -77,6 +114,7 @@ export class Stream {
|
|||
this.url = data.url
|
||||
this.referrer = data.http.referrer || undefined
|
||||
this.userAgent = data.http['user-agent'] || undefined
|
||||
this.directives = parseDirectives(data.raw)
|
||||
|
||||
return this
|
||||
}
|
||||
|
@ -99,6 +137,12 @@ export class Stream {
|
|||
return this
|
||||
}
|
||||
|
||||
withLogos(logosGroupedByStreamId: Dictionary): this {
|
||||
if (this.id) this.logos = new Collection(logosGroupedByStreamId.get(this.id))
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
setId(id: string): this {
|
||||
this.id = id
|
||||
|
||||
|
@ -130,6 +174,12 @@ export class Stream {
|
|||
return this.line || -1
|
||||
}
|
||||
|
||||
getFilename(): string {
|
||||
if (!this.filepath) return ''
|
||||
|
||||
return path.basename(this.filepath)
|
||||
}
|
||||
|
||||
setFilepath(filepath: string): this {
|
||||
this.filepath = filepath
|
||||
|
||||
|
@ -294,8 +344,35 @@ export class Stream {
|
|||
return this.feed ? this.feed.isInternational() : false
|
||||
}
|
||||
|
||||
getLogo(): string {
|
||||
return this?.channel?.logo || ''
|
||||
getLogos(): Collection {
|
||||
function format(logo: Logo): number {
|
||||
const levelByFormat = { SVG: 0, PNG: 3, APNG: 1, WebP: 1, AVIF: 1, JPEG: 2, GIF: 1 }
|
||||
|
||||
return logo.format ? levelByFormat[logo.format] : 0
|
||||
}
|
||||
|
||||
function size(logo: Logo): number {
|
||||
return Math.abs(512 - logo.width) + Math.abs(512 - logo.height)
|
||||
}
|
||||
|
||||
return this.logos.orderBy([format, size], ['desc', 'asc'], false)
|
||||
}
|
||||
|
||||
getLogo(): Logo | undefined {
|
||||
return this.getLogos().first()
|
||||
}
|
||||
|
||||
hasLogo(): boolean {
|
||||
return this.getLogos().notEmpty()
|
||||
}
|
||||
|
||||
getLogoUrl(): string {
|
||||
let logo: Logo | undefined
|
||||
|
||||
if (this.hasLogo()) logo = this.getLogo()
|
||||
else logo = this?.channel?.getLogo()
|
||||
|
||||
return logo ? logo.url : ''
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
|
@ -339,7 +416,7 @@ export class Stream {
|
|||
let output = `#EXTINF:-1 tvg-id="${this.getId()}"`
|
||||
|
||||
if (options.public) {
|
||||
output += ` tvg-logo="${this.getLogo()}" group-title="${this.groupTitle}"`
|
||||
output += ` tvg-logo="${this.getLogoUrl()}" group-title="${this.groupTitle}"`
|
||||
}
|
||||
|
||||
if (this.referrer) {
|
||||
|
@ -352,13 +429,9 @@ export class Stream {
|
|||
|
||||
output += `,${this.getTitle()}`
|
||||
|
||||
if (this.referrer) {
|
||||
output += `\r\n#EXTVLCOPT:http-referrer=${this.referrer}`
|
||||
}
|
||||
|
||||
if (this.userAgent) {
|
||||
output += `\r\n#EXTVLCOPT:http-user-agent=${this.userAgent}`
|
||||
}
|
||||
this.directives.forEach((prop: string) => {
|
||||
output += `\r\n${prop}`
|
||||
})
|
||||
|
||||
output += `\r\n${this.url}`
|
||||
|
||||
|
@ -366,19 +439,6 @@ export class Stream {
|
|||
}
|
||||
}
|
||||
|
||||
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, '\\$&')
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ export type ChannelSerializedData = {
|
|||
closed?: string
|
||||
replacedBy?: string
|
||||
website?: string
|
||||
logo: string
|
||||
}
|
||||
|
||||
export type ChannelData = {
|
||||
|
@ -39,7 +38,6 @@ export type ChannelData = {
|
|||
closed: string
|
||||
replaced_by: string
|
||||
website: string
|
||||
logo: string
|
||||
}
|
||||
|
||||
export type ChannelSearchableData = {
|
||||
|
|
|
@ -13,6 +13,7 @@ export type DataLoaderData = {
|
|||
blocklist: object | object[]
|
||||
channels: object | object[]
|
||||
feeds: object | object[]
|
||||
logos: object | object[]
|
||||
timezones: object | object[]
|
||||
guides: object | object[]
|
||||
streams: object | object[]
|
||||
|
|
|
@ -5,6 +5,7 @@ export type DataProcessorData = {
|
|||
subdivisionsGroupedByCountryCode: Dictionary
|
||||
feedsGroupedByChannelId: Dictionary
|
||||
guidesGroupedByStreamId: Dictionary
|
||||
logosGroupedByStreamId: Dictionary
|
||||
subdivisionsKeyByCode: Dictionary
|
||||
countriesKeyByCode: Dictionary
|
||||
languagesKeyByCode: Dictionary
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
export type LogoData = {
|
||||
channel: string
|
||||
feed: string | null
|
||||
tags: string[]
|
||||
width: number
|
||||
height: number
|
||||
format: string | null
|
||||
url: string
|
||||
}
|
|
@ -7,4 +7,5 @@ export type StreamData = {
|
|||
user_agent: string | null
|
||||
quality: string | null
|
||||
label: string | null
|
||||
directives: string[]
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
{
|
||||
"channel": "AndorraTV.ad",
|
||||
"feed": "SD",
|
||||
"url": "https://iptv-all.lanesh4d0w.repl.co/andorra/atv",
|
||||
"url": "https://iptv-all.lanesh4d0w.repl.co/andorra/atv|Referer=\"https://referer.xyz/\"|User-Agent=\"Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1\"|Origin=\"https://origin.xyz\"",
|
||||
"referrer": null,
|
||||
"user_agent": null
|
||||
},
|
||||
|
|
|
@ -6,6 +6,10 @@ http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.i
|
|||
#EXTINF:-1 tvg-id="NPO2.nl" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",NPO 2 (302p) [Geo-blocked]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8?|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0+(iPhone;+CPU+iPhone+OS+17_7+like+Mac+OS+X)+AppleWebKit/605.1.15+(KHTML,+like+Gecko)+Version/18.0+Mobile/15E148+Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 [Geo-blocked]
|
||||
http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo22.isml/.m3u8
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="" group-title="Undefined",ATV
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="" group-title="Undefined",ATV HD
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
||||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV
|
||||
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="" group-title="Undefined",ATV
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="" group-title="Undefined",ATV HD
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
||||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV
|
||||
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
||||
|
|
|
@ -12,10 +12,14 @@ http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
|
|||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="" group-title="Undefined",ATV
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="" group-title="Undefined",ATV HD
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
||||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV
|
||||
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="" group-title="Andorra",ATV
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Andorra",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Canada",Meteomedia
|
||||
http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
|
||||
|
@ -22,8 +22,12 @@ http://146.59.85.40:89/dunaworld/index.m3u8
|
|||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="" group-title="Undefined",ATV HD
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
||||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV
|
||||
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="" group-title="Catalan",ATV
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Catalan",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="English",BBC News HD
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8
|
||||
|
@ -8,8 +8,12 @@ http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
|
|||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="" group-title="Undefined",ATV HD
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
||||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV
|
||||
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="" group-title="Undefined",ATV
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="" group-title="Undefined",ATV HD
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
||||
#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8
|
||||
|
|
|
@ -11,13 +11,13 @@ http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8
|
|||
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
|
||||
#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="Commonwealth of Independent States",ЭлТР (480p) [Not 24/7]
|
||||
http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="" group-title="Europe",ATV
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Europe",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Europe",ЛДПР ТВ (1080p)
|
||||
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
|
||||
#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="Europe",ЭлТР (480p) [Not 24/7]
|
||||
http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="" group-title="Europe, the Middle East and Africa",ATV
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Europe, the Middle East and Africa",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Europe, the Middle East and Africa",ЛДПР ТВ (1080p)
|
||||
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
|
||||
|
@ -34,8 +34,12 @@ http://146.59.85.40:89/dunaworld/index.m3u8
|
|||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="" group-title="Undefined",ATV HD
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
||||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV
|
||||
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="" group-title="Undefined",ATV HD
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
||||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV
|
||||
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="" group-title="Undefined",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv2
|
|
@ -0,0 +1,3 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia
|
||||
http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
|
|
@ -0,0 +1,3 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV
|
||||
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
|
@ -0,0 +1,3 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7]
|
||||
http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8
|
|
@ -0,0 +1,3 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8
|
|
@ -0,0 +1,15 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p)
|
||||
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
|
||||
#EXTINF:-1 tvg-id="VisitXTV.nl" tvg-logo="https://i.imgur.com/RJ9wbNF.jpg" group-title="XXX",Visit-X TV
|
||||
https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8
|
||||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i)
|
||||
http://146.59.85.40:89/dunaworld/index.m3u8
|
|
@ -1,5 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="" group-title="Undefined",ATV
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p)
|
||||
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="" group-title="Undefined",ATV
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p)
|
||||
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="" group-title="Undefined",ATV HD
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
||||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV
|
||||
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="" group-title="Undefined",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
|
@ -0,0 +1,3 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia
|
||||
http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
|
|
@ -0,0 +1,3 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV
|
||||
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
|
@ -0,0 +1,3 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7]
|
||||
http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8
|
|
@ -0,0 +1,3 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8
|
|
@ -0,0 +1,15 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i)
|
||||
http://146.59.85.40:89/dunaworld/index.m3u8
|
||||
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p)
|
||||
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
|
||||
#EXTINF:-1 tvg-id="VisitXTV.nl" tvg-logo="https://i.imgur.com/RJ9wbNF.jpg" group-title="XXX",Visit-X TV
|
||||
https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8
|
|
@ -1,3 +1,15 @@
|
|||
{"type":"raw","filepath":"raw/ad.m3u","count":4}
|
||||
{"type":"raw","filepath":"raw/ca.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/in.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/kg.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/uk.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/unsorted.m3u","count":4}
|
||||
{"type":"source","filepath":"sources/ad.m3u","count":3}
|
||||
{"type":"source","filepath":"sources/ca.m3u","count":1}
|
||||
{"type":"source","filepath":"sources/in.m3u","count":1}
|
||||
{"type":"source","filepath":"sources/kg.m3u","count":1}
|
||||
{"type":"source","filepath":"sources/uk.m3u","count":1}
|
||||
{"type":"source","filepath":"sources/unsorted.m3u","count":4}
|
||||
{"type":"category","filepath":"categories/auto.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/cooking.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/comedy.m3u","count":0}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="TFX.fr" http-referrer="https://pkpakiplay.xyz/" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1",TFX
|
||||
#EXTVLCOPT:http-referrer=https://pkpakiplay.xyz/
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1
|
||||
https://stitcher-ipv4.pluto.tv/v1/stitch/embed/hls/channel/64c109a4798def0008a6e03e/master.m3u8?advertisingId={PSID}&appVersion=unknown&deviceDNT={TARGETOPT}&deviceId={PSID}&deviceLat=0&deviceLon=0&deviceMake=samsung&deviceModel=samsung&deviceType=samsung-tvplus&deviceVersion=unknown&embedPartner=samsung-tvplus&profileFloor=&profileLimit=&samsung_app_domain={APP_DOMAIN}&samsung_app_name={APP_NAME}&us_privacy=1YNY
|
||||
|
|
|
@ -4,4 +4,10 @@ http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8
|
|||
#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (480p) [Geo-blocked]
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8
|
||||
#EXTINF:-1 tvg-id="BeanoTV.uk",Beano TV
|
||||
https://a5b4bacecd47433dad06d3189fc7422e.mediatailor.us-east-1.amazonaws.com/v1/manifest/04fd913bb278d8775298c26fdca9d9841f37601f/RakutenTV-eu_BeanoTV/b1f233d5-847c-437d-aa4f-f73e67a85323/2.m3u8
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
https://a5b4bacecd47433dad06d3189fc7422e.mediatailor.us-east-1.amazonaws.com/v1/manifest/04fd913bb278d8775298c26fdca9d9841f37601f/RakutenTV-eu_BeanoTV/b1f233d5-847c-437d-aa4f-f73e67a85323/2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="BBCAmerica.us@East" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246",BBC America East (720p)
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246
|
||||
https://xui-backend.energeek.cl/live/9/playlist.m3u8?username=ZZDemoIPTVGH&password=mdo96EuqMkTR
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
https://xui-backend.energeek.cl/live/9/playlist.m3u8?username=ZZDemoIPTVGH&password=mdo96EuqMkTR|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="FastTV.us",Fast TV
|
||||
https://3fa797d5.wurl.com/manifest/f36d25e7e52f1ba8d7e56eb859c636563214f541/T05PX01vdG9yVHJlbmRGYXN0VFZfSExT/b5e5e0e2-12b3-4312-93c9-c0a7c50b41ca/4.m3u8
|
||||
|
|
|
@ -214,6 +214,28 @@ Same thing, but split up into separate files:
|
|||
|
||||
</details>
|
||||
|
||||
### Grouped by sources
|
||||
|
||||
Playlists in which channels are grouped by broadcast source.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
<br>
|
||||
|
||||
To use the playlist, simply replace `<FILENAME>` in the link below with the name of one of the files in the [streams](streams) folder.
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/sources/<FILENAME>.m3u
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Also, any of our internal playlists are available in raw form (without any filtering or sorting) at this link:
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/raw/<FILENAME>.m3u
|
||||
```
|
||||
|
||||
## Database
|
||||
|
||||
All channel data is taken from the [iptv-org/database](https://github.com/iptv-org/database) repository. If you find any errors please open a new [issue](https://github.com/iptv-org/database/issues) there.
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
#EXTINF:-1 tvg-id="Zoo.ad",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
||||
#EXTINF:-1 tvg-id="AndorraTV.ad@SD",ATV
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/atv|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
"subdivision": null,
|
||||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false,
|
||||
"logo": null
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "BBCNews.uk",
|
||||
|
@ -21,8 +20,7 @@
|
|||
"news",
|
||||
"general"
|
||||
],
|
||||
"is_nsfw": false,
|
||||
"logo": "https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png"
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "Eve.us",
|
||||
|
@ -32,8 +30,7 @@
|
|||
"subdivision": null,
|
||||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false,
|
||||
"logo": "https://www.lyngsat.com/logo/tv/ee/eve_us.png"
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "EverydayHeroes.us",
|
||||
|
@ -43,8 +40,7 @@
|
|||
"subdivision": null,
|
||||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false,
|
||||
"logo": "https://i.imgur.com/Iam3ol3.png"
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "FoxSports1.us",
|
||||
|
@ -54,8 +50,7 @@
|
|||
"subdivision": null,
|
||||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false,
|
||||
"logo": "https://cdn.tvpassport.com/image/station/100x100/fs1.png"
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "FoxSports2.us",
|
||||
|
@ -65,8 +60,7 @@
|
|||
"subdivision": null,
|
||||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false,
|
||||
"logo": null
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "LDPRTV.ru",
|
||||
|
@ -78,8 +72,7 @@
|
|||
"categories": [
|
||||
"general"
|
||||
],
|
||||
"is_nsfw": false,
|
||||
"logo": "https://iptvx.one/icn/ldpr-tv.png"
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "LibyasChannel.ly",
|
||||
|
@ -89,8 +82,7 @@
|
|||
"subdivision": null,
|
||||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false,
|
||||
"logo": "https://i.imgur.com/RD9wbNF.jpg"
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "MeteoMedia.ca",
|
||||
|
@ -102,8 +94,7 @@
|
|||
"categories": [
|
||||
"weather"
|
||||
],
|
||||
"is_nsfw": false,
|
||||
"logo": "https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png"
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "TVN.pl",
|
||||
|
@ -113,8 +104,7 @@
|
|||
"subdivision": null,
|
||||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false,
|
||||
"logo": "https://www.sms.cz/kategorie/televize/bmp/loga/velka/TVN.png"
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "VisitXTV.nl",
|
||||
|
@ -126,8 +116,7 @@
|
|||
"categories": [
|
||||
"xxx"
|
||||
],
|
||||
"is_nsfw": true,
|
||||
"logo": "https://i.imgur.com/RJ9wbNF.jpg"
|
||||
"is_nsfw": true
|
||||
},
|
||||
{
|
||||
"id": "TUTV.us",
|
||||
|
@ -139,8 +128,7 @@
|
|||
"categories": [
|
||||
"general"
|
||||
],
|
||||
"is_nsfw": false,
|
||||
"logo": "https://i.imgur.com/RJ9wbN4.jpg"
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "ManoramaNews.in",
|
||||
|
@ -160,8 +148,7 @@
|
|||
"launched": "2006-08-17",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.manoramanews.com",
|
||||
"logo": "https://i.imgur.com/adjRrVx.png"
|
||||
"website": "https://www.manoramanews.com"
|
||||
},
|
||||
{
|
||||
"id": "TV3.my",
|
||||
|
@ -179,8 +166,7 @@
|
|||
"launched": null,
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": null,
|
||||
"logo": "https://i.imgur.com/adjRrVx.png"
|
||||
"website": null
|
||||
},
|
||||
{
|
||||
"id": "BBCAmerica.us",
|
||||
|
@ -198,8 +184,7 @@
|
|||
"launched": null,
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": null,
|
||||
"logo": "https://i.imgur.com/adjRrVx.png"
|
||||
"website": null
|
||||
},
|
||||
{
|
||||
"id": "ATVPlus.pe",
|
||||
|
@ -219,8 +204,7 @@
|
|||
"launched": null,
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.atv.pe/",
|
||||
"logo": "https://i.imgur.com/fY9256H.png"
|
||||
"website": "https://www.atv.pe/"
|
||||
},
|
||||
{
|
||||
"id": "BeanoTV.uk",
|
||||
|
@ -238,8 +222,7 @@
|
|||
"launched": null,
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.beanostudios.com/",
|
||||
"logo": "https://i.imgur.com/IKHFZDJ.png"
|
||||
"website": "https://www.beanostudios.com/"
|
||||
},
|
||||
{
|
||||
"id": "ATX.jp",
|
||||
|
@ -261,8 +244,7 @@
|
|||
"launched": "1997-12-24",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "http://www.at-x.com/",
|
||||
"logo": "https://i.imgur.com/turWday.png"
|
||||
"website": "http://www.at-x.com/"
|
||||
},
|
||||
{
|
||||
"id": "AajTak.in",
|
||||
|
@ -282,8 +264,7 @@
|
|||
"launched": "2000-12-31",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.aajtak.in/livetv",
|
||||
"logo": "https://i.imgur.com/RpIdCB3.png"
|
||||
"website": "https://www.aajtak.in/livetv"
|
||||
},
|
||||
{
|
||||
"id": "Weathernews.jp",
|
||||
|
@ -301,8 +282,7 @@
|
|||
"launched": null,
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": null,
|
||||
"logo": "https://i.imgur.com/A8uRSTS.png"
|
||||
"website": null
|
||||
},
|
||||
{
|
||||
"id": "MethTV.lk",
|
||||
|
@ -322,8 +302,7 @@
|
|||
"launched": null,
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://methtv.lk/",
|
||||
"logo": "https://i.imgur.com/jZaOFxI.png"
|
||||
"website": "https://methtv.lk/"
|
||||
},
|
||||
{
|
||||
"id": "Match4.hu",
|
||||
|
@ -341,8 +320,7 @@
|
|||
"launched": null,
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": null,
|
||||
"logo": "https://i.imgur.com/hzexBLX.png"
|
||||
"website": null
|
||||
},
|
||||
{
|
||||
"id": "FastTV.us",
|
||||
|
@ -363,8 +341,7 @@
|
|||
"launched": "2022-10-26",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://watch.motortrend.com/",
|
||||
"logo": "https://us1-prod-images.disco-api.com/2020/7/13/4f26aaf2-a993-480d-9675-0d501fb8d86f.png?bf=0&f=png&p=true&q=85&w=250"
|
||||
"website": "https://watch.motortrend.com/"
|
||||
},
|
||||
{
|
||||
"id": "MCOTHD.th",
|
||||
|
@ -386,8 +363,7 @@
|
|||
"launched": "1955-06-24",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://tv.mcot.net/mcothd",
|
||||
"logo": "https://i.imgur.com/ejPxGmU.png"
|
||||
"website": "https://tv.mcot.net/mcothd"
|
||||
},
|
||||
{
|
||||
"id": "AmarinTV.th",
|
||||
|
@ -409,8 +385,7 @@
|
|||
"launched": "2012-12-01",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.amarintv.com/",
|
||||
"logo": "https://static.wikia.nocookie.net/logopedia/images/f/ff/Amarin_TV_2015.svg/revision/latest/scale-to-width-down/512"
|
||||
"website": "https://www.amarintv.com/"
|
||||
},
|
||||
{
|
||||
"id": "France2.fr",
|
||||
|
@ -430,8 +405,7 @@
|
|||
"launched": "1959-09-10",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.france.tv/france-2/",
|
||||
"logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/France_2_2018.svg/512px-France_2_2018.svg.png"
|
||||
"website": "https://www.france.tv/france-2/"
|
||||
},
|
||||
{
|
||||
"id": "France3.fr",
|
||||
|
@ -451,8 +425,7 @@
|
|||
"launched": "1972-12-31",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.france.tv/france-3/",
|
||||
"logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/France_3_2018.svg/512px-France_3_2018.svg.png"
|
||||
"website": "https://www.france.tv/france-3/"
|
||||
},
|
||||
{
|
||||
"id": "France5.fr",
|
||||
|
@ -472,8 +445,7 @@
|
|||
"launched": "1994-12-13",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.france.tv/france-5/",
|
||||
"logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/50/France_5_2018.svg/512px-France_5_2018.svg.png"
|
||||
"website": "https://www.france.tv/france-5/"
|
||||
},
|
||||
{
|
||||
"id": "France3.fr",
|
||||
|
@ -493,8 +465,7 @@
|
|||
"launched": "1962-01-01",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://france3-regions.francetvinfo.fr/nouvelle-aquitaine/",
|
||||
"logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/France_3_Aquitaine_-_Logo_2018.svg/512px-France_3_Aquitaine_-_Logo_2018.svg.png"
|
||||
"website": "https://france3-regions.francetvinfo.fr/nouvelle-aquitaine/"
|
||||
},
|
||||
{
|
||||
"id": "TF1.fr",
|
||||
|
@ -514,8 +485,7 @@
|
|||
"launched": "1975-01-06",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.tf1.fr",
|
||||
"logo": "https://i.imgur.com/QxHt9NC.png"
|
||||
"website": "https://www.tf1.fr"
|
||||
},
|
||||
{
|
||||
"id": "TF1SeriesFilms.fr",
|
||||
|
@ -537,8 +507,7 @@
|
|||
"launched": null,
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.tf1.fr/tf1-series-films",
|
||||
"logo": "https://i.imgur.com/4CJIDKQ.png"
|
||||
"website": "https://www.tf1.fr/tf1-series-films"
|
||||
},
|
||||
{
|
||||
"id": "TMC.fr",
|
||||
|
@ -558,8 +527,7 @@
|
|||
"launched": "1954-11-19",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.tf1.fr/tmc",
|
||||
"logo": "https://upload.wikimedia.org/wikipedia/en/thumb/5/54/TMC_logo.svg/512px-TMC_logo.svg.png"
|
||||
"website": "https://www.tf1.fr/tmc"
|
||||
},
|
||||
{
|
||||
"id": "TFX.fr",
|
||||
|
@ -575,8 +543,7 @@
|
|||
"launched": null,
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.tf1.fr/tfx",
|
||||
"logo": "https://i.imgur.com/d91GcVf.png"
|
||||
"website": "https://www.tf1.fr/tfx"
|
||||
},
|
||||
{
|
||||
"id": "ManoramaNews.in",
|
||||
|
@ -596,8 +563,7 @@
|
|||
"launched": "2006-08-17",
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://www.manoramanews.com",
|
||||
"logo": "https://i.imgur.com/adjRrVx.png"
|
||||
"website": "https://www.manoramanews.com"
|
||||
},
|
||||
{
|
||||
"id": "13thStreet.au",
|
||||
|
@ -617,8 +583,7 @@
|
|||
"launched": "2009-11-15",
|
||||
"closed": "2019-12-31",
|
||||
"replaced_by": "Sleuth.au",
|
||||
"website": "http://www.13thstreet.com.au/",
|
||||
"logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/13th_street_logo_uk_master_rgb_black.png/512px-13th_street_logo_uk_master_rgb_black.png"
|
||||
"website": "http://www.13thstreet.com.au/"
|
||||
},
|
||||
{
|
||||
"id": "Zoo.ad",
|
||||
|
@ -628,8 +593,7 @@
|
|||
"subdivision": null,
|
||||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false,
|
||||
"logo": null
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "DunaWorld.hu",
|
||||
|
@ -641,8 +605,7 @@
|
|||
"categories": [
|
||||
"General"
|
||||
],
|
||||
"is_nsfw": false,
|
||||
"logo": "https://i.imgur.com/uOBQJZS.png"
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "ElTR.kg",
|
||||
|
@ -675,8 +638,7 @@
|
|||
"launched": null,
|
||||
"closed": null,
|
||||
"replaced_by": null,
|
||||
"website": "https://eltr.kg",
|
||||
"logo": "https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png"
|
||||
"website": "https://eltr.kg"
|
||||
},
|
||||
{
|
||||
"id": "IONTV.us",
|
||||
|
@ -686,7 +648,26 @@
|
|||
"subdivision": null,
|
||||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false,
|
||||
"logo": "https://i.imgur.com/Iam3ol3.png"
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "NPO1.nl",
|
||||
"name": "NPO 1",
|
||||
"network": null,
|
||||
"country": "NL",
|
||||
"subdivision": null,
|
||||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "NPO2.nl",
|
||||
"name": "NPO 2",
|
||||
"network": null,
|
||||
"country": "NL",
|
||||
"subdivision": null,
|
||||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false
|
||||
}
|
||||
]
|
|
@ -0,0 +1,11 @@
|
|||
[
|
||||
{"channel":"MeteoMedia.ca","feed":null,"tags":[],"width":512,"height":512,"format":"PNG","url":"https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png"},
|
||||
{"channel":"LDPRTV.ru","feed":null,"tags":[],"width":512,"height":512,"format":"PNG","url":"https://iptvx.one/icn/ldpr-tv.png"},
|
||||
{"channel":"ElTR.kg","feed":null,"tags":[],"width":512,"height":512,"format":"PNG","url":"https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png"},
|
||||
{"channel":"BBCNews.uk","feed":null,"tags":[],"width":512,"height":512,"format":"PNG","url":"https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png"},
|
||||
{"channel":"DunaWorld.hu","feed":null,"tags":[],"width":512,"height":512,"format":"PNG","url":"https://i.imgur.com/uOBQJZS.png"},
|
||||
{"channel":"VisitXTV.nl","feed":null,"tags":[],"width":512,"height":512,"format":"JPEG","url":"https://i.imgur.com/RJ9wbNF.jpg"},
|
||||
{"channel":"AndorraTV.ad","feed":"SD","tags":[],"width":512,"height":512,"format":"PNG","url":"https://i.imgur.com/BnhTn8i.png"},
|
||||
{"channel":"AndorraTV.ad","feed":null,"tags":[],"width":1000,"height":1000,"format":"JPEG","url":"https://i.imgur.com/AnhTn8i.png"},
|
||||
{"channel":"AndorraTV.ad","feed":null,"tags":[],"width":512,"height":512,"format":"PNG","url":"https://i.imgur.com/CnhTn8i.png"}
|
||||
]
|
|
@ -1515,7 +1515,7 @@ module.exports = [
|
|||
closed_at: null,
|
||||
author_association: 'NONE',
|
||||
active_lock_reason: null,
|
||||
body: '### Stream ID\r\n\r\nBeanoTV.uk\r\n\r\n### Stream URL (optional)\r\n\r\nhttps://a5b4bacecd47433dad06d3189fc7422e.mediatailor.us-east-1.amazonaws.com/v1/manifest/04fd913bb278d8775298c26fdca9d9841f37601f/RakutenTV-eu_BeanoTV/b1f233d5-847c-437d-aa4f-f73e67a85323/2.m3u8\r\n\r\n### Notes (optional)\r\n\r\n_No response_\r\n\r\n### Please confirm the following\r\n\r\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)',
|
||||
body: '### Stream ID\r\n\r\nBeanoTV.uk\r\n\r\n### Stream URL (optional)\r\n\r\nhttps://a5b4bacecd47433dad06d3189fc7422e.mediatailor.us-east-1.amazonaws.com/v1/manifest/04fd913bb278d8775298c26fdca9d9841f37601f/RakutenTV-eu_BeanoTV/b1f233d5-847c-437d-aa4f-f73e67a85323/2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"\r\n\r\n### Directives (optional)\r\n\r\n#EXTVLCOPT:http-referrer=http://imn.iq\r\n\r\n#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148\r\n\r\n#KODIPROP:inputstream=inputstream.adaptive\r\n\r\n#KODIPROP:inputstream.adaptive.manifest_type=mpd\r\n\r\n#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha\r\n\r\n#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|\r\n\r\n### Notes (optional)\r\n\r\n_No response_\r\n\r\n### Please confirm the following\r\n\r\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)',
|
||||
reactions: {
|
||||
url: 'https://api.github.com/repos/iptv-org/iptv/issues/13751/reactions',
|
||||
total_count: 0,
|
||||
|
@ -1664,7 +1664,7 @@ module.exports = [
|
|||
{
|
||||
id: 5923508587,
|
||||
node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw',
|
||||
url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add',
|
||||
url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:edit',
|
||||
name: 'streams:edit',
|
||||
color: '017ff9',
|
||||
default: false,
|
||||
|
@ -1743,7 +1743,7 @@ module.exports = [
|
|||
{
|
||||
id: 5923508587,
|
||||
node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw',
|
||||
url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add',
|
||||
url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:edit',
|
||||
name: 'streams:edit',
|
||||
color: '017ff9',
|
||||
default: false,
|
||||
|
@ -1761,7 +1761,7 @@ module.exports = [
|
|||
closed_at: null,
|
||||
author_association: 'COLLABORATOR',
|
||||
active_lock_reason: null,
|
||||
body: '### Stream URL (required)\n\nhttps://servilive.com:3126/live/tele2000live.m3u8\n\n### New Stream URL\n\nhttps://xui-backend.energeek.cl/live/9/playlist.m3u8?username=ZZDemoIPTVGH&password=mdo96EuqMkTR\n\n### Stream ID\n\nBBCAmerica.us@East\n\n### Quality\n\n720p\n\n### Label\n\n~\n\n### HTTP User-Agent\n\nMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246\n\n### HTTP Referrer\n\n~\n\n### Notes\n\n_No response_\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)',
|
||||
body: '### Stream URL (required)\n\nhttps://servilive.com:3126/live/tele2000live.m3u8\n\n### New Stream URL\n\nhttps://xui-backend.energeek.cl/live/9/playlist.m3u8?username=ZZDemoIPTVGH&password=mdo96EuqMkTR|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"\n\n### Stream ID\n\nBBCAmerica.us@East\n\n### Quality\n\n720p\n\n### Label\n\n~\n\n### HTTP User-Agent\n\nMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246\n\n### HTTP Referrer\n\n~\n\n### Directives (optional)\r\n\r\n#EXTVLCOPT:http-referrer=http://imn.iq\r\n\r\n#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148\r\n\r\n#KODIPROP:inputstream=inputstream.adaptive\r\n\r\n#KODIPROP:inputstream.adaptive.manifest_type=mpd\r\n\r\n#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha\r\n\r\n#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|\n\n### Notes\n\n_No response_\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)',
|
||||
reactions: {
|
||||
url: 'https://api.github.com/repos/iptv-org/iptv/issues/14110/reactions',
|
||||
total_count: 0,
|
||||
|
@ -1822,7 +1822,7 @@ module.exports = [
|
|||
{
|
||||
id: 5923508587,
|
||||
node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw',
|
||||
url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add',
|
||||
url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:edit',
|
||||
name: 'streams:edit',
|
||||
color: '017ff9',
|
||||
default: false,
|
|
@ -2,7 +2,11 @@
|
|||
#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (302p) [Geo-blocked]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8?
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8?|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 [Geo-blocked]
|
||||
http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo22.isml/.m3u8
|
||||
#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (342p)
|
||||
|
|
|
@ -6,6 +6,10 @@ https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8
|
|||
#EXTINF:-1 tvg-id="" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7]
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"
|
||||
#EXTINF:-1 tvg-id="DunaWorld.hu",Duna World (576i)
|
||||
http://146.59.85.40:89/dunaworld/index.m3u8
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="qib22lAq1L.us",ABC (720p)
|
||||
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
#KODIPROP:inputstream=inputstream.adaptive
|
||||
#KODIPROP:inputstream.adaptive.manifest_type=mpd
|
||||
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
|
||||
#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|
|
||||
https://example.com/playlist2.m3u8
|
||||
|
|
|
@ -115,6 +115,28 @@ Same thing, but split up into separate files:
|
|||
|
||||
</details>
|
||||
|
||||
### Grouped by sources
|
||||
|
||||
Playlists in which channels are grouped by broadcast source.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
<br>
|
||||
|
||||
To use the playlist, simply replace `<FILENAME>` in the link below with the name of one of the files in the [streams](streams) folder.
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/sources/<FILENAME>.m3u
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Also, any of our internal playlists are available in raw form (without any filtering or sorting) at this link:
|
||||
|
||||
```
|
||||
https://iptv-org.github.io/iptv/raw/<FILENAME>.m3u
|
||||
```
|
||||
|
||||
## Database
|
||||
|
||||
All channel data is taken from the [iptv-org/database](https://github.com/iptv-org/database) repository. If you find any errors please open a new [issue](https://github.com/iptv-org/database/issues) there.
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
{"type":"source","filepath":"sources/ad.m3u","count":3}
|
||||
{"type":"source","filepath":"sources/ca.m3u","count":1}
|
||||
{"type":"source","filepath":"sources/in.m3u","count":1}
|
||||
{"type":"source","filepath":"sources/kg.m3u","count":1}
|
||||
{"type":"source","filepath":"sources/uk.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/auto.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/animation.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/business.m3u","count":0}
|
||||
|
|
|
@ -4,9 +4,10 @@ import * as fs from 'fs-extra'
|
|||
import { glob } from 'glob'
|
||||
import os from 'os'
|
||||
|
||||
let ENV_VAR = 'STREAMS_DIR=tests/__data__/output/streams'
|
||||
let ENV_VAR = 'STREAMS_DIR=tests/__data__/output/streams DATA_DIR=tests/__data__/input/data'
|
||||
if (os.platform() === 'win32') {
|
||||
ENV_VAR = 'SET "STREAMS_DIR=tests/__data__/output/streams" &&'
|
||||
ENV_VAR =
|
||||
'SET "STREAMS_DIR=tests/__data__/output/streams" && SET "DATA_DIR=tests/__data__/input/data" &&'
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -6,9 +6,9 @@ type ExecError = {
|
|||
stdout: string
|
||||
}
|
||||
|
||||
let ENV_VAR = 'ROOT_DIR=tests/__data__/input'
|
||||
let ENV_VAR = 'ROOT_DIR=tests/__data__/input DATA_DIR=tests/__data__/input/data'
|
||||
if (os.platform() === 'win32') {
|
||||
ENV_VAR = 'SET "ROOT_DIR=tests/__data__/input" &&'
|
||||
ENV_VAR = 'SET "ROOT_DIR=tests/__data__/input" && SET "DATA_DIR=tests/__data__/input/data" &&'
|
||||
}
|
||||
|
||||
describe('playlist:test', () => {
|
||||
|
|
|
@ -24,7 +24,8 @@ describe('report:create', () => {
|
|||
│ 3 │ 14178 │ 'streams:add' │ 'TV3.my' │ 'https://live-streams-ssai-01.tonton.com.my/live/2dd2b7cd-1b34-4871-b669-57b5c9beca23/live.isml/.m3u8...' │ 'blocked' │
|
||||
│ 4 │ 16120 │ 'streams:remove' │ undefined │ 'http://190.61.102.67:2000/play/a038/index.m3u8' │ 'wrong_link' │
|
||||
│ 5 │ 19956 │ 'channel search' │ 'CNBCe.tr' │ undefined │ 'invalid_id' │
|
||||
│ 6 │ 20956 │ 'channel search' │ 'IONTV.us' │ undefined │ 'fulfilled' │
|
||||
│ 6 │ 19957 │ 'channel search' │ '13thStreet.au' │ undefined │ 'closed' │
|
||||
│ 7 │ 20956 │ 'channel search' │ 'IONTV.us' │ undefined │ 'fulfilled' │
|
||||
└─────────┴─────────────┴──────────────────┴─────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────┴───────────────┘`)
|
||||
).toBe(true)
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue