diff --git a/sites/nhk.or.jp/nhk.or.jp.channels.xml b/sites/nhk.or.jp/nhk.or.jp.channels.xml new file mode 100644 index 00000000..5242039b --- /dev/null +++ b/sites/nhk.or.jp/nhk.or.jp.channels.xml @@ -0,0 +1,8 @@ + + + + NHK + World-Japan + + \ No newline at end of file diff --git a/sites/nhk.or.jp/nhk.or.jp.config.js b/sites/nhk.or.jp/nhk.or.jp.config.js new file mode 100644 index 00000000..f51fe044 --- /dev/null +++ b/sites/nhk.or.jp/nhk.or.jp.config.js @@ -0,0 +1,65 @@ +const dayjs = require('dayjs') + +module.exports = { + site: 'nhk.or.jp', + days: 5, + output: 'nhk.or.jp.guide.xml', + channels: 'nhk.or.jp.channels.xml', + lang: 'en', + delay: 5000, + + url: function ({ date }) { + return `https://nwapi.nhk.jp/nhkworld/epg/v7b/world/s${date.unix() * 1000}-e${date.add(1, 'd').unix() * 1000}.json` + }, + + request: { + method: 'GET', + timeout: 5000, + cache: { ttl: 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.content) + + items.forEach(item => { + programs.push({ + title: item.title, + start: parseStart(item), + stop: parseStop(item), + description: item.description, + icon: parseIcon(item), + sub_title: item.subtitle + }) + }) + + return programs + } +} + +function parseItems(content) { + if (content != '') { + const data = JSON.parse(content) + return (!data || !data.channel || !Array.isArray(data.channel.item)) ? [] : data.channel.item + } else { + return [] + } +} + +function parseStart(item) { + return dayjs.unix(parseInt(item.pubDate) / 1000) +} + +function parseStop(item) { + return dayjs.unix(parseInt(item.endDate) / 1000) +} + +function parseIcon(item) { + return 'https://www.nhk.or.jp' + item.thumbnail +} \ No newline at end of file diff --git a/sites/nhk.or.jp/nhk.or.jp.test.js b/sites/nhk.or.jp/nhk.or.jp.test.js new file mode 100644 index 00000000..6defd9f8 --- /dev/null +++ b/sites/nhk.or.jp/nhk.or.jp.test.js @@ -0,0 +1,36 @@ +// npx epg-grabber --config=sites/nhk.or.jp/nhk.or.jp.config.js --channels=sites/nhk.or.jp/nhk.or.jp.channels.xml --output=guide.xml --days=2 +// npx jest nhk.or.jp.test.js + +const { url, parser } = require('./nhk.or.jp.config.js') +const dayjs = require('dayjs') +const utc = require('dayjs/plugin/utc') +dayjs.extend(utc) + +const date = dayjs.utc('2023-04-29', 'YYYY-MM-DD').startOf('d') +const channel = { site_id: '0', xmltv_id: 'NHKWorldJapan.jp', lang: 'en', logo: 'https://www3.nhk.or.jp/nhkworld/common/site_images/nw_webapp_1024x1024.png' } + +it('can generate valid url', () => { + expect(url({ channel, date })).toBe('https://nwapi.nhk.jp/nhkworld/epg/v7b/world/s1682726400000-e1682812800000.json') +}) + +it('can parse response', () => { + const content = `{"channel":{"item":[{"seriesId":"1007","airingId":"000","title":"NHK NEWSLINE","description":"NHK WORLD-JAPAN's flagship hourly news program delivers the latest world news, business and weather, with a focus on Japan and the rest of Asia.","link":"/nhkworld/en/news/","pubDate":"1682726400000","endDate":"1682727000000","vodReserved":false,"jstrm":"1","wstrm":"1","subtitle":"","content":"","content_clean":"","pgm_gr_id":"","thumbnail":"/nhkworld/upld/thumbnails/en/tv/regular_program/340aed63308aafd1178172abf6325231_large.jpg","thumbnail_s":"/nhkworld/upld/thumbnails/en/tv/regular_program/340aed63308aafd1178172abf6325231_small.jpg","showlist":"0","internal":"0","genre":{"TV":"11","Top":"","LC":""},"vod_id":"","vod_url":"","analytics":"[nhkworld]simul;NHK NEWSLINE;w02,001;1007-000-2023;2023-04-29T09:00:00+09:00"}]}}` + const results = parser({ content }) + + expect(results).toMatchObject([ + { + title: 'NHK NEWSLINE', + start: dayjs(1682726400000), + stop: dayjs(1682727000000), + description: `NHK WORLD-JAPAN's flagship hourly news program delivers the latest world news, business and weather, with a focus on Japan and the rest of Asia.`, + icon: 'https://www.nhk.or.jp/nhkworld/upld/thumbnails/en/tv/regular_program/340aed63308aafd1178172abf6325231_large.jpg', + sub_title: '' + } + ]) +}) + +it('can handle empty guide', () => { + const results = parser({ content: '' }) + + expect(results).toMatchObject([]) +})