diff --git a/.github/workflows/i.mjh.nz.yml b/.github/workflows/i.mjh.nz.yml
new file mode 100644
index 00000000..5b2fd0ba
--- /dev/null
+++ b/.github/workflows/i.mjh.nz.yml
@@ -0,0 +1,17 @@
+name: i.mjh.nz
+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/package-lock.json b/package-lock.json
index 8c3ac996..5204801e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,7 +14,7 @@
"commander": "^8.2.0",
"csv-parser": "^3.0.0",
"dayjs": "^1.10.8",
- "epg-grabber": "^0.25.4",
+ "epg-grabber": "^0.26.0",
"epg-parser": "^0.1.6",
"form-data": "^4.0.0",
"fs-extra": "^10.0.1",
@@ -26,7 +26,7 @@
"lodash": "^4.17.21",
"markdown-include": "^0.4.3",
"mockdate": "^3.0.5",
- "nedb-promises": "^6.0.3",
+ "nedb-promises": "^4.1.5",
"node-cleanup": "^2.1.2",
"node-gzip": "^1.1.2",
"parse-duration": "^1.0.0",
@@ -867,26 +867,6 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
- "node_modules/@seald-io/binary-search-tree": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@seald-io/binary-search-tree/-/binary-search-tree-1.0.2.tgz",
- "integrity": "sha512-+pYGvPFAk7wUR+ONMOlc6A+LUN4kOCFwyPLjyaeS7wVibADPHWYJNYsNtyIAwjF1AXQkuaXElnIc4XjKt55QZA=="
- },
- "node_modules/@seald-io/nedb": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/@seald-io/nedb/-/nedb-2.2.2.tgz",
- "integrity": "sha512-z91J3pem4ENzHuu9BilOSdlGL2S14OQYePPdvBcPHgHr+s51VIUwQARcOjx21KvtkA27vEpgPqzrVKh7nSlIfw==",
- "dependencies": {
- "@seald-io/binary-search-tree": "^1.0.2",
- "async": "0.2.10",
- "localforage": "^1.9.0"
- }
- },
- "node_modules/@seald-io/nedb/node_modules/async": {
- "version": "0.2.10",
- "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
- "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
- },
"node_modules/@sindresorhus/is": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz",
@@ -1270,16 +1250,17 @@
"follow-redirects": "^1.14.0"
}
},
- "node_modules/axios-cache-adapter": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/axios-cache-adapter/-/axios-cache-adapter-2.7.3.tgz",
- "integrity": "sha512-A+ZKJ9lhpjthOEp4Z3QR/a9xC4du1ALaAsejgRGrH9ef6kSDxdFrhRpulqsh9khsEnwXxGfgpUuDp1YXMNMEiQ==",
+ "node_modules/axios-cache-interceptor": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-0.10.3.tgz",
+ "integrity": "sha512-oyHlhmA6zzZJDk/ZMPWPNmO3z8gBU3mWIqAZy+GIUsvwpmwyPlC2XvZ3PTOZHgpWI2kEocMUhk3+w9VwMXfZ4w==",
"dependencies": {
- "cache-control-esm": "1.0.0",
- "md5": "^2.2.1"
+ "cache-parser": "^1.2.4",
+ "fast-defer": "^1.1.7",
+ "object-code": "^1.2.2"
},
- "peerDependencies": {
- "axios": "~0.21.1"
+ "funding": {
+ "url": "https://github.com/ArthurFiorette/axios-cache-interceptor?sponsor=1"
}
},
"node_modules/axios-cookiejar-support": {
@@ -1438,6 +1419,14 @@
}
]
},
+ "node_modules/binary-search-tree": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/binary-search-tree/-/binary-search-tree-0.2.5.tgz",
+ "integrity": "sha1-fbs7IQ/coIJFDa0jNMMErzm9x4Q=",
+ "dependencies": {
+ "underscore": "~1.4.4"
+ }
+ },
"node_modules/bindings": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz",
@@ -1541,10 +1530,10 @@
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
- "node_modules/cache-control-esm": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/cache-control-esm/-/cache-control-esm-1.0.0.tgz",
- "integrity": "sha512-Fa3UV4+eIk4EOih8FTV6EEsVKO0W5XWtNs6FC3InTfVz+EjurjPfDXY5wZDo/lxjDxg5RjNcurLyxEJBcEUx9g=="
+ "node_modules/cache-parser": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/cache-parser/-/cache-parser-1.2.4.tgz",
+ "integrity": "sha512-O0KwuHuJnbHUrghHi2kGp0SxnWSIBXTYt7M8WVhW0kbPRUNUKoE/Of6e1rRD6AAxmfxFunKnt90yEK09D+sc5g=="
},
"node_modules/cacheable-lookup": {
"version": "5.0.4",
@@ -1644,14 +1633,6 @@
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
},
- "node_modules/charenc": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
- "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=",
- "engines": {
- "node": "*"
- }
- },
"node_modules/cheerio": {
"version": "1.0.0-rc.10",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
@@ -1906,14 +1887,6 @@
"node": ">= 8"
}
},
- "node_modules/crypt": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
- "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=",
- "engines": {
- "node": "*"
- }
- },
"node_modules/css-select": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
@@ -2252,12 +2225,12 @@
}
},
"node_modules/epg-grabber": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.25.4.tgz",
- "integrity": "sha512-fQh04OaNY+LsxtMerT3tOMfcaiMe0f5ZaXjjcm2TnnB4sPN0+KkSmX/uy24NErggBgV+O0jyl6+zulARciojtA==",
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.26.0.tgz",
+ "integrity": "sha512-QOJsPMhWi+s3jcx0U8f7ZlQfBgsaP56w1JdSascZ92yFiR2bvcdEFaAJuzAgKoQiicoXDKdzoK5r18mjLg05KQ==",
"dependencies": {
"axios": "^0.21.1",
- "axios-cache-adapter": "^2.7.3",
+ "axios-cache-interceptor": "^0.10.3",
"axios-cookiejar-support": "^1.0.1",
"axios-mock-adapter": "^1.20.0",
"commander": "^7.1.0",
@@ -2446,6 +2419,11 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
+ "node_modules/fast-defer": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/fast-defer/-/fast-defer-1.1.7.tgz",
+ "integrity": "sha512-tJ01ulDWT2WhqxMKS20nXX6wyX2iInBYpbN3GO7yjKwXMY4qvkdBRxak9IFwBLlFDESox+SwSvqMCZDfe1tqeg=="
+ },
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -4112,21 +4090,6 @@
"markdown-include": "bin/cli.js"
}
},
- "node_modules/md5": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
- "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
- "dependencies": {
- "charenc": "0.0.2",
- "crypt": "0.0.2",
- "is-buffer": "~1.1.6"
- }
- },
- "node_modules/md5/node_modules/is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
- },
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -4253,14 +4216,31 @@
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
},
- "node_modules/nedb-promises": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/nedb-promises/-/nedb-promises-6.0.3.tgz",
- "integrity": "sha512-pd0N6EsIPhXsfqdLcBJGig1FoTdV8wtuiXB7rBUqycJdUSA6wdI5BlkwEAjDBWIwZc4+xqBHRLtuAB7/bjS+rg==",
+ "node_modules/nedb": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/nedb/-/nedb-1.8.0.tgz",
+ "integrity": "sha1-DjUCzYLABNU1WkPJ5VV3vXvZHYg=",
"dependencies": {
- "@seald-io/nedb": "^2.2.0"
+ "async": "0.2.10",
+ "binary-search-tree": "0.2.5",
+ "localforage": "^1.3.0",
+ "mkdirp": "~0.5.1",
+ "underscore": "~1.4.4"
}
},
+ "node_modules/nedb-promises": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/nedb-promises/-/nedb-promises-4.1.5.tgz",
+ "integrity": "sha512-mnzB7y5tE1MXGDYurFNJeX2Kh4oEyH88uBCXOm4jDXiu6dAALDg8+urIuSuo15oo8spMbWzDsnD03KHKyuBjNw==",
+ "dependencies": {
+ "nedb": "^1.8.0"
+ }
+ },
+ "node_modules/nedb/node_modules/async": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
+ "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
+ },
"node_modules/needle": {
"version": "2.9.1",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz",
@@ -4466,6 +4446,11 @@
"node": ">=0.10.0"
}
},
+ "node_modules/object-code": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/object-code/-/object-code-1.2.2.tgz",
+ "integrity": "sha512-ZSbEQdei4ElzuDM4BmazKSwINacocBf3/8rte25aNqXzvT/8dSaNVY9egsjAaBL/UhW55JNxAvXOKPIsL2MwWQ=="
+ },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -5644,6 +5629,11 @@
"node": ">=4.2.0"
}
},
+ "node_modules/underscore": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz",
+ "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ="
+ },
"node_modules/universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
@@ -6584,28 +6574,6 @@
"chalk": "^4.0.0"
}
},
- "@seald-io/binary-search-tree": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@seald-io/binary-search-tree/-/binary-search-tree-1.0.2.tgz",
- "integrity": "sha512-+pYGvPFAk7wUR+ONMOlc6A+LUN4kOCFwyPLjyaeS7wVibADPHWYJNYsNtyIAwjF1AXQkuaXElnIc4XjKt55QZA=="
- },
- "@seald-io/nedb": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/@seald-io/nedb/-/nedb-2.2.2.tgz",
- "integrity": "sha512-z91J3pem4ENzHuu9BilOSdlGL2S14OQYePPdvBcPHgHr+s51VIUwQARcOjx21KvtkA27vEpgPqzrVKh7nSlIfw==",
- "requires": {
- "@seald-io/binary-search-tree": "^1.0.2",
- "async": "0.2.10",
- "localforage": "^1.9.0"
- },
- "dependencies": {
- "async": {
- "version": "0.2.10",
- "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
- "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
- }
- }
- },
"@sindresorhus/is": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz",
@@ -6945,13 +6913,14 @@
"follow-redirects": "^1.14.0"
}
},
- "axios-cache-adapter": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/axios-cache-adapter/-/axios-cache-adapter-2.7.3.tgz",
- "integrity": "sha512-A+ZKJ9lhpjthOEp4Z3QR/a9xC4du1ALaAsejgRGrH9ef6kSDxdFrhRpulqsh9khsEnwXxGfgpUuDp1YXMNMEiQ==",
+ "axios-cache-interceptor": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/axios-cache-interceptor/-/axios-cache-interceptor-0.10.3.tgz",
+ "integrity": "sha512-oyHlhmA6zzZJDk/ZMPWPNmO3z8gBU3mWIqAZy+GIUsvwpmwyPlC2XvZ3PTOZHgpWI2kEocMUhk3+w9VwMXfZ4w==",
"requires": {
- "cache-control-esm": "1.0.0",
- "md5": "^2.2.1"
+ "cache-parser": "^1.2.4",
+ "fast-defer": "^1.1.7",
+ "object-code": "^1.2.2"
}
},
"axios-cookiejar-support": {
@@ -7063,6 +7032,14 @@
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
+ "binary-search-tree": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/binary-search-tree/-/binary-search-tree-0.2.5.tgz",
+ "integrity": "sha1-fbs7IQ/coIJFDa0jNMMErzm9x4Q=",
+ "requires": {
+ "underscore": "~1.4.4"
+ }
+ },
"bindings": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz",
@@ -7139,10 +7116,10 @@
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
- "cache-control-esm": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/cache-control-esm/-/cache-control-esm-1.0.0.tgz",
- "integrity": "sha512-Fa3UV4+eIk4EOih8FTV6EEsVKO0W5XWtNs6FC3InTfVz+EjurjPfDXY5wZDo/lxjDxg5RjNcurLyxEJBcEUx9g=="
+ "cache-parser": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/cache-parser/-/cache-parser-1.2.4.tgz",
+ "integrity": "sha512-O0KwuHuJnbHUrghHi2kGp0SxnWSIBXTYt7M8WVhW0kbPRUNUKoE/Of6e1rRD6AAxmfxFunKnt90yEK09D+sc5g=="
},
"cacheable-lookup": {
"version": "5.0.4",
@@ -7207,11 +7184,6 @@
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
},
- "charenc": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
- "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc="
- },
"cheerio": {
"version": "1.0.0-rc.10",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
@@ -7422,11 +7394,6 @@
"which": "^2.0.1"
}
},
- "crypt": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
- "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs="
- },
"css-select": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
@@ -7670,12 +7637,12 @@
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
},
"epg-grabber": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.25.4.tgz",
- "integrity": "sha512-fQh04OaNY+LsxtMerT3tOMfcaiMe0f5ZaXjjcm2TnnB4sPN0+KkSmX/uy24NErggBgV+O0jyl6+zulARciojtA==",
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.26.0.tgz",
+ "integrity": "sha512-QOJsPMhWi+s3jcx0U8f7ZlQfBgsaP56w1JdSascZ92yFiR2bvcdEFaAJuzAgKoQiicoXDKdzoK5r18mjLg05KQ==",
"requires": {
"axios": "^0.21.1",
- "axios-cache-adapter": "^2.7.3",
+ "axios-cache-interceptor": "^0.10.3",
"axios-cookiejar-support": "^1.0.1",
"axios-mock-adapter": "^1.20.0",
"commander": "^7.1.0",
@@ -7812,6 +7779,11 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
+ "fast-defer": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/fast-defer/-/fast-defer-1.1.7.tgz",
+ "integrity": "sha512-tJ01ulDWT2WhqxMKS20nXX6wyX2iInBYpbN3GO7yjKwXMY4qvkdBRxak9IFwBLlFDESox+SwSvqMCZDfe1tqeg=="
+ },
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -9056,23 +9028,6 @@
"q": "^1.2.0"
}
},
- "md5": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
- "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
- "requires": {
- "charenc": "0.0.2",
- "crypt": "0.0.2",
- "is-buffer": "~1.1.6"
- },
- "dependencies": {
- "is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
- }
- }
- },
"merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -9180,12 +9135,31 @@
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
},
- "nedb-promises": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/nedb-promises/-/nedb-promises-6.0.3.tgz",
- "integrity": "sha512-pd0N6EsIPhXsfqdLcBJGig1FoTdV8wtuiXB7rBUqycJdUSA6wdI5BlkwEAjDBWIwZc4+xqBHRLtuAB7/bjS+rg==",
+ "nedb": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/nedb/-/nedb-1.8.0.tgz",
+ "integrity": "sha1-DjUCzYLABNU1WkPJ5VV3vXvZHYg=",
"requires": {
- "@seald-io/nedb": "^2.2.0"
+ "async": "0.2.10",
+ "binary-search-tree": "0.2.5",
+ "localforage": "^1.3.0",
+ "mkdirp": "~0.5.1",
+ "underscore": "~1.4.4"
+ },
+ "dependencies": {
+ "async": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
+ "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
+ }
+ }
+ },
+ "nedb-promises": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/nedb-promises/-/nedb-promises-4.1.5.tgz",
+ "integrity": "sha512-mnzB7y5tE1MXGDYurFNJeX2Kh4oEyH88uBCXOm4jDXiu6dAALDg8+urIuSuo15oo8spMbWzDsnD03KHKyuBjNw==",
+ "requires": {
+ "nedb": "^1.8.0"
}
},
"needle": {
@@ -9354,6 +9328,11 @@
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
+ "object-code": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/object-code/-/object-code-1.2.2.tgz",
+ "integrity": "sha512-ZSbEQdei4ElzuDM4BmazKSwINacocBf3/8rte25aNqXzvT/8dSaNVY9egsjAaBL/UhW55JNxAvXOKPIsL2MwWQ=="
+ },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -10215,6 +10194,11 @@
"optional": true,
"peer": true
},
+ "underscore": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz",
+ "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ="
+ },
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
diff --git a/package.json b/package.json
index 958e422c..e83b1f13 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,7 @@
"commander": "^8.2.0",
"csv-parser": "^3.0.0",
"dayjs": "^1.10.8",
- "epg-grabber": "^0.25.4",
+ "epg-grabber": "^0.26.0",
"epg-parser": "^0.1.6",
"form-data": "^4.0.0",
"fs-extra": "^10.0.1",
@@ -48,7 +48,7 @@
"lodash": "^4.17.21",
"markdown-include": "^0.4.3",
"mockdate": "^3.0.5",
- "nedb-promises": "^6.0.3",
+ "nedb-promises": "^4.1.5",
"node-cleanup": "^2.1.2",
"node-gzip": "^1.1.2",
"parse-duration": "^1.0.0",
diff --git a/sites/i.mjh.nz/i.mjh.nz.config.js b/sites/i.mjh.nz/i.mjh.nz.config.js
new file mode 100644
index 00000000..a58f4f16
--- /dev/null
+++ b/sites/i.mjh.nz/i.mjh.nz.config.js
@@ -0,0 +1,97 @@
+const dayjs = require('dayjs')
+const axios = require('axios')
+const parser = require('epg-parser')
+const isBetween = require('dayjs/plugin/isBetween')
+const customParseFormat = require('dayjs/plugin/customParseFormat')
+
+dayjs.extend(isBetween)
+dayjs.extend(customParseFormat)
+
+module.exports = {
+ site: 'i.mjh.nz',
+ request: {
+ cache: {
+ ttl: 6 * 60 * 60 * 1000 // 6h
+ }
+ },
+ url: function ({ channel }) {
+ const [source] = channel.site_id.split('#')
+
+ return `https://raw.githubusercontent.com/matthuisman/i.mjh.nz/master/${source}.xml`
+ },
+ parser: function ({ content, channel, date, cached }) {
+ let programs = []
+ const items = parseItems(content, channel, date)
+ items.forEach(item => {
+ programs.push({
+ title: parseTitle(item, channel),
+ description: parseDescription(item, channel),
+ category: parseCategory(item, channel),
+ start: parseStart(item),
+ stop: parseStop(item)
+ })
+ })
+
+ return programs
+ },
+ async channels({ service, region, lang = 'en' }) {
+ const data = await axios
+ .get(`https://i.mjh.nz/${service}/app.json`)
+ .then(r => r.data)
+ .catch(console.log)
+
+ const channels = []
+ const items = !region ? data.channels : data.regions[region].channels
+ region = region || 'all'
+ const path = `${service}/${region}`
+ for (let id in items) {
+ const channel = items[id]
+ channels.push({
+ lang,
+ site_id: `${path}#${id}`,
+ name: channel.name
+ })
+ }
+
+ return channels
+ }
+}
+
+function parseTitle(item, channel) {
+ return item.title.length ? item.title[0].value : null
+}
+
+function parseDescription(item, channel) {
+ return item.desc.length ? item.desc[0].value : null
+}
+
+function parseCategory(item, channel) {
+ const category = item.category.length ? item.category[0].value : ''
+
+ return category.split(/\s\&\;\s/g).filter(c => c)
+}
+
+function parseStart(item) {
+ return dayjs(item.start, 'YYYYMMDDHHmmss ZZ')
+}
+
+function parseStop(item) {
+ return dayjs(item.stop, 'YYYYMMDDHHmmss ZZ')
+}
+
+function parseItems(content, channel, date) {
+ try {
+ const curr_day = date
+ const next_day = date.add(1, 'd')
+ const [_, site_id] = channel.site_id.split('#')
+ const data = parser.parse(content)
+ if (!data || !Array.isArray(data.programs)) return []
+
+ return data.programs.filter(
+ p =>
+ p.channel === site_id && dayjs(p.start, 'YYYYMMDDHHmmss ZZ').isBetween(curr_day, next_day)
+ )
+ } catch (error) {
+ return []
+ }
+}
diff --git a/sites/i.mjh.nz/i.mjh.nz.test.js b/sites/i.mjh.nz/i.mjh.nz.test.js
new file mode 100644
index 00000000..eec79db1
--- /dev/null
+++ b/sites/i.mjh.nz/i.mjh.nz.test.js
@@ -0,0 +1,53 @@
+// npm run channels:parse -- --config=./sites/i.mjh.nz/i.mjh.nz.config.js --output=./sites/i.mjh.nz/i.mjh.nz_us-pluto.channels.xml --set=service:PlutoTV --set=region:us
+// npm run channels:parse -- --config=./sites/i.mjh.nz/i.mjh.nz.config.js --output=./sites/i.mjh.nz/i.mjh.nz_us-stirr.channels.xml --set=service:Stirr
+// npx epg-grabber --config=sites/i.mjh.nz/i.mjh.nz.config.js --channels=sites/i.mjh.nz/i.mjh.nz_us-pluto.channels.xml --output=guide.xml --days=2
+// npx epg-grabber --config=sites/i.mjh.nz/i.mjh.nz.config.js --channels=sites/i.mjh.nz/i.mjh.nz_us-stirr.channels.xml --output=guide.xml --days=2
+
+const { parser, url } = require('./i.mjh.nz.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-05-03', 'YYYY-MM-DD').startOf('d')
+const channel = {
+ site_id: 'PlutoTV/us#51c75f7bb6f26ba1cd00002f',
+ xmltv_id: 'LittleStarsUniverse.us',
+ lang: 'en'
+}
+
+it('can generate valid url', () => {
+ expect(url({ channel })).toBe(
+ 'https://raw.githubusercontent.com/matthuisman/i.mjh.nz/master/PlutoTV/us.xml'
+ )
+})
+
+it('can parse response', () => {
+ const content = ` Little Stars Universe Barney and Friends Baby Bop forgets to say "please" and "thank you". Riff shares his dream of becoming an inventor. Children & Family Barney and Friends Baby Bop forgets to say "please" and "thank you". Riff shares his dream of becoming an inventor. Children & Family `
+ 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-05-03T10:49:22.000Z',
+ stop: '2022-05-03T11:21:22.000Z',
+ title: 'Barney and Friends',
+ description:
+ 'Baby Bop forgets to say "please" and "thank you". Riff shares his dream of becoming an inventor.',
+ category: ['Children', 'Family']
+ }
+ ])
+})
+
+it('can handle empty guide', () => {
+ const result = parser({
+ content: `404: Not Found`,
+ channel,
+ date
+ })
+ expect(result).toMatchObject([])
+})
diff --git a/sites/i.mjh.nz/i.mjh.nz_us-pluto.channels.xml b/sites/i.mjh.nz/i.mjh.nz_us-pluto.channels.xml
new file mode 100644
index 00000000..23b6390b
--- /dev/null
+++ b/sites/i.mjh.nz/i.mjh.nz_us-pluto.channels.xml
@@ -0,0 +1,334 @@
+
+
+
+ 48 Hours
+ 70s Cinema
+ 80s Rewind
+ 90210
+ 90s Throwback
+ Acapulco Shore
+ All Reality by WE tv
+ Always Funny Videos
+ Amantes del romance
+ America's Test Kitchen
+ America's Voice News
+ Anime All Day
+ Antiques Roadshow UK
+ Antiques Road Trip
+ Awesomeness TV
+ Baby Shark TV
+ Badass novelas
+ Bar Rescue
+ Baywatch
+ BBC Food
+ BBC Home
+ BBC Kids
+ Bebecito Bum y sus amigos
+ beIN SPORTS XTRA en español
+ beIN SPORTS XTRA
+ Bellator MMA
+ Best of Dr. Phil
+ Best of The Drew Barrymore Show
+ BET Her
+ BET Pluto TV
+ Beverly Hillbillies
+ Black Cinema
+ Black Classics
+ Black Ink Crew
+ Black Throwbacks
+ Blaze Live
+ Bloomberg TV
+ BNC GO
+ Bounce XL
+ BritBox Mysteries
+ British Comedy
+ British Drama
+ BUZZR
+ Cats 24/7
+ CBS News
+ CBS News Baltimore
+ CBS News Bay Area
+ CBS News Boston
+ CBS News Chicago
+ CBS News Colorado
+ CBS News DFW
+ CBS News Los Angeles
+ CBS News Miami
+ CBS News Minnesota
+ CBS News New York
+ CBS News Philly
+ CBS News Pittsburgh
+ CBS News Sacramento
+ CBS Sports HQ
+ Cheddar News
+ Cine adrenalina
+ Cine ¡¡jaja!!
+ Cine Premiere
+ Cine terror
+ Cine XOXO
+ Classica
+ Classic Movies Channel
+ Classic Toons TV
+ Classic TV Comedy
+ Classic TV Drama
+ Classic TV: Families
+ CMT Equal Play
+ CMT Pluto TV
+ CNN
+ Cold Case Files
+ Combate World
+ Comedy Central Animation
+ Comedy Central en español
+ Comedy Central Pluto TV
+ COPS
+ Court TV
+ Crime 360
+ Crímenes imperfectos
+ CSI
+ CSI en español
+ Dabl
+ Dallas Cowboy Cheerleaders
+ Dark Shadows
+ Deal or No Deal
+ Degrassi
+ Demand Africa
+ Doctor Who Classic
+ Dogs 24/7
+ Dog the Bounty Hunter
+ Dora TV
+ Emergencia 911
+ Entre nosotras
+ Estrella News
+ EstrellaTV
+ ET Live
+ Euronews
+ FailArmy
+ Faith TV
+ Family Ties
+ Fear Factor
+ Fight
+ Find Out Why
+ Flicks of Fury
+ Foodies
+ Food TV
+ Forensic Files
+ Forever Kids
+ FOX Sports
+ Funny AF
+ Fuse Beat
+ G4 Select
+ Gameplay: Call of Duty
+ Gameplay: Fortnite
+ Gameplay: Roblox
+ Gameplay: Sports
+ Game Show Central
+ Garfield and Friends
+ GLORY Kickboxing
+ Gordon Ramsay's Hell's Kitchen
+ Grande-ish
+ Gunsmoke
+ Happy Days
+ Heartland
+ Hell's Kitchen en español
+ IGN
+ IMPACT Wrestling
+ Ink Master
+ Investiga
+ Iron Chef
+ Jersey Shore
+ Johnny Carson TV
+ Judge Nosey
+ Julia Child
+ Kartoon Channel!
+ K-Content by CJ ENM
+ Kevin Hart’s LOL! Network
+ Kids Movie Club
+ LEGO Kids TV
+ Little Baby Bum
+ Little Stars Universe
+ Lively Place
+ Live Music Replay
+ Logo Pluto TV
+ Love & Hip Hop
+ Lucha Libre AAA
+ Lupin the 3rd
+ Matlock
+ MAVTV Select
+ Midsomer Murders
+ MinecrafTV
+ Mi obsesión favorita
+ Mission Impossible
+ Misterios sin resolver
+ MLB
+ MLS
+ More TV Drama
+ More TV Sitcoms
+ MST3K
+ MTV Biggest Pop
+ MTV Block Party
+ MTV Dating
+ MTV en español
+ MTV Pluto TV
+ MTV Spankin' New
+ Mundo geek
+ Mundo paranormal
+ Mundo viajero
+ Narcos
+ Narcos en español
+ Naruto
+ Naruto en español
+ Naturescape
+ NBC News NOW
+ News 12 New York
+ Newsmax
+ Newsy
+ NFL Channel
+ Nick en español
+ Nick Jr. en español
+ Nick Jr. Pluto TV
+ Nick Pluto TV
+ Niños por BBC Kids
+ No Parents Allowed
+ Nosey
+ Nosey escándalos
+ Novelas con la abuela
+ Nuestra Visión
+ OAN Plus
+ One Piece
+ Paramount Movie Channel
+ Paramount+ Picks
+ PBR RidePass
+ Pelis y Popcorn
+ People Are Awesome
+ Perry Mason
+ PGA TOUR
+ Pluto TV Action
+ Pluto TV Action Sports
+ Pluto TV Animals
+ Pluto TV Backcountry
+ Pluto TV Best Life
+ Pluto TV Boxing
+ Pluto TV Cars
+ Pluto TV Celebrity
+ Pluto TV Comedy
+ Pluto TV Courtroom
+ Pluto TV Crime Drama
+ Pluto TV Crime Movies
+ Pluto TV Cult Films
+ Pluto TV Documentaries
+ Pluto TV Drama
+ Pluto TV Drama Life
+ Pluto TV Fantastic
+ Pluto TV Gamer
+ Pluto TV Game Shows
+ Pluto TV History
+ Pluto TV Home
+ Pluto TV Horror
+ Pluto TV Lives
+ Pluto TV Love Stories
+ Pluto TV Military
+ Pluto TV News
+ Pluto TV Paranormal
+ Pluto TV Pranks
+ Pluto TV Pro Wrestling
+ Pluto TV Reaction
+ Pluto TV Reality
+ Pluto TV Romance
+ Pluto TV Science
+ Pluto TV Sci-Fi
+ Pluto TV Soaps
+ Pluto TV Sports
+ Pluto TV Spotlight
+ Pluto TV Staff Picks
+ Pluto TV Suspense
+ Pluto TV Terror
+ Pluto TV Thrillers
+ Pluto TV Travel
+ Pluto TV True Crime
+ Pluto TV Vs.
+ Pluto TV Weddings
+ Pluto TV Westerns
+ pocket.watch
+ PokerGo
+ Rainbow Squad
+ Realmadrid tv
+ Rescue 911
+ RiffTrax
+ Ryan and Friends
+ Sala de parejas
+ Séptimo arte
+ Series con Ñ
+ Shout! Factory TV
+ Showtime Selects
+ Skills + Thrills
+ Sky News
+ Slightly Off IFC
+ Slow TV
+ Smithsonian Channel Selects
+ Sony Canal Comedias
+ Sony Canal Escape Perfecto
+ Spike ¡extremo!
+ Spike Outdoors
+ Spike Pluto TV
+ Stand-Up TV
+ Star Trek
+ Stories by AMC
+ Survivor
+ TBN
+ Team Spirit
+ Teen Mom
+ Telefe noticias
+ Telemundo telenovelas clásicas
+ The Addams Family
+ The Amazing Race
+ The Andy Griffith Show
+ The Asylum
+ The Bob Ross Channel
+ The Carol Burnett Show
+ The Challenge
+ The Design Network
+ The First
+ The Love Boat
+ The New Detectives
+ The Pet Collective
+ The Price Is Right: The Barker Era
+ The Rifleman
+ The Walking Dead en español
+ This Old House
+ Three's Company
+ Tiny House Nation
+ TODAY All Day
+ TokuSHOUTsu
+ Top Gear en español
+ Tosh.0
+ TOTALLY TURTLES
+ TV Land Drama
+ TV Land Sitcoms
+ TYT Network
+ Unsolved Mysteries
+ Vevo 2K
+ Vevo '70s
+ Vevo '80s
+ Vevo '90s
+ Vevo Country
+ Vevo Latino
+ Vevo Pop
+ Vevo R&B
+ Vevo Reggaetón & Trap
+ Vevo Retro Rock
+ Vevo True School Hip-Hop
+ VH1 Hip Hop Family
+ VH1 I Love Reality
+ Viaje a las estrellas
+ Voyager Documentaries
+ Wanted: Dead or Alive
+ WeatherNation
+ Western TV
+ Wild 'N Out
+ World Poker Tour
+ Yahoo Finance
+ Yo! MTV
+ Yu-Gi-Oh!
+ Yu-Gi-Oh! en español
+
+