From d3748413b2fb18d13e11d346798277e6b4c348e6 Mon Sep 17 00:00:00 2001 From: Arif Budiman Date: Fri, 25 Aug 2023 14:10:54 -0700 Subject: [PATCH] Initial commit --- sites/arirang.com/__data__/detail.json | 187 +++++++++++++++++++++ sites/arirang.com/__data__/schedule.json | 93 ++++++++++ sites/arirang.com/arirang.com.channels.xml | 10 ++ sites/arirang.com/arirang.com.config.js | 114 +++++++++++++ sites/arirang.com/arirang.com.test.js | 59 +++++++ 5 files changed, 463 insertions(+) create mode 100644 sites/arirang.com/__data__/detail.json create mode 100644 sites/arirang.com/__data__/schedule.json create mode 100644 sites/arirang.com/arirang.com.channels.xml create mode 100644 sites/arirang.com/arirang.com.config.js create mode 100644 sites/arirang.com/arirang.com.test.js 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..893c33da --- /dev/null +++ b/sites/arirang.com/arirang.com.channels.xml @@ -0,0 +1,10 @@ + + + + Arirang TV + + + \ 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..4d117bb1 --- /dev/null +++ b/sites/arirang.com/arirang.com.config.js @@ -0,0 +1,114 @@ +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: programDetail.image[0].url, + category: programDetail.category_Info[0].title, + description: programDetail.content[0].text + + }) + } + + 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) { + const data = await 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' + } + }) + .then(r => r.data) + .catch() + + if (!data) + return {} + + return data +} \ No newline at end of file diff --git a/sites/arirang.com/arirang.com.test.js b/sites/arirang.com/arirang.com.test.js new file mode 100644 index 00000000..8f22db86 --- /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