diff --git a/.github/workflows/starhubtvplus.com.yml b/.github/workflows/starhubtvplus.com.yml new file mode 100644 index 00000000..d9861396 --- /dev/null +++ b/.github/workflows/starhubtvplus.com.yml @@ -0,0 +1,17 @@ +name: starhubtvplus.com +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + workflow_run: + workflows: [_trigger] + types: + - completed +jobs: + load: + uses: ./.github/workflows/_load.yml + with: + site: ${{github.workflow}} + secrets: + APP_ID: ${{ secrets.APP_ID }} + APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} diff --git a/sites/starhubtvplus.com/starhubtvplus.com.config.js b/sites/starhubtvplus.com/starhubtvplus.com.config.js new file mode 100644 index 00000000..673256f7 --- /dev/null +++ b/sites/starhubtvplus.com/starhubtvplus.com.config.js @@ -0,0 +1,83 @@ +const axios = require('axios') +const dayjs = require('dayjs') + +const APP_KEY = '5ee2ef931de1c4001b2e7fa3_5ee2ec25a0e845001c1783dc' +const SESSION_KEY = '01G2QG0N3RWDNCBA1S5MK1MD2K17CE4431A2' + +module.exports = { + site: 'starhubtvplus.com', + request: { + headers: { + 'x-application-key': APP_KEY, + 'x-application-session': SESSION_KEY + }, + cache: { + ttl: 60 * 60 * 1000 // 1h + } + }, + url: function ({ date }) { + const variables = JSON.stringify({ + category: '', + dateFrom: date.format('YYYY-MM-DD'), + dateTo: date.add(1, 'd').format('YYYY-MM-DD') + }) + const query = `query webFilteredEpg($category: String, $dateFrom: DateWithoutTime, $dateTo: DateWithoutTime!) { nagraEpg(category: $category) { items { id: tvChannel image name: longName programs: programsByDate(dateFrom: $dateFrom, dateTo: $dateTo) { id title description Categories startTime endTime }}}}` + + const params = `operationName=webFilteredEpg&variables=${encodeURIComponent( + variables + )}&query=${encodeURIComponent(query)}` + + return `https://api.starhubtvplus.com/epg?${params}` + }, + parser: function ({ content, channel, cached }) { + let programs = [] + const items = parseItems(content, channel) + items.forEach(item => { + programs.push({ + title: item.title, + description: item.description, + category: item.Categories, + start: parseStart(item), + stop: parseStop(item) + }) + }) + + return programs + }, + async channels() { + const items = await axios + .get( + `https://api.starhubtvplus.com/epg?operationName=webFilteredEpg&variables=%7B%22category%22%3A%22%22,%22dateFrom%22%3A%222022-05-10%22,%22dateTo%22%3A%222022-05-11%22%7D&query=query%20webFilteredEpg(%24category%3A%20String)%20%7B%20nagraEpg(category%3A%20%24category)%20%7B%20items%20%7B%20id%3A%20tvChannel%20image%20name%3A%20longName%20%7D%7D%7D`, + { + headers: { + 'x-application-key': APP_KEY, + 'x-application-session': SESSION_KEY + } + } + ) + .then(r => r.data.data.nagraEpg.items) + .catch(console.log) + + return items.map(item => ({ + site_id: item.id, + name: item.name.replace('_DASH', '') + })) + } +} + +function parseStart(item) { + return dayjs(item.startTime) +} + +function parseStop(item) { + return dayjs(item.endTime) +} + +function parseItems(content, channel) { + const data = JSON.parse(content) + if (!data || !data.data || !data.data.nagraEpg || !Array.isArray(data.data.nagraEpg.items)) + return [] + const ch = data.data.nagraEpg.items.find(ch => ch.id == channel.site_id) + + return ch && Array.isArray(ch.programs) ? ch.programs : [] +} diff --git a/sites/starhubtvplus.com/starhubtvplus.com.test.js b/sites/starhubtvplus.com/starhubtvplus.com.test.js new file mode 100644 index 00000000..8224b8c0 --- /dev/null +++ b/sites/starhubtvplus.com/starhubtvplus.com.test.js @@ -0,0 +1,61 @@ +// npm run channels:parse -- --config=sites/starhubtvplus.com/starhubtvplus.com.config.js --output=sites/starhubtvplus.com/starhubtvplus.com_sg.channels.xml +// npx epg-grabber --config=sites/starhubtvplus.com/starhubtvplus.com.config.js --channels=sites/starhubtvplus.com/starhubtvplus.com_sg.channels.xml --output=guide.xml --days=2 + +const { parser, url, request } = require('./starhubtvplus.com.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-05-10', 'YYYY-MM-DD').startOf('d') +const channel = { + site_id: '102', + xmltv_id: 'Channel5Singapore.sg' +} + +it('can generate valid url', () => { + expect(url({ channel, date })).toBe( + 'https://api.starhubtvplus.com/epg?operationName=webFilteredEpg&variables=%7B%22category%22%3A%22%22%2C%22dateFrom%22%3A%222022-05-10%22%2C%22dateTo%22%3A%222022-05-11%22%7D&query=query%20webFilteredEpg(%24category%3A%20String%2C%20%24dateFrom%3A%20DateWithoutTime%2C%20%24dateTo%3A%20DateWithoutTime!)%20%7B%20nagraEpg(category%3A%20%24category)%20%7B%20items%20%7B%20id%3A%20tvChannel%20image%20name%3A%20longName%20programs%3A%20programsByDate(dateFrom%3A%20%24dateFrom%2C%20dateTo%3A%20%24dateTo)%20%7B%20id%20title%20description%20Categories%20startTime%20endTime%20%7D%7D%7D%7D' + ) +}) + +it('can generate valid request headers', () => { + expect(request.headers).toMatchObject({ + 'x-application-key': '5ee2ef931de1c4001b2e7fa3_5ee2ec25a0e845001c1783dc', + 'x-application-session': '01G2QG0N3RWDNCBA1S5MK1MD2K17CE4431A2' + }) +}) + +it('can generate valid cache settings', () => { + expect(request.cache).toMatchObject({ + ttl: 60 * 60 * 1000 + }) +}) + +it('can parse response', () => { + const content = `{"data":{"nagraEpg":{"items":[{"id":102,"name":"Channel 5 HD_DASH","programs":[{"id":"GLOBAL_TC0021650123","title":"Luke Nguyen's Vietnam","description":"Luke leaves the hustle and bustle of Hanoi behind for the mystical mountains of Sapa. There, he prepares some black chicken in and amongst the local streets. He cooks buffalo for a salad in the busy Sapa markets, as well as a tofu-and-tomato dish high up in the rice paddy fields with the most spectacular backdrop.","Categories":["Others"],"startTime":1652110200000,"endTime":1652112000000}]}]}}}` + const result = parser({ content, channel }).map(p => { + p.start = p.start.toJSON() + p.stop = p.stop.toJSON() + return p + }) + + expect(result).toMatchObject([ + { + start: '2022-05-09T15:30:00.000Z', + stop: '2022-05-09T16:00:00.000Z', + title: "Luke Nguyen's Vietnam", + description: + 'Luke leaves the hustle and bustle of Hanoi behind for the mystical mountains of Sapa. There, he prepares some black chicken in and amongst the local streets. He cooks buffalo for a salad in the busy Sapa markets, as well as a tofu-and-tomato dish high up in the rice paddy fields with the most spectacular backdrop.', + category: ['Others'] + } + ]) +}) + +it('can handle empty guide', () => { + const result = parser({ + content: `{"errors":[{"code":"A9999","message":"Syntax, request headers or server error","extendedLogging":{"message":"Cannot read property 'operation' of undefined"}}]}` + }) + expect(result).toMatchObject([]) +}) diff --git a/sites/starhubtvplus.com/starhubtvplus.com_sg.channels.xml b/sites/starhubtvplus.com/starhubtvplus.com_sg.channels.xml new file mode 100644 index 00000000..6e6de467 --- /dev/null +++ b/sites/starhubtvplus.com/starhubtvplus.com_sg.channels.xml @@ -0,0 +1,130 @@ + + + + ABC Australia + ADITHYA TV + ANC + Animax HD + Arirang TV + Asianet + Asianet Movies + Asia Travel HD + Hub Sensasi HD + Astro Warna + AXN HD + BabyFirst TV + BBC Earth HD + BBC Lifestyle HD + BBC World News HD + beIN SPORTS HD + beIN SPORTS 2 HD + beIN Sports 3 HD + beIN Sports 4 HD + beIN Sports 5 HD + Bloomberg Television HD + Boomerang HD + Cartoon Network + Cbeebies HD + CCTV-4 + CCM + Celestial Movies HD + CGTN + Channel 5 HD + Channel 8 HD + Channel U HD + Cinema One Global + CinemaWorld HD + Cinemax HD + Citra Entertainment + Channel NewsAsia HD + CNBC HD + CNN HD + COLORS + COLORS Tamil HD + Crime + Investigation HD + CTI TV HD + CuriosityStream HD + Dragon TV + DreamWorks Channel HD + DW (Deutsch) + Euronews HD + FashionTV HD + FIGHT SPORTS HD + Fox News Channel HD + GEM HD + GMA Life TV + GMA Pinoy TV + HBO HD + HBO Family HD + HBO Hits HD + HBO Signature HD + HISTORY HD + Hits HD + HITS MOVIES HD + Hub E City HD + Hub Sports 1 HD + Hub Sports 2 HD + Hub Sports 3 HD + Hub VVDrama HD + Kalaignar TV + Karisma + KBS World HD + KTV HD + Lifetime HD + Love Nature HD + Makeful HD + mio Stadium 102 (HD) + mio Stadium 103 (HD) + mio Stadium 104 (HD) + mio Stadium 105 (HD) + mio Stadium 106 (HD) + mio Stadium 107 (HD) + mio Stadium 108 (HD) + MTV Asia HD + National Geographic HD + Nat Geo Wild HD + NBA TV HD + NDTV 24x7 + NHK WORLD - JAPAN + NHK World Premium HD + Nickelodeon HD + Nick Jr HD + Now Jelli HD + Oh!K HD + ONE (Malay) + Paramount Network + Phoenix Chinese Channel HD + Phoenix InfoNews Channel HD + Premier Sports TV + Preview Channel + Blue Ant Entertainment HD + Russia Today + SEA Today + Sky News HD + Smithsonian Channel HD + Sony Entertainment Television + SONY MAX + SPOTV + SPOTV2 + Star Chinese Channel HD + SCM HD + Sun Music + Sun TV + Suria HD + The Filipino Channel + Travelxp HD + TV5MONDE HD + TVB Jade HD + TVBS Asia + TVBS-NEWS + TVB Xing He HD + tvN HD + Vannathirai + Vasantham HD + WarnerTV HD + Zee Cinema + Zee Tamil HD + Zee Thirai + Zee TV + +