diff --git a/.github/workflows/tapdmv.com.yml b/.github/workflows/tapdmv.com.yml new file mode 100644 index 00000000..17a99317 --- /dev/null +++ b/.github/workflows/tapdmv.com.yml @@ -0,0 +1,17 @@ +name: tapdmv.com +on: + schedule: + - cron: '0 3 * * *' + 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/tapdmv.com/tapdmv.com.config.js b/sites/tapdmv.com/tapdmv.com.config.js new file mode 100644 index 00000000..9d1c3c1f --- /dev/null +++ b/sites/tapdmv.com/tapdmv.com.config.js @@ -0,0 +1,60 @@ +const axios = require('axios') +const dayjs = require('dayjs') + +module.exports = { + site: 'tapdmv.com', + url({ channel, date }) { + return `https://epg.tapdmv.com/calendar/${ + channel.site_id + }?%24limit=10000&%24sort%5BcreatedAt%5D=-1&start=${date.toJSON()}&end=${date + .add(1, 'd') + .toJSON()}` + }, + parser: function ({ content, date }) { + let programs = [] + const items = parseItems(content, date) + items.forEach(item => { + programs.push({ + title: item.program.trim(), + description: item.description, + category: item.genre, + icon: item.thumbnailImage, + start: parseStart(item), + stop: parseStop(item) + }) + }) + + return programs + }, + async channels() { + const items = await axios + .get(`https://epg.tapdmv.com/calendar?$limit=10000&$sort[createdAt]=-1`) + .then(r => r.data.data) + .catch(console.log) + + return items.map(item => { + const [_, name] = item.name.match(/epg-tapgo-([^\.]+).json/) + return { + site_id: item.id, + name + } + }) + } +} + +function parseStart(item) { + return dayjs(item.startTime) +} + +function parseStop(item) { + return dayjs(item.endTime) +} + +function parseItems(content, date) { + if (!content) return [] + const data = JSON.parse(content) + if (!Array.isArray(data)) return [] + const d = date.format('YYYY-MM-DD') + + return data.filter(i => i.startTime.includes(d)) +} diff --git a/sites/tapdmv.com/tapdmv.com.test.js b/sites/tapdmv.com/tapdmv.com.test.js new file mode 100644 index 00000000..6c519a7b --- /dev/null +++ b/sites/tapdmv.com/tapdmv.com.test.js @@ -0,0 +1,50 @@ +// npx epg-grabber --config=sites/tapdmv.com/tapdmv.com.config.js --channels=sites/tapdmv.com/tapdmv.com_ph.channels.xml --output=guide.xml --days=2 +// npm run channels:parse -- --config=./sites/tapdmv.com/tapdmv.com.config.js --output=./sites/tapdmv.com/tapdmv.com_ph.channels.xml + +const { parser, url } = require('./tapdmv.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-10-04', 'YYYY-MM-DD').startOf('d') +const channel = { + site_id: '94b7db9b-5bbd-47d3-a2d3-ce792342a756', + xmltv_id: 'TAPActionFlix.ph' +} + +it('can generate valid url', () => { + expect(url({ channel, date })).toBe( + 'https://epg.tapdmv.com/calendar/94b7db9b-5bbd-47d3-a2d3-ce792342a756?%24limit=10000&%24sort%5BcreatedAt%5D=-1&start=2022-10-04T00:00:00.000Z&end=2022-10-05T00:00:00.000Z' + ) +}) + +it('can parse response', () => { + const content = `[{"id":"0afc3cc0-eab8-4960-a8b5-55d76edeb8f0","program":"The Bourne Ultimatum","episode":"The Bourne Ultimatum","description":"Jason Bourne dodges a ruthless C.I.A. official and his Agents from a new assassination program while searching for the origins of his life as a trained killer.","genre":"Action","thumbnailImage":"https://s3.ap-southeast-1.amazonaws.com/epg.tapdmv.com/tapactionflix.png","startTime":"2022-10-03T23:05:00.000Z","endTime":"2022-10-04T01:00:00.000Z","fileId":"94b7db9b-5bbd-47d3-a2d3-ce792342a756","createdAt":"2022-09-30T13:02:10.586Z","updatedAt":"2022-09-30T13:02:10.586Z"},{"id":"8dccd5e0-ab88-44b6-a2af-18d31c6e9ed7","program":"The Devil Inside ","episode":"The Devil Inside ","description":"In Italy, a woman becomes involved in a series of unauthorized exorcisms during her mission to discover what happened to her mother, who allegedly murdered three people during her own exorcism.","genre":"Horror","thumbnailImage":"https://s3.ap-southeast-1.amazonaws.com/epg.tapdmv.com/tapactionflix.png","startTime":"2022-10-04T01:00:00.000Z","endTime":"2022-10-04T02:25:00.000Z","fileId":"94b7db9b-5bbd-47d3-a2d3-ce792342a756","createdAt":"2022-09-30T13:02:24.031Z","updatedAt":"2022-09-30T13:02:24.031Z"}]` + const result = parser({ content, date }).map(p => { + p.start = p.start.toJSON() + p.stop = p.stop.toJSON() + return p + }) + + expect(result).toMatchObject([ + { + start: '2022-10-04T01:00:00.000Z', + stop: '2022-10-04T02:25:00.000Z', + title: 'The Devil Inside', + description: + 'In Italy, a woman becomes involved in a series of unauthorized exorcisms during her mission to discover what happened to her mother, who allegedly murdered three people during her own exorcism.', + category: 'Horror', + icon: 'https://s3.ap-southeast-1.amazonaws.com/epg.tapdmv.com/tapactionflix.png' + } + ]) +}) + +it('can handle empty guide', () => { + const result = parser({ + content: `[]`, + date + }) + expect(result).toMatchObject([]) +}) diff --git a/sites/tapdmv.com/tapdmv.com_ph.channels.xml b/sites/tapdmv.com/tapdmv.com_ph.channels.xml new file mode 100644 index 00000000..31f01e51 --- /dev/null +++ b/sites/tapdmv.com/tapdmv.com_ph.channels.xml @@ -0,0 +1,34 @@ + + + + anc + asianfoodchannel + cinemaworld + edgesport + kbsworld + knowledgechannel + premierfootball + premiersports1 + premiersports2 + tapactionflix + tapedge + tapmovies + tapsports + taptv + teleradyo + + + + + + + + + + + + + + + +