diff --git a/.gitignore b/.gitignore index a6693eac..34d14dc9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ -logs/ \ No newline at end of file +logs/ +guide.xml \ No newline at end of file diff --git a/sites/tvguide.myjcom.jp/tvguide.myjcom.jp.config.js b/sites/tvguide.myjcom.jp/tvguide.myjcom.jp.config.js new file mode 100644 index 00000000..fd40ab4e --- /dev/null +++ b/sites/tvguide.myjcom.jp/tvguide.myjcom.jp.config.js @@ -0,0 +1,116 @@ +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: 'tvguide.myjcom.jp', + url: function ({ date, channel }) { + const id = `${channel.site_id}_${date.format('YYYYMMDD')}` + + return `https://tvguide.myjcom.jp/api/getEpgInfo/?channels=${id}` + }, + logo({ channel }) { + return channel.logo || null + }, + parser: function ({ content, channel, date }) { + let programs = [] + const items = parseItems(content, channel, date) + items.forEach(item => { + programs.push({ + title: item.title, + description: item.commentary, + category: parseCategory(item), + icon: parseIcon(item), + start: parseStart(item), + stop: parseStop(item) + }) + }) + + return programs + }, + async channels() { + const requests = [ + axios.get( + `https://tvguide.myjcom.jp/api/mypage/getEpgChannelList/?channelType=2&area=108&channelGenre&course&chart&is_adult=true` + ), + axios.get( + `https://tvguide.myjcom.jp/api/mypage/getEpgChannelList/?channelType=3&area=108&channelGenre&course&chart&is_adult=true` + ), + axios.get( + `https://tvguide.myjcom.jp/api/mypage/getEpgChannelList/?channelType=5&area=108&channelGenre&course&chart&is_adult=true` + ), + axios.get( + `https://tvguide.myjcom.jp/api/mypage/getEpgChannelList/?channelType=120&area=108&channelGenre&course&chart&is_adult=true` + ), + axios.get( + `https://tvguide.myjcom.jp/api/mypage/getEpgChannelList/?channelType=200&area=108&channelGenre&course&chart&is_adult=true` + ) + ] + + let items = [] + await Promise.all(requests) + .then(responses => { + for (const r of responses) { + items = items.concat(r.data.header) + } + }) + .catch(console.log) + + return items.map(item => { + return { + lang: 'jp', + site_id: `${item.channel_type}_${item.channel_id}_${item.network_id}`, + name: item.channel_name, + logo: item.logo_url + } + }) + } +} + +function parseIcon(item) { + return item.imgPath ? `https://tvguide.myjcom.jp${item.imgPath}` : null +} + +function parseCategory(item) { + if (!item.sortGenre) return null + + const id = item.sortGenre[0] + const genres = { + 0: 'ニュース/報道', + 1: 'スポーツ', + 2: '情報/ワイドショー', + 3: 'ドラマ', + 4: '音楽', + 5: 'バラエティ', + 6: '映画', + 7: 'アニメ/特撮', + 8: 'ドキュメンタリー/教養', + 9: '劇場/公演', + 10: '趣味/教育', + 11: '福祉', + 12: 'その他' + } + + return genres[id] +} + +function parseStart(item) { + return dayjs.tz(item.programStart.toString(), 'YYYYMMDDHHmmss', 'Asia/Tokyo') +} + +function parseStop(item) { + return dayjs.tz(item.programEnd.toString(), 'YYYYMMDDHHmmss', 'Asia/Tokyo') +} + +function parseItems(content, channel, date) { + const id = `${channel.site_id}_${date.format('YYYYMMDD')}` + const parsed = JSON.parse(content) + + return parsed[id] || [] +} diff --git a/sites/tvguide.myjcom.jp/tvguide.myjcom.jp.test.js b/sites/tvguide.myjcom.jp/tvguide.myjcom.jp.test.js new file mode 100644 index 00000000..00b4562c --- /dev/null +++ b/sites/tvguide.myjcom.jp/tvguide.myjcom.jp.test.js @@ -0,0 +1,56 @@ +// node ./scripts/channels.js --config=./sites/tvguide.myjcom.jp/tvguide.myjcom.jp.config.js --output=./sites/tvguide.myjcom.jp/tvguide.myjcom.jp_jp.channels.xml +// npx epg-grabber --config=sites/tvguide.myjcom.jp/tvguide.myjcom.jp.config.js --channels=sites/tvguide.myjcom.jp/tvguide.myjcom.jp_jp.channels.xml --output=guide.xml --days=2 + +const { parser, url, logo } = require('./tvguide.myjcom.jp.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('2022-01-14', 'YYYY-MM-DD').startOf('d') +const channel = { + site_id: '120_200_4', + name: 'Star Channel 1', + xmltv_id: 'StarChannel1.jp', + logo: 'https://tvguide.myjcom.jp/monomedia/ch_logo/jcom/logo-0004-200-400x400.png' +} +const content = `{"120_200_4_20220114":[{"@search.score":1,"cid":"120_7305523","serviceCode":"200_4","channelName":"スターチャンネル1","digitalNo":195,"eventId":"181","title":"[5.1]フードロア:タマリンド","commentary":"HBO(R)アジア製作。日本の齊藤工などアジアの監督が、各国の食をテーマに描いたアンソロジーシリーズ。(全8話)(19年 シンガポール 56分)","attr":["5.1","hd","cp1"],"sortGenre":"31","hasImage":1,"imgPath":"\/monomedia\/si\/2022\/20220114\/7305523\/image\/7743d17b655b8d2274ca58b74f2f095c.jpg","isRecommended":null,"programStart":20220114050000,"programEnd":20220114060000,"programDate":20220114,"programId":568519,"start_time":"00","duration":60,"top":300,"end_time":"20220114060000","channel_type":"120","is_end":false,"show_remoterec":true}]}` + +it('can generate valid url', () => { + const result = url({ date, channel }) + expect(result).toBe('https://tvguide.myjcom.jp/api/getEpgInfo/?channels=120_200_4_20220114') +}) + +it('can get logo url', () => { + const result = logo({ channel }) + expect(result).toBe('https://tvguide.myjcom.jp/monomedia/ch_logo/jcom/logo-0004-200-400x400.png') +}) + +it('can parse response', () => { + const result = parser({ date, channel, content }).map(p => { + p.start = p.start.toJSON() + p.stop = p.stop.toJSON() + return p + }) + + expect(result).toMatchObject([ + { + start: '2022-01-13T20:00:00.000Z', + stop: '2022-01-13T21:00:00.000Z', + title: '[5.1]フードロア:タマリンド', + description: `HBO(R)アジア製作。日本の齊藤工などアジアの監督が、各国の食をテーマに描いたアンソロジーシリーズ。(全8話)(19年 シンガポール 56分)`, + icon: 'https://tvguide.myjcom.jp/monomedia/si/2022/20220114/7305523/image/7743d17b655b8d2274ca58b74f2f095c.jpg', + category: 'ドラマ' + } + ]) +}) + +it('can handle empty guide', () => { + const result = parser({ + date, + channel, + content: `{"120_200_3_20220114":[]}` + }) + expect(result).toMatchObject([]) +}) diff --git a/sites/tvguide.myjcom.jp/tvguide.myjcom.jp_jp.channels.xml b/sites/tvguide.myjcom.jp/tvguide.myjcom.jp_jp.channels.xml new file mode 100644 index 00000000..7e95f134 --- /dev/null +++ b/sites/tvguide.myjcom.jp/tvguide.myjcom.jp_jp.channels.xml @@ -0,0 +1,133 @@ + + + + Animal Planet Japan + Animax Japan + Asia Dramatic TV + AT-X + AXN Japan + AXN Mystery + BBC World News Asia Pacific + BS 11 + BS 12 + BS Asahi + BS Asahi 4K + BS Fuji + BS Fuji 4K + BS Nippon TV + BS Nippon TV 4K + BS-TBS + BS-TBS 4K + BS TV Tokyo + BS TV Tokyo 4K + Cable 4K + Cartoon Network Japan + CCTV Daifu + Channel Ginga + Channel Neco + CNN J + CNN USA + Dance Channel + Discovery Channel Japan + Disney Channel Japan + Disney Junior Japan + Eisei Gekijo + Entermei Tele + Family Gekijyo + Fighting TV Samurai! + Fishing Vision + Fox Japan + Fuji TV Next + Fuji TV One + Fuji TV Two + Gaora Sports + Golf Network + Green Channel + Green Channel 2 + GSTV + Home Drama Channel + Igo Shogi Channel + Japan Leisure Channel + J:COM Higashi Kanto + J:COM Premier Channel + J:COM TV + Jidaigeki Senmon Channel + Fuji TV (JOCX-DTV) + Tokyo MX (JOMX-DTV) + TBS (JORX-DTV) + TV Tokyo (JOTX-DTV) + J Sports 1 + J Sports 2 + J Sports 3 + J Sports 4 + Kayo Pops + KBS World Japan + Kids Station + KNTV + LaLa TV + Midnight Blue + Mnet Japan + Mondo TV + Movie Plus + MTV Japan + Music Air + Music On! TV + National Geographic Japan + NHK BS 1 + NHK BS 4K + NHK BS Premium + NHK Educational TV + NHK General TV + NHK World Japan + Nihon Eiga Senmon Channel + Nihon Jidai 4K + Nikkei CNBC + Nippon TV + Nittele G+ + Nittele Plus + NTV News 24 + Pachinko Pachislo TV + Paradise TV + Playboy Channel Japan + PPV Choice 940 + PPV Choice 941 + QVC Japan + QVC Japan 4K + Red Cherry + Shop Channel + Shop Channel 4K + Shop Channel Plus + Sky A + Space Shower TV + Space Shower TV Plus + Speed Channel 1 + Sports Live + + Star 1 + Star 2 + Star 3 + Star BS10 + Super! Drama TV + Tabi Channel + Takarazuka Sky Stage + TBS Channel 1 + TBS Channel 2 + TBS News + The Cinema + The Cinema 4K + The History Channel Japan + Toei Channel + TV5Monde Pacifique + TV Asahi + TV Asahi Channel 1 + TV Asahi Channel 2 + TV Kanagawa + TV Saitama + V Paradise + Wowow 4K + Wowow Cinema + Wowow Live + Wowow Plus + Wowow Prime + Yose Channel + + \ No newline at end of file