diff --git a/sites/arirang.com/__data__/detail.json b/sites/arirang.com/__data__/detail.json new file mode 100644 index 00000000..bf7ce091 --- /dev/null +++ b/sites/arirang.com/__data__/detail.json @@ -0,0 +1,187 @@ +{ + "resultCode": { + "code": 200000, + "http_status": 200, + "timestamp": 0, + "message": null, + "trace": null, + "access_token": null, + "expire_time": 0 + }, + "program_id": 173, + "order": 21, + "is_news_allow": true, + "bis_program": [ + { + "bis_program_code": "2023003T", + "bis_program_title": "WITHIN THE FRAME [L]" + }, + { + "bis_program_code": "2023004T", + "bis_program_title": "WITHIN THE FRAME [R]" + } + ], + "bis_bundle_program_code": "2023003T", + "bis_category_code": "시사보도", + "program_type": "tv", + "category_Info": [ + { + "category_id": 29, + "local": "en", + "title": "Current Affairs" + }, + { + "category_id": 29, + "local": "ko", + "title": "Current Affairs" + } + ], + "title": [ + { + "lan_code": "en", + "text": "WITHIN THE FRAME [L]" + }, + { + "lan_code": "ko", + "text": "WITHIN THE FRAME [L]" + } + ], + "content": [ + { + "lan_code": "en", + "text": "NEWS
" + }, + { + "lan_code": "ko", + "text": "NEWS 대담
" + } + ], + "property": { + "open_status": { + "is_allow": true, + "is_origin_allow": null, + "start_date": null, + "end_date": null + }, + "is_onair": true, + "is_teaser_allow": false, + "running_time": 30, + "schedule": [ + { + "week": [ + "Mon", + "Tue", + "Wed", + "Thu", + "Fri" + ], + "start_time": 1110 + }, + { + "week": [ + "" + ], + "start_time": -1 + }, + { + "week": [ + "" + ], + "start_time": -1 + }, + { + "week": [ + "" + ], + "start_time": -1 + }, + { + "week": [ + "" + ], + "start_time": -1 + }, + { + "week": [ + "" + ], + "start_time": -1 + }, + { + "week": [ + "" + ], + "start_time": -1 + }, + { + "week": [ + "" + ], + "start_time": -1 + }, + { + "week": [ + "" + ], + "start_time": -1 + }, + { + "week": [ + "" + ], + "start_time": -1 + } + ] + }, + "platform": { + "is_aos_allow": true, + "is_ios_allow": true, + "is_smat_tv_allow": true + }, + "image": [ + { + "order": 0, + "type": "horizontal", + "name": "2080840096998752900.png", + "action": null, + "url": "https://img.arirang.com/v1/AUTH_d52449c16d3b4bbca17d4fffd9fc44af/public/images/202308/2080840096998752900.png" + }, + { + "order": 0, + "type": "vertical", + "name": "1773516657138860509.png", + "action": null, + "url": "https://img.arirang.com/v1/AUTH_d52449c16d3b4bbca17d4fffd9fc44af/public/images/202301/1773516657138860509.png" + }, + { + "order": 0, + "type": "mobile", + "name": "1773516657893835229.png", + "action": null, + "url": "https://img.arirang.com/v1/AUTH_d52449c16d3b4bbca17d4fffd9fc44af/public/images/202301/1773516657893835229.png" + }, + { + "order": 0, + "type": "pc", + "name": "1773742773929771485.png", + "action": null, + "url": "https://img.arirang.com/v1/AUTH_d52449c16d3b4bbca17d4fffd9fc44af/public/images/202301/1773742773929771485.png" + }, + { + "order": 0, + "type": "smarttv", + "name": "1773742775607493085.png", + "action": null, + "url": "https://img.arirang.com/v1/AUTH_d52449c16d3b4bbca17d4fffd9fc44af/public/images/202301/1773742775607493085.png" + }, + { + "order": 0, + "type": "square", + "name": "1773742767839642077.png", + "action": null, + "url": "https://img.arirang.com/v1/AUTH_d52449c16d3b4bbca17d4fffd9fc44af/public/images/202301/1773742767839642077.png" + } + ], + "reg_date": "2023-01-03 10:21:56.0", + "update_date": "2023-08-03 10:55:34.0" +} \ No newline at end of file diff --git a/sites/arirang.com/__data__/schedule.json b/sites/arirang.com/__data__/schedule.json new file mode 100644 index 00000000..b6f620fa --- /dev/null +++ b/sites/arirang.com/__data__/schedule.json @@ -0,0 +1,93 @@ +{ + "resultCode": { + "code": 200000, + "http_status": 200, + "timestamp": 0, + "message": null, + "trace": null, + "access_token": null, + "expire_time": 0 + }, + "responseBody": { + "dsSchWeek": [ + { + "chanId": "CH_W", + "broadYmd": "20230825", + "planNo": 1, + "scheduleSeq": 1, + "broadHm": "0000", + "viewHm": "0000", + "broadRun": 30, + "timeGrade": "1", + "pgmCd": "2023004T", + "broadType": "R", + "displayNm": "WITHIN THE FRAME [R]", + "episodeNo": 4, + "episodeNm": "#4", + "displayEpisodeNm": null, + "partNo": 0, + "firstClf": "02", + "broadClf": "02", + "scheduleClf": "0", + "scheduleGrp": "01", + "videoClf": "H", + "audioClf": "0", + "liveClf": null, + "captionYn": "N", + "signLangYn": "N", + "dvsYn": "N", + "captionExceptClf": "N", + "signLangExceptClf": "N", + "dvsExceptClf": "N", + "delibGrade": "00", + "delibTopicYn": "N", + "delibLanguageYn": "N", + "delibCopyYn": "N", + "delibViolenceYn": "N", + "delibSexualYn": "N", + "infoGrade": "0+", + "episodeRun": null, + "bandCd": null, + "bandNm": null, + "keepYn": "N", + "firstYn": "N", + "addInfo": null, + "viewRating": null, + "scheduleColor": null, + "bgColor": null, + "bgColorR": null, + "bgColorG": null, + "bgColorB": null, + "textColorCd": null, + "textColorR": null, + "textColorG": null, + "textColorB": null, + "textColorHex": null, + "scheduleLineYn": "N", + "mediaInfo": null, + "regClf": "0", + "uuid": null, + "regUserId": "kylek", + "regDt": "20230816112556023", + "updUserId": "kylek", + "updDt": "20230817094411 ", + "weekDay": null, + "mtrlYn": null, + "timeGradeColor": null, + "timeGradeNm": "SA", + "broadClfNm": "재방", + "broadTypeNm": null, + "delibGradeNm": null, + "newsYn": "Y", + "bundlePgmCd": "2023003T", + "bundlePgmNm": "WITHIN THE FRAME", + "pgmOnm": "WITHIN THE FRAME [R]" + } + ], + "dmResult": { + "resultCode": "0", + "resultMsg": "success" + } + }, + "responseXML": null +} \ No newline at end of file diff --git a/sites/arirang.com/arirang.com.channels.xml b/sites/arirang.com/arirang.com.channels.xml new file mode 100644 index 00000000..140ab525 --- /dev/null +++ b/sites/arirang.com/arirang.com.channels.xml @@ -0,0 +1,8 @@ + + + + Arirang TV + Arirang UN + Arirang World + + \ No newline at end of file diff --git a/sites/arirang.com/arirang.com.config.js b/sites/arirang.com/arirang.com.config.js new file mode 100644 index 00000000..d0c133d5 --- /dev/null +++ b/sites/arirang.com/arirang.com.config.js @@ -0,0 +1,139 @@ +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: 'arirang.com', + output: 'arirang.com.guide.xml', + channels: 'arirang.com.channels.xml', + lang: 'en', + days: 7, + delay: 5000, + url: 'https://www.arirang.com/v1.0/open/external/proxy', + + request: { + method: 'POST', + timeout: 5000, + cache: { ttl: 60 * 60 * 1000 }, + headers: { + 'Accept': 'application/json, text/plain, */*', + 'Content-Type': 'application/json', + 'Origin': 'https://www.arirang.com', + 'Referer': 'https://www.arirang.com/schedule', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' + }, + data: function (context) { + const { channel, date } = context + return { + 'address': 'https://script.arirang.com/api/v1/bis/listScheduleV3.do', + 'method': 'POST', + 'headers': {}, + 'body': { + 'data': { + 'dmParam': { + 'chanId': channel.site_id, + 'broadYmd': dayjs.tz(date, 'Asia/Seoul').format('YYYYMMDD'), + 'planNo': '1' + } + } + } + } + } + }, + + logo: function (context) { + return context.channel.logo + }, + + async parser(context) { + const programs = [] + const items = parseItems(context.content) + + for (let item of items) { + const programDetail = await parseProgramDetail(item) + + programs.push({ + title: item.displayNm, + start: parseStart(item), + stop: parseStop(item), + icon: parseIcon(programDetail), + category: parseCategory(programDetail), + description: parseDescription(programDetail) + }) + } + + return programs + } +} + +function parseItems(content) { + if (content != '') { + const data = JSON.parse(content) + return (!data || !data.responseBody || !Array.isArray(data.responseBody.dsSchWeek)) ? [] : data.responseBody.dsSchWeek + } else { + return [] + } +} + +function parseStart(item) { + return dayjs.tz(item.broadYmd + ' ' + item.broadHm, 'YYYYMMDD HHmm', 'Asia/Seoul') +} + +function parseStop(item) { + return dayjs.tz(item.broadYmd + ' ' + item.broadHm, 'YYYYMMDD HHmm', 'Asia/Seoul').add(item.broadRun, 'minute') +} + +async function parseProgramDetail(item) { + return axios.post( + 'https://www.arirang.com/v1.0/open/program/detail', + { + 'bis_program_code': item.pgmCd + }, + { + headers: { + 'Accept': 'application/json, text/plain, */*', + 'Content-Type': 'application/json', + 'Origin': 'https://www.arirang.com', + 'Referer': 'https://www.arirang.com/schedule', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' + }, + timeout: 5000, + cache: { ttl: 60 * 1000 }, + } + ).then(function (response) { + return response.data + }).catch(function (error) { + // console.log(error) + }) +} + +function parseIcon(programDetail) { + if (programDetail && programDetail.image && programDetail.image[0].url) { + return programDetail.image[0].url + } else { + return '' + } +} + +function parseCategory(programDetail) { + if (programDetail && programDetail.category_Info && programDetail.category_Info[0].title) { + return programDetail.category_Info[0].title + } else { + return '' + } +} + +function parseDescription(programDetail) { + if (programDetail && programDetail.content && programDetail.content[0] && programDetail.content[0].text) { + let description = programDetail.content[0].text + let regex = /(<([^>]+)>)/ig + return description.replace(regex, '') + } else { + return '' + } +} diff --git a/sites/arirang.com/arirang.com.test.js b/sites/arirang.com/arirang.com.test.js new file mode 100644 index 00000000..f0d4d165 --- /dev/null +++ b/sites/arirang.com/arirang.com.test.js @@ -0,0 +1,59 @@ +// npx epg-grabber --config=sites/arirang.com/arirang.com.config.js --channels=sites/arirang.com/arirang.com.channels.xml --output=guide.xml --days=2 +// npx jest arirang.com.test.js + +const { url, parser } = require('./arirang.com.config.js') +const fs = require('fs') +const path = require('path') +const axios = require('axios') +const dayjs = require('dayjs') +const utc = require('dayjs/plugin/utc') +const { program } = require('commander') +dayjs.extend(utc) + +jest.mock('axios') + +const date = dayjs.tz('2023-08-25', 'Asia/Seoul').startOf('d') +const channel = { xmltv_id: 'ArirangWorld.kr', site_id: 'CH_W', name: 'Arirang World', lang: 'en', logo: 'https://i.imgur.com/5Aoithj.png' } +const content = fs.readFileSync(path.resolve(__dirname, '__data__/schedule.json'), 'utf8') +const programDetail = fs.readFileSync(path.resolve(__dirname, '__data__/detail.json'), 'utf8') +const context = { 'channel': channel, 'content': content, 'date': date } + +it('can generate valid url', () => { + expect(url).toBe('https://www.arirang.com/v1.0/open/external/proxy') +}) + +it('can handle empty guide', async () => { + const results = await parser({ 'channel': channel, 'content': '', 'date': date }) + expect(results).toMatchObject([]) +}) + +it('can parse response', async () => { + axios.post.mockImplementation((url, data) => { + if (url === 'https://www.arirang.com/v1.0/open/external/proxy' && JSON.stringify(data) === JSON.stringify({ "address": "https://script.arirang.com/api/v1/bis/listScheduleV3.do", "method": "POST", "headers": {}, "body": { "data": { "dmParam": { "chanId": "CH_W", "broadYmd": "20230825", "planNo": "1" } } } })) { + return Promise.resolve({ + data: JSON.parse(content) + }) + } else if (url === 'https://www.arirang.com/v1.0/open/program/detail' && JSON.stringify(data) === JSON.stringify({ "bis_program_code": "2023004T" })) { + return Promise.resolve({ + data: JSON.parse(programDetail) + }) + } else { + return Promise.resolve({ + data: '' + }) + } + }) + + const results = await parser(context) + + expect(results[0]).toMatchObject( + { + title: "WITHIN THE FRAME [R]", + start: dayjs.tz(date, 'Asia/Seoul'), + stop: dayjs.tz(date, 'Asia/Seoul').add(30, 'minute'), + icon: "https://img.arirang.com/v1/AUTH_d52449c16d3b4bbca17d4fffd9fc44af/public/images/202308/2080840096998752900.png", + description: "NEWS", + category: "Current Affairs" + } + ) +}) \ No newline at end of file diff --git a/sites/moji.id/moji.id.channels.xml b/sites/moji.id/moji.id.channels.xml new file mode 100644 index 00000000..5157482b --- /dev/null +++ b/sites/moji.id/moji.id.channels.xml @@ -0,0 +1,7 @@ + + + + Moji + + \ No newline at end of file diff --git a/sites/moji.id/moji.id.config.js b/sites/moji.id/moji.id.config.js new file mode 100644 index 00000000..b9c4ffe3 --- /dev/null +++ b/sites/moji.id/moji.id.config.js @@ -0,0 +1,104 @@ +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 currentYear = new Date().getFullYear() + +module.exports = { + site: 'moji.id', + days: 4, + output: 'moji.id.guide.xml', + channels: 'moji.id.channels.xml', + lang: 'en', + delay: 5000, + + url: function () { + return 'https://moji.id/schedule' + }, + + request: { + method: 'GET', + timeout: 5000, + cache: { ttl: 60 * 60 * 1000 }, + headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' } + }, + + logo: function (context) { + return context.channel.logo + }, + + parser: function (context) { + const programs = [] + const items = parseItems(context) + + items.forEach(function(item, i) { + programs.push({ + title: item.progTitle, + description: item.progDesc, + start: item.progStart, + stop: item.progStop + }) + }) + + return programs + } +} + +function parseItems(context) { + const $ = cheerio.load(context.content) + const schDayMonths = $('.date-slider .month').toArray() + const schPrograms = $('.desc-slider .list-slider').toArray() + const monthDate = dayjs(context.date).format('MMM DD') + const items = []; + + schDayMonths.forEach(function(schDayMonth, i) { + if (monthDate == $(schDayMonth).text()) { + let schDayPrograms = $(schPrograms[i]).find('.accordion').toArray() + schDayPrograms.forEach(function(program, i) { + let itemDay = { + progStart: parseStart(schDayMonth, program), + progStop: parseStop(schDayMonth, program, schDayPrograms[i+1]), + progTitle: parseTitle(program), + progDesc: parseDescription(program) + }; + items.push(itemDay) + }) + } + }) + + return items +} + +function parseTitle(item) { + return cheerio.load(item)('.name-prog').text() +} + +function parseDescription(item) { + return cheerio.load(item)('.content-acc span').text() +} + +function parseStart(schDayMonth, item) { + let monthDate = cheerio.load(schDayMonth).text().split(' ') + let startTime = cheerio.load(item)('.pkl').text() + let progStart = dayjs.tz(currentYear + ' ' + monthDate[0] + ' ' + monthDate[1] + ' ' + startTime, 'YYYY MMM DD HH:mm', 'Asia/Jakarta') + return progStart +} + +function parseStop(schDayMonth, itemCurrent, itemNext) { + let monthDate = cheerio.load(schDayMonth).text().split(' ') + + if (itemNext) { + let stopTime = cheerio.load(itemNext)('.pkl').text() + return dayjs.tz(currentYear + ' ' + monthDate[0] + ' ' + monthDate[1] + ' ' + stopTime, 'YYYY MMM DD HH:mm', 'Asia/Jakarta') + } + else + { + return dayjs.tz(currentYear + ' ' + monthDate[0] + ' ' + (parseInt(monthDate[1]) + 1).toString().padStart(2, '0') + ' 00:00', 'YYYY MMM DD HH:mm', 'Asia/Jakarta') + } +} \ No newline at end of file diff --git a/sites/moji.id/moji.id.test.js b/sites/moji.id/moji.id.test.js new file mode 100644 index 00000000..b579aa37 --- /dev/null +++ b/sites/moji.id/moji.id.test.js @@ -0,0 +1,39 @@ +// npx epg-grabber --config=sites/moji.id/moji.id.config.js --channels=sites/moji.id/moji.id.channels.xml --output=guide.xml --days=2 +// npx jest moji.id.test.js + +const { url, 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

FriAug 18
SatAug 19
SunAug 20
Jam TayangProgram
00:00TRUST
Informasi seputar menjaga vitalitas pria
00:302023 AVC CHALLENGE CUP FOR WOMEN (RECORDED)
India Vs. Vietnam
02:30ONE CHAMPIONSHIP 2021
Siaran laga-laga pertandingan tinju gaya bebas internasional. Meyuguhkan pertarungan sengit dari para petarung profeisional kelas dunia.
03:30VOLLEYBALL NATION'S LEAGUE 2023 (RECORDED)
TURKI vs BRAZIL
05:00MOJI SPORT
MOJI SPORT
06:15LIPUTAN 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:00UNGKAP
Liputan investigasi seputar berbagai topik dan peristiwa hangat serta kontroversial yang terjadi di Indonesia
08:00PIALA KAPOLRI 2023 PUTRI (LIVE)
PIALA KAPOLRI 2023 PUTRI (LIVE)
10:30SERIES PAGI
GANTENG GANTENG SERIGALA
12:30DIAM-DIAM SUKA
DIAM-DIAM SUKA
13:30PIALA KAPOLRI 2023 PUTRA (LIVE)
PIALA KAPOLRI 2023 PUTRA (LIVE)
16:00PIALA KAPOLRI 2023 PUTRI (LIVE)
PIALA KAPOLRI 2023 PUTRI (LIVE)
18:00PIALA KAPOLRI 2023 PUTRA (LIVE)
PIALA KAPOLRI 2023 PUTRA (LIVE)
20:00MOJI DRAMA (CHHOTI SARDARNI)
CHHOTI SARDARNI
21:30SINEMA MALAM (BIDADARI CANTIK DI RUMAH KOST)
(BIDADARI CANTIK DI RUMAH KOST
23:00TRUST
Informasi seputar menjaga vitalitas pria
23:30TRUST
Informasi seputar menjaga vitalitas pria
` + +const context = { + 'content': content, + 'date': date +} + +it('can generate valid url', () => { + expect(url({ channel, date })).toBe('https://moji.id/schedule') +}) + +it('can handle empty guide', () => { + const results = parser({ content: '' }) + expect(results).toMatchObject([]) +}) + +it('can parse response', () => { + const results = parser({ content: content, date: date }) + + expect(results[0]).toMatchObject( + { + title: 'TRUST', + start: dayjs.tz('2023 Aug 18 00:00', 'YYYY MMM DD HH:mm', 'Asia/Jakarta'), + stop: dayjs.tz('2023 Aug 18 00:30', 'YYYY MMM DD HH:mm', 'Asia/Jakarta'), + description: 'Informasi seputar menjaga vitalitas pria' + } + ) +}) \ No newline at end of file diff --git a/sites/taiwanplus.com/taiwanplus.com.channels.xml b/sites/taiwanplus.com/taiwanplus.com.channels.xml new file mode 100644 index 00000000..320a0ec0 --- /dev/null +++ b/sites/taiwanplus.com/taiwanplus.com.channels.xml @@ -0,0 +1,7 @@ + + + + Taiwan Plus TV + + \ No newline at end of file diff --git a/sites/taiwanplus.com/taiwanplus.com.config.js b/sites/taiwanplus.com/taiwanplus.com.config.js new file mode 100644 index 00000000..d8cb4896 --- /dev/null +++ b/sites/taiwanplus.com/taiwanplus.com.config.js @@ -0,0 +1,68 @@ +const dayjs = require('dayjs') +const utc = require('dayjs/plugin/utc') +const isSameOrAfter = require('dayjs/plugin/isSameOrAfter') +const isSameOrBefore = require('dayjs/plugin/isSameOrBefore') + +dayjs.extend(utc) +dayjs.extend(isSameOrAfter) +dayjs.extend(isSameOrBefore) + +module.exports = { + site: 'taiwanplus.com', + days: 7, + output: 'taiwanplus.com.guide.xml', + channels: 'taiwanplus.com.channels.xml', + lang: 'en', + delay: 5000, + + url: function () { + return 'https://www.taiwanplus.com/api/video/live/schedule/0' + }, + + request: { + method: 'GET', + timeout: 5000, + cache: { ttl: 60 * 60 * 1000 }, // 60 * 60 seconds = 1 hour + headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' } + }, + + logo: function (context) { + return context.channel.logo + }, + + parser: function (context) { + const programs = [] + const scheduleDates = parseItems(context.content) + const today = dayjs.utc(context.date).startOf('day') + const lastDay = today.add(1, 'day') + + for(let scheduleDate of scheduleDates) { + const currentScheduleDate = new dayjs.utc(scheduleDate.date, 'YYYY/MM/DD') + + if (currentScheduleDate.isSame(today)) { + scheduleDate.schedule.forEach(function(program, i) { + programs.push({ + title: program.title, + start: dayjs.utc(program.dateTime, 'YYYY/MM/DD HH:mm'), + stop: (i != (scheduleDate.schedule.length - 1)) ? dayjs.utc(scheduleDate.schedule[i+1].dateTime, 'YYYY/MM/DD HH:mm') : dayjs.utc(program.dateTime, 'YYYY/MM/DD HH:mm').add(1, 'day').startOf('day'), + description: program.description, + icon: program.image, + category: program.categoryName, + rating: program.ageRating + }) + }); + } + } + + return programs + } +} + +function parseItems(content) { + if (content != '') { + const data = JSON.parse(content) + return (!data || !data.data || !Array.isArray(data.data)) ? [] : data.data + } else { + return [] + } +} \ No newline at end of file diff --git a/sites/taiwanplus.com/taiwanplus.com.test.js b/sites/taiwanplus.com/taiwanplus.com.test.js new file mode 100644 index 00000000..dace4883 --- /dev/null +++ b/sites/taiwanplus.com/taiwanplus.com.test.js @@ -0,0 +1,38 @@ +// npx epg-grabber --config=sites/taiwanplus.com/taiwanplus.com.config.js --channels=sites/taiwanplus.com/taiwanplus.com.channels.xml --output=guide.xml --days=3 +// npx jest taiwanplus.com.test.js + +const { url, parser } = require('./taiwanplus.com.config.js') +const dayjs = require('dayjs') +const utc = require('dayjs/plugin/utc') +dayjs.extend(utc) + +const date = dayjs.utc('2023-08-20', 'YYYY-MM-DD').startOf('d') +const channel = { site_id: '#', xmltv_id: 'TaiwanPlusTV.tw', lang: 'en', logo: 'https://i.imgur.com/SfcZyqm.png' } + +it('can generate valid url', () => { + expect(url({ channel, date })).toBe('https://www.taiwanplus.com/api/video/live/schedule/0') +}) + +it('can parse response', () => { + const content = `{"data":[{"date":"2023/08/20","weekday":"SUN","schedule":[{"programId":30668,"dateTime":"2023/08/20 00:00","time":"00:00","image":"https://prod-img.taiwanplus.com/live-schedule/Single/S30668_20230810104937.webp","title":"Master Class","shortDescription":"From blockchain to Buddha statues, Taiwan’s culture is a kaleidoscope of old and new just waiting to be discovered.","description":"From blockchain to Buddha statues, Taiwan’s culture is a kaleidoscope of old and new just waiting to be discovered.","ageRating":"0+","programWebSiteType":"4","url":"","vodId":null,"categoryId":90000474,"categoryType":2,"categoryName":"TaiwanPlus ✕ Discovery","categoryFullPath":"Originals/TaiwanPlus ✕ Discovery","encodedCategoryFullPath":"originals/taiwanplus-discovery"}]}],"success":true,"code":"0000","message":""}` + + const results = parser({ content, date }) + + expect(results).toMatchObject([ + { + title: 'Master Class', + start: dayjs.utc('2023/08/20 00:00', 'YYYY/MM/DD HH:mm'), + stop: dayjs.utc('2023/08/21 00:00', 'YYYY/MM/DD HH:mm'), + description: `From blockchain to Buddha statues, Taiwan’s culture is a kaleidoscope of old and new just waiting to be discovered.`, + icon: 'https://prod-img.taiwanplus.com/live-schedule/Single/S30668_20230810104937.webp', + category: 'TaiwanPlus ✕ Discovery', + rating: '0+' + } + ]) +}) + +it('can handle empty guide', () => { + const results = parser({ content: '' }) + + expect(results).toMatchObject([]) +})