mirror of
https://github.com/iptv-org/epg.git
synced 2025-05-09 08:30:06 -04:00
Merge branch 'master' into patch-2025.01.2
This commit is contained in:
commit
979db51d7e
182 changed files with 7599 additions and 8012 deletions
|
@ -1,39 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"es2021": true,
|
||||
"jest": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"no-case-declarations": "off",
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"windows"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single",
|
||||
{
|
||||
"avoidEscape": true
|
||||
}
|
||||
],
|
||||
"semi": [
|
||||
"error",
|
||||
"never"
|
||||
]
|
||||
}
|
||||
}
|
42
.github/workflows/check.yml
vendored
Normal file
42
.github/workflows/check.yml
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
name: check
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, edited]
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- uses: tj-actions/changed-files@v45
|
||||
id: files
|
||||
with:
|
||||
since_last_remote_commit: true
|
||||
files_yaml: |
|
||||
js:
|
||||
- tests/**/*.{js,ts}
|
||||
- scripts/**/*.{js,ts}
|
||||
- sites/**/*.{js,ts}
|
||||
channels:
|
||||
- sites/**/*.channels.xml
|
||||
- uses: actions/setup-node@v4
|
||||
if: ${{ !env.ACT && (steps.files.outputs.js_any_changed == 'true' || steps.files.outputs.channels_any_changed == 'true') }}
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'npm'
|
||||
- name: install dependencies
|
||||
if: steps.files.outputs.js_any_changed == 'true' || steps.files.outputs.channels_any_changed == 'true'
|
||||
run: SKIP_POSTINSTALL=1 npm install
|
||||
- name: check changed js-files
|
||||
if: steps.files.outputs.js_any_changed == 'true'
|
||||
run: |
|
||||
npx eslint ${{ steps.files.outputs.js_all_changed_files }}
|
||||
- name: check changed *.channels.xml
|
||||
if: steps.files.outputs.channels_any_changed == 'true'
|
||||
run: |
|
||||
npm run channels:lint -- ${{ steps.files.outputs.channels_all_changed_files }}
|
2
.husky/pre-commit
Normal file
2
.husky/pre-commit
Normal file
|
@ -0,0 +1,2 @@
|
|||
npm run lint
|
||||
npm run channels:lint
|
|
@ -1,7 +1,7 @@
|
|||
module.exports = {
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
endOfLine: 'lf',
|
||||
endOfLine: 'crlf',
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
printWidth: 100,
|
||||
|
|
1
.sites/.gitignore
vendored
Normal file
1
.sites/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
_table.md
|
207
.sites/_table.md
207
.sites/_table.md
|
@ -1,207 +0,0 @@
|
|||
<table>
|
||||
<thead>
|
||||
<tr><th align="left">Site</th><th align="left">Status</th><th align="left">Notes</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td><a href="sites/9tv.co.il">9tv.co.il</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/abc.net.au">abc.net.au</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/allente.dk">allente.dk</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/allente.fi">allente.fi</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/allente.no">allente.no</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/allente.se">allente.se</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/andorradifusio.ad">andorradifusio.ad</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/anteltv.com.uy">anteltv.com.uy</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/arianaafgtv.com">arianaafgtv.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/arianatelevision.com">arianatelevision.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/arirang.com">arirang.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/artonline.tv">artonline.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/awilime.com">awilime.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/bein.com">bein.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/beinsports.com">beinsports.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/berrymedia.co.kr">berrymedia.co.kr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cablego.com.pe">cablego.com.pe</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cableplus.com.uy">cableplus.com.uy</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/canalplus-haiti.com">canalplus-haiti.com</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2237</td></tr>
|
||||
<tr><td><a href="sites/canalplus.com">canalplus.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cgates.lt">cgates.lt</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/chada.ma">chada.ma</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/chaines-tv.orange.fr">chaines-tv.orange.fr</a></td><td>🟡</td><td>https://github.com/iptv-org/epg/issues/2395</td></tr>
|
||||
<tr><td><a href="sites/clickthecity.com">clickthecity.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/comteco.com.bo">comteco.com.bo</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2239</td></tr>
|
||||
<tr><td><a href="sites/content.astro.com.my">content.astro.com.my</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cosmote.gr">cosmote.gr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cubmu.com">cubmu.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/dens.tv">dens.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/digiturk.com.tr">digiturk.com.tr</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2304, https://github.com/iptv-org/epg/issues/2547</td></tr>
|
||||
<tr><td><a href="sites/directv.com">directv.com</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2284</td></tr>
|
||||
<tr><td><a href="sites/directv.com.ar">directv.com.ar</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2339</td></tr>
|
||||
<tr><td><a href="sites/directv.com.uy">directv.com.uy</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/dishtv.in">dishtv.in</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2445</td></tr>
|
||||
<tr><td><a href="sites/dsmart.com.tr">dsmart.com.tr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/dstv.com">dstv.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/elcinema.com">elcinema.com</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2541</td></tr>
|
||||
<tr><td><a href="sites/ena.skylifetv.co.kr">ena.skylifetv.co.kr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/energeek.cl">energeek.cl</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/entertainment.ie">entertainment.ie</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/firstmedia.com">firstmedia.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/flixed.io">flixed.io</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/foxsports.com.au">foxsports.com.au</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/foxtel.com.au">foxtel.com.au</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/frikanalen.no">frikanalen.no</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/gatotv.com">gatotv.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/getafteritmedia.com">getafteritmedia.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/guida.tv">guida.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/guidatv.sky.it">guidatv.sky.it</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/hd-plus.de">hd-plus.de</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2173</td></tr>
|
||||
<tr><td><a href="sites/horizon.tv">horizon.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/hoy.tv">hoy.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/i.mjh.nz">i.mjh.nz</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/i24news.tv">i24news.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/iltalehti.fi">iltalehti.fi</a></td><td>🟡</td><td>https://github.com/iptv-org/epg/issues/2396</td></tr>
|
||||
<tr><td><a href="sites/indihometv.com">indihometv.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/ionplustv.com">ionplustv.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/ipko.tv">ipko.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/kan.org.il">kan.org.il</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2273</td></tr>
|
||||
<tr><td><a href="sites/knr.gl">knr.gl</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/kplus.vn">kplus.vn</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2240</td></tr>
|
||||
<tr><td><a href="sites/kvf.fo">kvf.fo</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/m.tv.sms.cz">m.tv.sms.cz</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2241</td></tr>
|
||||
<tr><td><a href="sites/m.tving.com">m.tving.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/magticom.ge">magticom.ge</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mako.co.il">mako.co.il</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/maxtv.hrvatskitelekom.hr">maxtv.hrvatskitelekom.hr</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2509</td></tr>
|
||||
<tr><td><a href="sites/maxtvgo.mk">maxtvgo.mk</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mediagenie.co.kr">mediagenie.co.kr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mediaklikk.hu">mediaklikk.hu</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mediasetinfinity.mediaset.it">mediasetinfinity.mediaset.it</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/melita.com">melita.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/meo.pt">meo.pt</a></td><td>🟡</td><td>https://github.com/iptv-org/epg/issues/2446</td></tr>
|
||||
<tr><td><a href="sites/meuguia.tv">meuguia.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mewatch.sg">mewatch.sg</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mi.tv">mi.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mncvision.id">mncvision.id</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/moji.id">moji.id</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mon-programme-tv.be">mon-programme-tv.be</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/movistarplus.es">movistarplus.es</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2498</td></tr>
|
||||
<tr><td><a href="sites/mtel.ba">mtel.ba</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mts.rs">mts.rs</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mujtvprogram.cz">mujtvprogram.cz</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/musor.tv">musor.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mysky.com.ph">mysky.com.ph</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mytelly.co.uk">mytelly.co.uk</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/mytvsuper.com">mytvsuper.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/neo.io">neo.io</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/nhkworldpremium.com">nhkworldpremium.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/nhl.com">nhl.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/nostv.pt">nostv.pt</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/novacyprus.com">novacyprus.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/novasports.gr">novasports.gr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/nowplayer.now.com">nowplayer.now.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/nuevosiglo.com.uy">nuevosiglo.com.uy</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/nzxmltv.com">nzxmltv.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/ontvtonight.com">ontvtonight.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/osn.com">osn.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/pbsguam.org">pbsguam.org</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/pickx.be">pickx.be</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/player.ee.co.uk">player.ee.co.uk</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/playtv.unifi.com.my">playtv.unifi.com.my</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/plex.tv">plex.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programacion-tv.elpais.com">programacion-tv.elpais.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programacion.tcc.com.uy">programacion.tcc.com.uy</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programetv.ro">programetv.ro</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programme-tv.net">programme-tv.net</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programme-tv.vini.pf">programme-tv.vini.pf</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programme.tvb.com">programme.tvb.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programtv.onet.pl">programtv.onet.pl</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/raiplay.it">raiplay.it</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/reportv.com.ar">reportv.com.ar</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/rev.bs">rev.bs</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2255</td></tr>
|
||||
<tr><td><a href="sites/rotana.net">rotana.net</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/rtb.gov.bn">rtb.gov.bn</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2257</td></tr>
|
||||
<tr><td><a href="sites/rthk.hk">rthk.hk</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/rtmklik.rtm.gov.my">rtmklik.rtm.gov.my</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/rtp.pt">rtp.pt</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/ruv.is">ruv.is</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/s.mxtv.jp">s.mxtv.jp</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/sat.tv">sat.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/shahid.mbc.net">shahid.mbc.net</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/siba.com.co">siba.com.co</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/singtel.com">singtel.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/sjonvarp.is">sjonvarp.is</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/sky.co.nz">sky.co.nz</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/sky.com">sky.com</a></td><td>🟡</td><td>https://github.com/iptv-org/epg/issues/2516, https://github.com/iptv-org/epg/issues/2501</td></tr>
|
||||
<tr><td><a href="sites/sky.de">sky.de</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/skylife.co.kr">skylife.co.kr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/skyperfectv.co.jp">skyperfectv.co.jp</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/snrt.ma">snrt.ma</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/sporttv.pt">sporttv.pt</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/starhubtvplus.com">starhubtvplus.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/startimestv.com">startimestv.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/streamingtvguides.com">streamingtvguides.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/superguidatv.it">superguidatv.it</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/taiwanplus.com">taiwanplus.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tapdmv.com">tapdmv.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/telenet.tv">telenet.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/teliatv.ee">teliatv.ee</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/telkussa.fi">telkussa.fi</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/telsu.fi">telsu.fi</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tivu.tv">tivu.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/toonamiaftermath.com">toonamiaftermath.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/turksatkablo.com.tr">turksatkablo.com.tr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv-programme.telecablesat.fr">tv-programme.telecablesat.fr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.blue.ch">tv.blue.ch</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.cctv.com">tv.cctv.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.dir.bg">tv.dir.bg</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.lv">tv.lv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.magenta.at">tv.magenta.at</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.mail.ru">tv.mail.ru</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.movistar.com.pe">tv.movistar.com.pe</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.nu">tv.nu</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.post.lu">tv.post.lu</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.trueid.net">tv.trueid.net</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.yandex.ru">tv.yandex.ru</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv.yettel.hu">tv.yettel.hu</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2263</td></tr>
|
||||
<tr><td><a href="sites/tv24.co.uk">tv24.co.uk</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv24.se">tv24.se</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tv2go.t-2.net">tv2go.t-2.net</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tva.tv">tva.tv</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2264</td></tr>
|
||||
<tr><td><a href="sites/tvarenasport.com">tvarenasport.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvarenasport.hr">tvarenasport.hr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvcesoir.fr">tvcesoir.fr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvcubana.icrt.cu">tvcubana.icrt.cu</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvgids.nl">tvgids.nl</a></td><td>🟡</td><td>https://github.com/iptv-org/epg/issues/2400</td></tr>
|
||||
<tr><td><a href="sites/tvguide.com">tvguide.com</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2542</td></tr>
|
||||
<tr><td><a href="sites/tvguide.myjcom.jp">tvguide.myjcom.jp</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvhebdo.com">tvhebdo.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvheute.at">tvheute.at</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvim.tv">tvim.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvireland.ie">tvireland.ie</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvmi.mt">tvmi.mt</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvmusor.hu">tvmusor.hu</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvpassport.com">tvpassport.com</a></td><td>🟡</td><td>https://github.com/iptv-org/epg/issues/2272</td></tr>
|
||||
<tr><td><a href="sites/tvplus.com.tr">tvplus.com.tr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/tvprofil.com">tvprofil.com</a></td><td>🟡</td><td>https://github.com/iptv-org/epg/issues/2399</td></tr>
|
||||
<tr><td><a href="sites/tvtv.us">tvtv.us</a></td><td>🟡</td><td>https://github.com/iptv-org/epg/issues/2176</td></tr>
|
||||
<tr><td><a href="sites/v3.myafn.dodmedia.osd.mil">v3.myafn.dodmedia.osd.mil</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/vidio.com">vidio.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/virginmediatelevision.ie">virginmediatelevision.ie</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/virgintvgo.virginmedia.com">virgintvgo.virginmedia.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/visionplus.id">visionplus.id</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/vivacom.bg">vivacom.bg</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2270</td></tr>
|
||||
<tr><td><a href="sites/vtm.be">vtm.be</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/walesi.com.fj">walesi.com.fj</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/watch.sportsnet.ca">watch.sportsnet.ca</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/watchyour.tv">watchyour.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/wavve.com">wavve.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/web.magentatv.de">web.magentatv.de</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/webtv.delta.nl">webtv.delta.nl</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/winplay.co">winplay.co</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/worldfishingnetwork.com">worldfishingnetwork.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/www3.nhk.or.jp">www3.nhk.or.jp</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/xumo.tv">xumo.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/zap.co.ao">zap.co.ao</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/ziggogo.tv">ziggogo.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/znbc.co.zm">znbc.co.zm</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/zuragt.mn">zuragt.mn</a></td><td>🟢</td><td></td></tr>
|
||||
</tbody>
|
||||
</table>
|
|
@ -147,6 +147,7 @@ For scripts to work, you must have [Node.js](https://nodejs.org/en) installed on
|
|||
|
||||
To run scripts use the `npm run <script-name>` command.
|
||||
|
||||
- `act:check`: allows to test the [check](https://github.com/iptv-org/iptv/blob/master/.github/workflows/check.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act).
|
||||
- `act:update`: allows to test the [update](https://github.com/iptv-org/iptv/blob/master/.github/workflows/update.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act).
|
||||
- `api:load`: downloads the latest channels data from the [iptv-org/api](https://github.com/iptv-org/api).
|
||||
- `api:generate`: generates a JSON file with all channels for the [iptv-org/api](https://github.com/iptv-org/api) repository.
|
||||
|
|
9
SITES.md
9
SITES.md
|
@ -28,12 +28,13 @@
|
|||
<tr><td><a href="sites/canalplus.com">canalplus.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cgates.lt">cgates.lt</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/chada.ma">chada.ma</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/chaines-tv.orange.fr">chaines-tv.orange.fr</a></td><td>🟡</td><td>https://github.com/iptv-org/epg/issues/2395</td></tr>
|
||||
<tr><td><a href="sites/chaines-tv.orange.fr">chaines-tv.orange.fr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/clickthecity.com">clickthecity.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/comteco.com.bo">comteco.com.bo</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2239</td></tr>
|
||||
<tr><td><a href="sites/content.astro.com.my">content.astro.com.my</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cosmotetv.gr">cosmotetv.gr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cubmu.com">cubmu.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/cyta.com.cy">cyta.com.cy</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/dens.tv">dens.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/digiturk.com.tr">digiturk.com.tr</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2304, https://github.com/iptv-org/epg/issues/2547</td></tr>
|
||||
<tr><td><a href="sites/directv.com">directv.com</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2284</td></tr>
|
||||
|
@ -42,7 +43,7 @@
|
|||
<tr><td><a href="sites/dishtv.in">dishtv.in</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2445</td></tr>
|
||||
<tr><td><a href="sites/dsmart.com.tr">dsmart.com.tr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/dstv.com">dstv.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/elcinema.com">elcinema.com</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2541</td></tr>
|
||||
<tr><td><a href="sites/elcinema.com">elcinema.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/ena.skylifetv.co.kr">ena.skylifetv.co.kr</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/energeek.cl">energeek.cl</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/entertainment.ie">entertainment.ie</a></td><td>🟢</td><td></td></tr>
|
||||
|
@ -110,6 +111,7 @@
|
|||
<tr><td><a href="sites/player.ee.co.uk">player.ee.co.uk</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/playtv.unifi.com.my">playtv.unifi.com.my</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/plex.tv">plex.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/pluto.tv">pluto.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programacion-tv.elpais.com">programacion-tv.elpais.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programacion.tcc.com.uy">programacion.tcc.com.uy</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/programetv.ro">programetv.ro</a></td><td>🟢</td><td></td></tr>
|
||||
|
@ -141,6 +143,7 @@
|
|||
<tr><td><a href="sites/sporttv.pt">sporttv.pt</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/starhubtvplus.com">starhubtvplus.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/startimestv.com">startimestv.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/stod2.is">stod2.is</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/streamingtvguides.com">streamingtvguides.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/superguidatv.it">superguidatv.it</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/taiwanplus.com">taiwanplus.com</a></td><td>🟢</td><td></td></tr>
|
||||
|
@ -198,7 +201,7 @@
|
|||
<tr><td><a href="sites/watch.sportsnet.ca">watch.sportsnet.ca</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/watchyour.tv">watchyour.tv</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/wavve.com">wavve.com</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/web.magentatv.de">web.magentatv.de</a></td><td>🔴</td><td>https://github.com/iptv-org/epg/issues/2555</td></tr>
|
||||
<tr><td><a href="sites/web.magentatv.de">web.magentatv.de</a></td><td>🟡</td><td>https://github.com/iptv-org/epg/issues/2570</td></tr>
|
||||
<tr><td><a href="sites/webtv.delta.nl">webtv.delta.nl</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/winplay.co">winplay.co</a></td><td>🟢</td><td></td></tr>
|
||||
<tr><td><a href="sites/worldfishingnetwork.com">worldfishingnetwork.com</a></td><td>🟢</td><td></td></tr>
|
||||
|
|
52
eslint.config.mjs
Normal file
52
eslint.config.mjs
Normal file
|
@ -0,0 +1,52 @@
|
|||
import typescriptEslint from '@typescript-eslint/eslint-plugin'
|
||||
import globals from 'globals'
|
||||
import tsParser from '@typescript-eslint/parser'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import js from '@eslint/js'
|
||||
import { FlatCompat } from '@eslint/eslintrc'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
recommendedConfig: js.configs.recommended,
|
||||
allConfig: js.configs.all
|
||||
})
|
||||
|
||||
export default [
|
||||
...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'),
|
||||
{
|
||||
plugins: {
|
||||
'@typescript-eslint': typescriptEslint
|
||||
},
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.jest
|
||||
},
|
||||
|
||||
parser: tsParser,
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module'
|
||||
},
|
||||
|
||||
rules: {
|
||||
'@typescript-eslint/no-require-imports': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'no-case-declarations': 'off',
|
||||
'linebreak-style': ['error', 'windows'],
|
||||
|
||||
quotes: [
|
||||
'error',
|
||||
'single',
|
||||
{
|
||||
avoidEscape: true
|
||||
}
|
||||
],
|
||||
|
||||
semi: ['error', 'never']
|
||||
}
|
||||
}
|
||||
]
|
631
package-lock.json
generated
631
package-lock.json
generated
|
@ -9,11 +9,15 @@
|
|||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"@alex_neo/jest-expect-message": "^1.0.5",
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.17.0",
|
||||
"@freearhey/core": "^0.3.1",
|
||||
"@freearhey/search-js": "^0.1.1",
|
||||
"@ntlab/sfetch": "^1.0.0",
|
||||
"@octokit/plugin-paginate-rest": "^11.3.6",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^13.2.6",
|
||||
"@swc/core": "^1.10.4",
|
||||
"@swc/jest": "^0.2.37",
|
||||
"@types/cli-progress": "^3.11.3",
|
||||
"@types/fs-extra": "^11.0.2",
|
||||
"@types/inquirer": "^9.0.3",
|
||||
|
@ -39,9 +43,12 @@
|
|||
"form-data": "^4.0.0",
|
||||
"fs-extra": "^10.0.1",
|
||||
"glob": "^7.2.0",
|
||||
"globals": "^15.14.0",
|
||||
"husky": "^9.1.7",
|
||||
"iconv-lite": "^0.4.24",
|
||||
"inquirer": "^8.2.6",
|
||||
"jest": "^29.7.0",
|
||||
"jest-offline": "^1.0.1",
|
||||
"langs": "^2.0.0",
|
||||
"libxmljs2": "^0.35.0",
|
||||
"lodash": "^4.17.21",
|
||||
|
@ -58,12 +65,12 @@
|
|||
"run-script-os": "^1.1.6",
|
||||
"serve": "^14.2.4",
|
||||
"signale": "^1.4.0",
|
||||
"skip-postinstall": "^1.0.0",
|
||||
"srcset": "^4.0.0",
|
||||
"table2array": "^0.0.2",
|
||||
"tabletojson": "^2.0.7",
|
||||
"tough-cookie": "^5.0.0",
|
||||
"transliteration": "^2.2.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"tsx": "^4.19.2",
|
||||
"unzipit": "^1.4.0",
|
||||
"wildcard-match": "^5.1.2"
|
||||
|
@ -639,6 +646,14 @@
|
|||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse/node_modules/globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.23.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz",
|
||||
|
@ -1508,6 +1523,17 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/create-cache-key-function": {
|
||||
"version": "29.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz",
|
||||
"integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==",
|
||||
"dependencies": {
|
||||
"@jest/types": "^29.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/environment": {
|
||||
"version": "29.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
|
||||
|
@ -2246,6 +2272,222 @@
|
|||
"@sinonjs/commons": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.4.tgz",
|
||||
"integrity": "sha512-ut3zfiTLORMxhr6y/GBxkHmzcGuVpwJYX4qyXWuBKkpw/0g0S5iO1/wW7RnLnZbAi8wS/n0atRZoaZlXWBkeJg==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@swc/counter": "^0.1.3",
|
||||
"@swc/types": "^0.1.17"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/swc"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-darwin-arm64": "1.10.4",
|
||||
"@swc/core-darwin-x64": "1.10.4",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.10.4",
|
||||
"@swc/core-linux-arm64-gnu": "1.10.4",
|
||||
"@swc/core-linux-arm64-musl": "1.10.4",
|
||||
"@swc/core-linux-x64-gnu": "1.10.4",
|
||||
"@swc/core-linux-x64-musl": "1.10.4",
|
||||
"@swc/core-win32-arm64-msvc": "1.10.4",
|
||||
"@swc/core-win32-ia32-msvc": "1.10.4",
|
||||
"@swc/core-win32-x64-msvc": "1.10.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/helpers": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@swc/helpers": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-arm64": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.4.tgz",
|
||||
"integrity": "sha512-sV/eurLhkjn/197y48bxKP19oqcLydSel42Qsy2zepBltqUx+/zZ8+/IS0Bi7kaWVFxerbW1IPB09uq8Zuvm3g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-x64": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.4.tgz",
|
||||
"integrity": "sha512-gjYNU6vrAUO4+FuovEo9ofnVosTFXkF0VDuo1MKPItz6e2pxc2ale4FGzLw0Nf7JB1sX4a8h06CN16/pLJ8Q2w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm-gnueabihf": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.4.tgz",
|
||||
"integrity": "sha512-zd7fXH5w8s+Sfvn2oO464KDWl+ZX1MJiVmE4Pdk46N3PEaNwE0koTfgx2vQRqRG4vBBobzVvzICC3618WcefOA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-gnu": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.4.tgz",
|
||||
"integrity": "sha512-+UGfoHDxsMZgFD3tABKLeEZHqLNOkxStu+qCG7atGBhS4Slri6h6zijVvf4yI5X3kbXdvc44XV/hrP/Klnui2A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-musl": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.4.tgz",
|
||||
"integrity": "sha512-cDDj2/uYsOH0pgAnDkovLZvKJpFmBMyXkxEG6Q4yw99HbzO6QzZ5HDGWGWVq/6dLgYKlnnmpjZCPPQIu01mXEg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-gnu": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.4.tgz",
|
||||
"integrity": "sha512-qJXh9D6Kf5xSdGWPINpLGixAbB5JX8JcbEJpRamhlDBoOcQC79dYfOMEIxWPhTS1DGLyFakAx2FX/b2VmQmj0g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-musl": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.4.tgz",
|
||||
"integrity": "sha512-A76lIAeyQnHCVt0RL/pG+0er8Qk9+acGJqSZOZm67Ve3B0oqMd871kPtaHBM0BW3OZAhoILgfHW3Op9Q3mx3Cw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-arm64-msvc": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.4.tgz",
|
||||
"integrity": "sha512-e6j5kBu4fIY7fFxFxnZI0MlEovRvp50Lg59Fw+DVbtqHk3C85dckcy5xKP+UoXeuEmFceauQDczUcGs19SRGSQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-ia32-msvc": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.4.tgz",
|
||||
"integrity": "sha512-RSYHfdKgNXV/amY5Tqk1EWVsyQnhlsM//jeqMLw5Fy9rfxP592W9UTumNikNRPdjI8wKKzNMXDb1U29tQjN0dg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-x64-msvc": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.4.tgz",
|
||||
"integrity": "sha512-1ujYpaqfqNPYdwKBlvJnOqcl+Syn3UrQ4XE0Txz6zMYgyh6cdU6a3pxqLqIUSJ12MtXRA9ZUhEz1ekU3LfLWXw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/counter": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
||||
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
|
||||
},
|
||||
"node_modules/@swc/jest": {
|
||||
"version": "0.2.37",
|
||||
"resolved": "https://registry.npmjs.org/@swc/jest/-/jest-0.2.37.tgz",
|
||||
"integrity": "sha512-CR2BHhmXKGxTiFr21DYPRHQunLkX3mNIFGFkxBGji6r9uyIR5zftTOVYj1e0sFNMV2H7mf/+vpaglqaryBtqfQ==",
|
||||
"dependencies": {
|
||||
"@jest/create-cache-key-function": "^29.7.0",
|
||||
"@swc/counter": "^0.1.3",
|
||||
"jsonc-parser": "^3.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"npm": ">= 7.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/core": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/types": {
|
||||
"version": "0.1.17",
|
||||
"resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.17.tgz",
|
||||
"integrity": "sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==",
|
||||
"dependencies": {
|
||||
"@swc/counter": "^0.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@szmarczak/http-timer": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||
|
@ -3326,17 +3568,6 @@
|
|||
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
||||
}
|
||||
},
|
||||
"node_modules/bs-logger": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
|
||||
"integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
|
||||
"dependencies": {
|
||||
"fast-json-stable-stringify": "2.x"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/bser": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
|
||||
|
@ -5262,11 +5493,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
|
||||
"version": "15.14.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz",
|
||||
"integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/got": {
|
||||
|
@ -5417,6 +5651,20 @@
|
|||
"node": ">=10.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/husky": {
|
||||
"version": "9.1.7",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
|
||||
"integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
|
||||
"bin": {
|
||||
"husky": "bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/typicode"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
|
@ -6209,6 +6457,14 @@
|
|||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-offline": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jest-offline/-/jest-offline-1.0.1.tgz",
|
||||
"integrity": "sha512-pcYJ8rVxWP3SS9de15iSQY87ErLGGgMC4qtVcRLb/qemrefI1IgnAzOusp0eemGu7JoAGlb4oBGnZorehu95KA==",
|
||||
"dependencies": {
|
||||
"mitm": "^1.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-pnp-resolver": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
|
||||
|
@ -6562,6 +6818,11 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonc-parser": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
|
||||
"integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
|
@ -6721,11 +6982,6 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"node_modules/lodash.memoize": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||
"integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="
|
||||
},
|
||||
"node_modules/lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
|
@ -6796,7 +7052,9 @@
|
|||
"node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/make-fetch-happen": {
|
||||
"version": "13.0.1",
|
||||
|
@ -7083,6 +7341,25 @@
|
|||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"node_modules/mitm": {
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/mitm/-/mitm-1.7.3.tgz",
|
||||
"integrity": "sha512-linie/mGisDH73C7aiW6JmstA5XskXd15JBJAEeNQBdH3/L0dJdE/yZ+rw/y2zT7Fcib5KAnL5OvxYOOFQbsgw==",
|
||||
"dependencies": {
|
||||
"semver": ">= 5 < 6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10.24"
|
||||
}
|
||||
},
|
||||
"node_modules/mitm/node_modules/semver": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||
"bin": {
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
|
@ -8910,6 +9187,15 @@
|
|||
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="
|
||||
},
|
||||
"node_modules/skip-postinstall": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/skip-postinstall/-/skip-postinstall-1.0.0.tgz",
|
||||
"integrity": "sha512-IUVEmm4v7Ubzrp9JDG15oTzMB+abJdHcduXMRzBlHnHRrmpQ/QoPtYCRaorP+abAULTGEh87gPPyyMK5H1X1Dg==",
|
||||
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
|
||||
"bin": {
|
||||
"skip-postinstall": "index.js"
|
||||
}
|
||||
},
|
||||
"node_modules/slash": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||
|
@ -9406,86 +9692,6 @@
|
|||
"typescript": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-jest": {
|
||||
"version": "29.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz",
|
||||
"integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==",
|
||||
"dependencies": {
|
||||
"bs-logger": "0.x",
|
||||
"fast-json-stable-stringify": "2.x",
|
||||
"jest-util": "^29.0.0",
|
||||
"json5": "^2.2.3",
|
||||
"lodash.memoize": "4.x",
|
||||
"make-error": "1.x",
|
||||
"semver": "^7.5.3",
|
||||
"yargs-parser": "^21.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"ts-jest": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": ">=7.0.0-beta.0 <8",
|
||||
"@jest/types": "^29.0.0",
|
||||
"babel-jest": "^29.0.0",
|
||||
"jest": "^29.0.0",
|
||||
"typescript": ">=4.3 <6"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@babel/core": {
|
||||
"optional": true
|
||||
},
|
||||
"@jest/types": {
|
||||
"optional": true
|
||||
},
|
||||
"babel-jest": {
|
||||
"optional": true
|
||||
},
|
||||
"esbuild": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ts-jest/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-jest/node_modules/semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-jest/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"node_modules/ts-jest/node_modules/yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-node": {
|
||||
"version": "10.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
|
||||
|
@ -10484,6 +10690,13 @@
|
|||
"@babel/types": "^7.23.3",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
|
@ -10994,6 +11207,14 @@
|
|||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@jest/create-cache-key-function": {
|
||||
"version": "29.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz",
|
||||
"integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==",
|
||||
"requires": {
|
||||
"@jest/types": "^29.6.3"
|
||||
}
|
||||
},
|
||||
"@jest/environment": {
|
||||
"version": "29.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
|
||||
|
@ -11591,6 +11812,108 @@
|
|||
"@sinonjs/commons": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"@swc/core": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.4.tgz",
|
||||
"integrity": "sha512-ut3zfiTLORMxhr6y/GBxkHmzcGuVpwJYX4qyXWuBKkpw/0g0S5iO1/wW7RnLnZbAi8wS/n0atRZoaZlXWBkeJg==",
|
||||
"requires": {
|
||||
"@swc/core-darwin-arm64": "1.10.4",
|
||||
"@swc/core-darwin-x64": "1.10.4",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.10.4",
|
||||
"@swc/core-linux-arm64-gnu": "1.10.4",
|
||||
"@swc/core-linux-arm64-musl": "1.10.4",
|
||||
"@swc/core-linux-x64-gnu": "1.10.4",
|
||||
"@swc/core-linux-x64-musl": "1.10.4",
|
||||
"@swc/core-win32-arm64-msvc": "1.10.4",
|
||||
"@swc/core-win32-ia32-msvc": "1.10.4",
|
||||
"@swc/core-win32-x64-msvc": "1.10.4",
|
||||
"@swc/counter": "^0.1.3",
|
||||
"@swc/types": "^0.1.17"
|
||||
}
|
||||
},
|
||||
"@swc/core-darwin-arm64": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.4.tgz",
|
||||
"integrity": "sha512-sV/eurLhkjn/197y48bxKP19oqcLydSel42Qsy2zepBltqUx+/zZ8+/IS0Bi7kaWVFxerbW1IPB09uq8Zuvm3g==",
|
||||
"optional": true
|
||||
},
|
||||
"@swc/core-darwin-x64": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.4.tgz",
|
||||
"integrity": "sha512-gjYNU6vrAUO4+FuovEo9ofnVosTFXkF0VDuo1MKPItz6e2pxc2ale4FGzLw0Nf7JB1sX4a8h06CN16/pLJ8Q2w==",
|
||||
"optional": true
|
||||
},
|
||||
"@swc/core-linux-arm-gnueabihf": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.4.tgz",
|
||||
"integrity": "sha512-zd7fXH5w8s+Sfvn2oO464KDWl+ZX1MJiVmE4Pdk46N3PEaNwE0koTfgx2vQRqRG4vBBobzVvzICC3618WcefOA==",
|
||||
"optional": true
|
||||
},
|
||||
"@swc/core-linux-arm64-gnu": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.4.tgz",
|
||||
"integrity": "sha512-+UGfoHDxsMZgFD3tABKLeEZHqLNOkxStu+qCG7atGBhS4Slri6h6zijVvf4yI5X3kbXdvc44XV/hrP/Klnui2A==",
|
||||
"optional": true
|
||||
},
|
||||
"@swc/core-linux-arm64-musl": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.4.tgz",
|
||||
"integrity": "sha512-cDDj2/uYsOH0pgAnDkovLZvKJpFmBMyXkxEG6Q4yw99HbzO6QzZ5HDGWGWVq/6dLgYKlnnmpjZCPPQIu01mXEg==",
|
||||
"optional": true
|
||||
},
|
||||
"@swc/core-linux-x64-gnu": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.4.tgz",
|
||||
"integrity": "sha512-qJXh9D6Kf5xSdGWPINpLGixAbB5JX8JcbEJpRamhlDBoOcQC79dYfOMEIxWPhTS1DGLyFakAx2FX/b2VmQmj0g==",
|
||||
"optional": true
|
||||
},
|
||||
"@swc/core-linux-x64-musl": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.4.tgz",
|
||||
"integrity": "sha512-A76lIAeyQnHCVt0RL/pG+0er8Qk9+acGJqSZOZm67Ve3B0oqMd871kPtaHBM0BW3OZAhoILgfHW3Op9Q3mx3Cw==",
|
||||
"optional": true
|
||||
},
|
||||
"@swc/core-win32-arm64-msvc": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.4.tgz",
|
||||
"integrity": "sha512-e6j5kBu4fIY7fFxFxnZI0MlEovRvp50Lg59Fw+DVbtqHk3C85dckcy5xKP+UoXeuEmFceauQDczUcGs19SRGSQ==",
|
||||
"optional": true
|
||||
},
|
||||
"@swc/core-win32-ia32-msvc": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.4.tgz",
|
||||
"integrity": "sha512-RSYHfdKgNXV/amY5Tqk1EWVsyQnhlsM//jeqMLw5Fy9rfxP592W9UTumNikNRPdjI8wKKzNMXDb1U29tQjN0dg==",
|
||||
"optional": true
|
||||
},
|
||||
"@swc/core-win32-x64-msvc": {
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.4.tgz",
|
||||
"integrity": "sha512-1ujYpaqfqNPYdwKBlvJnOqcl+Syn3UrQ4XE0Txz6zMYgyh6cdU6a3pxqLqIUSJ12MtXRA9ZUhEz1ekU3LfLWXw==",
|
||||
"optional": true
|
||||
},
|
||||
"@swc/counter": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
||||
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
|
||||
},
|
||||
"@swc/jest": {
|
||||
"version": "0.2.37",
|
||||
"resolved": "https://registry.npmjs.org/@swc/jest/-/jest-0.2.37.tgz",
|
||||
"integrity": "sha512-CR2BHhmXKGxTiFr21DYPRHQunLkX3mNIFGFkxBGji6r9uyIR5zftTOVYj1e0sFNMV2H7mf/+vpaglqaryBtqfQ==",
|
||||
"requires": {
|
||||
"@jest/create-cache-key-function": "^29.7.0",
|
||||
"@swc/counter": "^0.1.3",
|
||||
"jsonc-parser": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"@swc/types": {
|
||||
"version": "0.1.17",
|
||||
"resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.17.tgz",
|
||||
"integrity": "sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==",
|
||||
"requires": {
|
||||
"@swc/counter": "^0.1.3"
|
||||
}
|
||||
},
|
||||
"@szmarczak/http-timer": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||
|
@ -12372,14 +12695,6 @@
|
|||
"update-browserslist-db": "^1.0.11"
|
||||
}
|
||||
},
|
||||
"bs-logger": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
|
||||
"integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
|
||||
"requires": {
|
||||
"fast-json-stable-stringify": "2.x"
|
||||
}
|
||||
},
|
||||
"bser": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
|
||||
|
@ -13782,9 +14097,9 @@
|
|||
}
|
||||
},
|
||||
"globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
|
||||
"version": "15.14.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz",
|
||||
"integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig=="
|
||||
},
|
||||
"got": {
|
||||
"version": "11.8.5",
|
||||
|
@ -13888,6 +14203,11 @@
|
|||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="
|
||||
},
|
||||
"husky": {
|
||||
"version": "9.1.7",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
|
||||
"integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
|
@ -14438,6 +14758,14 @@
|
|||
"jest-util": "^29.7.0"
|
||||
}
|
||||
},
|
||||
"jest-offline": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jest-offline/-/jest-offline-1.0.1.tgz",
|
||||
"integrity": "sha512-pcYJ8rVxWP3SS9de15iSQY87ErLGGgMC4qtVcRLb/qemrefI1IgnAzOusp0eemGu7JoAGlb4oBGnZorehu95KA==",
|
||||
"requires": {
|
||||
"mitm": "^1.3.2"
|
||||
}
|
||||
},
|
||||
"jest-pnp-resolver": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
|
||||
|
@ -14721,6 +15049,11 @@
|
|||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
|
||||
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
|
||||
},
|
||||
"jsonc-parser": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
|
||||
"integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
|
@ -14849,11 +15182,6 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"lodash.memoize": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||
"integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="
|
||||
},
|
||||
"lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
|
@ -14908,7 +15236,9 @@
|
|||
"make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"make-fetch-happen": {
|
||||
"version": "13.0.1",
|
||||
|
@ -15138,6 +15468,21 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"mitm": {
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/mitm/-/mitm-1.7.3.tgz",
|
||||
"integrity": "sha512-linie/mGisDH73C7aiW6JmstA5XskXd15JBJAEeNQBdH3/L0dJdE/yZ+rw/y2zT7Fcib5KAnL5OvxYOOFQbsgw==",
|
||||
"requires": {
|
||||
"semver": ">= 5 < 6"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
|
@ -16465,6 +16810,11 @@
|
|||
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="
|
||||
},
|
||||
"skip-postinstall": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/skip-postinstall/-/skip-postinstall-1.0.0.tgz",
|
||||
"integrity": "sha512-IUVEmm4v7Ubzrp9JDG15oTzMB+abJdHcduXMRzBlHnHRrmpQ/QoPtYCRaorP+abAULTGEh87gPPyyMK5H1X1Dg=="
|
||||
},
|
||||
"slash": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||
|
@ -16818,49 +17168,6 @@
|
|||
"integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
|
||||
"requires": {}
|
||||
},
|
||||
"ts-jest": {
|
||||
"version": "29.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz",
|
||||
"integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==",
|
||||
"requires": {
|
||||
"bs-logger": "0.x",
|
||||
"fast-json-stable-stringify": "2.x",
|
||||
"jest-util": "^29.0.0",
|
||||
"json5": "^2.2.3",
|
||||
"lodash.memoize": "4.x",
|
||||
"make-error": "1.x",
|
||||
"semver": "^7.5.3",
|
||||
"yargs-parser": "^21.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ts-node": {
|
||||
"version": "10.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
|
||||
|
|
20
package.json
20
package.json
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "epg",
|
||||
"scripts": {
|
||||
"act:check": "act pull_request -W .github/workflows/check.yml",
|
||||
"act:update": "act workflow_dispatch -W .github/workflows/update.yml",
|
||||
"api:load": "npx tsx scripts/commands/api/load.ts",
|
||||
"api:generate": "npx tsx scripts/commands/api/generate.ts",
|
||||
|
@ -10,29 +11,37 @@
|
|||
"channels:validate": "npx tsx scripts/commands/channels/validate.ts",
|
||||
"sites:update": "npx tsx scripts/commands/sites/update.ts",
|
||||
"grab": "npx tsx scripts/commands/epg/grab.ts",
|
||||
"lint": "npx eslint \"{scripts,tests}/**/*.{ts,js}\"",
|
||||
"lint": "npx eslint \"{scripts,tests,sites}/**/*.{ts,js}\"",
|
||||
"test": "run-script-os",
|
||||
"test:win32": "SET \"TZ=Pacific/Nauru\" && npx jest --runInBand",
|
||||
"test:default": "TZ=Pacific/Nauru npx jest --runInBand",
|
||||
"postinstall": "npm run api:load"
|
||||
"postinstall": "skip-postinstall || npm run api:load",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"private": true,
|
||||
"author": "Arhey",
|
||||
"license": "UNLICENSED",
|
||||
"jest": {
|
||||
"setupFiles": [
|
||||
"<rootDir>/node_modules/jest-offline"
|
||||
],
|
||||
"transform": {
|
||||
"^.+\\.(ts|js)$": "ts-jest"
|
||||
"^.+\\.(ts|js)$": "@swc/jest"
|
||||
},
|
||||
"testRegex": "(tests|sites)/(.*?/)?.*test.(js|ts)$",
|
||||
"testTimeout": 10000
|
||||
},
|
||||
"dependencies": {
|
||||
"@alex_neo/jest-expect-message": "^1.0.5",
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.17.0",
|
||||
"@freearhey/core": "^0.3.1",
|
||||
"@freearhey/search-js": "^0.1.1",
|
||||
"@ntlab/sfetch": "^1.0.0",
|
||||
"@octokit/plugin-paginate-rest": "^11.3.6",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^13.2.6",
|
||||
"@swc/core": "^1.10.4",
|
||||
"@swc/jest": "^0.2.37",
|
||||
"@types/cli-progress": "^3.11.3",
|
||||
"@types/fs-extra": "^11.0.2",
|
||||
"@types/inquirer": "^9.0.3",
|
||||
|
@ -58,9 +67,12 @@
|
|||
"form-data": "^4.0.0",
|
||||
"fs-extra": "^10.0.1",
|
||||
"glob": "^7.2.0",
|
||||
"globals": "^15.14.0",
|
||||
"husky": "^9.1.7",
|
||||
"iconv-lite": "^0.4.24",
|
||||
"inquirer": "^8.2.6",
|
||||
"jest": "^29.7.0",
|
||||
"jest-offline": "^1.0.1",
|
||||
"langs": "^2.0.0",
|
||||
"libxmljs2": "^0.35.0",
|
||||
"lodash": "^4.17.21",
|
||||
|
@ -77,12 +89,12 @@
|
|||
"run-script-os": "^1.1.6",
|
||||
"serve": "^14.2.4",
|
||||
"signale": "^1.4.0",
|
||||
"skip-postinstall": "^1.0.0",
|
||||
"srcset": "^4.0.0",
|
||||
"table2array": "^0.0.2",
|
||||
"tabletojson": "^2.0.7",
|
||||
"tough-cookie": "^5.0.0",
|
||||
"transliteration": "^2.2.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"tsx": "^4.19.2",
|
||||
"unzipit": "^1.4.0",
|
||||
"wildcard-match": "^5.1.2"
|
||||
|
|
|
@ -43,7 +43,7 @@ async function main() {
|
|||
const channelsIndex = sj.createIndex(channelsContent)
|
||||
|
||||
const buffer = new Dictionary()
|
||||
for (let option of options.all()) {
|
||||
for (const option of options.all()) {
|
||||
const channel: Channel = option.channel
|
||||
if (channel.xmltv_id) {
|
||||
if (channel.xmltv_id !== '-') {
|
||||
|
@ -150,7 +150,7 @@ function getOptions(channelsIndex, channel: Channel) {
|
|||
const query = channel.name
|
||||
.replace(/\s(SD|TV|HD|SD\/HD|HDTV)$/i, '')
|
||||
.replace(/(\(|\)|,)/gi, '')
|
||||
.replace(/\-/gi, ' ')
|
||||
.replace(/-/gi, ' ')
|
||||
.replace(/\+/gi, '')
|
||||
const similar = channelsIndex.search(query).map(item => new ApiChannel(item))
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import chalk from 'chalk'
|
||||
import libxml, { ValidationError } from 'libxmljs2'
|
||||
import { program } from 'commander'
|
||||
import { Logger, Storage, File } from '@freearhey/core'
|
||||
import { Storage, File } from '@freearhey/core'
|
||||
|
||||
const xsd = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
|
||||
|
@ -23,26 +23,14 @@ const xsd = `<?xml version="1.0" encoding="UTF-8"?>
|
|||
</xs:element>
|
||||
</xs:schema>`
|
||||
|
||||
program
|
||||
.option(
|
||||
'-c, --channels <path>',
|
||||
'Path to channels.xml file to validate',
|
||||
'sites/**/*.channels.xml'
|
||||
)
|
||||
.parse(process.argv)
|
||||
|
||||
const options = program.opts()
|
||||
program.argument('[filepath]', 'Path to *.channels.xml files to validate').parse(process.argv)
|
||||
|
||||
async function main() {
|
||||
const logger = new Logger()
|
||||
const storage = new Storage()
|
||||
|
||||
logger.info('options:')
|
||||
logger.tree(options)
|
||||
|
||||
let errors: ValidationError[] = []
|
||||
|
||||
const files: string[] = await storage.list(options.channels)
|
||||
const files = program.args.length ? program.args : await storage.list('sites/**/*.channels.xml')
|
||||
for (const filepath of files) {
|
||||
const file = new File(filepath)
|
||||
if (file.extension() !== 'xml') continue
|
||||
|
@ -51,11 +39,15 @@ async function main() {
|
|||
|
||||
let localErrors: ValidationError[] = []
|
||||
|
||||
const xsdDoc = libxml.parseXml(xsd)
|
||||
const doc = libxml.parseXml(xml)
|
||||
try {
|
||||
const xsdDoc = libxml.parseXml(xsd)
|
||||
const doc = libxml.parseXml(xml)
|
||||
|
||||
if (!doc.validate(xsdDoc)) {
|
||||
localErrors = doc.validationErrors
|
||||
if (!doc.validate(xsdDoc)) {
|
||||
localErrors = doc.validationErrors
|
||||
}
|
||||
} catch (error) {
|
||||
localErrors.push(error)
|
||||
}
|
||||
|
||||
if (localErrors.length) {
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Logger, File, Collection, Storage } from '@freearhey/core'
|
|||
import { ChannelsParser, XML } from '../../core'
|
||||
import { Channel } from 'epg-grabber'
|
||||
import { Command } from 'commander'
|
||||
import path from 'path'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
|
||||
const program = new Command()
|
||||
program
|
||||
|
@ -26,7 +26,7 @@ async function main() {
|
|||
const logger = new Logger()
|
||||
const file = new File(options.config)
|
||||
const dir = file.dirname()
|
||||
const config = require(path.resolve(options.config))
|
||||
const config = (await import(pathToFileURL(options.config))).default
|
||||
const outputFilepath = options.output || `${dir}/${config.site}.channels.xml`
|
||||
|
||||
let channels = new Collection()
|
||||
|
|
|
@ -47,7 +47,6 @@ async function main() {
|
|||
|
||||
const parsedChannels = await parser.parse(filepath)
|
||||
|
||||
const bufferById = new Dictionary()
|
||||
const bufferBySiteId = new Dictionary()
|
||||
const errors: ValidationError[] = []
|
||||
parsedChannels.forEach((channel: Channel) => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Logger, Storage, Collection, Dictionary } from '@freearhey/core'
|
||||
import { Logger, Storage, Collection } from '@freearhey/core'
|
||||
import { IssueLoader, HTMLTable, Markdown } from '../../core'
|
||||
import { Issue, Site } from '../../models'
|
||||
import { SITES_DIR, DOT_SITES_DIR } from '../../constants'
|
||||
|
@ -28,7 +28,7 @@ async function main() {
|
|||
})
|
||||
|
||||
logger.info('creating sites table...')
|
||||
let data = new Collection()
|
||||
const data = new Collection()
|
||||
sites.forEach((site: Site) => {
|
||||
data.add([
|
||||
`<a href="sites/${site.domain}">${site.domain}</a>`,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
import dayjs from 'dayjs'
|
||||
import utc from 'dayjs/plugin/utc'
|
||||
|
||||
dayjs.extend(utc)
|
||||
|
||||
const date = {}
|
||||
|
@ -10,4 +11,4 @@ date.getUTC = function (d = null) {
|
|||
return dayjs.utc().startOf('d')
|
||||
}
|
||||
|
||||
module.exports = date
|
||||
export default date
|
||||
|
|
|
@ -16,15 +16,15 @@ export class HTMLTable {
|
|||
}
|
||||
|
||||
toString() {
|
||||
let output = '<table>\n'
|
||||
let output = '<table>\r\n'
|
||||
|
||||
output += ' <thead>\n <tr>'
|
||||
output += ' <thead>\r\n <tr>'
|
||||
for (const column of this.columns) {
|
||||
output += `<th align="left">${column.name}</th>`
|
||||
}
|
||||
output += '</tr>\n </thead>\n'
|
||||
output += '</tr>\r\n </thead>\r\n'
|
||||
|
||||
output += ' <tbody>\n'
|
||||
output += ' <tbody>\r\n'
|
||||
for (const item of this.data) {
|
||||
output += ' <tr>'
|
||||
let i = 0
|
||||
|
@ -35,9 +35,9 @@ export class HTMLTable {
|
|||
output += `<td${align}${nowrap}>${item[prop]}</td>`
|
||||
i++
|
||||
}
|
||||
output += '</tr>\n'
|
||||
output += '</tr>\r\n'
|
||||
}
|
||||
output += ' </tbody>\n'
|
||||
output += ' </tbody>\r\n'
|
||||
|
||||
output += '</table>'
|
||||
|
||||
|
|
|
@ -15,10 +15,11 @@ export class IssueLoader {
|
|||
if (TESTING) {
|
||||
switch (labels) {
|
||||
case 'broken guide,status:warning':
|
||||
issues = require('../../tests/__data__/input/issues/broken_guide_warning.js')
|
||||
issues = (await import('../../tests/__data__/input/issues/broken_guide_warning.mjs'))
|
||||
.default
|
||||
break
|
||||
case 'broken guide,status:down':
|
||||
issues = require('../../tests/__data__/input/issues/broken_guide_down.js')
|
||||
issues = (await import('../../tests/__data__/input/issues/broken_guide_down.mjs')).default
|
||||
break
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -11,7 +11,7 @@ export class IssueParser {
|
|||
|
||||
const data = new Dictionary()
|
||||
fields.forEach((field: string) => {
|
||||
let parsed = field.split(/\r?\n/).filter(Boolean)
|
||||
const parsed = field.split(/\r?\n/).filter(Boolean)
|
||||
let _label = parsed.shift()
|
||||
_label = _label ? _label.trim() : ''
|
||||
let _value = parsed.join('\r\n')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Storage, Collection, DateTime, Logger } from '@freearhey/core'
|
||||
import { ChannelsParser, ConfigLoader, ApiChannel, Queue } from './'
|
||||
import { SITES_DIR, DATA_DIR } from '../constants'
|
||||
import { Channel, SiteConfig } from 'epg-grabber'
|
||||
import { SiteConfig } from 'epg-grabber'
|
||||
import path from 'path'
|
||||
import { GrabOptions } from '../commands/epg/grab'
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ function parseItems(content, channel) {
|
|||
const [, channelId] = channel.site_id.split('#')
|
||||
const channelData = data.schedule.find(i => i.channel == channelId)
|
||||
return channelData.listing && Array.isArray(channelData.listing) ? channelData.listing : []
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const { parser, url, request } = require('./awilime.com.config.js')
|
||||
const { parser, url } = require('./awilime.com.config.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const dayjs = require('dayjs')
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const axios = require('axios')
|
||||
const cheerio = require('cheerio')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const timezone = require('dayjs/plugin/timezone')
|
||||
|
@ -62,7 +61,7 @@ function parseItems(content) {
|
|||
let data
|
||||
try {
|
||||
data = JSON.parse(content)
|
||||
} catch (error) {
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
const { parser, url } = require('./beinsports.com.config.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
const axios = require('axios');
|
||||
const cheerio = require('cheerio');
|
||||
const dayjs = require('dayjs');
|
||||
const utc = require('dayjs/plugin/utc');
|
||||
const timezone = require('dayjs/plugin/timezone');
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat');
|
||||
const cheerio = require('cheerio')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const timezone = require('dayjs/plugin/timezone')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
dayjs.extend(customParseFormat);
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
dayjs.extend(customParseFormat)
|
||||
|
||||
module.exports = {
|
||||
site: 'chada.ma',
|
||||
|
@ -19,36 +18,38 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
url() {
|
||||
return 'https://chada.ma/fr/chada-tv/grille-tv/';
|
||||
return 'https://chada.ma/fr/chada-tv/grille-tv/'
|
||||
},
|
||||
parser: function ({ content }) {
|
||||
const $ = cheerio.load(content);
|
||||
const programs = [];
|
||||
const $ = cheerio.load(content)
|
||||
const programs = []
|
||||
|
||||
$('#stopfix .posts-area h2').each((i, element) => {
|
||||
const timeRange = $(element).text().trim();
|
||||
const [start, stop] = timeRange.split(' - ').map(t => parseProgramTime(t.trim()));
|
||||
const timeRange = $(element).text().trim()
|
||||
const [start, stop] = timeRange.split(' - ').map(t => parseProgramTime(t.trim()))
|
||||
|
||||
const titleElement = $(element).next('div').next('h3');
|
||||
const title = titleElement.text().trim();
|
||||
const titleElement = $(element).next('div').next('h3')
|
||||
const title = titleElement.text().trim()
|
||||
|
||||
const description = titleElement.next('div').text().trim() || 'No description available';
|
||||
const description = titleElement.next('div').text().trim() || 'No description available'
|
||||
|
||||
programs.push({
|
||||
title,
|
||||
description,
|
||||
start,
|
||||
stop
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
return programs;
|
||||
return programs
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function parseProgramTime(timeStr) {
|
||||
const timeZone = 'Africa/Casablanca';
|
||||
const currentDate = dayjs().format('YYYY-MM-DD');
|
||||
const timeZone = 'Africa/Casablanca'
|
||||
const currentDate = dayjs().format('YYYY-MM-DD')
|
||||
|
||||
return dayjs.tz(`${currentDate} ${timeStr}`, 'YYYY-MM-DD HH:mm', timeZone).format('YYYY-MM-DDTHH:mm:ssZ');
|
||||
return dayjs
|
||||
.tz(`${currentDate} ${timeStr}`, 'YYYY-MM-DD HH:mm', timeZone)
|
||||
.format('YYYY-MM-DDTHH:mm:ssZ')
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
const { parser, url } = require('./chada.ma.config.js')
|
||||
const axios = require('axios')
|
||||
const dayjs = require('dayjs')
|
||||
const cheerio = require('cheerio')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const timezone = require('dayjs/plugin/timezone')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
|
@ -27,11 +25,11 @@ const mockHtmlContent = `
|
|||
<div class="ssprogramme row"></div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`
|
||||
|
||||
it('can generate valid url', () => {
|
||||
expect(url()).toBe('https://chada.ma/fr/chada-tv/grille-tv/')
|
||||
});
|
||||
})
|
||||
|
||||
it('can parse response', () => {
|
||||
const content = mockHtmlContent
|
||||
|
@ -44,8 +42,8 @@ it('can parse response', () => {
|
|||
|
||||
expect(result).toMatchObject([
|
||||
{
|
||||
title: "Bloc Prime + Clips",
|
||||
description: "No description available",
|
||||
title: 'Bloc Prime + Clips',
|
||||
description: 'No description available',
|
||||
start: dayjs.tz('00:00', 'HH:mm', 'Africa/Casablanca').format('YYYY-MM-DDTHH:mm:ssZ'),
|
||||
stop: dayjs.tz('09:00', 'HH:mm', 'Africa/Casablanca').format('YYYY-MM-DDTHH:mm:ssZ')
|
||||
}
|
||||
|
|
|
@ -16,9 +16,12 @@ module.exports = {
|
|||
const start = parseStart(item)
|
||||
const stop = parseStop(item, start)
|
||||
programs.push({
|
||||
title: item.season?.serie?.title ? item.season.serie.title : item.title,
|
||||
title: item.title,
|
||||
subTitle: item.season?.serie?.title,
|
||||
category: item.genreDetailed,
|
||||
description: item.synopsis,
|
||||
season: parseSeason(item),
|
||||
episode: parseEpisode(item),
|
||||
image: parseImage(item),
|
||||
start: start.toJSON(),
|
||||
stop: stop.toJSON()
|
||||
|
@ -29,7 +32,7 @@ module.exports = {
|
|||
},
|
||||
async channels() {
|
||||
const html = await axios
|
||||
.get(`https://chaines-tv.orange.fr/programme-tv?filtres=all`)
|
||||
.get('https://chaines-tv.orange.fr/programme-tv?filtres=all')
|
||||
.then(r => r.data)
|
||||
.catch(console.log)
|
||||
|
||||
|
@ -61,6 +64,14 @@ function parseStop(item, start) {
|
|||
return start.add(item.duration, 's')
|
||||
}
|
||||
|
||||
function parseSeason(item) {
|
||||
return item.season?.number
|
||||
}
|
||||
|
||||
function parseEpisode(item) {
|
||||
return item.episodeNumber
|
||||
}
|
||||
|
||||
function parseItems(content, channel) {
|
||||
const data = JSON.parse(content)
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@ it('can parse response', () => {
|
|||
start: '2021-11-07T23:35:00.000Z',
|
||||
stop: '2021-11-08T00:20:00.000Z',
|
||||
title: 'Tête de liste',
|
||||
subTitle: 'Esprits criminels',
|
||||
season: 10,
|
||||
episode: 12,
|
||||
description:
|
||||
"Un tueur en série prend un plaisir pervers à prévenir les autorités de Tallahassee avant chaque nouveau meurtre. Rossi apprend le décès d'un de ses vieux amis.",
|
||||
category: 'Série Suspense',
|
||||
|
|
|
@ -40,7 +40,7 @@ module.exports = {
|
|||
},
|
||||
async channels() {
|
||||
const data = await axios
|
||||
.get(`https://contenthub-api.eco.astro.com.my/channel/all.json`)
|
||||
.get('https://contenthub-api.eco.astro.com.my/channel/all.json')
|
||||
.then(r => r.data)
|
||||
.catch(console.log)
|
||||
|
||||
|
@ -85,7 +85,7 @@ function parseItems(content, date) {
|
|||
const schedules = data.response.schedule
|
||||
|
||||
return schedules[date.format('YYYY-MM-DD')] || []
|
||||
} catch (e) {
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,12 +16,13 @@ module.exports = {
|
|||
},
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'referer': 'https://www.cosmotetv.gr/',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
'Accept': '*/*',
|
||||
referer: 'https://www.cosmotetv.gr/',
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
Accept: '*/*',
|
||||
'Accept-Language': 'en-US,en;q=0.9',
|
||||
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
||||
'Origin': 'https://www.cosmotetv.gr',
|
||||
Origin: 'https://www.cosmotetv.gr',
|
||||
'Sec-Ch-Ua': '"Not.A/Brand";v="24", "Chromium";v="131", "Google Chrome";v="131"',
|
||||
'Sec-Ch-Ua-Mobile': '?0',
|
||||
'Sec-Ch-Ua-Platform': '"Windows"',
|
||||
|
@ -30,12 +31,12 @@ module.exports = {
|
|||
'Sec-Fetch-Site': 'cross-site'
|
||||
}
|
||||
},
|
||||
url: function ({date, channel}) {
|
||||
url: function ({ date, channel }) {
|
||||
const startOfDay = dayjs(date).startOf('day').utc().unix()
|
||||
const endOfDay = dayjs(date).endOf('day').utc().unix()
|
||||
return `https://mwapi-prod.cosmotetvott.gr/api/v3.4/epg/listings/el?from=${startOfDay}&to=${endOfDay}&callSigns=${channel.site_id}&endingIncludedInRange=false`
|
||||
},
|
||||
parser: function ({ date, content }) {
|
||||
parser: function ({ content }) {
|
||||
let programs = []
|
||||
const data = JSON.parse(content)
|
||||
data.channels.forEach(channel => {
|
||||
|
@ -57,16 +58,19 @@ module.exports = {
|
|||
async channels() {
|
||||
const axios = require('axios')
|
||||
try {
|
||||
const response = await axios.get('https://mwapi-prod.cosmotetvott.gr/api/v3.4/epg/channels/all/el', {
|
||||
headers: this.request.headers
|
||||
})
|
||||
const response = await axios.get(
|
||||
'https://mwapi-prod.cosmotetvott.gr/api/v3.4/epg/channels/all/el',
|
||||
{
|
||||
headers: this.request.headers
|
||||
}
|
||||
)
|
||||
const data = response.data
|
||||
|
||||
if (data && data.channels) {
|
||||
return data.channels.map(item => ({
|
||||
lang: 'el',
|
||||
site_id: item.callSign,
|
||||
name: item.title,
|
||||
name: item.title
|
||||
//logo: item.logos.square
|
||||
}))
|
||||
} else {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
const { parser, url, channels } = require('./cosmotetv.gr.config.js')
|
||||
const { parser, url } = require('./cosmotetv.gr.config.js')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
const timezone = require('dayjs/plugin/timezone')
|
||||
const axios = require('axios')
|
||||
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(customParseFormat)
|
||||
|
@ -14,34 +13,22 @@ jest.mock('axios')
|
|||
const date = dayjs.utc('2024-12-26', 'YYYY-MM-DD').startOf('d')
|
||||
const channel = { site_id: 'vouli', xmltv_id: 'HellenicParliamentTV.gr' }
|
||||
|
||||
const mockChannelData = {
|
||||
"channels": [
|
||||
{
|
||||
"guid": "XTV100000954",
|
||||
"title": "ΒΟΥΛΗ HD",
|
||||
"callSign": "vouli",
|
||||
"logos": {
|
||||
"square": "https://tr.static.cdn.cosmotetvott.gr/ote-prod/channel_logos/vouli1-normal.png",
|
||||
"wide": "https://tr.static.cdn.cosmotetvott.gr/ote-prod/channel_logos/vouli1-wide.png"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const mockEpgData = {
|
||||
"channels": [
|
||||
channels: [
|
||||
{
|
||||
"items": [
|
||||
items: [
|
||||
{
|
||||
"startTime": "2024-12-26T23:00:00+00:00",
|
||||
"endTime": "2024-12-27T00:00:00+00:00",
|
||||
"title": "Τι Λέει ο Νόμος",
|
||||
"description": "νημερωτική εκπομπή. Συζήτηση με τους εισηγητές των κομμάτων για το νομοθετικό έργο.",
|
||||
"qoe": {
|
||||
"genre": "Special"
|
||||
startTime: '2024-12-26T23:00:00+00:00',
|
||||
endTime: '2024-12-27T00:00:00+00:00',
|
||||
title: 'Τι Λέει ο Νόμος',
|
||||
description:
|
||||
'νημερωτική εκπομπή. Συζήτηση με τους εισηγητές των κομμάτων για το νομοθετικό έργο.',
|
||||
qoe: {
|
||||
genre: 'Special'
|
||||
},
|
||||
"thumbnails": {
|
||||
"standard": "https://gr-ermou-prod-cache05.static.cdn.cosmotetvott.gr/ote-prod/70/280/040029714812000800_1734415727199.jpg"
|
||||
thumbnails: {
|
||||
standard:
|
||||
'https://gr-ermou-prod-cache05.static.cdn.cosmotetvott.gr/ote-prod/70/280/040029714812000800_1734415727199.jpg'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -52,7 +39,9 @@ const mockEpgData = {
|
|||
it('can generate valid url', () => {
|
||||
const startOfDay = dayjs(date).startOf('day').utc().unix()
|
||||
const endOfDay = dayjs(date).endOf('day').utc().unix()
|
||||
expect(url({ date, channel })).toBe(`https://mwapi-prod.cosmotetvott.gr/api/v3.4/epg/listings/el?from=${startOfDay}&to=${endOfDay}&callSigns=${channel.site_id}&endingIncludedInRange=false`)
|
||||
expect(url({ date, channel })).toBe(
|
||||
`https://mwapi-prod.cosmotetvott.gr/api/v3.4/epg/listings/el?from=${startOfDay}&to=${endOfDay}&callSigns=${channel.site_id}&endingIncludedInRange=false`
|
||||
)
|
||||
})
|
||||
|
||||
it('can parse response', () => {
|
||||
|
@ -65,17 +54,23 @@ it('can parse response', () => {
|
|||
|
||||
expect(result).toMatchObject([
|
||||
{
|
||||
title: "Τι Λέει ο Νόμος",
|
||||
description: "νημερωτική εκπομπή. Συζήτηση με τους εισηγητές των κομμάτων για το νομοθετικό έργο.",
|
||||
category: "Special",
|
||||
image: "https://gr-ermou-prod-cache05.static.cdn.cosmotetvott.gr/ote-prod/70/280/040029714812000800_1734415727199.jpg",
|
||||
start: "2024-12-26T23:00:00.000Z",
|
||||
stop: "2024-12-27T00:00:00.000Z"
|
||||
title: 'Τι Λέει ο Νόμος',
|
||||
description:
|
||||
'νημερωτική εκπομπή. Συζήτηση με τους εισηγητές των κομμάτων για το νομοθετικό έργο.',
|
||||
category: 'Special',
|
||||
image:
|
||||
'https://gr-ermou-prod-cache05.static.cdn.cosmotetvott.gr/ote-prod/70/280/040029714812000800_1734415727199.jpg',
|
||||
start: '2024-12-26T23:00:00.000Z',
|
||||
stop: '2024-12-27T00:00:00.000Z'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it('can handle empty guide', () => {
|
||||
const result = parser({ date, channel, content: '{"date":"2024-12-26","categories":[],"channels":[]}' });
|
||||
const result = parser({
|
||||
date,
|
||||
channel,
|
||||
content: '{"date":"2024-12-26","categories":[],"channels":[]}'
|
||||
})
|
||||
expect(result).toMatchObject([])
|
||||
})
|
||||
|
|
|
@ -9,7 +9,9 @@ module.exports = {
|
|||
site: 'cubmu.com',
|
||||
days: 2,
|
||||
url({ channel, date }) {
|
||||
return `https://servicebuss.transvision.co.id/v2/cms/getEPGData?app_id=cubmu&tvs_platform_id=standalone&schedule_date=${date.format('YYYY-MM-DD')}&channel_id=${channel.site_id}`
|
||||
return `https://servicebuss.transvision.co.id/v2/cms/getEPGData?app_id=cubmu&tvs_platform_id=standalone&schedule_date=${date.format(
|
||||
'YYYY-MM-DD'
|
||||
)}&channel_id=${channel.site_id}`
|
||||
},
|
||||
parser({ content, channel }) {
|
||||
const programs = []
|
||||
|
@ -46,13 +48,19 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
// login to service bus
|
||||
const token = await axios
|
||||
.post(`https://servicebuss.transvision.co.id/tvs/login/external?email=${config.email}&password=${config.password}&deviceId=${config.deviceId}&deviceType=${config.deviceType}&deviceModel=${config.deviceModel}&deviceToken=&serial=&platformId=${config.platformId}`, options)
|
||||
await axios
|
||||
.post(
|
||||
`https://servicebuss.transvision.co.id/tvs/login/external?email=${config.email}&password=${config.password}&deviceId=${config.deviceId}&deviceType=${config.deviceType}&deviceModel=${config.deviceModel}&deviceToken=&serial=&platformId=${config.platformId}`,
|
||||
options
|
||||
)
|
||||
.then(response => response.data)
|
||||
.catch(console.error)
|
||||
// list channels
|
||||
const subscribedChannels = await axios
|
||||
.post(`https://servicebuss.transvision.co.id/tvs/subscribe_product/list?platformId=${config.platformId}`, options)
|
||||
.post(
|
||||
`https://servicebuss.transvision.co.id/tvs/subscribe_product/list?platformId=${config.platformId}`,
|
||||
options
|
||||
)
|
||||
.then(response => response.data)
|
||||
.catch(console.error)
|
||||
|
||||
|
@ -98,5 +106,9 @@ function parseStart(item) {
|
|||
}
|
||||
|
||||
function parseStop(item) {
|
||||
return dayjs.tz([item.schedule_date.split(' ')[0], item.schedule_end_time].join(' '), 'YYYY-MM-DD HH:mm:ss', 'Asia/Jakarta')
|
||||
return dayjs.tz(
|
||||
[item.schedule_date.split(' ')[0], item.schedule_end_time].join(' '),
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
'Asia/Jakarta'
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ const dayjs = require('dayjs')
|
|||
const utc = require('dayjs/plugin/utc')
|
||||
const timezone = require('dayjs/plugin/timezone')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
const cheerio = require('cheerio')
|
||||
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
|
@ -16,21 +15,21 @@ module.exports = {
|
|||
ttl: 60 * 60 * 1000 // 1 hour
|
||||
}
|
||||
},
|
||||
url: function ({date, channel}) {
|
||||
url: function ({ date, channel }) {
|
||||
// Get the epoch timestamp
|
||||
const todayEpoch = date.startOf('day').utc().valueOf()
|
||||
// Get the epoch timestamp for the next day
|
||||
const nextDayEpoch = date.add(1, 'day').startOf('day').utc().valueOf()
|
||||
return `https://epg.cyta.com.cy/api/mediacatalog/fetchEpg?startTimeEpoch=${todayEpoch}&endTimeEpoch=${nextDayEpoch}&language=1&channelIds=${channel.site_id}`
|
||||
},
|
||||
parser: function ({content}) {
|
||||
parser: function ({ content }) {
|
||||
const data = JSON.parse(content)
|
||||
const programs = []
|
||||
|
||||
data.channelEpgs.forEach(channel => {
|
||||
channel.epgPlayables.forEach(epg => {
|
||||
const start = new Date(epg.startTime).toISOString();
|
||||
const stop = new Date(epg.endTime).toISOString();
|
||||
const start = new Date(epg.startTime).toISOString()
|
||||
const stop = new Date(epg.endTime).toISOString()
|
||||
|
||||
programs.push({
|
||||
title: epg.name,
|
||||
|
@ -45,7 +44,7 @@ module.exports = {
|
|||
async channels() {
|
||||
const axios = require('axios')
|
||||
const data = await axios
|
||||
.get(`https://epg.cyta.com.cy/api/mediacatalog/fetchChannels?language=1`)
|
||||
.get('https://epg.cyta.com.cy/api/mediacatalog/fetchChannels?language=1')
|
||||
.then(r => r.data)
|
||||
.catch(console.log)
|
||||
|
||||
|
|
|
@ -30,11 +30,7 @@ it('can parse response', () => {
|
|||
]
|
||||
}`
|
||||
|
||||
const result = parser({ content }).map(p => {
|
||||
p.start = p.start
|
||||
p.stop = p.stop
|
||||
return p
|
||||
})
|
||||
const result = parser({ content })
|
||||
|
||||
expect(result).toMatchObject([
|
||||
{
|
||||
|
|
|
@ -13,9 +13,9 @@ module.exports = {
|
|||
site: 'dens.tv',
|
||||
days: 2,
|
||||
url({ channel, date }) {
|
||||
return `https://www.dens.tv/api/dens3/tv/TvChannels/listEpgByDate?date=${date.format('YYYY-MM-DD')}&id_channel=${
|
||||
channel.site_id
|
||||
}&app_type=10`
|
||||
return `https://www.dens.tv/api/dens3/tv/TvChannels/listEpgByDate?date=${date.format(
|
||||
'YYYY-MM-DD'
|
||||
)}&id_channel=${channel.site_id}&app_type=10`
|
||||
},
|
||||
parser({ content }) {
|
||||
// parsing
|
||||
|
@ -25,8 +25,9 @@ module.exports = {
|
|||
if (Array.isArray(response?.data)) {
|
||||
response.data.forEach(item => {
|
||||
const title = item.title
|
||||
const [, , , season, , , episode] = title.match(/( (Season |Season|S)(\d+))?( (Episode|Ep) (\d+))/) ||
|
||||
[null, null, null, null, null, null, null]
|
||||
const [, , , season, , , episode] = title.match(
|
||||
/( (Season |Season|S)(\d+))?( (Episode|Ep) (\d+))/
|
||||
) || [null, null, null, null, null, null, null]
|
||||
programs.push({
|
||||
title,
|
||||
description: item.description,
|
||||
|
@ -52,7 +53,7 @@ module.exports = {
|
|||
const channels = []
|
||||
for (const id_category of Object.values(categories)) {
|
||||
const data = await axios
|
||||
.get(`https://www.dens.tv/api/dens3/tv/TvChannels/listByCategory`, {
|
||||
.get('https://www.dens.tv/api/dens3/tv/TvChannels/listByCategory', {
|
||||
params: { id_category }
|
||||
})
|
||||
.then(r => r.data)
|
||||
|
|
|
@ -10,7 +10,9 @@ const date = dayjs.utc('2024-11-24').startOf('d')
|
|||
const channel = { site_id: '38', xmltv_id: 'AniplusAsia.sg', lang: 'id' }
|
||||
|
||||
it('can generate valid url', () => {
|
||||
expect(url({ channel, date })).toBe('https://www.dens.tv/api/dens3/tv/TvChannels/listEpgByDate?date=2024-11-24&id_channel=38&app_type=10')
|
||||
expect(url({ channel, date })).toBe(
|
||||
'https://www.dens.tv/api/dens3/tv/TvChannels/listEpgByDate?date=2024-11-24&id_channel=38&app_type=10'
|
||||
)
|
||||
})
|
||||
|
||||
it('can parse response', () => {
|
||||
|
|
|
@ -65,7 +65,7 @@ module.exports = {
|
|||
const cheerio = require('cheerio')
|
||||
|
||||
const data = await axios
|
||||
.get(`https://www.digiturk.com.tr/`, {
|
||||
.get('https://www.digiturk.com.tr/', {
|
||||
headers: {
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
|
||||
|
|
|
@ -60,7 +60,7 @@ module.exports = {
|
|||
$('.pgrid').each((i, el) => {
|
||||
const onclick = $(el).find('.chnl-logo').attr('onclick')
|
||||
const number = $(el).find('.cnl-fav > a > span').text().trim()
|
||||
const [, name, site_id] = onclick.match(/ShowChannelGuid\('([^']+)','([^']+)'/) || [
|
||||
const [, , site_id] = onclick.match(/ShowChannelGuid\('([^']+)','([^']+)'/) || [
|
||||
null,
|
||||
'',
|
||||
''
|
||||
|
|
|
@ -49,7 +49,7 @@ module.exports = {
|
|||
const channels = []
|
||||
for (let provider of providers) {
|
||||
const data = await axios
|
||||
.post(`https://www.guida.tv/guide/schedule`, null, {
|
||||
.post('https://www.guida.tv/guide/schedule', null, {
|
||||
params: {
|
||||
provider,
|
||||
region: 'Italy',
|
||||
|
@ -81,7 +81,7 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
|
||||
function parseStart($item, date, channel) {
|
||||
function parseStart($item, date) {
|
||||
const timeString = $item('td:eq(0)').text().trim()
|
||||
const dateString = `${date.format('YYYY-MM-DD')} ${timeString}`
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ module.exports = {
|
|||
const cheerio = require('cheerio')
|
||||
|
||||
const data = await axios
|
||||
.get(`https://guidatv.sky.it/canali`)
|
||||
.get('https://guidatv.sky.it/canali')
|
||||
.then(r => r.data)
|
||||
.catch(console.log)
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ module.exports = {
|
|||
url: function ({ channel, date }) {
|
||||
return `https://epg-file.hoy.tv/hoy/OTT${channel.site_id}${date.format('YYYYMMDD')}.xml`
|
||||
},
|
||||
parser({ content, channel, date }) {
|
||||
parser({ content, date }) {
|
||||
const data = convert.xml2js(content, {
|
||||
compact: true,
|
||||
ignoreDeclaration: true,
|
||||
|
@ -28,7 +28,7 @@ module.exports = {
|
|||
for (let item of data.ProgramGuide.Channel.EpgItem) {
|
||||
const start = dayjs.tz(item.EpgStartDateTime._text, 'YYYY-MM-DD HH:mm:ss', 'Asia/Hong_Kong')
|
||||
|
||||
if (! date.isSame(start, 'day')) {
|
||||
if (!date.isSame(start, 'day')) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -40,13 +40,13 @@ module.exports = {
|
|||
sub_title: subtitle,
|
||||
description: item.EpisodeInfo.EpisodeLongDescription._text,
|
||||
start,
|
||||
stop: dayjs.tz(item.EpgEndDateTime._text, 'YYYY-MM-DD HH:mm:ss', 'Asia/Hong_Kong'),
|
||||
stop: dayjs.tz(item.EpgEndDateTime._text, 'YYYY-MM-DD HH:mm:ss', 'Asia/Hong_Kong')
|
||||
})
|
||||
}
|
||||
|
||||
return programs
|
||||
},
|
||||
async channels({ lang }) {
|
||||
async channels() {
|
||||
const data = await axios
|
||||
.get('https://api2.hoy.tv/api/v2/a/channel')
|
||||
.then(r => r.data)
|
||||
|
@ -56,7 +56,7 @@ module.exports = {
|
|||
return {
|
||||
site_id: c.videos.id,
|
||||
name: c.name.zh_hk,
|
||||
lang: 'zh',
|
||||
lang: 'zh'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -87,9 +87,7 @@ const content = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
</ProgramGuide>`
|
||||
|
||||
it('can generate valid url', () => {
|
||||
expect(url({ channel, date })).toBe(
|
||||
'https://epg-file.hoy.tv/hoy/OTT7620240913.xml'
|
||||
)
|
||||
expect(url({ channel, date })).toBe('https://epg-file.hoy.tv/hoy/OTT7620240913.xml')
|
||||
})
|
||||
|
||||
it('can parse response', () => {
|
||||
|
@ -104,13 +102,14 @@ it('can parse response', () => {
|
|||
start: '2024-09-13T03:30:00.000Z',
|
||||
stop: '2024-09-13T04:30:00.000Z',
|
||||
title: '點講都係一家人[PG]',
|
||||
sub_title: '第46集',
|
||||
sub_title: '第46集'
|
||||
},
|
||||
{
|
||||
start: '2024-09-13T04:30:00.000Z',
|
||||
stop: '2024-09-13T05:30:00.000Z',
|
||||
title: '麝香之路',
|
||||
description: 'Ep. 2 .The Secret of disappeared kingdom.shows the mysterious disappearance of the ancient Tibetan kingdom which gained world',
|
||||
description:
|
||||
'Ep. 2 .The Secret of disappeared kingdom.shows the mysterious disappearance of the ancient Tibetan kingdom which gained world'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
|
|
@ -172,14 +172,17 @@ function parseItems(content, channel, date) {
|
|||
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))
|
||||
.filter(
|
||||
p =>
|
||||
p.channel === site_id && dayjs(p.start, 'YYYYMMDDHHmmss ZZ').isBetween(curr_day, next_day)
|
||||
)
|
||||
.map(p => {
|
||||
if (Array.isArray(p.date) && p.date.length) {
|
||||
p.date = p.date[0]
|
||||
}
|
||||
return p
|
||||
})
|
||||
} catch (error) {
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,27 +12,30 @@ module.exports = {
|
|||
site: 'ipko.tv',
|
||||
timezone: 'Europe/Belgrade',
|
||||
days: 5,
|
||||
url({ date, channel }) { return 'https://stargate.ipko.tv/api/titan.tv.WebEpg/GetWebEpgData' },
|
||||
url() {
|
||||
return 'https://stargate.ipko.tv/api/titan.tv.WebEpg/GetWebEpgData'
|
||||
},
|
||||
request: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Host': 'stargate.ipko.tv',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
Host: 'stargate.ipko.tv',
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
|
||||
Accept: 'application/json, text/plain, */*',
|
||||
'Accept-Language': 'nl,en-US;q=0.7,en;q=0.3',
|
||||
'Content-Type': 'application/json',
|
||||
'X-AppLayout': '1',
|
||||
'x-language': 'sq',
|
||||
'Origin': 'https://ipko.tv',
|
||||
Origin: 'https://ipko.tv',
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Sec-Fetch-Site': 'cross-site',
|
||||
'Sec-GPC': '1',
|
||||
'Connection': 'keep-alive'
|
||||
Connection: 'keep-alive'
|
||||
},
|
||||
data({ channel, date }) {
|
||||
const todayEpoch = date.startOf('day').unix();
|
||||
const nextDayEpoch = date.add(1, 'day').startOf('day').unix();
|
||||
const todayEpoch = date.startOf('day').unix()
|
||||
const nextDayEpoch = date.add(1, 'day').startOf('day').unix()
|
||||
return JSON.stringify({
|
||||
ch_ext_id: channel.site_id,
|
||||
from: todayEpoch,
|
||||
|
@ -41,11 +44,11 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
parser: function ({ content }) {
|
||||
const programs = [];
|
||||
const data = JSON.parse(content);
|
||||
const programs = []
|
||||
const data = JSON.parse(content)
|
||||
data.shows.forEach(show => {
|
||||
const start = dayjs.unix(show.show_start).utc();
|
||||
const stop = dayjs.unix(show.show_end).utc();
|
||||
const start = dayjs.unix(show.show_start).utc()
|
||||
const stop = dayjs.unix(show.show_end).utc()
|
||||
const programData = {
|
||||
title: show.title,
|
||||
description: show.summary || 'No description available',
|
||||
|
@ -58,15 +61,19 @@ module.exports = {
|
|||
return programs
|
||||
},
|
||||
async channels() {
|
||||
const response = await axios.post('https://stargate.ipko.tv/api/titan.tv.WebEpg/ZapList', JSON.stringify({ includeRadioStations: true }), {
|
||||
headers: this.request.headers
|
||||
});
|
||||
const response = await axios.post(
|
||||
'https://stargate.ipko.tv/api/titan.tv.WebEpg/ZapList',
|
||||
JSON.stringify({ includeRadioStations: true }),
|
||||
{
|
||||
headers: this.request.headers
|
||||
}
|
||||
)
|
||||
|
||||
const data = response.data.data;
|
||||
const data = response.data.data
|
||||
return data.map(item => ({
|
||||
lang: 'sq',
|
||||
name: String(item.channel.title),
|
||||
site_id: String(item.channel.id),
|
||||
site_id: String(item.channel.id)
|
||||
//logo: String(item.channel.logo)
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -76,33 +76,29 @@ it('can parse response', () => {
|
|||
]
|
||||
}`
|
||||
|
||||
const result = parser({ content, channel }).map(p => {
|
||||
p.start = p.start
|
||||
p.stop = p.stop
|
||||
return p
|
||||
})
|
||||
const result = parser({ content, channel })
|
||||
|
||||
expect(result).toMatchObject([
|
||||
{
|
||||
title: "IPKO Promo",
|
||||
description: "No description available",
|
||||
start: "2024-12-24T04:00:00.000Z",
|
||||
stop: "2024-12-24T06:00:00.000Z",
|
||||
thumbnail: "https://vimg.ipko.tv/mtcms/18/2/1/1821cc68-a9bf-4733-b1af-9a5d80163b78.jpg"
|
||||
title: 'IPKO Promo',
|
||||
description: 'No description available',
|
||||
start: '2024-12-24T04:00:00.000Z',
|
||||
stop: '2024-12-24T06:00:00.000Z',
|
||||
thumbnail: 'https://vimg.ipko.tv/mtcms/18/2/1/1821cc68-a9bf-4733-b1af-9a5d80163b78.jpg'
|
||||
},
|
||||
{
|
||||
title: "IPKO Promo",
|
||||
description: "No description available",
|
||||
start: "2024-12-24T06:00:00.000Z",
|
||||
stop: "2024-12-24T08:00:00.000Z",
|
||||
thumbnail: "https://vimg.ipko.tv/mtcms/18/2/1/1821cc68-a9bf-4733-b1af-9a5d80163b78.jpg"
|
||||
title: 'IPKO Promo',
|
||||
description: 'No description available',
|
||||
start: '2024-12-24T06:00:00.000Z',
|
||||
stop: '2024-12-24T08:00:00.000Z',
|
||||
thumbnail: 'https://vimg.ipko.tv/mtcms/18/2/1/1821cc68-a9bf-4733-b1af-9a5d80163b78.jpg'
|
||||
},
|
||||
{
|
||||
title: "IPKO Promo",
|
||||
description: "No description available",
|
||||
start: "2024-12-24T08:00:00.000Z",
|
||||
stop: "2024-12-24T10:00:00.000Z",
|
||||
thumbnail: "https://vimg.ipko.tv/mtcms/18/2/1/1821cc68-a9bf-4733-b1af-9a5d80163b78.jpg"
|
||||
title: 'IPKO Promo',
|
||||
description: 'No description available',
|
||||
start: '2024-12-24T08:00:00.000Z',
|
||||
stop: '2024-12-24T10:00:00.000Z',
|
||||
thumbnail: 'https://vimg.ipko.tv/mtcms/18/2/1/1821cc68-a9bf-4733-b1af-9a5d80163b78.jpg'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
|
|
@ -38,7 +38,7 @@ module.exports = {
|
|||
async channels() {
|
||||
const axios = require('axios')
|
||||
const data = await axios
|
||||
.get(`https://m.tv.sms.cz/?zmen_stanice=true`)
|
||||
.get('https://m.tv.sms.cz/?zmen_stanice=true')
|
||||
.then(r => r.data)
|
||||
.catch(console.log)
|
||||
|
||||
|
|
|
@ -77,8 +77,8 @@ function parseItems(content) {
|
|||
let data
|
||||
try {
|
||||
data = JSON.parse(content)
|
||||
} catch (error) {
|
||||
console.log(error.message)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
if (!data || !Array.isArray(data)) return []
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ module.exports = {
|
|||
async channels() {
|
||||
const axios = require('axios')
|
||||
const data = await axios
|
||||
.get(`https://player.maxtvtogo.tportal.hr:8082/OTT4Proxy/proxy/epg/channels`)
|
||||
.get('https://player.maxtvtogo.tportal.hr:8082/OTT4Proxy/proxy/epg/channels')
|
||||
.then(r => r.data)
|
||||
.catch(console.log)
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ function parseStop($item) {
|
|||
|
||||
try {
|
||||
return dayjs(timeString, 'YYYY-MM-DD HH:mm:ssZZ')
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,31 +10,35 @@ dayjs.extend(timezone)
|
|||
module.exports = {
|
||||
site: 'mediasetinfinity.mediaset.it',
|
||||
days: 2,
|
||||
url: function ({date, channel}) {
|
||||
url: function ({ date, channel }) {
|
||||
// Get the epoch timestamp
|
||||
const todayEpoch = date.startOf('day').utc().valueOf()
|
||||
// Get the epoch timestamp for the next day
|
||||
const nextDayEpoch = date.add(1, 'day').startOf('day').utc().valueOf()
|
||||
return `https://api-ott-prod-fe.mediaset.net/PROD/play/feed/allListingFeedEpg/v2.0?byListingTime=${todayEpoch}~${nextDayEpoch}&byCallSign=${channel.site_id}`
|
||||
},
|
||||
parser: function ({content}) {
|
||||
parser: function ({ content }) {
|
||||
const programs = []
|
||||
const data = JSON.parse(content)
|
||||
|
||||
if (!data.response || !data.response.entries || !data.response.entries[0] || !data.response.entries[0].listings) {
|
||||
if (
|
||||
!data.response ||
|
||||
!data.response.entries ||
|
||||
!data.response.entries[0] ||
|
||||
!data.response.entries[0].listings
|
||||
) {
|
||||
// If the structure is not as expected, return an empty array
|
||||
return programs
|
||||
}
|
||||
|
||||
const listings = data.response.entries[0].listings
|
||||
|
||||
listings.forEach((listing) => {
|
||||
listings.forEach(listing => {
|
||||
const title = listing.mediasetlisting$epgTitle
|
||||
const subTitle = listing.program.title
|
||||
const season = parseSeason(listing)
|
||||
const episode = parseEpisode(listing)
|
||||
|
||||
|
||||
if (listing.program.title && listing.startTime && listing.endTime) {
|
||||
programs.push({
|
||||
title: title || subTitle,
|
||||
|
@ -54,7 +58,6 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function parseTime(timestamp) {
|
||||
return dayjs(timestamp).utc().format('YYYY-MM-DD HH:mm')
|
||||
}
|
||||
|
@ -77,17 +80,18 @@ function getMaxResolutionThumbnails(item) {
|
|||
|
||||
for (const key in thumbnails) {
|
||||
const type = key.split('-')[0] // Estrarre il tipo di thumbnail
|
||||
const {width, height, url, title} = thumbnails[key]
|
||||
const { width, height, url, title } = thumbnails[key]
|
||||
|
||||
if (!maxResolutionThumbnails[type] ||
|
||||
(width * height > maxResolutionThumbnails[type].width * maxResolutionThumbnails[type].height)) {
|
||||
maxResolutionThumbnails[type] = {width, height, url, title}
|
||||
if (
|
||||
!maxResolutionThumbnails[type] ||
|
||||
width * height > maxResolutionThumbnails[type].width * maxResolutionThumbnails[type].height
|
||||
) {
|
||||
maxResolutionThumbnails[type] = { width, height, url, title }
|
||||
}
|
||||
}
|
||||
if (maxResolutionThumbnails.image_keyframe_poster)
|
||||
return maxResolutionThumbnails.image_keyframe_poster.url
|
||||
else if (maxResolutionThumbnails.image_header_poster)
|
||||
return maxResolutionThumbnails.image_header_poster.url
|
||||
else
|
||||
return null
|
||||
else return null
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const {parser, url} = require('./mediasetinfinity.mediaset.it.config.js')
|
||||
const { parser, url } = require('./mediasetinfinity.mediaset.it.config.js')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const dayjs = require('dayjs')
|
||||
|
@ -9,19 +9,24 @@ dayjs.extend(utc)
|
|||
|
||||
const date = dayjs.utc('2024-01-20', 'YYYY-MM-DD').startOf('d')
|
||||
const channel = {
|
||||
site_id: 'LB', xmltv_id: '20.it'
|
||||
site_id: 'LB',
|
||||
xmltv_id: '20.it'
|
||||
}
|
||||
|
||||
it('can generate valid url', () => {
|
||||
expect(url({
|
||||
channel,
|
||||
date
|
||||
})).toBe('https://api-ott-prod-fe.mediaset.net/PROD/play/feed/allListingFeedEpg/v2.0?byListingTime=1705708800000~1705795200000&byCallSign=LB')
|
||||
expect(
|
||||
url({
|
||||
channel,
|
||||
date
|
||||
})
|
||||
).toBe(
|
||||
'https://api-ott-prod-fe.mediaset.net/PROD/play/feed/allListingFeedEpg/v2.0?byListingTime=1705708800000~1705795200000&byCallSign=LB'
|
||||
)
|
||||
})
|
||||
|
||||
it('can parse response', () => {
|
||||
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'), 'utf8')
|
||||
const results = parser({content, date}).map(p => {
|
||||
const results = parser({ content, date }).map(p => {
|
||||
return p
|
||||
})
|
||||
|
||||
|
@ -30,11 +35,13 @@ it('can parse response', () => {
|
|||
stop: '2024-01-20 02:54',
|
||||
title: 'Chicago Fire',
|
||||
sub_title: 'Ep. 22 - Io non ti lascio',
|
||||
description: 'Severide e Kidd continuano a indagare su un vecchio caso doloso di Benny. Notizie inaspettate portano Brett a meditare su una grande decisione.',
|
||||
description:
|
||||
'Severide e Kidd continuano a indagare su un vecchio caso doloso di Benny. Notizie inaspettate portano Brett a meditare su una grande decisione.',
|
||||
category: 'Intrattenimento',
|
||||
season: '7',
|
||||
episode: '22',
|
||||
image: 'https://static2.mediasetplay.mediaset.it/Mediaset_Italia_Production_-_Main/F309370301002204/media/0/0/1ef76b73-3173-43bd-9c16-73986a0ec131/46896726-11e7-4438-b947-d2ae53f58c0b.jpg'
|
||||
image:
|
||||
'https://static2.mediasetplay.mediaset.it/Mediaset_Italia_Production_-_Main/F309370301002204/media/0/0/1ef76b73-3173-43bd-9c16-73986a0ec131/46896726-11e7-4438-b947-d2ae53f58c0b.jpg'
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ module.exports = {
|
|||
async channels() {
|
||||
const axios = require('axios')
|
||||
const data = await axios
|
||||
.post(`https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getGridAnon`, null, {
|
||||
.post('https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getGridAnon', null, {
|
||||
headers: {
|
||||
Origin: 'https://www.meo.pt'
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ module.exports = {
|
|||
.catch(console.error)
|
||||
|
||||
if (content) {
|
||||
const [ $, items ] = getItems(content)
|
||||
const [$, items] = getItems(content)
|
||||
if (seq === 0) {
|
||||
queues.push(...items.map(category => baseUrl + $(category).attr('href')))
|
||||
} else {
|
||||
|
@ -86,7 +86,11 @@ function parseItems(content, date) {
|
|||
data.season = parseInt(ep[1])
|
||||
data.episode = parseInt(ep[2])
|
||||
}
|
||||
data.start = dayjs.tz(`${lastDate} ${$item.find('.time').text()}`, 'DD/MM/YYYY HH:mm', 'America/Sao_Paulo')
|
||||
data.start = dayjs.tz(
|
||||
`${lastDate} ${$item.find('.time').text()}`,
|
||||
'DD/MM/YYYY HH:mm',
|
||||
'America/Sao_Paulo'
|
||||
)
|
||||
result.push(data)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ module.exports = {
|
|||
const axios = require('axios')
|
||||
const cheerio = require('cheerio')
|
||||
const data = await axios
|
||||
.get(`https://www.mewatch.sg/channel-guide`)
|
||||
.get('https://www.mewatch.sg/channel-guide')
|
||||
.then(r => r.data)
|
||||
.catch(console.log)
|
||||
|
||||
|
|
|
@ -11,9 +11,7 @@ dayjs.extend(utc)
|
|||
dayjs.extend(timezone)
|
||||
dayjs.extend(customParseFormat)
|
||||
|
||||
doFetch
|
||||
.setCheckResult(false)
|
||||
.setDebugger(debug)
|
||||
doFetch.setCheckResult(false).setDebugger(debug)
|
||||
|
||||
const languages = { en: 'english', id: 'indonesia' }
|
||||
const cookies = {}
|
||||
|
@ -125,7 +123,7 @@ async function parseItems(content, date, cookies) {
|
|||
const url = $item.find('a').attr('href')
|
||||
const headers = {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
Cookie: cookies,
|
||||
Cookie: cookies
|
||||
}
|
||||
queues.push({ i: $item, url, params: { headers, timeout } })
|
||||
}
|
||||
|
|
|
@ -48,8 +48,10 @@ function parseItems(context) {
|
|||
schDayPrograms.forEach((program, i) => {
|
||||
const itemDay = {
|
||||
progStart: parseStart($(schDayMonth), $(program)),
|
||||
progStop: parseStop($(schDayMonth), schDayPrograms[i + 1] ?
|
||||
$(schDayPrograms[i + 1]) : null),
|
||||
progStop: parseStop(
|
||||
$(schDayMonth),
|
||||
schDayPrograms[i + 1] ? $(schDayPrograms[i + 1]) : null
|
||||
),
|
||||
progTitle: parseTitle($(program)),
|
||||
progDesc: parseDescription($(program))
|
||||
}
|
||||
|
@ -91,7 +93,9 @@ function parseStop(schDayMonth, itemNext) {
|
|||
)
|
||||
} else {
|
||||
return dayjs.tz(
|
||||
`${currentYear}-${monthDate[0]}-${(parseInt(monthDate[1]) + 1).toString().padStart(2, '0')} 00:00`,
|
||||
`${currentYear}-${monthDate[0]}-${(parseInt(monthDate[1]) + 1)
|
||||
.toString()
|
||||
.padStart(2, '0')} 00:00`,
|
||||
'YYYY-MMM-DD HH:mm',
|
||||
tz
|
||||
)
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -41,7 +41,7 @@ module.exports = {
|
|||
const pages = Array.from(Array(totalPages).keys())
|
||||
for (let page of pages) {
|
||||
const data = await axios
|
||||
.get(`https://mtel.ba/oec/epg/program`, {
|
||||
.get('https://mtel.ba/oec/epg/program', {
|
||||
params: { page, date: dayjs().format('YYYY-MM-DD') },
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
|
@ -65,7 +65,7 @@ module.exports = {
|
|||
|
||||
async function getTotalPageCount() {
|
||||
const data = await axios
|
||||
.get(`https://mtel.ba/oec/epg/program`, {
|
||||
.get('https://mtel.ba/oec/epg/program', {
|
||||
params: { page: 0, date: dayjs().format('YYYY-MM-DD') },
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
|
|
|
@ -43,7 +43,7 @@ module.exports = {
|
|||
const pages = Array.from(Array(totalPages).keys())
|
||||
for (let page of pages) {
|
||||
const data = await axios
|
||||
.get(`https://mts.rs/oec/epg/program`, {
|
||||
.get('https://mts.rs/oec/epg/program', {
|
||||
params: { page, date: dayjs().format('YYYY-MM-DD') },
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
|
@ -67,7 +67,7 @@ module.exports = {
|
|||
|
||||
async function getTotalPageCount() {
|
||||
const data = await axios
|
||||
.get(`https://mts.rs/oec/epg/program`, {
|
||||
.get('https://mts.rs/oec/epg/program', {
|
||||
params: { page: 0, date: dayjs().format('YYYY-MM-DD') },
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
|
@ -84,8 +84,8 @@ function parseContent(content, channel) {
|
|||
let data
|
||||
try {
|
||||
data = JSON.parse(content)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
if (!data || !data.channels || !data.channels.length) return null
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ module.exports = {
|
|||
|
||||
const data = await axios
|
||||
.post(
|
||||
`https://services.mujtvprogram.cz/tvprogram2services/services/tvchannellist_mobile.php`,
|
||||
'https://services.mujtvprogram.cz/tvprogram2services/services/tvchannellist_mobile.php',
|
||||
params,
|
||||
{
|
||||
headers: {
|
||||
|
@ -86,7 +86,7 @@ function parseItems(content) {
|
|||
if (!data) return []
|
||||
const programmes = data['tv-program-programmes'].programme
|
||||
return programmes && Array.isArray(programmes) ? programmes : []
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ dayjs.extend(customParseFormat)
|
|||
|
||||
const headers = {
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 OPR/115.0.0.0',
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 OPR/115.0.0.0'
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -26,12 +26,11 @@ it('can generate valid url for today', () => {
|
|||
|
||||
it('can parse response', () => {
|
||||
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.html'))
|
||||
const results = parser({ content, date })
|
||||
.map(p => {
|
||||
p.start = p.start.toJSON()
|
||||
p.stop = p.stop.toJSON()
|
||||
return p
|
||||
})
|
||||
const results = parser({ content, date }).map(p => {
|
||||
p.start = p.start.toJSON()
|
||||
p.stop = p.stop.toJSON()
|
||||
return p
|
||||
})
|
||||
|
||||
expect(results[0]).toMatchObject({
|
||||
start: '2022-11-19T23:00:00.000Z',
|
||||
|
|
|
@ -23,14 +23,15 @@ module.exports = {
|
|||
channel.site_id
|
||||
}.html?dt=${date.format('YYYY-MM-DD')}`
|
||||
},
|
||||
async parser({ content, date, channel }) {
|
||||
async parser({ content, date }) {
|
||||
const programs = []
|
||||
|
||||
if (content) {
|
||||
const queues = []
|
||||
const $ = cheerio.load(content)
|
||||
|
||||
$('table.table > tbody > tr').toArray()
|
||||
$('table.table > tbody > tr')
|
||||
.toArray()
|
||||
.forEach(el => {
|
||||
const td = $(el).find('td:eq(1)')
|
||||
const title = td.find('h5 a')
|
||||
|
@ -66,12 +67,16 @@ module.exports = {
|
|||
const subTitle = parseText($('.tab-pane > h5 > strong'))
|
||||
const description = parseText($('.tab-pane > .tvbody > p'))
|
||||
const image = $('.program-media-image img').attr('src')
|
||||
const category = $('.schedule-attributes-genres span').toArray()
|
||||
const category = $('.schedule-attributes-genres span')
|
||||
.toArray()
|
||||
.map(el => $(el).text())
|
||||
const casts = $('.single-cast-head:not([id])').toArray()
|
||||
const casts = $('.single-cast-head:not([id])')
|
||||
.toArray()
|
||||
.map(el => {
|
||||
const cast = { name: parseText($(el).find('a')) }
|
||||
const [, role] = $(el).text().match(/\((.*)\)/) || [null, null]
|
||||
const [, role] = $(el)
|
||||
.text()
|
||||
.match(/\((.*)\)/) || [null, null]
|
||||
if (role) {
|
||||
cast.role = role
|
||||
}
|
||||
|
@ -102,7 +107,7 @@ module.exports = {
|
|||
start,
|
||||
stop
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,11 +120,17 @@ module.exports = {
|
|||
// process form -> provider
|
||||
if (queue.t === 'p') {
|
||||
const $ = cheerio.load(res)
|
||||
$('#guide_provider option').toArray()
|
||||
$('#guide_provider option')
|
||||
.toArray()
|
||||
.forEach(el => {
|
||||
const opt = $(el)
|
||||
const provider = opt.attr('value')
|
||||
queues.push({ t: 'r', method: 'post', url: 'https://www.mytelly.co.uk/getregions', params: { provider } })
|
||||
queues.push({
|
||||
t: 'r',
|
||||
method: 'post',
|
||||
url: 'https://www.mytelly.co.uk/getregions',
|
||||
params: { provider }
|
||||
})
|
||||
})
|
||||
}
|
||||
// process provider -> region
|
||||
|
@ -135,26 +146,30 @@ module.exports = {
|
|||
u_time: now.format('HHmm'),
|
||||
is_mobile: 1
|
||||
}
|
||||
queues.push({ t: 's', method: 'post', url: 'https://www.mytelly.co.uk/tv-guide/schedule', params })
|
||||
queues.push({
|
||||
t: 's',
|
||||
method: 'post',
|
||||
url: 'https://www.mytelly.co.uk/tv-guide/schedule',
|
||||
params
|
||||
})
|
||||
}
|
||||
}
|
||||
// process schedule -> channels
|
||||
if (queue.t === 's') {
|
||||
const $ = cheerio.load(res)
|
||||
$('.channelname')
|
||||
.each((i, el) => {
|
||||
const name = $(el).find('center > a:eq(1)').text()
|
||||
const url = $(el).find('center > a:eq(1)').attr('href')
|
||||
const [, number, slug] = url.match(/\/(\d+)\/(.*)\.html$/)
|
||||
const site_id = `${number}/${slug}`
|
||||
if (channels[site_id] === undefined) {
|
||||
channels[site_id] = {
|
||||
lang: 'en',
|
||||
site_id,
|
||||
name
|
||||
}
|
||||
$('.channelname').each((i, el) => {
|
||||
const name = $(el).find('center > a:eq(1)').text()
|
||||
const url = $(el).find('center > a:eq(1)').attr('href')
|
||||
const [, number, slug] = url.match(/\/(\d+)\/(.*)\.html$/)
|
||||
const site_id = `${number}/${slug}`
|
||||
if (channels[site_id] === undefined) {
|
||||
channels[site_id] = {
|
||||
lang: 'en',
|
||||
site_id,
|
||||
name
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -178,13 +193,10 @@ function parseTime(date, time) {
|
|||
}
|
||||
|
||||
function parseText($item) {
|
||||
let text = $item.text()
|
||||
.replace(/\t/g, '')
|
||||
.replace(/\n/g, ' ')
|
||||
.trim()
|
||||
let text = $item.text().replace(/\t/g, '').replace(/\n/g, ' ').trim()
|
||||
while (true) {
|
||||
if (text.match(/ /)) {
|
||||
text = text.replace(/ /g, ' ')
|
||||
if (text.match(/\s\s/)) {
|
||||
text = text.replace(/\s\s/g, ' ')
|
||||
continue
|
||||
}
|
||||
break
|
||||
|
|
|
@ -17,16 +17,18 @@ const channel = {
|
|||
xmltv_id: 'BBCOneLondon.uk'
|
||||
}
|
||||
|
||||
axios.get.mockImplementation((url, opts) => {
|
||||
axios.get.mockImplementation(url => {
|
||||
if (
|
||||
url === 'https://www.mytelly.co.uk/tv-guide/listings/programme?cid=713&pid=1906433&tm=2024-12-07+00%3A00%3A00'
|
||||
url ===
|
||||
'https://www.mytelly.co.uk/tv-guide/listings/programme?cid=713&pid=1906433&tm=2024-12-07+00%3A00%3A00'
|
||||
) {
|
||||
return Promise.resolve({
|
||||
data: fs.readFileSync(path.join(__dirname, '__data__', 'programme.html'))
|
||||
})
|
||||
}
|
||||
if (
|
||||
url === 'https://www.mytelly.co.uk/tv-guide/listings/programme?cid=713&pid=5656624&tm=2024-12-07+23%3A35%3A00'
|
||||
url ===
|
||||
'https://www.mytelly.co.uk/tv-guide/listings/programme?cid=713&pid=5656624&tm=2024-12-07+23%3A35%3A00'
|
||||
) {
|
||||
return Promise.resolve({
|
||||
data: fs.readFileSync(path.join(__dirname, '__data__', 'programme2.html'))
|
||||
|
@ -57,7 +59,8 @@ it('can parse response', async () => {
|
|||
title: 'Captain Phillips',
|
||||
description:
|
||||
'An American cargo ship sets a dangerous course around the coast of Somalia, while inland, four men are pressed into service as pirates by the local warlords. The captain is taken hostage when the raiding party hijacks the vessel, resulting in a tense five-day crisis. Fact-based thriller, starring Tom Hanks and Barkhad Abdi',
|
||||
image: 'https://d16ia5iwuvax6y.cloudfront.net/uk-prog-images/c44ce7b0d3ae602c0c93ece5af140815.jpg?k=VeeNdUjml3bSHdlZ0OXbGLy%2BmsLdYPwTV6iAxGkzq4dsylOCGGE7OWlqwSWt0cd0Qtrin4DkEMC0Zzdp8ZeNk2vNIQzjMF0DG0h3IeTR5NM%3D',
|
||||
image:
|
||||
'https://d16ia5iwuvax6y.cloudfront.net/uk-prog-images/c44ce7b0d3ae602c0c93ece5af140815.jpg?k=VeeNdUjml3bSHdlZ0OXbGLy%2BmsLdYPwTV6iAxGkzq4dsylOCGGE7OWlqwSWt0cd0Qtrin4DkEMC0Zzdp8ZeNk2vNIQzjMF0DG0h3IeTR5NM%3D',
|
||||
category: ['Factual', 'Movie/Drama', 'Thriller']
|
||||
})
|
||||
expect(results[1]).toMatchObject({
|
||||
|
@ -67,7 +70,8 @@ it('can parse response', async () => {
|
|||
subTitle: 'Past and Pressure Season 6, Episode 5',
|
||||
description:
|
||||
'The artists are tasked with writing a song about their heritage. For some, the pressure of the competition proves too much for them to match. In their final challenge, they are put face to face with industry experts who grill them about their plans after the competition. Some impress, while others leave the mentors confused',
|
||||
image: 'https://d16ia5iwuvax6y.cloudfront.net/uk-prog-images/2039278182b27cc279570b9ab9b89379.jpg?k=VeeNdUjml3bSHdlZ0OXbGLy%2BmsLdYPwTV6iAxGkzq4cDhR7jXTNFW3tgwQCdOPUobhXwlT81mIsqOe93HPusDG6tw1aoeYOgafojtynNWxc%3D',
|
||||
image:
|
||||
'https://d16ia5iwuvax6y.cloudfront.net/uk-prog-images/2039278182b27cc279570b9ab9b89379.jpg?k=VeeNdUjml3bSHdlZ0OXbGLy%2BmsLdYPwTV6iAxGkzq4cDhR7jXTNFW3tgwQCdOPUobhXwlT81mIsqOe93HPusDG6tw1aoeYOgafojtynNWxc%3D',
|
||||
category: ['Challenge/Reality Show', 'Show/Game Show'],
|
||||
season: 6,
|
||||
episode: 5
|
||||
|
|
|
@ -12,27 +12,30 @@ module.exports = {
|
|||
site: 'neo.io',
|
||||
timezone: 'Europe/Ljubljana',
|
||||
days: 5,
|
||||
url({ date, channel }) { return 'https://stargate.telekom.si/api/titan.tv.WebEpg/GetWebEpgData' },
|
||||
url() {
|
||||
return 'https://stargate.telekom.si/api/titan.tv.WebEpg/GetWebEpgData'
|
||||
},
|
||||
request: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Host': 'stargate.telekom.si',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
Host: 'stargate.telekom.si',
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
|
||||
Accept: 'application/json, text/plain, */*',
|
||||
'Accept-Language': 'nl,en-US;q=0.7,en;q=0.3',
|
||||
'Content-Type': 'application/json',
|
||||
'X-AppLayout': '1',
|
||||
'x-language': 'sl',
|
||||
'Origin': 'https://neo.io',
|
||||
Origin: 'https://neo.io',
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Sec-Fetch-Site': 'cross-site',
|
||||
'Sec-GPC': '1',
|
||||
'Connection': 'keep-alive'
|
||||
Connection: 'keep-alive'
|
||||
},
|
||||
data({ channel, date }) {
|
||||
const todayEpoch = date.startOf('day').unix();
|
||||
const nextDayEpoch = date.add(1, 'day').startOf('day').unix();
|
||||
const todayEpoch = date.startOf('day').unix()
|
||||
const nextDayEpoch = date.add(1, 'day').startOf('day').unix()
|
||||
return JSON.stringify({
|
||||
ch_ext_id: channel.site_id,
|
||||
from: todayEpoch,
|
||||
|
@ -41,11 +44,11 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
parser: function ({ content }) {
|
||||
const programs = [];
|
||||
const data = JSON.parse(content);
|
||||
const programs = []
|
||||
const data = JSON.parse(content)
|
||||
data.shows.forEach(show => {
|
||||
const start = dayjs.unix(show.show_start).utc();
|
||||
const stop = dayjs.unix(show.show_end).utc();
|
||||
const start = dayjs.unix(show.show_start).utc()
|
||||
const stop = dayjs.unix(show.show_end).utc()
|
||||
const programData = {
|
||||
title: show.title,
|
||||
description: show.summary || 'No description available',
|
||||
|
@ -58,15 +61,19 @@ module.exports = {
|
|||
return programs
|
||||
},
|
||||
async channels() {
|
||||
const response = await axios.post('https://stargate.telekom.si/api/titan.tv.WebEpg/ZapList', JSON.stringify({ includeRadioStations: true }), {
|
||||
headers: this.request.headers
|
||||
});
|
||||
const response = await axios.post(
|
||||
'https://stargate.telekom.si/api/titan.tv.WebEpg/ZapList',
|
||||
JSON.stringify({ includeRadioStations: true }),
|
||||
{
|
||||
headers: this.request.headers
|
||||
}
|
||||
)
|
||||
|
||||
const data = response.data.data;
|
||||
const data = response.data.data
|
||||
return data.map(item => ({
|
||||
lang: 'sq',
|
||||
name: String(item.channel.title),
|
||||
site_id: String(item.channel.id),
|
||||
site_id: String(item.channel.id)
|
||||
//logo: String(item.channel.logo)
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -12,7 +12,9 @@ const channel = {
|
|||
}
|
||||
|
||||
it('can generate valid url', () => {
|
||||
expect(url({ date, channel })).toBe('https://stargate.telekom.si/api/titan.tv.WebEpg/GetWebEpgData')
|
||||
expect(url({ date, channel })).toBe(
|
||||
'https://stargate.telekom.si/api/titan.tv.WebEpg/GetWebEpgData'
|
||||
)
|
||||
})
|
||||
|
||||
it('can parse response', () => {
|
||||
|
@ -82,33 +84,34 @@ it('can parse response', () => {
|
|||
]
|
||||
}`
|
||||
|
||||
const result = parser({ content, channel }).map(p => {
|
||||
p.start = p.start
|
||||
p.stop = p.stop
|
||||
return p
|
||||
})
|
||||
const result = parser({ content, channel })
|
||||
|
||||
expect(result).toMatchObject([
|
||||
{
|
||||
title: "Napovedujemo",
|
||||
description: "Vabilo k ogledu naših oddaj.",
|
||||
start: "2024-12-26T04:05:00.000Z",
|
||||
stop: "2024-12-26T05:50:00.000Z",
|
||||
thumbnail: "https://ngimg.siol.tv/sioltv/mtcmsprod/52/0/0/5200d01a-fe5f-487e-835a-274e77227a6b.jpg"
|
||||
title: 'Napovedujemo',
|
||||
description: 'Vabilo k ogledu naših oddaj.',
|
||||
start: '2024-12-26T04:05:00.000Z',
|
||||
stop: '2024-12-26T05:50:00.000Z',
|
||||
thumbnail:
|
||||
'https://ngimg.siol.tv/sioltv/mtcmsprod/52/0/0/5200d01a-fe5f-487e-835a-274e77227a6b.jpg'
|
||||
},
|
||||
{
|
||||
title: "S0E0 - Hrabri zajčki: Prvi sneg",
|
||||
description: "Hrabri zajčki so prispeli v borov gozd in izkusili prvi sneg. Bob in Bu še nikoli nista videla snega. Mami kuha korenčkov kakav, Bu in Bob pa kmalu spoznata novega prijatelja, losa Danija.",
|
||||
start: "2024-12-26T05:50:00.000Z",
|
||||
stop: "2024-12-26T06:00:00.000Z",
|
||||
thumbnail: "https://ngimg.siol.tv/sioltv/mtcmsprod/d6/4/5/d6456f4a-4f0a-4825-90c1-1749abd59688.jpg"
|
||||
title: 'S0E0 - Hrabri zajčki: Prvi sneg',
|
||||
description:
|
||||
'Hrabri zajčki so prispeli v borov gozd in izkusili prvi sneg. Bob in Bu še nikoli nista videla snega. Mami kuha korenčkov kakav, Bu in Bob pa kmalu spoznata novega prijatelja, losa Danija.',
|
||||
start: '2024-12-26T05:50:00.000Z',
|
||||
stop: '2024-12-26T06:00:00.000Z',
|
||||
thumbnail:
|
||||
'https://ngimg.siol.tv/sioltv/mtcmsprod/d6/4/5/d6456f4a-4f0a-4825-90c1-1749abd59688.jpg'
|
||||
},
|
||||
{
|
||||
title: "Dobro jutro",
|
||||
description: "Oddaja Dobro jutro poleg informativnih in zabavnih vsebin podaja koristne nasvete o najrazličnejših tematikah iz vsakdanjega življenja.",
|
||||
start: "2024-12-26T06:00:00.000Z",
|
||||
stop: "2024-12-26T09:05:00.000Z",
|
||||
thumbnail: "https://ngimg.siol.tv/sioltv/mtcmsprod/e1/2/d/e12d8eb4-693a-43d3-89d4-fd96dade9f0f.jpg"
|
||||
title: 'Dobro jutro',
|
||||
description:
|
||||
'Oddaja Dobro jutro poleg informativnih in zabavnih vsebin podaja koristne nasvete o najrazličnejših tematikah iz vsakdanjega življenja.',
|
||||
start: '2024-12-26T06:00:00.000Z',
|
||||
stop: '2024-12-26T09:05:00.000Z',
|
||||
thumbnail:
|
||||
'https://ngimg.siol.tv/sioltv/mtcmsprod/e1/2/d/e12d8eb4-693a-43d3-89d4-fd96dade9f0f.jpg'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
|
|
@ -50,7 +50,7 @@ function parseItems(content, date) {
|
|||
if (!data || !data.item || !Array.isArray(data.item.episodes)) return []
|
||||
|
||||
return data.item.episodes.filter(ep => ep.schedule.startsWith(date.format('YYYY-MM-DD')))
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@ module.exports = {
|
|||
// I'm not sure what `endDate` represents but they only return 1 day of
|
||||
// results, with `endTime`s ocassionally in the following day.
|
||||
days: 1,
|
||||
url: ({ date }) => `https://api-web.nhle.com/v1/network/tv-schedule/${date.toJSON().split("T")[0]}`,
|
||||
url: ({ date }) =>
|
||||
`https://api-web.nhle.com/v1/network/tv-schedule/${date.toJSON().split('T')[0]}`,
|
||||
parser({ content }) {
|
||||
const programs = []
|
||||
const items = parseItems(content)
|
||||
|
@ -13,7 +14,7 @@ module.exports = {
|
|||
programs.push({
|
||||
title: item.title,
|
||||
description: item.description === item.title ? undefined : item.description,
|
||||
category: "Sports",
|
||||
category: 'Sports',
|
||||
// image: parseImage(item),
|
||||
start: parseStart(item),
|
||||
stop: parseStop(item)
|
||||
|
|
|
@ -10,9 +10,7 @@ dayjs.extend(utc)
|
|||
const date = dayjs.utc('2024-11-21', 'YYYY-MM-DD').startOf('d')
|
||||
|
||||
it('can generate valid url', () => {
|
||||
expect(url({ date })).toBe(
|
||||
'https://api-web.nhle.com/v1/network/tv-schedule/2024-11-21'
|
||||
)
|
||||
expect(url({ date })).toBe('https://api-web.nhle.com/v1/network/tv-schedule/2024-11-21')
|
||||
})
|
||||
|
||||
it('can parse response', () => {
|
||||
|
@ -28,17 +26,19 @@ it('can parse response', () => {
|
|||
start: '2024-11-21T12:00:00.000Z',
|
||||
stop: '2024-11-21T13:00:00.000Z',
|
||||
title: 'On The Fly',
|
||||
category: 'Sports',
|
||||
category: 'Sports'
|
||||
})
|
||||
})
|
||||
|
||||
it('can handle empty guide', () => {
|
||||
const results = parser({ content: JSON.stringify({
|
||||
// extra props not necessary but they form a valid response
|
||||
date: "2024-11-21",
|
||||
startDate: "2024-11-07",
|
||||
endDate: "2024-12-05",
|
||||
broadcasts: [],
|
||||
}) })
|
||||
const results = parser({
|
||||
content: JSON.stringify({
|
||||
// extra props not necessary but they form a valid response
|
||||
date: '2024-11-21',
|
||||
startDate: '2024-11-07',
|
||||
endDate: '2024-12-05',
|
||||
broadcasts: []
|
||||
})
|
||||
})
|
||||
expect(results).toMatchObject([])
|
||||
})
|
||||
|
|
|
@ -55,7 +55,7 @@ module.exports = {
|
|||
.map(function () {
|
||||
return {
|
||||
lang: 'es',
|
||||
site_id: $(this).attr('alt').replace(/\&/gi, '&'),
|
||||
site_id: $(this).attr('alt').replace(/&/gi, '&'),
|
||||
name: $(this).attr('alt')
|
||||
}
|
||||
})
|
||||
|
|
|
@ -27,7 +27,7 @@ module.exports = {
|
|||
if (item.episodeNum) {
|
||||
item.episodeNum.forEach(ep => {
|
||||
if (ep.system === 'xmltv_ns') {
|
||||
const [season, episode, _] = ep.value.split('.')
|
||||
const [season, episode] = ep.value.split('.')
|
||||
program.season = parseInt(season) + 1
|
||||
program.episode = parseInt(episode) + 1
|
||||
return true
|
||||
|
|
|
@ -132,7 +132,7 @@ module.exports = {
|
|||
const $ = cheerio.load(data)
|
||||
$('.channelname').each((i, el) => {
|
||||
let name = $(el).find('center > a:eq(1)').text()
|
||||
name = name.replace(/\-\-/gi, '-')
|
||||
name = name.replace(/--/gi, '-')
|
||||
const url = $(el).find('center > a:eq(1)').attr('href')
|
||||
if (!url) return
|
||||
const [, number, slug] = url.match(/\/(\d+)\/(.*)\.html$/)
|
||||
|
|
|
@ -5,7 +5,8 @@ const axios = require('axios')
|
|||
dayjs.extend(utc)
|
||||
|
||||
const API_PROGRAM_ENDPOINT = 'https://epg.orangetv.orange.es/epg/Smartphone_Android/1_PRO'
|
||||
const API_CHANNEL_ENDPOINT = 'https://pc.orangetv.orange.es/pc/api/rtv/v1/GetChannelList?bouquet_id=1&model_external_id=PC&filter_unsupported_channels=false&client=json'
|
||||
const API_CHANNEL_ENDPOINT =
|
||||
'https://pc.orangetv.orange.es/pc/api/rtv/v1/GetChannelList?bouquet_id=1&model_external_id=PC&filter_unsupported_channels=false&client=json'
|
||||
const API_IMAGE_ENDPOINT = 'https://pc.orangetv.orange.es/pc/api/rtv/v1/images'
|
||||
|
||||
module.exports = {
|
||||
|
@ -25,15 +26,9 @@ module.exports = {
|
|||
if (!items.length) return programs
|
||||
|
||||
const promises = [
|
||||
axios.get(
|
||||
`${API_PROGRAM_ENDPOINT}/${date.format('YYYYMMDD')}_8h_1.json`,
|
||||
),
|
||||
axios.get(
|
||||
`${API_PROGRAM_ENDPOINT}/${date.format('YYYYMMDD')}_8h_2.json`,
|
||||
),
|
||||
axios.get(
|
||||
`${API_PROGRAM_ENDPOINT}/${date.format('YYYYMMDD')}_8h_3.json`,
|
||||
),
|
||||
axios.get(`${API_PROGRAM_ENDPOINT}/${date.format('YYYYMMDD')}_8h_1.json`),
|
||||
axios.get(`${API_PROGRAM_ENDPOINT}/${date.format('YYYYMMDD')}_8h_2.json`),
|
||||
axios.get(`${API_PROGRAM_ENDPOINT}/${date.format('YYYYMMDD')}_8h_3.json`)
|
||||
]
|
||||
|
||||
await Promise.allSettled(promises)
|
||||
|
@ -42,7 +37,9 @@ module.exports = {
|
|||
if (r.status === 'fulfilled') {
|
||||
const parsed = parseItems(r.value.data, channel)
|
||||
|
||||
items = items.filter((item, index) => items.findIndex(oi => oi.id === item.id) === index).concat(parsed)
|
||||
items = items
|
||||
.filter((item, index) => items.findIndex(oi => oi.id === item.id) === index)
|
||||
.concat(parsed)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -57,7 +54,7 @@ module.exports = {
|
|||
episode: item.episodeId || null,
|
||||
icon: parseIcon(item),
|
||||
start: dayjs.utc(item.startDate) || null,
|
||||
stop: dayjs.utc(item.endDate) || null,
|
||||
stop: dayjs.utc(item.endDate) || null
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -72,42 +69,40 @@ module.exports = {
|
|||
return data.response.map(item => {
|
||||
return {
|
||||
lang: 'es',
|
||||
name: item.name,
|
||||
name: item.name,
|
||||
site_id: item.externalChannelId
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function parseIcon(item){
|
||||
function parseIcon(item) {
|
||||
if (item.attachments.length > 0) {
|
||||
const cover = item.attachments.find(i => i.name === 'COVER' || i.name === 'cover')
|
||||
|
||||
if(item.attachments.length > 0){
|
||||
const cover = item.attachments.find(i => i.name === "COVER" || i.name === "cover")
|
||||
|
||||
if(cover)
|
||||
{
|
||||
return `${API_IMAGE_ENDPOINT}${cover.value}`;
|
||||
if (cover) {
|
||||
return `${API_IMAGE_ENDPOINT}${cover.value}`
|
||||
}
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
function parseGenres(item){
|
||||
return item.genres.map(i => i.name);
|
||||
function parseGenres(item) {
|
||||
return item.genres.map(i => i.name)
|
||||
}
|
||||
|
||||
function parseItems(content, channel) {
|
||||
const json = typeof content === 'string' ? JSON.parse(content) : Array.isArray(content) ? content : []
|
||||
const json =
|
||||
typeof content === 'string' ? JSON.parse(content) : Array.isArray(content) ? content : []
|
||||
|
||||
if (!Array.isArray(json)) {
|
||||
return [];
|
||||
return []
|
||||
}
|
||||
|
||||
const channelData = json.find(i => i.channelExternalId == channel.site_id);
|
||||
const channelData = json.find(i => i.channelExternalId == channel.site_id)
|
||||
|
||||
if(!channelData)
|
||||
return [];
|
||||
if (!channelData) return []
|
||||
|
||||
return channelData.programs;
|
||||
return channelData.programs
|
||||
}
|
||||
|
|
|
@ -14,11 +14,15 @@ const channel = {
|
|||
}
|
||||
|
||||
it('can generate valid url', () => {
|
||||
expect(url({ date })).toBe(`https://epg.orangetv.orange.es/epg/Smartphone_Android/1_PRO/${date.format('YYYYMMDD')}_8h_1.json`)
|
||||
expect(url({ date })).toBe(
|
||||
`https://epg.orangetv.orange.es/epg/Smartphone_Android/1_PRO/${date.format(
|
||||
'YYYYMMDD'
|
||||
)}_8h_1.json`
|
||||
)
|
||||
})
|
||||
|
||||
it('can parse response', async () => {
|
||||
const content = fs.readFileSync(path.resolve(__dirname, '__data__/data.json')).toString()
|
||||
const content = fs.readFileSync(path.resolve(__dirname, '__data__/data.json')).toString()
|
||||
let results = await parser({ content, channel, date })
|
||||
results = results.map(p => {
|
||||
p.start = p.start.toJSON()
|
||||
|
@ -28,13 +32,14 @@ it('can parse response', async () => {
|
|||
|
||||
expect(results.length).toBe(4)
|
||||
|
||||
var sampleResult = results[0];
|
||||
var sampleResult = results[0]
|
||||
|
||||
expect(sampleResult).toMatchObject({
|
||||
start: '2024-11-30T22:36:51.000Z',
|
||||
stop: '2024-11-30T23:57:25.000Z',
|
||||
category: ['Cine', 'Romance', 'Comedia', 'Comedia Romántica'],
|
||||
description: 'Charlie trabaja como director en una escuela de primaria y goza de una placentera existencia junto a sus amigos. A pesar de ello, no es feliz porque cada vez que se enamora pierde la cordura.',
|
||||
description:
|
||||
'Charlie trabaja como director en una escuela de primaria y goza de una placentera existencia junto a sus amigos. A pesar de ello, no es feliz porque cada vez que se enamora pierde la cordura.',
|
||||
title: 'Loco de amor'
|
||||
})
|
||||
})
|
||||
|
|
|
@ -5,7 +5,12 @@ const timezone = require('dayjs/plugin/timezone')
|
|||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
|
||||
const packages = { 'OSNTV CONNECT': 3720, 'OSNTV PRIME': 3733, 'ALFA': 1281, 'OSN PINOY PLUS EXTRA': 3519 }
|
||||
const packages = {
|
||||
'OSNTV CONNECT': 3720,
|
||||
'OSNTV PRIME': 3733,
|
||||
ALFA: 1281,
|
||||
'OSN PINOY PLUS EXTRA': 3519
|
||||
}
|
||||
const country = 'AE'
|
||||
const tz = 'Asia/Dubai'
|
||||
|
||||
|
@ -13,11 +18,9 @@ module.exports = {
|
|||
site: 'osn.com',
|
||||
days: 2,
|
||||
url({ channel, date }) {
|
||||
return `https://www.osn.com/api/TVScheduleWebService.asmx/time?dt=${
|
||||
encodeURIComponent(date.format('MM/DD/YYYY'))
|
||||
}&co=${country}&ch=${
|
||||
channel.site_id
|
||||
}&mo=false&hr=0`
|
||||
return `https://www.osn.com/api/TVScheduleWebService.asmx/time?dt=${encodeURIComponent(
|
||||
date.format('MM/DD/YYYY')
|
||||
)}&co=${country}&ch=${channel.site_id}&mo=false&hr=0`
|
||||
},
|
||||
request: {
|
||||
headers({ channel }) {
|
||||
|
@ -46,7 +49,9 @@ module.exports = {
|
|||
const axios = require('axios')
|
||||
for (const pkg of Object.values(packages)) {
|
||||
const channels = await axios
|
||||
.get(`https://www.osn.com/api/tvchannels.ashx?culture=en-US&packageId=${pkg}&country=${country}`)
|
||||
.get(
|
||||
`https://www.osn.com/api/tvchannels.ashx?culture=en-US&packageId=${pkg}&country=${country}`
|
||||
)
|
||||
.then(response => response.data)
|
||||
.catch(console.error)
|
||||
|
||||
|
|
|
@ -28,32 +28,30 @@ it('can generate valid url', () => {
|
|||
})
|
||||
|
||||
it('can parse response (ar)', () => {
|
||||
const result = parser({ date, channel: channelAR, content })
|
||||
.map(a => {
|
||||
a.start = a.start.toJSON()
|
||||
a.stop = a.stop.toJSON()
|
||||
return a
|
||||
})
|
||||
const result = parser({ date, channel: channelAR, content }).map(a => {
|
||||
a.start = a.start.toJSON()
|
||||
a.stop = a.stop.toJSON()
|
||||
return a
|
||||
})
|
||||
expect(result.length).toBe(29)
|
||||
expect(result[1]).toMatchObject({
|
||||
start: '2024-11-26T20:50:00.000Z',
|
||||
stop: '2024-11-26T21:45:00.000Z',
|
||||
title: 'بيت الحلويات: الحلقة 3',
|
||||
title: 'بيت الحلويات: الحلقة 3'
|
||||
})
|
||||
})
|
||||
|
||||
it('can parse response (en)', () => {
|
||||
const result = parser({ date, channel: channelEN, content })
|
||||
.map(a => {
|
||||
a.start = a.start.toJSON()
|
||||
a.stop = a.stop.toJSON()
|
||||
return a
|
||||
})
|
||||
const result = parser({ date, channel: channelEN, content }).map(a => {
|
||||
a.start = a.start.toJSON()
|
||||
a.stop = a.stop.toJSON()
|
||||
return a
|
||||
})
|
||||
expect(result.length).toBe(29)
|
||||
expect(result[1]).toMatchObject({
|
||||
start: '2024-11-26T20:50:00.000Z',
|
||||
stop: '2024-11-26T21:45:00.000Z',
|
||||
title: 'House Of Desserts: Episode 3',
|
||||
title: 'House Of Desserts: Episode 3'
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ function parseItems(content, date) {
|
|||
let data
|
||||
try {
|
||||
data = JSON.parse(json)
|
||||
} catch (error) {
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
|
||||
|
|
|
@ -129,36 +129,34 @@ module.exports = {
|
|||
)
|
||||
}
|
||||
}
|
||||
function fetchApiVersion() {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
async function fetchApiVersion() {
|
||||
// you'll never find what happened here :)
|
||||
// load the pickx page and get the hash from the MWC configuration.
|
||||
// it's not the best way to get the version but it's the only way to get it.
|
||||
const hashUrl = 'https://www.pickx.be/nl/televisie/tv-gids'
|
||||
const hashData = await axios
|
||||
.get(hashUrl)
|
||||
.then(r => {
|
||||
const re = /"hashes":\["(.*)"\]/
|
||||
const match = r.data.match(re)
|
||||
if (match && match[1]) {
|
||||
return match[1]
|
||||
} else {
|
||||
throw new Error('React app version hash not found')
|
||||
}
|
||||
})
|
||||
.catch(console.error)
|
||||
|
||||
const versionUrl = `https://www.pickx.be/api/s-${hashData}`
|
||||
const response = await axios.get(versionUrl, {
|
||||
headers: {
|
||||
Origin: 'https://www.pickx.be',
|
||||
Referer: 'https://www.pickx.be/'
|
||||
}
|
||||
})
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
// you'll never find what happened here :)
|
||||
// load the pickx page and get the hash from the MWC configuration.
|
||||
// it's not the best way to get the version but it's the only way to get it.
|
||||
|
||||
const hashUrl = 'https://www.pickx.be/nl/televisie/tv-gids';
|
||||
|
||||
const hashData = await axios.get(hashUrl)
|
||||
.then(r => {
|
||||
const re = /"hashes":\["(.*)"\]/
|
||||
const match = r.data.match(re)
|
||||
if (match && match[1]) {
|
||||
return match[1]
|
||||
} else {
|
||||
throw new Error('React app version hash not found')
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
const versionUrl = `https://www.pickx.be/api/s-${hashData}`
|
||||
|
||||
const response = await axios.get(versionUrl, {
|
||||
headers: {
|
||||
Origin: 'https://www.pickx.be',
|
||||
Referer: 'https://www.pickx.be/'
|
||||
}
|
||||
})
|
||||
|
||||
if (response.status === 200) {
|
||||
apiVersion = response.data.version
|
||||
resolve()
|
||||
|
|
|
@ -6,14 +6,7 @@ jest.mock('./pickx.be.config.js', () => {
|
|||
}
|
||||
})
|
||||
|
||||
const {
|
||||
parser,
|
||||
url,
|
||||
request,
|
||||
fetchApiVersion,
|
||||
setApiVersion,
|
||||
getApiVersion
|
||||
} = require('./pickx.be.config.js')
|
||||
const { parser, url, request, setApiVersion } = require('./pickx.be.config.js')
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
@ -36,7 +29,7 @@ beforeEach(() => {
|
|||
it('can generate valid url', async () => {
|
||||
const generatedUrl = await url({ channel, date })
|
||||
expect(generatedUrl).toBe(
|
||||
`https://px-epg.azureedge.net/airings/mockedApiVersion/2023-12-13/channel/UID0118?timezone=Europe%2FBrussels`
|
||||
'https://px-epg.azureedge.net/airings/mockedApiVersion/2023-12-13/channel/UID0118?timezone=Europe%2FBrussels'
|
||||
)
|
||||
})
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@ module.exports = {
|
|||
site: 'player.ee.co.uk',
|
||||
days: 2,
|
||||
url({ date, channel, hour = 0 }) {
|
||||
return `https://api.youview.tv/metadata/linear/v2/schedule/by-servicelocator?serviceLocator=${
|
||||
encodeURIComponent(channel.site_id)
|
||||
}&interval=${date.format('YYYY-MM-DD')}T${hour.toString().padStart(2,'0')}Z/PT12H`
|
||||
return `https://api.youview.tv/metadata/linear/v2/schedule/by-servicelocator?serviceLocator=${encodeURIComponent(
|
||||
channel.site_id
|
||||
)}&interval=${date.format('YYYY-MM-DD')}T${hour.toString().padStart(2, '0')}Z/PT12H`
|
||||
},
|
||||
request: {
|
||||
headers: {
|
||||
|
@ -39,7 +39,7 @@ module.exports = {
|
|||
const stop = start.add(item.publishedDuration, 's')
|
||||
const description = item.synopsis
|
||||
if (description) {
|
||||
const matches = description.trim().match(/\(?S(\d+)[\/\s]Ep(\d+)\)?/)
|
||||
const matches = description.trim().match(/\(?S(\d+)[/\s]Ep(\d+)\)?/)
|
||||
if (matches) {
|
||||
if (matches[1]) {
|
||||
season = parseInt(matches[1])
|
||||
|
@ -79,7 +79,7 @@ module.exports = {
|
|||
'BTSubscriptionCodesExtension'
|
||||
]
|
||||
const result = await axios
|
||||
.get(`https://api.youview.tv/metadata/linear/v2/linear-services`, {
|
||||
.get('https://api.youview.tv/metadata/linear/v2/linear-services', {
|
||||
params: {
|
||||
contentTargetingToken: token,
|
||||
extensions: extensions.join(',')
|
||||
|
@ -89,14 +89,16 @@ module.exports = {
|
|||
.then(response => response.data)
|
||||
.catch(console.error)
|
||||
|
||||
return result?.items
|
||||
.filter(channel => channel.contentTypes.indexOf('tv') >= 0)
|
||||
.map(channel => {
|
||||
return {
|
||||
lang: 'en',
|
||||
site_id: channel.serviceLocator,
|
||||
name: channel.fullName
|
||||
}
|
||||
}) || []
|
||||
return (
|
||||
result?.items
|
||||
.filter(channel => channel.contentTypes.indexOf('tv') >= 0)
|
||||
.map(channel => {
|
||||
return {
|
||||
lang: 'en',
|
||||
site_id: channel.serviceLocator,
|
||||
name: channel.fullName
|
||||
}
|
||||
}) || []
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,11 @@ const channel = {
|
|||
xmltv_id: 'HGTV.uk'
|
||||
}
|
||||
|
||||
axios.get.mockImplementation((url, opts) => {
|
||||
if (url === 'https://api.youview.tv/metadata/linear/v2/schedule/by-servicelocator?serviceLocator=dvb%3A%2F%2F233a..6d60&interval=2023-12-13T12Z/PT12H') {
|
||||
axios.get.mockImplementation(url => {
|
||||
if (
|
||||
url ===
|
||||
'https://api.youview.tv/metadata/linear/v2/schedule/by-servicelocator?serviceLocator=dvb%3A%2F%2F233a..6d60&interval=2023-12-13T12Z/PT12H'
|
||||
) {
|
||||
return Promise.resolve({
|
||||
data: JSON.parse(fs.readFileSync(path.resolve(__dirname, '__data__/data1.json')))
|
||||
})
|
||||
|
@ -33,12 +36,11 @@ it('can generate valid url', () => {
|
|||
|
||||
it('can parse response', async () => {
|
||||
const content = fs.readFileSync(path.resolve(__dirname, '__data__/data.json'))
|
||||
const result = (await parser({ content, channel, date }))
|
||||
.map(p => {
|
||||
p.start = p.start.toJSON()
|
||||
p.stop = p.stop.toJSON()
|
||||
return p
|
||||
})
|
||||
const result = (await parser({ content, channel, date })).map(p => {
|
||||
p.start = p.start.toJSON()
|
||||
p.stop = p.stop.toJSON()
|
||||
return p
|
||||
})
|
||||
|
||||
expect(result).toMatchObject([
|
||||
{
|
||||
|
|
|
@ -43,7 +43,7 @@ module.exports = {
|
|||
const axios = require('axios')
|
||||
const data = await axios
|
||||
.post(
|
||||
`https://playtv.unifi.com.my:7053/VSP/V3/QueryAllChannel`,
|
||||
'https://playtv.unifi.com.my:7053/VSP/V3/QueryAllChannel',
|
||||
{ isReturnAllMedia: '0' },
|
||||
{
|
||||
params: {
|
||||
|
@ -74,7 +74,7 @@ function parseItems(content, channel) {
|
|||
|
||||
const channelData = data.find(i => i.id == channel.site_id)
|
||||
return channelData.items && Array.isArray(channelData.items) ? channelData.items : []
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const timezone = require('dayjs/plugin/timezone')
|
||||
const axios = require('axios')
|
||||
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
|
|
|
@ -33,14 +33,17 @@ it('can parse response', () => {
|
|||
start: '2024-12-28T00:21:00.000Z',
|
||||
stop: '2024-12-28T00:48:00.000Z',
|
||||
title: 'Naruto: El Tercer Hokage, Eternamente',
|
||||
description: 'Gaara y Naruto continúan combatiendo con todas sus fuerzas. Decidido a proteger a Sakura, Naruto ataca a Gaara una y otra vez.',
|
||||
description:
|
||||
'Gaara y Naruto continúan combatiendo con todas sus fuerzas. Decidido a proteger a Sakura, Naruto ataca a Gaara una y otra vez.',
|
||||
subTitle: 'El Tercer Hokage, Eternamente',
|
||||
episode: 80,
|
||||
season: 2,
|
||||
actors: ["Isabel Martion (Naruto Uzumaki)",
|
||||
"Christine Byrd (Sakura Haruno)",
|
||||
"Victor Ugarte (Sasuke Uchiha)",
|
||||
"Alfonso Obreg (Kakashi Hatake)"],
|
||||
actors: [
|
||||
'Isabel Martion (Naruto Uzumaki)',
|
||||
'Christine Byrd (Sakura Haruno)',
|
||||
'Victor Ugarte (Sasuke Uchiha)',
|
||||
'Alfonso Obreg (Kakashi Hatake)'
|
||||
],
|
||||
categories: ['Anime', 'Anime Action & Adventure'],
|
||||
rating: 'TV-14',
|
||||
date: '2004-04-21T00:00:00.000Z',
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="pluto.tv" lang="en" xmltv_id="PlutoTVAdventCalendar.ca" site_id="6712256349c4060008e9e0f0">Pluto TV Advent Calendar</channel>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="pluto.tv" lang="en" xmltv_id="Diane,femmeflic.uk" site_id="6671b26836a2f90008d9333c">Diane, femme flic</channel>
|
||||
|
|
|
@ -46,10 +46,10 @@ module.exports = {
|
|||
|
||||
return programs
|
||||
},
|
||||
async channels({ country, lang }) {
|
||||
async channels() {
|
||||
const axios = require('axios')
|
||||
const data = await axios
|
||||
.get(`https://www.programetv.ro/api/station/index/`)
|
||||
.get('https://www.programetv.ro/api/station/index/')
|
||||
.then(r => r.data)
|
||||
.catch(console.log)
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ module.exports = {
|
|||
$('.channelList-listItemsLink').each((i, el) => {
|
||||
const name = $(el).attr('title')
|
||||
const url = $(el).attr('href')
|
||||
const [, site_id] = url.match(/\/programme\-(.*)\.html$/i)
|
||||
const [, site_id] = url.match(/\/programme-(.*)\.html$/i)
|
||||
|
||||
channels.push({
|
||||
lang: 'fr',
|
||||
|
|
|
@ -51,7 +51,7 @@ module.exports = {
|
|||
|
||||
return data.programmes.map(item => {
|
||||
const site_id = item.url.replace('/', '')
|
||||
const name = site_id.replace(/\-/gi, ' ')
|
||||
const name = site_id.replace(/-/gi, ' ')
|
||||
|
||||
return {
|
||||
lang: 'fr',
|
||||
|
|
|
@ -13,19 +13,17 @@ module.exports = {
|
|||
site: 'programme.tvb.com',
|
||||
days: 2,
|
||||
url({ channel, date, time = null }) {
|
||||
return `https://programme.tvb.com/api/schedule?input_date=${
|
||||
date.format('YYYYMMDD')
|
||||
}&network_code=${channel.site_id}&_t=${time ? time : parseInt(Date.now() / 1000)}`
|
||||
return `https://programme.tvb.com/api/schedule?input_date=${date.format(
|
||||
'YYYYMMDD'
|
||||
)}&network_code=${channel.site_id}&_t=${time ? time : parseInt(Date.now() / 1000)}`
|
||||
},
|
||||
parser({ content, channel, date }) {
|
||||
const programs = []
|
||||
const data = content ? JSON.parse(content) : {}
|
||||
if (Array.isArray(data.data?.list)) {
|
||||
const dt = date.format('YYYY-MM-DD')
|
||||
for (const d of data.data.list) {
|
||||
if (Array.isArray(d.schedules)) {
|
||||
const schedules = d.schedules
|
||||
.filter(s => s.network_code === channel.site_id)
|
||||
const schedules = d.schedules.filter(s => s.network_code === channel.site_id)
|
||||
schedules.forEach((s, i) => {
|
||||
const start = dayjs.tz(s.event_datetime, 'YYYY-MM-DD HH:mm:ss', tz)
|
||||
let stop
|
||||
|
@ -64,7 +62,7 @@ module.exports = {
|
|||
if (assets) {
|
||||
queues.push(...assets.map(a => base + '/' + a))
|
||||
} else {
|
||||
const metadata = content.match(/e\=(\[(.*?)\])/)
|
||||
const metadata = content.match(/e=(\[(.*?)\])/)
|
||||
if (metadata) {
|
||||
const infos = eval(metadata[1])
|
||||
if (Array.isArray(infos)) {
|
||||
|
|
|
@ -34,7 +34,7 @@ it('can parse response (en)', () => {
|
|||
expect(results[1]).toMatchObject({
|
||||
start: '2024-12-06T15:55:00.000Z',
|
||||
stop: '2024-12-06T16:55:00.000Z',
|
||||
title: 'Line Walker: Bull Fight#16[Can][PG]',
|
||||
title: 'Line Walker: Bull Fight#16[Can][PG]'
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -51,7 +51,7 @@ it('can parse response (zh)', () => {
|
|||
stop: '2024-12-06T16:55:00.000Z',
|
||||
title: '使徒行者3#16[粵][PG]',
|
||||
description:
|
||||
'文鼎從淑梅手上救走大聖爺兒子,大聖爺還恩於歡喜,答允支持九指強。崇聯社定下選舉日子,恰巧是韋傑出獄之日,頭目們顧念舊日恩義,紛紛轉投浩洋。浩洋帶亞希逛傢俬店,憧憬二人未來。亞希向家強承認愛上浩洋,要求退出臥底任務。作榮與歡喜暗中會面,將國際犯罪組織「永恆幫」情報交給他。阿火遭家強出賣,到沐足店搶錢。家強逮住阿火,惟被合星誤會而受拘捕。家強把正植遺下的頸鏈和學生證交還,合星意識到家強已知悉正植身世。',
|
||||
'文鼎從淑梅手上救走大聖爺兒子,大聖爺還恩於歡喜,答允支持九指強。崇聯社定下選舉日子,恰巧是韋傑出獄之日,頭目們顧念舊日恩義,紛紛轉投浩洋。浩洋帶亞希逛傢俬店,憧憬二人未來。亞希向家強承認愛上浩洋,要求退出臥底任務。作榮與歡喜暗中會面,將國際犯罪組織「永恆幫」情報交給他。阿火遭家強出賣,到沐足店搶錢。家強逮住阿火,惟被合星誤會而受拘捕。家強把正植遺下的頸鏈和學生證交還,合星意識到家強已知悉正植身世。'
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ module.exports = {
|
|||
$('ul.channelList a').each((i, el) => {
|
||||
const name = $(el).text()
|
||||
const url = $(el).attr('href')
|
||||
const [, site_id] = url.match(/^\/program\-tv\/(.*)$/i)
|
||||
const [, site_id] = url.match(/^\/program-tv\/(.*)$/i)
|
||||
|
||||
channels.push({
|
||||
lang: 'pl',
|
||||
|
|
|
@ -58,7 +58,7 @@ function parseItems(content, channel) {
|
|||
let data
|
||||
try {
|
||||
data = JSON.parse(content)
|
||||
} catch (error) {
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,7 @@ dayjs.extend(timezone)
|
|||
dayjs.extend(utc)
|
||||
dayjs.extend(customParseFormat)
|
||||
|
||||
doFetch
|
||||
.setCheckResult(false)
|
||||
.setDebugger(debug)
|
||||
doFetch.setCheckResult(false).setDebugger(debug)
|
||||
|
||||
const tz = 'Asia/Riyadh'
|
||||
const defaultHeaders = {
|
||||
|
@ -47,7 +45,7 @@ module.exports = {
|
|||
headers: {
|
||||
...defaultHeaders,
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
cookie: cookies[channel.lang],
|
||||
cookie: cookies[channel.lang]
|
||||
}
|
||||
}
|
||||
queues.push({ i: item, url, params })
|
||||
|
@ -61,7 +59,7 @@ module.exports = {
|
|||
},
|
||||
async channels({ lang = 'en' }) {
|
||||
const result = await axios
|
||||
.get(`https://rotana.net/api/channels`)
|
||||
.get('https://rotana.net/api/channels')
|
||||
.then(response => response.data)
|
||||
.catch(console.error)
|
||||
|
||||
|
@ -88,34 +86,37 @@ function parseProgram(item, result) {
|
|||
item.description = desc
|
||||
}
|
||||
}
|
||||
break;
|
||||
break
|
||||
case 'Element':
|
||||
if (el.name === 'span') {
|
||||
const [k, v] = $(el).text().split(':').map(a => a.trim())
|
||||
const [k, v] = $(el)
|
||||
.text()
|
||||
.split(':')
|
||||
.map(a => a.trim())
|
||||
switch (k) {
|
||||
case 'Category':
|
||||
case 'التصنيف':
|
||||
item.category = v;
|
||||
break;
|
||||
item.category = v
|
||||
break
|
||||
case 'Country':
|
||||
case 'البلد':
|
||||
item.country = v;
|
||||
break;
|
||||
item.country = v
|
||||
break
|
||||
case 'Director':
|
||||
case 'المخرج':
|
||||
item.director = v;
|
||||
break;
|
||||
item.director = v
|
||||
break
|
||||
case 'Language':
|
||||
case 'اللغة':
|
||||
item.language = v;
|
||||
break;
|
||||
item.language = v
|
||||
break
|
||||
case 'Release Year':
|
||||
case 'سنة الإصدار':
|
||||
item.date = v;
|
||||
break;
|
||||
item.date = v
|
||||
break
|
||||
}
|
||||
}
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +143,9 @@ function parseItems(content, date) {
|
|||
const heading = top.find('.iq-accordion-title .big-title')
|
||||
if (heading.length) {
|
||||
const progId = top.attr('id')
|
||||
const title = heading.find('span:eq(1)').text()
|
||||
const title = heading
|
||||
.find('span:eq(1)')
|
||||
.text()
|
||||
.split('\n')
|
||||
.map(a => a.trim())
|
||||
.join(' ')
|
||||
|
@ -151,7 +154,7 @@ function parseItems(content, date) {
|
|||
items.push({
|
||||
program: progId.substr(progId.indexOf('-') + 1),
|
||||
title: title ? title.trim() : title,
|
||||
start: `${y}-${m}-${d} ${time.trim()}`,
|
||||
start: `${y}-${m}-${d} ${time.trim()}`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ const channel = {
|
|||
}
|
||||
const channelAr = Object.assign({}, channel, { lang: 'ar' })
|
||||
|
||||
axios.get.mockImplementation((url, opts) => {
|
||||
axios.get.mockImplementation(url => {
|
||||
if (url === 'https://rotana.net/en/streams?channel=439&itemId=736970') {
|
||||
return Promise.resolve({
|
||||
data: fs.readFileSync(path.resolve(__dirname, '__data__/program_en.html'))
|
||||
|
@ -52,11 +52,13 @@ it('can generate valid arabic url', () => {
|
|||
})
|
||||
|
||||
it('can parse english response', async () => {
|
||||
const result = (await parser({
|
||||
channel,
|
||||
date,
|
||||
content: fs.readFileSync(path.join(__dirname, '/__data__/content_en.html'))
|
||||
})).map(a => {
|
||||
const result = (
|
||||
await parser({
|
||||
channel,
|
||||
date,
|
||||
content: fs.readFileSync(path.join(__dirname, '/__data__/content_en.html'))
|
||||
})
|
||||
).map(a => {
|
||||
a.start = a.start.toJSON()
|
||||
a.stop = a.stop.toJSON()
|
||||
return a
|
||||
|
@ -69,17 +71,20 @@ it('can parse english response', async () => {
|
|||
title: 'Khiyana Mashroua',
|
||||
description:
|
||||
'Hisham knows that his father has given all his wealth to his elder brother. This leads him to plan to kill his brother to make it look like a defense of honor, which he does by killing his wife along...',
|
||||
image: 'https://s3.eu-central-1.amazonaws.com/rotana.website/spider_storage/1398X1000/1687084565',
|
||||
image:
|
||||
'https://s3.eu-central-1.amazonaws.com/rotana.website/spider_storage/1398X1000/1687084565',
|
||||
category: 'Movie'
|
||||
})
|
||||
})
|
||||
|
||||
it('can parse arabic response', async () => {
|
||||
const result = (await parser({
|
||||
channel: channelAr,
|
||||
date,
|
||||
content: fs.readFileSync(path.join(__dirname, '/__data__/content_ar.html'))
|
||||
})).map(a => {
|
||||
const result = (
|
||||
await parser({
|
||||
channel: channelAr,
|
||||
date,
|
||||
content: fs.readFileSync(path.join(__dirname, '/__data__/content_ar.html'))
|
||||
})
|
||||
).map(a => {
|
||||
a.start = a.start.toJSON()
|
||||
a.stop = a.stop.toJSON()
|
||||
return a
|
||||
|
@ -92,7 +97,8 @@ it('can parse arabic response', async () => {
|
|||
title: 'خيانة مشروعة',
|
||||
description:
|
||||
'يعلم هشام البحيري أن والده قد حرمه من الميراث، ووهب كل ثروته لشقيقه اﻷكبر، وهو ما يدفعه لتدبير جريمة قتل شقيقه لتبدو وكأنها دفاع عن الشرف، وذلك حين يقتل هشام زوجته مع شقيقه.',
|
||||
image: 'https://s3.eu-central-1.amazonaws.com/rotana.website/spider_storage/1398X1000/1687084565',
|
||||
image:
|
||||
'https://s3.eu-central-1.amazonaws.com/rotana.website/spider_storage/1398X1000/1687084565',
|
||||
category: 'فيلم'
|
||||
})
|
||||
})
|
||||
|
|
|
@ -53,7 +53,7 @@ async function parseItems(buffer) {
|
|||
let data
|
||||
try {
|
||||
data = await pdf(buffer)
|
||||
} catch (err) {
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const _ = require('lodash')
|
||||
const axios = require('axios')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const timezone = require('dayjs/plugin/timezone')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const dayjs = require('dayjs')
|
||||
const duration = require("dayjs/plugin/duration")
|
||||
const duration = require('dayjs/plugin/duration')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const timezone = require('dayjs/plugin/timezone')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
|
@ -10,72 +10,74 @@ dayjs.extend(customParseFormat)
|
|||
dayjs.extend(duration)
|
||||
|
||||
module.exports = {
|
||||
site: 's.mxtv.jp',
|
||||
days: 1,
|
||||
lang: 'ja',
|
||||
url: function ({ date, channel }) {
|
||||
const id = `SV${channel.site_id}EPG${date.format('YYYYMMDD')}`
|
||||
return `https://s.mxtv.jp/bangumi_file/json01/${id}.json`
|
||||
},
|
||||
parser: function ({ content }) {
|
||||
let programs = []
|
||||
const items = parseItems(content)
|
||||
items.forEach(item => {
|
||||
programs.push({
|
||||
title: item.Event_name,
|
||||
description: item.Event_text,
|
||||
category: parseCategory(item),
|
||||
image: parseImage(item),
|
||||
start: parseStart(item),
|
||||
stop: parseStop(item)
|
||||
})
|
||||
})
|
||||
return programs
|
||||
},
|
||||
channels() {
|
||||
return [
|
||||
{
|
||||
lang: 'ja',
|
||||
site_id: '1',
|
||||
name: 'Tokyo MX1',
|
||||
xmltv_id: 'TokyoMX1.jp'
|
||||
},
|
||||
{
|
||||
lang: 'ja',
|
||||
site_id: '2',
|
||||
name: 'Tokyo MX2',
|
||||
xmltv_id: 'TokyoMX2.jp'
|
||||
}
|
||||
]
|
||||
}
|
||||
site: 's.mxtv.jp',
|
||||
days: 1,
|
||||
lang: 'ja',
|
||||
url: function ({ date, channel }) {
|
||||
const id = `SV${channel.site_id}EPG${date.format('YYYYMMDD')}`
|
||||
return `https://s.mxtv.jp/bangumi_file/json01/${id}.json`
|
||||
},
|
||||
parser: function ({ content }) {
|
||||
let programs = []
|
||||
const items = parseItems(content)
|
||||
items.forEach(item => {
|
||||
programs.push({
|
||||
title: item.Event_name,
|
||||
description: item.Event_text,
|
||||
category: parseCategory(item),
|
||||
image: parseImage(item),
|
||||
start: parseStart(item),
|
||||
stop: parseStop(item)
|
||||
})
|
||||
})
|
||||
return programs
|
||||
},
|
||||
channels() {
|
||||
return [
|
||||
{
|
||||
lang: 'ja',
|
||||
site_id: '1',
|
||||
name: 'Tokyo MX1',
|
||||
xmltv_id: 'TokyoMX1.jp'
|
||||
},
|
||||
{
|
||||
lang: 'ja',
|
||||
site_id: '2',
|
||||
name: 'Tokyo MX2',
|
||||
xmltv_id: 'TokyoMX2.jp'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function parseImage(item) {
|
||||
// Should return a string if we can output an image URL
|
||||
// Might be done with `https://s.mxtv.jp/bangumi/link/weblinkU.csv?1722421896752` ?
|
||||
return null
|
||||
function parseImage() {
|
||||
// Should return a string if we can output an image URL
|
||||
// Might be done with `https://s.mxtv.jp/bangumi/link/weblinkU.csv?1722421896752` ?
|
||||
return null
|
||||
}
|
||||
|
||||
function parseCategory(item) {
|
||||
// Should return a string if we can determine the category
|
||||
// Might be done with `https://s.mxtv.jp/index_set/csv/ranking_bangumi_allU.csv` ?
|
||||
return null
|
||||
function parseCategory() {
|
||||
// Should return a string if we can determine the category
|
||||
// Might be done with `https://s.mxtv.jp/index_set/csv/ranking_bangumi_allU.csv` ?
|
||||
return null
|
||||
}
|
||||
|
||||
function parseStart(item) {
|
||||
return dayjs.tz(item.Start_time.toString(), 'YYYY年MM月DD日HH時mm分ss秒', 'Asia/Tokyo')
|
||||
return dayjs.tz(item.Start_time.toString(), 'YYYY年MM月DD日HH時mm分ss秒', 'Asia/Tokyo')
|
||||
}
|
||||
|
||||
function parseStop(item) {
|
||||
// Add the duration to the start time
|
||||
const durationDate = dayjs(item.Duration, 'HH:mm:ss');
|
||||
return parseStart(item).add(dayjs.duration({
|
||||
hours: durationDate.hour(),
|
||||
minutes: durationDate.minute(),
|
||||
seconds: durationDate.second()
|
||||
}))
|
||||
// Add the duration to the start time
|
||||
const durationDate = dayjs(item.Duration, 'HH:mm:ss')
|
||||
return parseStart(item).add(
|
||||
dayjs.duration({
|
||||
hours: durationDate.hour(),
|
||||
minutes: durationDate.minute(),
|
||||
seconds: durationDate.second()
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
function parseItems(content) {
|
||||
return JSON.parse(content) || []
|
||||
return JSON.parse(content) || []
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ const channel = {
|
|||
name: 'Tokyo MX2',
|
||||
xmltv_id: 'TokyoMX2.jp'
|
||||
}
|
||||
const content = `[{ "Event_id": "0x6a57", "Start_time": "2024年07月27日05時00分00秒", "Duration": "01:00:00", "Event_name": "ヒーリングタイム&ヘッドラインニュース", "Event_text": "ねこの足跡", "Component": "480i 16:9 パンベクトルなし", "Sound": "ステレオ", "Event_detail": ""}]`
|
||||
const content =
|
||||
'[{ "Event_id": "0x6a57", "Start_time": "2024年07月27日05時00分00秒", "Duration": "01:00:00", "Event_name": "ヒーリングタイム&ヘッドラインニュース", "Event_text": "ねこの足跡", "Component": "480i 16:9 パンベクトルなし", "Sound": "ステレオ", "Event_detail": ""}]'
|
||||
|
||||
it('can generate valid url', () => {
|
||||
const result = url({ date, channel })
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue