From 5df982bb7c05da8229bd11c718f363aceb2f7366 Mon Sep 17 00:00:00 2001
From: freearhey <7253922+freearhey@users.noreply.github.com>
Date: Wed, 1 Jan 2025 12:27:22 +0300
Subject: [PATCH] Fix linter issues in sites/
---
sites/abc.net.au/abc.net.au.config.js | 2 +-
sites/awilime.com/awilime.com.test.js | 2 +-
sites/beinsports.com/beinsports.com.config.js | 3 +-
sites/beinsports.com/beinsports.com.test.js | 2 -
sites/chada.ma/chada.ma.config.js | 109 +++---
sites/chada.ma/chada.ma.test.js | 118 +++---
.../chaines-tv.orange.fr.config.js | 2 +-
.../content.astro.com.my.config.js | 4 +-
sites/cosmotetv.gr/cosmotetv.gr.config.js | 166 +++++----
sites/cosmotetv.gr/cosmotetv.gr.test.js | 157 ++++----
sites/cubmu.com/cubmu.com.config.js | 216 +++++------
sites/cubmu.com/cubmu.com.test.js | 94 ++---
sites/dens.tv/dens.tv.config.js | 13 +-
sites/dens.tv/dens.tv.test.js | 4 +-
.../digiturk.com.tr/digiturk.com.tr.config.js | 2 +-
sites/dishtv.in/dishtv.in.config.js | 2 +-
sites/guida.tv/guida.tv.config.js | 4 +-
sites/guidatv.sky.it/guidatv.sky.it.config.js | 2 +-
sites/hoy.tv/hoy.tv.config.js | 126 +++----
sites/hoy.tv/hoy.tv.test.js | 231 ++++++------
sites/i.mjh.nz/i.mjh.nz.config.js | 7 +-
sites/ipko.tv/ipko.tv.config.js | 153 ++++----
sites/ipko.tv/ipko.tv.test.js | 226 ++++++------
sites/m.tv.sms.cz/m.tv.sms.cz.config.js | 2 +-
sites/magticom.ge/magticom.ge.config.js | 4 +-
.../maxtv.hrvatskitelekom.hr.config.js | 2 +-
sites/mediaklikk.hu/mediaklikk.hu.config.js | 2 +-
.../mediasetinfinity.mediaset.it.config.js | 190 +++++-----
.../mediasetinfinity.mediaset.it.test.js | 99 ++---
sites/meo.pt/meo.pt.config.js | 2 +-
sites/meuguia.tv/meuguia.tv.config.js | 206 ++++++-----
sites/meuguia.tv/meuguia.tv.test.js | 120 +++---
sites/mewatch.sg/mewatch.sg.config.js | 2 +-
sites/mncvision.id/mncvision.id.config.js | 6 +-
sites/moji.id/moji.id.config.js | 10 +-
sites/moji.id/moji.id.test.js | 19 +-
sites/mtel.ba/mtel.ba.config.js | 4 +-
sites/mts.rs/mts.rs.config.js | 8 +-
.../mujtvprogram.cz/mujtvprogram.cz.config.js | 4 +-
sites/musor.tv/musor.tv.config.js | 2 +-
sites/musor.tv/musor.tv.test.js | 11 +-
sites/mytelly.co.uk/mytelly.co.uk.config.js | 68 ++--
sites/mytelly.co.uk/mytelly.co.uk.test.js | 14 +-
sites/neo.io/neo.io.config.js | 153 ++++----
sites/neo.io/neo.io.test.js | 245 +++++++------
.../nhkworldpremium.com.config.js | 2 +-
sites/nhl.com/nhl.com.config.js | 91 ++---
sites/nhl.com/nhl.com.test.js | 88 ++---
sites/nostv.pt/nostv.pt.config.js | 136 +++----
sites/nostv.pt/nostv.pt.test.js | 102 +++---
.../nuevosiglo.com.uy.config.js | 2 +-
sites/nzxmltv.com/nzxmltv.com.config.js | 162 ++++----
sites/nzxmltv.com/nzxmltv.com.test.js | 80 ++--
.../ontvtonight.com/ontvtonight.com.config.js | 2 +-
.../orangetv.orange.es.config.js | 221 ++++++-----
.../orangetv.orange.es.test.js | 103 +++---
sites/osn.com/osn.com.config.js | 19 +-
sites/osn.com/osn.com.test.js | 26 +-
sites/pbsguam.org/pbsguam.org.config.js | 2 +-
sites/pickx.be/pickx.be.config.js | 346 +++++++++---------
sites/pickx.be/pickx.be.test.js | 145 ++++----
.../player.ee.co.uk/player.ee.co.uk.config.js | 206 +++++------
sites/player.ee.co.uk/player.ee.co.uk.test.js | 146 ++++----
.../playtv.unifi.com.my.config.js | 4 +-
sites/programetv.ro/programetv.ro.config.js | 4 +-
.../programme-tv.net.config.js | 2 +-
.../programme-tv.vini.pf.config.js | 2 +-
.../programme.tvb.com.config.js | 12 +-
.../programme.tvb.com.test.js | 4 +-
.../programtv.onet.pl.config.js | 2 +-
sites/rev.bs/rev.bs.config.js | 2 +-
sites/rotana.net/rotana.net.config.js | 43 ++-
sites/rotana.net/rotana.net.test.js | 32 +-
sites/rtb.gov.bn/rtb.gov.bn.config.js | 2 +-
sites/rtp.pt/rtp.pt.config.js | 1 -
sites/s.mxtv.jp/s.mxtv.jp.config.js | 114 +++---
sites/s.mxtv.jp/s.mxtv.jp.test.js | 3 +-
sites/sat.tv/sat.tv.config.js | 2 +-
sites/shahid.mbc.net/shahid.mbc.net.config.js | 153 ++++----
sites/shahid.mbc.net/shahid.mbc.net.test.js | 76 ++--
sites/singtel.com/singtel.com.config.js | 4 +-
sites/sjonvarp.is/sjonvarp.is.config.js | 2 +-
sites/sky.com/sky.com.config.js | 35 +-
sites/sky.com/sky.com.test.js | 6 +-
sites/skylife.co.kr/skylife.co.kr.test.js | 2 +-
sites/skyperfectv.co.jp/__data__/content.html | 1 +
sites/skyperfectv.co.jp/__data__/empty.html | 1 +
.../skyperfectv.co.jp.config.js | 191 +++++-----
.../skyperfectv.co.jp.test.js | 18 +-
sites/snrt.ma/snrt.ma.config.js | 183 +++++----
sites/snrt.ma/snrt.ma.test.js | 16 +-
.../starhubtvplus.com.config.js | 26 +-
.../starhubtvplus.com.test.js | 9 +-
.../startimestv.com/startimestv.com.config.js | 22 +-
.../streamingtvguides.com.config.js | 4 +-
sites/telenet.tv/telenet.tv.config.js | 8 +-
sites/telkussa.fi/telkussa.fi.config.js | 4 +-
sites/tivie.id/tivie.id.config.js | 266 +++++++-------
sites/tivie.id/tivie.id.test.js | 152 ++++----
.../turksatkablo.com.tr.config.js | 2 +-
sites/tv.mail.ru/tv.mail.ru.config.js | 2 +-
sites/tv.nu/tv.nu.config.js | 2 +-
sites/tv.trueid.net/tv.trueid.net.config.js | 2 +-
sites/tv.yandex.ru/tv.yandex.ru.config.js | 63 ++--
sites/tv.yandex.ru/tv.yandex.ru.test.js | 18 +-
sites/tv2go.t-2.net/tv2go.t-2.net.config.js | 2 +-
.../tvarenasport.com.config.js | 41 ++-
.../tvarenasport.com/tvarenasport.com.test.js | 4 +-
sites/tvarenasport.hr/tvarenasport.hr.test.js | 4 +-
sites/tvcesoir.fr/tvcesoir.fr.config.js | 4 +-
.../tvcubana.icrt.cu.config.js | 2 +-
sites/tvguide.com/tvguide.com.config.js | 5 +-
sites/tvheute.at/tvheute.at.config.js | 2 +-
sites/tvim.tv/tvim.tv.config.js | 2 +-
sites/tvireland.ie/tvireland.ie.config.js | 4 +-
sites/tvpassport.com/tvpassport.com.config.js | 2 +-
sites/tvplus.com.tr/tvplus.com.tr.config.js | 27 +-
sites/tvplus.com.tr/tvplus.com.tr.test.js | 19 +-
sites/tvtv.us/tvtv.us.config.js | 2 +-
.../virgintvgo.virginmedia.com.config.js | 48 +--
.../virgintvgo.virginmedia.com.test.js | 18 +-
sites/visionplus.id/visionplus.id.config.js | 18 +-
sites/visionplus.id/visionplus.id.test.js | 30 +-
.../watch.sportsnet.ca.config.js | 4 +-
.../web.magentatv.de.config.js | 13 +-
.../web.magentatv.de/web.magentatv.de.test.js | 26 +-
sites/winplay.co/winplay.co.config.js | 1 -
sites/ziggogo.tv/ziggogo.tv.config.js | 48 +--
sites/ziggogo.tv/ziggogo.tv.test.js | 22 +-
129 files changed, 3316 insertions(+), 3226 deletions(-)
create mode 100644 sites/skyperfectv.co.jp/__data__/content.html
create mode 100644 sites/skyperfectv.co.jp/__data__/empty.html
diff --git a/sites/abc.net.au/abc.net.au.config.js b/sites/abc.net.au/abc.net.au.config.js
index 5caa9356..0550574b 100644
--- a/sites/abc.net.au/abc.net.au.config.js
+++ b/sites/abc.net.au/abc.net.au.config.js
@@ -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 []
}
}
diff --git a/sites/awilime.com/awilime.com.test.js b/sites/awilime.com/awilime.com.test.js
index df3677fe..08da5912 100644
--- a/sites/awilime.com/awilime.com.test.js
+++ b/sites/awilime.com/awilime.com.test.js
@@ -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')
diff --git a/sites/beinsports.com/beinsports.com.config.js b/sites/beinsports.com/beinsports.com.config.js
index 4bfae6de..41b6c899 100644
--- a/sites/beinsports.com/beinsports.com.config.js
+++ b/sites/beinsports.com/beinsports.com.config.js
@@ -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 []
}
diff --git a/sites/beinsports.com/beinsports.com.test.js b/sites/beinsports.com/beinsports.com.test.js
index 7651968e..563c18b1 100644
--- a/sites/beinsports.com/beinsports.com.test.js
+++ b/sites/beinsports.com/beinsports.com.test.js
@@ -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')
diff --git a/sites/chada.ma/chada.ma.config.js b/sites/chada.ma/chada.ma.config.js
index 087028a7..b6002c35 100644
--- a/sites/chada.ma/chada.ma.config.js
+++ b/sites/chada.ma/chada.ma.config.js
@@ -1,54 +1,55 @@
-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');
-
-dayjs.extend(utc);
-dayjs.extend(timezone);
-dayjs.extend(customParseFormat);
-
-module.exports = {
- site: 'chada.ma',
- channels: 'chada.ma.channels.xml',
- days: 1,
- request: {
- cache: {
- ttl: 60 * 60 * 1000 // 1 hour
- }
- },
- url() {
- return 'https://chada.ma/fr/chada-tv/grille-tv/';
- },
- parser: function ({ content }) {
- 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 titleElement = $(element).next('div').next('h3');
- const title = titleElement.text().trim();
-
- const description = titleElement.next('div').text().trim() || 'No description available';
-
- programs.push({
- title,
- description,
- start,
- stop
- });
- });
-
- return programs;
- }
-};
-
-function parseProgramTime(timeStr) {
- 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');
-}
+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)
+
+module.exports = {
+ site: 'chada.ma',
+ channels: 'chada.ma.channels.xml',
+ days: 1,
+ request: {
+ cache: {
+ ttl: 60 * 60 * 1000 // 1 hour
+ }
+ },
+ url() {
+ return 'https://chada.ma/fr/chada-tv/grille-tv/'
+ },
+ parser: function ({ content }) {
+ 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 titleElement = $(element).next('div').next('h3')
+ const title = titleElement.text().trim()
+
+ const description = titleElement.next('div').text().trim() || 'No description available'
+
+ programs.push({
+ title,
+ description,
+ start,
+ stop
+ })
+ })
+
+ return programs
+ }
+}
+
+function parseProgramTime(timeStr) {
+ 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')
+}
diff --git a/sites/chada.ma/chada.ma.test.js b/sites/chada.ma/chada.ma.test.js
index 557da6ea..51f715d4 100644
--- a/sites/chada.ma/chada.ma.test.js
+++ b/sites/chada.ma/chada.ma.test.js
@@ -1,60 +1,58 @@
-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')
-
-dayjs.extend(utc)
-dayjs.extend(timezone)
-dayjs.extend(customParseFormat)
-
-jest.mock('axios')
-
-const mockHtmlContent = `
-
-
Programmes d'Aujourd'hui
-
-
00:00 - 09:00
-
-
Bloc Prime + Clips
-
-
-
-
-`;
-
-it('can generate valid url', () => {
- expect(url()).toBe('https://chada.ma/fr/chada-tv/grille-tv/')
-});
-
-it('can parse response', () => {
- const content = mockHtmlContent
-
- const result = parser({ content }).map(p => {
- p.start = dayjs(p.start).tz('Africa/Casablanca').format('YYYY-MM-DDTHH:mm:ssZ')
- p.stop = dayjs(p.stop).tz('Africa/Casablanca').format('YYYY-MM-DDTHH:mm:ssZ')
- return p
- })
-
- expect(result).toMatchObject([
- {
- 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')
- }
- ])
-})
-
-it('can handle empty guide', () => {
- const result = parser({
- content: ''
- })
- expect(result).toMatchObject([])
-})
+const { parser, url } = require('./chada.ma.config.js')
+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)
+
+jest.mock('axios')
+
+const mockHtmlContent = `
+
+
Programmes d'Aujourd'hui
+
+
00:00 - 09:00
+
+
Bloc Prime + Clips
+
+
+
+
+`
+
+it('can generate valid url', () => {
+ expect(url()).toBe('https://chada.ma/fr/chada-tv/grille-tv/')
+})
+
+it('can parse response', () => {
+ const content = mockHtmlContent
+
+ const result = parser({ content }).map(p => {
+ p.start = dayjs(p.start).tz('Africa/Casablanca').format('YYYY-MM-DDTHH:mm:ssZ')
+ p.stop = dayjs(p.stop).tz('Africa/Casablanca').format('YYYY-MM-DDTHH:mm:ssZ')
+ return p
+ })
+
+ expect(result).toMatchObject([
+ {
+ 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')
+ }
+ ])
+})
+
+it('can handle empty guide', () => {
+ const result = parser({
+ content: ''
+ })
+ expect(result).toMatchObject([])
+})
diff --git a/sites/chaines-tv.orange.fr/chaines-tv.orange.fr.config.js b/sites/chaines-tv.orange.fr/chaines-tv.orange.fr.config.js
index d8b49148..cc44e33c 100644
--- a/sites/chaines-tv.orange.fr/chaines-tv.orange.fr.config.js
+++ b/sites/chaines-tv.orange.fr/chaines-tv.orange.fr.config.js
@@ -29,7 +29,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)
diff --git a/sites/content.astro.com.my/content.astro.com.my.config.js b/sites/content.astro.com.my/content.astro.com.my.config.js
index 12c7f2af..6f261a91 100644
--- a/sites/content.astro.com.my/content.astro.com.my.config.js
+++ b/sites/content.astro.com.my/content.astro.com.my.config.js
@@ -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 []
}
}
diff --git a/sites/cosmotetv.gr/cosmotetv.gr.config.js b/sites/cosmotetv.gr/cosmotetv.gr.config.js
index ef26df1f..8374f050 100644
--- a/sites/cosmotetv.gr/cosmotetv.gr.config.js
+++ b/sites/cosmotetv.gr/cosmotetv.gr.config.js
@@ -1,81 +1,85 @@
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-const customParseFormat = require('dayjs/plugin/customParseFormat')
-const timezone = require('dayjs/plugin/timezone')
-
-dayjs.extend(utc)
-dayjs.extend(customParseFormat)
-dayjs.extend(timezone)
-
-module.exports = {
- site: 'cosmotetv.gr',
- days: 5,
- request: {
- cache: {
- ttl: 60 * 60 * 1000 // 1 hour
- },
- 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': '*/*',
- 'Accept-Language': 'en-US,en;q=0.9',
- 'Accept-Encoding': 'gzip, deflate, br, zstd',
- '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"',
- 'Sec-Fetch-Dest': 'empty',
- 'Sec-Fetch-Mode': 'cors',
- 'Sec-Fetch-Site': 'cross-site'
- }
- },
- 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 }) {
- let programs = []
- const data = JSON.parse(content)
- data.channels.forEach(channel => {
- channel.items.forEach(item => {
- const start = dayjs(item.startTime).utc().toISOString()
- const stop = dayjs(item.endTime).utc().toISOString()
- programs.push({
- title: item.title,
- description: item.description || 'No description available',
- category: item.qoe.genre,
- image: item.thumbnails.standard,
- start,
- stop
- })
- })
- })
- return programs
- },
- 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 data = response.data
-
- if (data && data.channels) {
- return data.channels.map(item => ({
- lang: 'el',
- site_id: item.callSign,
- name: item.title,
- //logo: item.logos.square
- }))
- } else {
- console.error('Unexpected response structure:', data)
- return []
- }
- } catch (error) {
- console.error('Error fetching channel data:', error)
- return []
- }
- }
-}
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+const customParseFormat = require('dayjs/plugin/customParseFormat')
+const timezone = require('dayjs/plugin/timezone')
+
+dayjs.extend(utc)
+dayjs.extend(customParseFormat)
+dayjs.extend(timezone)
+
+module.exports = {
+ site: 'cosmotetv.gr',
+ days: 5,
+ request: {
+ cache: {
+ ttl: 60 * 60 * 1000 // 1 hour
+ },
+ 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: '*/*',
+ 'Accept-Language': 'en-US,en;q=0.9',
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
+ 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"',
+ 'Sec-Fetch-Dest': 'empty',
+ 'Sec-Fetch-Mode': 'cors',
+ 'Sec-Fetch-Site': 'cross-site'
+ }
+ },
+ 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 ({ content }) {
+ let programs = []
+ const data = JSON.parse(content)
+ data.channels.forEach(channel => {
+ channel.items.forEach(item => {
+ const start = dayjs(item.startTime).utc().toISOString()
+ const stop = dayjs(item.endTime).utc().toISOString()
+ programs.push({
+ title: item.title,
+ description: item.description || 'No description available',
+ category: item.qoe.genre,
+ image: item.thumbnails.standard,
+ start,
+ stop
+ })
+ })
+ })
+ return programs
+ },
+ 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 data = response.data
+
+ if (data && data.channels) {
+ return data.channels.map(item => ({
+ lang: 'el',
+ site_id: item.callSign,
+ name: item.title
+ //logo: item.logos.square
+ }))
+ } else {
+ console.error('Unexpected response structure:', data)
+ return []
+ }
+ } catch (error) {
+ console.error('Error fetching channel data:', error)
+ return []
+ }
+ }
+}
diff --git a/sites/cosmotetv.gr/cosmotetv.gr.test.js b/sites/cosmotetv.gr/cosmotetv.gr.test.js
index dc73ce7e..405e3d9b 100644
--- a/sites/cosmotetv.gr/cosmotetv.gr.test.js
+++ b/sites/cosmotetv.gr/cosmotetv.gr.test.js
@@ -1,81 +1,76 @@
-const { parser, url, channels } = 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)
-dayjs.extend(timezone)
-
-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": [
- {
- "items": [
- {
- "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"
- }
- }
- ]
- }
- ]
-}
-
-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`)
-})
-
-it('can parse response', () => {
- const content = JSON.stringify(mockEpgData)
- const result = parser({ date, content }).map(p => {
- p.start = dayjs(p.start).toISOString()
- p.stop = dayjs(p.stop).toISOString()
- return p
- })
-
- 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"
- }
- ])
-})
-
-it('can handle empty guide', () => {
- const result = parser({ date, channel, content: '{"date":"2024-12-26","categories":[],"channels":[]}' });
- expect(result).toMatchObject([])
-})
+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')
+
+dayjs.extend(utc)
+dayjs.extend(customParseFormat)
+dayjs.extend(timezone)
+
+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 mockEpgData = {
+ channels: [
+ {
+ items: [
+ {
+ 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'
+ }
+ }
+ ]
+ }
+ ]
+}
+
+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`
+ )
+})
+
+it('can parse response', () => {
+ const content = JSON.stringify(mockEpgData)
+ const result = parser({ date, content }).map(p => {
+ p.start = dayjs(p.start).toISOString()
+ p.stop = dayjs(p.stop).toISOString()
+ return p
+ })
+
+ 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'
+ }
+ ])
+})
+
+it('can handle empty guide', () => {
+ const result = parser({
+ date,
+ channel,
+ content: '{"date":"2024-12-26","categories":[],"channels":[]}'
+ })
+ expect(result).toMatchObject([])
+})
diff --git a/sites/cubmu.com/cubmu.com.config.js b/sites/cubmu.com/cubmu.com.config.js
index 6b408aed..ec288a36 100644
--- a/sites/cubmu.com/cubmu.com.config.js
+++ b/sites/cubmu.com/cubmu.com.config.js
@@ -1,102 +1,114 @@
-const dayjs = require('dayjs')
-const timezone = require('dayjs/plugin/timezone')
-const utc = require('dayjs/plugin/utc')
-
-dayjs.extend(timezone)
-dayjs.extend(utc)
-
-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}`
- },
- parser({ content, channel }) {
- const programs = []
- const items = parseItems(content)
- items.forEach(item => {
- programs.push({
- title: parseTitle(item),
- description: parseDescription(item, channel.lang),
- episode: parseEpisode(item),
- start: parseStart(item).toISOString(),
- stop: parseStop(item).toISOString()
- })
- })
-
- return programs
- },
- async channels({ lang = 'id' }) {
- const axios = require('axios')
- const cheerio = require('cheerio')
- const result = await axios
- .get('https://cubmu.com/live-tv')
- .then(response => response.data)
- .catch(console.error)
-
- const $ = cheerio.load(result)
-
- // retrieve service api data
- const config = JSON.parse($('#__NEXT_DATA__').text()).runtimeConfig || {}
-
- const options = {
- headers: {
- Origin: 'https://cubmu.com',
- Referer: 'https://cubmu.com/live-tv'
- }
- }
- // 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)
- .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)
- .then(response => response.data)
- .catch(console.error)
-
- const channels = []
- const included = []
- if (Array.isArray(subscribedChannels.channelPackageList)) {
- subscribedChannels.channelPackageList.forEach(pkg => {
- pkg.channelList.forEach(channel => {
- if (included.indexOf(channel.id) < 0) {
- included.push(channel.id)
- channels.push({
- lang,
- site_id: channel.id,
- name: channel.name
- })
- }
- })
- })
- }
-
- return channels
- }
-}
-
-function parseItems(content) {
- return content ? JSON.parse(content.trim()).result || [] : []
-}
-
-function parseTitle(item) {
- return item.scehedule_title
-}
-
-function parseDescription(item, lang = 'id') {
- return lang === 'id' ? item.schedule_json.primarySynopsis : item.schedule_json.secondarySynopsis
-}
-
-function parseEpisode(item) {
- return item.schedule_json.episodeName
-}
-
-function parseStart(item) {
- return dayjs.tz(item.schedule_date, 'YYYY-MM-DD HH:mm:ss', 'Asia/Jakarta')
-}
-
-function parseStop(item) {
- return dayjs.tz([item.schedule_date.split(' ')[0], item.schedule_end_time].join(' '), 'YYYY-MM-DD HH:mm:ss', 'Asia/Jakarta')
-}
+const dayjs = require('dayjs')
+const timezone = require('dayjs/plugin/timezone')
+const utc = require('dayjs/plugin/utc')
+
+dayjs.extend(timezone)
+dayjs.extend(utc)
+
+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}`
+ },
+ parser({ content, channel }) {
+ const programs = []
+ const items = parseItems(content)
+ items.forEach(item => {
+ programs.push({
+ title: parseTitle(item),
+ description: parseDescription(item, channel.lang),
+ episode: parseEpisode(item),
+ start: parseStart(item).toISOString(),
+ stop: parseStop(item).toISOString()
+ })
+ })
+
+ return programs
+ },
+ async channels({ lang = 'id' }) {
+ const axios = require('axios')
+ const cheerio = require('cheerio')
+ const result = await axios
+ .get('https://cubmu.com/live-tv')
+ .then(response => response.data)
+ .catch(console.error)
+
+ const $ = cheerio.load(result)
+
+ // retrieve service api data
+ const config = JSON.parse($('#__NEXT_DATA__').text()).runtimeConfig || {}
+
+ const options = {
+ headers: {
+ Origin: 'https://cubmu.com',
+ Referer: 'https://cubmu.com/live-tv'
+ }
+ }
+ // login to service bus
+ 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
+ )
+ .then(response => response.data)
+ .catch(console.error)
+
+ const channels = []
+ const included = []
+ if (Array.isArray(subscribedChannels.channelPackageList)) {
+ subscribedChannels.channelPackageList.forEach(pkg => {
+ pkg.channelList.forEach(channel => {
+ if (included.indexOf(channel.id) < 0) {
+ included.push(channel.id)
+ channels.push({
+ lang,
+ site_id: channel.id,
+ name: channel.name
+ })
+ }
+ })
+ })
+ }
+
+ return channels
+ }
+}
+
+function parseItems(content) {
+ return content ? JSON.parse(content.trim()).result || [] : []
+}
+
+function parseTitle(item) {
+ return item.scehedule_title
+}
+
+function parseDescription(item, lang = 'id') {
+ return lang === 'id' ? item.schedule_json.primarySynopsis : item.schedule_json.secondarySynopsis
+}
+
+function parseEpisode(item) {
+ return item.schedule_json.episodeName
+}
+
+function parseStart(item) {
+ return dayjs.tz(item.schedule_date, 'YYYY-MM-DD HH:mm:ss', 'Asia/Jakarta')
+}
+
+function parseStop(item) {
+ return dayjs.tz(
+ [item.schedule_date.split(' ')[0], item.schedule_end_time].join(' '),
+ 'YYYY-MM-DD HH:mm:ss',
+ 'Asia/Jakarta'
+ )
+}
diff --git a/sites/cubmu.com/cubmu.com.test.js b/sites/cubmu.com/cubmu.com.test.js
index 38bbf099..cdf5cde3 100644
--- a/sites/cubmu.com/cubmu.com.test.js
+++ b/sites/cubmu.com/cubmu.com.test.js
@@ -1,47 +1,47 @@
-const { url, parser } = require('./cubmu.com.config.js')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-dayjs.extend(utc)
-
-const date = dayjs.utc('2023-11-05', 'DD/MM/YYYY').startOf('d')
-const channel = { site_id: '4028c68574537fcd0174be43042758d8', xmltv_id: 'TransTV.id', lang: 'id' }
-const channelEn = Object.assign({}, channel, { lang: 'en' })
-
-it('can generate valid url', () => {
- expect(url({ channel, date })).toBe(
- 'https://servicebuss.transvision.co.id/v2/cms/getEPGData?app_id=cubmu&tvs_platform_id=standalone&schedule_date=2023-11-05&channel_id=4028c68574537fcd0174be43042758d8'
- )
-})
-
-it('can parse response', () => {
- const content =
- '{"result":[{"channel_id":"4028c68574537fcd0174be43042758d8","channel_name":"Trans TV","scehedule_title":"CNN Tech News","schedule_date":"2023-11-05 01:30:00","schedule_end_time":"02:00:00","schedule_json":{"availability":0,"channelId":"4028c68574537fcd0174be43042758d8","channelName":"Trans TV","duration":1800,"editable":true,"episodeName":"","imageUrl":"https://cdnjkt2.transvision.co.id:1001/catchup/schedule/thumbnail/4028c68574537fcd0174be43042758d8/4028c6858b8b3621018b9330e3701a7e/458x640","imageUrlWide":"https://cdnjkt2.transvision.co.id:1001/catchup/schedule/thumbnail/4028c68574537fcd0174be43042758d8/4028c6858b8b3621018b9330e3701a7e/320x180","name":"CNN Tech News","ottImageUrl":"","primarySynopsis":"CNN Indonesia Tech News adalah berita teknologi yang membawa pemirsa ke dunia teknologi yang penuh dengan informasi, pendidikan, hiburan sampai informasi kesehatan terkini.","scheduleId":"4028c6858b8b3621018b9330e3701a7e","scheduleTime":"18:30:00","secondarySynopsis":"CNN Indonesia Tech News is tech news brings viewers into the world of technology that provides information, education, entertainment to the latest health information.","startDt":"20231104183000","url":""},"schedule_start_time":"01:30:00"}]}'
-
- const idResults = parser({ content, channel })
- expect(idResults).toMatchObject([
- {
- start: '2023-11-04T18:30:00.000Z',
- stop: '2023-11-04T19:00:00.000Z',
- title: 'CNN Tech News',
- description:
- 'CNN Indonesia Tech News adalah berita teknologi yang membawa pemirsa ke dunia teknologi yang penuh dengan informasi, pendidikan, hiburan sampai informasi kesehatan terkini.'
- }
- ])
-
- const enResults = parser({ content, channel: channelEn })
- expect(enResults).toMatchObject([
- {
- start: '2023-11-04T18:30:00.000Z',
- stop: '2023-11-04T19:00:00.000Z',
- title: 'CNN Tech News',
- description:
- 'CNN Indonesia Tech News is tech news brings viewers into the world of technology that provides information, education, entertainment to the latest health information.'
- }
- ])
-})
-
-it('can handle empty guide', () => {
- const results = parser({ content: '' })
-
- expect(results).toMatchObject([])
-})
+const { url, parser } = require('./cubmu.com.config.js')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+dayjs.extend(utc)
+
+const date = dayjs.utc('2023-11-05', 'DD/MM/YYYY').startOf('d')
+const channel = { site_id: '4028c68574537fcd0174be43042758d8', xmltv_id: 'TransTV.id', lang: 'id' }
+const channelEn = Object.assign({}, channel, { lang: 'en' })
+
+it('can generate valid url', () => {
+ expect(url({ channel, date })).toBe(
+ 'https://servicebuss.transvision.co.id/v2/cms/getEPGData?app_id=cubmu&tvs_platform_id=standalone&schedule_date=2023-11-05&channel_id=4028c68574537fcd0174be43042758d8'
+ )
+})
+
+it('can parse response', () => {
+ const content =
+ '{"result":[{"channel_id":"4028c68574537fcd0174be43042758d8","channel_name":"Trans TV","scehedule_title":"CNN Tech News","schedule_date":"2023-11-05 01:30:00","schedule_end_time":"02:00:00","schedule_json":{"availability":0,"channelId":"4028c68574537fcd0174be43042758d8","channelName":"Trans TV","duration":1800,"editable":true,"episodeName":"","imageUrl":"https://cdnjkt2.transvision.co.id:1001/catchup/schedule/thumbnail/4028c68574537fcd0174be43042758d8/4028c6858b8b3621018b9330e3701a7e/458x640","imageUrlWide":"https://cdnjkt2.transvision.co.id:1001/catchup/schedule/thumbnail/4028c68574537fcd0174be43042758d8/4028c6858b8b3621018b9330e3701a7e/320x180","name":"CNN Tech News","ottImageUrl":"","primarySynopsis":"CNN Indonesia Tech News adalah berita teknologi yang membawa pemirsa ke dunia teknologi yang penuh dengan informasi, pendidikan, hiburan sampai informasi kesehatan terkini.","scheduleId":"4028c6858b8b3621018b9330e3701a7e","scheduleTime":"18:30:00","secondarySynopsis":"CNN Indonesia Tech News is tech news brings viewers into the world of technology that provides information, education, entertainment to the latest health information.","startDt":"20231104183000","url":""},"schedule_start_time":"01:30:00"}]}'
+
+ const idResults = parser({ content, channel })
+ expect(idResults).toMatchObject([
+ {
+ start: '2023-11-04T18:30:00.000Z',
+ stop: '2023-11-04T19:00:00.000Z',
+ title: 'CNN Tech News',
+ description:
+ 'CNN Indonesia Tech News adalah berita teknologi yang membawa pemirsa ke dunia teknologi yang penuh dengan informasi, pendidikan, hiburan sampai informasi kesehatan terkini.'
+ }
+ ])
+
+ const enResults = parser({ content, channel: channelEn })
+ expect(enResults).toMatchObject([
+ {
+ start: '2023-11-04T18:30:00.000Z',
+ stop: '2023-11-04T19:00:00.000Z',
+ title: 'CNN Tech News',
+ description:
+ 'CNN Indonesia Tech News is tech news brings viewers into the world of technology that provides information, education, entertainment to the latest health information.'
+ }
+ ])
+})
+
+it('can handle empty guide', () => {
+ const results = parser({ content: '' })
+
+ expect(results).toMatchObject([])
+})
diff --git a/sites/dens.tv/dens.tv.config.js b/sites/dens.tv/dens.tv.config.js
index 4ac40aa3..25cd3036 100644
--- a/sites/dens.tv/dens.tv.config.js
+++ b/sites/dens.tv/dens.tv.config.js
@@ -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)
diff --git a/sites/dens.tv/dens.tv.test.js b/sites/dens.tv/dens.tv.test.js
index 3417000e..79883d0f 100644
--- a/sites/dens.tv/dens.tv.test.js
+++ b/sites/dens.tv/dens.tv.test.js
@@ -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', () => {
diff --git a/sites/digiturk.com.tr/digiturk.com.tr.config.js b/sites/digiturk.com.tr/digiturk.com.tr.config.js
index 03280f4c..4dba0999 100644
--- a/sites/digiturk.com.tr/digiturk.com.tr.config.js
+++ b/sites/digiturk.com.tr/digiturk.com.tr.config.js
@@ -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'
diff --git a/sites/dishtv.in/dishtv.in.config.js b/sites/dishtv.in/dishtv.in.config.js
index 6a9d3f18..8c2bd878 100644
--- a/sites/dishtv.in/dishtv.in.config.js
+++ b/sites/dishtv.in/dishtv.in.config.js
@@ -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,
'',
''
diff --git a/sites/guida.tv/guida.tv.config.js b/sites/guida.tv/guida.tv.config.js
index 44402d16..0c14a1cd 100644
--- a/sites/guida.tv/guida.tv.config.js
+++ b/sites/guida.tv/guida.tv.config.js
@@ -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}`
diff --git a/sites/guidatv.sky.it/guidatv.sky.it.config.js b/sites/guidatv.sky.it/guidatv.sky.it.config.js
index 834deab4..ddafb89d 100644
--- a/sites/guidatv.sky.it/guidatv.sky.it.config.js
+++ b/sites/guidatv.sky.it/guidatv.sky.it.config.js
@@ -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)
diff --git a/sites/hoy.tv/hoy.tv.config.js b/sites/hoy.tv/hoy.tv.config.js
index d5931ee1..30cc2b82 100644
--- a/sites/hoy.tv/hoy.tv.config.js
+++ b/sites/hoy.tv/hoy.tv.config.js
@@ -1,63 +1,63 @@
-const axios = require('axios')
-const convert = require('xml-js')
-const dayjs = require('dayjs')
-const timezone = require('dayjs/plugin/timezone')
-
-dayjs.extend(timezone)
-
-module.exports = {
- site: 'hoy.tv',
- days: 2,
- request: {
- cache: {
- ttl: 60 * 60 * 1000 // 1h
- }
- },
- url: function ({ channel, date }) {
- return `https://epg-file.hoy.tv/hoy/OTT${channel.site_id}${date.format('YYYYMMDD')}.xml`
- },
- parser({ content, channel, date }) {
- const data = convert.xml2js(content, {
- compact: true,
- ignoreDeclaration: true,
- ignoreAttributes: true
- })
-
- const programs = []
-
- 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')) {
- continue
- }
-
- const epIndex = item.EpisodeInfo.EpisodeIndex._text
- const subtitle = parseInt(epIndex) > 0 ? `第${epIndex}集` : undefined
-
- programs.push({
- title: `${item.ComScore.ns_st_pr._text}${item.EpgOtherInfo?._text || ''}`,
- sub_title: subtitle,
- description: item.EpisodeInfo.EpisodeLongDescription._text,
- start,
- stop: dayjs.tz(item.EpgEndDateTime._text, 'YYYY-MM-DD HH:mm:ss', 'Asia/Hong_Kong'),
- })
- }
-
- return programs
- },
- async channels({ lang }) {
- const data = await axios
- .get('https://api2.hoy.tv/api/v2/a/channel')
- .then(r => r.data)
- .catch(console.error)
-
- return data.data.map(c => {
- return {
- site_id: c.videos.id,
- name: c.name.zh_hk,
- lang: 'zh',
- }
- })
- }
-}
+const axios = require('axios')
+const convert = require('xml-js')
+const dayjs = require('dayjs')
+const timezone = require('dayjs/plugin/timezone')
+
+dayjs.extend(timezone)
+
+module.exports = {
+ site: 'hoy.tv',
+ days: 2,
+ request: {
+ cache: {
+ ttl: 60 * 60 * 1000 // 1h
+ }
+ },
+ url: function ({ channel, date }) {
+ return `https://epg-file.hoy.tv/hoy/OTT${channel.site_id}${date.format('YYYYMMDD')}.xml`
+ },
+ parser({ content, date }) {
+ const data = convert.xml2js(content, {
+ compact: true,
+ ignoreDeclaration: true,
+ ignoreAttributes: true
+ })
+
+ const programs = []
+
+ 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')) {
+ continue
+ }
+
+ const epIndex = item.EpisodeInfo.EpisodeIndex._text
+ const subtitle = parseInt(epIndex) > 0 ? `第${epIndex}集` : undefined
+
+ programs.push({
+ title: `${item.ComScore.ns_st_pr._text}${item.EpgOtherInfo?._text || ''}`,
+ sub_title: subtitle,
+ description: item.EpisodeInfo.EpisodeLongDescription._text,
+ start,
+ stop: dayjs.tz(item.EpgEndDateTime._text, 'YYYY-MM-DD HH:mm:ss', 'Asia/Hong_Kong')
+ })
+ }
+
+ return programs
+ },
+ async channels() {
+ const data = await axios
+ .get('https://api2.hoy.tv/api/v2/a/channel')
+ .then(r => r.data)
+ .catch(console.error)
+
+ return data.data.map(c => {
+ return {
+ site_id: c.videos.id,
+ name: c.name.zh_hk,
+ lang: 'zh'
+ }
+ })
+ }
+}
diff --git a/sites/hoy.tv/hoy.tv.test.js b/sites/hoy.tv/hoy.tv.test.js
index 1a751021..155c2963 100644
--- a/sites/hoy.tv/hoy.tv.test.js
+++ b/sites/hoy.tv/hoy.tv.test.js
@@ -1,116 +1,115 @@
-const { parser, url } = require('./hoy.tv.config.js')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-
-dayjs.extend(utc)
-
-jest.mock('axios')
-
-const date = dayjs.utc('2024-09-13', 'YYYY-MM-DD').startOf('d')
-const channel = {
- site_id: '76',
- xmltv_id: 'HOYIBC.hk',
- lang: 'zh'
-}
-const content = `
-
-
-
- 2024-09-13 11:30:00
- 2024-09-13 12:30:00
- [PG]
- false
- false
- 2024-09-27 11:30:00
-
- 0
-
- 0
-
- http://tv.fantv.hk/images/thumbnail_1920_1080_fantv.jpg
-
-
- EQ00135
- 46
- 點講都係一家人
-
- http://tv.fantv.hk/images/nosuchthumbnail.jpg
-
-
-
- 點講都係一家人
- 0
- EQ00135
- 點講都係一家人 Episode 46
- 1
- 20240913
- 1130
- 0001
- 3704000
-
-
-
- 2024-09-13 12:30:00
- 2024-09-13 13:30:00
-
- false
- false
- 2024-09-27 12:30:00
-
- 0
-
- 0
-
- http://tv.fantv.hk/images/thumbnail_1920_1080_fantv.jpg
-
-
- ED00311
- 0
- 麝香之路
- Ep. 2 .The Secret of disappeared kingdom.shows the mysterious disappearance of the ancient Tibetan kingdom which gained world
- http://tv.fantv.hk/images/nosuchthumbnail.jpg
-
-
-
- 麝香之路
- 0
- ED00311
- 麝香之路 2024-09-13
- 1
- 20240913
- 1230
- 0001
- 3704000
-
-
-
- `
-
-it('can generate valid url', () => {
- expect(url({ channel, date })).toBe(
- 'https://epg-file.hoy.tv/hoy/OTT7620240913.xml'
- )
-})
-
-it('can parse response', () => {
- const result = parser({ content, channel, date }).map(p => {
- p.start = p.start.toJSON()
- p.stop = p.stop.toJSON()
- return p
- })
-
- expect(result).toMatchObject([
- {
- start: '2024-09-13T03:30:00.000Z',
- stop: '2024-09-13T04:30:00.000Z',
- title: '點講都係一家人[PG]',
- 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',
- }
- ])
-})
+const { parser, url } = require('./hoy.tv.config.js')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+
+dayjs.extend(utc)
+
+jest.mock('axios')
+
+const date = dayjs.utc('2024-09-13', 'YYYY-MM-DD').startOf('d')
+const channel = {
+ site_id: '76',
+ xmltv_id: 'HOYIBC.hk',
+ lang: 'zh'
+}
+const content = `
+
+
+
+ 2024-09-13 11:30:00
+ 2024-09-13 12:30:00
+ [PG]
+ false
+ false
+ 2024-09-27 11:30:00
+
+ 0
+
+ 0
+
+ http://tv.fantv.hk/images/thumbnail_1920_1080_fantv.jpg
+
+
+ EQ00135
+ 46
+ 點講都係一家人
+
+ http://tv.fantv.hk/images/nosuchthumbnail.jpg
+
+
+
+ 點講都係一家人
+ 0
+ EQ00135
+ 點講都係一家人 Episode 46
+ 1
+ 20240913
+ 1130
+ 0001
+ 3704000
+
+
+
+ 2024-09-13 12:30:00
+ 2024-09-13 13:30:00
+
+ false
+ false
+ 2024-09-27 12:30:00
+
+ 0
+
+ 0
+
+ http://tv.fantv.hk/images/thumbnail_1920_1080_fantv.jpg
+
+
+ ED00311
+ 0
+ 麝香之路
+ Ep. 2 .The Secret of disappeared kingdom.shows the mysterious disappearance of the ancient Tibetan kingdom which gained world
+ http://tv.fantv.hk/images/nosuchthumbnail.jpg
+
+
+
+ 麝香之路
+ 0
+ ED00311
+ 麝香之路 2024-09-13
+ 1
+ 20240913
+ 1230
+ 0001
+ 3704000
+
+
+
+ `
+
+it('can generate valid url', () => {
+ expect(url({ channel, date })).toBe('https://epg-file.hoy.tv/hoy/OTT7620240913.xml')
+})
+
+it('can parse response', () => {
+ const result = parser({ content, channel, date }).map(p => {
+ p.start = p.start.toJSON()
+ p.stop = p.stop.toJSON()
+ return p
+ })
+
+ expect(result).toMatchObject([
+ {
+ start: '2024-09-13T03:30:00.000Z',
+ stop: '2024-09-13T04:30:00.000Z',
+ title: '點講都係一家人[PG]',
+ 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'
+ }
+ ])
+})
diff --git a/sites/i.mjh.nz/i.mjh.nz.config.js b/sites/i.mjh.nz/i.mjh.nz.config.js
index f0a12a69..f29316a0 100644
--- a/sites/i.mjh.nz/i.mjh.nz.config.js
+++ b/sites/i.mjh.nz/i.mjh.nz.config.js
@@ -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 []
}
}
diff --git a/sites/ipko.tv/ipko.tv.config.js b/sites/ipko.tv/ipko.tv.config.js
index 6658ee01..55803f1e 100644
--- a/sites/ipko.tv/ipko.tv.config.js
+++ b/sites/ipko.tv/ipko.tv.config.js
@@ -1,73 +1,80 @@
-const axios = require('axios')
-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)
-
-module.exports = {
- site: 'ipko.tv',
- timezone: 'Europe/Belgrade',
- days: 5,
- url({ date, channel }) { 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, */*',
- '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',
- 'Sec-Fetch-Dest': 'empty',
- 'Sec-Fetch-Mode': 'cors',
- 'Sec-Fetch-Site': 'cross-site',
- 'Sec-GPC': '1',
- 'Connection': 'keep-alive'
- },
- data({ channel, date }) {
- 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,
- to: nextDayEpoch
- })
- }
- },
- parser: function ({ 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 programData = {
- title: show.title,
- description: show.summary || 'No description available',
- start: start.toISOString(),
- stop: stop.toISOString(),
- thumbnail: show.thumbnail
- }
- programs.push(programData)
- })
- 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 data = response.data.data;
- return data.map(item => ({
- lang: 'sq',
- name: String(item.channel.title),
- site_id: String(item.channel.id),
- //logo: String(item.channel.logo)
- }))
- }
-}
+const axios = require('axios')
+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)
+
+module.exports = {
+ site: 'ipko.tv',
+ timezone: 'Europe/Belgrade',
+ days: 5,
+ 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, */*',
+ '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',
+ 'Sec-Fetch-Dest': 'empty',
+ 'Sec-Fetch-Mode': 'cors',
+ 'Sec-Fetch-Site': 'cross-site',
+ 'Sec-GPC': '1',
+ Connection: 'keep-alive'
+ },
+ data({ channel, date }) {
+ 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,
+ to: nextDayEpoch
+ })
+ }
+ },
+ parser: function ({ 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 programData = {
+ title: show.title,
+ description: show.summary || 'No description available',
+ start: start.toISOString(),
+ stop: stop.toISOString(),
+ thumbnail: show.thumbnail
+ }
+ programs.push(programData)
+ })
+ 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 data = response.data.data
+ return data.map(item => ({
+ lang: 'sq',
+ name: String(item.channel.title),
+ site_id: String(item.channel.id)
+ //logo: String(item.channel.logo)
+ }))
+ }
+}
diff --git a/sites/ipko.tv/ipko.tv.test.js b/sites/ipko.tv/ipko.tv.test.js
index 2064eeb0..19a83e86 100644
--- a/sites/ipko.tv/ipko.tv.test.js
+++ b/sites/ipko.tv/ipko.tv.test.js
@@ -1,115 +1,111 @@
-const { parser, url } = require('./ipko.tv.config.js')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-const customParseFormat = require('dayjs/plugin/customParseFormat')
-dayjs.extend(customParseFormat)
-dayjs.extend(utc)
-
-const date = dayjs.utc('2024-12-24', 'YYYY-MM-DD').startOf('day')
-const channel = {
- site_id: 'ipko-promo',
- xmltv_id: 'IPKOPROMO'
-}
-
-it('can generate valid url', () => {
- expect(url({ date, channel })).toBe('https://stargate.ipko.tv/api/titan.tv.WebEpg/GetWebEpgData')
-})
-
-it('can parse response', () => {
- const content = `
- {
- "shows": [
- {
- "title": "IPKO Promo",
- "show_start": 1735012800,
- "show_end": 1735020000,
- "timestamp": "5:00 - 7:00",
- "show_id": "EPG_TvProfil_IPKOPROMO_296105567",
- "thumbnail": "https://vimg.ipko.tv/mtcms/18/2/1/1821cc68-a9bf-4733-b1af-9a5d80163b78.jpg",
- "is_adult": false,
- "friendly_id": "ipko_promo_4cf3",
- "pg": "",
- "genres": [],
- "year": 0,
- "summary": "",
- "categories": "Other",
- "stb_only": false,
- "is_live": false,
- "original_title": "IPKO Promo"
- },
- {
- "title": "IPKO Promo",
- "show_start": 1735020000,
- "show_end": 1735027200,
- "timestamp": "7:00 - 9:00",
- "show_id": "EPG_TvProfil_IPKOPROMO_296105568",
- "thumbnail": "https://vimg.ipko.tv/mtcms/18/2/1/1821cc68-a9bf-4733-b1af-9a5d80163b78.jpg",
- "is_adult": false,
- "friendly_id": "ipko_promo_416b",
- "pg": "",
- "genres": [],
- "year": 0,
- "summary": "",
- "categories": "Other",
- "stb_only": false,
- "is_live": false,
- "original_title": "IPKO Promo"
- },
- {
- "title": "IPKO Promo",
- "show_start": 1735027200,
- "show_end": 1735034400,
- "timestamp": "9:00 - 11:00",
- "show_id": "EPG_TvProfil_IPKOPROMO_296105569",
- "thumbnail": "https://vimg.ipko.tv/mtcms/18/2/1/1821cc68-a9bf-4733-b1af-9a5d80163b78.jpg",
- "is_adult": false,
- "friendly_id": "ipko_promo_2e23",
- "pg": "",
- "genres": [],
- "year": 0,
- "summary": "",
- "categories": "Other",
- "stb_only": false,
- "is_live": false,
- "original_title": "IPKO Promo"
- }
- ]
- }`
-
- const result = parser({ content, channel }).map(p => {
- p.start = p.start
- p.stop = p.stop
- return p
- })
-
- 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-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"
- }
- ])
-})
-
-it('can handle empty guide', () => {
- const result = parser({
- content: '{"shows":[]}'
- })
- expect(result).toMatchObject([])
-})
+const { parser, url } = require('./ipko.tv.config.js')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+const customParseFormat = require('dayjs/plugin/customParseFormat')
+dayjs.extend(customParseFormat)
+dayjs.extend(utc)
+
+const date = dayjs.utc('2024-12-24', 'YYYY-MM-DD').startOf('day')
+const channel = {
+ site_id: 'ipko-promo',
+ xmltv_id: 'IPKOPROMO'
+}
+
+it('can generate valid url', () => {
+ expect(url({ date, channel })).toBe('https://stargate.ipko.tv/api/titan.tv.WebEpg/GetWebEpgData')
+})
+
+it('can parse response', () => {
+ const content = `
+ {
+ "shows": [
+ {
+ "title": "IPKO Promo",
+ "show_start": 1735012800,
+ "show_end": 1735020000,
+ "timestamp": "5:00 - 7:00",
+ "show_id": "EPG_TvProfil_IPKOPROMO_296105567",
+ "thumbnail": "https://vimg.ipko.tv/mtcms/18/2/1/1821cc68-a9bf-4733-b1af-9a5d80163b78.jpg",
+ "is_adult": false,
+ "friendly_id": "ipko_promo_4cf3",
+ "pg": "",
+ "genres": [],
+ "year": 0,
+ "summary": "",
+ "categories": "Other",
+ "stb_only": false,
+ "is_live": false,
+ "original_title": "IPKO Promo"
+ },
+ {
+ "title": "IPKO Promo",
+ "show_start": 1735020000,
+ "show_end": 1735027200,
+ "timestamp": "7:00 - 9:00",
+ "show_id": "EPG_TvProfil_IPKOPROMO_296105568",
+ "thumbnail": "https://vimg.ipko.tv/mtcms/18/2/1/1821cc68-a9bf-4733-b1af-9a5d80163b78.jpg",
+ "is_adult": false,
+ "friendly_id": "ipko_promo_416b",
+ "pg": "",
+ "genres": [],
+ "year": 0,
+ "summary": "",
+ "categories": "Other",
+ "stb_only": false,
+ "is_live": false,
+ "original_title": "IPKO Promo"
+ },
+ {
+ "title": "IPKO Promo",
+ "show_start": 1735027200,
+ "show_end": 1735034400,
+ "timestamp": "9:00 - 11:00",
+ "show_id": "EPG_TvProfil_IPKOPROMO_296105569",
+ "thumbnail": "https://vimg.ipko.tv/mtcms/18/2/1/1821cc68-a9bf-4733-b1af-9a5d80163b78.jpg",
+ "is_adult": false,
+ "friendly_id": "ipko_promo_2e23",
+ "pg": "",
+ "genres": [],
+ "year": 0,
+ "summary": "",
+ "categories": "Other",
+ "stb_only": false,
+ "is_live": false,
+ "original_title": "IPKO Promo"
+ }
+ ]
+ }`
+
+ 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-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'
+ }
+ ])
+})
+
+it('can handle empty guide', () => {
+ const result = parser({
+ content: '{"shows":[]}'
+ })
+ expect(result).toMatchObject([])
+})
diff --git a/sites/m.tv.sms.cz/m.tv.sms.cz.config.js b/sites/m.tv.sms.cz/m.tv.sms.cz.config.js
index b3dcd9c2..92861212 100644
--- a/sites/m.tv.sms.cz/m.tv.sms.cz.config.js
+++ b/sites/m.tv.sms.cz/m.tv.sms.cz.config.js
@@ -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)
diff --git a/sites/magticom.ge/magticom.ge.config.js b/sites/magticom.ge/magticom.ge.config.js
index 0e5a475d..2a936ba1 100644
--- a/sites/magticom.ge/magticom.ge.config.js
+++ b/sites/magticom.ge/magticom.ge.config.js
@@ -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 []
diff --git a/sites/maxtv.hrvatskitelekom.hr/maxtv.hrvatskitelekom.hr.config.js b/sites/maxtv.hrvatskitelekom.hr/maxtv.hrvatskitelekom.hr.config.js
index c9723812..3dea9ef4 100644
--- a/sites/maxtv.hrvatskitelekom.hr/maxtv.hrvatskitelekom.hr.config.js
+++ b/sites/maxtv.hrvatskitelekom.hr/maxtv.hrvatskitelekom.hr.config.js
@@ -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)
diff --git a/sites/mediaklikk.hu/mediaklikk.hu.config.js b/sites/mediaklikk.hu/mediaklikk.hu.config.js
index 07d17a30..673fb4b3 100644
--- a/sites/mediaklikk.hu/mediaklikk.hu.config.js
+++ b/sites/mediaklikk.hu/mediaklikk.hu.config.js
@@ -56,7 +56,7 @@ function parseStop($item) {
try {
return dayjs(timeString, 'YYYY-MM-DD HH:mm:ssZZ')
- } catch (err) {
+ } catch {
return null
}
}
diff --git a/sites/mediasetinfinity.mediaset.it/mediasetinfinity.mediaset.it.config.js b/sites/mediasetinfinity.mediaset.it/mediasetinfinity.mediaset.it.config.js
index 9997eda8..3a168953 100644
--- a/sites/mediasetinfinity.mediaset.it/mediasetinfinity.mediaset.it.config.js
+++ b/sites/mediasetinfinity.mediaset.it/mediasetinfinity.mediaset.it.config.js
@@ -1,93 +1,97 @@
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-const customParseFormat = require('dayjs/plugin/customParseFormat')
-const timezone = require('dayjs/plugin/timezone')
-
-dayjs.extend(utc)
-dayjs.extend(customParseFormat)
-dayjs.extend(timezone)
-
-module.exports = {
- site: 'mediasetinfinity.mediaset.it',
- days: 2,
- 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}) {
- const programs = []
- const data = JSON.parse(content)
-
- 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) => {
- 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,
- sub_title: title && title != subTitle ? subTitle : null,
- description: listing.program.description || null,
- category: listing.program.mediasetprogram$skyGenre || null,
- season: episode && !season ? '0' : season,
- episode: episode,
- start: parseTime(listing.startTime),
- stop: parseTime(listing.endTime),
- image: getMaxResolutionThumbnails(listing)
- })
- }
- })
-
- return programs
- }
-}
-
-
-function parseTime(timestamp) {
- return dayjs(timestamp).utc().format('YYYY-MM-DD HH:mm')
-}
-
-function parseSeason(item) {
- if (!item.mediasetlisting$shortDescription) return null
- const season = item.mediasetlisting$shortDescription.match(/S(\d+)\s/)
- return season ? season[1] : null
-}
-
-function parseEpisode(item) {
- if (!item.mediasetlisting$shortDescription) return null
- const episode = item.mediasetlisting$shortDescription.match(/Ep(\d+)\s/)
- return episode ? episode[1] : null
-}
-
-function getMaxResolutionThumbnails(item) {
- const thumbnails = item.program.thumbnails || null
- const maxResolutionThumbnails = {}
-
- for (const key in thumbnails) {
- const type = key.split('-')[0] // Estrarre il tipo di thumbnail
- 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.image_keyframe_poster)
- return maxResolutionThumbnails.image_keyframe_poster.url
- else if (maxResolutionThumbnails.image_header_poster)
- return maxResolutionThumbnails.image_header_poster.url
- else
- return null
-}
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+const customParseFormat = require('dayjs/plugin/customParseFormat')
+const timezone = require('dayjs/plugin/timezone')
+
+dayjs.extend(utc)
+dayjs.extend(customParseFormat)
+dayjs.extend(timezone)
+
+module.exports = {
+ site: 'mediasetinfinity.mediaset.it',
+ days: 2,
+ 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 }) {
+ const programs = []
+ const data = JSON.parse(content)
+
+ 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 => {
+ 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,
+ sub_title: title && title != subTitle ? subTitle : null,
+ description: listing.program.description || null,
+ category: listing.program.mediasetprogram$skyGenre || null,
+ season: episode && !season ? '0' : season,
+ episode: episode,
+ start: parseTime(listing.startTime),
+ stop: parseTime(listing.endTime),
+ image: getMaxResolutionThumbnails(listing)
+ })
+ }
+ })
+
+ return programs
+ }
+}
+
+function parseTime(timestamp) {
+ return dayjs(timestamp).utc().format('YYYY-MM-DD HH:mm')
+}
+
+function parseSeason(item) {
+ if (!item.mediasetlisting$shortDescription) return null
+ const season = item.mediasetlisting$shortDescription.match(/S(\d+)\s/)
+ return season ? season[1] : null
+}
+
+function parseEpisode(item) {
+ if (!item.mediasetlisting$shortDescription) return null
+ const episode = item.mediasetlisting$shortDescription.match(/Ep(\d+)\s/)
+ return episode ? episode[1] : null
+}
+
+function getMaxResolutionThumbnails(item) {
+ const thumbnails = item.program.thumbnails || null
+ const maxResolutionThumbnails = {}
+
+ for (const key in thumbnails) {
+ const type = key.split('-')[0] // Estrarre il tipo di thumbnail
+ 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.image_keyframe_poster)
+ return maxResolutionThumbnails.image_keyframe_poster.url
+ else if (maxResolutionThumbnails.image_header_poster)
+ return maxResolutionThumbnails.image_header_poster.url
+ else return null
+}
diff --git a/sites/mediasetinfinity.mediaset.it/mediasetinfinity.mediaset.it.test.js b/sites/mediasetinfinity.mediaset.it/mediasetinfinity.mediaset.it.test.js
index 528d9200..c1c8ce11 100644
--- a/sites/mediasetinfinity.mediaset.it/mediasetinfinity.mediaset.it.test.js
+++ b/sites/mediasetinfinity.mediaset.it/mediasetinfinity.mediaset.it.test.js
@@ -1,46 +1,53 @@
-const {parser, url} = require('./mediasetinfinity.mediaset.it.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')
-dayjs.extend(customParseFormat)
-dayjs.extend(utc)
-
-const date = dayjs.utc('2024-01-20', 'YYYY-MM-DD').startOf('d')
-const channel = {
- 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')
-})
-
-it('can parse response', () => {
- const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'), 'utf8')
- const results = parser({content, date}).map(p => {
- return p
- })
-
- expect(results[3]).toMatchObject({
- start: '2024-01-20 02:14',
- 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.',
- 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'
- })
-})
-
-it('can handle empty guide', () => {
- const result = parser({
- content: '[]'
- })
- expect(result).toMatchObject([])
-})
+const { parser, url } = require('./mediasetinfinity.mediaset.it.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')
+dayjs.extend(customParseFormat)
+dayjs.extend(utc)
+
+const date = dayjs.utc('2024-01-20', 'YYYY-MM-DD').startOf('d')
+const channel = {
+ 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'
+ )
+})
+
+it('can parse response', () => {
+ const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'), 'utf8')
+ const results = parser({ content, date }).map(p => {
+ return p
+ })
+
+ expect(results[3]).toMatchObject({
+ start: '2024-01-20 02:14',
+ 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.',
+ 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'
+ })
+})
+
+it('can handle empty guide', () => {
+ const result = parser({
+ content: '[]'
+ })
+ expect(result).toMatchObject([])
+})
diff --git a/sites/meo.pt/meo.pt.config.js b/sites/meo.pt/meo.pt.config.js
index 55e74434..d3aa53a5 100644
--- a/sites/meo.pt/meo.pt.config.js
+++ b/sites/meo.pt/meo.pt.config.js
@@ -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'
}
diff --git a/sites/meuguia.tv/meuguia.tv.config.js b/sites/meuguia.tv/meuguia.tv.config.js
index c877a08f..e86f2bfa 100644
--- a/sites/meuguia.tv/meuguia.tv.config.js
+++ b/sites/meuguia.tv/meuguia.tv.config.js
@@ -1,101 +1,105 @@
-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)
-
-module.exports = {
- site: 'meuguia.tv',
- days: 2,
- url({ channel }) {
- return `https://meuguia.tv/programacao/canal/${channel.site_id}`
- },
- parser({ content, date }) {
- const programs = []
- parseItems(content, date).forEach(item => {
- if (dayjs.utc(item.start).isSame(date, 'day')) {
- programs.push(item)
- }
- })
-
- return programs
- },
- async channels() {
- const channels = []
- const axios = require('axios')
- const baseUrl = 'https://meuguia.tv'
-
- let seq = 0
- const queues = [baseUrl]
- while (true) {
- if (!queues.length) {
- break
- }
- const url = queues.shift()
- const content = await axios
- .get(url)
- .then(response => response.data)
- .catch(console.error)
-
- if (content) {
- const [ $, items ] = getItems(content)
- if (seq === 0) {
- queues.push(...items.map(category => baseUrl + $(category).attr('href')))
- } else {
- items.forEach(item => {
- const href = $(item).attr('href')
- channels.push({
- lang: 'pt',
- site_id: href.substr(href.lastIndexOf('/') + 1),
- name: $(item).find('.licontent h2').text().trim()
- })
- })
- }
- }
- seq++
- }
-
- return channels
- }
-}
-
-function getItems(content) {
- const $ = cheerio.load(content)
- return [$, $('div.mw ul li a').toArray()]
-}
-
-function parseItems(content, date) {
- const result = []
- const $ = cheerio.load(content)
-
- let lastDate
- for (const item of $('ul.mw li').toArray()) {
- const $item = $(item)
- if ($item.hasClass('subheader')) {
- lastDate = `${$item.text().split(', ')[1]}/${date.format('YYYY')}`
- } else if ($item.hasClass('divider')) {
- // ignore
- } else if (lastDate) {
- const data = { title: $item.find('a').attr('title').trim() }
- const ep = data.title.match(/T(\d+) EP(\d+)/)
- if (ep) {
- 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')
- result.push(data)
- }
- }
- // use stop time from next item
- if (result.length > 1) {
- for (let i = 0; i < result.length - 1; i++) {
- result[i].stop = result[i + 1].start
- }
- }
-
- return result
-}
\ No newline at end of file
+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)
+
+module.exports = {
+ site: 'meuguia.tv',
+ days: 2,
+ url({ channel }) {
+ return `https://meuguia.tv/programacao/canal/${channel.site_id}`
+ },
+ parser({ content, date }) {
+ const programs = []
+ parseItems(content, date).forEach(item => {
+ if (dayjs.utc(item.start).isSame(date, 'day')) {
+ programs.push(item)
+ }
+ })
+
+ return programs
+ },
+ async channels() {
+ const channels = []
+ const axios = require('axios')
+ const baseUrl = 'https://meuguia.tv'
+
+ let seq = 0
+ const queues = [baseUrl]
+ while (true) {
+ if (!queues.length) {
+ break
+ }
+ const url = queues.shift()
+ const content = await axios
+ .get(url)
+ .then(response => response.data)
+ .catch(console.error)
+
+ if (content) {
+ const [$, items] = getItems(content)
+ if (seq === 0) {
+ queues.push(...items.map(category => baseUrl + $(category).attr('href')))
+ } else {
+ items.forEach(item => {
+ const href = $(item).attr('href')
+ channels.push({
+ lang: 'pt',
+ site_id: href.substr(href.lastIndexOf('/') + 1),
+ name: $(item).find('.licontent h2').text().trim()
+ })
+ })
+ }
+ }
+ seq++
+ }
+
+ return channels
+ }
+}
+
+function getItems(content) {
+ const $ = cheerio.load(content)
+ return [$, $('div.mw ul li a').toArray()]
+}
+
+function parseItems(content, date) {
+ const result = []
+ const $ = cheerio.load(content)
+
+ let lastDate
+ for (const item of $('ul.mw li').toArray()) {
+ const $item = $(item)
+ if ($item.hasClass('subheader')) {
+ lastDate = `${$item.text().split(', ')[1]}/${date.format('YYYY')}`
+ } else if ($item.hasClass('divider')) {
+ // ignore
+ } else if (lastDate) {
+ const data = { title: $item.find('a').attr('title').trim() }
+ const ep = data.title.match(/T(\d+) EP(\d+)/)
+ if (ep) {
+ 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'
+ )
+ result.push(data)
+ }
+ }
+ // use stop time from next item
+ if (result.length > 1) {
+ for (let i = 0; i < result.length - 1; i++) {
+ result[i].stop = result[i + 1].start
+ }
+ }
+
+ return result
+}
diff --git a/sites/meuguia.tv/meuguia.tv.test.js b/sites/meuguia.tv/meuguia.tv.test.js
index c121039c..3fe2ce94 100644
--- a/sites/meuguia.tv/meuguia.tv.test.js
+++ b/sites/meuguia.tv/meuguia.tv.test.js
@@ -1,60 +1,60 @@
-const { parser, url } = require('./meuguia.tv.config.js')
-const fs = require('fs')
-const path = require('path')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-
-dayjs.extend(utc)
-
-const date = dayjs.utc('2023-11-21').startOf('d')
-const channel = {
- site_id: 'AXN',
- xmltv_id: 'AXN.id'
-}
-it('can generate valid url', () => {
- expect(url({ channel })).toBe('https://meuguia.tv/programacao/canal/AXN')
-})
-
-it('can parse response', () => {
- const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.html'))
- const result = parser({ content, channel, date }).map(p => {
- p.start = p.start.toJSON()
- if (p.stop) {
- p.stop = p.stop.toJSON()
- }
- return p
- })
-
- expect(result).toMatchObject([
- {
- title: 'Hawaii Five-0 : T10 EP4 - Tiny Is the Flower, Yet It Scents the Grasses Around It',
- start: '2023-11-21T21:20:00.000Z',
- stop: '2023-11-21T22:15:00.000Z',
- season: 10,
- episode: 4
- },
- {
- title:
- "Hawaii Five-0 : T10 EP5 - Don't Blame Ghosts and Spirits for One's Troubles; A Human Is Responsible",
- start: '2023-11-21T22:15:00.000Z',
- stop: '2023-11-21T23:10:00.000Z',
- season: 10,
- episode: 5
- },
- {
- title: 'NCIS : T5 EP15 - In the Zone',
- start: '2023-11-21T23:10:00.000Z',
- season: 5,
- episode: 15
- }
- ])
-})
-
-it('can handle empty guide', () => {
- const result = parser({
- date,
- channel,
- content: ''
- })
- expect(result).toMatchObject([])
-})
+const { parser, url } = require('./meuguia.tv.config.js')
+const fs = require('fs')
+const path = require('path')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+
+dayjs.extend(utc)
+
+const date = dayjs.utc('2023-11-21').startOf('d')
+const channel = {
+ site_id: 'AXN',
+ xmltv_id: 'AXN.id'
+}
+it('can generate valid url', () => {
+ expect(url({ channel })).toBe('https://meuguia.tv/programacao/canal/AXN')
+})
+
+it('can parse response', () => {
+ const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.html'))
+ const result = parser({ content, channel, date }).map(p => {
+ p.start = p.start.toJSON()
+ if (p.stop) {
+ p.stop = p.stop.toJSON()
+ }
+ return p
+ })
+
+ expect(result).toMatchObject([
+ {
+ title: 'Hawaii Five-0 : T10 EP4 - Tiny Is the Flower, Yet It Scents the Grasses Around It',
+ start: '2023-11-21T21:20:00.000Z',
+ stop: '2023-11-21T22:15:00.000Z',
+ season: 10,
+ episode: 4
+ },
+ {
+ title:
+ "Hawaii Five-0 : T10 EP5 - Don't Blame Ghosts and Spirits for One's Troubles; A Human Is Responsible",
+ start: '2023-11-21T22:15:00.000Z',
+ stop: '2023-11-21T23:10:00.000Z',
+ season: 10,
+ episode: 5
+ },
+ {
+ title: 'NCIS : T5 EP15 - In the Zone',
+ start: '2023-11-21T23:10:00.000Z',
+ season: 5,
+ episode: 15
+ }
+ ])
+})
+
+it('can handle empty guide', () => {
+ const result = parser({
+ date,
+ channel,
+ content: ''
+ })
+ expect(result).toMatchObject([])
+})
diff --git a/sites/mewatch.sg/mewatch.sg.config.js b/sites/mewatch.sg/mewatch.sg.config.js
index 1559fdf0..1b793c83 100644
--- a/sites/mewatch.sg/mewatch.sg.config.js
+++ b/sites/mewatch.sg/mewatch.sg.config.js
@@ -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)
diff --git a/sites/mncvision.id/mncvision.id.config.js b/sites/mncvision.id/mncvision.id.config.js
index ba944503..2dd7d94f 100644
--- a/sites/mncvision.id/mncvision.id.config.js
+++ b/sites/mncvision.id/mncvision.id.config.js
@@ -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 } })
}
diff --git a/sites/moji.id/moji.id.config.js b/sites/moji.id/moji.id.config.js
index 80c1baf7..ee6d6db2 100644
--- a/sites/moji.id/moji.id.config.js
+++ b/sites/moji.id/moji.id.config.js
@@ -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
)
diff --git a/sites/moji.id/moji.id.test.js b/sites/moji.id/moji.id.test.js
index ca2ddc55..452a7072 100644
--- a/sites/moji.id/moji.id.test.js
+++ b/sites/moji.id/moji.id.test.js
@@ -1,15 +1,9 @@
-const { url, parser } = require('./moji.id.config.js')
+const { parser } = require('./moji.id.config.js')
const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)
const date = dayjs.utc('2023-08-18', 'YYYY-MM-DD').startOf('d')
-const channel = {
- site_id: '0',
- xmltv_id: 'moji.id',
- lang: 'en',
- logo: 'https://moji.id/site/uploads/logo/62f9387ce00a2-224-x-71.png'
-}
const content =
'
schedule Jam Tayang Program
00:00 TRUST
Informasi seputar menjaga vitalitas pria
00:30 2023 AVC CHALLENGE CUP FOR WOMEN (RECORDED)
India Vs. Vietnam
02:30 ONE CHAMPIONSHIP 2021
Siaran laga-laga pertandingan tinju gaya bebas internasional. Meyuguhkan pertarungan sengit dari para petarung profeisional kelas dunia.
03:30 VOLLEYBALL NATION\'S LEAGUE 2023 (RECORDED)
TURKI vs BRAZIL
05:00 MOJI SPORT
MOJI SPORT
06:15 LIPUTAN 6 PAGI MOJI
Kompilasi ragam berita hard news dan soft news baik dari dalam negeri maupun internasional juga info prediksi cuaca di wilayah Indonesia
07:00 UNGKAP
Liputan investigasi seputar berbagai topik dan peristiwa hangat serta kontroversial yang terjadi di Indonesia
08:00 PIALA KAPOLRI 2023 PUTRI (LIVE)
PIALA KAPOLRI 2023 PUTRI (LIVE)
10:30 SERIES PAGI
GANTENG GANTENG SERIGALA
12:30 DIAM-DIAM SUKA
DIAM-DIAM SUKA
13:30 PIALA KAPOLRI 2023 PUTRA (LIVE)
PIALA KAPOLRI 2023 PUTRA (LIVE)
16:00 PIALA KAPOLRI 2023 PUTRI (LIVE)
PIALA KAPOLRI 2023 PUTRI (LIVE)
18:00 PIALA KAPOLRI 2023 PUTRA (LIVE)
PIALA KAPOLRI 2023 PUTRA (LIVE)
20:00 MOJI DRAMA (CHHOTI SARDARNI)
CHHOTI SARDARNI
21:30 SINEMA MALAM (BIDADARI CANTIK DI RUMAH KOST)
(BIDADARI CANTIK DI RUMAH KOST
23:00 TRUST
Informasi seputar menjaga vitalitas pria
23:30 TRUST
Informasi seputar menjaga vitalitas pria
00:00 TRUST
Informasi seputar menjaga vitalitas pria
00:30 UNGKAP
Liputan investigasi seputar berbagai topik dan peristiwa hangat serta kontroversial yang terjadi di Indonesia
01:00 EXCLUSIVE INTERVIEW
PETER SCHMEICHEL
01:30 PREMIER LEAGUE (LIVE)
NOTT\'M FOREST VS SHEFFIELD UTD
03:30 VOLLEYBALL NATION\'S LEAGUE 2023 FOR WOMEN (RECORDED)
GERMANY vs USA
05:00 MOJI SPORT
MOJI SPORT
06:15 LIPUTAN 6 PAGI MOJI
Kompilasi ragam berita hard news dan soft news baik dari dalam negeri maupun internasional juga info prediksi cuaca di wilayah Indonesia
07:00 UNGKAP
Liputan investigasi seputar berbagai topik dan peristiwa hangat serta kontroversial yang terjadi di Indonesia
08:00 TRUST
Informasi Kesehatan
08:30 TRUST
Informasi Kesehatan
09:00 MASAK APA CEU?
Jenny Hendrawati, seorang koki selebritis, menyajikan beraneka hidangan internasional serta membagikan tips-tips seputar dunia memasak yang mudah diikuti oleh para pemirsa di rumah.
09:30 BISIK PAGI
berbagai berita dan perkembangan terbaru dari sederet kasus yang menimpa sejumlah sosok ternama di Indonesia.
10:30 GANTENG GANTENG SERIGALA
GANTENG GANTENG SERIGALA
11:30 PIALA KAPOLRI 2023 PUTRI (LIVE)
PIALA KAPOLRI 2023 PUTRI (LIVE)
14:00 PIALA KAPOLRI 2023 PUTRA (LIVE)
PIALA KAPOLRI 2023 PUTRA (LIVE)
16:00 PIALA KAPOLRI 2023 PUTRI (LIVE)
PIALA KAPOLRI 2023 PUTRI (LIVE)
18:00 PIALA KAPOLRI 2023 PUTRA (LIVE)
PIALA KAPOLRI 2023 PUTRA (LIVE)
20:00 MOJI DRAMA (CHHOTI SARDARNI)
CHHOTI SARDARNI
20:45 PREMIER LEAGUE (LIVE)
WOLVES VS BRIGHTON
00:00 TRUST
Informasi seputar menjaga vitalitas pria
00:30 2023 AVC CHALLENGE CUP FOR WOMEN (RECORDED)
Chinese Taipei Vs. India
02:30 ONE CHAMPIONSHIP 2021
Siaran laga-laga pertandingan tinju gaya bebas internasional. Meyuguhkan pertarungan sengit dari para petarung profeisional kelas dunia.
03:30 VOLLEYBALL NATION\'S LEAGUE 2023 FOR WOMEN (RECORDED)
THAILAND vs JAPAN
05:00 MOJI SPORT
MOJI SPORT
06:15 LIPUTAN 6 PAGI MOJI
Kompilasi ragam berita hard news dan soft news baik dari dalam negeri maupun internasional juga info prediksi cuaca di wilayah Indonesia
07:00 UNGKAP
Liputan investigasi seputar berbagai topik dan peristiwa hangat serta kontroversial yang terjadi di Indonesia
08:00 TRUST
Informasi Kesehatan
08:30 TRUST
Informasi Kesehatan
09:00 MASAK APA CEU?
Jenny Hendrawati, seorang koki selebritis, menyajikan beraneka hidangan internasional serta membagikan tips-tips seputar dunia memasak yang mudah diikuti oleh para pemirsa di rumah.
09:30 BISIK PAGI
berbagai berita dan perkembangan terbaru dari sederet kasus yang menimpa sejumlah sosok ternama di Indonesia.
10:30 GANTENG GANTENG SERIGALA
GANTENG GANTENG SERIGALA
12:30 DIAM-DIAM SUKA
DIAM-DIAM SUKA
16:00 SEA VLEAGUE (RECORDED)
PHILIPPINES VS INDONESIA
18:00 NETIZEN UPDATE
berbagai berita dan perkembangan terbaru dari sederet kasus yang menimpa sejumlah sosok ternama di Indonesia.
19:00 MOJI DRAMA (CHHOTI SARDARNI)
CHHOTI SARDARNI
21:00 MOJI MOVIE (LONDON LOVE STORY)
LONDON LOVE STORY
23:00 TRUST
Informasi seputar menjaga vitalitas pria
23:30 TRUST
Informasi seputar menjaga vitalitas pria
'
@@ -20,12 +14,11 @@ it('can handle empty guide', () => {
})
it('can parse response', () => {
- const results = parser({ content, date })
- .map(p => {
- p.start = p.start.year(2023).toJSON()
- p.stop = p.stop.year(2023).toJSON()
- return p
- })
+ const results = parser({ content, date }).map(p => {
+ p.start = p.start.year(2023).toJSON()
+ p.stop = p.stop.year(2023).toJSON()
+ return p
+ })
expect(results[0]).toMatchObject({
title: 'TRUST',
diff --git a/sites/mtel.ba/mtel.ba.config.js b/sites/mtel.ba/mtel.ba.config.js
index 2da967bd..d2a6cc85 100644
--- a/sites/mtel.ba/mtel.ba.config.js
+++ b/sites/mtel.ba/mtel.ba.config.js
@@ -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'
diff --git a/sites/mts.rs/mts.rs.config.js b/sites/mts.rs/mts.rs.config.js
index 251cae94..8b700c38 100644
--- a/sites/mts.rs/mts.rs.config.js
+++ b/sites/mts.rs/mts.rs.config.js
@@ -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
diff --git a/sites/mujtvprogram.cz/mujtvprogram.cz.config.js b/sites/mujtvprogram.cz/mujtvprogram.cz.config.js
index e544721c..0a8ddb95 100644
--- a/sites/mujtvprogram.cz/mujtvprogram.cz.config.js
+++ b/sites/mujtvprogram.cz/mujtvprogram.cz.config.js
@@ -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 []
}
}
diff --git a/sites/musor.tv/musor.tv.config.js b/sites/musor.tv/musor.tv.config.js
index 5900d6f6..d645a811 100644
--- a/sites/musor.tv/musor.tv.config.js
+++ b/sites/musor.tv/musor.tv.config.js
@@ -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 = {
diff --git a/sites/musor.tv/musor.tv.test.js b/sites/musor.tv/musor.tv.test.js
index 42ed2d4b..98bbd4be 100644
--- a/sites/musor.tv/musor.tv.test.js
+++ b/sites/musor.tv/musor.tv.test.js
@@ -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',
diff --git a/sites/mytelly.co.uk/mytelly.co.uk.config.js b/sites/mytelly.co.uk/mytelly.co.uk.config.js
index 282f8dc4..6ebe128a 100644
--- a/sites/mytelly.co.uk/mytelly.co.uk.config.js
+++ b/sites/mytelly.co.uk/mytelly.co.uk.config.js
@@ -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
diff --git a/sites/mytelly.co.uk/mytelly.co.uk.test.js b/sites/mytelly.co.uk/mytelly.co.uk.test.js
index 20f6ced0..6199a416 100644
--- a/sites/mytelly.co.uk/mytelly.co.uk.test.js
+++ b/sites/mytelly.co.uk/mytelly.co.uk.test.js
@@ -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
diff --git a/sites/neo.io/neo.io.config.js b/sites/neo.io/neo.io.config.js
index 28d41e8d..bea58fca 100644
--- a/sites/neo.io/neo.io.config.js
+++ b/sites/neo.io/neo.io.config.js
@@ -1,73 +1,80 @@
-const axios = require('axios')
-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)
-
-module.exports = {
- site: 'neo.io',
- timezone: 'Europe/Ljubljana',
- days: 5,
- url({ date, channel }) { 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, */*',
- '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',
- 'Sec-Fetch-Dest': 'empty',
- 'Sec-Fetch-Mode': 'cors',
- 'Sec-Fetch-Site': 'cross-site',
- 'Sec-GPC': '1',
- 'Connection': 'keep-alive'
- },
- data({ channel, date }) {
- 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,
- to: nextDayEpoch
- })
- }
- },
- parser: function ({ 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 programData = {
- title: show.title,
- description: show.summary || 'No description available',
- start: start.toISOString(),
- stop: stop.toISOString(),
- thumbnail: show.thumbnail
- }
- programs.push(programData)
- })
- 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 data = response.data.data;
- return data.map(item => ({
- lang: 'sq',
- name: String(item.channel.title),
- site_id: String(item.channel.id),
- //logo: String(item.channel.logo)
- }))
- }
-}
+const axios = require('axios')
+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)
+
+module.exports = {
+ site: 'neo.io',
+ timezone: 'Europe/Ljubljana',
+ days: 5,
+ 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, */*',
+ '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',
+ 'Sec-Fetch-Dest': 'empty',
+ 'Sec-Fetch-Mode': 'cors',
+ 'Sec-Fetch-Site': 'cross-site',
+ 'Sec-GPC': '1',
+ Connection: 'keep-alive'
+ },
+ data({ channel, date }) {
+ 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,
+ to: nextDayEpoch
+ })
+ }
+ },
+ parser: function ({ 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 programData = {
+ title: show.title,
+ description: show.summary || 'No description available',
+ start: start.toISOString(),
+ stop: stop.toISOString(),
+ thumbnail: show.thumbnail
+ }
+ programs.push(programData)
+ })
+ 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 data = response.data.data
+ return data.map(item => ({
+ lang: 'sq',
+ name: String(item.channel.title),
+ site_id: String(item.channel.id)
+ //logo: String(item.channel.logo)
+ }))
+ }
+}
diff --git a/sites/neo.io/neo.io.test.js b/sites/neo.io/neo.io.test.js
index 3698a2fb..295120f7 100644
--- a/sites/neo.io/neo.io.test.js
+++ b/sites/neo.io/neo.io.test.js
@@ -1,121 +1,124 @@
-const { parser, url } = require('./neo.io.config.js')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-const customParseFormat = require('dayjs/plugin/customParseFormat')
-dayjs.extend(customParseFormat)
-dayjs.extend(utc)
-
-const date = dayjs.utc('2024-12-26', 'YYYY-MM-DD').startOf('day')
-const channel = {
- site_id: 'tv-slo-1',
- xmltv_id: 'TVSLO1.si'
-}
-
-it('can generate valid url', () => {
- expect(url({ date, channel })).toBe('https://stargate.telekom.si/api/titan.tv.WebEpg/GetWebEpgData')
-})
-
-it('can parse response', () => {
- const content = `
- {
- "shows": [
- {
- "title": "Napovedujemo",
- "show_start": 1735185900,
- "show_end": 1735192200,
- "timestamp": "5:05 - 6:50",
- "show_id": "CUP_IECOM_SLO1_10004660",
- "thumbnail": "https://ngimg.siol.tv/sioltv/mtcmsprod/52/0/0/5200d01a-fe5f-487e-835a-274e77227a6b.jpg",
- "is_adult": false,
- "friendly_id": "napovedujemo_db48",
- "pg": "",
- "genres": [
- "napovednik"
- ],
- "year": 0,
- "summary": "Vabilo k ogledu naših oddaj.",
- "categories": "Ostalo",
- "stb_only": false,
- "is_live": false,
- "original_title": "Napovedujemo"
- },
- {
- "title": "S0E0 - Hrabri zajčki: Prvi sneg",
- "show_start": 1735192200,
- "show_end": 1735192800,
- "timestamp": "6:50 - 7:00",
- "show_id": "CUP_IECOM_SLO1_79637910",
- "thumbnail": "https://ngimg.siol.tv/sioltv/mtcmsprod/d6/4/5/d6456f4a-4f0a-4825-90c1-1749abd59688.jpg",
- "is_adult": false,
- "friendly_id": "hrabri_zajcki_prvi_sneg_1619",
- "pg": "",
- "genres": [
- "risanka"
- ],
- "year": 2020,
- "summary": "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.",
- "categories": "Otroški/Mladinski",
- "stb_only": false,
- "is_live": false,
- "original_title": "S0E0 - Brave Bunnies"
- },
- {
- "title": "Dobro jutro",
- "show_start": 1735192800,
- "show_end": 1735203900,
- "timestamp": "7:00 - 10:05",
- "show_id": "CUP_IECOM_SLO1_79637911",
- "thumbnail": "https://ngimg.siol.tv/sioltv/mtcmsprod/e1/2/d/e12d8eb4-693a-43d3-89d4-fd96dade9f0f.jpg",
- "is_adult": false,
- "friendly_id": "dobro_jutro_2f10",
- "pg": "",
- "genres": [
- "zabavna oddaja"
- ],
- "year": 2024,
- "summary": "Oddaja Dobro jutro poleg informativnih in zabavnih vsebin podaja koristne nasvete o najrazličnejših tematikah iz vsakdanjega življenja.",
- "categories": "Razvedrilni program",
- "stb_only": false,
- "is_live": false,
- "original_title": "Dobro jutro"
- }
- ]
- }`
-
- const result = parser({ content, channel }).map(p => {
- p.start = p.start
- p.stop = p.stop
- return p
- })
-
- 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: "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"
- }
- ])
-})
-
-it('can handle empty guide', () => {
- const result = parser({
- content: '{"shows":[]}'
- })
- expect(result).toMatchObject([])
-})
+const { parser, url } = require('./neo.io.config.js')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+const customParseFormat = require('dayjs/plugin/customParseFormat')
+dayjs.extend(customParseFormat)
+dayjs.extend(utc)
+
+const date = dayjs.utc('2024-12-26', 'YYYY-MM-DD').startOf('day')
+const channel = {
+ site_id: 'tv-slo-1',
+ xmltv_id: 'TVSLO1.si'
+}
+
+it('can generate valid url', () => {
+ expect(url({ date, channel })).toBe(
+ 'https://stargate.telekom.si/api/titan.tv.WebEpg/GetWebEpgData'
+ )
+})
+
+it('can parse response', () => {
+ const content = `
+ {
+ "shows": [
+ {
+ "title": "Napovedujemo",
+ "show_start": 1735185900,
+ "show_end": 1735192200,
+ "timestamp": "5:05 - 6:50",
+ "show_id": "CUP_IECOM_SLO1_10004660",
+ "thumbnail": "https://ngimg.siol.tv/sioltv/mtcmsprod/52/0/0/5200d01a-fe5f-487e-835a-274e77227a6b.jpg",
+ "is_adult": false,
+ "friendly_id": "napovedujemo_db48",
+ "pg": "",
+ "genres": [
+ "napovednik"
+ ],
+ "year": 0,
+ "summary": "Vabilo k ogledu naših oddaj.",
+ "categories": "Ostalo",
+ "stb_only": false,
+ "is_live": false,
+ "original_title": "Napovedujemo"
+ },
+ {
+ "title": "S0E0 - Hrabri zajčki: Prvi sneg",
+ "show_start": 1735192200,
+ "show_end": 1735192800,
+ "timestamp": "6:50 - 7:00",
+ "show_id": "CUP_IECOM_SLO1_79637910",
+ "thumbnail": "https://ngimg.siol.tv/sioltv/mtcmsprod/d6/4/5/d6456f4a-4f0a-4825-90c1-1749abd59688.jpg",
+ "is_adult": false,
+ "friendly_id": "hrabri_zajcki_prvi_sneg_1619",
+ "pg": "",
+ "genres": [
+ "risanka"
+ ],
+ "year": 2020,
+ "summary": "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.",
+ "categories": "Otroški/Mladinski",
+ "stb_only": false,
+ "is_live": false,
+ "original_title": "S0E0 - Brave Bunnies"
+ },
+ {
+ "title": "Dobro jutro",
+ "show_start": 1735192800,
+ "show_end": 1735203900,
+ "timestamp": "7:00 - 10:05",
+ "show_id": "CUP_IECOM_SLO1_79637911",
+ "thumbnail": "https://ngimg.siol.tv/sioltv/mtcmsprod/e1/2/d/e12d8eb4-693a-43d3-89d4-fd96dade9f0f.jpg",
+ "is_adult": false,
+ "friendly_id": "dobro_jutro_2f10",
+ "pg": "",
+ "genres": [
+ "zabavna oddaja"
+ ],
+ "year": 2024,
+ "summary": "Oddaja Dobro jutro poleg informativnih in zabavnih vsebin podaja koristne nasvete o najrazličnejših tematikah iz vsakdanjega življenja.",
+ "categories": "Razvedrilni program",
+ "stb_only": false,
+ "is_live": false,
+ "original_title": "Dobro jutro"
+ }
+ ]
+ }`
+
+ 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: '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'
+ }
+ ])
+})
+
+it('can handle empty guide', () => {
+ const result = parser({
+ content: '{"shows":[]}'
+ })
+ expect(result).toMatchObject([])
+})
diff --git a/sites/nhkworldpremium.com/nhkworldpremium.com.config.js b/sites/nhkworldpremium.com/nhkworldpremium.com.config.js
index bdce0c26..79ba59bf 100644
--- a/sites/nhkworldpremium.com/nhkworldpremium.com.config.js
+++ b/sites/nhkworldpremium.com/nhkworldpremium.com.config.js
@@ -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 []
}
}
diff --git a/sites/nhl.com/nhl.com.config.js b/sites/nhl.com/nhl.com.config.js
index c3c01408..46127652 100644
--- a/sites/nhl.com/nhl.com.config.js
+++ b/sites/nhl.com/nhl.com.config.js
@@ -1,45 +1,46 @@
-const dayjs = require('dayjs')
-
-module.exports = {
- site: 'nhl.com',
- // 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]}`,
- parser({ content }) {
- const programs = []
- const items = parseItems(content)
- for (const item of items) {
- programs.push({
- title: item.title,
- description: item.description === item.title ? undefined : item.description,
- category: "Sports",
- // image: parseImage(item),
- start: parseStart(item),
- stop: parseStop(item)
- })
- }
-
- return programs
- }
-}
-
-// Unfortunately I couldn't determine how these are
-// supposed to be formatted. Pointers appreciated!
-// function parseImage(item) {
-// const uri = item.broadcastImageUrl
-
-// return uri ? `https://???/${uri}` : null
-// }
-
-function parseStart(item) {
- return dayjs(item.startTime)
-}
-
-function parseStop(item) {
- return dayjs(item.endTime)
-}
-
-function parseItems(content) {
- return JSON.parse(content).broadcasts
-}
+const dayjs = require('dayjs')
+
+module.exports = {
+ site: 'nhl.com',
+ // 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]}`,
+ parser({ content }) {
+ const programs = []
+ const items = parseItems(content)
+ for (const item of items) {
+ programs.push({
+ title: item.title,
+ description: item.description === item.title ? undefined : item.description,
+ category: 'Sports',
+ // image: parseImage(item),
+ start: parseStart(item),
+ stop: parseStop(item)
+ })
+ }
+
+ return programs
+ }
+}
+
+// Unfortunately I couldn't determine how these are
+// supposed to be formatted. Pointers appreciated!
+// function parseImage(item) {
+// const uri = item.broadcastImageUrl
+
+// return uri ? `https://???/${uri}` : null
+// }
+
+function parseStart(item) {
+ return dayjs(item.startTime)
+}
+
+function parseStop(item) {
+ return dayjs(item.endTime)
+}
+
+function parseItems(content) {
+ return JSON.parse(content).broadcasts
+}
diff --git a/sites/nhl.com/nhl.com.test.js b/sites/nhl.com/nhl.com.test.js
index a12db69a..49ce4a0e 100644
--- a/sites/nhl.com/nhl.com.test.js
+++ b/sites/nhl.com/nhl.com.test.js
@@ -1,44 +1,44 @@
-const { parser, url } = require('./nhl.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')
-dayjs.extend(customParseFormat)
-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'
- )
-})
-
-it('can parse response', () => {
- const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'))
- let results = parser({ content, date })
- results = results.map(p => {
- p.start = p.start.toJSON()
- p.stop = p.stop.toJSON()
- return p
- })
-
- expect(results[0]).toMatchObject({
- start: '2024-11-21T12:00:00.000Z',
- stop: '2024-11-21T13:00:00.000Z',
- title: 'On The Fly',
- 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: [],
- }) })
- expect(results).toMatchObject([])
-})
+const { parser, url } = require('./nhl.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')
+dayjs.extend(customParseFormat)
+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')
+})
+
+it('can parse response', () => {
+ const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'))
+ let results = parser({ content, date })
+ results = results.map(p => {
+ p.start = p.start.toJSON()
+ p.stop = p.stop.toJSON()
+ return p
+ })
+
+ expect(results[0]).toMatchObject({
+ start: '2024-11-21T12:00:00.000Z',
+ stop: '2024-11-21T13:00:00.000Z',
+ title: 'On The Fly',
+ 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: []
+ })
+ })
+ expect(results).toMatchObject([])
+})
diff --git a/sites/nostv.pt/nostv.pt.config.js b/sites/nostv.pt/nostv.pt.config.js
index a823d165..6ba4dbac 100644
--- a/sites/nostv.pt/nostv.pt.config.js
+++ b/sites/nostv.pt/nostv.pt.config.js
@@ -1,68 +1,68 @@
-const axios = require('axios')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-
-dayjs.extend(utc)
-
-const headers = {
- 'X-Apikey': 'xe1dgrShwdR1DVOKGmsj8Ut4QLlGyOFI',
- 'X-Core-Appversion': '2.14.0.1',
- 'X-Core-Contentratinglimit': '0',
- 'X-Core-Deviceid': '',
- 'X-Core-Devicetype': 'web',
- Origin: 'https://nostv.pt',
- 'User-Agent':
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
-}
-
-module.exports = {
- site: 'nostv.pt',
- days: 2,
- url({ channel, date }) {
- return `https://tyr-prod.apigee.net/nostv/ott/schedule/range/contents/guest?channels=${
- channel.site_id
- }&minDate=${date.format('YYYY-MM-DD')}T00:00:00Z&maxDate=${date.format(
- 'YYYY-MM-DD'
- )}T23:59:59Z&isDateInclusive=true&client_id=${headers['X-Apikey']}`
- },
- request: { headers },
- parser({ content }) {
- const programs = []
- if (content) {
- const items = Array.isArray(content) ? content : JSON.parse(content)
- items.forEach(item => {
- programs.push({
- title: item.Metadata?.Title,
- sub_title: item.Metadata?.SubTitle ? item.Metadata?.SubTitle : null,
- description: item.Metadata?.Description,
- season: item.Metadata?.Season,
- episode: item.Metadata?.Episode,
- image: item.Images
- ? `https://mage.stream.nos.pt/v1/nostv_mage/Images?sourceUri=${item.Images[0].Url}&profile=ott_1_452x340&client_id=${headers['X-Apikey']}`
- : null,
- start: dayjs.utc(item.UtcDateTimeStart),
- stop: dayjs.utc(item.UtcDateTimeEnd)
- })
- })
- }
-
- return programs
- },
- async channels() {
- const result = await axios
- .get(
- `https://tyr-prod.apigee.net/nostv/ott/channels/guest?client_id=${headers['X-Apikey']}`,
- { headers }
- )
- .then(r => r.data)
- .catch(console.error)
-
- return result.map(item => {
- return {
- lang: 'pt',
- site_id: item.ServiceId,
- name: item.Name
- }
- })
- }
-}
+const axios = require('axios')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+
+dayjs.extend(utc)
+
+const headers = {
+ 'X-Apikey': 'xe1dgrShwdR1DVOKGmsj8Ut4QLlGyOFI',
+ 'X-Core-Appversion': '2.14.0.1',
+ 'X-Core-Contentratinglimit': '0',
+ 'X-Core-Deviceid': '',
+ 'X-Core-Devicetype': 'web',
+ Origin: 'https://nostv.pt',
+ 'User-Agent':
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
+}
+
+module.exports = {
+ site: 'nostv.pt',
+ days: 2,
+ url({ channel, date }) {
+ return `https://tyr-prod.apigee.net/nostv/ott/schedule/range/contents/guest?channels=${
+ channel.site_id
+ }&minDate=${date.format('YYYY-MM-DD')}T00:00:00Z&maxDate=${date.format(
+ 'YYYY-MM-DD'
+ )}T23:59:59Z&isDateInclusive=true&client_id=${headers['X-Apikey']}`
+ },
+ request: { headers },
+ parser({ content }) {
+ const programs = []
+ if (content) {
+ const items = Array.isArray(content) ? content : JSON.parse(content)
+ items.forEach(item => {
+ programs.push({
+ title: item.Metadata?.Title,
+ sub_title: item.Metadata?.SubTitle ? item.Metadata?.SubTitle : null,
+ description: item.Metadata?.Description,
+ season: item.Metadata?.Season,
+ episode: item.Metadata?.Episode,
+ image: item.Images
+ ? `https://mage.stream.nos.pt/v1/nostv_mage/Images?sourceUri=${item.Images[0].Url}&profile=ott_1_452x340&client_id=${headers['X-Apikey']}`
+ : null,
+ start: dayjs.utc(item.UtcDateTimeStart),
+ stop: dayjs.utc(item.UtcDateTimeEnd)
+ })
+ })
+ }
+
+ return programs
+ },
+ async channels() {
+ const result = await axios
+ .get(
+ `https://tyr-prod.apigee.net/nostv/ott/channels/guest?client_id=${headers['X-Apikey']}`,
+ { headers }
+ )
+ .then(r => r.data)
+ .catch(console.error)
+
+ return result.map(item => {
+ return {
+ lang: 'pt',
+ site_id: item.ServiceId,
+ name: item.Name
+ }
+ })
+ }
+}
diff --git a/sites/nostv.pt/nostv.pt.test.js b/sites/nostv.pt/nostv.pt.test.js
index 47297845..b4163c9b 100644
--- a/sites/nostv.pt/nostv.pt.test.js
+++ b/sites/nostv.pt/nostv.pt.test.js
@@ -1,51 +1,51 @@
-const { parser, url } = require('./nostv.pt.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')
-
-dayjs.extend(customParseFormat)
-dayjs.extend(utc)
-
-const date = dayjs.utc('2023-12-11').startOf('d')
-const channel = {
- site_id: '510',
- xmltv_id: 'SPlus.pt'
-}
-
-it('can generate valid url', () => {
- expect(url({ channel, date })).toBe(
- 'https://tyr-prod.apigee.net/nostv/ott/schedule/range/contents/guest?channels=510&minDate=2023-12-11T00:00:00Z&maxDate=2023-12-11T23:59:59Z&isDateInclusive=true&client_id=xe1dgrShwdR1DVOKGmsj8Ut4QLlGyOFI'
- )
-})
-
-it('can parse response', () => {
- const content = fs.readFileSync(path.resolve(__dirname, '__data__/data.json'))
- const results = parser({ content }).map(p => {
- p.start = p.start.toJSON()
- p.stop = p.stop.toJSON()
- return p
- })
-
- expect(results[0]).toMatchObject({
- start: '2023-12-11T16:30:00.000Z',
- stop: '2023-12-11T17:00:00.000Z',
- title: 'Village Vets',
- description:
- 'A história de dois melhores amigos veterinários e o seu extraordinário trabalho na Austrália.',
- season: 1,
- episode: 12,
- image:
- 'https://mage.stream.nos.pt/v1/nostv_mage/Images?sourceUri=http://vip.pam.local.internal/PAM.Images/Store/8329ed1aec5d4c0faa2056972256ff9f&profile=ott_1_452x340&client_id=xe1dgrShwdR1DVOKGmsj8Ut4QLlGyOFI'
- })
-})
-
-it('can handle empty guide', async () => {
- const results = await parser({
- date,
- content: '[]'
- })
-
- expect(results).toMatchObject([])
-})
+const { parser, url } = require('./nostv.pt.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')
+
+dayjs.extend(customParseFormat)
+dayjs.extend(utc)
+
+const date = dayjs.utc('2023-12-11').startOf('d')
+const channel = {
+ site_id: '510',
+ xmltv_id: 'SPlus.pt'
+}
+
+it('can generate valid url', () => {
+ expect(url({ channel, date })).toBe(
+ 'https://tyr-prod.apigee.net/nostv/ott/schedule/range/contents/guest?channels=510&minDate=2023-12-11T00:00:00Z&maxDate=2023-12-11T23:59:59Z&isDateInclusive=true&client_id=xe1dgrShwdR1DVOKGmsj8Ut4QLlGyOFI'
+ )
+})
+
+it('can parse response', () => {
+ const content = fs.readFileSync(path.resolve(__dirname, '__data__/data.json'))
+ const results = parser({ content }).map(p => {
+ p.start = p.start.toJSON()
+ p.stop = p.stop.toJSON()
+ return p
+ })
+
+ expect(results[0]).toMatchObject({
+ start: '2023-12-11T16:30:00.000Z',
+ stop: '2023-12-11T17:00:00.000Z',
+ title: 'Village Vets',
+ description:
+ 'A história de dois melhores amigos veterinários e o seu extraordinário trabalho na Austrália.',
+ season: 1,
+ episode: 12,
+ image:
+ 'https://mage.stream.nos.pt/v1/nostv_mage/Images?sourceUri=http://vip.pam.local.internal/PAM.Images/Store/8329ed1aec5d4c0faa2056972256ff9f&profile=ott_1_452x340&client_id=xe1dgrShwdR1DVOKGmsj8Ut4QLlGyOFI'
+ })
+})
+
+it('can handle empty guide', async () => {
+ const results = await parser({
+ date,
+ content: '[]'
+ })
+
+ expect(results).toMatchObject([])
+})
diff --git a/sites/nuevosiglo.com.uy/nuevosiglo.com.uy.config.js b/sites/nuevosiglo.com.uy/nuevosiglo.com.uy.config.js
index 37429ac8..6dd2c7e1 100644
--- a/sites/nuevosiglo.com.uy/nuevosiglo.com.uy.config.js
+++ b/sites/nuevosiglo.com.uy/nuevosiglo.com.uy.config.js
@@ -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')
}
})
diff --git a/sites/nzxmltv.com/nzxmltv.com.config.js b/sites/nzxmltv.com/nzxmltv.com.config.js
index 4c6e42b8..609b2c09 100644
--- a/sites/nzxmltv.com/nzxmltv.com.config.js
+++ b/sites/nzxmltv.com/nzxmltv.com.config.js
@@ -1,81 +1,81 @@
-const parser = require('epg-parser')
-
-module.exports = {
- site: 'nzxmltv.com',
- days: 2,
- request: {
- cache: {
- ttl: 3600000 // 1 hour
- },
- maxContentLength: 104857600 // 100 MB
- },
- url({ channel }) {
- const [path] = channel.site_id.split('#')
-
- return `https://nzxmltv.com/${path}.xml`
- },
- parser({ content, channel, date }) {
- const programs = []
- parseItems(content, channel, date).forEach(item => {
- const program = {
- title: item.title?.[0]?.value,
- description: item.desc?.[0]?.value,
- icon: item.icon?.[0],
- start: item.start,
- stop: item.stop
- }
- if (item.episodeNum) {
- item.episodeNum.forEach(ep => {
- if (ep.system === 'xmltv_ns') {
- const [season, episode, _] = ep.value.split('.')
- program.season = parseInt(season) + 1
- program.episode = parseInt(episode) + 1
- return true
- }
- })
- }
- programs.push(program)
- })
-
- return programs
- },
- async channels({ provider }) {
- const axios = require('axios')
- const cheerio = require('cheerio')
-
- const providers = {
- freeview: 'xmltv/guide',
- sky: 'sky/guide',
- redbull: 'iptv/redbull',
- pluto: 'iptv/plutotv'
- }
-
- const channels = []
- const path = providers[provider]
- const xml = await axios
- .get(`https://nzxmltv.com/${path}.xml`)
- .then(r => r.data)
- .catch(console.error)
-
- const $ = cheerio.load(xml)
- $('tv channel').each((i, el) => {
- const disp = $(el).find('display-name')
- const channelId = $(el).attr('id')
-
- channels.push({
- lang: disp.attr('lang').substr(0, 2),
- site_id: `${path}#${channelId}`,
- name: disp.text().trim()
- })
- })
-
- return channels
- }
-}
-
-function parseItems(content, channel, date) {
- const { programs } = parser.parse(content)
- const [, channelId] = channel.site_id.split('#')
-
- return programs.filter(p => p.channel === channelId && date.isSame(p.start, 'day'))
-}
+const parser = require('epg-parser')
+
+module.exports = {
+ site: 'nzxmltv.com',
+ days: 2,
+ request: {
+ cache: {
+ ttl: 3600000 // 1 hour
+ },
+ maxContentLength: 104857600 // 100 MB
+ },
+ url({ channel }) {
+ const [path] = channel.site_id.split('#')
+
+ return `https://nzxmltv.com/${path}.xml`
+ },
+ parser({ content, channel, date }) {
+ const programs = []
+ parseItems(content, channel, date).forEach(item => {
+ const program = {
+ title: item.title?.[0]?.value,
+ description: item.desc?.[0]?.value,
+ icon: item.icon?.[0],
+ start: item.start,
+ stop: item.stop
+ }
+ if (item.episodeNum) {
+ item.episodeNum.forEach(ep => {
+ if (ep.system === 'xmltv_ns') {
+ const [season, episode] = ep.value.split('.')
+ program.season = parseInt(season) + 1
+ program.episode = parseInt(episode) + 1
+ return true
+ }
+ })
+ }
+ programs.push(program)
+ })
+
+ return programs
+ },
+ async channels({ provider }) {
+ const axios = require('axios')
+ const cheerio = require('cheerio')
+
+ const providers = {
+ freeview: 'xmltv/guide',
+ sky: 'sky/guide',
+ redbull: 'iptv/redbull',
+ pluto: 'iptv/plutotv'
+ }
+
+ const channels = []
+ const path = providers[provider]
+ const xml = await axios
+ .get(`https://nzxmltv.com/${path}.xml`)
+ .then(r => r.data)
+ .catch(console.error)
+
+ const $ = cheerio.load(xml)
+ $('tv channel').each((i, el) => {
+ const disp = $(el).find('display-name')
+ const channelId = $(el).attr('id')
+
+ channels.push({
+ lang: disp.attr('lang').substr(0, 2),
+ site_id: `${path}#${channelId}`,
+ name: disp.text().trim()
+ })
+ })
+
+ return channels
+ }
+}
+
+function parseItems(content, channel, date) {
+ const { programs } = parser.parse(content)
+ const [, channelId] = channel.site_id.split('#')
+
+ return programs.filter(p => p.channel === channelId && date.isSame(p.start, 'day'))
+}
diff --git a/sites/nzxmltv.com/nzxmltv.com.test.js b/sites/nzxmltv.com/nzxmltv.com.test.js
index f1af8d89..e6ef97a8 100644
--- a/sites/nzxmltv.com/nzxmltv.com.test.js
+++ b/sites/nzxmltv.com/nzxmltv.com.test.js
@@ -1,40 +1,40 @@
-const { parser, url } = require('./nzxmltv.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')
-
-dayjs.extend(customParseFormat)
-dayjs.extend(utc)
-
-const date = dayjs.utc('2023-11-21').startOf('d')
-const channel = {
- site_id: 'xmltv/guide#1',
- xmltv_id: 'TVNZ1.nz'
-}
-
-it('can generate valid url', () => {
- expect(url({ channel })).toBe('https://nzxmltv.com/xmltv/guide.xml')
-})
-
-it('can parse response', () => {
- const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.xml'))
- const results = parser({ content, channel, date })
-
- expect(results[0]).toMatchObject({
- start: '2023-11-21T10:30:00.000Z',
- stop: '2023-11-21T11:25:00.000Z',
- title: 'Sunday',
- description:
- 'On Sunday, an unmissable show with stories about divorce, weight loss, and the incomprehensible devastation of Gaza.',
- season: 2023,
- episode: 37,
- icon: 'https://www.thetvdb.com/banners/posters/5dbebff2986f2.jpg'
- })
-})
-
-it('can handle empty guide', () => {
- const result = parser({ content: '', channel, date })
- expect(result).toMatchObject([])
-})
+const { parser, url } = require('./nzxmltv.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')
+
+dayjs.extend(customParseFormat)
+dayjs.extend(utc)
+
+const date = dayjs.utc('2023-11-21').startOf('d')
+const channel = {
+ site_id: 'xmltv/guide#1',
+ xmltv_id: 'TVNZ1.nz'
+}
+
+it('can generate valid url', () => {
+ expect(url({ channel })).toBe('https://nzxmltv.com/xmltv/guide.xml')
+})
+
+it('can parse response', () => {
+ const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.xml'))
+ const results = parser({ content, channel, date })
+
+ expect(results[0]).toMatchObject({
+ start: '2023-11-21T10:30:00.000Z',
+ stop: '2023-11-21T11:25:00.000Z',
+ title: 'Sunday',
+ description:
+ 'On Sunday, an unmissable show with stories about divorce, weight loss, and the incomprehensible devastation of Gaza.',
+ season: 2023,
+ episode: 37,
+ icon: 'https://www.thetvdb.com/banners/posters/5dbebff2986f2.jpg'
+ })
+})
+
+it('can handle empty guide', () => {
+ const result = parser({ content: '', channel, date })
+ expect(result).toMatchObject([])
+})
diff --git a/sites/ontvtonight.com/ontvtonight.com.config.js b/sites/ontvtonight.com/ontvtonight.com.config.js
index e41f6ada..20b6efd0 100644
--- a/sites/ontvtonight.com/ontvtonight.com.config.js
+++ b/sites/ontvtonight.com/ontvtonight.com.config.js
@@ -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$/)
diff --git a/sites/orangetv.orange.es/orangetv.orange.es.config.js b/sites/orangetv.orange.es/orangetv.orange.es.config.js
index 34742993..690e1e80 100644
--- a/sites/orangetv.orange.es/orangetv.orange.es.config.js
+++ b/sites/orangetv.orange.es/orangetv.orange.es.config.js
@@ -1,113 +1,108 @@
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-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_IMAGE_ENDPOINT = 'https://pc.orangetv.orange.es/pc/api/rtv/v1/images'
-
-module.exports = {
- site: 'orangetv.orange.es',
- days: 2,
- request: {
- cache: {
- ttl: 60 * 60 * 1000 // 1 hour
- }
- },
- url({ date }) {
- return `${API_PROGRAM_ENDPOINT}/${date.format('YYYYMMDD')}_8h_1.json`
- },
- async parser({ content, channel, date }) {
- let programs = []
- let items = parseItems(content, channel)
- 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`,
- ),
- ]
-
- await Promise.allSettled(promises)
- .then(results => {
- results.forEach(r => {
- 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)
- }
- })
- })
- .catch(console.error)
-
- items.forEach(item => {
- programs.push({
- title: item.name,
- description: item.description,
- category: parseGenres(item),
- season: item.seriesSeason || null,
- episode: item.episodeId || null,
- icon: parseIcon(item),
- start: dayjs.utc(item.startDate) || null,
- stop: dayjs.utc(item.endDate) || null,
- })
- })
-
- return programs
- },
- async channels() {
- const axios = require('axios')
- const data = await axios
- .get(API_CHANNEL_ENDPOINT)
- .then(r => r.data)
- .catch(console.log)
- return data.response.map(item => {
- return {
- lang: 'es',
- name: item.name,
- site_id: item.externalChannelId
- }
- })
- }
-}
-
-function parseIcon(item){
-
- 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}`;
- }
- }
-
- return ''
-}
-
-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 : []
-
- if (!Array.isArray(json)) {
- return [];
- }
-
- const channelData = json.find(i => i.channelExternalId == channel.site_id);
-
- if(!channelData)
- return [];
-
- return channelData.programs;
-}
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+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_IMAGE_ENDPOINT = 'https://pc.orangetv.orange.es/pc/api/rtv/v1/images'
+
+module.exports = {
+ site: 'orangetv.orange.es',
+ days: 2,
+ request: {
+ cache: {
+ ttl: 60 * 60 * 1000 // 1 hour
+ }
+ },
+ url({ date }) {
+ return `${API_PROGRAM_ENDPOINT}/${date.format('YYYYMMDD')}_8h_1.json`
+ },
+ async parser({ content, channel, date }) {
+ let programs = []
+ let items = parseItems(content, channel)
+ 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`)
+ ]
+
+ await Promise.allSettled(promises)
+ .then(results => {
+ results.forEach(r => {
+ 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)
+ }
+ })
+ })
+ .catch(console.error)
+
+ items.forEach(item => {
+ programs.push({
+ title: item.name,
+ description: item.description,
+ category: parseGenres(item),
+ season: item.seriesSeason || null,
+ episode: item.episodeId || null,
+ icon: parseIcon(item),
+ start: dayjs.utc(item.startDate) || null,
+ stop: dayjs.utc(item.endDate) || null
+ })
+ })
+
+ return programs
+ },
+ async channels() {
+ const axios = require('axios')
+ const data = await axios
+ .get(API_CHANNEL_ENDPOINT)
+ .then(r => r.data)
+ .catch(console.log)
+ return data.response.map(item => {
+ return {
+ lang: 'es',
+ name: item.name,
+ site_id: item.externalChannelId
+ }
+ })
+ }
+}
+
+function parseIcon(item) {
+ 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}`
+ }
+ }
+
+ return ''
+}
+
+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 : []
+
+ if (!Array.isArray(json)) {
+ return []
+ }
+
+ const channelData = json.find(i => i.channelExternalId == channel.site_id)
+
+ if (!channelData) return []
+
+ return channelData.programs
+}
diff --git a/sites/orangetv.orange.es/orangetv.orange.es.test.js b/sites/orangetv.orange.es/orangetv.orange.es.test.js
index 3738523c..c9decd52 100644
--- a/sites/orangetv.orange.es/orangetv.orange.es.test.js
+++ b/sites/orangetv.orange.es/orangetv.orange.es.test.js
@@ -1,49 +1,54 @@
-const { parser, url } = require('./orangetv.orange.es.config.js')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-const customParseFormat = require('dayjs/plugin/customParseFormat')
-dayjs.extend(customParseFormat)
-dayjs.extend(utc)
-const path = require('path')
-const fs = require('fs')
-
-const date = dayjs.utc('2024-12-01', 'YYYY-MM-DD').startOf('d')
-const channel = {
- site_id: '1010',
- xmltv_id: 'La1.es'
-}
-
-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`)
-})
-
-it('can parse response', async () => {
- 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()
- p.stop = p.stop.toJSON()
- return p
- })
-
- expect(results.length).toBe(4)
-
- 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.',
- title: 'Loco de amor'
- })
-})
-
-it('can handle empty guide', () => {
- const result = parser({
- date,
- channel,
- content: '{}'
- })
- expect(result).toMatchObject({})
-})
+const { parser, url } = require('./orangetv.orange.es.config.js')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+const customParseFormat = require('dayjs/plugin/customParseFormat')
+dayjs.extend(customParseFormat)
+dayjs.extend(utc)
+const path = require('path')
+const fs = require('fs')
+
+const date = dayjs.utc('2024-12-01', 'YYYY-MM-DD').startOf('d')
+const channel = {
+ site_id: '1010',
+ xmltv_id: 'La1.es'
+}
+
+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`
+ )
+})
+
+it('can parse response', async () => {
+ 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()
+ p.stop = p.stop.toJSON()
+ return p
+ })
+
+ expect(results.length).toBe(4)
+
+ 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.',
+ title: 'Loco de amor'
+ })
+})
+
+it('can handle empty guide', () => {
+ const result = parser({
+ date,
+ channel,
+ content: '{}'
+ })
+ expect(result).toMatchObject({})
+})
diff --git a/sites/osn.com/osn.com.config.js b/sites/osn.com/osn.com.config.js
index d85efae5..ece2bf72 100644
--- a/sites/osn.com/osn.com.config.js
+++ b/sites/osn.com/osn.com.config.js
@@ -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)
diff --git a/sites/osn.com/osn.com.test.js b/sites/osn.com/osn.com.test.js
index 144a0b5c..fb2fcfbc 100644
--- a/sites/osn.com/osn.com.test.js
+++ b/sites/osn.com/osn.com.test.js
@@ -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'
})
})
diff --git a/sites/pbsguam.org/pbsguam.org.config.js b/sites/pbsguam.org/pbsguam.org.config.js
index 8be09c60..504778df 100644
--- a/sites/pbsguam.org/pbsguam.org.config.js
+++ b/sites/pbsguam.org/pbsguam.org.config.js
@@ -27,7 +27,7 @@ function parseItems(content, date) {
let data
try {
data = JSON.parse(json)
- } catch (error) {
+ } catch {
return []
}
diff --git a/sites/pickx.be/pickx.be.config.js b/sites/pickx.be/pickx.be.config.js
index 38d1ac21..c6a507d1 100644
--- a/sites/pickx.be/pickx.be.config.js
+++ b/sites/pickx.be/pickx.be.config.js
@@ -1,174 +1,172 @@
-const axios = require('axios')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-
-let apiVersion
-
-dayjs.extend(utc)
-
-module.exports = {
- site: 'pickx.be',
- days: 2,
- setApiVersion: function (version) {
- apiVersion = version
- },
- getApiVersion: function () {
- return apiVersion
- },
- fetchApiVersion: fetchApiVersion,
- url: async function ({ channel, date }) {
- if (!apiVersion) {
- await fetchApiVersion()
- }
- return `https://px-epg.azureedge.net/airings/${apiVersion}/${date.format(
- 'YYYY-MM-DD'
- )}/channel/${channel.site_id}?timezone=Europe%2FBrussels`
- },
- request: {
- headers: {
- Origin: 'https://www.pickx.be',
- Referer: 'https://www.pickx.be/'
- }
- },
- parser({ channel, content }) {
- const programs = []
- if (content) {
- const items = JSON.parse(content)
- items.forEach(item => {
- programs.push({
- title: item.program.title,
- sub_title: item.program.episodeTitle,
- description: item.program.description,
- category: item.program.translatedCategory?.[channel.lang]
- ? item.program.translatedCategory[channel.lang]
- : item.program.category.split('.')[1],
- image: item.program.posterFileName
- ? `https://experience-cache.proximustv.be/posterserver/poster/EPG/w-166_h-110/${item.program.posterFileName}`
- : null,
- season: item.program.seasonNumber,
- episode: item.program.episodeNumber,
- actors: item.program.actors,
- director: item.program.director ? [item.program.director] : null,
- start: dayjs.utc(item.programScheduleStart),
- stop: dayjs.utc(item.programScheduleEnd)
- })
- })
- }
-
- return programs
- },
- async channels({ lang = '' }) {
- const query = {
- operationName: 'getChannels',
- variables: {
- language: lang,
- queryParams: {},
- id: '0',
- params: {
- shouldReadFromCache: true
- }
- },
- query: `query getChannels($language: String!, $queryParams: ChannelQueryParams, $id: String, $params: ChannelParams) {
- channels(language: $language, queryParams: $queryParams, id: $id, params: $params) {
- id
- channelReferenceNumber
- name
- callLetter
- number
- logo {
- key
- url
- __typename
- }
- language
- hd
- radio
- replayable
- ottReplayable
- playable
- ottPlayable
- recordable
- subscribed
- cloudRecordable
- catchUpWindowInHours
- isOttNPVREnabled
- ottNPVRStart
- subscription {
- channelRef
- subscribed
- upselling {
- upsellable
- packages
- __typename
- }
- __typename
- }
- packages
- __typename
- }
- }`
- }
- const result = await axios
- .post('https://api.proximusmwc.be/tiams/v3/graphql', query)
- .then(r => r.data)
- .catch(console.error)
-
- return (
- result?.data?.channels
- .filter(
- channel =>
- !channel.radio && (!lang || channel.language === (lang === 'de' ? 'ger' : lang))
- )
- .map(channel => {
- return {
- lang: channel.language === 'ger' ? 'de' : channel.language,
- site_id: channel.id,
- name: channel.name
- }
- }) || []
- )
- }
-}
-function fetchApiVersion() {
- return new Promise(async (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()
- } else {
- console.error(`Failed to fetch API version. Status: ${response.status}`)
- reject(`Failed to fetch API version. Status: ${response.status}`)
- }
- } catch (error) {
- console.error('Error during fetchApiVersion:', error)
- reject(error)
- }
- })
-}
+const axios = require('axios')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+
+let apiVersion
+
+dayjs.extend(utc)
+
+module.exports = {
+ site: 'pickx.be',
+ days: 2,
+ setApiVersion: function (version) {
+ apiVersion = version
+ },
+ getApiVersion: function () {
+ return apiVersion
+ },
+ fetchApiVersion: fetchApiVersion,
+ url: async function ({ channel, date }) {
+ if (!apiVersion) {
+ await fetchApiVersion()
+ }
+ return `https://px-epg.azureedge.net/airings/${apiVersion}/${date.format(
+ 'YYYY-MM-DD'
+ )}/channel/${channel.site_id}?timezone=Europe%2FBrussels`
+ },
+ request: {
+ headers: {
+ Origin: 'https://www.pickx.be',
+ Referer: 'https://www.pickx.be/'
+ }
+ },
+ parser({ channel, content }) {
+ const programs = []
+ if (content) {
+ const items = JSON.parse(content)
+ items.forEach(item => {
+ programs.push({
+ title: item.program.title,
+ sub_title: item.program.episodeTitle,
+ description: item.program.description,
+ category: item.program.translatedCategory?.[channel.lang]
+ ? item.program.translatedCategory[channel.lang]
+ : item.program.category.split('.')[1],
+ image: item.program.posterFileName
+ ? `https://experience-cache.proximustv.be/posterserver/poster/EPG/w-166_h-110/${item.program.posterFileName}`
+ : null,
+ season: item.program.seasonNumber,
+ episode: item.program.episodeNumber,
+ actors: item.program.actors,
+ director: item.program.director ? [item.program.director] : null,
+ start: dayjs.utc(item.programScheduleStart),
+ stop: dayjs.utc(item.programScheduleEnd)
+ })
+ })
+ }
+
+ return programs
+ },
+ async channels({ lang = '' }) {
+ const query = {
+ operationName: 'getChannels',
+ variables: {
+ language: lang,
+ queryParams: {},
+ id: '0',
+ params: {
+ shouldReadFromCache: true
+ }
+ },
+ query: `query getChannels($language: String!, $queryParams: ChannelQueryParams, $id: String, $params: ChannelParams) {
+ channels(language: $language, queryParams: $queryParams, id: $id, params: $params) {
+ id
+ channelReferenceNumber
+ name
+ callLetter
+ number
+ logo {
+ key
+ url
+ __typename
+ }
+ language
+ hd
+ radio
+ replayable
+ ottReplayable
+ playable
+ ottPlayable
+ recordable
+ subscribed
+ cloudRecordable
+ catchUpWindowInHours
+ isOttNPVREnabled
+ ottNPVRStart
+ subscription {
+ channelRef
+ subscribed
+ upselling {
+ upsellable
+ packages
+ __typename
+ }
+ __typename
+ }
+ packages
+ __typename
+ }
+ }`
+ }
+ const result = await axios
+ .post('https://api.proximusmwc.be/tiams/v3/graphql', query)
+ .then(r => r.data)
+ .catch(console.error)
+
+ return (
+ result?.data?.channels
+ .filter(
+ channel =>
+ !channel.radio && (!lang || channel.language === (lang === 'de' ? 'ger' : lang))
+ )
+ .map(channel => {
+ return {
+ lang: channel.language === 'ger' ? 'de' : channel.language,
+ site_id: channel.id,
+ name: channel.name
+ }
+ }) || []
+ )
+ }
+}
+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 {
+ if (response.status === 200) {
+ apiVersion = response.data.version
+ resolve()
+ } else {
+ console.error(`Failed to fetch API version. Status: ${response.status}`)
+ reject(`Failed to fetch API version. Status: ${response.status}`)
+ }
+ } catch (error) {
+ console.error('Error during fetchApiVersion:', error)
+ reject(error)
+ }
+ })
+}
diff --git a/sites/pickx.be/pickx.be.test.js b/sites/pickx.be/pickx.be.test.js
index aa89f09c..05a37ae0 100644
--- a/sites/pickx.be/pickx.be.test.js
+++ b/sites/pickx.be/pickx.be.test.js
@@ -1,76 +1,69 @@
-jest.mock('./pickx.be.config.js', () => {
- const originalModule = jest.requireActual('./pickx.be.config.js')
- return {
- ...originalModule,
- fetchApiVersion: jest.fn(() => Promise.resolve())
- }
-})
-
-const {
- parser,
- url,
- request,
- fetchApiVersion,
- setApiVersion,
- getApiVersion
-} = require('./pickx.be.config.js')
-
-const fs = require('fs')
-const path = require('path')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-
-dayjs.extend(utc)
-
-const date = dayjs.utc('2023-12-13').startOf('d')
-const channel = {
- lang: 'fr',
- site_id: 'UID0118',
- xmltv_id: 'Vedia.be'
-}
-
-beforeEach(() => {
- setApiVersion('mockedApiVersion')
-})
-
-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`
- )
-})
-
-it('can generate valid request headers', () => {
- expect(request.headers).toMatchObject({
- Origin: 'https://www.pickx.be',
- Referer: 'https://www.pickx.be/'
- })
-})
-
-it('can parse response', () => {
- const content = fs.readFileSync(path.resolve(__dirname, '__data__/data.json'))
- const result = parser({ content, channel, date }).map(p => {
- p.start = p.start.toJSON()
- p.stop = p.stop.toJSON()
- return p
- })
-
- expect(result[0]).toMatchObject({
- start: '2023-12-12T23:55:00.000Z',
- stop: '2023-12-13T00:15:00.000Z',
- title: 'Le 22h30',
- description: 'Le journal de vivre ici.',
- category: 'Info',
- image:
- 'https://experience-cache.proximustv.be/posterserver/poster/EPG/w-166_h-110/250_250_4B990CC58066A7B2A660AFA0BDDE5C41.jpg'
- })
-})
-
-it('can handle empty guide', () => {
- const result = parser({
- date,
- channel,
- content: ''
- })
- expect(result).toMatchObject([])
-})
+jest.mock('./pickx.be.config.js', () => {
+ const originalModule = jest.requireActual('./pickx.be.config.js')
+ return {
+ ...originalModule,
+ fetchApiVersion: jest.fn(() => Promise.resolve())
+ }
+})
+
+const { parser, url, request, setApiVersion } = require('./pickx.be.config.js')
+
+const fs = require('fs')
+const path = require('path')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+
+dayjs.extend(utc)
+
+const date = dayjs.utc('2023-12-13').startOf('d')
+const channel = {
+ lang: 'fr',
+ site_id: 'UID0118',
+ xmltv_id: 'Vedia.be'
+}
+
+beforeEach(() => {
+ setApiVersion('mockedApiVersion')
+})
+
+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'
+ )
+})
+
+it('can generate valid request headers', () => {
+ expect(request.headers).toMatchObject({
+ Origin: 'https://www.pickx.be',
+ Referer: 'https://www.pickx.be/'
+ })
+})
+
+it('can parse response', () => {
+ const content = fs.readFileSync(path.resolve(__dirname, '__data__/data.json'))
+ const result = parser({ content, channel, date }).map(p => {
+ p.start = p.start.toJSON()
+ p.stop = p.stop.toJSON()
+ return p
+ })
+
+ expect(result[0]).toMatchObject({
+ start: '2023-12-12T23:55:00.000Z',
+ stop: '2023-12-13T00:15:00.000Z',
+ title: 'Le 22h30',
+ description: 'Le journal de vivre ici.',
+ category: 'Info',
+ image:
+ 'https://experience-cache.proximustv.be/posterserver/poster/EPG/w-166_h-110/250_250_4B990CC58066A7B2A660AFA0BDDE5C41.jpg'
+ })
+})
+
+it('can handle empty guide', () => {
+ const result = parser({
+ date,
+ channel,
+ content: ''
+ })
+ expect(result).toMatchObject([])
+})
diff --git a/sites/player.ee.co.uk/player.ee.co.uk.config.js b/sites/player.ee.co.uk/player.ee.co.uk.config.js
index f8a9411e..6914b017 100644
--- a/sites/player.ee.co.uk/player.ee.co.uk.config.js
+++ b/sites/player.ee.co.uk/player.ee.co.uk.config.js
@@ -1,102 +1,104 @@
-const axios = require('axios')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-
-dayjs.extend(utc)
-
-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`
- },
- request: {
- headers: {
- Referer: 'https://player.ee.co.uk/'
- }
- },
- async parser({ content, channel, date }) {
- const programs = []
- if (content) {
- const schedule = JSON.parse(content)
- // fetch next 12 hours schedule
- const { url, request } = module.exports
- const nextSchedule = await axios
- .get(url({ channel, date, hour: 12 }), { headers: request.headers })
- .then(response => response.data)
- .catch(console.error)
-
- if (schedule?.items) {
- // merge schedules
- if (nextSchedule?.items) {
- schedule.items.push(...nextSchedule.items)
- }
- schedule.items.forEach(item => {
- let season, episode
- const start = dayjs.utc(item.publishedStartTime)
- const stop = start.add(item.publishedDuration, 's')
- const description = item.synopsis
- if (description) {
- const matches = description.trim().match(/\(?S(\d+)[\/\s]Ep(\d+)\)?/)
- if (matches) {
- if (matches[1]) {
- season = parseInt(matches[1])
- }
- if (matches[2]) {
- episode = parseInt(matches[2])
- }
- }
- }
- programs.push({
- title: item.title,
- description,
- season,
- episode,
- start,
- stop
- })
- })
- }
- }
-
- return programs
- },
- async channels() {
- const token =
- 'eyJkaXNjb3ZlcnlVc2VyR3JvdXBzIjpbIkFMTFVTRVJTIiwiYWxsIiwiaHR0cDovL3JlZmRhd' +
- 'GEueW91dmlldy5jb20vbXBlZzdjcy9Zb3VWaWV3QXBwbGljYXRpb25QbGF5ZXJDUy8yMDIxLT' +
- 'A5LTEwI2FuZHJvaWRfcnVudGltZS1wcm9maWxlMSIsInRhZzpidC5jb20sMjAxOC0wNy0xMTp' +
- '1c2VyZ3JvdXAjR0JSLWJ0X25vd1RWX211bHRpY2FzdCIsInRhZzpidC5jb20sMjAyMS0xMC0y' +
- 'NTp1c2VyZ3JvdXAjR0JSLWJ0X2V1cm9zcG9ydCJdLCJyZWdpb25zIjpbIkFMTFJFR0lPTlMiL' +
- 'CJHQlIiLCJHQlItRU5HIiwiR0JSLUVORy1sb25kb24iLCJhbGwiXSwic3Vic2V0IjoiMy41Lj' +
- 'EvYW5kcm9pZF9ydW50aW1lLXByb2ZpbGUxL0JST0FEQ0FTVF9JUC9HQlItYnRfYnJvYWRiYW5' +
- 'kIiwic3Vic2V0cyI6WyIvLy8iLCIvL0JST0FEQ0FTVF9JUC8iLCIzLjUvLy8iXX0='
- const extensions = [
- 'LinearCategoriesExtension',
- 'LogicalChannelNumberExtension',
- 'BTSubscriptionCodesExtension'
- ]
- const result = await axios
- .get(`https://api.youview.tv/metadata/linear/v2/linear-services`, {
- params: {
- contentTargetingToken: token,
- extensions: extensions.join(',')
- },
- headers: module.exports.request.headers
- })
- .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
- }
- }) || []
- }
-}
+const axios = require('axios')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+
+dayjs.extend(utc)
+
+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`
+ },
+ request: {
+ headers: {
+ Referer: 'https://player.ee.co.uk/'
+ }
+ },
+ async parser({ content, channel, date }) {
+ const programs = []
+ if (content) {
+ const schedule = JSON.parse(content)
+ // fetch next 12 hours schedule
+ const { url, request } = module.exports
+ const nextSchedule = await axios
+ .get(url({ channel, date, hour: 12 }), { headers: request.headers })
+ .then(response => response.data)
+ .catch(console.error)
+
+ if (schedule?.items) {
+ // merge schedules
+ if (nextSchedule?.items) {
+ schedule.items.push(...nextSchedule.items)
+ }
+ schedule.items.forEach(item => {
+ let season, episode
+ const start = dayjs.utc(item.publishedStartTime)
+ const stop = start.add(item.publishedDuration, 's')
+ const description = item.synopsis
+ if (description) {
+ const matches = description.trim().match(/\(?S(\d+)[/\s]Ep(\d+)\)?/)
+ if (matches) {
+ if (matches[1]) {
+ season = parseInt(matches[1])
+ }
+ if (matches[2]) {
+ episode = parseInt(matches[2])
+ }
+ }
+ }
+ programs.push({
+ title: item.title,
+ description,
+ season,
+ episode,
+ start,
+ stop
+ })
+ })
+ }
+ }
+
+ return programs
+ },
+ async channels() {
+ const token =
+ 'eyJkaXNjb3ZlcnlVc2VyR3JvdXBzIjpbIkFMTFVTRVJTIiwiYWxsIiwiaHR0cDovL3JlZmRhd' +
+ 'GEueW91dmlldy5jb20vbXBlZzdjcy9Zb3VWaWV3QXBwbGljYXRpb25QbGF5ZXJDUy8yMDIxLT' +
+ 'A5LTEwI2FuZHJvaWRfcnVudGltZS1wcm9maWxlMSIsInRhZzpidC5jb20sMjAxOC0wNy0xMTp' +
+ '1c2VyZ3JvdXAjR0JSLWJ0X25vd1RWX211bHRpY2FzdCIsInRhZzpidC5jb20sMjAyMS0xMC0y' +
+ 'NTp1c2VyZ3JvdXAjR0JSLWJ0X2V1cm9zcG9ydCJdLCJyZWdpb25zIjpbIkFMTFJFR0lPTlMiL' +
+ 'CJHQlIiLCJHQlItRU5HIiwiR0JSLUVORy1sb25kb24iLCJhbGwiXSwic3Vic2V0IjoiMy41Lj' +
+ 'EvYW5kcm9pZF9ydW50aW1lLXByb2ZpbGUxL0JST0FEQ0FTVF9JUC9HQlItYnRfYnJvYWRiYW5' +
+ 'kIiwic3Vic2V0cyI6WyIvLy8iLCIvL0JST0FEQ0FTVF9JUC8iLCIzLjUvLy8iXX0='
+ const extensions = [
+ 'LinearCategoriesExtension',
+ 'LogicalChannelNumberExtension',
+ 'BTSubscriptionCodesExtension'
+ ]
+ const result = await axios
+ .get('https://api.youview.tv/metadata/linear/v2/linear-services', {
+ params: {
+ contentTargetingToken: token,
+ extensions: extensions.join(',')
+ },
+ headers: module.exports.request.headers
+ })
+ .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
+ }
+ }) || []
+ )
+ }
+}
diff --git a/sites/player.ee.co.uk/player.ee.co.uk.test.js b/sites/player.ee.co.uk/player.ee.co.uk.test.js
index 19c90cda..30424e74 100644
--- a/sites/player.ee.co.uk/player.ee.co.uk.test.js
+++ b/sites/player.ee.co.uk/player.ee.co.uk.test.js
@@ -1,72 +1,74 @@
-const { parser, url } = require('./player.ee.co.uk.config.js')
-const fs = require('fs')
-const path = require('path')
-const axios = require('axios')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-
-dayjs.extend(utc)
-
-jest.mock('axios')
-
-const date = dayjs.utc('2023-12-13').startOf('d')
-const channel = {
- site_id: 'dvb://233a..6d60',
- 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') {
- return Promise.resolve({
- data: JSON.parse(fs.readFileSync(path.resolve(__dirname, '__data__/data1.json')))
- })
- }
-
- return Promise.resolve({ data: '' })
-})
-
-it('can generate valid url', () => {
- expect(url({ date, channel })).toBe(
- 'https://api.youview.tv/metadata/linear/v2/schedule/by-servicelocator?serviceLocator=dvb%3A%2F%2F233a..6d60&interval=2023-12-13T00Z/PT12H'
- )
-})
-
-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
- })
-
- expect(result).toMatchObject([
- {
- title: 'Bargain Mansions',
- description:
- 'Tamara and her dad help a recent widow who loves to cook for her family design her dream kitchen, perfect for entertaining and large gatherings. S4/Ep1',
- season: 4,
- episode: 1,
- start: '2023-12-13T13:00:00.000Z',
- stop: '2023-12-13T14:00:00.000Z'
- },
- {
- title: 'Flip Or Flop',
- description:
- 'Tarek and Christina are contacted by a cash strapped flipper who needs to unload a project house. S2/Ep2',
- season: 2,
- episode: 2,
- start: '2023-12-13T14:00:00.000Z',
- stop: '2023-12-13T14:30:00.000Z'
- }
- ])
-})
-
-it('can handle empty guide', async () => {
- const result = await parser({
- channel,
- date,
- content: ''
- })
- expect(result).toMatchObject([])
-})
+const { parser, url } = require('./player.ee.co.uk.config.js')
+const fs = require('fs')
+const path = require('path')
+const axios = require('axios')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+
+dayjs.extend(utc)
+
+jest.mock('axios')
+
+const date = dayjs.utc('2023-12-13').startOf('d')
+const channel = {
+ site_id: 'dvb://233a..6d60',
+ xmltv_id: 'HGTV.uk'
+}
+
+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')))
+ })
+ }
+
+ return Promise.resolve({ data: '' })
+})
+
+it('can generate valid url', () => {
+ expect(url({ date, channel })).toBe(
+ 'https://api.youview.tv/metadata/linear/v2/schedule/by-servicelocator?serviceLocator=dvb%3A%2F%2F233a..6d60&interval=2023-12-13T00Z/PT12H'
+ )
+})
+
+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
+ })
+
+ expect(result).toMatchObject([
+ {
+ title: 'Bargain Mansions',
+ description:
+ 'Tamara and her dad help a recent widow who loves to cook for her family design her dream kitchen, perfect for entertaining and large gatherings. S4/Ep1',
+ season: 4,
+ episode: 1,
+ start: '2023-12-13T13:00:00.000Z',
+ stop: '2023-12-13T14:00:00.000Z'
+ },
+ {
+ title: 'Flip Or Flop',
+ description:
+ 'Tarek and Christina are contacted by a cash strapped flipper who needs to unload a project house. S2/Ep2',
+ season: 2,
+ episode: 2,
+ start: '2023-12-13T14:00:00.000Z',
+ stop: '2023-12-13T14:30:00.000Z'
+ }
+ ])
+})
+
+it('can handle empty guide', async () => {
+ const result = await parser({
+ channel,
+ date,
+ content: ''
+ })
+ expect(result).toMatchObject([])
+})
diff --git a/sites/playtv.unifi.com.my/playtv.unifi.com.my.config.js b/sites/playtv.unifi.com.my/playtv.unifi.com.my.config.js
index 787d235e..d426eeb5 100644
--- a/sites/playtv.unifi.com.my/playtv.unifi.com.my.config.js
+++ b/sites/playtv.unifi.com.my/playtv.unifi.com.my.config.js
@@ -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 []
}
}
diff --git a/sites/programetv.ro/programetv.ro.config.js b/sites/programetv.ro/programetv.ro.config.js
index f55eea31..4a14f0e5 100644
--- a/sites/programetv.ro/programetv.ro.config.js
+++ b/sites/programetv.ro/programetv.ro.config.js
@@ -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)
diff --git a/sites/programme-tv.net/programme-tv.net.config.js b/sites/programme-tv.net/programme-tv.net.config.js
index 21810bef..4d69ed6e 100644
--- a/sites/programme-tv.net/programme-tv.net.config.js
+++ b/sites/programme-tv.net/programme-tv.net.config.js
@@ -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',
diff --git a/sites/programme-tv.vini.pf/programme-tv.vini.pf.config.js b/sites/programme-tv.vini.pf/programme-tv.vini.pf.config.js
index 6d17bb8b..1e697583 100644
--- a/sites/programme-tv.vini.pf/programme-tv.vini.pf.config.js
+++ b/sites/programme-tv.vini.pf/programme-tv.vini.pf.config.js
@@ -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',
diff --git a/sites/programme.tvb.com/programme.tvb.com.config.js b/sites/programme.tvb.com/programme.tvb.com.config.js
index c487257e..87c3580e 100644
--- a/sites/programme.tvb.com/programme.tvb.com.config.js
+++ b/sites/programme.tvb.com/programme.tvb.com.config.js
@@ -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)) {
diff --git a/sites/programme.tvb.com/programme.tvb.com.test.js b/sites/programme.tvb.com/programme.tvb.com.test.js
index 8bcf56f7..558f4600 100644
--- a/sites/programme.tvb.com/programme.tvb.com.test.js
+++ b/sites/programme.tvb.com/programme.tvb.com.test.js
@@ -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:
- '文鼎從淑梅手上救走大聖爺兒子,大聖爺還恩於歡喜,答允支持九指強。崇聯社定下選舉日子,恰巧是韋傑出獄之日,頭目們顧念舊日恩義,紛紛轉投浩洋。浩洋帶亞希逛傢俬店,憧憬二人未來。亞希向家強承認愛上浩洋,要求退出臥底任務。作榮與歡喜暗中會面,將國際犯罪組織「永恆幫」情報交給他。阿火遭家強出賣,到沐足店搶錢。家強逮住阿火,惟被合星誤會而受拘捕。家強把正植遺下的頸鏈和學生證交還,合星意識到家強已知悉正植身世。',
+ '文鼎從淑梅手上救走大聖爺兒子,大聖爺還恩於歡喜,答允支持九指強。崇聯社定下選舉日子,恰巧是韋傑出獄之日,頭目們顧念舊日恩義,紛紛轉投浩洋。浩洋帶亞希逛傢俬店,憧憬二人未來。亞希向家強承認愛上浩洋,要求退出臥底任務。作榮與歡喜暗中會面,將國際犯罪組織「永恆幫」情報交給他。阿火遭家強出賣,到沐足店搶錢。家強逮住阿火,惟被合星誤會而受拘捕。家強把正植遺下的頸鏈和學生證交還,合星意識到家強已知悉正植身世。'
})
})
diff --git a/sites/programtv.onet.pl/programtv.onet.pl.config.js b/sites/programtv.onet.pl/programtv.onet.pl.config.js
index 62e4c447..64ff12df 100644
--- a/sites/programtv.onet.pl/programtv.onet.pl.config.js
+++ b/sites/programtv.onet.pl/programtv.onet.pl.config.js
@@ -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',
diff --git a/sites/rev.bs/rev.bs.config.js b/sites/rev.bs/rev.bs.config.js
index 67dcd7bd..c956fd1c 100644
--- a/sites/rev.bs/rev.bs.config.js
+++ b/sites/rev.bs/rev.bs.config.js
@@ -58,7 +58,7 @@ function parseItems(content, channel) {
let data
try {
data = JSON.parse(content)
- } catch (error) {
+ } catch {
return []
}
diff --git a/sites/rotana.net/rotana.net.config.js b/sites/rotana.net/rotana.net.config.js
index 9eb0b930..f38abbff 100644
--- a/sites/rotana.net/rotana.net.config.js
+++ b/sites/rotana.net/rotana.net.config.js
@@ -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()}`
})
}
}
diff --git a/sites/rotana.net/rotana.net.test.js b/sites/rotana.net/rotana.net.test.js
index 17803fdd..ef49b147 100644
--- a/sites/rotana.net/rotana.net.test.js
+++ b/sites/rotana.net/rotana.net.test.js
@@ -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: 'فيلم'
})
})
diff --git a/sites/rtb.gov.bn/rtb.gov.bn.config.js b/sites/rtb.gov.bn/rtb.gov.bn.config.js
index 3af095de..c560f224 100644
--- a/sites/rtb.gov.bn/rtb.gov.bn.config.js
+++ b/sites/rtb.gov.bn/rtb.gov.bn.config.js
@@ -53,7 +53,7 @@ async function parseItems(buffer) {
let data
try {
data = await pdf(buffer)
- } catch (err) {
+ } catch {
return []
}
diff --git a/sites/rtp.pt/rtp.pt.config.js b/sites/rtp.pt/rtp.pt.config.js
index a2f1e008..0108e255 100644
--- a/sites/rtp.pt/rtp.pt.config.js
+++ b/sites/rtp.pt/rtp.pt.config.js
@@ -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')
diff --git a/sites/s.mxtv.jp/s.mxtv.jp.config.js b/sites/s.mxtv.jp/s.mxtv.jp.config.js
index e676d826..d85d3c06 100644
--- a/sites/s.mxtv.jp/s.mxtv.jp.config.js
+++ b/sites/s.mxtv.jp/s.mxtv.jp.config.js
@@ -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) || []
}
diff --git a/sites/s.mxtv.jp/s.mxtv.jp.test.js b/sites/s.mxtv.jp/s.mxtv.jp.test.js
index f2219d31..b6891abc 100644
--- a/sites/s.mxtv.jp/s.mxtv.jp.test.js
+++ b/sites/s.mxtv.jp/s.mxtv.jp.test.js
@@ -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 })
diff --git a/sites/sat.tv/sat.tv.config.js b/sites/sat.tv/sat.tv.config.js
index c0568c5a..8a011a33 100644
--- a/sites/sat.tv/sat.tv.config.js
+++ b/sites/sat.tv/sat.tv.config.js
@@ -114,7 +114,7 @@ module.exports = {
const $ = cheerio.load(data)
$('.main-container-channels-events > .container-channel-events').each((i, el) => {
const name = $(el).find('.channel-title').text().trim()
- const channelId = name.replace(/\s\&\s/gi, ' & ')
+ const channelId = name.replace(/\s&\s/gi, ' & ')
if (!name) return
diff --git a/sites/shahid.mbc.net/shahid.mbc.net.config.js b/sites/shahid.mbc.net/shahid.mbc.net.config.js
index 0e31cbc2..a847c769 100644
--- a/sites/shahid.mbc.net/shahid.mbc.net.config.js
+++ b/sites/shahid.mbc.net/shahid.mbc.net.config.js
@@ -1,74 +1,79 @@
-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)
-
-module.exports = {
- site: 'shahid.mbc.net',
- days: 2,
- url({ channel, date}) {
- return `https://api2.shahid.net/proxy/v2.1/shahid-epg-api/?csvChannelIds=${channel.site_id}&from=${date.format('YYYY-MM-DD')}T00:00:00.000Z&to=${date.format('YYYY-MM-DD')}T23:59:59.999Z&country=SA&language=${channel.lang}&Accept-Language=${channel.lang}`
- },
- parser({ content, channel }) {
- const programs = parseItems(content, channel)
- .map(item => {
- return {
- title: item.title,
- description: item.description,
- session: item.seasonNumber,
- episode: item.episodeNumber,
- start: dayjs.tz(item.actualFrom, 'Asia/Riyadh').toISOString(),
- stop: dayjs.tz(item.actualTo, 'Asia/Riyadh').toISOString()
- }
- })
-
- return programs
- },
- async channels({lang = 'en'}) {
- const axios = require('axios')
- const items = []
- let page = 0
- while (true) {
- const result = await axios
- .get(`https://api2.shahid.net/proxy/v2.1/product/filter?filter=%7B"pageNumber":${page},"pageSize":100,"productType":"LIVESTREAM","productSubType":"LIVE_CHANNEL"%7D&country=SA&language=${lang}&Accept-Language=${lang}`)
- .then(response => response.data)
- .catch(console.error)
- if (result.productList) {
- items.push(...result.productList.products)
- if (result.productList.hasMore) {
- page++
- continue
- }
- }
- break;
- }
- const channels = items.map(channel => {
- return {
- lang,
- site_id: channel.id,
- name: channel.title
- }
- })
-
- return channels
- }
-}
-
-function parseItems(content, channel) {
- const items = []
- content = content ? JSON.parse(content) : []
- if (content.items) {
- content.items.forEach(schedules => {
- if (schedules.channelId == channel.site_id) {
- items.push(...schedules.items)
- return true
- }
- })
- }
-
- return items
-}
+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)
+
+module.exports = {
+ site: 'shahid.mbc.net',
+ days: 2,
+ url({ channel, date }) {
+ return `https://api2.shahid.net/proxy/v2.1/shahid-epg-api/?csvChannelIds=${
+ channel.site_id
+ }&from=${date.format('YYYY-MM-DD')}T00:00:00.000Z&to=${date.format(
+ 'YYYY-MM-DD'
+ )}T23:59:59.999Z&country=SA&language=${channel.lang}&Accept-Language=${channel.lang}`
+ },
+ parser({ content, channel }) {
+ const programs = parseItems(content, channel).map(item => {
+ return {
+ title: item.title,
+ description: item.description,
+ session: item.seasonNumber,
+ episode: item.episodeNumber,
+ start: dayjs.tz(item.actualFrom, 'Asia/Riyadh').toISOString(),
+ stop: dayjs.tz(item.actualTo, 'Asia/Riyadh').toISOString()
+ }
+ })
+
+ return programs
+ },
+ async channels({ lang = 'en' }) {
+ const axios = require('axios')
+ const items = []
+ let page = 0
+ while (true) {
+ const result = await axios
+ .get(
+ `https://api2.shahid.net/proxy/v2.1/product/filter?filter=%7B"pageNumber":${page},"pageSize":100,"productType":"LIVESTREAM","productSubType":"LIVE_CHANNEL"%7D&country=SA&language=${lang}&Accept-Language=${lang}`
+ )
+ .then(response => response.data)
+ .catch(console.error)
+ if (result.productList) {
+ items.push(...result.productList.products)
+ if (result.productList.hasMore) {
+ page++
+ continue
+ }
+ }
+ break
+ }
+ const channels = items.map(channel => {
+ return {
+ lang,
+ site_id: channel.id,
+ name: channel.title
+ }
+ })
+
+ return channels
+ }
+}
+
+function parseItems(content, channel) {
+ const items = []
+ content = content ? JSON.parse(content) : []
+ if (content.items) {
+ content.items.forEach(schedules => {
+ if (schedules.channelId == channel.site_id) {
+ items.push(...schedules.items)
+ return true
+ }
+ })
+ }
+
+ return items
+}
diff --git a/sites/shahid.mbc.net/shahid.mbc.net.test.js b/sites/shahid.mbc.net/shahid.mbc.net.test.js
index 920fff1e..7cc03032 100644
--- a/sites/shahid.mbc.net/shahid.mbc.net.test.js
+++ b/sites/shahid.mbc.net/shahid.mbc.net.test.js
@@ -1,36 +1,40 @@
-const { url, parser } = require('./shahid.mbc.net.config.js')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-
-dayjs.extend(utc)
-
-const date = dayjs.utc('2023-11-11').startOf('d')
-const channel = { site_id: '996520', xmltv_id: 'AlAanTV.ae', lang: 'en' }
-
-it('can generate valid url', () => {
- expect(url({ channel, date })).toBe(
- `https://api2.shahid.net/proxy/v2.1/shahid-epg-api/?csvChannelIds=${channel.site_id}&from=${date.format('YYYY-MM-DD')}T00:00:00.000Z&to=${date.format('YYYY-MM-DD')}T23:59:59.999Z&country=SA&language=${channel.lang}&Accept-Language=${channel.lang}`
- )
-})
-
-it('can parse response', () => {
- const content =
- '{"items":[{"channelId":"996520","items":[{"actualFrom":"2023-11-11T00:00:00.000+00:00","actualTo":"2023-11-11T00:30:00.000+00:00","description":"The presenter reviews the most prominent episodes of news programs produced by the channel\'s team on a weekly basis, which include the most important global updates and developments at all levels.","duration":null,"emptySlot":false,"episodeNumber":194,"from":"2023-11-11T00:00:00.000+00:00","genres":["TV Show"],"productId":null,"productionYear":null,"productPoster":"https://imagesmbc.whatsonindia.com/dasimages/landscape/1920x1080/F968D4A39DB25793E9EED1BDAFBAD2EA8A8F9B30Z.jpg","productSubType":null,"productType":null,"replay":false,"restritectContent":null,"seasonId":null,"seasonNumber":"1","showId":null,"streamInfo":null,"title":"Menassaatona Fi Osboo\'","to":"2023-11-11T00:30:00.000+00:00"}]}]}'
- const result = parser({ content, channel, date })
-
- expect(result).toMatchObject([
- {
- start: '2023-11-10T21:00:00.000Z',
- stop: '2023-11-10T21:30:00.000Z',
- title: 'Menassaatona Fi Osboo\'',
- description:
- 'The presenter reviews the most prominent episodes of news programs produced by the channel\'s team on a weekly basis, which include the most important global updates and developments at all levels.'
- }
- ])
-})
-
-it('can handle empty guide', () => {
- const result = parser({ content: '' })
-
- expect(result).toMatchObject([])
-})
+const { url, parser } = require('./shahid.mbc.net.config.js')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+
+dayjs.extend(utc)
+
+const date = dayjs.utc('2023-11-11').startOf('d')
+const channel = { site_id: '996520', xmltv_id: 'AlAanTV.ae', lang: 'en' }
+
+it('can generate valid url', () => {
+ expect(url({ channel, date })).toBe(
+ `https://api2.shahid.net/proxy/v2.1/shahid-epg-api/?csvChannelIds=${
+ channel.site_id
+ }&from=${date.format('YYYY-MM-DD')}T00:00:00.000Z&to=${date.format(
+ 'YYYY-MM-DD'
+ )}T23:59:59.999Z&country=SA&language=${channel.lang}&Accept-Language=${channel.lang}`
+ )
+})
+
+it('can parse response', () => {
+ const content =
+ '{"items":[{"channelId":"996520","items":[{"actualFrom":"2023-11-11T00:00:00.000+00:00","actualTo":"2023-11-11T00:30:00.000+00:00","description":"The presenter reviews the most prominent episodes of news programs produced by the channel\'s team on a weekly basis, which include the most important global updates and developments at all levels.","duration":null,"emptySlot":false,"episodeNumber":194,"from":"2023-11-11T00:00:00.000+00:00","genres":["TV Show"],"productId":null,"productionYear":null,"productPoster":"https://imagesmbc.whatsonindia.com/dasimages/landscape/1920x1080/F968D4A39DB25793E9EED1BDAFBAD2EA8A8F9B30Z.jpg","productSubType":null,"productType":null,"replay":false,"restritectContent":null,"seasonId":null,"seasonNumber":"1","showId":null,"streamInfo":null,"title":"Menassaatona Fi Osboo\'","to":"2023-11-11T00:30:00.000+00:00"}]}]}'
+ const result = parser({ content, channel, date })
+
+ expect(result).toMatchObject([
+ {
+ start: '2023-11-10T21:00:00.000Z',
+ stop: '2023-11-10T21:30:00.000Z',
+ title: "Menassaatona Fi Osboo'",
+ description:
+ "The presenter reviews the most prominent episodes of news programs produced by the channel's team on a weekly basis, which include the most important global updates and developments at all levels."
+ }
+ ])
+})
+
+it('can handle empty guide', () => {
+ const result = parser({ content: '' })
+
+ expect(result).toMatchObject([])
+})
diff --git a/sites/singtel.com/singtel.com.config.js b/sites/singtel.com/singtel.com.config.js
index 368e4ded..07d3a33e 100644
--- a/sites/singtel.com/singtel.com.config.js
+++ b/sites/singtel.com/singtel.com.config.js
@@ -40,7 +40,7 @@ module.exports = {
const cheerio = require('cheerio')
const data = await axios
- .get(`https://www.singtel.com/personal/products-services/tv/tv-programme-guide`)
+ .get('https://www.singtel.com/personal/products-services/tv/tv-programme-guide')
.then(r => r.data)
.catch(console.log)
@@ -62,7 +62,7 @@ function parseItems(content, channel) {
try {
const data = JSON.parse(content)
return data && data[channel.site_id] ? data[channel.site_id] : []
- } catch (err) {
+ } catch {
return []
}
}
diff --git a/sites/sjonvarp.is/sjonvarp.is.config.js b/sites/sjonvarp.is/sjonvarp.is.config.js
index 0721d0c0..7fd6c33f 100644
--- a/sites/sjonvarp.is/sjonvarp.is.config.js
+++ b/sites/sjonvarp.is/sjonvarp.is.config.js
@@ -44,7 +44,7 @@ module.exports = {
const cheerio = require('cheerio')
const data = await axios
- .get(`https://sjonvarp.is/`)
+ .get('https://sjonvarp.is/')
.then(r => r.data)
.catch(console.log)
diff --git a/sites/sky.com/sky.com.config.js b/sites/sky.com/sky.com.config.js
index cf024178..3183834d 100644
--- a/sites/sky.com/sky.com.config.js
+++ b/sites/sky.com/sky.com.config.js
@@ -12,9 +12,7 @@ module.exports = {
site: 'sky.com',
days: 2,
url({ date, channel }) {
- return `https://awk.epgsky.com/hawk/linear/schedule/${
- date.format('YYYYMMDD')
- }/${
+ return `https://awk.epgsky.com/hawk/linear/schedule/${date.format('YYYYMMDD')}/${
channel.site_id
}`
},
@@ -27,19 +25,18 @@ module.exports = {
.filter(schedule => schedule.sid === channel.site_id)
.forEach(schedule => {
if (Array.isArray(schedule.events)) {
- schedule.events
- .forEach(event => {
- const start = dayjs.utc(event.st * 1000)
- const stop = start.add(event.d, 's')
- programs.push({
- title: event.t,
- description: event.sy,
- season: event.seasonnumber,
- episode: event.episodenumber,
- start,
- stop
- })
+ schedule.events.forEach(event => {
+ const start = dayjs.utc(event.st * 1000)
+ const stop = start.add(event.d, 's')
+ programs.push({
+ title: event.t,
+ description: event.sy,
+ season: event.seasonnumber,
+ episode: event.episodenumber,
+ start,
+ stop
})
+ })
}
})
}
@@ -55,10 +52,12 @@ module.exports = {
if (queue.t === 'r') {
const $ = cheerio.load(res)
const initialData = JSON.parse(decodeURIComponent($('#initialData').text()))
- initialData.state.epgData.regions
- .forEach(region => {
- queues.push({ t: 'c', url: `https://awk.epgsky.com/hawk/linear/services/${region.bouquet}/${region.subBouquet}` })
+ initialData.state.epgData.regions.forEach(region => {
+ queues.push({
+ t: 'c',
+ url: `https://awk.epgsky.com/hawk/linear/services/${region.bouquet}/${region.subBouquet}`
})
+ })
}
// process channels
if (queue.t === 'c') {
diff --git a/sites/sky.com/sky.com.test.js b/sites/sky.com/sky.com.test.js
index c4cce548..4ac89758 100644
--- a/sites/sky.com/sky.com.test.js
+++ b/sites/sky.com/sky.com.test.js
@@ -15,9 +15,7 @@ const channel = {
}
it('can generate valid url', () => {
- expect(url({ channel, date })).toBe(
- 'https://awk.epgsky.com/hawk/linear/schedule/20241214/4086'
- )
+ expect(url({ channel, date })).toBe('https://awk.epgsky.com/hawk/linear/schedule/20241214/4086')
})
it('can parse response', () => {
@@ -34,7 +32,7 @@ it('can parse response', () => {
stop: '2024-12-13T23:00:00.000Z',
title: 'The UnXplained With...',
description:
- 'The Hunt for Jack the Ripper: Jack the Ripper\'s identity has eluded police, historians and armchair detectives for over a century. What do we know about the notorious killer? (S3, ep 21)',
+ "The Hunt for Jack the Ripper: Jack the Ripper's identity has eluded police, historians and armchair detectives for over a century. What do we know about the notorious killer? (S3, ep 21)",
season: 4,
episode: 14
})
diff --git a/sites/skylife.co.kr/skylife.co.kr.test.js b/sites/skylife.co.kr/skylife.co.kr.test.js
index 8ac317ee..c35e85d4 100644
--- a/sites/skylife.co.kr/skylife.co.kr.test.js
+++ b/sites/skylife.co.kr/skylife.co.kr.test.js
@@ -1,4 +1,4 @@
-const { parser, url, request } = require('./skylife.co.kr.config.js')
+const { parser, url } = require('./skylife.co.kr.config.js')
const fs = require('fs')
const path = require('path')
const dayjs = require('dayjs')
diff --git a/sites/skyperfectv.co.jp/__data__/content.html b/sites/skyperfectv.co.jp/__data__/content.html
new file mode 100644
index 00000000..aa569a31
--- /dev/null
+++ b/sites/skyperfectv.co.jp/__data__/content.html
@@ -0,0 +1 @@
+番組表(アニメシアターX(AT-X))|スカパー!
現在マイリストを更新中です。
現在マイリストに登録中です。
現在マイリストから削除中です。
08/01(木)
08/02(金)
ヴァルキリードライヴマーメイド #06
・このサイトでは、当日から1週間分はEPGと同等の番組情報が表示され、その先1ヶ月後まではガイド誌(有料)と同等の番組情報が表示されます。番組や放送予定は予告なく変更される場合がありますのでご了承ください。 ・このサイトは、ウェブブラウザーMicrosoftEdge最新版、GoogleChrome最新版、Firefox最新版、Safari最新版での動作を確認しております。上記以外のウェブブラウザーで閲覧されますと、表示の乱れや予期せぬ動作を起こす場合がございますので、予めご了承ください。
©橋本悠/集英社・リリサ製作委員会/©鍋敷/アース・スターエンターテイメント/俺は全てを【パリイ】する製作委員会/©AT-X ©天原・masha/株式会社KADOKAWA/異種族レビュアーズ製作委員会/©THEMARGINALSERVICE PROJECT/©荒巻義雄・徳間書店/©2015上栖綴人・Nitroplus/KADOKAWA/「新妹魔王の契約者BURST」製作委員会/©中村力斗・野澤ゆき子/集英社・君のことが大大大大大好きな製作委員会/©2018上栖綴人・Nitroplus/KADOKAWA/「新妹魔王の契約者DEPARTURES」製作委員会/© 小林尽/講談社・マーベラス・キングレコード・創通
ログインをしてお気に入り番組を登録しよう! Myスカパー!にログインをすると、マイリストにお気に入り番組リストを作成することができます! マイリストに番組を登録できません ##ERROR_MSG##
\ No newline at end of file
diff --git a/sites/skyperfectv.co.jp/__data__/empty.html b/sites/skyperfectv.co.jp/__data__/empty.html
new file mode 100644
index 00000000..9560ec25
--- /dev/null
+++ b/sites/skyperfectv.co.jp/__data__/empty.html
@@ -0,0 +1 @@
+番組表(アニメシアターX(AT-X))|スカパー!
現在マイリストを更新中です。
現在マイリストに登録中です。
現在マイリストから削除中です。
・このサイトでは、当日から1週間分はEPGと同等の番組情報が表示され、その先1ヶ月後まではガイド誌(有料)と同等の番組情報が表示されます。番組や放送予定は予告なく変更される場合がありますのでご了承ください。 ・このサイトは、ウェブブラウザーMicrosoftEdge最新版、GoogleChrome最新版、Firefox最新版、Safari最新版での動作を確認しております。上記以外のウェブブラウザーで閲覧されますと、表示の乱れや予期せぬ動作を起こす場合がございますので、予めご了承ください。
©橋本悠/集英社・リリサ製作委員会/©鍋敷/アース・スターエンターテイメント/俺は全てを【パリイ】する製作委員会/©AT-X ©天原・masha/株式会社KADOKAWA/異種族レビュアーズ製作委員会/©THEMARGINALSERVICE PROJECT/©荒巻義雄・徳間書店/©2015上栖綴人・Nitroplus/KADOKAWA/「新妹魔王の契約者BURST」製作委員会/©中村力斗・野澤ゆき子/集英社・君のことが大大大大大好きな製作委員会/©2018上栖綴人・Nitroplus/KADOKAWA/「新妹魔王の契約者DEPARTURES」製作委員会/© 小林尽/講談社・マーベラス・キングレコード・創通
ログインをしてお気に入り番組を登録しよう! Myスカパー!にログインをすると、マイリストにお気に入り番組リストを作成することができます! マイリストに番組を登録できません ##ERROR_MSG##
\ No newline at end of file
diff --git a/sites/skyperfectv.co.jp/skyperfectv.co.jp.config.js b/sites/skyperfectv.co.jp/skyperfectv.co.jp.config.js
index c2d4aa23..1963124d 100644
--- a/sites/skyperfectv.co.jp/skyperfectv.co.jp.config.js
+++ b/sites/skyperfectv.co.jp/skyperfectv.co.jp.config.js
@@ -12,103 +12,110 @@ dayjs.extend(customParseFormat)
dayjs.extend(duration)
const exported = {
- site: 'skyperfectv.co.jp',
- days: 1,
- lang: 'ja',
- url: function ({ date, channel }) {
- let [type, ...code] = channel.site_id.split('_')
- code = code.join('_')
- return `https://www.skyperfectv.co.jp/program/schedule/${type}/channel:${code}/date:${date.format('YYMMDD')}`
- },
- logo: function ({ channel }) {
- return `https://www.skyperfectv.co.jp/library/common/img/channel/icon/basic/m_${channel.site_id.toLowerCase()}.gif`
- },
- // Specific function that permits to gather NSFW channels (needs confirmation)
- async fetchSchedule({ date, channel }) {
- const url = exported.url({ date, channel })
- const response = await axios.get(url, {
- headers: {
- 'Cookie': 'adult_auth=true'
- }
+ site: 'skyperfectv.co.jp',
+ days: 1,
+ lang: 'ja',
+ url: function ({ date, channel }) {
+ let [type, ...code] = channel.site_id.split('_')
+ code = code.join('_')
+ return `https://www.skyperfectv.co.jp/program/schedule/${type}/channel:${code}/date:${date.format(
+ 'YYMMDD'
+ )}`
+ },
+ logo: function ({ channel }) {
+ return `https://www.skyperfectv.co.jp/library/common/img/channel/icon/basic/m_${channel.site_id.toLowerCase()}.gif`
+ },
+ // Specific function that permits to gather NSFW channels (needs confirmation)
+ async fetchSchedule({ date, channel }) {
+ const url = exported.url({ date, channel })
+ const response = await axios.get(url, {
+ headers: {
+ Cookie: 'adult_auth=true'
+ }
+ })
+ return response.data
+ },
+ parser({ content, date }) {
+ const $ = cheerio.load(content)
+ const programs = []
+
+ const sections = [
+ { id: 'js-am', addition: 0 },
+ { id: 'js-pm', addition: 0 },
+ { id: 'js-md', addition: 1 }
+ ]
+
+ sections.forEach(({ id, addition }) => {
+ $(`#${id} > td`).each((index, element) => {
+ // `td` is a column for a day
+ // the next `td` will be the next day
+ const today = date.add(index + addition, 'd').tz('Asia/Tokyo')
+
+ const parseTime = timeString => {
+ // timeString is in the format "HH:mm"
+ // replace `today` with the time from timeString
+ const [hour, minute] = timeString.split(':').map(Number)
+ return today.hour(hour).minute(minute)
+ }
+
+ const $element = $(element) // Wrap element with Cheerio
+ $element.find('.p-program__item').each((itemIndex, itemElement) => {
+ const $itemElement = $(itemElement) // Wrap itemElement with Cheerio
+ const [start, stop] = $itemElement
+ .find('.p-program__range')
+ .first()
+ .text()
+ .split('〜')
+ .map(parseTime)
+ const title = $itemElement.find('.p-program__name').first().text()
+ const image = $itemElement.find('.js-program_thumbnail').first().attr('data-lazysrc')
+ programs.push({
+ title,
+ start,
+ stop,
+ image
+ })
})
- return response.data
- },
- parser({ content, date }) {
- const $ = cheerio.load(content)
- const programs = []
+ })
+ })
- const sections = [
- { id: 'js-am', addition: 0 },
- { id: 'js-pm', addition: 0 },
- { id: 'js-md', addition: 1 }
- ]
+ return programs
+ },
+ async channels() {
+ const pageParser = (content, type) => {
+ // type: "basic" | "premium"
+ // Returns an array of channel objects
- sections.forEach(({ id, addition }) => {
- $(`#${id} > td`).each((index, element) => {
- // `td` is a column for a day
- // the next `td` will be the next day
- const today = date.add(index + addition, 'd').tz('Asia/Tokyo')
+ const $ = cheerio.load(content)
+ const channels = []
- const parseTime = (timeString) => {
- // timeString is in the format "HH:mm"
- // replace `today` with the time from timeString
- const [hour, minute] = timeString.split(':').map(Number)
- return today.hour(hour).minute(minute)
- }
+ $('.p-channel').each((index, element) => {
+ const site_id = `${type}_${$(element).find('.p-channel__id').text()}`
+ const name = $(element).find('.p-channel__name').text()
+ channels.push({ site_id, name, lang: 'ja' })
+ })
- const $element = $(element) // Wrap element with Cheerio
- $element.find('.p-program__item').each((itemIndex, itemElement) => {
- const $itemElement = $(itemElement) // Wrap itemElement with Cheerio
- const [start, stop] = $itemElement.find('.p-program__range').first().text().split('〜').map(parseTime)
- const title = $itemElement.find('.p-program__name').first().text()
- const image = $itemElement.find('.js-program_thumbnail').first().attr('data-lazysrc')
- programs.push({
- title,
- start,
- stop,
- image
- })
- })
- })
- })
-
- return programs
- },
- async channels() {
- const pageParser = (content, type) => {
- // type: "basic" | "premium"
- // Returns an array of channel objects
-
- const $ = cheerio.load(content)
- const channels = []
-
- $('.p-channel').each((index, element) => {
- const site_id = `${type}_${$(element).find('.p-channel__id').text()}`
- const name = $(element).find('.p-channel__name').text()
- channels.push({ site_id, name, lang: 'ja' })
- })
-
- return channels
- }
-
- const getChannels = async (type) => {
- const response = await axios.get(`https://www.skyperfectv.co.jp/program/schedule/${type}/`, {
- headers: {
- 'Cookie': 'adult_auth=true;'
- }
- })
- return pageParser(response.data, type)
- }
-
- const fetchAllChannels = async () => {
- const basicChannels = await getChannels('basic')
- const premiumChannels = await getChannels('premium')
- const results = [...basicChannels, ...premiumChannels]
- return results
- }
-
- return await fetchAllChannels()
+ return channels
}
+
+ const getChannels = async type => {
+ const response = await axios.get(`https://www.skyperfectv.co.jp/program/schedule/${type}/`, {
+ headers: {
+ Cookie: 'adult_auth=true;'
+ }
+ })
+ return pageParser(response.data, type)
+ }
+
+ const fetchAllChannels = async () => {
+ const basicChannels = await getChannels('basic')
+ const premiumChannels = await getChannels('premium')
+ const results = [...basicChannels, ...premiumChannels]
+ return results
+ }
+
+ return await fetchAllChannels()
+ }
}
-module.exports = exported
\ No newline at end of file
+module.exports = exported
diff --git a/sites/skyperfectv.co.jp/skyperfectv.co.jp.test.js b/sites/skyperfectv.co.jp/skyperfectv.co.jp.test.js
index eae08e3f..c70ae27c 100644
--- a/sites/skyperfectv.co.jp/skyperfectv.co.jp.test.js
+++ b/sites/skyperfectv.co.jp/skyperfectv.co.jp.test.js
@@ -1,4 +1,6 @@
const { parser, url } = require('./skyperfectv.co.jp.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')
@@ -12,13 +14,13 @@ const channel = {
xmltv_id: 'WOWOWCinema.jp'
}
-const content = `
-番組表(アニメシアターX(AT-X))|スカパー!
現在マイリストを更新中です。
現在マイリストに登録中です。
現在マイリストから削除中です。
08/01(木)
08/02(金)
ヴァルキリードライヴマーメイド #06
・このサイトでは、当日から1週間分はEPGと同等の番組情報が表示され、その先1ヶ月後まではガイド誌(有料)と同等の番組情報が表示されます。番組や放送予定は予告なく変更される場合がありますのでご了承ください。 ・このサイトは、ウェブブラウザーMicrosoftEdge最新版、GoogleChrome最新版、Firefox最新版、Safari最新版での動作を確認しております。上記以外のウェブブラウザーで閲覧されますと、表示の乱れや予期せぬ動作を起こす場合がございますので、予めご了承ください。
©橋本悠/集英社・リリサ製作委員会/©鍋敷/アース・スターエンターテイメント/俺は全てを【パリイ】する製作委員会/©AT-X ©天原・masha/株式会社KADOKAWA/異種族レビュアーズ製作委員会/©THEMARGINALSERVICE PROJECT/©荒巻義雄・徳間書店/©2015上栖綴人・Nitroplus/KADOKAWA/「新妹魔王の契約者BURST」製作委員会/©中村力斗・野澤ゆき子/集英社・君のことが大大大大大好きな製作委員会/©2018上栖綴人・Nitroplus/KADOKAWA/「新妹魔王の契約者DEPARTURES」製作委員会/© 小林尽/講談社・マーベラス・キングレコード・創通
ログインをしてお気に入り番組を登録しよう! Myスカパー!にログインをすると、マイリストにお気に入り番組リストを作成することができます! マイリストに番組を登録できません ##ERROR_MSG##
-`
+const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.html'))
it('can generate valid url', () => {
const result = url({ date, channel })
- expect(result).toBe('https://www.skyperfectv.co.jp/program/schedule/basic/channel:BS193/date:240801')
+ expect(result).toBe(
+ 'https://www.skyperfectv.co.jp/program/schedule/basic/channel:BS193/date:240801'
+ )
})
it('can parse response', async () => {
@@ -33,15 +35,13 @@ it('can parse response', async () => {
start: '2024-07-31T19:00:00.000Z', // UTC time
stop: '2024-07-31T19:30:00.000Z', // UTC
title: 'ヴァルキリードライヴマーメイド #06',
- image: 'https://pm-img-ap.skyperfectv.co.jp/uploads/thumbnail/image/11301805/S_BC929697780313_be7975d4e26a4cad9b89fc6c94807e38_20240613144158569.jpg'
+ image:
+ 'https://pm-img-ap.skyperfectv.co.jp/uploads/thumbnail/image/11301805/S_BC929697780313_be7975d4e26a4cad9b89fc6c94807e38_20240613144158569.jpg'
}
])
})
-
-const empty = `
-番組表(アニメシアターX(AT-X))|スカパー!
現在マイリストを更新中です。
現在マイリストに登録中です。
現在マイリストから削除中です。
・このサイトでは、当日から1週間分はEPGと同等の番組情報が表示され、その先1ヶ月後まではガイド誌(有料)と同等の番組情報が表示されます。番組や放送予定は予告なく変更される場合がありますのでご了承ください。 ・このサイトは、ウェブブラウザーMicrosoftEdge最新版、GoogleChrome最新版、Firefox最新版、Safari最新版での動作を確認しております。上記以外のウェブブラウザーで閲覧されますと、表示の乱れや予期せぬ動作を起こす場合がございますので、予めご了承ください。
©橋本悠/集英社・リリサ製作委員会/©鍋敷/アース・スターエンターテイメント/俺は全てを【パリイ】する製作委員会/©AT-X ©天原・masha/株式会社KADOKAWA/異種族レビュアーズ製作委員会/©THEMARGINALSERVICE PROJECT/©荒巻義雄・徳間書店/©2015上栖綴人・Nitroplus/KADOKAWA/「新妹魔王の契約者BURST」製作委員会/©中村力斗・野澤ゆき子/集英社・君のことが大大大大大好きな製作委員会/©2018上栖綴人・Nitroplus/KADOKAWA/「新妹魔王の契約者DEPARTURES」製作委員会/© 小林尽/講談社・マーベラス・キングレコード・創通
ログインをしてお気に入り番組を登録しよう! Myスカパー!にログインをすると、マイリストにお気に入り番組リストを作成することができます! マイリストに番組を登録できません ##ERROR_MSG##
-`
+const empty = fs.readFileSync(path.resolve(__dirname, '__data__/empty.html'))
it('can handle empty guide', async () => {
const result = parser({
diff --git a/sites/snrt.ma/snrt.ma.config.js b/sites/snrt.ma/snrt.ma.config.js
index f1251b4e..06b692f7 100644
--- a/sites/snrt.ma/snrt.ma.config.js
+++ b/sites/snrt.ma/snrt.ma.config.js
@@ -1,97 +1,86 @@
-const cheerio = require('cheerio')
-const { DateTime } = require('luxon')
-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)
-
-const channel = [{ site_id: '1208', xmltv_id: 'AlAoula.ma', lang: 'ar' },
- { site_id: '4069', xmltv_id: 'Laayoune.ma', lang: 'ar' },
- { site_id: '4070', xmltv_id: 'Arryadia.ma', lang: 'ar' },
- { site_id: '4071', xmltv_id: 'Athaqafia.ma', lang: 'ar' },
- { site_id: '4072', xmltv_id: 'AlMaghribia.ma', lang: 'ar' },
- { site_id: '4073', xmltv_id: 'Assadissa.ma', lang: 'ar' },
- { site_id: '4075', xmltv_id: 'Tamazight.ma', lang: 'ar' }]
-
-
-module.exports = {
- site: 'snrt.ma',
- channels: 'snrt.ma.channels.xml',
- days: 2,
- url: function ({ channel }) {
- return `https://www.snrt.ma/ar/node/${channel.site_id}`
- },
- request: {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded'
- },
- data: function ({ date }) {
- const params = new URLSearchParams()
- params.append('_method', 'POST')
- params.append('data-date', date.format('YYYYMMDD'))
- params.append('current_date', date.format('YYYYMMDD'))
-
- return params
- }
- },
- parser: function ({ content, date }) {
- const programs = []
- const items = parseItems(content)
- items.forEach(item => {
- const prev = programs[programs.length - 1]
- const $item = cheerio.load(item)
- let start = parseStart($item, date)
- if (prev) {
- if (start.isBefore(prev.start)) {
- start = start.add(1, 'd')
- date = date.add(1, 'd')
- }
- prev.stop = start
- }
- const stop = start.add(30, 'm')
- programs.push({
- title: parseTitle($item),
- description: parseDescription($item),
- category: parseCategory($item),
- start,
- stop
- })
- })
-
- return programs
- }
-}
-
-function parseStart($item, date) {
- const timeString = $item('.grille-time').text().trim()
- const [hours, minutes] = timeString.split('H').map(Number)
- const formattedTime = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:00`
-
- const dateString = `${date.format('YYYY-MM-DD')} ${formattedTime}`
-
- return dayjs.tz(dateString, 'YYYY-MM-DD HH:mm:ss', 'Africa/Casablanca')
-}
-
-
-function parseTitle($item) {
- return $item('.program-title-sm').text().trim()
-}
-
-function parseDescription($item) {
- return $item('.program-description-sm').text().trim()
-}
-
-function parseCategory($item) {
- return $item('.genre-first').text().trim()
-}
-
-function parseItems(content) {
- const $ = cheerio.load(content)
-
- return $('.grille-line').toArray()
-}
\ No newline at end of file
+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)
+
+module.exports = {
+ site: 'snrt.ma',
+ channels: 'snrt.ma.channels.xml',
+ days: 2,
+ url: function ({ channel }) {
+ return `https://www.snrt.ma/ar/node/${channel.site_id}`
+ },
+ request: {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ },
+ data: function ({ date }) {
+ const params = new URLSearchParams()
+ params.append('_method', 'POST')
+ params.append('data-date', date.format('YYYYMMDD'))
+ params.append('current_date', date.format('YYYYMMDD'))
+
+ return params
+ }
+ },
+ parser: function ({ content, date }) {
+ const programs = []
+ const items = parseItems(content)
+ items.forEach(item => {
+ const prev = programs[programs.length - 1]
+ const $item = cheerio.load(item)
+ let start = parseStart($item, date)
+ if (prev) {
+ if (start.isBefore(prev.start)) {
+ start = start.add(1, 'd')
+ date = date.add(1, 'd')
+ }
+ prev.stop = start
+ }
+ const stop = start.add(30, 'm')
+ programs.push({
+ title: parseTitle($item),
+ description: parseDescription($item),
+ category: parseCategory($item),
+ start,
+ stop
+ })
+ })
+
+ return programs
+ }
+}
+
+function parseStart($item, date) {
+ const timeString = $item('.grille-time').text().trim()
+ const [hours, minutes] = timeString.split('H').map(Number)
+ const formattedTime = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:00`
+
+ const dateString = `${date.format('YYYY-MM-DD')} ${formattedTime}`
+
+ return dayjs.tz(dateString, 'YYYY-MM-DD HH:mm:ss', 'Africa/Casablanca')
+}
+
+function parseTitle($item) {
+ return $item('.program-title-sm').text().trim()
+}
+
+function parseDescription($item) {
+ return $item('.program-description-sm').text().trim()
+}
+
+function parseCategory($item) {
+ return $item('.genre-first').text().trim()
+}
+
+function parseItems(content) {
+ const $ = cheerio.load(content)
+
+ return $('.grille-line').toArray()
+}
diff --git a/sites/snrt.ma/snrt.ma.test.js b/sites/snrt.ma/snrt.ma.test.js
index b97ac1f3..97dcf197 100644
--- a/sites/snrt.ma/snrt.ma.test.js
+++ b/sites/snrt.ma/snrt.ma.test.js
@@ -1,6 +1,4 @@
const { parser, url } = require('./snrt.ma.config.js')
-const cheerio = require('cheerio')
-const { DateTime } = require('luxon')
const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc')
const timezone = require('dayjs/plugin/timezone')
@@ -25,16 +23,14 @@ it('can parse response', () => {
})
expect(results[0]).toMatchObject({
- "category": "القرآن الكريم",
- "description": "",
- "start": "2024-12-19T06:00:00.000Z",
- "stop": "2024-12-19T06:10:00.000Z",
- "stop": "2024-12-19T06:30:00.000Z",
- "title": "ﺍﻟﺴﻼﻡ ﺍﻟﻮﻃﻨﻲ + ﺍﻟﻘﺮﺁﻥ ﺍﻟﻜﺮﻳﻢ"
+ category: 'القرآن الكريم',
+ description: '',
+ start: '2024-12-19T06:00:00.000Z',
+ stop: '2024-12-19T06:30:00.000Z',
+ title: 'ﺍﻟﺴﻼﻡ ﺍﻟﻮﻃﻨﻲ + ﺍﻟﻘﺮﺁﻥ ﺍﻟﻜﺮﻳﻢ'
})
})
-
it('can handle empty guide', () => {
const result = parser({
date,
@@ -42,4 +38,4 @@ it('can handle empty guide', () => {
content: ''
})
expect(result).toMatchObject([])
-})
\ No newline at end of file
+})
diff --git a/sites/starhubtvplus.com/starhubtvplus.com.config.js b/sites/starhubtvplus.com/starhubtvplus.com.config.js
index c93af434..c9710bae 100644
--- a/sites/starhubtvplus.com/starhubtvplus.com.config.js
+++ b/sites/starhubtvplus.com/starhubtvplus.com.config.js
@@ -9,15 +9,9 @@ module.exports = {
url({ date, channel }) {
return `https://waf-starhub-metadata-api-p001.ifs.vubiquity.com/v3.1/epg/schedules?locale=${
languages[channel.lang]
- }&locale_default=${
- languages[channel.lang]
- }&device=1&in_channel_id=${
+ }&locale_default=${languages[channel.lang]}&device=1&in_channel_id=${
channel.site_id
- }>_end=${
- date.unix()
- }<_start=${
- date.add(1, 'd').unix()
- }&limit=100&page=1`
+ }>_end=${date.unix()}<_start=${date.add(1, 'd').unix()}&limit=100&page=1`
},
async parser({ content, date, channel }) {
const programs = []
@@ -29,7 +23,11 @@ module.exports = {
}
if (res.page && res.page.current < res.page.total) {
res = await axios
- .get(module.exports.url({ date, channel }).replace(/page=(\d+)/, `page=${res.page.current + 1}`))
+ .get(
+ module.exports
+ .url({ date, channel })
+ .replace(/page=(\d+)/, `page=${res.page.current + 1}`)
+ )
.then(r => r.data)
.catch(console.error)
} else {
@@ -39,7 +37,7 @@ module.exports = {
}
const season = s => {
if (s) {
- const [ , , n ] = s.match(/(S|Season )(\d+)/) || [null, null, null]
+ const [, , n] = s.match(/(S|Season )(\d+)/) || [null, null, null]
if (n) {
return parseInt(n)
}
@@ -66,11 +64,9 @@ module.exports = {
let page = 1
while (true) {
const items = await axios
- .get(`https://waf-starhub-metadata-api-p001.ifs.vubiquity.com/v3.1/epg/channels?locale=${
- languages[lang]
- }&locale_default=${
- languages[lang]
- }&device=1&limit=50&page=${page}`)
+ .get(
+ `https://waf-starhub-metadata-api-p001.ifs.vubiquity.com/v3.1/epg/channels?locale=${languages[lang]}&locale_default=${languages[lang]}&device=1&limit=50&page=${page}`
+ )
.then(r => r.data)
.catch(console.error)
if (items.resources) {
diff --git a/sites/starhubtvplus.com/starhubtvplus.com.test.js b/sites/starhubtvplus.com/starhubtvplus.com.test.js
index 71561072..78d97c5b 100644
--- a/sites/starhubtvplus.com/starhubtvplus.com.test.js
+++ b/sites/starhubtvplus.com/starhubtvplus.com.test.js
@@ -1,4 +1,4 @@
-const { parser, url, request } = require('./starhubtvplus.com.config.js')
+const { parser, url } = require('./starhubtvplus.com.config.js')
const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc')
const customParseFormat = require('dayjs/plugin/customParseFormat')
@@ -36,9 +36,12 @@ it('can parse response', async () => {
title: 'Northern Rexposure',
subTitle: 'Hudson & Rex (Season 5)',
description:
- 'When Jesse\'s sister contacts him for help, he, Sarah and Rex head to Northern Ontario and find themselves in the middle of a deadly situation.',
+ "When Jesse's sister contacts him for help, he, Sarah and Rex head to Northern Ontario and find themselves in the middle of a deadly situation.",
category: ['Drama'],
- image: ['https://poster.starhubgo.com/poster/ch511_hudson_rex5.jpg?w=960&h=540', 'https://poster.starhubgo.com/poster/ch511_hudson_rex5.jpg?w=341&h=192'],
+ image: [
+ 'https://poster.starhubgo.com/poster/ch511_hudson_rex5.jpg?w=960&h=540',
+ 'https://poster.starhubgo.com/poster/ch511_hudson_rex5.jpg?w=341&h=192'
+ ],
season: 5,
episode: 15,
rating: 'PG13'
diff --git a/sites/startimestv.com/startimestv.com.config.js b/sites/startimestv.com/startimestv.com.config.js
index 83b6a4d4..214e28b1 100644
--- a/sites/startimestv.com/startimestv.com.config.js
+++ b/sites/startimestv.com/startimestv.com.config.js
@@ -8,9 +8,7 @@ const debug = require('debug')('site:startimestv.com')
dayjs.extend(utc)
dayjs.extend(customParseFormat)
-doFetch
- .setDebugger(debug)
- .setMaxWorker(5)
+doFetch.setDebugger(debug).setMaxWorker(5)
module.exports = {
site: 'startimestv.com',
@@ -24,7 +22,8 @@ module.exports = {
const programs = []
if (content) {
const $ = cheerio.load(content)
- $('.box .mask').toArray()
+ $('.box .mask')
+ .toArray()
.forEach(el => {
let title = parseText($(el).find('h4'))
const [s, e] = title.substr(0, title.indexOf(' ')).split('-') || [null, null]
@@ -53,7 +52,8 @@ module.exports = {
// process area-id
if (queue.t === 'a') {
const $ = cheerio.load(res)
- $('dd.update-areaID').toArray()
+ $('dd.update-areaID')
+ .toArray()
.forEach(el => {
const dd = $(el)
const areaId = dd.attr('area-id')
@@ -72,7 +72,8 @@ module.exports = {
if (queue.t === 's') {
if (res) {
const $ = cheerio.load(res)
- $(`.channl .c`).toArray()
+ $('.channl .c')
+ .toArray()
.forEach(el => {
// only process channel with schedule only
const clazz = $(el).attr('class')
@@ -98,13 +99,10 @@ module.exports = {
}
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
diff --git a/sites/streamingtvguides.com/streamingtvguides.com.config.js b/sites/streamingtvguides.com/streamingtvguides.com.config.js
index 0807c0d6..440ca9e1 100644
--- a/sites/streamingtvguides.com/streamingtvguides.com.config.js
+++ b/sites/streamingtvguides.com/streamingtvguides.com.config.js
@@ -33,10 +33,10 @@ module.exports = {
return programs
},
- async channels({ country, lang }) {
+ async channels() {
const axios = require('axios')
const data = await axios
- .get(`https://streamingtvguides.com/Preferences`)
+ .get('https://streamingtvguides.com/Preferences')
.then(r => r.data)
.catch(console.log)
diff --git a/sites/telenet.tv/telenet.tv.config.js b/sites/telenet.tv/telenet.tv.config.js
index fa392183..7f286001 100644
--- a/sites/telenet.tv/telenet.tv.config.js
+++ b/sites/telenet.tv/telenet.tv.config.js
@@ -3,7 +3,7 @@ const dayjs = require('dayjs')
const API_STATIC_ENDPOINT = 'https://static.spark.telenet.tv/eng/web/epg-service-lite/be'
const API_PROD_ENDPOINT = 'https://spark-prod-be.gnp.cloud.telenet.tv/eng/web/linear-service/v2'
-const API_IMAGE_ENDPOINT = 'https://staticqbr-prod-be.gnp.cloud.telenet.tv/image-service';
+const API_IMAGE_ENDPOINT = 'https://staticqbr-prod-be.gnp.cloud.telenet.tv/image-service'
module.exports = {
site: 'telenet.tv',
@@ -94,7 +94,7 @@ module.exports = {
async function loadProgramDetails(item, channel) {
if (!item.id) return {}
- const url = `${API_PROD_ENDPOINT}/replayEvent/${item.id}?returnLinearContent=true&language=${channel.lang}`
+ const url = `${API_PROD_ENDPOINT}/replayEvent/${item.id}?returnLinearContent=true&language=${channel.lang}`
const data = await axios
.get(url)
.then(r => r.data)
@@ -134,5 +134,5 @@ function parseEpisode(detail) {
}
function parseIcon(item) {
- return `${API_IMAGE_ENDPOINT}/intent/${item.id}/posterTile`;
-}
\ No newline at end of file
+ return `${API_IMAGE_ENDPOINT}/intent/${item.id}/posterTile`
+}
diff --git a/sites/telkussa.fi/telkussa.fi.config.js b/sites/telkussa.fi/telkussa.fi.config.js
index d1b54f08..d9eeb6c2 100644
--- a/sites/telkussa.fi/telkussa.fi.config.js
+++ b/sites/telkussa.fi/telkussa.fi.config.js
@@ -27,10 +27,10 @@ module.exports = {
return programs
},
- async channels({ lang }) {
+ async channels() {
const axios = require('axios')
const data = await axios
- .get(`https://telkussa.fi/API/Channels`)
+ .get('https://telkussa.fi/API/Channels')
.then(r => r.data)
.catch(console.log)
diff --git a/sites/tivie.id/tivie.id.config.js b/sites/tivie.id/tivie.id.config.js
index cb6be07c..080a74e7 100644
--- a/sites/tivie.id/tivie.id.config.js
+++ b/sites/tivie.id/tivie.id.config.js
@@ -1,132 +1,134 @@
-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 doFetch = require('@ntlab/sfetch')
-const debug = require('debug')('site:tivie.id')
-
-dayjs.extend(utc)
-dayjs.extend(timezone)
-dayjs.extend(customParseFormat)
-
-doFetch
- .setDebugger(debug)
-
-const tz = 'Asia/Jakarta'
-
-module.exports = {
- site: 'tivie.id',
- days: 2,
- url({ channel, date }) {
- return `https://tivie.id/channel/${
- channel.site_id
- }/${
- date.format('YYYYMMDD')
- }`
- },
- async parser({ content, date }) {
- const programs = []
- if (content) {
- const $ = cheerio.load(content)
- const items = $('ul[x-data] > li[id*="event-"] > div.w-full').toArray()
- .map(item => {
- const $item = $(item)
- const time = $item.find('div:nth-child(1) span:nth-child(1)')
- const info = $item.find('div:nth-child(2) h5')
- const detail = info.find('a')
- const p = {
- start: dayjs.tz(`${date.format('YYYY-MM-DD')} ${time.html()}`, 'YYYY-MM-DD HH:mm', tz)
- }
- if (detail.length) {
- const subtitle = detail.find('div')
- p.title = parseText(subtitle.length ? subtitle : detail)
- p.url = detail.attr('href')
- } else {
- p.title = parseText(info)
- }
- if (p.title) {
- const [, , season, episode] = p.title.match(/( S(\d+))?, Ep\. (\d+)/) || [null, null, null, null]
- if (season) {
- p.season = parseInt(season)
- }
- if (episode) {
- p.episode = parseInt(episode)
- }
- }
- return p
- })
- // fetch detailed guide if necessary
- const queues = items
- .filter(i => i.url)
- .map(i => {
- const url = i.url
- delete i.url
- return {i, url}
- })
- if (queues.length) {
- await doFetch(queues, (queue, res) => {
- const $ = cheerio.load(res)
- const img = $('#main-content > div > div:nth-child(1) img')
- const info = $('#main-content > div > div:nth-child(2)')
- const title = parseText(info.find('h2:nth-child(2)'))
- if (!queue.i.title.startsWith(title)) {
- queue.i.subTitle = parseText(info.find('h2:nth-child(2)'))
- }
- queue.i.description = parseText(info.find('div[class=""]:nth-child(4)'))
- queue.i.date = parseText(info.find('h2:nth-child(3)'))
- queue.i.image = img.length ? img.attr('src') : null
- })
- }
- // fill start-stop
- for (let i = 0; i < items.length; i++) {
- if (i < items.length - 1) {
- items[i].stop = items[i + 1].start
- } else {
- items[i].stop = dayjs.tz(`${date.add(1, 'd').format('YYYY-MM-DD')} 00:00`, 'YYYY-MM-DD HH:mm', tz)
- }
- }
- // add programs
- programs.push(...items)
- }
-
- return programs
- },
- async channels({ lang = 'id' }) {
- const result = await axios
- .get('https://tivie.id/channel')
- .then(response => response.data)
- .catch(console.error)
-
- const $ = cheerio.load(result)
- const items = $('ul[x-data] li[x-data] div header h2 a').toArray()
- const channels = items.map(item => {
- const $item = $(item)
- const url = $item.attr('href')
- return {
- lang,
- site_id: url.substr(url.lastIndexOf('/') + 1),
- name: $item.find('strong').text()
- }
- })
-
- return channels
- }
-}
-
-function parseText($item) {
- let text = $item.text()
- .replace(/\t/g, '')
- .replace(/\n/g, ' ')
- .trim()
- while (true) {
- if (text.match(/ /)) {
- text = text.replace(/ /g, ' ')
- continue
- }
- break
- }
-
- return text
-}
+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 doFetch = require('@ntlab/sfetch')
+const debug = require('debug')('site:tivie.id')
+
+dayjs.extend(utc)
+dayjs.extend(timezone)
+dayjs.extend(customParseFormat)
+
+doFetch.setDebugger(debug)
+
+const tz = 'Asia/Jakarta'
+
+module.exports = {
+ site: 'tivie.id',
+ days: 2,
+ url({ channel, date }) {
+ return `https://tivie.id/channel/${channel.site_id}/${date.format('YYYYMMDD')}`
+ },
+ async parser({ content, date }) {
+ const programs = []
+ if (content) {
+ const $ = cheerio.load(content)
+ const items = $('ul[x-data] > li[id*="event-"] > div.w-full')
+ .toArray()
+ .map(item => {
+ const $item = $(item)
+ const time = $item.find('div:nth-child(1) span:nth-child(1)')
+ const info = $item.find('div:nth-child(2) h5')
+ const detail = info.find('a')
+ const p = {
+ start: dayjs.tz(`${date.format('YYYY-MM-DD')} ${time.html()}`, 'YYYY-MM-DD HH:mm', tz)
+ }
+ if (detail.length) {
+ const subtitle = detail.find('div')
+ p.title = parseText(subtitle.length ? subtitle : detail)
+ p.url = detail.attr('href')
+ } else {
+ p.title = parseText(info)
+ }
+ if (p.title) {
+ const [, , season, episode] = p.title.match(/( S(\d+))?, Ep\. (\d+)/) || [
+ null,
+ null,
+ null,
+ null
+ ]
+ if (season) {
+ p.season = parseInt(season)
+ }
+ if (episode) {
+ p.episode = parseInt(episode)
+ }
+ }
+ return p
+ })
+ // fetch detailed guide if necessary
+ const queues = items
+ .filter(i => i.url)
+ .map(i => {
+ const url = i.url
+ delete i.url
+ return { i, url }
+ })
+ if (queues.length) {
+ await doFetch(queues, (queue, res) => {
+ const $ = cheerio.load(res)
+ const img = $('#main-content > div > div:nth-child(1) img')
+ const info = $('#main-content > div > div:nth-child(2)')
+ const title = parseText(info.find('h2:nth-child(2)'))
+ if (!queue.i.title.startsWith(title)) {
+ queue.i.subTitle = parseText(info.find('h2:nth-child(2)'))
+ }
+ queue.i.description = parseText(info.find('div[class=""]:nth-child(4)'))
+ queue.i.date = parseText(info.find('h2:nth-child(3)'))
+ queue.i.image = img.length ? img.attr('src') : null
+ })
+ }
+ // fill start-stop
+ for (let i = 0; i < items.length; i++) {
+ if (i < items.length - 1) {
+ items[i].stop = items[i + 1].start
+ } else {
+ items[i].stop = dayjs.tz(
+ `${date.add(1, 'd').format('YYYY-MM-DD')} 00:00`,
+ 'YYYY-MM-DD HH:mm',
+ tz
+ )
+ }
+ }
+ // add programs
+ programs.push(...items)
+ }
+
+ return programs
+ },
+ async channels({ lang = 'id' }) {
+ const result = await axios
+ .get('https://tivie.id/channel')
+ .then(response => response.data)
+ .catch(console.error)
+
+ const $ = cheerio.load(result)
+ const items = $('ul[x-data] li[x-data] div header h2 a').toArray()
+ const channels = items.map(item => {
+ const $item = $(item)
+ const url = $item.attr('href')
+ return {
+ lang,
+ site_id: url.substr(url.lastIndexOf('/') + 1),
+ name: $item.find('strong').text()
+ }
+ })
+
+ return channels
+ }
+}
+
+function parseText($item) {
+ let text = $item.text().replace(/\t/g, '').replace(/\n/g, ' ').trim()
+ while (true) {
+ if (text.match(/\s\s/)) {
+ text = text.replace(/\s\s/g, ' ')
+ continue
+ }
+ break
+ }
+
+ return text
+}
diff --git a/sites/tivie.id/tivie.id.test.js b/sites/tivie.id/tivie.id.test.js
index e03247d2..dcc4e0ee 100644
--- a/sites/tivie.id/tivie.id.test.js
+++ b/sites/tivie.id/tivie.id.test.js
@@ -1,77 +1,75 @@
-const { parser, url } = require('./tivie.id.config')
-const fs = require('fs')
-const path = require('path')
-const axios = require('axios')
-const dayjs = require('dayjs')
-const utc = require('dayjs/plugin/utc')
-const customParseFormat = require('dayjs/plugin/customParseFormat')
-
-dayjs.extend(customParseFormat)
-dayjs.extend(utc)
-
-jest.mock('axios')
-
-const date = dayjs.utc('2024-12-31').startOf('d')
-const channel = {
- site_id: 'axn',
- xmltv_id: 'AXN.id',
- lang: 'id'
-}
-
-axios.get.mockImplementation(url => {
- const urls = {
- 'https://tivie.id/film/white-house-down-nwzDnwz9nAv6':
- 'program01.html',
- 'https://tivie.id/program/hudson-rex-s6-e14-nwzDnwvBmQr9':
- 'program02.html',
- }
- let data = ''
- if (urls[url] !== undefined) {
- data = fs.readFileSync(path.join(__dirname, '__data__', urls[url])).toString()
- }
- return Promise.resolve({ data })
-})
-
-it('can generate valid url', () => {
- expect(url({ channel, date })).toBe('https://tivie.id/channel/axn/20241231')
-})
-
-it('can parse response', async () => {
- const content = fs.readFileSync(path.join(__dirname, '__data__', 'content.html'))
- const results = (
- await parser({ date, content, channel })
- ).map(p => {
- p.start = p.start.toJSON()
- p.stop = p.stop.toJSON()
- return p
- })
-
- expect(results.length).toBe(27)
- expect(results[0]).toMatchObject({
- start: '2024-12-30T17:00:00.000Z',
- stop: '2024-12-30T17:05:00.000Z',
- title: 'White House Down',
- description:
- 'Saat melakukan tur di Gedung Putih bersama putrinya yang masih kecil, seorang perwira polisi beraksi untuk melindungi anaknya dan presiden dari sekelompok penjajah paramiliter bersenjata lengkap.',
- image: 'https://i0.wp.com/is3.cloudhost.id/tivie/poster/2023/09/65116c78791c2-1695640694.jpg?resize=480,270',
- })
- expect(results[2]).toMatchObject({
- start: '2024-12-30T18:00:00.000Z',
- stop: '2024-12-30T18:55:00.000Z',
- title: 'Hudson & Rex S6, Ep. 14',
- description:
- 'Saat guru musik Jesse terbunuh di studio rekamannya, Charlie dan Rex menghubungkan kejahatan tersebut dengan pembunuhan yang tampaknya tak ada hubungannya.',
- image: 'https://i0.wp.com/is3.cloudhost.id/tivie/poster/2024/07/668b7ced47b25-1720417517.jpg?resize=480,270',
- season: 6,
- episode: 14,
- })
-})
-
-it('can handle empty guide', async () => {
- const results = await parser({
- date,
- channel,
- content: '',
- })
- expect(results).toMatchObject([])
-})
+const { parser, url } = require('./tivie.id.config')
+const fs = require('fs')
+const path = require('path')
+const axios = require('axios')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+const customParseFormat = require('dayjs/plugin/customParseFormat')
+
+dayjs.extend(customParseFormat)
+dayjs.extend(utc)
+
+jest.mock('axios')
+
+const date = dayjs.utc('2024-12-31').startOf('d')
+const channel = {
+ site_id: 'axn',
+ xmltv_id: 'AXN.id',
+ lang: 'id'
+}
+
+axios.get.mockImplementation(url => {
+ const urls = {
+ 'https://tivie.id/film/white-house-down-nwzDnwz9nAv6': 'program01.html',
+ 'https://tivie.id/program/hudson-rex-s6-e14-nwzDnwvBmQr9': 'program02.html'
+ }
+ let data = ''
+ if (urls[url] !== undefined) {
+ data = fs.readFileSync(path.join(__dirname, '__data__', urls[url])).toString()
+ }
+ return Promise.resolve({ data })
+})
+
+it('can generate valid url', () => {
+ expect(url({ channel, date })).toBe('https://tivie.id/channel/axn/20241231')
+})
+
+it('can parse response', async () => {
+ const content = fs.readFileSync(path.join(__dirname, '__data__', 'content.html'))
+ const results = (await parser({ date, content, channel })).map(p => {
+ p.start = p.start.toJSON()
+ p.stop = p.stop.toJSON()
+ return p
+ })
+
+ expect(results.length).toBe(27)
+ expect(results[0]).toMatchObject({
+ start: '2024-12-30T17:00:00.000Z',
+ stop: '2024-12-30T17:05:00.000Z',
+ title: 'White House Down',
+ description:
+ 'Saat melakukan tur di Gedung Putih bersama putrinya yang masih kecil, seorang perwira polisi beraksi untuk melindungi anaknya dan presiden dari sekelompok penjajah paramiliter bersenjata lengkap.',
+ image:
+ 'https://i0.wp.com/is3.cloudhost.id/tivie/poster/2023/09/65116c78791c2-1695640694.jpg?resize=480,270'
+ })
+ expect(results[2]).toMatchObject({
+ start: '2024-12-30T18:00:00.000Z',
+ stop: '2024-12-30T18:55:00.000Z',
+ title: 'Hudson & Rex S6, Ep. 14',
+ description:
+ 'Saat guru musik Jesse terbunuh di studio rekamannya, Charlie dan Rex menghubungkan kejahatan tersebut dengan pembunuhan yang tampaknya tak ada hubungannya.',
+ image:
+ 'https://i0.wp.com/is3.cloudhost.id/tivie/poster/2024/07/668b7ced47b25-1720417517.jpg?resize=480,270',
+ season: 6,
+ episode: 14
+ })
+})
+
+it('can handle empty guide', async () => {
+ const results = await parser({
+ date,
+ channel,
+ content: ''
+ })
+ expect(results).toMatchObject([])
+})
diff --git a/sites/turksatkablo.com.tr/turksatkablo.com.tr.config.js b/sites/turksatkablo.com.tr/turksatkablo.com.tr.config.js
index 64140b30..933b6513 100644
--- a/sites/turksatkablo.com.tr/turksatkablo.com.tr.config.js
+++ b/sites/turksatkablo.com.tr/turksatkablo.com.tr.config.js
@@ -73,7 +73,7 @@ function parseItems(content, channel) {
let parsed
try {
parsed = JSON.parse(content)
- } catch (error) {
+ } catch {
return []
}
if (!parsed || !parsed.k) return []
diff --git a/sites/tv.mail.ru/tv.mail.ru.config.js b/sites/tv.mail.ru/tv.mail.ru.config.js
index 25691c14..92c19623 100644
--- a/sites/tv.mail.ru/tv.mail.ru.config.js
+++ b/sites/tv.mail.ru/tv.mail.ru.config.js
@@ -70,7 +70,7 @@ module.exports = {
async function getTotalPageCount(region) {
const data = await axios
- .get(`https://tv.mail.ru/ajax/channel/list/`, {
+ .get('https://tv.mail.ru/ajax/channel/list/', {
params: { page: 0 },
headers: {
cookie: `s=fver=0|geo=${region};`
diff --git a/sites/tv.nu/tv.nu.config.js b/sites/tv.nu/tv.nu.config.js
index 9afa14ea..5dd28959 100644
--- a/sites/tv.nu/tv.nu.config.js
+++ b/sites/tv.nu/tv.nu.config.js
@@ -40,7 +40,7 @@ module.exports = {
let offset = 0
while (offset !== undefined) {
const data = await axios
- .get(`https://web-api.tv.nu/tableauLinearChannels`, {
+ .get('https://web-api.tv.nu/tableauLinearChannels', {
params: {
modules,
date: dayjs().format('YYYY-MM-DD'),
diff --git a/sites/tv.trueid.net/tv.trueid.net.config.js b/sites/tv.trueid.net/tv.trueid.net.config.js
index f0736044..2de101cf 100644
--- a/sites/tv.trueid.net/tv.trueid.net.config.js
+++ b/sites/tv.trueid.net/tv.trueid.net.config.js
@@ -24,7 +24,7 @@ module.exports = {
return programs
},
- async channels({ token, lang = en }) {
+ async channels({ token, lang = 'en' }) {
const axios = require('axios')
const ACCESS_TOKEN = token
? token
diff --git a/sites/tv.yandex.ru/tv.yandex.ru.config.js b/sites/tv.yandex.ru/tv.yandex.ru.config.js
index e12df5d0..0dd19c00 100644
--- a/sites/tv.yandex.ru/tv.yandex.ru.config.js
+++ b/sites/tv.yandex.ru/tv.yandex.ru.config.js
@@ -2,9 +2,7 @@ const dayjs = require('dayjs')
const doFetch = require('@ntlab/sfetch')
const debug = require('debug')('site:tv.yandex.ru')
-doFetch
- .setDebugger(debug)
- .setMaxWorker(10)
+doFetch.setDebugger(debug).setMaxWorker(10)
// enable to fetch guide description but its take a longer time
const detailedGuide = true
@@ -12,14 +10,16 @@ const detailedGuide = true
// update this data by heading to https://tv.yandex.ru and change the values accordingly
const cookies = {
i: 'eIUfSP+/mzQWXcH+Cuz8o1vY+D2K8fhBd6Sj0xvbPZeO4l3cY+BvMp8fFIuM17l6UE1Z5+R2a18lP00ex9iYVJ+VT+c=',
- spravka: 'dD0xNzM0MjA0NjM4O2k9MTI1LjE2NC4xNDkuMjAwO0Q9QTVCQ0IyOTI5RDQxNkU5NkEyOTcwMTNDMzZGMDAzNjRDNTFFNDM4QkE2Q0IyOTJDRjhCOTZDRDIzODdBQzk2MzRFRDc5QTk2Qjc2OEI1MUY5MTM5M0QzNkY3OEQ2OUY3OTUwNkQ3RjBCOEJGOEJDMjAwMTQ0RDUwRkFCMDNEQzJFMDI2OEI5OTk5OUJBNEFERUYwOEQ1MjUwQTE0QTI3RDU1MEQwM0U0O3U9MTczNDIwNDYzODUyNDYyNzg1NDtoPTIxNTc0ZTc2MDQ1ZjcwMDBkYmY0NTVkM2Q2ZWMyM2Y1',
+ spravka:
+ 'dD0xNzM0MjA0NjM4O2k9MTI1LjE2NC4xNDkuMjAwO0Q9QTVCQ0IyOTI5RDQxNkU5NkEyOTcwMTNDMzZGMDAzNjRDNTFFNDM4QkE2Q0IyOTJDRjhCOTZDRDIzODdBQzk2MzRFRDc5QTk2Qjc2OEI1MUY5MTM5M0QzNkY3OEQ2OUY3OTUwNkQ3RjBCOEJGOEJDMjAwMTQ0RDUwRkFCMDNEQzJFMDI2OEI5OTk5OUJBNEFERUYwOEQ1MjUwQTE0QTI3RDU1MEQwM0U0O3U9MTczNDIwNDYzODUyNDYyNzg1NDtoPTIxNTc0ZTc2MDQ1ZjcwMDBkYmY0NTVkM2Q2ZWMyM2Y1',
yandexuid: '1197179041732383499',
yashr: '4682342911732383504',
yuidss: '1197179041732383499',
- user_display: 824,
+ user_display: 824
}
const headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0',
+ 'User-Agent':
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0'
}
const caches = {}
@@ -50,7 +50,9 @@ module.exports = {
}
caches[cacheid].forEach(schedule => {
schedule.events
- .filter(event => event.channelFamilyId == channel.site_id && date.isSame(event.start, 'day'))
+ .filter(
+ event => event.channelFamilyId == channel.site_id && date.isSame(event.start, 'day')
+ )
.forEach(event => {
if (events.indexOf(event.id) < 0) {
events.push(event.id)
@@ -171,7 +173,10 @@ function parseContent(content, date, checkOnly = false) {
content = content.toString()
}
// got captcha, its look like our cookies has expired
- if (content?.type === 'captcha' || (typeof content === 'string' && content.match(/SmartCaptcha/))) {
+ if (
+ content?.type === 'captcha' ||
+ (typeof content === 'string' && content.match(/SmartCaptcha/))
+ ) {
throw new Error('Got captcha, please goto https://tv.yandex.ru and update cookies!')
}
if (typeof content === 'object') {
@@ -210,35 +215,41 @@ function parseContent(content, date, checkOnly = false) {
headers['X-User-Session-Id'] = sessionId
}
if (checkOnly && region && tvSk.key && sessionId) {
- valid = true;
+ valid = true
}
}
}
- return checkOnly ? valid : [queues, schedules]
+ return checkOnly ? valid : [queues, schedules]
}
function parseCookies(headers) {
if (Array.isArray(headers['set-cookie'])) {
- headers['set-cookie']
- .forEach(cookie => {
- const [key, value] = cookie.split('; ')[0].split('=')
- if (cookies[key] !== value) {
- cookies[key] = value
- debug(`Update cookie ${key}=${value}`)
- }
- })
+ headers['set-cookie'].forEach(cookie => {
+ const [key, value] = cookie.split('; ')[0].split('=')
+ if (cookies[key] !== value) {
+ cookies[key] = value
+ debug(`Update cookie ${key}=${value}`)
+ }
+ })
}
}
function getSchedules(schedules) {
- return schedules.filter(schedule => schedule.events.length);
+ return schedules.filter(schedule => schedule.events.length)
}
function getHeaders(data = {}) {
- return Object.assign({}, headers, {
- Cookie: Object.keys(cookies).map(cookie => `${cookie}=${cookies[cookie]}`).join('; ')
- }, data)
+ return Object.assign(
+ {},
+ headers,
+ {
+ Cookie: Object.keys(cookies)
+ .map(cookie => `${cookie}=${cookies[cookie]}`)
+ .join('; ')
+ },
+ data
+ )
}
function getUrl(date, region = null, page = null, event = null) {
@@ -253,7 +264,9 @@ function getUrl(date, region = null, page = null, event = null) {
url += `${url.endsWith('/') ? '' : '/'}event?eventId=${event.id}&programCoId=`
}
if (date) {
- url += `${url.indexOf('?') < 0 ? '?' : '&'}date=${date.format('YYYY-MM-DD')}${!page ? '&grid=all' : ''}&period=all-day`
+ url += `${url.indexOf('?') < 0 ? '?' : '&'}date=${date.format('YYYY-MM-DD')}${
+ !page ? '&grid=all' : ''
+ }&period=all-day`
}
if (page && page.id !== undefined && page.offset !== undefined) {
url += `${url.indexOf('?') < 0 ? '?' : '&'}offset=${page.offset}`
@@ -266,7 +279,7 @@ function getUrl(date, region = null, page = null, event = null) {
function getQueue(url, referer) {
const data = {
- 'Origin': 'https://tv.yandex.ru',
+ Origin: 'https://tv.yandex.ru'
}
if (referer) {
data['Referer'] = referer
@@ -279,4 +292,4 @@ function getQueue(url, referer) {
url,
params: { headers }
}
-}
\ No newline at end of file
+}
diff --git a/sites/tv.yandex.ru/tv.yandex.ru.test.js b/sites/tv.yandex.ru/tv.yandex.ru.test.js
index ea72df5b..9661089f 100644
--- a/sites/tv.yandex.ru/tv.yandex.ru.test.js
+++ b/sites/tv.yandex.ru/tv.yandex.ru.test.js
@@ -16,7 +16,7 @@ const channel = {
site_id: '16',
xmltv_id: 'ChannelOne.ru'
}
-axios.get.mockImplementation((url, opts) => {
+axios.get.mockImplementation(url => {
if (url === 'https://tv.yandex.ru/?date=2023-11-26&grid=all&period=all-day') {
return Promise.resolve({
headers: {},
@@ -29,7 +29,10 @@ axios.get.mockImplementation((url, opts) => {
data: JSON.parse(fs.readFileSync(path.resolve(__dirname, '__data__/schedule.json')))
})
}
- if (url === 'https://tv.yandex.ru/api/120809/main/chunk?page=0&date=2023-11-26&period=all-day&offset=0&limit=11') {
+ if (
+ url ===
+ 'https://tv.yandex.ru/api/120809/main/chunk?page=0&date=2023-11-26&period=all-day&offset=0&limit=11'
+ ) {
return Promise.resolve({
headers: {},
data: JSON.parse(fs.readFileSync(path.resolve(__dirname, '__data__/schedule0.json')))
@@ -44,9 +47,7 @@ axios.get.mockImplementation((url, opts) => {
})
it('can generate valid url', () => {
- expect(url({ date })).toBe(
- 'https://tv.yandex.ru/?date=2023-11-26&grid=all&period=all-day'
- )
+ expect(url({ date })).toBe('https://tv.yandex.ru/?date=2023-11-26&grid=all&period=all-day')
})
it('can generate valid request headers', () => {
@@ -63,9 +64,7 @@ it('can generate valid request headers', () => {
it('can parse response', async () => {
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.html'))
- const result = (
- await parser({ content, date, channel })
- ).map(p => {
+ const result = (await parser({ content, date, channel })).map(p => {
p.start = p.start.toJSON()
p.stop = p.stop.toJSON()
return p
@@ -77,7 +76,8 @@ it('can parse response', async () => {
stop: '2023-11-26T02:10:00.000Z',
title: 'ПОДКАСТ.ЛАБ. Мелодии моей жизни',
category: 'досуг',
- description: 'Впереди вся ночь и есть о чем поговорить. Фильмы, музыка, любовь, звезды, еда, мода, анекдоты, спорт, деньги, настоящее, будущее - все это в творческом эксперименте.\nЛариса Гузеева читает любовные письма. Леонид Якубович рассказывает, кого не берут в пилоты. Арина Холина - какой секс способен довести до мужа или до развода. Валерий Сюткин на ходу сочиняет песню для Карины Кросс и Вали Карнавал. Дмитрий Дибров дарит новую жизнь любимой \"Антропологии\". Денис Казанский - все о футболе, хоккее и не только.\n\"ПОДКАСТЫ. ЛАБ\" - серия подкастов разной тематики, которые невозможно проспать. Интеллектуальные дискуссии после полуночи с самыми компетентными экспертами и актуальными спикерами.'
+ description:
+ 'Впереди вся ночь и есть о чем поговорить. Фильмы, музыка, любовь, звезды, еда, мода, анекдоты, спорт, деньги, настоящее, будущее - все это в творческом эксперименте.\nЛариса Гузеева читает любовные письма. Леонид Якубович рассказывает, кого не берут в пилоты. Арина Холина - какой секс способен довести до мужа или до развода. Валерий Сюткин на ходу сочиняет песню для Карины Кросс и Вали Карнавал. Дмитрий Дибров дарит новую жизнь любимой "Антропологии". Денис Казанский - все о футболе, хоккее и не только.\n"ПОДКАСТЫ. ЛАБ" - серия подкастов разной тематики, которые невозможно проспать. Интеллектуальные дискуссии после полуночи с самыми компетентными экспертами и актуальными спикерами.'
}
])
})
diff --git a/sites/tv2go.t-2.net/tv2go.t-2.net.config.js b/sites/tv2go.t-2.net/tv2go.t-2.net.config.js
index 9b77abec..2fc449f3 100644
--- a/sites/tv2go.t-2.net/tv2go.t-2.net.config.js
+++ b/sites/tv2go.t-2.net/tv2go.t-2.net.config.js
@@ -109,7 +109,7 @@ function parseItems(content) {
let data
try {
data = JSON.parse(content)
- } catch (e) {
+ } catch {
return []
}
if (!data || !Array.isArray(data.entries)) return []
diff --git a/sites/tvarenasport.com/tvarenasport.com.config.js b/sites/tvarenasport.com/tvarenasport.com.config.js
index f30d2efa..d2297d9c 100644
--- a/sites/tvarenasport.com/tvarenasport.com.config.js
+++ b/sites/tvarenasport.com/tvarenasport.com.config.js
@@ -26,22 +26,25 @@ module.exports = {
if (content) {
const dates = []
const $ = cheerio.load(content)
- const parent = $(`.tv-scheme-chanel-header img[src*="chanel-${channel.site_id}.png"]`)
- .parents('div')
+ const parent = $(
+ `.tv-scheme-chanel-header img[src*="chanel-${channel.site_id}.png"]`
+ ).parents('div')
parent
.siblings('.tv-scheme-days')
- .find('a').toArray()
- .forEach(el => {
- const a = $(el)
- const dt = a.find('span:nth-child(3)').text()
- dates.push(dayjs(dt + date.year(), 'DD.MM.YYYY'))
- })
+ .find('a')
+ .toArray()
+ .forEach(el => {
+ const a = $(el)
+ const dt = a.find('span:nth-child(3)').text()
+ dates.push(dayjs(dt + date.year(), 'DD.MM.YYYY'))
+ })
parent
.siblings('.tv-scheme-new-slider-wrapper')
- .find('.tv-scheme-new-slider-item').toArray()
- .forEach((el, i) => {
- programs.push(...parseSchedules($(el), dates[i], module.exports.tz))
- })
+ .find('.tv-scheme-new-slider-item')
+ .toArray()
+ .forEach((el, i) => {
+ programs.push(...parseSchedules($(el), dates[i], module.exports.tz))
+ })
programs.forEach((s, i) => {
if (i < programs.length - 2) {
s.stop = programs[i + 1].start
@@ -51,8 +54,11 @@ module.exports = {
})
}
- return programs
- .filter(p => p.start.format('YYYY-MM-DD') === expectedDate || p.stop.format('YYYY-MM-DD') === expectedDate)
+ return programs.filter(
+ p =>
+ p.start.format('YYYY-MM-DD') === expectedDate ||
+ p.stop.format('YYYY-MM-DD') === expectedDate
+ )
},
async channels() {
const channels = []
@@ -81,7 +87,9 @@ module.exports = {
const $ = cheerio.load(data)
const items = $('.tv-scheme-chanel-header img').toArray()
for (const item of items) {
- const [, id] = $(item).attr('src').match(/chanel-([a-z0-9]+)\.png/) || [null, null]
+ const [, id] = $(item)
+ .attr('src')
+ .match(/chanel-([a-z0-9]+)\.png/) || [null, null]
if (id) {
channels.push({
lang: this.lang,
@@ -99,7 +107,8 @@ module.exports = {
function parseSchedules($s, date, tz) {
const schedules = []
const $ = $s._make
- $s.find('.slider-content').toArray()
+ $s.find('.slider-content')
+ .toArray()
.forEach(el => {
schedules.push(parseSchedule($(el), date, tz))
})
diff --git a/sites/tvarenasport.com/tvarenasport.com.test.js b/sites/tvarenasport.com/tvarenasport.com.test.js
index 54ff2c33..1866f963 100644
--- a/sites/tvarenasport.com/tvarenasport.com.test.js
+++ b/sites/tvarenasport.com/tvarenasport.com.test.js
@@ -32,12 +32,12 @@ it('can parse response', () => {
stop: '2024-12-07T05:00:00.000Z',
title: 'EVROPSKO PRVENSTVO Ž',
description: 'Francuska - Crna Gora',
- category: 'Rukomet',
+ category: 'Rukomet'
})
expect(result[8]).toMatchObject({
start: '2024-12-07T11:00:00.000Z',
stop: '2024-12-07T11:05:00.000Z',
- title: 'Arena News',
+ title: 'Arena News'
})
})
diff --git a/sites/tvarenasport.hr/tvarenasport.hr.test.js b/sites/tvarenasport.hr/tvarenasport.hr.test.js
index eaf115da..9358952c 100644
--- a/sites/tvarenasport.hr/tvarenasport.hr.test.js
+++ b/sites/tvarenasport.hr/tvarenasport.hr.test.js
@@ -32,14 +32,14 @@ it('can parse response', () => {
stop: '2024-12-07T00:30:00.000Z',
title: 'MAGAZIN',
description: 'NBA ACTION',
- category: 'Košarka',
+ category: 'Košarka'
})
expect(result[4]).toMatchObject({
start: '2024-12-07T06:00:00.000Z',
stop: '2024-12-07T07:30:00.000Z',
title: 'EHF LIGA PRVAKA',
description: 'DINAMO BUKUREŠT - PSG',
- category: 'Rukomet',
+ category: 'Rukomet'
})
})
diff --git a/sites/tvcesoir.fr/tvcesoir.fr.config.js b/sites/tvcesoir.fr/tvcesoir.fr.config.js
index 937f6583..306f819f 100644
--- a/sites/tvcesoir.fr/tvcesoir.fr.config.js
+++ b/sites/tvcesoir.fr/tvcesoir.fr.config.js
@@ -49,7 +49,7 @@ module.exports = {
const channels = []
for (let provider of providers) {
const data = await axios
- .post(`https://www.tvcesoir.fr/guide/schedule`, null, {
+ .post('https://www.tvcesoir.fr/guide/schedule', null, {
params: {
provider,
region: 'France',
@@ -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}`
diff --git a/sites/tvcubana.icrt.cu/tvcubana.icrt.cu.config.js b/sites/tvcubana.icrt.cu/tvcubana.icrt.cu.config.js
index 515da300..41edebca 100644
--- a/sites/tvcubana.icrt.cu/tvcubana.icrt.cu.config.js
+++ b/sites/tvcubana.icrt.cu/tvcubana.icrt.cu.config.js
@@ -39,7 +39,7 @@ function parseItems(content) {
let data
try {
data = JSON.parse(content)
- } catch (error) {
+ } catch {
return []
}
if (!data || !Array.isArray(data)) return []
diff --git a/sites/tvguide.com/tvguide.com.config.js b/sites/tvguide.com/tvguide.com.config.js
index 5ddddf8b..54b08bbb 100644
--- a/sites/tvguide.com/tvguide.com.config.js
+++ b/sites/tvguide.com/tvguide.com.config.js
@@ -82,7 +82,10 @@ function parseItems(content) {
}
async function loadProgramDetails(item) {
- item.programDetails = item.programDetails.replace('player1-backend-prod-internal.apigee.net', 'internal-prod.apigee.fandom.net')
+ item.programDetails = item.programDetails.replace(
+ 'player1-backend-prod-internal.apigee.net',
+ 'internal-prod.apigee.fandom.net'
+ )
const data = await axios
.get(item.programDetails)
.then(r => r.data)
diff --git a/sites/tvheute.at/tvheute.at.config.js b/sites/tvheute.at/tvheute.at.config.js
index 4862eec1..d73706c8 100644
--- a/sites/tvheute.at/tvheute.at.config.js
+++ b/sites/tvheute.at/tvheute.at.config.js
@@ -28,7 +28,7 @@ module.exports = {
async channels() {
const axios = require('axios')
const html = await axios
- .get(`https://tvheute.at/part/channel-selection`)
+ .get('https://tvheute.at/part/channel-selection')
.then(r => r.data)
.catch(console.log)
diff --git a/sites/tvim.tv/tvim.tv.config.js b/sites/tvim.tv/tvim.tv.config.js
index 678291af..f67ac2ea 100644
--- a/sites/tvim.tv/tvim.tv.config.js
+++ b/sites/tvim.tv/tvim.tv.config.js
@@ -29,7 +29,7 @@ module.exports = {
async channels() {
const axios = require('axios')
const data = await axios
- .get(`https://www.tvim.tv/script/epg/category_channels?category=all&filter=playable`)
+ .get('https://www.tvim.tv/script/epg/category_channels?category=all&filter=playable')
.then(r => r.data)
.catch(console.log)
diff --git a/sites/tvireland.ie/tvireland.ie.config.js b/sites/tvireland.ie/tvireland.ie.config.js
index 93e712af..c28eb8c8 100644
--- a/sites/tvireland.ie/tvireland.ie.config.js
+++ b/sites/tvireland.ie/tvireland.ie.config.js
@@ -49,7 +49,7 @@ module.exports = {
const channels = []
for (let provider of providers) {
const data = await axios
- .post(`https://www.tvireland.ie/tv/schedule`, null, {
+ .post('https://www.tvireland.ie/tv/schedule', null, {
params: {
provider,
region: 'Ireland',
@@ -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}`
diff --git a/sites/tvpassport.com/tvpassport.com.config.js b/sites/tvpassport.com/tvpassport.com.config.js
index c8d28d3f..fe95d1b4 100644
--- a/sites/tvpassport.com/tvpassport.com.config.js
+++ b/sites/tvpassport.com/tvpassport.com.config.js
@@ -70,7 +70,7 @@ module.exports = {
let i = 1
for (let el of elements) {
const url = $(el).text()
- const [, site_id] = url.match(/\/tv\-listings\/stations\/(.*)$/)
+ const [, site_id] = url.match(/\/tv-listings\/stations\/(.*)$/)
console.log(`[${i}/${total}]`, url)
diff --git a/sites/tvplus.com.tr/tvplus.com.tr.config.js b/sites/tvplus.com.tr/tvplus.com.tr.config.js
index 391f3929..60ed9aa2 100644
--- a/sites/tvplus.com.tr/tvplus.com.tr.config.js
+++ b/sites/tvplus.com.tr/tvplus.com.tr.config.js
@@ -24,15 +24,7 @@ module.exports = {
debug('Got build id', module.exports.buildId)
}
const channelId = channel.site_id.replace('/', '--')
- return `https://tvplus.com.tr/_next/data/${
- module.exports.buildId
- }/${
- channel.lang
- }/canli-tv/yayin-akisi/${
- channelId
- }.json?title=${
- channelId
- }`
+ return `https://tvplus.com.tr/_next/data/${module.exports.buildId}/${channel.lang}/canli-tv/yayin-akisi/${channelId}.json?title=${channelId}`
},
parser({ content, date }) {
const programs = []
@@ -43,7 +35,9 @@ module.exports = {
.filter(i => i.length && i[0].starttime.startsWith(date.format('YYYY-MM-DD')))
.forEach(i => {
for (const schedule of i) {
- const [, season, episode] = schedule.seasonInfo?.match(/(\d+)\. Sezon \- (\d+)\. Bölüm/) || [null, null, null]
+ const [, season, episode] = schedule.seasonInfo?.match(
+ /(\d+)\. Sezon - (\d+)\. Bölüm/
+ ) || [null, null, null]
programs.push({
title: schedule.name,
description: schedule.introduce,
@@ -69,14 +63,19 @@ module.exports = {
.catch(console.error)
const $ = cheerio.load(data)
- $('.channel-list-item a').toArray()
+ $('.channel-list-item a')
+ .toArray()
.forEach(el => {
const a = $(el)
channels.push({
lang: 'tr',
- name: a.attr('title').replace(/Yayın Akışı/, '').trim(),
- site_id: a.attr('href')
- .replace(/\/canli\-tv\/yayin\-akisi\//, '')
+ name: a
+ .attr('title')
+ .replace(/Yayın Akışı/, '')
+ .trim(),
+ site_id: a
+ .attr('href')
+ .replace(/\/canli-tv\/yayin-akisi\//, '')
.replace('--', '/') // change -- to / as it used in xml comment
})
})
diff --git a/sites/tvplus.com.tr/tvplus.com.tr.test.js b/sites/tvplus.com.tr/tvplus.com.tr.test.js
index c0f5c13e..d7586cda 100644
--- a/sites/tvplus.com.tr/tvplus.com.tr.test.js
+++ b/sites/tvplus.com.tr/tvplus.com.tr.test.js
@@ -18,7 +18,7 @@ const channel = {
xmltv_id: 'NickJr.tr'
}
-axios.get.mockImplementation((url, opts) => {
+axios.get.mockImplementation(url => {
if (url === 'https://tvplus.com.tr/canli-tv/yayin-akisi') {
return Promise.resolve({
data: fs.readFileSync(path.join(__dirname, '__data__', 'build.html')).toString()
@@ -27,17 +27,18 @@ axios.get.mockImplementation((url, opts) => {
})
it('can generate valid url', async () => {
- expect(await url({ channel })).toBe('https://tvplus.com.tr/_next/data/kUzvz_bbQJNaShlFUkrR3/tr/canli-tv/yayin-akisi/nick-jr--4353.json?title=nick-jr--4353')
+ expect(await url({ channel })).toBe(
+ 'https://tvplus.com.tr/_next/data/kUzvz_bbQJNaShlFUkrR3/tr/canli-tv/yayin-akisi/nick-jr--4353.json?title=nick-jr--4353'
+ )
})
it('can parse response', () => {
const content = fs.readFileSync(path.join(__dirname, '__data__', 'content.json'))
- const results = parser({ date, channel, content })
- .map(p => {
- p.start = p.start.toJSON()
- p.stop = p.stop.toJSON()
- return p
- })
+ const results = parser({ date, channel, content }).map(p => {
+ p.start = p.start.toJSON()
+ p.stop = p.stop.toJSON()
+ return p
+ })
expect(results.length).toBe(88)
expect(results[0]).toMatchObject({
@@ -45,7 +46,7 @@ it('can parse response', () => {
stop: '2024-12-14T21:20:00.000Z',
title: 'Camgöz (2020)',
description:
- 'Max\'in Camgöz adında yarı köpek balığı yarı köpek eşsiz bir evcil havyanı vardır. İlk başlarda Camgöz\'ü saklamaya çalışsa da Sisli Pınarlar\'da, en iyi arkadaşlar, meraklı komşular ve hatta Max\'in ailesi bile yaramaz yeni arkadaşını fark edecektir.',
+ "Max'in Camgöz adında yarı köpek balığı yarı köpek eşsiz bir evcil havyanı vardır. İlk başlarda Camgöz'ü saklamaya çalışsa da Sisli Pınarlar'da, en iyi arkadaşlar, meraklı komşular ve hatta Max'in ailesi bile yaramaz yeni arkadaşını fark edecektir.",
image:
'https://gbzeottvsc01.tvplus.com.tr:33207/CPS/images/universal/film/program/202412/20241209/21/2126356250845eb88428_0_XL.jpg',
category: 'Çocuk',
diff --git a/sites/tvtv.us/tvtv.us.config.js b/sites/tvtv.us/tvtv.us.config.js
index dec7fb9e..b1eb7629 100644
--- a/sites/tvtv.us/tvtv.us.config.js
+++ b/sites/tvtv.us/tvtv.us.config.js
@@ -1,4 +1,4 @@
-const dayjs = require('dayjs')
+const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)
diff --git a/sites/virgintvgo.virginmedia.com/virgintvgo.virginmedia.com.config.js b/sites/virgintvgo.virginmedia.com/virgintvgo.virginmedia.com.config.js
index a26c23fd..dba45f8d 100644
--- a/sites/virgintvgo.virginmedia.com/virgintvgo.virginmedia.com.config.js
+++ b/sites/virgintvgo.virginmedia.com/virgintvgo.virginmedia.com.config.js
@@ -18,11 +18,9 @@ module.exports = {
}
},
url({ date, segment = 0 }) {
- return `https://staticqbr-prod-gb.gnp.cloud.virgintvgo.virginmedia.com/eng/web/epg-service-lite/gb/en/events/segments/${
- date.format('YYYYMMDD')
- }${
- segment.toString().padStart(2, '0')
- }0000`
+ return `https://staticqbr-prod-gb.gnp.cloud.virgintvgo.virginmedia.com/eng/web/epg-service-lite/gb/en/events/segments/${date.format(
+ 'YYYYMMDD'
+ )}${segment.toString().padStart(2, '0')}0000`
},
async parser({ content, channel, date }) {
const programs = []
@@ -31,9 +29,9 @@ module.exports = {
if (Array.isArray(items.entries)) {
// fetch other segments
const queues = [
- module.exports.url({ date, segment: 6}),
- module.exports.url({ date, segment: 12}),
- module.exports.url({ date, segment: 18}),
+ module.exports.url({ date, segment: 6 }),
+ module.exports.url({ date, segment: 12 }),
+ module.exports.url({ date, segment: 18 })
]
await doFetch(queues, (url, res) => {
if (Array.isArray(res.entries)) {
@@ -43,13 +41,12 @@ module.exports = {
items.entries
.filter(item => item.channelId === channel.site_id)
.forEach(item => {
- if (Array.isArray(item.events)){
+ if (Array.isArray(item.events)) {
if (detailedGuide) {
- queues.push(...item.events
- .map(event =>
- `https://spark-prod-gb.gnp.cloud.virgintvgo.virginmedia.com/eng/web/linear-service/v2/replayEvent/${
- event.id
- }?returnLinearContent=true&forceLinearResponse=true&language=en`
+ queues.push(
+ ...item.events.map(
+ event =>
+ `https://spark-prod-gb.gnp.cloud.virgintvgo.virginmedia.com/eng/web/linear-service/v2/replayEvent/${event.id}?returnLinearContent=true&forceLinearResponse=true&language=en`
)
)
} else {
@@ -92,20 +89,23 @@ module.exports = {
const channels = []
const axios = require('axios')
const res = await axios
- .get('https://spark-prod-gb.gnp.cloud.virgintvgo.virginmedia.com/eng/web/linear-service/v2/channels?cityId=40980&language=en&productClass=Orion-DASH&platform=web')
+ .get(
+ 'https://spark-prod-gb.gnp.cloud.virgintvgo.virginmedia.com/eng/web/linear-service/v2/channels?cityId=40980&language=en&productClass=Orion-DASH&platform=web'
+ )
.then(r => r.data)
.catch(console.error)
if (Array.isArray(res)) {
- channels.push(...res
- .filter(item => !item.isHidden)
- .map(item => {
- return {
- lang: 'en',
- site_id: item.id,
- name: item.name
- }
- })
+ channels.push(
+ ...res
+ .filter(item => !item.isHidden)
+ .map(item => {
+ return {
+ lang: 'en',
+ site_id: item.id,
+ name: item.name
+ }
+ })
)
}
diff --git a/sites/virgintvgo.virginmedia.com/virgintvgo.virginmedia.com.test.js b/sites/virgintvgo.virginmedia.com/virgintvgo.virginmedia.com.test.js
index d2213198..1fbc3400 100644
--- a/sites/virgintvgo.virginmedia.com/virgintvgo.virginmedia.com.test.js
+++ b/sites/virgintvgo.virginmedia.com/virgintvgo.virginmedia.com.test.js
@@ -32,7 +32,7 @@ axios.get.mockImplementation(url => {
'https://spark-prod-gb.gnp.cloud.virgintvgo.virginmedia.com/eng/web/linear-service/v2/replayEvent/crid:~~2F~~2Fgn.tv~~2F17641069~~2FEP026460800059,imi:23c363d12af79f43134f4a15b96dd12df81b19ab?returnLinearContent=true&forceLinearResponse=true&language=en':
'program02.json',
'https://spark-prod-gb.gnp.cloud.virgintvgo.virginmedia.com/eng/web/linear-service/v2/replayEvent/crid:~~2F~~2Fgn.tv~~2F19221598~~2FSH037146530000~~2F333458689,imi:f1060b3f63cd5399e0f97901b25a85ef71097891?returnLinearContent=true&forceLinearResponse=true&language=en':
- 'program03.json',
+ 'program03.json'
}
let data = ''
if (urls[url] !== undefined) {
@@ -50,16 +50,16 @@ it('can generate valid url', () => {
)
})
-it('can parse response', async() => {
- const content = await axios.get(url({ date }))
+it('can parse response', async () => {
+ const content = await axios
+ .get(url({ date }))
.then(response => response.data)
.catch(console.error)
- 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.length).toBe(3)
expect(result[0]).toMatchObject({
diff --git a/sites/visionplus.id/visionplus.id.config.js b/sites/visionplus.id/visionplus.id.config.js
index f2f5ca49..e4220ca4 100644
--- a/sites/visionplus.id/visionplus.id.config.js
+++ b/sites/visionplus.id/visionplus.id.config.js
@@ -13,11 +13,11 @@ module.exports = {
site: 'visionplus.id',
days: 2,
url({ date, channel }) {
- return `https://www.visionplus.id/managetv/tvinfo/events/schedule?language=${languages[channel.lang]}&serviceId=${channel.site_id}&start=${date.format(
- 'YYYY-MM-DD'
- )}T00%3A00%3A00Z&end=${date.add(1, 'd').format(
- 'YYYY-MM-DD'
- )}T00%3A00%3A00Z&view=cd-events-grid-view`
+ return `https://www.visionplus.id/managetv/tvinfo/events/schedule?language=${
+ languages[channel.lang]
+ }&serviceId=${channel.site_id}&start=${date.format('YYYY-MM-DD')}T00%3A00%3A00Z&end=${date
+ .add(1, 'd')
+ .format('YYYY-MM-DD')}T00%3A00%3A00Z&view=cd-events-grid-view`
},
parser({ content, channel }) {
const programs = []
@@ -26,7 +26,13 @@ module.exports = {
for (const ev of json.evs) {
if (ev.sid === channel.site_id) {
const title = ev.con && ev.con.loc ? ev.con.loc[0].tit : ev.con.oti
- const [, , season, , episode] = title.match(/( S(\d+))?(, Ep (\d+))/) || [null, null, null, null, null]
+ const [, , season, , episode] = title.match(/( S(\d+))?(, Ep (\d+))/) || [
+ null,
+ null,
+ null,
+ null,
+ null
+ ]
programs.push({
title,
description: ev.con && ev.con.loc ? ev.con.loc[0].syn : null,
diff --git a/sites/visionplus.id/visionplus.id.test.js b/sites/visionplus.id/visionplus.id.test.js
index 99b1398c..f71f7c6f 100644
--- a/sites/visionplus.id/visionplus.id.test.js
+++ b/sites/visionplus.id/visionplus.id.test.js
@@ -16,7 +16,7 @@ const channel = {
xmltv_id: 'AXN.id',
lang: 'en'
}
-const channelId = { ...channel, lang: 'id' }
+const channelId = { ...channel, lang: 'id' }
it('can generate valid url', () => {
expect(url({ channel, date })).toBe(
@@ -29,37 +29,37 @@ it('can generate valid url', () => {
it('can parse response', () => {
let content = fs.readFileSync(path.resolve(__dirname, '__data__/content_en.json'))
- let results = parser({ content, channel, date })
- .map(p => {
- p.start = p.start.toJSON()
- p.stop = p.stop.toJSON()
- return p
- })
+ let results = parser({ content, channel, date }).map(p => {
+ p.start = p.start.toJSON()
+ p.stop = p.stop.toJSON()
+ return p
+ })
expect(results.length).toBe(1)
expect(results[0]).toMatchObject({
start: '2024-11-23T23:30:00.000Z',
stop: '2024-11-24T00:15:00.000Z',
title: 'FBI: Most Wanted S4, Ep 18',
- description: 'After two agents from the Bureau of Land Management go missing while executing a land seizure warrant in Wyoming, the Fugitive Task Force heads west to track them down in an unwelcoming county.',
+ description:
+ 'After two agents from the Bureau of Land Management go missing while executing a land seizure warrant in Wyoming, the Fugitive Task Force heads west to track them down in an unwelcoming county.',
season: 4,
episode: 18
})
content = fs.readFileSync(path.resolve(__dirname, '__data__/content_id.json'))
- results = parser({ content, channel: channelId, date })
- .map(p => {
- p.start = p.start.toJSON()
- p.stop = p.stop.toJSON()
- return p
- })
+ results = parser({ content, channel: channelId, date }).map(p => {
+ p.start = p.start.toJSON()
+ p.stop = p.stop.toJSON()
+ return p
+ })
expect(results.length).toBe(1)
expect(results[0]).toMatchObject({
start: '2024-11-23T23:30:00.000Z',
stop: '2024-11-24T00:15:00.000Z',
title: 'FBI: Most Wanted S4, Ep 18',
- description: 'Satgas Buronan pergi ke wilayah barat untuk melacak keberadaan dua petugas Biro Pengelolaan Lahan yang menghilang saat menjalankan perintah penyitaan lahan di negara bagian yang tak ramah, Wyoming.',
+ description:
+ 'Satgas Buronan pergi ke wilayah barat untuk melacak keberadaan dua petugas Biro Pengelolaan Lahan yang menghilang saat menjalankan perintah penyitaan lahan di negara bagian yang tak ramah, Wyoming.',
season: 4,
episode: 18
})
diff --git a/sites/watch.sportsnet.ca/watch.sportsnet.ca.config.js b/sites/watch.sportsnet.ca/watch.sportsnet.ca.config.js
index 88e3db99..a3e956e9 100644
--- a/sites/watch.sportsnet.ca/watch.sportsnet.ca.config.js
+++ b/sites/watch.sportsnet.ca/watch.sportsnet.ca.config.js
@@ -29,11 +29,11 @@ module.exports = {
async channels() {
const axios = require('axios')
const html = await axios
- .get(`https://watch.sportsnet.ca/schedule/tvlistings`)
+ .get('https://watch.sportsnet.ca/schedule/tvlistings')
.then(r => r.data)
.catch(console.log)
- let [, __data] = html.match(/window\.__data \= ([^<]+)<\/script>/)
+ let [, __data] = html.match(/window\.__data = ([^<]+)<\/script>/)
const func = new Function(`"use strict";return ${__data}`)
const data = func()
diff --git a/sites/web.magentatv.de/web.magentatv.de.config.js b/sites/web.magentatv.de/web.magentatv.de.config.js
index b5ecbaa2..722ef2a5 100644
--- a/sites/web.magentatv.de/web.magentatv.de.config.js
+++ b/sites/web.magentatv.de/web.magentatv.de.config.js
@@ -30,7 +30,8 @@ module.exports = {
offset: 0,
properties: [
{
- include: 'endtime,genres,id,name,starttime,channelid,pictures,introduce,subName,seasonNum,subNum,cast,country,producedate,externalIds',
+ include:
+ 'endtime,genres,id,name,starttime,channelid,pictures,introduce,subName,seasonNum,subNum,cast,country,producedate,externalIds',
name: 'playbill'
}
],
@@ -113,15 +114,15 @@ function parseCategory(item) {
}
function parseDirectors(item) {
- if (!item.cast || !item.cast.director) return [];
+ if (!item.cast || !item.cast.director) return []
return item.cast.director
.replace('und', ',')
.split(',')
- .map(i => i.trim());
+ .map(i => i.trim())
}
function parseProducers(item) {
- if (!item.cast || !item.cast.producer) return [];
+ if (!item.cast || !item.cast.producer) return []
return item.cast.producer
.replace('und', ',')
.split(',')
@@ -129,7 +130,7 @@ function parseProducers(item) {
}
function parseAdapters(item) {
- if (!item.cast || !item.cast.adaptor) return [];
+ if (!item.cast || !item.cast.adaptor) return []
return item.cast.adaptor
.replace('und', ',')
.split(',')
@@ -138,7 +139,7 @@ function parseAdapters(item) {
function parseUrls(item) {
// currently only a imdb id is returned by the api, thus we can construct the url here
- if (!item.externalIds) return [];
+ if (!item.externalIds) return []
return JSON.parse(item.externalIds)
.filter(externalId => externalId.type === 'imdb' && externalId.id)
.map(externalId => ({ system: 'imdb', value: `https://www.imdb.com/title/${externalId.id}` }))
diff --git a/sites/web.magentatv.de/web.magentatv.de.test.js b/sites/web.magentatv.de/web.magentatv.de.test.js
index 935b0828..95332580 100644
--- a/sites/web.magentatv.de/web.magentatv.de.test.js
+++ b/sites/web.magentatv.de/web.magentatv.de.test.js
@@ -41,7 +41,8 @@ it('can generate valid request data', () => {
offset: 0,
properties: [
{
- include: 'endtime,genres,id,name,starttime,channelid,pictures,introduce,subName,seasonNum,subNum,cast,country,producedate,externalIds',
+ include:
+ 'endtime,genres,id,name,starttime,channelid,pictures,introduce,subName,seasonNum,subNum,cast,country,producedate,externalIds',
name: 'playbill'
}
],
@@ -78,20 +79,27 @@ it('can parse response', () => {
sub_title: 'Tritte unter dem Tisch',
description:
'Amy arbeitet für eine Weile in Sheldons Universität, er freut sich darüber, doch sie warnt ihn, dass sie sich jetzt häufiger zu Gesicht bekommen. Als Leonard, Sheldon, Raj und Howard zusammen sitzen, diskutieren sie darüber. Sheldon lässt auf sich einreden und informiert Amy, dass er ein Problem mit ihr auf seiner Arbeit hat. Sie ist enttäuscht, während Bernadette mit Howard darüber spricht, warum er auf Sheldon eingeredet hat.',
- season: "7",
- episode: "5",
+ season: '7',
+ episode: '5',
image:
'http://ngiss.t-online.de/cm1s/media/gracenote/1/0/p10262968_e_h9_ah_2021-10-20T07_16_16.jpg',
category: ['Sitcom'],
- directors: ["Mark Cendrowski"],
- producers: ["Chuck Lorre","Bill Prady","Steven Molaro"],
- adapters: ["Steven Molaro","Steve Holland","Maria Ferrari","Chuck Lorre","Eric Kaplan","Jim Reynolds"],
+ directors: ['Mark Cendrowski'],
+ producers: ['Chuck Lorre', 'Bill Prady', 'Steven Molaro'],
+ adapters: [
+ 'Steven Molaro',
+ 'Steve Holland',
+ 'Maria Ferrari',
+ 'Chuck Lorre',
+ 'Eric Kaplan',
+ 'Jim Reynolds'
+ ],
country: 'US',
- date: "2013-01-01",
+ date: '2013-01-01',
urls: [
{
- system: "imdb",
- value: "https://www.imdb.com/title/tt0898266"
+ system: 'imdb',
+ value: 'https://www.imdb.com/title/tt0898266'
}
]
}
diff --git a/sites/winplay.co/winplay.co.config.js b/sites/winplay.co/winplay.co.config.js
index 39375208..831fecc7 100644
--- a/sites/winplay.co/winplay.co.config.js
+++ b/sites/winplay.co/winplay.co.config.js
@@ -1,4 +1,3 @@
-const axios = require('axios')
const dayjs = require('dayjs')
module.exports = {
diff --git a/sites/ziggogo.tv/ziggogo.tv.config.js b/sites/ziggogo.tv/ziggogo.tv.config.js
index 0de4cc63..480904dc 100644
--- a/sites/ziggogo.tv/ziggogo.tv.config.js
+++ b/sites/ziggogo.tv/ziggogo.tv.config.js
@@ -18,11 +18,9 @@ module.exports = {
}
},
url({ date, segment = 0 }) {
- return `https://static.spark.ziggogo.tv/eng/web/epg-service-lite/nl/en/events/segments/${
- date.format('YYYYMMDD')
- }${
- segment.toString().padStart(2, '0')
- }0000`
+ return `https://static.spark.ziggogo.tv/eng/web/epg-service-lite/nl/en/events/segments/${date.format(
+ 'YYYYMMDD'
+ )}${segment.toString().padStart(2, '0')}0000`
},
async parser({ content, channel, date }) {
const programs = []
@@ -31,9 +29,9 @@ module.exports = {
if (Array.isArray(items.entries)) {
// fetch other segments
const queues = [
- module.exports.url({ date, segment: 6}),
- module.exports.url({ date, segment: 12}),
- module.exports.url({ date, segment: 18}),
+ module.exports.url({ date, segment: 6 }),
+ module.exports.url({ date, segment: 12 }),
+ module.exports.url({ date, segment: 18 })
]
await doFetch(queues, (url, res) => {
if (Array.isArray(res.entries)) {
@@ -43,13 +41,12 @@ module.exports = {
items.entries
.filter(item => item.channelId === channel.site_id)
.forEach(item => {
- if (Array.isArray(item.events)){
+ if (Array.isArray(item.events)) {
if (detailedGuide) {
- queues.push(...item.events
- .map(event =>
- `https://spark-prod-nl.gnp.cloud.ziggogo.tv/eng/web/linear-service/v2/replayEvent/${
- event.id
- }?returnLinearContent=true&forceLinearResponse=true&language=nl`
+ queues.push(
+ ...item.events.map(
+ event =>
+ `https://spark-prod-nl.gnp.cloud.ziggogo.tv/eng/web/linear-service/v2/replayEvent/${event.id}?returnLinearContent=true&forceLinearResponse=true&language=nl`
)
)
} else {
@@ -92,20 +89,23 @@ module.exports = {
const channels = []
const axios = require('axios')
const res = await axios
- .get('https://spark-prod-nl.gnp.cloud.ziggogo.tv/eng/web/linear-service/v2/channels?cityId=65535&language=en&productClass=Orion-DASH&platform=web')
+ .get(
+ 'https://spark-prod-nl.gnp.cloud.ziggogo.tv/eng/web/linear-service/v2/channels?cityId=65535&language=en&productClass=Orion-DASH&platform=web'
+ )
.then(r => r.data)
.catch(console.error)
if (Array.isArray(res)) {
- channels.push(...res
- .filter(item => !item.isHidden)
- .map(item => {
- return {
- lang: 'nl',
- site_id: item.id,
- name: item.name
- }
- })
+ channels.push(
+ ...res
+ .filter(item => !item.isHidden)
+ .map(item => {
+ return {
+ lang: 'nl',
+ site_id: item.id,
+ name: item.name
+ }
+ })
)
}
diff --git a/sites/ziggogo.tv/ziggogo.tv.test.js b/sites/ziggogo.tv/ziggogo.tv.test.js
index e4d9aef1..bfc5b2d4 100644
--- a/sites/ziggogo.tv/ziggogo.tv.test.js
+++ b/sites/ziggogo.tv/ziggogo.tv.test.js
@@ -32,7 +32,7 @@ axios.get.mockImplementation(url => {
'https://spark-prod-nl.gnp.cloud.ziggogo.tv/eng/web/linear-service/v2/replayEvent/crid:~~2F~~2Fgn.tv~~2F28842707~~2FEP022675661065,imi:33138a61bfa639696f386a5b8da9052e98cffdf8?returnLinearContent=true&forceLinearResponse=true&language=nl':
'program02.json',
'https://spark-prod-nl.gnp.cloud.ziggogo.tv/eng/web/linear-service/v2/replayEvent/crid:~~2F~~2Fgn.tv~~2F28728829~~2FEP052397600066,imi:34a0b026912de96e3546b15ad2983070a250dfd5?returnLinearContent=true&forceLinearResponse=true&language=nl':
- 'program03.json',
+ 'program03.json'
}
let data = ''
if (urls[url] !== undefined) {
@@ -51,15 +51,15 @@ it('can generate valid url', () => {
})
it('can parse response', async () => {
- const content = await axios.get(url({ date }))
+ const content = await axios
+ .get(url({ date }))
.then(response => response.data)
.catch(console.error)
- 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.length).toBe(3)
expect(result[0]).toMatchObject({
@@ -91,11 +91,7 @@ it('can parse response', async () => {
category: ['Talkshow'],
season: 1,
episode: 65,
- actor: [
- 'Sophie Hilbrand',
- 'Jeroen Pauw',
- 'Tim de Wit'
- ]
+ actor: ['Sophie Hilbrand', 'Jeroen Pauw', 'Tim de Wit']
})
})