mirror of https://github.com/iptv-org/iptv
Merge pull request #25158 from iptv-org/patch-2025.07.2
Patch 2025.07.2
This commit is contained in:
commit
e8cf7f2482
|
@ -0,0 +1 @@
|
|||
* text eol=crlf
|
|
@ -2,3 +2,4 @@ _categories.md
|
|||
_countries.md
|
||||
_languages.md
|
||||
_regions.md
|
||||
_subdivisions.md
|
|
@ -1,31 +0,0 @@
|
|||
# Supported Categories
|
||||
|
||||
| Category | Definition |
|
||||
| ------------- | --------------------------------------------------------------------- |
|
||||
| Auto | Programming related to cars, motorcycles, and other automobiles |
|
||||
| Animation | Programming is mostly 2D or 3D animation |
|
||||
| Business | Programming related to business |
|
||||
| Classic | Programming is mostly from earlier decades |
|
||||
| Comedy | Programming is mostly comedy |
|
||||
| Cooking | Programs related to cooking or food in general |
|
||||
| Culture | Programming is mostly about art and culture |
|
||||
| Documentary | Programming that depicts a person or real-world event |
|
||||
| Education | Programming is intended to be educational |
|
||||
| Entertainment | Channels with a variety of entertainment programs |
|
||||
| Family | Programming that is be suitable for all members of a family |
|
||||
| General | Provides a variety of different programming |
|
||||
| Kids | Programming targeted to children |
|
||||
| Legislative | Programming specific to the operation of government |
|
||||
| Lifestyle | Programs related to health, fitness, leisure, fashion, decor, etc. |
|
||||
| Movies | Channels that only show movies |
|
||||
| Music | Programming is music or music related |
|
||||
| News | Programming is mostly news |
|
||||
| Outdoor | Programming related to outdoor activities like fishing, hunting, etc. |
|
||||
| Relax | Programming is calm sounding and beautiful views |
|
||||
| Religious | Religious programming |
|
||||
| Science | Science and Technology |
|
||||
| Series | Channels that only show series |
|
||||
| Shop | Programming is for shopping |
|
||||
| Sports | Programming is sports |
|
||||
| Travel | Programming is travel related |
|
||||
| Weather | Programming is focused on weather |
|
|
@ -36,7 +36,7 @@ https://iptv-org.github.io/iptv/index.m3u
|
|||
|
||||
### Grouped by category
|
||||
|
||||
Playlists in which channels are grouped by category. A list of all supported categories with descriptions can be found [here](.readme/supported-categories.md).
|
||||
Playlists in which channels are grouped by category.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
|
@ -91,6 +91,19 @@ Same thing, but split up into separate files:
|
|||
|
||||
</details>
|
||||
|
||||
### Grouped by subdivision
|
||||
|
||||
Playlists in which channels are grouped by subdivision for which they are broadcasted.
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
<br>
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
#include "./.readme/_subdivisions.md"
|
||||
|
||||
</details>
|
||||
|
||||
### Grouped by region
|
||||
|
||||
Playlists in which channels are grouped by the region for which they are broadcasted.
|
||||
|
|
|
@ -31,7 +31,7 @@ Note all links in playlists are sorted automatically by scripts so there is no n
|
|||
|
||||
### How to fix the stream description?
|
||||
|
||||
Most of the stream description (channel name, categories, languages, broadcast area, logo) we load from the [iptv-org/database](https://github.com/iptv-org/database) using the stream ID.
|
||||
Most of the stream description (channel name, feed name, categories, languages, broadcast area, logo) we load from the [iptv-org/database](https://github.com/iptv-org/database) using the stream ID.
|
||||
|
||||
So first of all, make sure that the desired stream has the correct ID. A full list of all supported channels and their corresponding IDs can be found on [iptv-org.github.io](https://iptv-org.github.io/). To change the stream ID of any link in the playlist, just fill out this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=streams%3Aedit&projects=&template=2_streams_edit.yml&title=Edit%3A+).
|
||||
|
||||
|
@ -110,14 +110,14 @@ Please note that we only accept removal requests from channel owners and their o
|
|||
For a stream to be approved, its description must follow this template:
|
||||
|
||||
```
|
||||
#EXTINF:-1 tvg-id="STREAM_ID",CHANNEL_NAME (QUALITY) [LABEL]
|
||||
#EXTINF:-1 tvg-id="STREAM_ID",STREAM_TITLE (QUALITY) [LABEL]
|
||||
STREAM_URL
|
||||
```
|
||||
|
||||
| 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 | - |
|
||||
| `STREAM_TITLE` | Stream title consisting of channel name and feed name. 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 | - |
|
||||
|
@ -125,7 +125,7 @@ STREAM_URL
|
|||
Example:
|
||||
|
||||
```xml
|
||||
#EXTINF:-1 tvg-id="ExampleTV.ua@HD",Example TV (720p) [Not 24/7]
|
||||
#EXTINF:-1 tvg-id="ExampleTV.us@East",Example TV East (720p) [Not 24/7]
|
||||
https://example.com/playlist.m3u8
|
||||
```
|
||||
|
||||
|
@ -165,7 +165,6 @@ http://example.com/stream.m3u8
|
|||
- `.readme/`
|
||||
- `config.json`: config for the `markdown-include` package, which is used to compile everything into one `README.md` file.
|
||||
- `preview.png`: image displayed in the `README.md`.
|
||||
- `supported-categories.md`: list of supported categories.
|
||||
- `template.md`: template for `README.md`.
|
||||
- `scripts/`: contains all scripts used in the repository.
|
||||
- `streams/`: contains all streams broken down by the country from which they are broadcast.
|
||||
|
|
|
@ -1,46 +1,54 @@
|
|||
import typescriptEslint from "@typescript-eslint/eslint-plugin";
|
||||
import globals from "globals";
|
||||
import tsParser from "@typescript-eslint/parser";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import js from "@eslint/js";
|
||||
import { FlatCompat } from "@eslint/eslintrc";
|
||||
import typescriptEslint from '@typescript-eslint/eslint-plugin'
|
||||
import globals from 'globals'
|
||||
import tsParser from '@typescript-eslint/parser'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import js from '@eslint/js'
|
||||
import { FlatCompat } from '@eslint/eslintrc'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
recommendedConfig: js.configs.recommended,
|
||||
allConfig: js.configs.all
|
||||
});
|
||||
baseDirectory: __dirname,
|
||||
recommendedConfig: js.configs.recommended,
|
||||
allConfig: js.configs.all
|
||||
})
|
||||
|
||||
export default [
|
||||
...compat.extends("eslint:recommended", "plugin:@typescript-eslint/recommended"),
|
||||
{
|
||||
plugins: {
|
||||
"@typescript-eslint": typescriptEslint,
|
||||
},
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
},
|
||||
|
||||
parser: tsParser,
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
},
|
||||
|
||||
rules: {
|
||||
"no-case-declarations": "off",
|
||||
|
||||
indent: ["error", 2, {
|
||||
SwitchCase: 1,
|
||||
}],
|
||||
|
||||
"linebreak-style": ["error", "unix"],
|
||||
quotes: ["error", "single"],
|
||||
semi: ["error", "never"],
|
||||
},
|
||||
...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/recommended'),
|
||||
{
|
||||
plugins: {
|
||||
'@typescript-eslint': typescriptEslint
|
||||
},
|
||||
];
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser
|
||||
},
|
||||
|
||||
parser: tsParser,
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module'
|
||||
},
|
||||
|
||||
rules: {
|
||||
'no-case-declarations': 'off',
|
||||
|
||||
indent: [
|
||||
'error',
|
||||
2,
|
||||
{
|
||||
SwitchCase: 1
|
||||
}
|
||||
],
|
||||
|
||||
'linebreak-style': ['error', 'windows'],
|
||||
quotes: ['error', 'single'],
|
||||
semi: ['error', 'never']
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
ignores: ['tests/__data__/**']
|
||||
}
|
||||
]
|
||||
|
|
|
@ -928,9 +928,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/config-array": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz",
|
||||
"integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==",
|
||||
"version": "0.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
|
||||
"integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
|
||||
"dependencies": {
|
||||
"@eslint/object-schema": "^2.1.6",
|
||||
"debug": "^4.3.1",
|
||||
|
@ -941,17 +941,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/config-helpers": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz",
|
||||
"integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==",
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz",
|
||||
"integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/core": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz",
|
||||
"integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==",
|
||||
"version": "0.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz",
|
||||
"integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.15"
|
||||
},
|
||||
|
@ -993,11 +993,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "9.25.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.25.1.tgz",
|
||||
"integrity": "sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==",
|
||||
"version": "9.32.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz",
|
||||
"integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://eslint.org/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/object-schema": {
|
||||
|
@ -1009,11 +1012,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/plugin-kit": {
|
||||
"version": "0.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz",
|
||||
"integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==",
|
||||
"version": "0.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz",
|
||||
"integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==",
|
||||
"dependencies": {
|
||||
"@eslint/core": "^0.13.0",
|
||||
"@eslint/core": "^0.15.1",
|
||||
"levn": "^0.4.1"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -2816,9 +2819,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
|
@ -3651,18 +3654,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "9.25.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.25.1.tgz",
|
||||
"integrity": "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==",
|
||||
"version": "9.32.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz",
|
||||
"integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
"@eslint/config-array": "^0.20.0",
|
||||
"@eslint/config-helpers": "^0.2.1",
|
||||
"@eslint/core": "^0.13.0",
|
||||
"@eslint/config-array": "^0.21.0",
|
||||
"@eslint/config-helpers": "^0.3.0",
|
||||
"@eslint/core": "^0.15.0",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "9.25.1",
|
||||
"@eslint/plugin-kit": "^0.2.8",
|
||||
"@eslint/js": "9.32.0",
|
||||
"@eslint/plugin-kit": "^0.3.4",
|
||||
"@humanfs/node": "^0.16.6",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@humanwhocodes/retry": "^0.4.2",
|
||||
|
@ -3673,9 +3676,9 @@
|
|||
"cross-spawn": "^7.0.6",
|
||||
"debug": "^4.3.2",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"eslint-scope": "^8.3.0",
|
||||
"eslint-visitor-keys": "^4.2.0",
|
||||
"espree": "^10.3.0",
|
||||
"eslint-scope": "^8.4.0",
|
||||
"eslint-visitor-keys": "^4.2.1",
|
||||
"espree": "^10.4.0",
|
||||
"esquery": "^1.5.0",
|
||||
"esutils": "^2.0.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
|
@ -3710,9 +3713,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint-scope": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
|
||||
"integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
|
||||
"version": "8.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
|
||||
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
|
||||
"dependencies": {
|
||||
"esrecurse": "^4.3.0",
|
||||
"estraverse": "^5.2.0"
|
||||
|
@ -3736,9 +3739,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/eslint-visitor-keys": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
|
||||
"integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
|
||||
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
|
@ -3747,13 +3750,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/espree": {
|
||||
"version": "10.3.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
|
||||
"integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
|
||||
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
|
||||
"dependencies": {
|
||||
"acorn": "^8.14.0",
|
||||
"acorn": "^8.15.0",
|
||||
"acorn-jsx": "^5.3.2",
|
||||
"eslint-visitor-keys": "^4.2.0"
|
||||
"eslint-visitor-keys": "^4.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
|
@ -3763,9 +3766,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/espree/node_modules/eslint-visitor-keys": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
|
||||
"integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
|
||||
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
|
@ -4047,13 +4050,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
||||
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
"format": "npm run playlist:format",
|
||||
"update": "npm run playlist:generate && npm run api:generate && npm run readme:update",
|
||||
"deploy": "npm run playlist:deploy && npm run api:deploy",
|
||||
"lint": "npx eslint ./scripts/**/*.ts ./tests/**/*.ts",
|
||||
"lint": "npx eslint \"scripts/**/*.{ts,js}\" \"tests/**/*.{ts,js}\"",
|
||||
"test": "jest --runInBand",
|
||||
"postinstall": "npm run api:load"
|
||||
},
|
||||
|
|
|
@ -73,7 +73,7 @@ export default async function main(filepath: string) {
|
|||
logger.info('creating search index...')
|
||||
const items = channels.map((channel: Channel) => channel.getSearchable()).all()
|
||||
const searchIndex = sjs.createIndex(items, {
|
||||
searchable: ['name', 'altNames', 'guideNames', 'streamNames', 'feedFullNames']
|
||||
searchable: ['name', 'altNames', 'guideNames', 'streamTitles', 'feedFullNames']
|
||||
})
|
||||
|
||||
logger.info('starting...\n')
|
||||
|
@ -100,7 +100,7 @@ async function selectChannel(
|
|||
feedsGroupedByChannelId: Dictionary,
|
||||
channelsKeyById: Dictionary
|
||||
): Promise<string> {
|
||||
const query = escapeRegex(stream.getName())
|
||||
const query = escapeRegex(stream.getTitle())
|
||||
const similarChannels = searchIndex
|
||||
.search(query)
|
||||
.map((item: ChannelSearchableData) => channelsKeyById.get(item.id))
|
||||
|
@ -108,7 +108,7 @@ async function selectChannel(
|
|||
const url = stream.url.length > 50 ? stream.url.slice(0, 50) + '...' : stream.url
|
||||
|
||||
const selected: ChoiceValue = await select({
|
||||
message: `Select channel ID for "${stream.name}" (${url}):`,
|
||||
message: `Select channel ID for "${stream.title}" (${url}):`,
|
||||
choices: getChannelChoises(new Collection(similarChannels)),
|
||||
pageSize: 10
|
||||
})
|
||||
|
@ -136,7 +136,7 @@ async function selectChannel(
|
|||
}
|
||||
|
||||
async function selectFeed(channelId: string, feedsGroupedByChannelId: Dictionary): Promise<string> {
|
||||
const channelFeeds = new Collection(feedsGroupedByChannelId.get(channelId)) || new Collection()
|
||||
const channelFeeds = new Collection(feedsGroupedByChannelId.get(channelId))
|
||||
const choices = getFeedChoises(channelFeeds)
|
||||
|
||||
const selected: ChoiceValue = await select({
|
||||
|
|
|
@ -53,7 +53,7 @@ async function main() {
|
|||
logger.info('sorting links...')
|
||||
streams = streams.orderBy(
|
||||
[
|
||||
(stream: Stream) => stream.name,
|
||||
(stream: Stream) => stream.title,
|
||||
(stream: Stream) => stream.getVerticalResolution(),
|
||||
(stream: Stream) => stream.getLabel(),
|
||||
(stream: Stream) => stream.url
|
||||
|
@ -63,7 +63,7 @@ async function main() {
|
|||
|
||||
logger.info('saving...')
|
||||
const groupedStreams = streams.groupBy((stream: Stream) => stream.getFilepath())
|
||||
for (let filepath of groupedStreams.keys()) {
|
||||
for (const filepath of groupedStreams.keys()) {
|
||||
const streams = groupedStreams.get(filepath) || []
|
||||
|
||||
if (!streams.length) return
|
||||
|
|
|
@ -9,13 +9,14 @@ import {
|
|||
IndexCategoryGenerator,
|
||||
IndexLanguageGenerator,
|
||||
IndexCountryGenerator,
|
||||
SubdivisionsGenerator,
|
||||
IndexRegionGenerator,
|
||||
CategoriesGenerator,
|
||||
CountriesGenerator,
|
||||
LanguagesGenerator,
|
||||
RegionsGenerator,
|
||||
IndexGenerator,
|
||||
SourcesGenerator,
|
||||
IndexGenerator,
|
||||
RawGenerator
|
||||
} from '../../generators'
|
||||
|
||||
|
@ -32,6 +33,7 @@ async function main() {
|
|||
feedsGroupedByChannelId,
|
||||
logosGroupedByStreamId,
|
||||
channelsKeyById,
|
||||
subdivisions,
|
||||
categories,
|
||||
countries,
|
||||
regions
|
||||
|
@ -71,6 +73,9 @@ async function main() {
|
|||
logger.info('generating categories/...')
|
||||
await new CategoriesGenerator({ categories, streams, logFile }).generate()
|
||||
|
||||
logger.info('generating languages/...')
|
||||
await new LanguagesGenerator({ streams, logFile }).generate()
|
||||
|
||||
logger.info('generating countries/...')
|
||||
await new CountriesGenerator({
|
||||
countries,
|
||||
|
@ -78,8 +83,12 @@ async function main() {
|
|||
logFile
|
||||
}).generate()
|
||||
|
||||
logger.info('generating languages/...')
|
||||
await new LanguagesGenerator({ streams, logFile }).generate()
|
||||
logger.info('generating subdivisions/...')
|
||||
await new SubdivisionsGenerator({
|
||||
subdivisions,
|
||||
streams,
|
||||
logFile
|
||||
}).generate()
|
||||
|
||||
logger.info('generating regions/...')
|
||||
await new RegionsGenerator({
|
||||
|
|
|
@ -18,7 +18,7 @@ const LIVE_UPDATE_MAX_STREAMS = 100
|
|||
|
||||
let errors = 0
|
||||
let warnings = 0
|
||||
let results = {}
|
||||
const results = {}
|
||||
let interval
|
||||
let streams = new Collection()
|
||||
let isLiveUpdateEnabled = true
|
||||
|
|
|
@ -4,9 +4,9 @@ import type { DataProcessorData } from '../../types/dataProcessor'
|
|||
import { Stream, Playlist, Channel, Issue } from '../../models'
|
||||
import type { DataLoaderData } from '../../types/dataLoader'
|
||||
import { DATA_DIR, STREAMS_DIR } from '../../constants'
|
||||
import validUrl from 'valid-url'
|
||||
import { isURI } from '../../utils'
|
||||
|
||||
let processedIssues = new Collection()
|
||||
const processedIssues = new Collection()
|
||||
|
||||
async function main() {
|
||||
const logger = new Logger({ level: -999 })
|
||||
|
@ -55,7 +55,7 @@ async function main() {
|
|||
|
||||
logger.info('saving...')
|
||||
const groupedStreams = streams.groupBy((stream: Stream) => stream.getFilepath())
|
||||
for (let filepath of groupedStreams.keys()) {
|
||||
for (const filepath of groupedStreams.keys()) {
|
||||
let streams = groupedStreams.get(filepath) || []
|
||||
streams = streams.filter((stream: Stream) => stream.removed === false)
|
||||
|
||||
|
@ -114,7 +114,7 @@ async function editStreams({
|
|||
|
||||
if (data.missing('streamUrl')) return
|
||||
|
||||
let stream: Stream = streams.first(
|
||||
const stream: Stream = streams.first(
|
||||
(_stream: Stream) => _stream.url === data.getString('streamUrl')
|
||||
)
|
||||
if (!stream) return
|
||||
|
@ -129,7 +129,7 @@ async function editStreams({
|
|||
.withChannel(channelsKeyById)
|
||||
.withFeed(feedsGroupedByChannelId)
|
||||
.updateId()
|
||||
.updateName()
|
||||
.updateTitle()
|
||||
.updateFilepath()
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ async function addStreams({
|
|||
if (data.missing('streamId') || data.missing('streamUrl')) return
|
||||
if (streams.includes((_stream: Stream) => _stream.url === data.getString('streamUrl'))) return
|
||||
const streamUrl = data.getString('streamUrl') || ''
|
||||
if (!isUri(streamUrl)) return
|
||||
if (!isURI(streamUrl)) return
|
||||
|
||||
const streamId = data.getString('streamId') || ''
|
||||
const [channelId, feedId] = streamId.split('@')
|
||||
|
@ -173,11 +173,11 @@ async function addStreams({
|
|||
const directives = data.getArray('directives') || []
|
||||
|
||||
const stream = new Stream({
|
||||
channel: channelId,
|
||||
feed: feedId,
|
||||
name: data.getString('channelName') || channel.name,
|
||||
channelId,
|
||||
feedId,
|
||||
title: channel.name,
|
||||
url: streamUrl,
|
||||
user_agent: httpUserAgent,
|
||||
userAgent: httpUserAgent,
|
||||
referrer: httpReferrer,
|
||||
directives,
|
||||
quality,
|
||||
|
@ -185,14 +185,10 @@ async function addStreams({
|
|||
})
|
||||
.withChannel(channelsKeyById)
|
||||
.withFeed(feedsGroupedByChannelId)
|
||||
.updateName()
|
||||
.updateTitle()
|
||||
.updateFilepath()
|
||||
|
||||
streams.add(stream)
|
||||
processedIssues.add(issue.number)
|
||||
})
|
||||
}
|
||||
|
||||
function isUri(string: string) {
|
||||
return validUrl.isUri(encodeURI(string))
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ async function main() {
|
|||
|
||||
let errors = new Collection()
|
||||
let warnings = new Collection()
|
||||
let streamsGroupedByFilepath = streams.groupBy((stream: Stream) => stream.getFilepath())
|
||||
const streamsGroupedByFilepath = streams.groupBy((stream: Stream) => stream.getFilepath())
|
||||
for (const filepath of streamsGroupedByFilepath.keys()) {
|
||||
const streams = streamsGroupedByFilepath.get(filepath)
|
||||
if (!streams) continue
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
import { Logger } from '@freearhey/core'
|
||||
import { CategoryTable, CountryTable, LanguageTable, RegionTable } from '../../tables'
|
||||
import {
|
||||
CategoryTable,
|
||||
CountryTable,
|
||||
LanguageTable,
|
||||
RegionTable,
|
||||
SubdivisionTable
|
||||
} from '../../tables'
|
||||
import { Markdown } from '../../core'
|
||||
import { README_DIR } from '../../constants'
|
||||
import path from 'path'
|
||||
|
@ -9,10 +15,12 @@ async function main() {
|
|||
|
||||
logger.info('creating category table...')
|
||||
await new CategoryTable().make()
|
||||
logger.info('creating country table...')
|
||||
await new CountryTable().make()
|
||||
logger.info('creating language table...')
|
||||
await new LanguageTable().make()
|
||||
logger.info('creating country table...')
|
||||
await new CountryTable().make()
|
||||
logger.info('creating subdivision table...')
|
||||
await new SubdivisionTable().make()
|
||||
logger.info('creating region table...')
|
||||
await new RegionTable().make()
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import { DataProcessorData } from '../../types/dataProcessor'
|
|||
import { DATA_DIR, STREAMS_DIR } from '../../constants'
|
||||
import { DataLoaderData } from '../../types/dataLoader'
|
||||
import { Issue, Stream } from '../../models'
|
||||
import { isURI } from '../../utils'
|
||||
|
||||
async function main() {
|
||||
const logger = new Logger()
|
||||
|
@ -44,7 +45,7 @@ async function main() {
|
|||
issue.labels.find((label: string) => label === 'streams:remove')
|
||||
)
|
||||
removeRequests.forEach((issue: Issue) => {
|
||||
const streamUrls = issue.data.has('streamUrl') ? issue.data.getArray('streamUrl') : []
|
||||
const streamUrls = issue.data.getArray('streamUrl') || []
|
||||
|
||||
if (!streamUrls.length) {
|
||||
const result = {
|
||||
|
@ -93,6 +94,7 @@ async function main() {
|
|||
|
||||
if (!channelId) result.status = 'missing_id'
|
||||
else if (!streamUrl) result.status = 'missing_link'
|
||||
else if (!isURI(streamUrl)) result.status = 'invalid_link'
|
||||
else if (blocklistRecordsGroupedByChannelId.has(channelId)) result.status = 'blocked'
|
||||
else if (channelsKeyById.missing(channelId)) result.status = 'wrong_id'
|
||||
else if (streamsGroupedByUrl.has(streamUrl)) result.status = 'on_playlist'
|
||||
|
|
|
@ -25,7 +25,7 @@ export class DataProcessor {
|
|||
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))
|
||||
let subdivisions = new Collection(data.subdivisions).map(data => new Subdivision(data))
|
||||
const subdivisionsKeyByCode = subdivisions.keyBy((subdivision: Subdivision) => subdivision.code)
|
||||
const subdivisionsGroupedByCountryCode = subdivisions.groupBy(
|
||||
(subdivision: Subdivision) => subdivision.countryCode
|
||||
|
@ -42,6 +42,10 @@ export class DataProcessor {
|
|||
)
|
||||
const countriesKeyByCode = countries.keyBy((country: Country) => country.code)
|
||||
|
||||
subdivisions = subdivisions.map((subdivision: Subdivision) =>
|
||||
subdivision.withCountry(countriesKeyByCode)
|
||||
)
|
||||
|
||||
const timezones = new Collection(data.timezones).map(data =>
|
||||
new Timezone(data).withCountries(countriesKeyByCode)
|
||||
)
|
||||
|
@ -74,7 +78,7 @@ export class DataProcessor {
|
|||
const feedsGroupedByChannelId = feeds.groupBy((feed: Feed) => feed.channelId)
|
||||
const feedsGroupedById = feeds.groupBy((feed: Feed) => feed.id)
|
||||
|
||||
let logos = new Collection(data.logos).map(data => new Logo(data).withFeed(feedsGroupedById))
|
||||
const 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())
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ export class IssueLoader {
|
|||
repo: REPO,
|
||||
per_page: 100,
|
||||
labels,
|
||||
status: 'open',
|
||||
headers: {
|
||||
'X-GitHub-Api-Version': '2022-11-28'
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ const FIELDS = new Dictionary({
|
|||
'New Stream URL': 'newStreamUrl',
|
||||
Label: 'label',
|
||||
Quality: 'quality',
|
||||
'Channel Name': 'channelName',
|
||||
'HTTP User-Agent': 'httpUserAgent',
|
||||
'HTTP User Agent': 'httpUserAgent',
|
||||
'HTTP Referrer': 'httpReferrer',
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Country, Subdivision, Stream, Playlist } from '../models'
|
||||
import { Country, Stream, Playlist } from '../models'
|
||||
import { Collection, Storage, File } from '@freearhey/core'
|
||||
import { PUBLIC_DIR } from '../constants'
|
||||
import { Generator } from './generator'
|
||||
|
@ -40,21 +40,6 @@ export class CountriesGenerator implements Generator {
|
|||
this.logFile.append(
|
||||
JSON.stringify({ type: 'country', filepath, count: playlist.streams.count() }) + EOL
|
||||
)
|
||||
|
||||
country.getSubdivisions().forEach(async (subdivision: Subdivision) => {
|
||||
const subdivisionStreams = streams.filter((stream: Stream) =>
|
||||
stream.isBroadcastInSubdivision(subdivision)
|
||||
)
|
||||
|
||||
if (subdivisionStreams.isEmpty()) return
|
||||
|
||||
const playlist = new Playlist(subdivisionStreams, { public: true })
|
||||
const filepath = `subdivisions/${subdivision.code.toLowerCase()}.m3u`
|
||||
await this.storage.save(filepath, playlist.toString())
|
||||
this.logFile.append(
|
||||
JSON.stringify({ type: 'subdivision', filepath, count: playlist.streams.count() }) + EOL
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
const undefinedStreams = streams.filter((stream: Stream) => !stream.hasBroadcastArea())
|
||||
|
|
|
@ -10,3 +10,4 @@ export * from './languagesGenerator'
|
|||
export * from './rawGenerator'
|
||||
export * from './regionsGenerator'
|
||||
export * from './sourcesGenerator'
|
||||
export * from './subdivisionsGenerator'
|
||||
|
|
|
@ -23,7 +23,7 @@ export class RawGenerator implements Generator {
|
|||
async generate() {
|
||||
const files = this.streams.groupBy((stream: Stream) => stream.getFilename())
|
||||
|
||||
for (let filename of files.keys()) {
|
||||
for (const filename of files.keys()) {
|
||||
const streams = new Collection(files.get(filename)).map((stream: Stream) => {
|
||||
const groupTitle = stream.getCategoryNames().join(';')
|
||||
if (groupTitle) stream.groupTitle = groupTitle
|
||||
|
|
|
@ -23,7 +23,7 @@ export class SourcesGenerator implements Generator {
|
|||
async generate() {
|
||||
const files: Dictionary = this.streams.groupBy((stream: Stream) => stream.getFilename())
|
||||
|
||||
for (let filename of files.keys()) {
|
||||
for (const filename of files.keys()) {
|
||||
if (!filename) continue
|
||||
|
||||
let streams = new Collection(files.get(filename))
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
import { Subdivision, Stream, Playlist } from '../models'
|
||||
import { Collection, Storage, File } from '@freearhey/core'
|
||||
import { PUBLIC_DIR } from '../constants'
|
||||
import { Generator } from './generator'
|
||||
import { EOL } from 'node:os'
|
||||
|
||||
type SubdivisionsGeneratorProps = {
|
||||
streams: Collection
|
||||
subdivisions: Collection
|
||||
logFile: File
|
||||
}
|
||||
|
||||
export class SubdivisionsGenerator implements Generator {
|
||||
streams: Collection
|
||||
subdivisions: Collection
|
||||
storage: Storage
|
||||
logFile: File
|
||||
|
||||
constructor({ streams, subdivisions, logFile }: SubdivisionsGeneratorProps) {
|
||||
this.streams = streams.clone()
|
||||
this.subdivisions = subdivisions
|
||||
this.storage = new Storage(PUBLIC_DIR)
|
||||
this.logFile = logFile
|
||||
}
|
||||
|
||||
async generate(): Promise<void> {
|
||||
const streams = this.streams
|
||||
.orderBy((stream: Stream) => stream.getTitle())
|
||||
.filter((stream: Stream) => stream.isSFW())
|
||||
|
||||
this.subdivisions.forEach(async (subdivision: Subdivision) => {
|
||||
const subdivisionStreams = streams.filter((stream: Stream) =>
|
||||
stream.isBroadcastInSubdivision(subdivision)
|
||||
)
|
||||
|
||||
if (subdivisionStreams.isEmpty()) return
|
||||
|
||||
const playlist = new Playlist(subdivisionStreams, { public: true })
|
||||
const filepath = `subdivisions/${subdivision.code.toLowerCase()}.m3u`
|
||||
await this.storage.save(filepath, playlist.toString())
|
||||
this.logFile.append(
|
||||
JSON.stringify({ type: 'subdivision', filepath, count: playlist.streams.count() }) + EOL
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -133,9 +133,9 @@ export class Channel {
|
|||
return streams
|
||||
}
|
||||
|
||||
getStreamNames(): Collection {
|
||||
getStreamTitles(): Collection {
|
||||
return this.getStreams()
|
||||
.map((stream: Stream) => stream.getName())
|
||||
.map((stream: Stream) => stream.getTitle())
|
||||
.uniq()
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ export class Channel {
|
|||
name: this.name,
|
||||
altNames: this.altNames.all(),
|
||||
guideNames: this.getGuideNames().all(),
|
||||
streamNames: this.getStreamNames().all(),
|
||||
streamTitles: this.getStreamTitles().all(),
|
||||
feedFullNames: this.getFeedFullNames().all()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,8 +190,15 @@ export class Feed {
|
|||
|
||||
isBroadcastInSubdivision(subdivision: Subdivision): boolean {
|
||||
if (this.isInternational()) return false
|
||||
if (this.broadcastSubdivisionCodes.includes(subdivision.code)) return true
|
||||
if (
|
||||
this.broadcastSubdivisionCodes.isEmpty() &&
|
||||
subdivision.country &&
|
||||
this.isBroadcastInCountry(subdivision.country)
|
||||
)
|
||||
return true
|
||||
|
||||
return this.broadcastSubdivisionCodes.includes(subdivision.code)
|
||||
return false
|
||||
}
|
||||
|
||||
isBroadcastInCountry(country: Country): boolean {
|
||||
|
|
|
@ -6,7 +6,7 @@ import { IssueData } from '../core'
|
|||
import path from 'node:path'
|
||||
|
||||
export class Stream {
|
||||
name?: string
|
||||
title: string
|
||||
url: string
|
||||
id?: string
|
||||
channelId?: string
|
||||
|
@ -28,16 +28,17 @@ export class Stream {
|
|||
constructor(data?: StreamData) {
|
||||
if (!data) return
|
||||
|
||||
const id = data.channel && data.feed ? [data.channel, data.feed].join('@') : data.channel
|
||||
const id =
|
||||
data.channelId && data.feedId ? [data.channelId, data.feedId].join('@') : data.channelId
|
||||
const { verticalResolution, isInterlaced } = parseQuality(data.quality)
|
||||
|
||||
this.id = id || undefined
|
||||
this.channelId = data.channel || undefined
|
||||
this.feedId = data.feed || undefined
|
||||
this.name = data.name || undefined
|
||||
this.channelId = data.channelId || undefined
|
||||
this.feedId = data.feedId || undefined
|
||||
this.title = data.title || ''
|
||||
this.url = data.url
|
||||
this.referrer = data.referrer || undefined
|
||||
this.userAgent = data.user_agent || undefined
|
||||
this.userAgent = data.userAgent || undefined
|
||||
this.verticalResolution = verticalResolution || undefined
|
||||
this.isInterlaced = isInterlaced || undefined
|
||||
this.label = data.label || undefined
|
||||
|
@ -65,21 +66,22 @@ export class Stream {
|
|||
}
|
||||
|
||||
fromPlaylistItem(data: parser.PlaylistItem): this {
|
||||
function parseTitle(title: string): {
|
||||
name: string
|
||||
function parseName(name: string): {
|
||||
title: string
|
||||
label: string
|
||||
quality: string
|
||||
} {
|
||||
let title = name
|
||||
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 }
|
||||
return { title, label, quality }
|
||||
}
|
||||
|
||||
function parseDirectives(string: string) {
|
||||
let directives = new Collection()
|
||||
const directives = new Collection()
|
||||
|
||||
if (!string) return directives
|
||||
|
||||
|
@ -100,7 +102,7 @@ export class Stream {
|
|||
if (!data.url) throw new Error('"url" property is required')
|
||||
|
||||
const [channelId, feedId] = data.tvg.id.split('@')
|
||||
const { name, label, quality } = parseTitle(data.name)
|
||||
const { title, label, quality } = parseName(data.name)
|
||||
const { verticalResolution, isInterlaced } = parseQuality(quality)
|
||||
|
||||
this.id = data.tvg.id || undefined
|
||||
|
@ -108,7 +110,7 @@ export class Stream {
|
|||
this.channelId = channelId || undefined
|
||||
this.line = data.line
|
||||
this.label = label || undefined
|
||||
this.name = name
|
||||
this.title = title
|
||||
this.verticalResolution = verticalResolution || undefined
|
||||
this.isInterlaced = isInterlaced || undefined
|
||||
this.url = data.url
|
||||
|
@ -241,12 +243,12 @@ export class Stream {
|
|||
return parseInt(this.getQuality().replace(/p|i/, ''))
|
||||
}
|
||||
|
||||
updateName(): this {
|
||||
updateTitle(): this {
|
||||
if (!this.channel) return this
|
||||
|
||||
this.name = this.channel.name
|
||||
this.title = this.channel.name
|
||||
if (this.feed && !this.feed.isMain) {
|
||||
this.name += ` ${this.feed.name}`
|
||||
this.title += ` ${this.feed.name}`
|
||||
}
|
||||
|
||||
return this
|
||||
|
@ -375,12 +377,12 @@ export class Stream {
|
|||
return logo ? logo.url : ''
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
return this.name || ''
|
||||
getTitle(): string {
|
||||
return this.title || ''
|
||||
}
|
||||
|
||||
getTitle(): string {
|
||||
let title = `${this.getName()}`
|
||||
getFullTitle(): string {
|
||||
let title = `${this.getTitle()}`
|
||||
|
||||
if (this.getQuality()) {
|
||||
title += ` (${this.getQuality()})`
|
||||
|
@ -405,6 +407,7 @@ export class Stream {
|
|||
return {
|
||||
channel: this.channelId || null,
|
||||
feed: this.feedId || null,
|
||||
title: this.title,
|
||||
url: this.url,
|
||||
referrer: this.referrer || null,
|
||||
user_agent: this.userAgent || null,
|
||||
|
@ -427,7 +430,7 @@ export class Stream {
|
|||
output += ` http-user-agent="${this.userAgent}"`
|
||||
}
|
||||
|
||||
output += `,${this.getTitle()}`
|
||||
output += `,${this.getFullTitle()}`
|
||||
|
||||
this.directives.forEach((prop: string) => {
|
||||
output += `\r\n${prop}`
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Storage, Collection, File } from '@freearhey/core'
|
||||
import { HTMLTable, LogParser, LogItem } from '../core'
|
||||
import { Country, Subdivision } from '../models'
|
||||
import { Country } from '../models'
|
||||
import { DATA_DIR, LOGS_DIR, README_DIR } from '../constants'
|
||||
import { Table } from './table'
|
||||
|
||||
|
@ -13,11 +13,6 @@ export class CountryTable implements Table {
|
|||
const countriesContent = await dataStorage.json('countries.json')
|
||||
const countries = new Collection(countriesContent).map(data => new Country(data))
|
||||
const countriesGroupedByCode = countries.keyBy((country: Country) => country.code)
|
||||
const subdivisionsContent = await dataStorage.json('subdivisions.json')
|
||||
const subdivisions = new Collection(subdivisionsContent).map(data => new Subdivision(data))
|
||||
const subdivisionsGroupedByCode = subdivisions.keyBy(
|
||||
(subdivision: Subdivision) => subdivision.code
|
||||
)
|
||||
|
||||
const parser = new LogParser()
|
||||
const logsStorage = new Storage(LOGS_DIR)
|
||||
|
@ -26,27 +21,6 @@ export class CountryTable implements Table {
|
|||
|
||||
let data = new Collection()
|
||||
|
||||
parsed
|
||||
.filter((logItem: LogItem) => logItem.type === 'subdivision')
|
||||
.forEach((logItem: LogItem) => {
|
||||
const file = new File(logItem.filepath)
|
||||
const code = file.name().toUpperCase()
|
||||
const [countryCode, subdivisionCode] = code.split('-') || ['', '']
|
||||
const country = countriesGroupedByCode.get(countryCode)
|
||||
|
||||
if (country && subdivisionCode) {
|
||||
const subdivision = subdivisionsGroupedByCode.get(code)
|
||||
if (subdivision) {
|
||||
data.add([
|
||||
`${country.name}/${subdivision.name}`,
|
||||
` ${subdivision.name}`,
|
||||
logItem.count,
|
||||
`<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>`
|
||||
])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
parsed
|
||||
.filter((logItem: LogItem) => logItem.type === 'country')
|
||||
.forEach((logItem: LogItem) => {
|
||||
|
|
|
@ -2,3 +2,4 @@ export * from './categoryTable'
|
|||
export * from './countryTable'
|
||||
export * from './languageTable'
|
||||
export * from './regionTable'
|
||||
export * from './subdivisionTable'
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
import { Storage, Collection, File } from '@freearhey/core'
|
||||
import { HTMLTable, LogParser, LogItem } from '../core'
|
||||
import { Country, Subdivision } from '../models'
|
||||
import { DATA_DIR, LOGS_DIR, README_DIR } from '../constants'
|
||||
import { Table } from './table'
|
||||
|
||||
export class SubdivisionTable implements Table {
|
||||
constructor() {}
|
||||
|
||||
async make() {
|
||||
const dataStorage = new Storage(DATA_DIR)
|
||||
|
||||
const countriesContent = await dataStorage.json('countries.json')
|
||||
const countries = new Collection(countriesContent).map(data => new Country(data))
|
||||
const countriesGroupedByCode = countries.keyBy((country: Country) => country.code)
|
||||
const subdivisionsContent = await dataStorage.json('subdivisions.json')
|
||||
const subdivisions = new Collection(subdivisionsContent).map(data => new Subdivision(data))
|
||||
const subdivisionsGroupedByCode = subdivisions.keyBy(
|
||||
(subdivision: Subdivision) => subdivision.code
|
||||
)
|
||||
|
||||
const parser = new LogParser()
|
||||
const logsStorage = new Storage(LOGS_DIR)
|
||||
const generatorsLog = await logsStorage.load('generators.log')
|
||||
const parsed = parser.parse(generatorsLog)
|
||||
const parsedSubdivisions = parsed.filter((logItem: LogItem) => logItem.type === 'subdivision')
|
||||
|
||||
let output = ''
|
||||
countries.forEach((country: Country) => {
|
||||
const parsedCountrySubdivisions = parsedSubdivisions.filter((logItem: LogItem) =>
|
||||
logItem.filepath.includes(`subdivisions/${country.code.toLowerCase()}`)
|
||||
)
|
||||
|
||||
if (!parsedCountrySubdivisions.length) return
|
||||
|
||||
output += `\r\n<details>\r\n<summary>${country.name}</summary>\r\n`
|
||||
|
||||
const data = new Collection()
|
||||
|
||||
parsedCountrySubdivisions.forEach((logItem: LogItem) => {
|
||||
const file = new File(logItem.filepath)
|
||||
const code = file.name().toUpperCase()
|
||||
const [countryCode, subdivisionCode] = code.split('-') || ['', '']
|
||||
const country = countriesGroupedByCode.get(countryCode)
|
||||
|
||||
if (country && subdivisionCode) {
|
||||
const subdivision = subdivisionsGroupedByCode.get(code)
|
||||
if (subdivision) {
|
||||
data.add([
|
||||
subdivision.name,
|
||||
logItem.count,
|
||||
`<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>`
|
||||
])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const table = new HTMLTable(data.all(), [
|
||||
{ name: 'Subdivision' },
|
||||
{ name: 'Channels', align: 'right' },
|
||||
{ name: 'Playlist', nowrap: true }
|
||||
])
|
||||
|
||||
output += table.toString()
|
||||
|
||||
output += '\r\n</details>'
|
||||
})
|
||||
|
||||
const readmeStorage = new Storage(README_DIR)
|
||||
await readmeStorage.save('_subdivisions.md', output.trim())
|
||||
}
|
||||
}
|
|
@ -45,6 +45,6 @@ export type ChannelSearchableData = {
|
|||
name: string
|
||||
altNames: string[]
|
||||
guideNames: string[]
|
||||
streamNames: string[]
|
||||
streamTitles: string[]
|
||||
feedFullNames: string[]
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
export type StreamData = {
|
||||
channel: string | null
|
||||
feed: string | null
|
||||
name: string | null
|
||||
channelId: string | null
|
||||
feedId: string | null
|
||||
title: string | null
|
||||
url: string
|
||||
referrer: string | null
|
||||
user_agent: string | null
|
||||
userAgent: string | null
|
||||
quality: string | null
|
||||
label: string | null
|
||||
directives: string[]
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
import validUrl from 'valid-url'
|
||||
|
||||
export function isURI(string: string) {
|
||||
return validUrl.isUri(encodeURI(string))
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
{
|
||||
"channel": null,
|
||||
"feed": null,
|
||||
"title": "Daawah TV",
|
||||
"url": "http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8",
|
||||
"referrer": null,
|
||||
"user_agent": null
|
||||
|
@ -9,6 +10,7 @@
|
|||
{
|
||||
"channel": null,
|
||||
"feed": null,
|
||||
"title": "Andorra TV",
|
||||
"url": "http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8",
|
||||
"referrer": "http://imn.iq",
|
||||
"user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148"
|
||||
|
@ -16,12 +18,15 @@
|
|||
{
|
||||
"channel": "AndorraTV.ad",
|
||||
"feed": "SD",
|
||||
"title": "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
|
||||
},
|
||||
{
|
||||
"channel": "BBCNews.uk",
|
||||
"feed": null,
|
||||
"title": "BBC News HD",
|
||||
"url": "http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8",
|
||||
"referrer": null,
|
||||
"user_agent": null
|
||||
|
@ -29,6 +34,7 @@
|
|||
{
|
||||
"channel": "LDPRTV.ru",
|
||||
"feed": null,
|
||||
"title": "ЛДПР ТВ",
|
||||
"url": "http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8",
|
||||
"referrer": null,
|
||||
"user_agent": null
|
||||
|
@ -36,6 +42,7 @@
|
|||
{
|
||||
"channel": "MeteoMedia.ca",
|
||||
"feed": null,
|
||||
"title": "Meteomedia",
|
||||
"url": "http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8",
|
||||
"referrer": null,
|
||||
"user_agent": null
|
||||
|
@ -43,6 +50,7 @@
|
|||
{
|
||||
"channel": "VisitXTV.nl",
|
||||
"feed": null,
|
||||
"title": "Visit-X TV",
|
||||
"url": "https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8",
|
||||
"referrer": null,
|
||||
"user_agent": null
|
||||
|
@ -50,6 +58,7 @@
|
|||
{
|
||||
"channel": "Zoo.ad",
|
||||
"feed": null,
|
||||
"title": "Zoo",
|
||||
"url": "https://iptv-all.lanesh4d0w.repl.co/andorra/zoo",
|
||||
"referrer": null,
|
||||
"user_agent": null
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/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
|
||||
|
@ -15,5 +17,5 @@ https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
|||
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
||||
#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="Zoo.ad@HD" tvg-logo="" group-title="Undefined",Zoo (720p)
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8
|
||||
#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
|
||||
|
|
|
@ -11,5 +11,5 @@ http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://refe
|
|||
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
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="" group-title="Undefined",Zoo (720p)
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
||||
|
|
|
@ -9,6 +9,8 @@ http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8
|
|||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8
|
||||
#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
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/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
|
||||
|
@ -25,5 +27,5 @@ https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd
|
|||
http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
||||
#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="Zoo.ad@HD" tvg-logo="" group-title="Undefined",Zoo (720p)
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#EXTM3U
|
||||
#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="5AABTV.ca" tvg-logo="" group-title="Canada",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8
|
||||
#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
|
||||
#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="Kazakhstan",ЭлТР (480p) [Not 24/7]
|
||||
|
@ -31,5 +33,5 @@ http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://refe
|
|||
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
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="" group-title="Undefined",Zoo (720p)
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
||||
|
|
|
@ -5,6 +5,8 @@ https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
|||
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8
|
||||
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Russian",ЛДПР ТВ (1080p)
|
||||
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/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
|
||||
|
@ -21,7 +23,7 @@ http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
|||
http://146.59.85.40:89/dunaworld/index.m3u8
|
||||
#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Undefined",Meteomedia
|
||||
http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="" group-title="Undefined",Zoo (720p)
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
||||
#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="Undefined",ЭлТР (480p) [Not 24/7]
|
||||
http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/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
|
||||
|
@ -19,7 +21,7 @@ http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
|||
http://146.59.85.40:89/dunaworld/index.m3u8
|
||||
#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
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="" group-title="Undefined",Zoo (720p)
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
||||
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p)
|
||||
http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Americas",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8
|
||||
#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Americas",Meteomedia
|
||||
http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
|
||||
#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Asia",ЛДПР ТВ (1080p)
|
||||
|
@ -23,8 +25,12 @@ https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
|||
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, the Middle East and Africa",ЭлТР (480p) [Not 24/7]
|
||||
http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="North America",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8
|
||||
#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="North America",Meteomedia
|
||||
http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Northern America",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8
|
||||
#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Northern America",Meteomedia
|
||||
http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
|
||||
#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="International",BBC News HD
|
||||
|
@ -43,5 +49,5 @@ http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://refe
|
|||
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
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="" group-title="Undefined",Zoo (720p)
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/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
|
||||
|
@ -15,7 +17,7 @@ http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
|
|||
http://146.59.85.40:89/dunaworld/index.m3u8
|
||||
#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
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="" group-title="Undefined",Zoo (720p)
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
||||
#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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="" group-title="Undefined",Zoo (720p)
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" 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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8
|
||||
#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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8
|
||||
#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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8
|
||||
#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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8
|
||||
#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
|
||||
|
|
|
@ -11,5 +11,5 @@ http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://refe
|
|||
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
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="" group-title="Undefined",Zoo (720p)
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
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)
|
||||
#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p)
|
||||
https://iptv-all.lanesh4d0w.repl.co/andorra/zoo
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8
|
||||
#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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8
|
||||
#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
|
||||
|
|
|
@ -1,88 +1,238 @@
|
|||
{"type":"raw","filepath":"raw/ad.m3u","count":4}
|
||||
{"type":"raw","filepath":"raw/ca.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/ca.m3u","count":2}
|
||||
{"type":"raw","filepath":"raw/in.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/kg.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/uk.m3u","count":1}
|
||||
{"type":"raw","filepath":"raw/unsorted.m3u","count":4}
|
||||
{"type":"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}
|
||||
{"type":"category","filepath":"categories/documentary.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/business.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/classic.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/entertainment.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/education.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/cooking.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/animation.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/classic.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/documentary.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/family.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/kids.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/culture.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/lifestyle.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/education.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/general.m3u","count":3}
|
||||
{"type":"category","filepath":"categories/outdoor.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/music.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/legislative.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/series.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/news.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/kids.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/lifestyle.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/movies.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/relax.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/religious.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/weather.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/music.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/outdoor.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/science.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/shop.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/xxx.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/news.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/religious.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/series.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/relax.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/sports.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/undefined.m3u","count":7}
|
||||
{"type":"category","filepath":"categories/shop.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/entertainment.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/travel.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/undefined.m3u","count":6}
|
||||
{"type":"country","filepath":"countries/ad.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/ca.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/kg.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/kz.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/tj.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/ru.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/tm.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/undefined.m3u","count":4}
|
||||
{"type":"country","filepath":"countries/uz.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/xxx.m3u","count":1}
|
||||
{"type":"category","filepath":"categories/legislative.m3u","count":0}
|
||||
{"type":"category","filepath":"categories/weather.m3u","count":1}
|
||||
{"type":"language","filepath":"languages/cat.m3u","count":1}
|
||||
{"type":"language","filepath":"languages/rus.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-on.m3u","count":1}
|
||||
{"type":"language","filepath":"languages/undefined.m3u","count":7}
|
||||
{"type":"language","filepath":"languages/eng.m3u","count":1}
|
||||
{"type":"language","filepath":"languages/undefined.m3u","count":8}
|
||||
{"type":"country","filepath":"countries/ca.m3u","count":2}
|
||||
{"type":"country","filepath":"countries/ad.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/ru.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/uz.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/kz.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/tj.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/tm.m3u","count":1}
|
||||
{"type":"country","filepath":"countries/undefined.m3u","count":4}
|
||||
{"type":"country","filepath":"countries/kg.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ad-07.m3u","count":1}
|
||||
{"type":"region","filepath":"regions/afr.m3u","count":0}
|
||||
{"type":"subdivision","filepath":"subdivisions/ad-02.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ad-04.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ad-08.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ad-03.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-ab.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ad-05.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-bc.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-nl.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ad-06.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-mb.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-nb.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-nt.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-nu.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-on.m3u","count":2}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-ns.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-pe.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-qc.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-sk.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kg-j.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kg-b.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kg-t.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ca-yt.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kg-c.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kg-gb.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kg-n.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kg-y.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-ala.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kg-go.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-alm.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-akm.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-zap.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-aty.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-man.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-yuz.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-kus.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-akt.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-kar.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-kzy.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-ast.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-shy.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-pav.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-vos.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-ad.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-sev.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-al.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-ba.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-da.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-bu.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-in.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kk.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kl.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/kz-zha.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-me.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-se.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-mo.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-ko.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-ty.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kr.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-alt.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-amu.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-bel.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-ast.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-sa.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-che.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-cu.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-ta.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-ce.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-bry.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-irk.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-chu.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kb.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-iva.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-klu.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kc.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-ark.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kda.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kha.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kgd.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kya.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-khm.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kgn.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kem.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kir.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-mag.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kam.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-krs.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-len.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-kos.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-lip.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-mur.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-mow.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-niz.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-nen.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-ngr.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-ore.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-oms.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-orl.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-nvs.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-mos.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-psk.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-ros.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-per.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-pnz.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-pri.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-sam.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-sak.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-rya.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-spe.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-sar.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-tam.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-tom.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-smo.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-sta.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-tul.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-sve.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-vla.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-tve.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-ud.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-vgg.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-vor.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-uly.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-zab.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-vlg.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-tyu.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/tj-du.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-yan.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/tj-kt.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/tj-gb.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/tj-ra.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/tm-a.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-yev.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/ru-yar.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/tj-su.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/tm-b.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/tm-l.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/tm-m.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/tm-d.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-ji.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-nw.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-bu.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-qr.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-an.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-fa.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-qa.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-si.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-sa.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-tk.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-ng.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-xo.m3u","count":1}
|
||||
{"type":"subdivision","filepath":"subdivisions/uz-su.m3u","count":1}
|
||||
{"type":"region","filepath":"regions/apac.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/amer.m3u","count":1}
|
||||
{"type":"region","filepath":"regions/arab.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/amer.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/asean.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/cenamer.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/asia.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/arab.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/carib.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/cis.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/hispam.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/emea.m3u","count":3}
|
||||
{"type":"region","filepath":"regions/lac.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/cas.m3u","count":1}
|
||||
{"type":"region","filepath":"regions/latam.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/cenamer.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/lac.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/emea.m3u","count":3}
|
||||
{"type":"region","filepath":"regions/eur.m3u","count":3}
|
||||
{"type":"region","filepath":"regions/nam.m3u","count":1}
|
||||
{"type":"region","filepath":"regions/mena.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/noram.m3u","count":1}
|
||||
{"type":"region","filepath":"regions/mideast.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/hispam.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/latam.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/maghreb.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/ssa.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/nord.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/asia.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/oce.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/southam.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/wafr.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/noram.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/nord.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/nam.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/int.m3u","count":2}
|
||||
{"type":"region","filepath":"regions/southam.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/mideast.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/wafr.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/sas.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/ssa.m3u","count":0}
|
||||
{"type":"region","filepath":"regions/undefined.m3u","count":4}
|
||||
{"type":"index","filepath":"index.m3u","count":10}
|
||||
{"type":"index","filepath":"index.category.m3u","count":11}
|
||||
{"type":"index","filepath":"index.country.m3u","count":14}
|
||||
{"type":"index","filepath":"index.language.m3u","count":10}
|
||||
{"type":"index","filepath":"index.region.m3u","count":20}
|
||||
{"type":"source","filepath":"sources/in.m3u","count":1}
|
||||
{"type":"source","filepath":"sources/unsorted.m3u","count":4}
|
||||
{"type":"source","filepath":"sources/ca.m3u","count":2}
|
||||
{"type":"source","filepath":"sources/ad.m3u","count":3}
|
||||
{"type":"source","filepath":"sources/uk.m3u","count":1}
|
||||
{"type":"source","filepath":"sources/kg.m3u","count":1}
|
||||
{"type":"index","filepath":"index.m3u","count":11}
|
||||
{"type":"index","filepath":"index.category.m3u","count":12}
|
||||
{"type":"index","filepath":"index.country.m3u","count":15}
|
||||
{"type":"index","filepath":"index.language.m3u","count":11}
|
||||
{"type":"index","filepath":"index.region.m3u","count":23}
|
||||
|
|
|
@ -145,7 +145,6 @@ Same thing, but split up into separate files:
|
|||
<tbody>
|
||||
<tr><td>🇨🇲 Cameroon</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cm.m3u</code></td></tr>
|
||||
<tr><td>🇨🇦 Canada</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/ca.m3u</code></td></tr>
|
||||
<tr><td> Ontario</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ca-on.m3u</code></td></tr>
|
||||
<tr><td>🇨🇻 Cape Verde</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cv.m3u</code></td></tr>
|
||||
<tr><td>🇨🇬 Republic of the Congo</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/cg.m3u</code></td></tr>
|
||||
<tr><td>🇷🇪 Réunion</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/countries/re.m3u</code></td></tr>
|
||||
|
@ -161,6 +160,27 @@ Same thing, but split up into separate files:
|
|||
|
||||
</details>
|
||||
|
||||
### Grouped by subdivision
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
<br>
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<details>
|
||||
<summary>Canada</summary>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th align="left">Subdivision</th><th align="left">Channels</th><th align="left">Playlist</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>Ontario</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/iptv/subdivisions/ca-on.m3u</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
### Grouped by region
|
||||
|
||||
<details>
|
||||
|
|
|
@ -669,5 +669,15 @@
|
|||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false
|
||||
},
|
||||
{
|
||||
"id": "5AABTV.ca",
|
||||
"name": "5AAB TV",
|
||||
"network": null,
|
||||
"country": "CA",
|
||||
"subdivision": null,
|
||||
"city": null,
|
||||
"categories": [],
|
||||
"is_nsfw": false
|
||||
}
|
||||
]
|
|
@ -826,5 +826,19 @@
|
|||
],
|
||||
"languages": [],
|
||||
"video_format": "576i"
|
||||
},
|
||||
{
|
||||
"channel": "5AABTV.ca",
|
||||
"id": "SD",
|
||||
"name": "SD",
|
||||
"is_main": true,
|
||||
"broadcast_area": [
|
||||
"c/CA"
|
||||
],
|
||||
"timezones": [
|
||||
"Asia/Bishkek"
|
||||
],
|
||||
"languages": [],
|
||||
"video_format": "576i"
|
||||
}
|
||||
]
|
|
@ -7,5 +7,6 @@
|
|||
{"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"}
|
||||
{"channel":"AndorraTV.ad","feed":null,"tags":[],"width":512,"height":512,"format":"PNG","url":"https://i.imgur.com/CnhTn8i.png"},
|
||||
{"channel":"Zoo.ad","feed":null,"tags":[],"width":512,"height":512,"format":"PNG","url":"https://i.imgur.com/ciTJrnl.png"}
|
||||
]
|
|
@ -1682,7 +1682,7 @@ module.exports = [
|
|||
closed_at: null,
|
||||
author_association: 'COLLABORATOR',
|
||||
active_lock_reason: null,
|
||||
body: '### Stream URL\n\nhttps://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8\n\n### Stream ID\n\nboo.us\n\n### Channel Name\n\nBBC America\n\n### Quality\n\n720p\n\n### Label\n\nGeo-blocked\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_No response_\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\n\nhttps://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8\n\n### Stream ID\n\nboo.us\n\n### Quality\n\n720p\n\n### Label\n\nGeo-blocked\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_No response_\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/14120/reactions',
|
||||
total_count: 0,
|
||||
|
@ -2284,5 +2284,114 @@ module.exports = [
|
|||
timeline_url: 'https://api.github.com/repos/iptv-org/iptv/issues/20956/timeline',
|
||||
performed_via_github_app: null,
|
||||
state_reason: null
|
||||
},
|
||||
{
|
||||
url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157',
|
||||
repository_url: 'https://api.github.com/repos/iptv-org/iptv',
|
||||
labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/labels{/name}',
|
||||
comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/comments',
|
||||
events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/events',
|
||||
html_url: 'https://github.com/iptv-org/iptv/issues/25157',
|
||||
id: 3245640024,
|
||||
node_id: 'I_kwDOCWUK8M7BdIlY',
|
||||
number: 25157,
|
||||
title: 'Add: OnTime Sports SD',
|
||||
user: {
|
||||
login: 'zezopm300',
|
||||
id: 215159878,
|
||||
node_id: 'U_kgDODNMURg',
|
||||
avatar_url: 'https://avatars.githubusercontent.com/u/215159878?v=4',
|
||||
gravatar_id: '',
|
||||
url: 'https://api.github.com/users/zezopm300',
|
||||
html_url: 'https://github.com/zezopm300',
|
||||
followers_url: 'https://api.github.com/users/zezopm300/followers',
|
||||
following_url: 'https://api.github.com/users/zezopm300/following{/other_user}',
|
||||
gists_url: 'https://api.github.com/users/zezopm300/gists{/gist_id}',
|
||||
starred_url: 'https://api.github.com/users/zezopm300/starred{/owner}{/repo}',
|
||||
subscriptions_url: 'https://api.github.com/users/zezopm300/subscriptions',
|
||||
organizations_url: 'https://api.github.com/users/zezopm300/orgs',
|
||||
repos_url: 'https://api.github.com/users/zezopm300/repos',
|
||||
events_url: 'https://api.github.com/users/zezopm300/events{/privacy}',
|
||||
received_events_url: 'https://api.github.com/users/zezopm300/received_events',
|
||||
type: 'User',
|
||||
user_view_type: 'public',
|
||||
site_admin: false
|
||||
},
|
||||
labels: [
|
||||
{
|
||||
id: 5923508587,
|
||||
node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw',
|
||||
url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add',
|
||||
name: 'streams:add',
|
||||
color: '017ff9',
|
||||
default: false,
|
||||
description: 'Request to add a new link to a playlist'
|
||||
}
|
||||
],
|
||||
state: 'open',
|
||||
locked: false,
|
||||
assignee: null,
|
||||
assignees: [],
|
||||
milestone: null,
|
||||
comments: 0,
|
||||
created_at: '2025-07-19T20:44:05Z',
|
||||
updated_at: '2025-07-19T20:44:05Z',
|
||||
closed_at: null,
|
||||
author_association: 'NONE',
|
||||
type: null,
|
||||
active_lock_reason: null,
|
||||
sub_issues_summary: { total: 0, completed: 0, percent_completed: 0 },
|
||||
body:
|
||||
'### Stream ID (required)\n' +
|
||||
'\n' +
|
||||
'OnTimeSports.eg@SD\n' +
|
||||
'\n' +
|
||||
'### Stream URL (required)\n' +
|
||||
'\n' +
|
||||
' OnTime Sports SD.mu38\n' +
|
||||
'\n' +
|
||||
'### Quality\n' +
|
||||
'\n' +
|
||||
'None\n' +
|
||||
'\n' +
|
||||
'### Label\n' +
|
||||
'\n' +
|
||||
'None\n' +
|
||||
'\n' +
|
||||
'### HTTP User Agent\n' +
|
||||
'\n' +
|
||||
'_No response_\n' +
|
||||
'\n' +
|
||||
'### HTTP Referrer\n' +
|
||||
'\n' +
|
||||
'_No response_\n' +
|
||||
'\n' +
|
||||
'### Directives\n' +
|
||||
'\n' +
|
||||
'_No response_\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)',
|
||||
closed_by: null,
|
||||
reactions: {
|
||||
url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/reactions',
|
||||
total_count: 0,
|
||||
'+1': 0,
|
||||
'-1': 0,
|
||||
laugh: 0,
|
||||
hooray: 0,
|
||||
confused: 0,
|
||||
heart: 0,
|
||||
rocket: 0,
|
||||
eyes: 0
|
||||
},
|
||||
timeline_url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/timeline',
|
||||
performed_via_github_app: null,
|
||||
state_reason: null
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#EXTM3U
|
||||
#EXTINF:-1 tvg-id="5AABTV.ca",5AAB TV
|
||||
http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8
|
||||
#EXTINF:-1 tvg-id="MeteoMedia.ca",Meteomedia
|
||||
http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
|
||||
|
|
|
@ -96,6 +96,17 @@ Same thing, but split up into separate files:
|
|||
|
||||
</details>
|
||||
|
||||
### Grouped by subdivision
|
||||
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
<br>
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
#include "tests/__data__/output/.readme/_subdivisions.md"
|
||||
|
||||
</details>
|
||||
|
||||
### Grouped by region
|
||||
|
||||
<details>
|
||||
|
|
|
@ -15,18 +15,20 @@ describe('report:create', () => {
|
|||
|
||||
expect(
|
||||
stdout.includes(`
|
||||
┌─────────┬─────────────┬──────────────────┬─────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────┬───────────────┐
|
||||
│ (index) │ issueNumber │ type │ streamId │ streamUrl │ status │
|
||||
├─────────┼─────────────┼──────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────┤
|
||||
│ 0 │ 14120 │ 'streams:edit' │ 'boo.us' │ 'https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8' │ 'invalid_id' │
|
||||
│ 1 │ 14135 │ 'streams:add' │ 'BBCWorldNews.uk@SouthAsia' │ 'http://103.199.161.254/Content/bbcworld/Live/Channel%28BBCworld%29/Stream%2801%29/index.m3u8' │ 'wrong_id' │
|
||||
│ 2 │ 14177 │ 'streams:add' │ 'TUTV.us' │ 'https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8' │ 'on_playlist' │
|
||||
│ 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 │ 19957 │ 'channel search' │ '13thStreet.au' │ undefined │ 'closed' │
|
||||
│ 7 │ 20956 │ 'channel search' │ 'IONTV.us' │ undefined │ 'fulfilled' │
|
||||
└─────────┴─────────────┴──────────────────┴─────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────┴───────────────┘`)
|
||||
┌─────────┬─────────────┬──────────────────┬─────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────┐
|
||||
│ (index) │ issueNumber │ type │ streamId │ streamUrl │ status │
|
||||
├─────────┼─────────────┼──────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────┤
|
||||
│ 0 │ 14120 │ 'streams:edit' │ 'boo.us' │ 'https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8' │ 'invalid_id' │
|
||||
│ 1 │ 14135 │ 'streams:add' │ 'BBCWorldNews.uk@SouthAsia' │ 'http://103.199.161.254/Content/bbcworld/Live/Channel%28BBCworld%29/Stream%2801%29/index.m3u8' │ 'wrong_id' │
|
||||
│ 2 │ 14177 │ 'streams:add' │ 'TUTV.us' │ 'https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8' │ 'on_playlist' │
|
||||
│ 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 │ 14179 │ 'streams:add' │ 'ManoramaNews.in' │ '(https://mitelefe.com/Api/Videos/GetSourceUrl/694564/0/HLS / https://ssl.cloud.telefe.com/Api/Videos...' │ 'invalid_link' │
|
||||
│ 5 │ 16120 │ 'streams:remove' │ undefined │ 'http://190.61.102.67:2000/play/a038/index.m3u8' │ 'wrong_link' │
|
||||
│ 6 │ 19956 │ 'channel search' │ 'CNBCe.tr' │ undefined │ 'invalid_id' │
|
||||
│ 7 │ 19957 │ 'channel search' │ '13thStreet.au' │ undefined │ 'closed' │
|
||||
│ 8 │ 20956 │ 'channel search' │ 'IONTV.us' │ undefined │ 'fulfilled' │
|
||||
│ 9 │ 25157 │ 'streams:add' │ 'OnTimeSports.eg@SD' │ 'OnTime Sports SD.mu38' │ 'invalid_link' │
|
||||
└─────────┴─────────────┴──────────────────┴─────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────┘`)
|
||||
).toBe(true)
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue