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éunion119https://iptv-org.github.io/epg/guides/re/canalplus-reunion.com.epg.xmlcanalplus-reunion.com 🇧🇱 Saint Barthélemy128https://iptv-org.github.io/epg/guides/bl/canalplus-caraibes.com.epg.xmlcanalplus-caraibes.com 🇲🇫 Saint Martin128https://iptv-org.github.io/epg/guides/mf/canalplus-caraibes.com.epg.xmlcanalplus-caraibes.com - 🇸🇦 Saudi Arabia98https://iptv-org.github.io/epg/guides/sa-ar/osn.com.epg.xmlosn.com + 🇸🇦 Saudi Arabia98https://iptv-org.github.io/epg/guides/sa-ar/osn.com.epg.xmlosn.com 98https://iptv-org.github.io/epg/guides/sa-en/osn.com.epg.xmlosn.com + 5https://iptv-org.github.io/epg/guides/sa/artonline.tv.epg.xmlartonline.tv 🇸🇳 Senegal242https://iptv-org.github.io/epg/guides/sn/canalplus-afrique.com.epg.xmlcanalplus-afrique.com 125https://iptv-org.github.io/epg/guides/sn/dstv.com.epg.xmldstv.com 🇷🇸 Serbia357https://iptv-org.github.io/epg/guides/rs/mts.rs.epg.xmlmts.rs @@ -231,7 +232,7 @@ To load a program guide, all you need to do is copy the link to one or more of t 99https://iptv-org.github.io/epg/guides/ae-en/osn.com.epg.xmlosn.com 🇬🇧 United Kingdom258https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xmlsky.com 97https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xmlontvtonight.com - 🇺🇸 United States1714https://iptv-org.github.io/epg/guides/us/tvtv.us.epg.xmltvtv.us + 🇺🇸 United States1717https://iptv-org.github.io/epg/guides/us/tvtv.us.epg.xmltvtv.us 410https://iptv-org.github.io/epg/guides/us/directv.com.epg.xmldirectv.com 88https://iptv-org.github.io/epg/guides/us/tvguide.com.epg.xmltvguide.com 22https://iptv-org.github.io/epg/guides/us/gatotv.com.epg.xmlgatotv.com 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!