diff --git a/.github/workflows/_load.yml b/.github/workflows/_load.yml
index 17e58f35..37f7413e 100644
--- a/.github/workflows/_load.yml
+++ b/.github/workflows/_load.yml
@@ -15,10 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - name: Download data from API
- run: |
- mkdir -p scripts/data
- curl -L -o scripts/data/channels.json https://iptv-org.github.io/api/channels.json
+ - run: npm run api:load
- uses: FedericoCarboni/setup-ffmpeg@v1
- uses: actions/setup-node@v2
if: ${{ !env.ACT }}
diff --git a/.github/workflows/proximusmwc.be.yml b/.github/workflows/proximusmwc.be.yml
new file mode 100644
index 00000000..7bfc2c0b
--- /dev/null
+++ b/.github/workflows/proximusmwc.be.yml
@@ -0,0 +1,17 @@
+name: proximusmwc.be
+on:
+ schedule:
+ - cron: '0 0 * * *'
+ workflow_dispatch:
+ workflow_run:
+ workflows: [_trigger]
+ types:
+ - completed
+jobs:
+ load:
+ uses: ./.github/workflows/_load.yml
+ with:
+ site: ${{github.workflow}}
+ secrets:
+ APP_ID: ${{ secrets.APP_ID }}
+ APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
diff --git a/.github/workflows/tvim.tv.yml b/.github/workflows/tvim.tv.yml
index db5d2c87..7e100893 100644
--- a/.github/workflows/tvim.tv.yml
+++ b/.github/workflows/tvim.tv.yml
@@ -1,7 +1,7 @@
name: tvim.tv
on:
schedule:
- - cron: '0 0 * * *'
+ - cron: '5 0 * * *'
workflow_dispatch:
workflow_run:
workflows: [_trigger]
diff --git a/README.md b/README.md
index 90fd2764..87219673 100644
--- a/README.md
+++ b/README.md
@@ -198,8 +198,9 @@ To load a program guide, all you need to do is copy the link to one or more of t
🇷🇪 Réunion | 119 | https://iptv-org.github.io/epg/guides/re/canalplus-reunion.com.epg.xml |  |
🇧🇱 Saint Barthélemy | 128 | https://iptv-org.github.io/epg/guides/bl/canalplus-caraibes.com.epg.xml |  |
🇲🇫 Saint Martin | 128 | https://iptv-org.github.io/epg/guides/mf/canalplus-caraibes.com.epg.xml |  |
- 🇸🇦 Saudi Arabia | 98 | https://iptv-org.github.io/epg/guides/sa-ar/osn.com.epg.xml |  |
+ 🇸🇦 Saudi Arabia | 98 | https://iptv-org.github.io/epg/guides/sa-ar/osn.com.epg.xml |  |
98 | https://iptv-org.github.io/epg/guides/sa-en/osn.com.epg.xml |  |
+ 5 | https://iptv-org.github.io/epg/guides/sa/artonline.tv.epg.xml |  |
🇸🇳 Senegal | 242 | https://iptv-org.github.io/epg/guides/sn/canalplus-afrique.com.epg.xml |  |
125 | https://iptv-org.github.io/epg/guides/sn/dstv.com.epg.xml |  |
🇷🇸 Serbia | 357 | https://iptv-org.github.io/epg/guides/rs/mts.rs.epg.xml |  |
@@ -231,7 +232,7 @@ To load a program guide, all you need to do is copy the link to one or more of t
99 | https://iptv-org.github.io/epg/guides/ae-en/osn.com.epg.xml |  |
🇬🇧 United Kingdom | 258 | https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml |  |
97 | https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml |  |
- 🇺🇸 United States | 1714 | https://iptv-org.github.io/epg/guides/us/tvtv.us.epg.xml |  |
+ 🇺🇸 United States | 1717 | https://iptv-org.github.io/epg/guides/us/tvtv.us.epg.xml |  |
410 | https://iptv-org.github.io/epg/guides/us/directv.com.epg.xml |  |
88 | https://iptv-org.github.io/epg/guides/us/tvguide.com.epg.xml |  |
22 | https://iptv-org.github.io/epg/guides/us/gatotv.com.epg.xml |  |
diff --git a/package-lock.json b/package-lock.json
index 690e3bbb..f0555882 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,17 +19,20 @@
"fs-extra": "^10.0.1",
"glob": "^7.2.0",
"iconv-lite": "^0.4.24",
+ "inquirer": "^8.2.0",
"jest": "^27.3.1",
"libxmljs": "^0.19.7",
"lodash": "^4.17.21",
"markdown-include": "^0.4.3",
"mockdate": "^3.0.5",
"nedb-promises": "^5.0.3",
+ "node-cleanup": "^2.1.2",
"parse-duration": "^1.0.0",
"pdf-parse": "^1.1.1",
"signale": "^1.4.0",
"srcset": "^4.0.0",
"tabletojson": "^2.0.7",
+ "transliteration": "^2.2.0",
"wildcard-match": "^5.1.2"
}
},
@@ -1397,11 +1400,40 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
"node_modules/bindings": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz",
"integrity": "sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew=="
},
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
@@ -1462,6 +1494,29 @@
"node-int64": "^0.4.0"
}
},
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -1554,6 +1609,11 @@
"node": ">=10"
}
},
+ "node_modules/chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
+ },
"node_modules/cheerio": {
"version": "1.0.0-rc.10",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
@@ -1604,6 +1664,36 @@
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
},
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz",
+ "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
"node_modules/cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
@@ -1614,6 +1704,14 @@
"wrap-ansi": "^7.0.0"
}
},
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/clone-response": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
@@ -1921,6 +2019,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/defaults": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
+ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
+ "dependencies": {
+ "clone": "^1.0.2"
+ }
+ },
"node_modules/defer-to-connect": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
@@ -2265,6 +2371,19 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dependencies": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -2692,6 +2811,25 @@
"node": ">=0.10.0"
}
},
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
"node_modules/ignore-walk": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz",
@@ -2747,6 +2885,52 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
+ "node_modules/inquirer": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz",
+ "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==",
+ "dependencies": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.1.1",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^3.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.21",
+ "mute-stream": "0.0.8",
+ "ora": "^5.4.1",
+ "run-async": "^2.4.0",
+ "rxjs": "^7.2.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/inquirer/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/inquirer/node_modules/figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
@@ -2812,6 +2996,14 @@
"node": ">=6"
}
},
+ "node_modules/is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -2849,6 +3041,17 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -3766,6 +3969,21 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/logform": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/logform/-/logform-2.3.0.tgz",
@@ -3948,6 +4166,11 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
+ "node_modules/mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
+ },
"node_modules/nan": {
"version": "2.14.2",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
@@ -3990,6 +4213,11 @@
"ms": "^2.1.1"
}
},
+ "node_modules/node-cleanup": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz",
+ "integrity": "sha1-esGavSl+Caf3KnFUXZUbUX5N3iw="
+ },
"node_modules/node-ensure": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz",
@@ -4207,6 +4435,28 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "dependencies": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
@@ -4658,6 +4908,18 @@
"lowercase-keys": "^2.0.0"
}
},
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -4672,6 +4934,22 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/rxjs": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz",
+ "integrity": "sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -5096,6 +5374,22 @@
"resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz",
"integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w=="
},
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+ },
+ "node_modules/tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dependencies": {
+ "os-tmpdir": "~1.0.2"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
"node_modules/tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
@@ -5144,6 +5438,21 @@
"node": ">=8"
}
},
+ "node_modules/transliteration": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/transliteration/-/transliteration-2.2.0.tgz",
+ "integrity": "sha512-o29GDWtecNoK4TNfnJQesGluFPiza+U8NoiKrErU8eTNlVgma6w1LV/tTiGo+waFLkhtL9WxrW0lXhZKmm7msQ==",
+ "dependencies": {
+ "yargs": "^16.1.0"
+ },
+ "bin": {
+ "slugify": "dist/bin/slugify",
+ "transliterate": "dist/bin/transliterate"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/triple-beam": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
@@ -5319,6 +5628,14 @@
"makeerror": "1.0.12"
}
},
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
"node_modules/webidl-conversions": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
@@ -6650,11 +6967,26 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
+ "base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+ },
"bindings": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz",
"integrity": "sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew=="
},
+ "bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "requires": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
"boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
@@ -6702,6 +7034,15 @@
"node-int64": "^0.4.0"
}
},
+ "buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "requires": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
"buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -6765,6 +7106,11 @@
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
"integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="
},
+ "chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
+ },
"cheerio": {
"version": "1.0.0-rc.10",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
@@ -6806,6 +7152,24 @@
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
},
+ "cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "requires": {
+ "restore-cursor": "^3.1.0"
+ }
+ },
+ "cli-spinners": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz",
+ "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g=="
+ },
+ "cli-width": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw=="
+ },
"cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
@@ -6816,6 +7180,11 @@
"wrap-ansi": "^7.0.0"
}
},
+ "clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
+ },
"clone-response": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
@@ -7060,6 +7429,14 @@
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
},
+ "defaults": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
+ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
+ "requires": {
+ "clone": "^1.0.2"
+ }
+ },
"defer-to-connect": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
@@ -7303,6 +7680,16 @@
}
}
},
+ "external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "requires": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ }
+ },
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -7621,6 +8008,11 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
+ "ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
+ },
"ignore-walk": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz",
@@ -7667,6 +8059,42 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
+ "inquirer": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz",
+ "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==",
+ "requires": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.1.1",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^3.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.21",
+ "mute-stream": "0.0.8",
+ "ora": "^5.4.1",
+ "run-async": "^2.4.0",
+ "rxjs": "^7.2.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+ },
+ "figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ }
+ }
+ },
"is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
@@ -7700,6 +8128,11 @@
"resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
"integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ=="
},
+ "is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="
+ },
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -7725,6 +8158,11 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
+ "is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="
+ },
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -8436,6 +8874,15 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
+ "log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "requires": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ }
+ },
"logform": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/logform/-/logform-2.3.0.tgz",
@@ -8584,6 +9031,11 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
+ "mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
+ },
"nan": {
"version": "2.14.2",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
@@ -8622,6 +9074,11 @@
}
}
},
+ "node-cleanup": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz",
+ "integrity": "sha1-esGavSl+Caf3KnFUXZUbUX5N3iw="
+ },
"node-ensure": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz",
@@ -8795,6 +9252,22 @@
"word-wrap": "~1.2.3"
}
},
+ "ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "requires": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ }
+ },
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
@@ -9128,6 +9601,15 @@
"lowercase-keys": "^2.0.0"
}
},
+ "restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "requires": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -9136,6 +9618,19 @@
"glob": "^7.1.3"
}
},
+ "run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ=="
+ },
+ "rxjs": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz",
+ "integrity": "sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==",
+ "requires": {
+ "tslib": "^2.1.0"
+ }
+ },
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -9451,6 +9946,19 @@
"resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz",
"integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w=="
},
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
"tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
@@ -9487,6 +9995,14 @@
"punycode": "^2.1.1"
}
},
+ "transliteration": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/transliteration/-/transliteration-2.2.0.tgz",
+ "integrity": "sha512-o29GDWtecNoK4TNfnJQesGluFPiza+U8NoiKrErU8eTNlVgma6w1LV/tTiGo+waFLkhtL9WxrW0lXhZKmm7msQ==",
+ "requires": {
+ "yargs": "^16.1.0"
+ }
+ },
"triple-beam": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
@@ -9611,6 +10127,14 @@
"makeerror": "1.0.12"
}
},
+ "wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
+ "requires": {
+ "defaults": "^1.0.3"
+ }
+ },
"webidl-conversions": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
diff --git a/package.json b/package.json
index 57ad993f..157617f0 100644
--- a/package.json
+++ b/package.json
@@ -4,11 +4,13 @@
"channels:validate": "node scripts/commands/channels/validate.js",
"channels:lint": "node scripts/commands/channels/lint.js",
"channels:parse": "node scripts/commands/channels/parse.js",
+ "channels:editor": "node scripts/commands/channels/editor.js",
"queue:create": "node scripts/commands/queue/create.js",
"cluster:load": "node scripts/commands/cluster/load.js",
"programs:save": "node scripts/commands/programs/save.js",
"guides:update": "node scripts/commands/guides/update.js",
"api:update": "node scripts/commands/api/update.js",
+ "api:load": "mkdir -p scripts/data && curl -L -o scripts/data/channels.json https://iptv-org.github.io/api/channels.json",
"readme:update": "node scripts/commands/readme/update.js",
"test": "npx jest --runInBand",
"test:commands": "npx jest --runInBand -- commands",
@@ -36,17 +38,20 @@
"fs-extra": "^10.0.1",
"glob": "^7.2.0",
"iconv-lite": "^0.4.24",
+ "inquirer": "^8.2.0",
"jest": "^27.3.1",
"libxmljs": "^0.19.7",
"lodash": "^4.17.21",
"markdown-include": "^0.4.3",
"mockdate": "^3.0.5",
"nedb-promises": "^5.0.3",
+ "node-cleanup": "^2.1.2",
"parse-duration": "^1.0.0",
"pdf-parse": "^1.1.1",
"signale": "^1.4.0",
"srcset": "^4.0.0",
"tabletojson": "^2.0.7",
+ "transliteration": "^2.2.0",
"wildcard-match": "^5.1.2"
}
}
diff --git a/scripts/commands/channels/editor.js b/scripts/commands/channels/editor.js
new file mode 100644
index 00000000..94e37caf
--- /dev/null
+++ b/scripts/commands/channels/editor.js
@@ -0,0 +1,117 @@
+const { api, parser, xml, file, logger } = require('../../core')
+const { transliterate } = require('transliteration')
+const nodeCleanup = require('node-cleanup')
+const { program } = require('commander')
+const inquirer = require('inquirer')
+
+program
+ .requiredOption('-i, --input ', 'Load channels from the file')
+ .option('-c, --country ', 'Source country', 'us')
+ .parse(process.argv)
+
+const options = program.opts()
+const defaultCountry = options.country
+const newLabel = ` [new]`
+
+let site
+let channels = []
+
+async function main() {
+ await api.channels.load()
+ let result = await parser.parseChannels(options.input)
+ site = result.site
+ channels = result.channels
+ for (const channel of channels) {
+ if (channel.xmltv_id) continue
+ let choices = await getOptions(channel)
+ const question = {
+ name: 'option',
+ message: `Choose an option:`,
+ type: 'list',
+ choices,
+ pageSize: 10
+ }
+ await inquirer.prompt(question).then(async selected => {
+ switch (selected.option) {
+ case 'Overwrite...':
+ const input = await getInput(channel)
+ channel.xmltv_id = input.xmltv_id
+ break
+ case 'Skip...':
+ channel.xmltv_id = '-'
+ break
+ default:
+ const [name, xmltv_id] = selected.option
+ .replace(/ \[.*\]/, '')
+ .split('|')
+ .map(i => i.trim().replace(newLabel, ''))
+ channel.xmltv_id = xmltv_id
+ break
+ }
+ })
+ }
+}
+
+main()
+
+function save() {
+ const output = xml.create(channels, site)
+
+ file.writeSync(options.input, output)
+
+ logger.info(`\nFile '${options.input}' successfully saved`)
+}
+
+nodeCleanup(() => {
+ save()
+})
+
+async function getInput(channel) {
+ const name = channel.name.trim()
+ const input = await inquirer.prompt([
+ {
+ name: 'xmltv_id',
+ message: ' ID:',
+ type: 'input',
+ default: generateCode(name, defaultCountry)
+ }
+ ])
+
+ return { name, xmltv_id: input['xmltv_id'] }
+}
+
+async function getOptions(channel) {
+ const channels = await api.channels.all()
+ const similar = await getSimilar(channels, channel)
+ let variants = []
+ variants.push(`${channel.name.trim()} | ${generateCode(channel.name, defaultCountry)}${newLabel}`)
+ similar.forEach(i => {
+ variants.push(`${i.name} | ${i.id} [api]`)
+ })
+ variants.push(`Overwrite...`)
+ variants.push(`Skip...`)
+
+ return variants
+}
+
+async function getSimilar(list, channel) {
+ return list.filter(i =>
+ i.name
+ .toLowerCase()
+ .replace(/\s|-|:/gi, '')
+ .startsWith(
+ channel.name
+ .replace(/(\s|-|:)/gi, '')
+ .slice(0, 8)
+ .toLowerCase()
+ )
+ )
+}
+
+function generateCode(name, country) {
+ const id = transliterate(name)
+ .replace(/\+/gi, 'Plus')
+ .replace(/[^a-z\d]+/gi, '')
+
+ return `${id}.${country}`
+}
diff --git a/sites/delta.nl/delta.nl.config.js b/sites/delta.nl/delta.nl.config.js
index e3be8d1a..90cbfbf1 100644
--- a/sites/delta.nl/delta.nl.config.js
+++ b/sites/delta.nl/delta.nl.config.js
@@ -8,17 +8,19 @@ module.exports = {
.add(1, 'd')
.unix()}&includeDetails=true&channels=${channel.site_id}`
},
- parser: function ({ content, channel }) {
+ async parser({ content, channel }) {
let programs = []
const items = parseItems(content, channel)
- items.forEach(item => {
+ for (let item of items) {
+ const details = await loadProgramDetails(item)
programs.push({
title: item.title,
icon: item.images.thumbnail.url,
+ description: details.description,
start: parseStart(item).toJSON(),
stop: parseStop(item).toJSON()
})
- })
+ }
return programs
},
@@ -40,6 +42,17 @@ module.exports = {
}
}
+async function loadProgramDetails(item) {
+ if (!item.ID) return {}
+ const url = `https://clientapi.tv.delta.nl/guide/4/details/${item.ID}?X-Response-Version=4.5`
+ const data = await axios
+ .get(url)
+ .then(r => r.data)
+ .catch(console.log)
+
+ return data || {}
+}
+
function parseStart(item) {
return dayjs.unix(item.start)
}
diff --git a/sites/delta.nl/delta.nl.test.js b/sites/delta.nl/delta.nl.test.js
index cb7fa226..2f979ba1 100644
--- a/sites/delta.nl/delta.nl.test.js
+++ b/sites/delta.nl/delta.nl.test.js
@@ -1,13 +1,16 @@
-// node ./scripts/channels.js --config=./sites/delta.nl/delta.nl.config.js --output=./sites/delta.nl/delta.nl_nl.channels.xml
-// npx epg-grabber --config=sites/delta.nl/delta.nl.config.js --channels=sites/delta.nl/delta.nl_nl.channels.xml --output=.gh-pages/guides/nl/delta.nl.epg.xml --days=2
+// npm run channels:parse --config=./sites/delta.nl/delta.nl.config.js --output=./sites/delta.nl/delta.nl_nl.channels.xml
+// npx epg-grabber --config=sites/delta.nl/delta.nl.config.js --channels=sites/delta.nl/delta.nl_nl.channels.xml --output=guide.xml --days=2
const { parser, url, request } = require('./delta.nl.config.js')
+const axios = require('axios')
const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc')
const customParseFormat = require('dayjs/plugin/customParseFormat')
dayjs.extend(customParseFormat)
dayjs.extend(utc)
+jest.mock('axios')
+
const date = dayjs.utc('2021-11-12', 'YYYY-MM-DD').startOf('d')
const channel = {
site_id: '1',
@@ -20,25 +23,47 @@ it('can generate valid url', () => {
)
})
-it('can parse response', () => {
- const content = `{"1":[{"ID":"P~945cb98e-3d19-11ec-8456-953363d7a344","seriesID":"S~d37c4626-b691-11ea-ba69-255835135f02","channelID":"1","start":1636674960,"end":1636676520,"catchupAvailableUntil":1637279760,"title":"NOS Journaal","images":{"thumbnail":{"url":"https://cdn.gvidi.tv/img/booxmedia/e19c/static/NOS%20Journaal5.jpg"}},"additionalInformation":{"metadataID":"M~944f3c6e-3d19-11ec-9faf-2735f2e98d2a","externalMetadataID":"E~TV01-2026117420668"},"parentalGuidance":{"kijkwijzer":["AL"]},"restrictions":{"startoverDisabled":false,"catchupDisabled":false,"recordingDisabled":false},"isFiller":false}]}`
- const result = parser({ date, channel, content })
+it('can parse response', done => {
+ axios.get.mockImplementation(() =>
+ Promise.resolve({
+ data: JSON.parse(
+ `{"ID":"P~945cb98e-3d19-11ec-8456-953363d7a344","seriesID":"S~d37c4626-b691-11ea-ba69-255835135f02","channelID":"1","start":1636674960,"end":1636676520,"catchupAvailableUntil":1637279760,"title":"Eigen Huis & Tuin: Lekker Leven","description":"Nederlands lifestyleprogramma uit 2022 (ook in HD) met dagelijkse inspiratie voor een lekker leven in en om het huis.\\nPresentatrice Froukje de Both, kok Hugo Kennis en een team van experts, onder wie tuinman Tom Groot, geven praktische tips op het gebied van wonen, lifestyle, tuinieren en koken. Daarmee kun je zelf direct aan de slag om je leven leuker én gezonder te maken. Afl. 15 van seizoen 4.","images":{"thumbnail":{"url":"https://cdn.gvidi.tv/img/booxmedia/b291/561946.jpg"}},"additionalInformation":{"metadataID":"M~c512c206-95e5-11ec-87d8-494f70130311","externalMetadataID":"E~RTL4-89d99356_6599_4b65_a7a0_a93f39019645"},"parentalGuidance":{"kijkwijzer":["AL"]},"restrictions":{"startoverDisabled":false,"catchupDisabled":false,"recordingDisabled":false},"isFiller":false}`
+ )
+ })
+ )
- expect(result).toMatchObject([
- {
- start: '2021-11-11T23:56:00.000Z',
- stop: '2021-11-12T00:22:00.000Z',
- title: 'NOS Journaal',
- icon: 'https://cdn.gvidi.tv/img/booxmedia/e19c/static/NOS%20Journaal5.jpg'
- }
- ])
+ const content = `{"1":[{"ID":"P~945cb98e-3d19-11ec-8456-953363d7a344","seriesID":"S~d37c4626-b691-11ea-ba69-255835135f02","channelID":"1","start":1636674960,"end":1636676520,"catchupAvailableUntil":1637279760,"title":"NOS Journaal","images":{"thumbnail":{"url":"https://cdn.gvidi.tv/img/booxmedia/e19c/static/NOS%20Journaal5.jpg"}},"additionalInformation":{"metadataID":"M~944f3c6e-3d19-11ec-9faf-2735f2e98d2a","externalMetadataID":"E~TV01-2026117420668"},"parentalGuidance":{"kijkwijzer":["AL"]},"restrictions":{"startoverDisabled":false,"catchupDisabled":false,"recordingDisabled":false},"isFiller":false}]}`
+
+ parser({ date, channel, content })
+ .then(result => {
+ expect(result).toMatchObject([
+ {
+ start: '2021-11-11T23:56:00.000Z',
+ stop: '2021-11-12T00:22:00.000Z',
+ title: 'NOS Journaal',
+ description:
+ 'Nederlands lifestyleprogramma uit 2022 (ook in HD) met dagelijkse inspiratie voor een lekker leven in en om het huis.\nPresentatrice Froukje de Both, kok Hugo Kennis en een team van experts, onder wie tuinman Tom Groot, geven praktische tips op het gebied van wonen, lifestyle, tuinieren en koken. Daarmee kun je zelf direct aan de slag om je leven leuker én gezonder te maken. Afl. 15 van seizoen 4.',
+ icon: 'https://cdn.gvidi.tv/img/booxmedia/e19c/static/NOS%20Journaal5.jpg'
+ }
+ ])
+ done()
+ })
+ .catch(error => {
+ done(error)
+ })
})
-it('can handle empty guide', () => {
- const result = parser({
+it('can handle empty guide', done => {
+ parser({
date,
channel,
content: `{"code":500,"message":"Error retrieving guide"}`
})
- expect(result).toMatchObject([])
+ .then(result => {
+ expect(result).toMatchObject([])
+ done()
+ })
+ .catch(error => {
+ done(error)
+ })
})
diff --git a/sites/delta.nl/delta.nl_nl.channels.xml b/sites/delta.nl/delta.nl_nl.channels.xml
index e175fd07..a3f7745a 100644
--- a/sites/delta.nl/delta.nl_nl.channels.xml
+++ b/sites/delta.nl/delta.nl_nl.channels.xml
@@ -1,10 +1,10 @@
- 3sat
- 24 Kitchen Nederland
100% NL TV
192 TV
+ 24 Kitchen Nederland
+ 3sat
AAVISIE
Albrandswaard TV
Aljazeera English
@@ -69,8 +69,8 @@
FilmBox Nederland
Fox NL
France 2
- France 3
France 24 Français
+ France 3
Gemeente Westland TV
GL8
GO-TV
@@ -82,7 +82,7 @@
Hustler TV Europe
Ideaal TV
Ijsselmond TV
- Insight HD
+ Insight TV
Investigation Discovery Europe
JenZ
Kabel Eins Deutschland
@@ -166,6 +166,7 @@
RTV Arnhem TV
RTV Focus TV
RTV Horizon
+ RTV Oost
RTV Purmerend
RTV Rijnstreek TV
RTV Scheldemond
@@ -199,8 +200,8 @@
Trace Sport Stars
Trace Urban
TRT Türk
- TV5Monde Europe
TV 538
+ TV5Monde Europe
TV Berghem
TV Drenthe
TVE Internacional Europa
@@ -208,7 +209,6 @@
TV Krimpenerwaard
TV Noord
TV Nunspeet
- TV Oost
TV Oranje
TV Rijnmond
TV Stichtse Vecht
diff --git a/sites/dsmart.com.tr/dsmart.com.tr_tr.channels.xml b/sites/dsmart.com.tr/dsmart.com.tr_tr.channels.xml
index c42498b1..f63f80c0 100644
--- a/sites/dsmart.com.tr/dsmart.com.tr_tr.channels.xml
+++ b/sites/dsmart.com.tr/dsmart.com.tr_tr.channels.xml
@@ -44,7 +44,7 @@
Haber Global
Habertürk
Halk TV
- Insight HD
+ Insight HD
Kanal 7
Kanal D
Lider TV
diff --git a/sites/novacyprus.com/novacyprus.com_cy.channels.xml b/sites/novacyprus.com/novacyprus.com_cy.channels.xml
index 8f2d59c3..41573b96 100644
--- a/sites/novacyprus.com/novacyprus.com_cy.channels.xml
+++ b/sites/novacyprus.com/novacyprus.com_cy.channels.xml
@@ -10,7 +10,7 @@
Eurosport 2
Fox Greece
Fox Life Greece
- Insight HD
+ Insight HD
Mad Greekz
Mad TV
MTV Live
diff --git a/sites/proximusmwc.be/proximusmwc.be.config.js b/sites/proximusmwc.be/proximusmwc.be.config.js
new file mode 100644
index 00000000..c384ea7f
--- /dev/null
+++ b/sites/proximusmwc.be/proximusmwc.be.config.js
@@ -0,0 +1,79 @@
+const axios = require('axios')
+const dayjs = require('dayjs')
+
+module.exports = {
+ site: 'proximusmwc.be',
+ url: 'https://api.proximusmwc.be/v2/graphql',
+ request: {
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ data({ channel, date }) {
+ return {
+ query:
+ 'query ($language: String!, $startTime: Int!, $endTime: Int!, $options: SchedulesByIntervalOptions) { schedulesByInterval(language: $language, startTime: $startTime, endTime: $endTime, options: $options) { trailId programReferenceNumber channelId title category startTime endTime image { key url __typename } parentalRating detailUrl grouped description shortDescription category categoryId subCategory links { episodeNumber id seasonId seasonName seriesId seriesTitle title type __typename } seriesId __typename }}',
+ variables: {
+ startTime: date.unix(),
+ endTime: date.add(1, 'd').unix(),
+ language: 'fr',
+ options: { channelIds: [channel.site_id] }
+ }
+ }
+ }
+ },
+ parser: function ({ content, date, channel }) {
+ const programs = []
+ const items = parseItems(content)
+ items.forEach(item => {
+ programs.push({
+ title: item.title,
+ description: item.description,
+ icon: parseIcon(item),
+ category: parseCategory(item),
+ start: dayjs.unix(item.startTime),
+ stop: dayjs.unix(item.endTime)
+ })
+ })
+
+ return programs
+ },
+ async channels() {
+ const query = {
+ operationName: 'getPlayableChannels',
+ variables: { language: 'fr', id: '0' },
+ query:
+ 'query getPlayableChannels($language: String!, $queryParams: ChannelQueryParams, $id: String) { playableChannels(language: $language, queryParams: $queryParams, id: $id) { id name language radio }}'
+ }
+ const data = await axios
+ .post(`https://api.proximusmwc.be/v2/graphql`, query)
+ .then(r => r.data)
+ .catch(console.log)
+
+ const channels = []
+ for (let item of data.data.playableChannels) {
+ if (item.radio) continue
+ channels.push({
+ lang: item.language,
+ site_id: item.id,
+ name: item.name
+ })
+ }
+
+ return channels
+ }
+}
+
+function parseCategory(item) {
+ return item.category ? item.category.replace(/^C\./, '') : null
+}
+
+function parseIcon(item) {
+ return item.image[0] ? item.image[0].url : null
+}
+
+function parseItems(content) {
+ const data = JSON.parse(content)
+ if (!data || !data.data || !Array.isArray(data.data.schedulesByInterval)) return []
+
+ return data.data.schedulesByInterval
+}
diff --git a/sites/proximusmwc.be/proximusmwc.be.test.js b/sites/proximusmwc.be/proximusmwc.be.test.js
new file mode 100644
index 00000000..6a3498d8
--- /dev/null
+++ b/sites/proximusmwc.be/proximusmwc.be.test.js
@@ -0,0 +1,68 @@
+// npm run channels:parse -- --config=./sites/proximusmwc.be/proximusmwc.be.config.js --output=./sites/proximusmwc.be/proximusmwc.be_be.channels.xml
+// npx epg-grabber --config=sites/proximusmwc.be/proximusmwc.be.config.js --channels=sites/proximusmwc.be/proximusmwc.be_be.channels.xml --output=guide.xml --days=2
+
+const { parser, url, request } = require('./proximusmwc.be.config.js')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+const customParseFormat = require('dayjs/plugin/customParseFormat')
+dayjs.extend(customParseFormat)
+dayjs.extend(utc)
+
+const date = dayjs.utc('2022-03-04', 'YYYY-MM-DD').startOf('d')
+const channel = {
+ site_id: 'UID0024',
+ xmltv_id: 'DasErste.de'
+}
+
+it('can generate valid url', () => {
+ expect(url).toBe('https://api.proximusmwc.be/v2/graphql')
+})
+
+it('can generate valid request headers', () => {
+ expect(request.headers).toMatchObject({
+ 'Content-Type': 'application/json'
+ })
+})
+
+it('can generate valid request data', () => {
+ expect(request.data({ channel, date })).toMatchObject({
+ query:
+ 'query ($language: String!, $startTime: Int!, $endTime: Int!, $options: SchedulesByIntervalOptions) { schedulesByInterval(language: $language, startTime: $startTime, endTime: $endTime, options: $options) { trailId programReferenceNumber channelId title category startTime endTime image { key url __typename } parentalRating detailUrl grouped description shortDescription category categoryId subCategory links { episodeNumber id seasonId seasonName seriesId seriesTitle title type __typename } seriesId __typename }}',
+ variables: {
+ endTime: 1646438400,
+ language: 'fr',
+ options: { channelIds: ['UID0024'] },
+ startTime: 1646352000
+ }
+ })
+})
+
+it('can parse response', () => {
+ const content = `{"data":{"schedulesByInterval":[{"trailId":"UID0024_202202225537","programReferenceNumber":"107504040014","channelId":"UID0024","title":"Der Bozen-Krimi","category":"C.Magazine","startTime":1646350800,"endTime":1646356200,"description":"Chiara Schoras alias \\"Capo\\" Sonja Schwarz muss im 14. Bozen-Krimi nicht nur einen widersprüchlichen Mordfall aufklären, sondern auch ein Geheimnis ans Licht bringen, das zwei Familien auf schmerzhafte Weise untrennbar verbindet.","image":[{"key":"source","url":"https://experience-cache.proximustv.be:443/posterserver/poster/EPG/250_250_BF6BF77FC28F72FA23EAEA6CAAE98B60.jpg","__typename":"Image"},{"key":"custom","url":"https://experience-cache.proximustv.be:443/posterserver/poster/EPG/w-%width%_h-%height%/250_250_BF6BF77FC28F72FA23EAEA6CAAE98B60.jpg","__typename":"Image"}]}]}}`
+ const result = parser({ content, channel, date }).map(p => {
+ p.start = p.start.toJSON()
+ p.stop = p.stop.toJSON()
+ return p
+ })
+
+ expect(result).toMatchObject([
+ {
+ start: '2022-03-03T23:40:00.000Z',
+ stop: '2022-03-04T01:10:00.000Z',
+ title: `Der Bozen-Krimi`,
+ description:
+ 'Chiara Schoras alias "Capo" Sonja Schwarz muss im 14. Bozen-Krimi nicht nur einen widersprüchlichen Mordfall aufklären, sondern auch ein Geheimnis ans Licht bringen, das zwei Familien auf schmerzhafte Weise untrennbar verbindet.',
+ category: 'Magazine',
+ icon: 'https://experience-cache.proximustv.be:443/posterserver/poster/EPG/250_250_BF6BF77FC28F72FA23EAEA6CAAE98B60.jpg'
+ }
+ ])
+})
+
+it('can handle empty guide', () => {
+ const result = parser({
+ date,
+ channel,
+ content: `{"data":{"schedulesByInterval":[]}}`
+ })
+ expect(result).toMatchObject([])
+})
diff --git a/sites/proximusmwc.be/proximusmwc.be_be.channels.xml b/sites/proximusmwc.be/proximusmwc.be_be.channels.xml
new file mode 100644
index 00000000..99db6a44
--- /dev/null
+++ b/sites/proximusmwc.be/proximusmwc.be_be.channels.xml
@@ -0,0 +1,219 @@
+
+
+
+ BRF TV HD
+ Das Erste
+ RTL
+ ZDF
+ BBC Ent
+ BBC First
+ BBC One
+ BBC Two
+ BBC World
+ CNN
+ eSportsONE
+ Euronews E
+ Extreme
+ FashionTV
+ MVTV
+ MTV Live HD
+ Penthouse Gold
+ TVE Int
+ 13è Rue HD
+ 2M Monde
+ AB3
+ ABXPLO HD
+ Action
+ Al Aoula
+ Al Jazeera
+ Animaux
+ Antenne Centre HD
+ Arte
+ AUTOMOTO
+ Be1
+ Be Ciné
+ Bel RTL
+ Be Séries
+ Boomerang F
+ Bouké HD
+ bx1
+ C8
+ Canal J
+ Canal Zoom
+ Cartoon F
+ Ciné+Classic
+ Ciné+Frisson
+ Ciné+Premier
+ ClubRTL
+ Comedy Central F
+ Crime District
+ Discovery F
+ Disn Ch HD F
+ Disn Jr F
+ Disney+
+ Dobbit TV F
+ Dorcel XXX
+ E! F
+ Eleven Pro League 1 (FR)
+ Eleven Pro League 2 (FR)
+ Eleven Pro League 3 (FR)
+ ES1 F
+ ES2 F
+ ES3 F
+ Euronews F
+ Eurosp F
+ Eurosp2 F
+ France 2
+ France 24 F
+ France 3
+ France 4
+ France 5
+ Game One
+ Gulli HD
+ Histoire
+ KTO
+ LCI
+ LN24
+ Maghreb TV
+ Mangas
+ MaTélé
+ Melody.tv
+ MezzoLive
+ MTV F
+ MTV Hits
+ Museum TV
+ MyZen.tv
+ NGC F
+ NGC Wild F
+ nick F
+ nick jr F
+ No Télé HD
+ Paramount Channel
+ PickxLive F HD
+ Pickx+ F
+ Pickx+ Sports 10 F HD
+ Pickx+ Sports 1 F
+ Pickx+ Sports 3 F
+ Pickx+ Sports 4 F
+ Pickx+ Sports 5 F
+ Pickx+ Sports 6 F
+ Pickx+ Sports 7 F
+ Pickx+ Sports 8 F HD
+ Pickx+ Sports 9 F HD
+ Pink
+ PlugRTL
+ ContactV
+ RFM TV
+ La Trois
+ La Une
+ RTC Liège HD
+ RTL-TVI
+ Sc et Vie TV
+ ST100TV F
+ SyFy F
+ TCM cinéma
+ Télé MB HD
+ Télé Sambre
+ TF1
+ Tiji
+ TIPIK
+ TIPIK vision
+ TMC HD
+ TraceUrban
+ TREK
+ TV5 Monde
+ TV Breizh
+ TV Com
+ TV Lux
+ Ushuaïa
+ Vedia
+ Mediaset
+ RAI Uno
+ RAI Due
+ RAI Tre
+ Animal Pl
+ ATV
+ AVS HD
+ AVS Gent
+ Baby TV N
+ Boomerang N
+ BRUZZ HD
+ Canvas
+ Cartoon N
+ Comedy Central N
+ Discovery N
+ Disc Science
+ Disn Ch N
+ DisnJr N
+ Dobbit TV N
+ Dusk
+ Eclips
+ één
+ E! N
+ Eleven Pro League 1 (NL)
+ Eleven Pro League 2 (NL)
+ Eleven Pro League 3 (NL)
+ ES1 N
+ ES2 N
+ ES3 N
+ Eurosp N
+ Eurosp2 N
+ Focus TV HD
+ FOX
+ History
+ Insight TV
+ Inv Disc
+ Kanaal Z
+ Ketnet
+ Ment TV
+ MTV 80s
+ MTV N
+ NGC N
+ NGC Wild N
+ nick N
+ nick jr N
+ nick Toons
+ Njam! HD
+ NPO 1
+ NPO 2
+ NPO 3
+ OUT tv
+ Passie XXX
+ Pebble TV
+ PickxLive N HD
+ Pickx+ N
+ Pickx+ Sports 10 N
+ Pickx+ Sports 1 N
+ Pickx+ Sports 2 N
+ Pickx+ Sports 3 N
+ Pickx+ Sports 4 N
+ Pickx+ Sports 5 N
+ Pickx+ Sports 6 N
+ Pickx+ Sports 7 N
+ Pickx+ Sports 8 N
+ Pickx+ Sports 9 N
+ Plattelands
+ Play4
+ Play5
+ Play6
+ Play7 HD
+ Ring TV HD
+ ROB TV
+ RTV Kempen HD
+ RTV Mech HD
+ Sport 10
+ Classica
+ ST100 Hits
+ ST100TV N
+ TLC
+ TVLimbC
+ TV Oost
+ Vlaamsparlement.tv
+ VTM
+ VTM 2
+ VTM 3
+ VTM 4
+ VTM Gold
+ VTM Kids
+
+
diff --git a/sites/tv.blue.ch/tv.blue.ch_ch.channels.xml b/sites/tv.blue.ch/tv.blue.ch_ch.channels.xml
index 71c3a54e..96284754 100644
--- a/sites/tv.blue.ch/tv.blue.ch_ch.channels.xml
+++ b/sites/tv.blue.ch/tv.blue.ch_ch.channels.xml
@@ -244,7 +244,7 @@
Great! Movies Action
Great! Movies Classic
I24 News English
- Insight HD
+ Insight HD
Insight UHD
ITV 2
ITV 3
diff --git a/sites/tvtv.us/tvtv.us_us.channels.xml b/sites/tvtv.us/tvtv.us_us.channels.xml
index 71ef366c..08753819 100644
--- a/sites/tvtv.us/tvtv.us_us.channels.xml
+++ b/sites/tvtv.us/tvtv.us_us.channels.xml
@@ -1718,5 +1718,14 @@
Univision East (National Feed)
Univision West (National Feed)
Unimas West (National Feed)
+ Dust
+ Entertainment Tonight Live
+ Game Show Central
+ Game Show Central (Pluto)
+ IFC Film Picks
+ World Poker Tour
+ World Poker Tour (Pluto)
+ Totally Turtles
+ LiveNow From FOX
diff --git a/sites/vidio.com/vidio.com_id.channels.xml b/sites/vidio.com/vidio.com_id.channels.xml
index 5eb49687..ab65c892 100644
--- a/sites/vidio.com/vidio.com_id.channels.xml
+++ b/sites/vidio.com/vidio.com_id.channels.xml
@@ -24,7 +24,7 @@
DW English
EuroNews English
Fashion TV Asia
- Fashion TV L'Original
+ Fashion TV L'Original
Fashion TV Midnite Secret
Hip Hip Horee!
Horee!