From 29ab6b0d6420a81f27a708f614adc295dbb86232 Mon Sep 17 00:00:00 2001 From: freearhey <7253922+freearhey@users.noreply.github.com> Date: Thu, 16 Jan 2025 23:40:45 +0300 Subject: [PATCH 1/7] Fix linter issues --- sites/rikstv.no/readme.md | 42 +++---- sites/rikstv.no/rikstv.no.channels.xml | 166 ++++++++++++------------- sites/rikstv.no/rikstv.no.config.js | 148 +++++++++++----------- sites/rikstv.no/rikstv.no.test.js | 138 ++++++++++---------- 4 files changed, 252 insertions(+), 242 deletions(-) diff --git a/sites/rikstv.no/readme.md b/sites/rikstv.no/readme.md index 31eb0b38..463a3282 100644 --- a/sites/rikstv.no/readme.md +++ b/sites/rikstv.no/readme.md @@ -1,21 +1,21 @@ -# rikstv.no - -https://play.rikstv.no/tv-guide - -### Download the guide - -```sh -npm run grab --- --site=rikstv.no -``` - -### Update channel list - -```sh -npm run channels:parse --- --config=./sites/rikstv.no/rikstv.no.config.js --output=./sites/rikstv.no/rikstv.no.channels.xml -``` - -### Test - -```sh -npm test --- rikstv.no -``` +# rikstv.no + +https://play.rikstv.no/tv-guide + +### Download the guide + +```sh +npm run grab --- --site=rikstv.no +``` + +### Update channel list + +```sh +npm run channels:parse --- --config=./sites/rikstv.no/rikstv.no.config.js --output=./sites/rikstv.no/rikstv.no.channels.xml +``` + +### Test + +```sh +npm test --- rikstv.no +``` diff --git a/sites/rikstv.no/rikstv.no.channels.xml b/sites/rikstv.no/rikstv.no.channels.xml index 96aebc97..8e9e46c9 100644 --- a/sites/rikstv.no/rikstv.no.channels.xml +++ b/sites/rikstv.no/rikstv.no.channels.xml @@ -1,83 +1,83 @@ - - - BBC News - Discovery - TLC - Disney Channel - Eurosport 1 - FEM - Frikanalen - REX - National Geographic - NRK Super/3 - NRK1 - NRK1 Tegnspråk - NRK2 - SVT1 - TV 2 Livsstil - TV 2 Direkte - TV 2 Nyheter - TV 2 Zebra - TV3 - TVNorge - TV3+ - Visjon Norge - VOX - Animal Planet - BBC Nordic - TV6 - History Channel - Eurosport Norge - Nick Jr. - Nickelodeon - TV 2 Danmark - DR2 - DR1 - SVT2 - TV4 - CNN - Discovery Science - Investigation Discovery - Norway Live - V Sport + - V Sport 1 - V Sport 2 - V Sport 3 - Hits - Stars - SF-kanalen - TV 2 Sport 1 - TV 2 Sport 2 - Sky News - CNBC - Deutsche Welle - France 24 - NRK1 Sørlandet - NRK1 Nordland - NRK1 Midtnytt - NRK1 Vestfold og Telemark - NRK1 Vestlandsrevyen - NRK1 Nordnytt - NRK1 Innlandet - MTV00s - TV Nord - Travel Channel - Food Network - Euronews - Auto Motor og Sport TV - Rikstoto Direkte - TV Øst - NRK1 Rogaland - NRK1 Møre og Romsdal - NRK1 Lydtekst - NRK2 Lydtekst - NRK3 Super Lydtekst - Heim TV - V sport golf - NRK1 Underteksting - NRK2 Underteksting - Naturkanal1 - V Film Action - V Film Premiere - V Series - + + + BBC News + Discovery + TLC + Disney Channel + Eurosport 1 + FEM + Frikanalen + REX + National Geographic + NRK Super/3 + NRK1 + NRK1 Tegnspråk + NRK2 + SVT1 + TV 2 Livsstil + TV 2 Direkte + TV 2 Nyheter + TV 2 Zebra + TV3 + TVNorge + TV3+ + Visjon Norge + VOX + Animal Planet + BBC Nordic + TV6 + History Channel + Eurosport Norge + Nick Jr. + Nickelodeon + TV 2 Danmark + DR2 + DR1 + SVT2 + TV4 + CNN + Discovery Science + Investigation Discovery + Norway Live + V Sport + + V Sport 1 + V Sport 2 + V Sport 3 + Hits + Stars + SF-kanalen + TV 2 Sport 1 + TV 2 Sport 2 + Sky News + CNBC + Deutsche Welle + France 24 + NRK1 Sørlandet + NRK1 Nordland + NRK1 Midtnytt + NRK1 Vestfold og Telemark + NRK1 Vestlandsrevyen + NRK1 Nordnytt + NRK1 Innlandet + MTV00s + TV Nord + Travel Channel + Food Network + Euronews + Auto Motor og Sport TV + Rikstoto Direkte + TV Øst + NRK1 Rogaland + NRK1 Møre og Romsdal + NRK1 Lydtekst + NRK2 Lydtekst + NRK3 Super Lydtekst + Heim TV + V sport golf + NRK1 Underteksting + NRK2 Underteksting + Naturkanal1 + V Film Action + V Film Premiere + V Series + diff --git a/sites/rikstv.no/rikstv.no.config.js b/sites/rikstv.no/rikstv.no.config.js index 29c64be7..b897473b 100644 --- a/sites/rikstv.no/rikstv.no.config.js +++ b/sites/rikstv.no/rikstv.no.config.js @@ -1,72 +1,76 @@ -const dayjs = require('dayjs') -const utc = require('dayjs/plugin/utc') -const axios = require('axios') - -dayjs.extend(utc) - -module.exports = { - site: 'rikstv.no', - days: 3, - request: { - cache: { - ttl: 60 * 60 * 1000 // 1 hour - } - }, - url({ channel, date }) { - return `https://play.rikstv.no/api/content-search/1/channel/${channel.site_id}/epg/${date.format('YYYY-MM-DD')}` - }, - parser: function ({ content }) { - let data - try { - data = JSON.parse(content) - } catch (error) { - console.error('Error parsing JSON:', error) - return [] - } - - const programs = [] - - if (data && Array.isArray(data)) { - data.forEach(item => { - if (!item) return - //const start = dayjs.utc(item.broadcastedTime) - //const stop = dayjs.utc(item.broadcastedTimeEnd) - - programs.push({ - title: item.seriesName, - sub_title: item.name, - description: item.description || item.synopsis, - season: item.season || null, - episode: item.episode || null, - category: item.genres, - actors: item.actors, - directors: item.director || item.directors, - icon: item.imagePackUri, - start: item.broadcastedTime, - stop: item.broadcastedTimeEnd - }) - }) - } - - return programs - }, - async channels() { - try { - const response = await axios.get('https://play.rikstv.no/api/content-search/1/channel?includePrograms=false') - if (!response.data || !Array.isArray(response.data)) { - console.error('Error: No channels data found') - return [] - } - return response.data.map(item => { - return { - lang: 'no', - site_id: item.channelId, - name: item.serviceName - } - }) - } catch (error) { - console.error('Error fetching channels:', error) - return [] - } - } -} +const dayjs = require('dayjs') +const utc = require('dayjs/plugin/utc') +const axios = require('axios') + +dayjs.extend(utc) + +module.exports = { + site: 'rikstv.no', + days: 3, + request: { + cache: { + ttl: 60 * 60 * 1000 // 1 hour + } + }, + url({ channel, date }) { + return `https://play.rikstv.no/api/content-search/1/channel/${ + channel.site_id + }/epg/${date.format('YYYY-MM-DD')}` + }, + parser: function ({ content }) { + let data + try { + data = JSON.parse(content) + } catch (error) { + console.error('Error parsing JSON:', error) + return [] + } + + const programs = [] + + if (data && Array.isArray(data)) { + data.forEach(item => { + if (!item) return + //const start = dayjs.utc(item.broadcastedTime) + //const stop = dayjs.utc(item.broadcastedTimeEnd) + + programs.push({ + title: item.seriesName, + sub_title: item.name, + description: item.description || item.synopsis, + season: item.season || null, + episode: item.episode || null, + category: item.genres, + actors: item.actors, + directors: item.director || item.directors, + icon: item.imagePackUri, + start: item.broadcastedTime, + stop: item.broadcastedTimeEnd + }) + }) + } + + return programs + }, + async channels() { + try { + const response = await axios.get( + 'https://play.rikstv.no/api/content-search/1/channel?includePrograms=false' + ) + if (!response.data || !Array.isArray(response.data)) { + console.error('Error: No channels data found') + return [] + } + return response.data.map(item => { + return { + lang: 'no', + site_id: item.channelId, + name: item.serviceName + } + }) + } catch (error) { + console.error('Error fetching channels:', error) + return [] + } + } +} diff --git a/sites/rikstv.no/rikstv.no.test.js b/sites/rikstv.no/rikstv.no.test.js index b37143e2..ce0f0959 100644 --- a/sites/rikstv.no/rikstv.no.test.js +++ b/sites/rikstv.no/rikstv.no.test.js @@ -1,66 +1,72 @@ -const { parser, url } = require('./rikstv.no.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('2025-01-14', 'YYYY-MM-DD').startOf('d') -const channel = { - site_id: '47', - xmltv_id: 'NRK1.no' -} - -describe('rikstv.no Module Tests', () => { - it('can generate valid url', () => { - expect(url({ date, channel })).toBe(`https://play.rikstv.no/api/content-search/1/channel/${channel.site_id}/epg/${date.format('YYYY-MM-DD')}`) - }) - - it('can parse response', () => { - const content = JSON.stringify([ - { - seriesName: 'Vakre og ville Oman', - name: 'Vakre og ville Oman', - description: 'Oman er eit arabisk skattkammer av unike habitat og variert dyreliv. Rev, kvalhai, reptil og skjelpadder er blant skapningane du finn her.', - season: 1, - episode: 1, - genres: ['Dokumentar', 'Fakta', 'Natur'], - actors: ['Gergana Muskalla'], - director: 'Stefania Muller', - imagePackUri: 'https://imageservice.rikstv.no/hash/EC206C374F42287C0BDF850A7D3CB4D3.jpg', - broadcastedTime: '2025-01-13T23:00:00Z', - broadcastedTimeEnd: '2025-01-13T23:55:00Z' - } - ]) - - const result = parser({ content }).map(p => { - p.start = dayjs(p.start).toISOString() - p.stop = dayjs(p.stop).toISOString() - return p - }) - - expect(result).toMatchObject([ - { - title: 'Vakre og ville Oman', - sub_title: 'Vakre og ville Oman', - description: 'Oman er eit arabisk skattkammer av unike habitat og variert dyreliv. Rev, kvalhai, reptil og skjelpadder er blant skapningane du finn her.', - season: 1, - episode: 1, - category: ['Dokumentar', 'Fakta', 'Natur'], - actors: ['Gergana Muskalla'], - directors: 'Stefania Muller', - icon: 'https://imageservice.rikstv.no/hash/EC206C374F42287C0BDF850A7D3CB4D3.jpg', - start: '2025-01-13T23:00:00.000Z', - stop: '2025-01-13T23:55:00.000Z' - } - ]) - }) - - it('can handle empty guide', () => { - const result = parser({ - content: '[]' - }) - expect(result).toMatchObject([]) - }) -}) +const { parser, url } = require('./rikstv.no.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('2025-01-14', 'YYYY-MM-DD').startOf('d') +const channel = { + site_id: '47', + xmltv_id: 'NRK1.no' +} + +describe('rikstv.no Module Tests', () => { + it('can generate valid url', () => { + expect(url({ date, channel })).toBe( + `https://play.rikstv.no/api/content-search/1/channel/${channel.site_id}/epg/${date.format( + 'YYYY-MM-DD' + )}` + ) + }) + + it('can parse response', () => { + const content = JSON.stringify([ + { + seriesName: 'Vakre og ville Oman', + name: 'Vakre og ville Oman', + description: + 'Oman er eit arabisk skattkammer av unike habitat og variert dyreliv. Rev, kvalhai, reptil og skjelpadder er blant skapningane du finn her.', + season: 1, + episode: 1, + genres: ['Dokumentar', 'Fakta', 'Natur'], + actors: ['Gergana Muskalla'], + director: 'Stefania Muller', + imagePackUri: 'https://imageservice.rikstv.no/hash/EC206C374F42287C0BDF850A7D3CB4D3.jpg', + broadcastedTime: '2025-01-13T23:00:00Z', + broadcastedTimeEnd: '2025-01-13T23:55:00Z' + } + ]) + + const result = parser({ content }).map(p => { + p.start = dayjs(p.start).toISOString() + p.stop = dayjs(p.stop).toISOString() + return p + }) + + expect(result).toMatchObject([ + { + title: 'Vakre og ville Oman', + sub_title: 'Vakre og ville Oman', + description: + 'Oman er eit arabisk skattkammer av unike habitat og variert dyreliv. Rev, kvalhai, reptil og skjelpadder er blant skapningane du finn her.', + season: 1, + episode: 1, + category: ['Dokumentar', 'Fakta', 'Natur'], + actors: ['Gergana Muskalla'], + directors: 'Stefania Muller', + icon: 'https://imageservice.rikstv.no/hash/EC206C374F42287C0BDF850A7D3CB4D3.jpg', + start: '2025-01-13T23:00:00.000Z', + stop: '2025-01-13T23:55:00.000Z' + } + ]) + }) + + it('can handle empty guide', () => { + const result = parser({ + content: '[]' + }) + expect(result).toMatchObject([]) + }) +}) From 2c5d68812e8d5f9cb4c106e71f1b7322d0c93dc5 Mon Sep 17 00:00:00 2001 From: freearhey <7253922+freearhey@users.noreply.github.com> Date: Thu, 16 Jan 2025 23:40:59 +0300 Subject: [PATCH 2/7] Create content.html --- sites/thesportplus.com/__data__/content.html | 223 +++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 sites/thesportplus.com/__data__/content.html diff --git a/sites/thesportplus.com/__data__/content.html b/sites/thesportplus.com/__data__/content.html new file mode 100644 index 00000000..42666219 --- /dev/null +++ b/sites/thesportplus.com/__data__/content.html @@ -0,0 +1,223 @@ + + + + + + + Sport Plus + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ Sport Plus U.S.A. +

Sport Plus U.S.A.

+ +
+
+ « + + SUN 19/01 + + » +
+ +
+
+ +
*New York time
+ +
+

01:00

+
ASTERAS vs ATROMITOS
+

Super League Season 24-25 MD 4

+
+ +
+

03:00

+
KALLITHEA vs VOLOS
+

Super League Season 24-25 MD 19

+
+ +
+

05:00

+
OLYMPIACOS vs MAROUSI
+

Greek Basket League 24-25 GD 11

+
+ +
+

07:00

+
PURE ACTION
+

Extreme Sports

+
+ +
+

08:00

+
ATROMITOS vs OLYMPIACOS LIVE
+

Super League Season 24-25 MD 19

+
+ +
+

10:00

+
LEVADIAKOS vs ASTERAS
+

Super League Season 24-25 MD 19

+
+ +
+

12:00

+
ARIS vs PAOK LIVE
+

Super League Season 24-25 MD 19

+
+ +
+

15:00

+
AEK vs PAOK
+

Greek Basket League 24-25 GD 15

+
+ +
+

14:00

+
PURE ACTION
+

Extreme Sports

+
+ +
+

17:00

+
SPORTSHOW
+

Super League

+
+ +
+

19:00

+
ATROMITOS vs OLYMPIACOS
+

Super League Season 24-25 MD 19

+
+ +
+

21:00

+
ARIS vs PAOK
+

Super League Season 24-25 MD 19

+
+ +
+

23:00

+
SPORTSHOW
+

Super League

+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + From 2915e93408252bacd599941007f734624c777479 Mon Sep 17 00:00:00 2001 From: freearhey <7253922+freearhey@users.noreply.github.com> Date: Thu, 16 Jan 2025 23:41:14 +0300 Subject: [PATCH 3/7] Create no_content.html --- .../thesportplus.com/__data__/no_content.html | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 sites/thesportplus.com/__data__/no_content.html diff --git a/sites/thesportplus.com/__data__/no_content.html b/sites/thesportplus.com/__data__/no_content.html new file mode 100644 index 00000000..976553d2 --- /dev/null +++ b/sites/thesportplus.com/__data__/no_content.html @@ -0,0 +1,145 @@ + + + + + + + Sport Plus + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ Sport Plus U.S.A. +

Sport Plus U.S.A.

+ +
+
+ « + + MON 19/01 + + » +
+ +
+
+ +
*New York time
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + From b85abb28850d69a6510b0f4ba6a36ffd8316c0fb Mon Sep 17 00:00:00 2001 From: freearhey <7253922+freearhey@users.noreply.github.com> Date: Thu, 16 Jan 2025 23:41:57 +0300 Subject: [PATCH 4/7] Create thesportplus.com.test.js --- .../thesportplus.com/thesportplus.com.test.js | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 sites/thesportplus.com/thesportplus.com.test.js diff --git a/sites/thesportplus.com/thesportplus.com.test.js b/sites/thesportplus.com/thesportplus.com.test.js new file mode 100644 index 00000000..ed431fda --- /dev/null +++ b/sites/thesportplus.com/thesportplus.com.test.js @@ -0,0 +1,50 @@ +const { parser, url } = require('./thesportplus.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('2025-01-19', 'YYYY-MM-DD').startOf('d') +const channel = { + site_id: 'usa', + xmltv_id: 'SportPlusUSA.us' +} + +it('can generate valid url', () => { + expect(url({ channel, date })).toBe('https://www.thesportplus.com/schedule_usa.php?d=2025-01-19') +}) + +it('can parse response', () => { + const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.html')) + const results = parser({ content, date, channel }).map(p => { + p.start = p.start.toJSON() + p.stop = p.stop.toJSON() + return p + }) + + expect(results.length).toBe(13) + expect(results[0]).toMatchObject({ + start: '2025-01-19T06:00:00.000Z', + stop: '2025-01-19T08:00:00.000Z', + title: 'ASTERAS vs ATROMITOS', + description: 'Super League Season 24-25 MD 4' + }) + expect(results[12]).toMatchObject({ + start: '2025-01-20T04:00:00.000Z', + stop: '2025-01-20T05:00:00.000Z', + title: 'SPORTSHOW', + description: 'Super League' + }) +}) + +it('can handle empty guide', () => { + const results = parser({ + date, + channel, + content: fs.readFileSync(path.resolve(__dirname, '__data__/no_content.html')) + }) + expect(results).toMatchObject([]) +}) From 506c7fd18edd751149649a8556dc37b9dae76861 Mon Sep 17 00:00:00 2001 From: freearhey <7253922+freearhey@users.noreply.github.com> Date: Thu, 16 Jan 2025 23:42:10 +0300 Subject: [PATCH 5/7] Create thesportplus.com.config.js --- .../thesportplus.com.config.js | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 sites/thesportplus.com/thesportplus.com.config.js diff --git a/sites/thesportplus.com/thesportplus.com.config.js b/sites/thesportplus.com/thesportplus.com.config.js new file mode 100644 index 00000000..dd48e5e2 --- /dev/null +++ b/sites/thesportplus.com/thesportplus.com.config.js @@ -0,0 +1,73 @@ +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) + +const timezones = { + usa: 'America/New_York', + aus: 'Australia/Sydney', + euro: 'UTC' +} + +module.exports = { + site: 'thesportplus.com', + days: 2, + url({ channel, date }) { + return `https://www.thesportplus.com/schedule_${channel.site_id}.php?d=${date.format( + 'YYYY-MM-DD' + )}` + }, + parser({ content, date, channel }) { + const programs = [] + const items = parseItems(content) + items.forEach(item => { + const $item = cheerio.load(item) + const prev = programs[programs.length - 1] + let start = parseStart($item, date, channel) + if (!start) return + if (prev) { + if (start.isBefore(prev.start) && start.hour() < 12) { + start = start.add(1, 'd') + date = date.add(1, 'd') + } + prev.stop = start + } + const stop = start.add(1, 'h') + programs.push({ + title: parseTitle($item), + description: parseDescription($item), + start, + stop + }) + }) + + return programs + } +} + +function parseTitle($item) { + return $item('h5:last').text().trim() +} + +function parseDescription($item) { + return $item('p').text().trim() +} + +function parseStart($item, date, channel) { + const timezone = timezones[channel.site_id] + const time = $item('h4').text().trim() + const dateString = `${date.format('YYYY-MM-DD')} ${time}` + + return dayjs.tz(dateString, 'YYYY-MM-DD HH:mm', timezone) +} + +function parseItems(content) { + const $ = cheerio.load(content) + + return $('.resume-item').toArray() +} From 2434bd2dc92d18b9859952f10e76ea6b720bf679 Mon Sep 17 00:00:00 2001 From: freearhey <7253922+freearhey@users.noreply.github.com> Date: Thu, 16 Jan 2025 23:42:28 +0300 Subject: [PATCH 6/7] Create thesportplus.com.channels.xml --- sites/thesportplus.com/thesportplus.com.channels.xml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 sites/thesportplus.com/thesportplus.com.channels.xml diff --git a/sites/thesportplus.com/thesportplus.com.channels.xml b/sites/thesportplus.com/thesportplus.com.channels.xml new file mode 100644 index 00000000..c2d560fc --- /dev/null +++ b/sites/thesportplus.com/thesportplus.com.channels.xml @@ -0,0 +1,6 @@ + + + Sport Plus U.S.A. + Sport Plus Australia + Sport Plus Europe + \ No newline at end of file From d1f96419ea4e32fc128c43d4d2808f79689b1900 Mon Sep 17 00:00:00 2001 From: freearhey <7253922+freearhey@users.noreply.github.com> Date: Thu, 16 Jan 2025 23:43:05 +0300 Subject: [PATCH 7/7] Create readme.md --- sites/thesportplus.com/readme.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 sites/thesportplus.com/readme.md diff --git a/sites/thesportplus.com/readme.md b/sites/thesportplus.com/readme.md new file mode 100644 index 00000000..a70f13c5 --- /dev/null +++ b/sites/thesportplus.com/readme.md @@ -0,0 +1,17 @@ +# thesportplus.com + +US: https://www.thesportplus.com/schedule_usa.php +Australia: https://www.thesportplus.com/schedule_aus.php +Europe: https://www.thesportplus.com/schedule_euro.php + +### Download the guide + +```sh +npm run grab --- --site=thesportplus.com +``` + +### Test + +```sh +npm test --- thesportplus.com +```