mirror of
https://github.com/iptv-org/epg.git
synced 2025-05-09 16:40:07 -04:00
Make code prettier
This commit is contained in:
parent
268d150cc5
commit
dd6d694491
31 changed files with 1079 additions and 1051 deletions
|
@ -1,76 +1,76 @@
|
||||||
const chalk = require('chalk')
|
const chalk = require('chalk')
|
||||||
const libxml = require('libxmljs2')
|
const libxml = require('libxmljs2')
|
||||||
const { program } = require('commander')
|
const { program } = require('commander')
|
||||||
const { logger, file } = require('../../core')
|
const { logger, file } = require('../../core')
|
||||||
|
|
||||||
const xsd = `<?xml version="1.0" encoding="UTF-8"?>
|
const xsd = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
|
||||||
<xs:element name="site">
|
<xs:element name="site">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element ref="channels"/>
|
<xs:element ref="channels"/>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
<xs:attribute name="site" use="required" type="xs:string"/>
|
<xs:attribute name="site" use="required" type="xs:string"/>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="channels">
|
<xs:element name="channels">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element minOccurs="0" maxOccurs="unbounded" ref="channel"/>
|
<xs:element minOccurs="0" maxOccurs="unbounded" ref="channel"/>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="channel">
|
<xs:element name="channel">
|
||||||
<xs:complexType mixed="true">
|
<xs:complexType mixed="true">
|
||||||
<xs:attribute name="lang" use="required" type="xs:string"/>
|
<xs:attribute name="lang" use="required" type="xs:string"/>
|
||||||
<xs:attribute name="site_id" use="required" type="xs:string"/>
|
<xs:attribute name="site_id" use="required" type="xs:string"/>
|
||||||
<xs:attribute name="xmltv_id" use="required" type="xs:string"/>
|
<xs:attribute name="xmltv_id" use="required" type="xs:string"/>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
</xs:schema>`
|
</xs:schema>`
|
||||||
|
|
||||||
program.argument('<filepath>', 'Path to file to validate').parse(process.argv)
|
program.argument('<filepath>', 'Path to file to validate').parse(process.argv)
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
if (!program.args.length) {
|
if (!program.args.length) {
|
||||||
logger.error('required argument "filepath" not specified')
|
logger.error('required argument "filepath" not specified')
|
||||||
}
|
}
|
||||||
|
|
||||||
let errors = []
|
let errors = []
|
||||||
|
|
||||||
for (const filepath of program.args) {
|
for (const filepath of program.args) {
|
||||||
if (!filepath.endsWith('.xml')) continue
|
if (!filepath.endsWith('.xml')) continue
|
||||||
|
|
||||||
const xml = await file.read(filepath)
|
const xml = await file.read(filepath)
|
||||||
|
|
||||||
let localErrors = []
|
let localErrors = []
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const xsdDoc = libxml.parseXml(xsd)
|
const xsdDoc = libxml.parseXml(xsd)
|
||||||
const doc = libxml.parseXml(xml)
|
const doc = libxml.parseXml(xml)
|
||||||
|
|
||||||
if (!doc.validate(xsdDoc)) {
|
if (!doc.validate(xsdDoc)) {
|
||||||
localErrors = doc.validationErrors
|
localErrors = doc.validationErrors
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
localErrors.push(error)
|
localErrors.push(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localErrors.length) {
|
if (localErrors.length) {
|
||||||
logger.info(`\n${chalk.underline(filepath)}`)
|
logger.info(`\n${chalk.underline(filepath)}`)
|
||||||
localErrors.forEach(error => {
|
localErrors.forEach(error => {
|
||||||
const position = `${error.line}:${error.column}`
|
const position = `${error.line}:${error.column}`
|
||||||
logger.error(` ${chalk.gray(position.padEnd(4, ' '))} ${error.message.trim()}`)
|
logger.error(` ${chalk.gray(position.padEnd(4, ' '))} ${error.message.trim()}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
errors = errors.concat(localErrors)
|
errors = errors.concat(localErrors)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
logger.error(chalk.red(`\n${errors.length} error(s)`))
|
logger.error(chalk.red(`\n${errors.length} error(s)`))
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,68 +1,68 @@
|
||||||
const { parser, logger, api } = require('../../core')
|
const { parser, logger, api } = require('../../core')
|
||||||
const { program } = require('commander')
|
const { program } = require('commander')
|
||||||
const chalk = require('chalk')
|
const chalk = require('chalk')
|
||||||
const langs = require('langs')
|
const langs = require('langs')
|
||||||
|
|
||||||
program.argument('<filepath>', 'Path to file to validate').parse(process.argv)
|
program.argument('<filepath>', 'Path to file to validate').parse(process.argv)
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
await api.channels.load()
|
await api.channels.load()
|
||||||
|
|
||||||
const stats = {
|
const stats = {
|
||||||
files: 0,
|
files: 0,
|
||||||
errors: 0
|
errors: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!program.args.length) {
|
if (!program.args.length) {
|
||||||
logger.error('required argument "filepath" not specified')
|
logger.error('required argument "filepath" not specified')
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const filepath of program.args) {
|
for (const filepath of program.args) {
|
||||||
if (!filepath.endsWith('.xml')) continue
|
if (!filepath.endsWith('.xml')) continue
|
||||||
|
|
||||||
const { site, channels } = await parser.parseChannels(filepath)
|
const { site, channels } = await parser.parseChannels(filepath)
|
||||||
|
|
||||||
const bufferById = {}
|
const bufferById = {}
|
||||||
const bufferBySiteId = {}
|
const bufferBySiteId = {}
|
||||||
const errors = []
|
const errors = []
|
||||||
for (const channel of channels) {
|
for (const channel of channels) {
|
||||||
if (!bufferById[channel.id + channel.lang]) {
|
if (!bufferById[channel.id + channel.lang]) {
|
||||||
bufferById[channel.id + channel.lang] = channel
|
bufferById[channel.id + channel.lang] = channel
|
||||||
} else {
|
} else {
|
||||||
errors.push({ type: 'duplicate', xmltv_id: channel.id, ...channel })
|
errors.push({ type: 'duplicate', xmltv_id: channel.id, ...channel })
|
||||||
stats.errors++
|
stats.errors++
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bufferBySiteId[channel.site_id + channel.lang]) {
|
if (!bufferBySiteId[channel.site_id + channel.lang]) {
|
||||||
bufferBySiteId[channel.site_id + channel.lang] = channel
|
bufferBySiteId[channel.site_id + channel.lang] = channel
|
||||||
} else {
|
} else {
|
||||||
errors.push({ type: 'duplicate', xmltv_id: channel.id, ...channel })
|
errors.push({ type: 'duplicate', xmltv_id: channel.id, ...channel })
|
||||||
stats.errors++
|
stats.errors++
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!api.channels.find({ id: channel.id })) {
|
if (!api.channels.find({ id: channel.id })) {
|
||||||
errors.push({ type: 'wrong_xmltv_id', xmltv_id: channel.id, ...channel })
|
errors.push({ type: 'wrong_xmltv_id', xmltv_id: channel.id, ...channel })
|
||||||
stats.errors++
|
stats.errors++
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!langs.where('1', channel.lang)) {
|
if (!langs.where('1', channel.lang)) {
|
||||||
errors.push({ type: 'wrong_lang', xmltv_id: channel.id, ...channel })
|
errors.push({ type: 'wrong_lang', xmltv_id: channel.id, ...channel })
|
||||||
stats.errors++
|
stats.errors++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
logger.info(chalk.underline(filepath))
|
logger.info(chalk.underline(filepath))
|
||||||
console.table(errors, ['type', 'lang', 'xmltv_id', 'site_id', 'name'])
|
console.table(errors, ['type', 'lang', 'xmltv_id', 'site_id', 'name'])
|
||||||
console.log()
|
console.log()
|
||||||
stats.files++
|
stats.files++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stats.errors > 0) {
|
if (stats.errors > 0) {
|
||||||
logger.error(chalk.red(`${stats.errors} error(s) in ${stats.files} file(s)`))
|
logger.error(chalk.red(`${stats.errors} error(s) in ${stats.files} file(s)`))
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
const utc = require('dayjs/plugin/utc')
|
const utc = require('dayjs/plugin/utc')
|
||||||
dayjs.extend(utc)
|
dayjs.extend(utc)
|
||||||
|
|
||||||
const date = {}
|
const date = {}
|
||||||
|
|
||||||
date.getUTC = function (d = null) {
|
date.getUTC = function (d = null) {
|
||||||
if (typeof d === 'string') return dayjs.utc(d).startOf('d')
|
if (typeof d === 'string') return dayjs.utc(d).startOf('d')
|
||||||
|
|
||||||
return dayjs.utc().startOf('d')
|
return dayjs.utc().startOf('d')
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = date
|
module.exports = date
|
||||||
|
|
|
@ -3,11 +3,11 @@ const { gzip, ungzip } = require('node-gzip')
|
||||||
const zip = {}
|
const zip = {}
|
||||||
|
|
||||||
zip.compress = async function (string) {
|
zip.compress = async function (string) {
|
||||||
return gzip(string)
|
return gzip(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
zip.decompress = async function (string) {
|
zip.decompress = async function (string) {
|
||||||
return ungzip(string)
|
return ungzip(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = zip
|
module.exports = zip
|
||||||
|
|
|
@ -1,74 +1,76 @@
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
const utc = require('dayjs/plugin/utc')
|
const utc = require('dayjs/plugin/utc')
|
||||||
const timezone = require('dayjs/plugin/timezone')
|
const timezone = require('dayjs/plugin/timezone')
|
||||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||||
|
|
||||||
dayjs.extend(utc)
|
dayjs.extend(utc)
|
||||||
dayjs.extend(timezone)
|
dayjs.extend(timezone)
|
||||||
dayjs.extend(customParseFormat)
|
dayjs.extend(customParseFormat)
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
site: 'abc.net.au',
|
site: 'abc.net.au',
|
||||||
request: {
|
request: {
|
||||||
cache: {
|
cache: {
|
||||||
ttl: 60 * 60 * 1000 // 1 hour
|
ttl: 60 * 60 * 1000 // 1 hour
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
url({ date }) {
|
url({ date }) {
|
||||||
return `https://epg.abctv.net.au/processed/Sydney_${date.format('YYYY-MM-DD')}.json`
|
return `https://epg.abctv.net.au/processed/Sydney_${date.format('YYYY-MM-DD')}.json`
|
||||||
},
|
},
|
||||||
parser({ content, channel }) {
|
parser({ content, channel }) {
|
||||||
let programs = []
|
let programs = []
|
||||||
const items = parseItems(content, channel)
|
const items = parseItems(content, channel)
|
||||||
items.forEach(item => {
|
items.forEach(item => {
|
||||||
programs.push({
|
programs.push({
|
||||||
title: item.title,
|
title: item.title,
|
||||||
sub_title: item.episode_title,
|
sub_title: item.episode_title,
|
||||||
category: item.genres,
|
category: item.genres,
|
||||||
description: item.description,
|
description: item.description,
|
||||||
season: parseSeason(item),
|
season: parseSeason(item),
|
||||||
episode: parseEpisode(item),
|
episode: parseEpisode(item),
|
||||||
rating: parseRating(item),
|
rating: parseRating(item),
|
||||||
icon: parseIcon(item),
|
icon: parseIcon(item),
|
||||||
start: parseTime(item.start_time),
|
start: parseTime(item.start_time),
|
||||||
stop: parseTime(item.end_time)
|
stop: parseTime(item.end_time)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return programs
|
return programs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseItems(content, channel) {
|
function parseItems(content, channel) {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(content)
|
const data = JSON.parse(content)
|
||||||
if (!data) return []
|
if (!data) return []
|
||||||
if (!Array.isArray(data.schedule)) return []
|
if (!Array.isArray(data.schedule)) return []
|
||||||
|
|
||||||
const channelData = data.schedule.find(i => i.channel == channel.site_id)
|
const channelData = data.schedule.find(i => i.channel == channel.site_id)
|
||||||
return channelData.listing && Array.isArray(channelData.listing) ? channelData.listing : []
|
return channelData.listing && Array.isArray(channelData.listing) ? channelData.listing : []
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSeason(item) {
|
function parseSeason(item) {
|
||||||
return item.series_num || null
|
return item.series_num || null
|
||||||
}
|
}
|
||||||
function parseEpisode(item) {
|
function parseEpisode(item) {
|
||||||
return item.episode_num || null
|
return item.episode_num || null
|
||||||
}
|
}
|
||||||
function parseTime(time) {
|
function parseTime(time) {
|
||||||
return dayjs.tz(time, 'YYYY-MM-DD HH:mm', 'Australia/Sydney')
|
return dayjs.tz(time, 'YYYY-MM-DD HH:mm', 'Australia/Sydney')
|
||||||
}
|
}
|
||||||
function parseIcon(item) {
|
function parseIcon(item) {
|
||||||
return item.image_file ? `https://www.abc.net.au/tv/common/images/publicity/${item.image_file}` : null
|
return item.image_file
|
||||||
}
|
? `https://www.abc.net.au/tv/common/images/publicity/${item.image_file}`
|
||||||
function parseRating(item) {
|
: null
|
||||||
return item.rating
|
}
|
||||||
? {
|
function parseRating(item) {
|
||||||
system: 'ACB',
|
return item.rating
|
||||||
value: item.rating
|
? {
|
||||||
}
|
system: 'ACB',
|
||||||
: null
|
value: item.rating
|
||||||
}
|
}
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
|
|
@ -1,54 +1,53 @@
|
||||||
// npx epg-grabber --config=sites/abc.net.au/abc.net.au.config.js --channels=sites/abc.net.au/abc.net.au_au.channels.xml --output=guide.xml --days=2
|
// npx epg-grabber --config=sites/abc.net.au/abc.net.au.config.js --channels=sites/abc.net.au/abc.net.au_au.channels.xml --output=guide.xml --days=2
|
||||||
|
|
||||||
const { parser, url } = require('./abc.net.au.config.js')
|
const { parser, url } = require('./abc.net.au.config.js')
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
const utc = require('dayjs/plugin/utc')
|
const utc = require('dayjs/plugin/utc')
|
||||||
dayjs.extend(utc)
|
dayjs.extend(utc)
|
||||||
|
|
||||||
const date = dayjs.utc('2022-12-22', 'YYYY-MM-DD').startOf('d')
|
const date = dayjs.utc('2022-12-22', 'YYYY-MM-DD').startOf('d')
|
||||||
const channel = {
|
const channel = {
|
||||||
site_id: 'ABC1',
|
site_id: 'ABC1',
|
||||||
xmltv_id: 'ABCTV.au'
|
xmltv_id: 'ABCTV.au'
|
||||||
}
|
}
|
||||||
it('can generate valid url', () => {
|
it('can generate valid url', () => {
|
||||||
expect(url({ date })).toBe(
|
expect(url({ date })).toBe('https://epg.abctv.net.au/processed/Sydney_2022-12-22.json')
|
||||||
'https://epg.abctv.net.au/processed/Sydney_2022-12-22.json'
|
})
|
||||||
)
|
|
||||||
})
|
it('can parse response', () => {
|
||||||
|
const content = `{"date":"2022-12-22","region":"Sydney","schedule":[{"channel":"ABC1","listing":[{"consumer_advice":"Adult Themes, Drug Use, Violence","rating":"M","show_id":912747,"repeat":true,"description":"When tragedy strikes close to home, it puts head teacher Noah Taylor on a collision course with the criminals responsible. Can the Lyell team help him stop the cycle of violence?","title":"Silent Witness","crid":"ZW2178A004S00","start_time":"2022-12-22T00:46:00","series-crid":"ZW2178A","live":false,"captioning":true,"show_type":"Episode","series_num":22,"episode_title":"Lift Up Your Hearts (part Two)","length":58,"onair_title":"Silent Witness","end_time":"2022-12-22T01:44:00","genres":["Entertainment"],"image_file":"ZW2178A004S00_460.jpg","prog_slug":"silent-witness","episode_num":4}]}]}`
|
||||||
it('can parse response', () => {
|
|
||||||
const content = `{"date":"2022-12-22","region":"Sydney","schedule":[{"channel":"ABC1","listing":[{"consumer_advice":"Adult Themes, Drug Use, Violence","rating":"M","show_id":912747,"repeat":true,"description":"When tragedy strikes close to home, it puts head teacher Noah Taylor on a collision course with the criminals responsible. Can the Lyell team help him stop the cycle of violence?","title":"Silent Witness","crid":"ZW2178A004S00","start_time":"2022-12-22T00:46:00","series-crid":"ZW2178A","live":false,"captioning":true,"show_type":"Episode","series_num":22,"episode_title":"Lift Up Your Hearts (part Two)","length":58,"onair_title":"Silent Witness","end_time":"2022-12-22T01:44:00","genres":["Entertainment"],"image_file":"ZW2178A004S00_460.jpg","prog_slug":"silent-witness","episode_num":4}]}]}`
|
const result = parser({ content, channel }).map(p => {
|
||||||
|
p.start = p.start.toJSON()
|
||||||
const result = parser({ content, channel }).map(p => {
|
p.stop = p.stop.toJSON()
|
||||||
p.start = p.start.toJSON()
|
return p
|
||||||
p.stop = p.stop.toJSON()
|
})
|
||||||
return p
|
|
||||||
})
|
expect(result).toMatchObject([
|
||||||
|
{
|
||||||
expect(result).toMatchObject([
|
title: 'Silent Witness',
|
||||||
{
|
sub_title: 'Lift Up Your Hearts (part Two)',
|
||||||
title: 'Silent Witness',
|
description: `When tragedy strikes close to home, it puts head teacher Noah Taylor on a collision course with the criminals responsible. Can the Lyell team help him stop the cycle of violence?`,
|
||||||
sub_title: 'Lift Up Your Hearts (part Two)',
|
category: ['Entertainment'],
|
||||||
description: `When tragedy strikes close to home, it puts head teacher Noah Taylor on a collision course with the criminals responsible. Can the Lyell team help him stop the cycle of violence?`,
|
rating: {
|
||||||
category: ['Entertainment'],
|
system: 'ACB',
|
||||||
rating: {
|
value: 'M'
|
||||||
system: 'ACB',
|
},
|
||||||
value: 'M'},
|
season: 22,
|
||||||
season: 22,
|
episode: 4,
|
||||||
episode: 4,
|
icon: 'https://www.abc.net.au/tv/common/images/publicity/ZW2178A004S00_460.jpg',
|
||||||
icon: 'https://www.abc.net.au/tv/common/images/publicity/ZW2178A004S00_460.jpg',
|
start: '2022-12-21T13:46:00.000Z',
|
||||||
start: '2022-12-21T13:46:00.000Z',
|
stop: '2022-12-21T14:44:00.000Z'
|
||||||
stop: '2022-12-21T14:44:00.000Z'
|
}
|
||||||
}
|
])
|
||||||
])
|
})
|
||||||
})
|
|
||||||
|
it('can handle empty guide', () => {
|
||||||
it('can handle empty guide', () => {
|
const result = parser(
|
||||||
const result = parser(
|
{
|
||||||
{
|
content: `<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>processed/Sydney_2023-01-17.json</Key><RequestId>6MRHX5TJ12X39B3Y</RequestId><HostId>59rH6XRMrmkFywg8Kv58iqpI6O1fuOCuEbKa1HRRYa4buByXMBTvAhz8zuAK7X5D+ZN9ZuWxyGs=</HostId></Error>`
|
||||||
content: `<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>processed/Sydney_2023-01-17.json</Key><RequestId>6MRHX5TJ12X39B3Y</RequestId><HostId>59rH6XRMrmkFywg8Kv58iqpI6O1fuOCuEbKa1HRRYa4buByXMBTvAhz8zuAK7X5D+ZN9ZuWxyGs=</HostId></Error>`
|
},
|
||||||
},
|
channel
|
||||||
channel
|
)
|
||||||
)
|
expect(result).toMatchObject([])
|
||||||
expect(result).toMatchObject([])
|
})
|
||||||
})
|
|
||||||
|
|
|
@ -55,8 +55,8 @@ function parseItems(content, channel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSeason(item) {
|
function parseSeason(item) {
|
||||||
return item.details.season || null
|
return item.details.season || null
|
||||||
}
|
}
|
||||||
function parseEpisode(item) {
|
function parseEpisode(item) {
|
||||||
return item.details.episode || null
|
return item.details.episode || null
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,8 @@ it('can parse response', () => {
|
||||||
start: '2022-03-03T21:30:00.000Z',
|
start: '2022-03-03T21:30:00.000Z',
|
||||||
stop: '2022-03-03T23:04:00.000Z',
|
stop: '2022-03-03T23:04:00.000Z',
|
||||||
title: 'الراقصه و السياسي',
|
title: 'الراقصه و السياسي',
|
||||||
description: 'تقرر الراقصه سونيا انشاء دار حضانه للأطفال اليتامى و عندما تتقدم بمشورعها للمسئول يرفض فتتحداه ، تلجأ للوزير عبد الحميد رأفت تربطه بها علاقة قديمة ، يخشى على مركزه و يرفض مساعدتها فتقرر كتابة مذكراتها بمساعدة أحد الصحفيين ، يتخوف عبد الحميد و المسئولين ثم يفاجأ عبد الحميد بحصول سونيا على الموافقه للمشورع و البدء في تنفيذه و ذلك لعلاقتها بأحد كبار المسئولين .',
|
description:
|
||||||
|
'تقرر الراقصه سونيا انشاء دار حضانه للأطفال اليتامى و عندما تتقدم بمشورعها للمسئول يرفض فتتحداه ، تلجأ للوزير عبد الحميد رأفت تربطه بها علاقة قديمة ، يخشى على مركزه و يرفض مساعدتها فتقرر كتابة مذكراتها بمساعدة أحد الصحفيين ، يتخوف عبد الحميد و المسئولين ثم يفاجأ عبد الحميد بحصول سونيا على الموافقه للمشورع و البدء في تنفيذه و ذلك لعلاقتها بأحد كبار المسئولين .',
|
||||||
icon: 'https://www.artonline.tv/UploadImages/Channel/ARTAFLAM1/03/AlRaqesaWaAlSeyasi.jpg'
|
icon: 'https://www.artonline.tv/UploadImages/Channel/ARTAFLAM1/03/AlRaqesaWaAlSeyasi.jpg'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
|
@ -1,48 +1,53 @@
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
site: 'bt.com',
|
site: 'bt.com',
|
||||||
url: function ({ date, channel }) {
|
url: function ({ date, channel }) {
|
||||||
return `https://voila.metabroadcast.com/4/schedules/${channel.site_id}.json?key=b4d2edb68da14dfb9e47b5465e99b1b1&from=${date.utc().format()}&to=${date.add(1, 'd').utc().format()}&source=api.youview.tv&annotations=content.description`
|
return `https://voila.metabroadcast.com/4/schedules/${
|
||||||
},
|
channel.site_id
|
||||||
parser: function ({ content }) {
|
}.json?key=b4d2edb68da14dfb9e47b5465e99b1b1&from=${date.utc().format()}&to=${date
|
||||||
const programs = []
|
.add(1, 'd')
|
||||||
const items = parseItems(content)
|
.utc()
|
||||||
items.forEach(item => {
|
.format()}&source=api.youview.tv&annotations=content.description`
|
||||||
programs.push({
|
},
|
||||||
title: item.item.title,
|
parser: function ({ content }) {
|
||||||
description: item.item.description,
|
const programs = []
|
||||||
icon: parseIcon(item),
|
const items = parseItems(content)
|
||||||
season: parseSeason(item),
|
items.forEach(item => {
|
||||||
episode: parseEpisode(item),
|
programs.push({
|
||||||
start: parseStart(item),
|
title: item.item.title,
|
||||||
stop: parseStop(item)
|
description: item.item.description,
|
||||||
})
|
icon: parseIcon(item),
|
||||||
})
|
season: parseSeason(item),
|
||||||
|
episode: parseEpisode(item),
|
||||||
|
start: parseStart(item),
|
||||||
|
stop: parseStop(item)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
return programs
|
return programs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseItems(content) {
|
function parseItems(content) {
|
||||||
const data = JSON.parse(content)
|
const data = JSON.parse(content)
|
||||||
return data && data.schedule.entries ? data.schedule.entries : []
|
return data && data.schedule.entries ? data.schedule.entries : []
|
||||||
}
|
}
|
||||||
function parseSeason(item) {
|
function parseSeason(item) {
|
||||||
if (item.item.type !== 'episode') return null
|
if (item.item.type !== 'episode') return null
|
||||||
return item.item.series_number || null
|
return item.item.series_number || null
|
||||||
}
|
}
|
||||||
function parseEpisode(item) {
|
function parseEpisode(item) {
|
||||||
if (item.item.type !== 'episode') return null
|
if (item.item.type !== 'episode') return null
|
||||||
return item.item.episode_number || null
|
return item.item.episode_number || null
|
||||||
}
|
}
|
||||||
function parseIcon(item) {
|
function parseIcon(item) {
|
||||||
return item.item.image || null
|
return item.item.image || null
|
||||||
}
|
}
|
||||||
function parseStart(item) {
|
function parseStart(item) {
|
||||||
return dayjs(item.broadcast.transmission_time)
|
return dayjs(item.broadcast.transmission_time)
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseStop(item) {
|
function parseStop(item) {
|
||||||
return dayjs(item.broadcast.transmission_end_time)
|
return dayjs(item.broadcast.transmission_end_time)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,41 +11,41 @@ dayjs.extend(utc)
|
||||||
|
|
||||||
const date = dayjs.utc('2022-03-20', 'YYYY-MM-DD').startOf('d')
|
const date = dayjs.utc('2022-03-20', 'YYYY-MM-DD').startOf('d')
|
||||||
const channel = {
|
const channel = {
|
||||||
site_id: 'hsxv',
|
site_id: 'hsxv',
|
||||||
xmltv_id: 'BBCOneHD.uk'
|
xmltv_id: 'BBCOneHD.uk'
|
||||||
}
|
}
|
||||||
|
|
||||||
it('can generate valid url', () => {
|
it('can generate valid url', () => {
|
||||||
expect(url({ date, channel })).toBe(
|
expect(url({ date, channel })).toBe(
|
||||||
'https://voila.metabroadcast.com/4/schedules/hsxv.json?key=b4d2edb68da14dfb9e47b5465e99b1b1&from=2022-03-20T00:00:00Z&to=2022-03-21T00:00:00Z&source=api.youview.tv&annotations=content.description'
|
'https://voila.metabroadcast.com/4/schedules/hsxv.json?key=b4d2edb68da14dfb9e47b5465e99b1b1&from=2022-03-20T00:00:00Z&to=2022-03-21T00:00:00Z&source=api.youview.tv&annotations=content.description'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can parse response', () => {
|
it('can parse response', () => {
|
||||||
const content = `{"schedule":{"channel":{"title":"BBC One HD","id":"hsxv","uri":"http://api.youview.tv/channels/dvb://233a..4484","images":[{"uri":"https://images.metabroadcast.com?source=http%3A%2F%2Fimages-live.youview.tv%2Fimages%2Fentity%2F8c4c0357-d7ee-5d8a-8bc4-b177b6875128%2Fident%2F1_1024x532.png%3Fdefaultimg%3D0&ETag=r5vyecG6of%2BhCbHeEClx0Q%3D%3D","mime_type":"image/png","type":null,"color":"monochrome","theme":"light_monochrome","aspect_ratio":null,"availability_start":null,"availability_end":null,"width":1024,"height":532,"hasTitleArt":null,"source":null}],"available_from":[{"key":"api.youview.tv","name":"YouView JSON","country":"GB"}],"source":{"key":"api.youview.tv","name":"YouView JSON","country":"GB"},"same_as":[],"media_type":"video","broadcaster":null,"aliases":[{"namespace":"youview:serviceLocator","value":"dvb://233a..4484"},{"namespace":"youview:channel:id","value":"8c4c0357-d7ee-5d8a-8bc4-b177b6875128"}],"genres":[],"high_definition":true,"timeshifted":null,"regional":null,"related_links":[],"start_date":null,"advertised_from":null,"advertised_to":null,"short_description":null,"medium_description":null,"long_description":null,"region":null,"target_regions":[],"channel_type":"CHANNEL","interactive":false,"transmission_types":["DTT"],"quality":"HD","hdr":false},"source":"api.youview.tv","entries":[{"broadcast":{"aliases":[{"namespace":"api.youview.tv:slot","value":"dvb://233a..4484;76bc"},{"namespace":"dvb:event-locator","value":"dvb://233a..4484;76bc"},{"namespace":"dvb:pcrid","value":"crid://fp.bbc.co.uk/b/3Q30S2"},{"namespace":"youview:schedule_event:id","value":"79d318f3-b41a-582d-b089-7b0172538b42"}],"transmission_time":"2022-03-19T23:30:00.000Z","transmission_end_time":"2022-03-20T01:20:00.000Z","broadcast_duration":6600,"broadcast_on":"hsxv","schedule_date":null,"repeat":null,"subtitled":true,"signed":null,"audio_described":false,"high_definition":null,"widescreen":null,"surround":null,"live":null,"premiere":null,"continuation":null,"new_series":null,"new_episode":null,"new_one_off":null,"revised_repeat":null,"blackout_restriction":{"all":false}},"item":{"id":"n72nsw","type":"item","display_title":{"title":"The Finest Hours (2016)","subtitle":null},"year":null,"media_type":"video","specialization":"tv","source":{"key":"api.youview.tv","name":"YouView JSON","country":"GB"},"title":"The Finest Hours (2016)","description":"Drama based on a true story, recounting one of history's most daring coastguard rescue attempts. Stranded on a sinking oil tanker along with 30 other sailors, engineer Ray Sybert battles to buy his crew more time as Captain Bernie Webber and three of his colleagues tackle gigantic waves and gale-force winds in their astonishing bid to save the seamen.","image":"https://images.metabroadcast.com?source=http%3A%2F%2Fimages-live.youview.tv%2Fimages%2Fentity%2F52172983%2Fprimary%2F1_1024x576.jpg%3Fdefaultimg%3D0&ETag=z7ucT5kdAq7HuNQf%2FGTEJg%3D%3D","thumbnail":null,"duration":null,"container":null}}]},"terms_and_conditions":{"text":"Specific terms and conditions in your agreement with MetaBroadcast, and with any data provider, apply to your use of this data, and associated systems."},"results":1,"request":{"path":"/4/schedules/hsxv.json","parameters":{"annotations":"content.description","from":"2022-03-20T00:00:00Z","to":"2022-03-21T00:00:00Z","source":"api.youview.tv","key":"b4d2edb68da14dfb9e47b5465e99b1b1"}}}`
|
const content = `{"schedule":{"channel":{"title":"BBC One HD","id":"hsxv","uri":"http://api.youview.tv/channels/dvb://233a..4484","images":[{"uri":"https://images.metabroadcast.com?source=http%3A%2F%2Fimages-live.youview.tv%2Fimages%2Fentity%2F8c4c0357-d7ee-5d8a-8bc4-b177b6875128%2Fident%2F1_1024x532.png%3Fdefaultimg%3D0&ETag=r5vyecG6of%2BhCbHeEClx0Q%3D%3D","mime_type":"image/png","type":null,"color":"monochrome","theme":"light_monochrome","aspect_ratio":null,"availability_start":null,"availability_end":null,"width":1024,"height":532,"hasTitleArt":null,"source":null}],"available_from":[{"key":"api.youview.tv","name":"YouView JSON","country":"GB"}],"source":{"key":"api.youview.tv","name":"YouView JSON","country":"GB"},"same_as":[],"media_type":"video","broadcaster":null,"aliases":[{"namespace":"youview:serviceLocator","value":"dvb://233a..4484"},{"namespace":"youview:channel:id","value":"8c4c0357-d7ee-5d8a-8bc4-b177b6875128"}],"genres":[],"high_definition":true,"timeshifted":null,"regional":null,"related_links":[],"start_date":null,"advertised_from":null,"advertised_to":null,"short_description":null,"medium_description":null,"long_description":null,"region":null,"target_regions":[],"channel_type":"CHANNEL","interactive":false,"transmission_types":["DTT"],"quality":"HD","hdr":false},"source":"api.youview.tv","entries":[{"broadcast":{"aliases":[{"namespace":"api.youview.tv:slot","value":"dvb://233a..4484;76bc"},{"namespace":"dvb:event-locator","value":"dvb://233a..4484;76bc"},{"namespace":"dvb:pcrid","value":"crid://fp.bbc.co.uk/b/3Q30S2"},{"namespace":"youview:schedule_event:id","value":"79d318f3-b41a-582d-b089-7b0172538b42"}],"transmission_time":"2022-03-19T23:30:00.000Z","transmission_end_time":"2022-03-20T01:20:00.000Z","broadcast_duration":6600,"broadcast_on":"hsxv","schedule_date":null,"repeat":null,"subtitled":true,"signed":null,"audio_described":false,"high_definition":null,"widescreen":null,"surround":null,"live":null,"premiere":null,"continuation":null,"new_series":null,"new_episode":null,"new_one_off":null,"revised_repeat":null,"blackout_restriction":{"all":false}},"item":{"id":"n72nsw","type":"item","display_title":{"title":"The Finest Hours (2016)","subtitle":null},"year":null,"media_type":"video","specialization":"tv","source":{"key":"api.youview.tv","name":"YouView JSON","country":"GB"},"title":"The Finest Hours (2016)","description":"Drama based on a true story, recounting one of history's most daring coastguard rescue attempts. Stranded on a sinking oil tanker along with 30 other sailors, engineer Ray Sybert battles to buy his crew more time as Captain Bernie Webber and three of his colleagues tackle gigantic waves and gale-force winds in their astonishing bid to save the seamen.","image":"https://images.metabroadcast.com?source=http%3A%2F%2Fimages-live.youview.tv%2Fimages%2Fentity%2F52172983%2Fprimary%2F1_1024x576.jpg%3Fdefaultimg%3D0&ETag=z7ucT5kdAq7HuNQf%2FGTEJg%3D%3D","thumbnail":null,"duration":null,"container":null}}]},"terms_and_conditions":{"text":"Specific terms and conditions in your agreement with MetaBroadcast, and with any data provider, apply to your use of this data, and associated systems."},"results":1,"request":{"path":"/4/schedules/hsxv.json","parameters":{"annotations":"content.description","from":"2022-03-20T00:00:00Z","to":"2022-03-21T00:00:00Z","source":"api.youview.tv","key":"b4d2edb68da14dfb9e47b5465e99b1b1"}}}`
|
||||||
|
|
||||||
const result = parser({ content }).map(p => {
|
const result = parser({ content }).map(p => {
|
||||||
p.start = p.start.toJSON()
|
p.start = p.start.toJSON()
|
||||||
p.stop = p.stop.toJSON()
|
p.stop = p.stop.toJSON()
|
||||||
return p
|
return p
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toMatchObject([
|
expect(result).toMatchObject([
|
||||||
{
|
{
|
||||||
title: 'The Finest Hours (2016)',
|
title: 'The Finest Hours (2016)',
|
||||||
description: `Drama based on a true story, recounting one of history's most daring coastguard rescue attempts. Stranded on a sinking oil tanker along with 30 other sailors, engineer Ray Sybert battles to buy his crew more time as Captain Bernie Webber and three of his colleagues tackle gigantic waves and gale-force winds in their astonishing bid to save the seamen.`,
|
description: `Drama based on a true story, recounting one of history's most daring coastguard rescue attempts. Stranded on a sinking oil tanker along with 30 other sailors, engineer Ray Sybert battles to buy his crew more time as Captain Bernie Webber and three of his colleagues tackle gigantic waves and gale-force winds in their astonishing bid to save the seamen.`,
|
||||||
icon: 'https://images.metabroadcast.com?source=http%3A%2F%2Fimages-live.youview.tv%2Fimages%2Fentity%2F52172983%2Fprimary%2F1_1024x576.jpg%3Fdefaultimg%3D0&ETag=z7ucT5kdAq7HuNQf%2FGTEJg%3D%3D',
|
icon: 'https://images.metabroadcast.com?source=http%3A%2F%2Fimages-live.youview.tv%2Fimages%2Fentity%2F52172983%2Fprimary%2F1_1024x576.jpg%3Fdefaultimg%3D0&ETag=z7ucT5kdAq7HuNQf%2FGTEJg%3D%3D',
|
||||||
season: null,
|
season: null,
|
||||||
episode: null,
|
episode: null,
|
||||||
start: '2022-03-19T23:30:00.000Z',
|
start: '2022-03-19T23:30:00.000Z',
|
||||||
stop: '2022-03-20T01:20:00.000Z'
|
stop: '2022-03-20T01:20:00.000Z'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can handle empty guide', () => {
|
it('can handle empty guide', () => {
|
||||||
const result = parser({
|
const result = parser({
|
||||||
content: `{"schedule":{"channel":{"title":"BBC One HD","id":"hsxv","uri":"http://api.youview.tv/channels/dvb://233a..4484","images":[{"uri":"https://images.metabroadcast.com?source=http%3A%2F%2Fimages-live.youview.tv%2Fimages%2Fentity%2F8c4c0357-d7ee-5d8a-8bc4-b177b6875128%2Fident%2F1_1024x532.png%3Fdefaultimg%3D0&ETag=r5vyecG6of%2BhCbHeEClx0Q%3D%3D","mime_type":"image/png","type":null,"color":"monochrome","theme":"light_monochrome","aspect_ratio":null,"availability_start":null,"availability_end":null,"width":1024,"height":532,"hasTitleArt":null,"source":null}],"available_from":[{"key":"api.youview.tv","name":"YouView JSON","country":"GB"}],"source":{"key":"api.youview.tv","name":"YouView JSON","country":"GB"},"same_as":[],"media_type":"video","broadcaster":null,"aliases":[{"namespace":"youview:serviceLocator","value":"dvb://233a..4484"},{"namespace":"youview:channel:id","value":"8c4c0357-d7ee-5d8a-8bc4-b177b6875128"}],"genres":[],"high_definition":true,"timeshifted":null,"regional":null,"related_links":[],"start_date":null,"advertised_from":null,"advertised_to":null,"short_description":null,"medium_description":null,"long_description":null,"region":null,"target_regions":[],"channel_type":"CHANNEL","interactive":false,"transmission_types":["DTT"],"quality":"HD","hdr":false},"source":"api.youview.tv","entries":[]},"terms_and_conditions":{"text":"Specific terms and conditions in your agreement with MetaBroadcast, and with any data provider, apply to your use of this data, and associated systems."},"results":1,"request":{"path":"/4/schedules/hsxv.json","parameters":{"annotations":"content.description","from":"2022-03-20T00:00:00Z","to":"2022-03-21T00:00:00Z","source":"api.youview.tv","key":"b4d2edb68da14dfb9e47b5465e99b1b1"}}}`
|
content: `{"schedule":{"channel":{"title":"BBC One HD","id":"hsxv","uri":"http://api.youview.tv/channels/dvb://233a..4484","images":[{"uri":"https://images.metabroadcast.com?source=http%3A%2F%2Fimages-live.youview.tv%2Fimages%2Fentity%2F8c4c0357-d7ee-5d8a-8bc4-b177b6875128%2Fident%2F1_1024x532.png%3Fdefaultimg%3D0&ETag=r5vyecG6of%2BhCbHeEClx0Q%3D%3D","mime_type":"image/png","type":null,"color":"monochrome","theme":"light_monochrome","aspect_ratio":null,"availability_start":null,"availability_end":null,"width":1024,"height":532,"hasTitleArt":null,"source":null}],"available_from":[{"key":"api.youview.tv","name":"YouView JSON","country":"GB"}],"source":{"key":"api.youview.tv","name":"YouView JSON","country":"GB"},"same_as":[],"media_type":"video","broadcaster":null,"aliases":[{"namespace":"youview:serviceLocator","value":"dvb://233a..4484"},{"namespace":"youview:channel:id","value":"8c4c0357-d7ee-5d8a-8bc4-b177b6875128"}],"genres":[],"high_definition":true,"timeshifted":null,"regional":null,"related_links":[],"start_date":null,"advertised_from":null,"advertised_to":null,"short_description":null,"medium_description":null,"long_description":null,"region":null,"target_regions":[],"channel_type":"CHANNEL","interactive":false,"transmission_types":["DTT"],"quality":"HD","hdr":false},"source":"api.youview.tv","entries":[]},"terms_and_conditions":{"text":"Specific terms and conditions in your agreement with MetaBroadcast, and with any data provider, apply to your use of this data, and associated systems."},"results":1,"request":{"path":"/4/schedules/hsxv.json","parameters":{"annotations":"content.description","from":"2022-03-20T00:00:00Z","to":"2022-03-21T00:00:00Z","source":"api.youview.tv","key":"b4d2edb68da14dfb9e47b5465e99b1b1"}}}`
|
||||||
})
|
})
|
||||||
expect(result).toMatchObject([])
|
expect(result).toMatchObject([])
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,12 +19,12 @@ module.exports = {
|
||||||
if (item.title === 'Fin des programmes') return
|
if (item.title === 'Fin des programmes') return
|
||||||
const detail = await loadProgramDetails(item)
|
const detail = await loadProgramDetails(item)
|
||||||
programs.push({
|
programs.push({
|
||||||
title: item.title,
|
title: item.title,
|
||||||
description:parseDescription(detail),
|
description: parseDescription(detail),
|
||||||
category: parseCategory(detail),
|
category: parseCategory(detail),
|
||||||
icon: parseIcon(item),
|
icon: parseIcon(item),
|
||||||
start: parseStart(item),
|
start: parseStart(item),
|
||||||
stop: parseStop(item)
|
stop: parseStop(item)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,26 +52,25 @@ module.exports = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function loadProgramDetails(item) {
|
async function loadProgramDetails(item) {
|
||||||
if (!item.onClick.URLPage) return {}
|
if (!item.onClick.URLPage) return {}
|
||||||
const url = item.onClick.URLPage
|
const url = item.onClick.URLPage
|
||||||
const data = await axios
|
const data = await axios
|
||||||
.get(url)
|
.get(url)
|
||||||
.then(r => r.data)
|
.then(r => r.data)
|
||||||
.catch(console.log)
|
.catch(console.log)
|
||||||
return data || {}
|
return data || {}
|
||||||
}
|
|
||||||
|
|
||||||
function parseDescription(detail){
|
|
||||||
return detail.detail.informations.summary || null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseCategory(detail){
|
function parseDescription(detail) {
|
||||||
return detail.detail.informations.subGenre || null
|
return detail.detail.informations.summary || null
|
||||||
}
|
}
|
||||||
function parseIcon(item){
|
|
||||||
return item.URLImage || item.URLImageDefault
|
function parseCategory(detail) {
|
||||||
|
return detail.detail.informations.subGenre || null
|
||||||
|
}
|
||||||
|
function parseIcon(item) {
|
||||||
|
return item.URLImage || item.URLImageDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseStart(item) {
|
function parseStart(item) {
|
||||||
|
@ -92,4 +91,3 @@ function parseItems(content) {
|
||||||
|
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,30 +12,30 @@ dayjs.extend(utc)
|
||||||
jest.mock('axios')
|
jest.mock('axios')
|
||||||
|
|
||||||
const channel = {
|
const channel = {
|
||||||
site_id: '80759',
|
site_id: '80759',
|
||||||
xmltv_id: 'Animaux.fr'
|
xmltv_id: 'Animaux.fr'
|
||||||
}
|
}
|
||||||
|
|
||||||
it('can generate valid url for today', () => {
|
it('can generate valid url for today', () => {
|
||||||
const date = dayjs.utc().startOf('d')
|
const date = dayjs.utc().startOf('d')
|
||||||
expect(url({ channel, date })).toBe(
|
expect(url({ channel, date })).toBe(
|
||||||
'https://service.canal-overseas.com/ott-frontend/vector/83001/channel/80759/events?filter.day=0'
|
'https://service.canal-overseas.com/ott-frontend/vector/83001/channel/80759/events?filter.day=0'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can generate valid url for tomorrow', () => {
|
it('can generate valid url for tomorrow', () => {
|
||||||
const date = dayjs.utc().startOf('d').add(1, 'd')
|
const date = dayjs.utc().startOf('d').add(1, 'd')
|
||||||
expect(url({ channel, date })).toBe(
|
expect(url({ channel, date })).toBe(
|
||||||
'https://service.canal-overseas.com/ott-frontend/vector/83001/channel/80759/events?filter.day=1'
|
'https://service.canal-overseas.com/ott-frontend/vector/83001/channel/80759/events?filter.day=1'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can parse response', done => {
|
it('can parse response', done => {
|
||||||
const content = `{"timeSlices":[{"contents":[{"title":"A petit pas","subtitle":"Episode 1 - La naissance","thirdTitle":"ANIMAUX","startTime":1660794900,"endTime":1660797900,"onClick":{"displayTemplate":"miniDetail","displayName":"A petit pas","URLPage":"https://service.canal-overseas.com/ott-frontend/vector/83001/event/140280189","URLVitrine":"https://service.canal-overseas.com/ott-frontend/vector/83001/program/104991257/recommendations"},"programID":104991257,"diffusionID":"140280189","URLImageDefault":"https://service.canal-overseas.com/image-api/v1/image/generic","URLImage":"https://service.canal-overseas.com/image-api/v1/image/7dedf4a579b66153a1988637e9e023f5"}],"timeSlice":"1"}]}`
|
const content = `{"timeSlices":[{"contents":[{"title":"A petit pas","subtitle":"Episode 1 - La naissance","thirdTitle":"ANIMAUX","startTime":1660794900,"endTime":1660797900,"onClick":{"displayTemplate":"miniDetail","displayName":"A petit pas","URLPage":"https://service.canal-overseas.com/ott-frontend/vector/83001/event/140280189","URLVitrine":"https://service.canal-overseas.com/ott-frontend/vector/83001/program/104991257/recommendations"},"programID":104991257,"diffusionID":"140280189","URLImageDefault":"https://service.canal-overseas.com/image-api/v1/image/generic","URLImage":"https://service.canal-overseas.com/image-api/v1/image/7dedf4a579b66153a1988637e9e023f5"}],"timeSlice":"1"}]}`
|
||||||
axios.get.mockImplementation(url => {
|
axios.get.mockImplementation(url => {
|
||||||
if (url === 'https://service.canal-overseas.com/ott-frontend/vector/83001/event/140280189') {
|
if (url === 'https://service.canal-overseas.com/ott-frontend/vector/83001/event/140280189') {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
data: JSON.parse(`{
|
data: JSON.parse(`{
|
||||||
"currentPage": {
|
"currentPage": {
|
||||||
"displayName": "A petit pas",
|
"displayName": "A petit pas",
|
||||||
"displayTemplate": "detailPage",
|
"displayTemplate": "detailPage",
|
||||||
|
@ -109,42 +109,43 @@ it('can parse response', done => {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
return Promise.resolve({ data: '' })
|
return Promise.resolve({ data: '' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
parser({ content })
|
||||||
|
.then(result => {
|
||||||
|
result = result.map(p => {
|
||||||
|
p.start = p.start.toJSON()
|
||||||
|
p.stop = p.stop.toJSON()
|
||||||
|
return p
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result).toMatchObject([
|
||||||
|
{
|
||||||
|
start: '2022-08-18T03:55:00.000Z',
|
||||||
|
stop: '2022-08-18T04:45:00.000Z',
|
||||||
|
title: 'A petit pas',
|
||||||
|
icon: 'https://service.canal-overseas.com/image-api/v1/image/7dedf4a579b66153a1988637e9e023f5',
|
||||||
|
category: 'Doc. Animalier',
|
||||||
|
description:
|
||||||
|
'Suivi pendant une année entière de trois bébés animaux, un border collie, un poulain et un lémurien, prédestinés par leur maître à devenir de véritables champions.'
|
||||||
}
|
}
|
||||||
|
])
|
||||||
|
done()
|
||||||
})
|
})
|
||||||
|
.catch(done)
|
||||||
parser({ content })
|
|
||||||
.then(result => {
|
|
||||||
result = result.map(p => {
|
|
||||||
p.start = p.start.toJSON()
|
|
||||||
p.stop = p.stop.toJSON()
|
|
||||||
return p
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(result).toMatchObject([
|
|
||||||
{
|
|
||||||
start: '2022-08-18T03:55:00.000Z',
|
|
||||||
stop: '2022-08-18T04:45:00.000Z',
|
|
||||||
title: 'A petit pas',
|
|
||||||
icon: 'https://service.canal-overseas.com/image-api/v1/image/7dedf4a579b66153a1988637e9e023f5',
|
|
||||||
category: 'Doc. Animalier',
|
|
||||||
description: 'Suivi pendant une année entière de trois bébés animaux, un border collie, un poulain et un lémurien, prédestinés par leur maître à devenir de véritables champions.'
|
|
||||||
}
|
|
||||||
])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
.catch(done)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can handle empty guide', done => {
|
it('can handle empty guide', done => {
|
||||||
parser({
|
parser({
|
||||||
content: `{"currentPage":{"displayTemplate":"error","BOName":"Page introuvable"},"title":"Page introuvable","text":"La page que vous demandez est introuvable. Si le problème persiste, vous pouvez contacter l'assistance de CANAL+/CANALSAT.","code":404}`
|
content: `{"currentPage":{"displayTemplate":"error","BOName":"Page introuvable"},"title":"Page introuvable","text":"La page que vous demandez est introuvable. Si le problème persiste, vous pouvez contacter l'assistance de CANAL+/CANALSAT.","code":404}`
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
expect(result).toMatchObject([])
|
||||||
|
done()
|
||||||
})
|
})
|
||||||
.then(result => {
|
.catch(done)
|
||||||
expect(result).toMatchObject([])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
.catch(done)
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,12 +19,12 @@ module.exports = {
|
||||||
if (item.title === 'Fin des programmes') return
|
if (item.title === 'Fin des programmes') return
|
||||||
const detail = await loadProgramDetails(item)
|
const detail = await loadProgramDetails(item)
|
||||||
programs.push({
|
programs.push({
|
||||||
title: item.title,
|
title: item.title,
|
||||||
description:parseDescription(detail),
|
description: parseDescription(detail),
|
||||||
category: parseCategory(detail),
|
category: parseCategory(detail),
|
||||||
icon: parseIcon(item),
|
icon: parseIcon(item),
|
||||||
start: parseStart(item),
|
start: parseStart(item),
|
||||||
stop: parseStop(item)
|
stop: parseStop(item)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,24 +53,24 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadProgramDetails(item) {
|
async function loadProgramDetails(item) {
|
||||||
if (!item.onClick.URLPage) return {}
|
if (!item.onClick.URLPage) return {}
|
||||||
const url = item.onClick.URLPage
|
const url = item.onClick.URLPage
|
||||||
const data = await axios
|
const data = await axios
|
||||||
.get(url)
|
.get(url)
|
||||||
.then(r => r.data)
|
.then(r => r.data)
|
||||||
.catch(console.log)
|
.catch(console.log)
|
||||||
return data || {}
|
return data || {}
|
||||||
}
|
|
||||||
|
|
||||||
function parseDescription(detail){
|
|
||||||
return detail.detail.informations.summary || null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseCategory(detail){
|
function parseDescription(detail) {
|
||||||
return detail.detail.informations.subGenre || null
|
return detail.detail.informations.summary || null
|
||||||
}
|
}
|
||||||
function parseIcon(item){
|
|
||||||
return item.URLImage || item.URLImageDefault
|
function parseCategory(detail) {
|
||||||
|
return detail.detail.informations.subGenre || null
|
||||||
|
}
|
||||||
|
function parseIcon(item) {
|
||||||
|
return item.URLImage || item.URLImageDefault
|
||||||
}
|
}
|
||||||
function parseStart(item) {
|
function parseStart(item) {
|
||||||
return dayjs.unix(item.startTime)
|
return dayjs.unix(item.startTime)
|
||||||
|
|
|
@ -19,12 +19,12 @@ module.exports = {
|
||||||
if (item.title === 'Fin des programmes') return
|
if (item.title === 'Fin des programmes') return
|
||||||
const detail = await loadProgramDetails(item)
|
const detail = await loadProgramDetails(item)
|
||||||
programs.push({
|
programs.push({
|
||||||
title: item.title,
|
title: item.title,
|
||||||
description:parseDescription(detail),
|
description: parseDescription(detail),
|
||||||
category: parseCategory(detail),
|
category: parseCategory(detail),
|
||||||
icon: parseIcon(item),
|
icon: parseIcon(item),
|
||||||
start: parseStart(item),
|
start: parseStart(item),
|
||||||
stop: parseStop(item)
|
stop: parseStop(item)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,26 +52,25 @@ module.exports = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function loadProgramDetails(item) {
|
async function loadProgramDetails(item) {
|
||||||
if (!item.onClick.URLPage) return {}
|
if (!item.onClick.URLPage) return {}
|
||||||
const url = item.onClick.URLPage
|
const url = item.onClick.URLPage
|
||||||
const data = await axios
|
const data = await axios
|
||||||
.get(url)
|
.get(url)
|
||||||
.then(r => r.data)
|
.then(r => r.data)
|
||||||
.catch(console.log)
|
.catch(console.log)
|
||||||
return data || {}
|
return data || {}
|
||||||
}
|
|
||||||
|
|
||||||
function parseDescription(detail){
|
|
||||||
return detail.detail.informations.summary || null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseCategory(detail){
|
function parseDescription(detail) {
|
||||||
return detail.detail.informations.subGenre || null
|
return detail.detail.informations.summary || null
|
||||||
}
|
}
|
||||||
function parseIcon(item){
|
|
||||||
return item.URLImage || item.URLImageDefault
|
function parseCategory(detail) {
|
||||||
|
return detail.detail.informations.subGenre || null
|
||||||
|
}
|
||||||
|
function parseIcon(item) {
|
||||||
|
return item.URLImage || item.URLImageDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseStart(item) {
|
function parseStart(item) {
|
||||||
|
|
|
@ -18,12 +18,12 @@ module.exports = {
|
||||||
if (item.title === 'Fin des programmes') return
|
if (item.title === 'Fin des programmes') return
|
||||||
const detail = await loadProgramDetails(item)
|
const detail = await loadProgramDetails(item)
|
||||||
programs.push({
|
programs.push({
|
||||||
title: item.title,
|
title: item.title,
|
||||||
description:parseDescription(detail),
|
description: parseDescription(detail),
|
||||||
category: parseCategory(detail),
|
category: parseCategory(detail),
|
||||||
icon: parseIcon(item),
|
icon: parseIcon(item),
|
||||||
start: parseStart(item),
|
start: parseStart(item),
|
||||||
stop: parseStop(item)
|
stop: parseStop(item)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,24 +32,24 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadProgramDetails(item) {
|
async function loadProgramDetails(item) {
|
||||||
if (!item.onClick.URLPage) return {}
|
if (!item.onClick.URLPage) return {}
|
||||||
const url = item.onClick.URLPage
|
const url = item.onClick.URLPage
|
||||||
const data = await axios
|
const data = await axios
|
||||||
.get(url)
|
.get(url)
|
||||||
.then(r => r.data)
|
.then(r => r.data)
|
||||||
.catch(console.log)
|
.catch(console.log)
|
||||||
return data || {}
|
return data || {}
|
||||||
}
|
|
||||||
|
|
||||||
function parseDescription(detail){
|
|
||||||
return detail.detail.informations.summary || null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseCategory(detail){
|
function parseDescription(detail) {
|
||||||
return detail.detail.informations.subGenre || null
|
return detail.detail.informations.summary || null
|
||||||
}
|
}
|
||||||
function parseIcon(item){
|
|
||||||
return item.URLImage || item.URLImageDefault
|
function parseCategory(detail) {
|
||||||
|
return detail.detail.informations.subGenre || null
|
||||||
|
}
|
||||||
|
function parseIcon(item) {
|
||||||
|
return item.URLImage || item.URLImageDefault
|
||||||
}
|
}
|
||||||
function parseStart(item) {
|
function parseStart(item) {
|
||||||
return dayjs.unix(item.startTime)
|
return dayjs.unix(item.startTime)
|
||||||
|
|
|
@ -1,39 +1,41 @@
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
site: 'foxsports.com.au',
|
site: 'foxsports.com.au',
|
||||||
request: {
|
request: {
|
||||||
cache: {
|
cache: {
|
||||||
ttl: 60 * 60 * 1000 // 1 hour
|
ttl: 60 * 60 * 1000 // 1 hour
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
url({ date }) {
|
url({ date }) {
|
||||||
return `https://tvguide.foxsports.com.au/granite-api/programmes.json?from=${date.format('YYYY-MM-DD')}&to=${date.add(1, 'd').format('YYYY-MM-DD')}`
|
return `https://tvguide.foxsports.com.au/granite-api/programmes.json?from=${date.format(
|
||||||
},
|
'YYYY-MM-DD'
|
||||||
parser({ content, channel }) {
|
)}&to=${date.add(1, 'd').format('YYYY-MM-DD')}`
|
||||||
let programs = []
|
},
|
||||||
const items = parseItems(content, channel)
|
parser({ content, channel }) {
|
||||||
items.forEach(item => {
|
let programs = []
|
||||||
programs.push({
|
const items = parseItems(content, channel)
|
||||||
title: item.programmeTitle,
|
items.forEach(item => {
|
||||||
sub_title: item.title,
|
programs.push({
|
||||||
category: item.genreTitle,
|
title: item.programmeTitle,
|
||||||
description: item.synopsis,
|
sub_title: item.title,
|
||||||
start: dayjs.utc(item.startTime),
|
category: item.genreTitle,
|
||||||
stop: dayjs.utc(item.endTime)
|
description: item.synopsis,
|
||||||
})
|
start: dayjs.utc(item.startTime),
|
||||||
})
|
stop: dayjs.utc(item.endTime)
|
||||||
|
})
|
||||||
return programs
|
})
|
||||||
}
|
|
||||||
}
|
return programs
|
||||||
|
}
|
||||||
function parseItems(content, channel) {
|
}
|
||||||
const data = JSON.parse(content)
|
|
||||||
if (!data) return []
|
function parseItems(content, channel) {
|
||||||
const programmes = data['channel-programme']
|
const data = JSON.parse(content)
|
||||||
if (!Array.isArray(programmes)) return []
|
if (!data) return []
|
||||||
|
const programmes = data['channel-programme']
|
||||||
const channelData = programmes.filter(i => i.channelId == channel.site_id)
|
if (!Array.isArray(programmes)) return []
|
||||||
return channelData && Array.isArray(channelData) ? channelData : []
|
|
||||||
}
|
const channelData = programmes.filter(i => i.channelId == channel.site_id)
|
||||||
|
return channelData && Array.isArray(channelData) ? channelData : []
|
||||||
|
}
|
||||||
|
|
|
@ -1,48 +1,48 @@
|
||||||
// npx epg-grabber --config=sites/foxsports.com.au/foxsports.com.au.config.js --channels=sites/foxsports.com.au/foxsports.com.au_au.channels.xml --output=guide.xml --days=2
|
// npx epg-grabber --config=sites/foxsports.com.au/foxsports.com.au.config.js --channels=sites/foxsports.com.au/foxsports.com.au_au.channels.xml --output=guide.xml --days=2
|
||||||
|
|
||||||
const { parser, url } = require('./foxsports.com.au.config.js')
|
const { parser, url } = require('./foxsports.com.au.config.js')
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
const utc = require('dayjs/plugin/utc')
|
const utc = require('dayjs/plugin/utc')
|
||||||
dayjs.extend(utc)
|
dayjs.extend(utc)
|
||||||
|
|
||||||
const date = dayjs.utc('2022-12-14', 'YYYY-MM-DD').startOf('d')
|
const date = dayjs.utc('2022-12-14', 'YYYY-MM-DD').startOf('d')
|
||||||
const channel = {
|
const channel = {
|
||||||
site_id: '2',
|
site_id: '2',
|
||||||
xmltv_id: 'FoxLeague.au'
|
xmltv_id: 'FoxLeague.au'
|
||||||
}
|
}
|
||||||
it('can generate valid url', () => {
|
it('can generate valid url', () => {
|
||||||
expect(url({ date })).toBe(
|
expect(url({ date })).toBe(
|
||||||
'https://tvguide.foxsports.com.au/granite-api/programmes.json?from=2022-12-14&to=2022-12-15'
|
'https://tvguide.foxsports.com.au/granite-api/programmes.json?from=2022-12-14&to=2022-12-15'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can parse response', () => {
|
it('can parse response', () => {
|
||||||
const content = `{"channel-programme":[{"id":"31cc8b4c-3711-49f0-bf22-2ec3993b0a07","programmeTitle":"NRL","title":"Eels v Titans","startTime":"2022-12-14T00:00:00+11:00","endTime":"2022-12-14T01:00:00+11:00","duration":60,"live":false,"genreId":"5c389cf4-8db7-4b52-9773-52355bd28559","channelId":2,"channelName":"FOX League","channelAbbreviation":"LEAGUE","programmeUID":235220,"round":"R1","statsMatchId":null,"closedCaptioned":true,"statsFixtureId":10207,"genreTitle":"Rugby League","parentGenreId":"a953f929-2d12-41a4-b0e9-97f401afff11","parentGenreTitle":"Sport","pmgId":"PMG01306944","statsSport":"league","type":"GAME","hiDef":true,"widescreen":true,"classification":"","synopsis":"The Eels and Titans have plenty of motivation this season after heartbreaking Finals losses in 2021. Parramatta has won their past five against Gold Coast.","preGameStartTime":null,"closeCaptioned":true}]}`
|
const content = `{"channel-programme":[{"id":"31cc8b4c-3711-49f0-bf22-2ec3993b0a07","programmeTitle":"NRL","title":"Eels v Titans","startTime":"2022-12-14T00:00:00+11:00","endTime":"2022-12-14T01:00:00+11:00","duration":60,"live":false,"genreId":"5c389cf4-8db7-4b52-9773-52355bd28559","channelId":2,"channelName":"FOX League","channelAbbreviation":"LEAGUE","programmeUID":235220,"round":"R1","statsMatchId":null,"closedCaptioned":true,"statsFixtureId":10207,"genreTitle":"Rugby League","parentGenreId":"a953f929-2d12-41a4-b0e9-97f401afff11","parentGenreTitle":"Sport","pmgId":"PMG01306944","statsSport":"league","type":"GAME","hiDef":true,"widescreen":true,"classification":"","synopsis":"The Eels and Titans have plenty of motivation this season after heartbreaking Finals losses in 2021. Parramatta has won their past five against Gold Coast.","preGameStartTime":null,"closeCaptioned":true}]}`
|
||||||
|
|
||||||
const result = parser({ content, channel }).map(p => {
|
const result = parser({ content, channel }).map(p => {
|
||||||
p.start = p.start.toJSON()
|
p.start = p.start.toJSON()
|
||||||
p.stop = p.stop.toJSON()
|
p.stop = p.stop.toJSON()
|
||||||
return p
|
return p
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toMatchObject([
|
expect(result).toMatchObject([
|
||||||
{
|
{
|
||||||
title: 'NRL',
|
title: 'NRL',
|
||||||
sub_title: 'Eels v Titans',
|
sub_title: 'Eels v Titans',
|
||||||
description: `The Eels and Titans have plenty of motivation this season after heartbreaking Finals losses in 2021. Parramatta has won their past five against Gold Coast.`,
|
description: `The Eels and Titans have plenty of motivation this season after heartbreaking Finals losses in 2021. Parramatta has won their past five against Gold Coast.`,
|
||||||
category: 'Rugby League',
|
category: 'Rugby League',
|
||||||
start: '2022-12-13T13:00:00.000Z',
|
start: '2022-12-13T13:00:00.000Z',
|
||||||
stop: '2022-12-13T14:00:00.000Z'
|
stop: '2022-12-13T14:00:00.000Z'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can handle empty guide', () => {
|
it('can handle empty guide', () => {
|
||||||
const result = parser(
|
const result = parser(
|
||||||
{
|
{
|
||||||
content: `{"channel-programme":[]}`
|
content: `{"channel-programme":[]}`
|
||||||
},
|
},
|
||||||
channel
|
channel
|
||||||
)
|
)
|
||||||
expect(result).toMatchObject([])
|
expect(result).toMatchObject([])
|
||||||
})
|
})
|
||||||
|
|
|
@ -32,12 +32,12 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseCategory(item) {
|
function parseCategory(item) {
|
||||||
let category = item.content.genre.name || null;
|
let category = item.content.genre.name || null
|
||||||
const subcategory = item.content.subgenre.name || null;
|
const subcategory = item.content.subgenre.name || null
|
||||||
if(category && subcategory){
|
if (category && subcategory) {
|
||||||
category += `/${subcategory}`;
|
category += `/${subcategory}`
|
||||||
}
|
}
|
||||||
return category;
|
return category
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseStart(item) {
|
function parseStart(item) {
|
||||||
|
@ -59,13 +59,13 @@ function parseIcon(item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSeason(item) {
|
function parseSeason(item) {
|
||||||
if (!item.content.seasonNumber) return null
|
if (!item.content.seasonNumber) return null
|
||||||
if (String(item.content.seasonNumber).length > 2) return null
|
if (String(item.content.seasonNumber).length > 2) return null
|
||||||
return item.content.seasonNumber
|
return item.content.seasonNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseEpisode(item) {
|
function parseEpisode(item) {
|
||||||
if (!item.content.episodeNumber) return null
|
if (!item.content.episodeNumber) return null
|
||||||
if (String(item.content.episodeNumber).length > 3) return null
|
if (String(item.content.episodeNumber).length > 3) return null
|
||||||
return item.content.episodeNumber
|
return item.content.episodeNumber
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,13 +122,13 @@ function parseItems(content, channel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSeason(detail) {
|
function parseSeason(detail) {
|
||||||
if (!detail.seasonNumber) return null
|
if (!detail.seasonNumber) return null
|
||||||
if (String(detail.seasonNumber).length > 2) return null
|
if (String(detail.seasonNumber).length > 2) return null
|
||||||
return detail.seasonNumber
|
return detail.seasonNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseEpisode(detail) {
|
function parseEpisode(detail) {
|
||||||
if (!detail.episodeNumber) return null
|
if (!detail.episodeNumber) return null
|
||||||
if (String(detail.episodeNumber).length > 3) return null
|
if (String(detail.episodeNumber).length > 3) return null
|
||||||
return detail.episodeNumber
|
return detail.episodeNumber
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||||
dayjs.extend(customParseFormat)
|
dayjs.extend(customParseFormat)
|
||||||
dayjs.extend(utc)
|
dayjs.extend(utc)
|
||||||
|
|
||||||
|
|
||||||
const channel = {
|
const channel = {
|
||||||
site_id: '1',
|
site_id: '1',
|
||||||
xmltv_id: 'CT1.cz'
|
xmltv_id: 'CT1.cz'
|
||||||
|
@ -17,36 +16,40 @@ const channel = {
|
||||||
|
|
||||||
it('can generate valid url for today', () => {
|
it('can generate valid url for today', () => {
|
||||||
const date = dayjs.utc().startOf('d')
|
const date = dayjs.utc().startOf('d')
|
||||||
expect(url({ channel, date })).toBe('https://services.mujtvprogram.cz/tvprogram2services/services/tvprogrammelist_mobile.php?channel_cid=1&day=0')
|
expect(url({ channel, date })).toBe(
|
||||||
|
'https://services.mujtvprogram.cz/tvprogram2services/services/tvprogrammelist_mobile.php?channel_cid=1&day=0'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can generate valid url for tomorrow', () => {
|
it('can generate valid url for tomorrow', () => {
|
||||||
const date = dayjs.utc().startOf('d').add(1, 'd')
|
const date = dayjs.utc().startOf('d').add(1, 'd')
|
||||||
expect(url({ channel, date })).toBe('https://services.mujtvprogram.cz/tvprogram2services/services/tvprogrammelist_mobile.php?channel_cid=1&day=1')
|
expect(url({ channel, date })).toBe(
|
||||||
|
'https://services.mujtvprogram.cz/tvprogram2services/services/tvprogrammelist_mobile.php?channel_cid=1&day=1'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can parse response', () => {
|
it('can parse response', () => {
|
||||||
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.html'))
|
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.html'))
|
||||||
|
|
||||||
let results = parser({ content }).map(p => {
|
let results = parser({ content }).map(p => {
|
||||||
p.start = p.start.toJSON()
|
p.start = p.start.toJSON()
|
||||||
p.stop = p.stop.toJSON()
|
p.stop = p.stop.toJSON()
|
||||||
return p
|
return p
|
||||||
})
|
})
|
||||||
expect(results[3]).toMatchObject({
|
expect(results[3]).toMatchObject({
|
||||||
title: `Čepice`,
|
title: `Čepice`,
|
||||||
description: `Jarka (J. Bohdalová) vyčítá manželovi Jiřímu (F. Řehák), že jí nepomáhá při předvánočním úklidu. Vzápětí ale náhodou najde ve skříni ukrytou dámskou čepici a napadne ji, že jde o Jiřího dárek pro ni pod stromeček. Její chování se ihned změní. Jen muži naznačí, že by chtěla čepici jiné barvy. Manžel jí ovšem řekne, že čepici si u něj schoval kamarád Venca (M. Šulc). Zklamaná žena to prozradí Vencově manželce Božce (A. Tománková). Na Štědrý den však Božka najde pod stromečkem jen rtěnku...`,
|
description: `Jarka (J. Bohdalová) vyčítá manželovi Jiřímu (F. Řehák), že jí nepomáhá při předvánočním úklidu. Vzápětí ale náhodou najde ve skříni ukrytou dámskou čepici a napadne ji, že jde o Jiřího dárek pro ni pod stromeček. Její chování se ihned změní. Jen muži naznačí, že by chtěla čepici jiné barvy. Manžel jí ovšem řekne, že čepici si u něj schoval kamarád Venca (M. Šulc). Zklamaná žena to prozradí Vencově manželce Božce (A. Tománková). Na Štědrý den však Božka najde pod stromečkem jen rtěnku...`,
|
||||||
category: 'film',
|
category: 'film',
|
||||||
date: '1983',
|
date: '1983',
|
||||||
director: ['Mudra F.'],
|
director: ['Mudra F.'],
|
||||||
actor: ['Bohdalová J.', 'Řehák F.', 'Šulc M.'],
|
actor: ['Bohdalová J.', 'Řehák F.', 'Šulc M.'],
|
||||||
start: '2022-12-23T08:00:00.000Z',
|
start: '2022-12-23T08:00:00.000Z',
|
||||||
stop: '2022-12-23T08:20:00.000Z'
|
stop: '2022-12-23T08:20:00.000Z'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can handle empty guide', () => {
|
it('can handle empty guide', () => {
|
||||||
const content = fs.readFileSync(path.resolve(__dirname, '__data__/no_content.html'))
|
const content = fs.readFileSync(path.resolve(__dirname, '__data__/no_content.html'))
|
||||||
const result = parser(content, channel )
|
const result = parser(content, channel)
|
||||||
expect(result).toMatchObject([])
|
expect(result).toMatchObject([])
|
||||||
})
|
})
|
||||||
|
|
|
@ -61,20 +61,19 @@ function parseContent(content) {
|
||||||
return data ? JSON.parse(data) : {}
|
return data ? JSON.parse(data) : {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function parseDirector(item) {
|
function parseDirector(item) {
|
||||||
return item.credits && item.credits.director ? item.credits.director : null
|
return item.credits && item.credits.director ? item.credits.director : null
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseActor(item) {
|
function parseActor(item) {
|
||||||
return item.credits && item.credits.actor ? item.credits.actor : null
|
return item.credits && item.credits.actor ? item.credits.actor : null
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseRating(item) {
|
function parseRating(item) {
|
||||||
return item.rating
|
return item.rating
|
||||||
? {
|
? {
|
||||||
system: 'CNC',
|
system: 'CNC',
|
||||||
value: item.rating.toUpperCase()
|
value: item.rating.toUpperCase()
|
||||||
}
|
}
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,39 +8,37 @@ dayjs.extend(timezone)
|
||||||
dayjs.extend(customParseFormat)
|
dayjs.extend(customParseFormat)
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
site: 'rtmklik.rtm.gov.my',
|
site: 'rtmklik.rtm.gov.my',
|
||||||
url: function ({ date, channel }) {
|
url: function ({ date, channel }) {
|
||||||
return `https://rtm.glueapi.io/v3/epg/${channel.site_id}/ChannelSchedule?dateStart=${date.format(
|
return `https://rtm.glueapi.io/v3/epg/${
|
||||||
'YYYY-MM-DD'
|
channel.site_id
|
||||||
)}&dateEnd=${date.format(
|
}/ChannelSchedule?dateStart=${date.format('YYYY-MM-DD')}&dateEnd=${date.format(
|
||||||
'YYYY-MM-DD'
|
'YYYY-MM-DD'
|
||||||
)}&timezone=0`
|
)}&timezone=0`
|
||||||
// return `https://rtm.glueapi.io/v3/epg/99/ChannelSchedule?dateStart=${date.format('YYYY-MM-DD')}&dateEnd=${date.format('YYYY-MM-DD')}&timezone=0`
|
// return `https://rtm.glueapi.io/v3/epg/99/ChannelSchedule?dateStart=${date.format('YYYY-MM-DD')}&dateEnd=${date.format('YYYY-MM-DD')}&timezone=0`
|
||||||
},
|
},
|
||||||
parser: function ({ content }) {
|
parser: function ({ content }) {
|
||||||
const programs = []
|
const programs = []
|
||||||
const items = parseItems(content)
|
const items = parseItems(content)
|
||||||
if (!items.length) return programs
|
if (!items.length) return programs
|
||||||
items.forEach(item => {
|
items.forEach(item => {
|
||||||
programs.push({
|
programs.push({
|
||||||
title: item.programTitle,
|
title: item.programTitle,
|
||||||
description: item.description,
|
description: item.description,
|
||||||
start: parseTime(item.dateTimeStart),
|
start: parseTime(item.dateTimeStart),
|
||||||
stop: parseTime(item.dateTimeEnd)
|
stop: parseTime(item.dateTimeEnd)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
return programs
|
return programs
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function parseItems(content) {
|
function parseItems(content) {
|
||||||
const data = JSON.parse(content)
|
const data = JSON.parse(content)
|
||||||
return data.schedule ? data.schedule : []
|
return data.schedule ? data.schedule : []
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseTime(time) {
|
function parseTime(time) {
|
||||||
return dayjs.utc(time, 'YYYY-MM-DDTHH:mm:ss')
|
return dayjs.utc(time, 'YYYY-MM-DDTHH:mm:ss')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,45 +1,45 @@
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
site: 'sky.de',
|
site: 'sky.de',
|
||||||
skip: true, // server returns error 403 (https://github.com/iptv-org/epg/runs/5435899744?check_suite_focus=true)
|
skip: true, // server returns error 403 (https://github.com/iptv-org/epg/runs/5435899744?check_suite_focus=true)
|
||||||
url: `https://www.sky.de/sgtvg/service/getBroadcastsForGrid`,
|
url: `https://www.sky.de/sgtvg/service/getBroadcastsForGrid`,
|
||||||
request: {
|
request: {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: function ({ channel, date }) {
|
data: function ({ channel, date }) {
|
||||||
return {
|
return {
|
||||||
cil: [channel.site_id],
|
cil: [channel.site_id],
|
||||||
d: date.valueOf()
|
d: date.valueOf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
parser: function ({ content, channel }) {
|
parser: function ({ content, channel }) {
|
||||||
const programs = []
|
const programs = []
|
||||||
const items = parseItems(content, channel)
|
const items = parseItems(content, channel)
|
||||||
items.forEach(item => {
|
items.forEach(item => {
|
||||||
programs.push({
|
programs.push({
|
||||||
title: item.et,
|
title: item.et,
|
||||||
description: item.epit,
|
description: item.epit,
|
||||||
category: item.ec,
|
category: item.ec,
|
||||||
start: dayjs(item.bsdt),
|
start: dayjs(item.bsdt),
|
||||||
stop: dayjs(item.bedt),
|
stop: dayjs(item.bedt),
|
||||||
season: item.sn,
|
season: item.sn,
|
||||||
episode: item.en,
|
episode: item.en,
|
||||||
icon: item.pu ? `http://sky.de${item.pu}` : null
|
icon: item.pu ? `http://sky.de${item.pu}` : null
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return programs
|
return programs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseContent(content, channel) {
|
function parseContent(content, channel) {
|
||||||
const json = JSON.parse(content)
|
const json = JSON.parse(content)
|
||||||
if (!Array.isArray(json.cl)) return null
|
if (!Array.isArray(json.cl)) return null
|
||||||
return json.cl.find(i => i.ci == channel.site_id)
|
return json.cl.find(i => i.ci == channel.site_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseItems(content, channel) {
|
function parseItems(content, channel) {
|
||||||
const data = parseContent(content, channel)
|
const data = parseContent(content, channel)
|
||||||
return data && Array.isArray(data.el) ? data.el : []
|
return data && Array.isArray(data.el) ? data.el : []
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,67 +1,67 @@
|
||||||
// npx epg-grabber --config=sites/sky.de/sky.de.config.js --channels=sites/sky.de/sky.de_de.channels.xml --output=guide.xml --days=2
|
// npx epg-grabber --config=sites/sky.de/sky.de.config.js --channels=sites/sky.de/sky.de_de.channels.xml --output=guide.xml --days=2
|
||||||
|
|
||||||
const { parser, url, request } = require('./sky.de.config.js')
|
const { parser, url, request } = require('./sky.de.config.js')
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
const utc = require('dayjs/plugin/utc')
|
const utc = require('dayjs/plugin/utc')
|
||||||
dayjs.extend(utc)
|
dayjs.extend(utc)
|
||||||
|
|
||||||
const date = dayjs.utc('2022-02-28', 'YYYY-MM-DD').startOf('d')
|
const date = dayjs.utc('2022-02-28', 'YYYY-MM-DD').startOf('d')
|
||||||
const channel = {
|
const channel = {
|
||||||
site_id: '522',
|
site_id: '522',
|
||||||
xmltv_id: 'WarnerTVComedyHD.de'
|
xmltv_id: 'WarnerTVComedyHD.de'
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = `{"cl":[{"ci":522,"el":[{"ei":122309300,"bsdt":1645916700000,"bst":"00:05","bedt":1645918200000,"len":25,"et":"King of Queens","ec":"Comedyserie","cop":"USA","yop":2001,"fsk":"ab 0 Jahre","epit":"Der Experte","sn":"4","en":"11","pu":"/static/img/program_guide/1522936_s.jpg"},{"ei":122309301,"bsdt":1645918200000,"bst":"00:30","bedt":1645919700000,"len":25,"et":"King of Queens","ec":"Comedyserie","cop":"USA","yop":2001,"fsk":"ab 0 Jahre","epit":"Speedy Gonzales","sn":"4","en":"12","pu":"/static/img/program_guide/1522937_s.jpg"}]}]}`
|
const content = `{"cl":[{"ci":522,"el":[{"ei":122309300,"bsdt":1645916700000,"bst":"00:05","bedt":1645918200000,"len":25,"et":"King of Queens","ec":"Comedyserie","cop":"USA","yop":2001,"fsk":"ab 0 Jahre","epit":"Der Experte","sn":"4","en":"11","pu":"/static/img/program_guide/1522936_s.jpg"},{"ei":122309301,"bsdt":1645918200000,"bst":"00:30","bedt":1645919700000,"len":25,"et":"King of Queens","ec":"Comedyserie","cop":"USA","yop":2001,"fsk":"ab 0 Jahre","epit":"Speedy Gonzales","sn":"4","en":"12","pu":"/static/img/program_guide/1522937_s.jpg"}]}]}`
|
||||||
|
|
||||||
it('can generate valid url', () => {
|
it('can generate valid url', () => {
|
||||||
expect(url).toBe('https://www.sky.de/sgtvg/service/getBroadcastsForGrid')
|
expect(url).toBe('https://www.sky.de/sgtvg/service/getBroadcastsForGrid')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can generate valid request method', () => {
|
it('can generate valid request method', () => {
|
||||||
expect(request.method).toBe('POST')
|
expect(request.method).toBe('POST')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can generate valid request data', () => {
|
it('can generate valid request data', () => {
|
||||||
expect(request.data({ channel, date })).toMatchObject({
|
expect(request.data({ channel, date })).toMatchObject({
|
||||||
cil: [channel.site_id],
|
cil: [channel.site_id],
|
||||||
d: date.valueOf()
|
d: date.valueOf()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can parse response', () => {
|
it('can parse response', () => {
|
||||||
const result = parser({ content, channel }).map(p => {
|
const result = parser({ content, channel }).map(p => {
|
||||||
p.start = p.start.toJSON()
|
p.start = p.start.toJSON()
|
||||||
p.stop = p.stop.toJSON()
|
p.stop = p.stop.toJSON()
|
||||||
return p
|
return p
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toMatchObject([
|
expect(result).toMatchObject([
|
||||||
{
|
{
|
||||||
title: 'King of Queens',
|
title: 'King of Queens',
|
||||||
description: 'Der Experte',
|
description: 'Der Experte',
|
||||||
category: 'Comedyserie',
|
category: 'Comedyserie',
|
||||||
start: '2022-02-26T23:05:00.000Z',
|
start: '2022-02-26T23:05:00.000Z',
|
||||||
stop: '2022-02-26T23:30:00.000Z',
|
stop: '2022-02-26T23:30:00.000Z',
|
||||||
season: '4',
|
season: '4',
|
||||||
episode: '11',
|
episode: '11',
|
||||||
icon: 'http://sky.de/static/img/program_guide/1522936_s.jpg'
|
icon: 'http://sky.de/static/img/program_guide/1522936_s.jpg'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'King of Queens',
|
title: 'King of Queens',
|
||||||
description: 'Speedy Gonzales',
|
description: 'Speedy Gonzales',
|
||||||
category: 'Comedyserie',
|
category: 'Comedyserie',
|
||||||
start: '2022-02-26T23:30:00.000Z',
|
start: '2022-02-26T23:30:00.000Z',
|
||||||
stop: '2022-02-26T23:55:00.000Z',
|
stop: '2022-02-26T23:55:00.000Z',
|
||||||
season: '4',
|
season: '4',
|
||||||
episode: '12',
|
episode: '12',
|
||||||
icon: 'http://sky.de/static/img/program_guide/1522937_s.jpg'
|
icon: 'http://sky.de/static/img/program_guide/1522937_s.jpg'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can handle empty guide', () => {
|
it('can handle empty guide', () => {
|
||||||
const result = parser({
|
const result = parser({
|
||||||
content: `[]`
|
content: `[]`
|
||||||
})
|
})
|
||||||
expect(result).toMatchObject([])
|
expect(result).toMatchObject([])
|
||||||
})
|
})
|
||||||
|
|
|
@ -119,13 +119,13 @@ function parseItems(content, channel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSeason(detail) {
|
function parseSeason(detail) {
|
||||||
if (!detail.seasonNumber) return null
|
if (!detail.seasonNumber) return null
|
||||||
if (String(detail.seasonNumber).length > 2) return null
|
if (String(detail.seasonNumber).length > 2) return null
|
||||||
return detail.seasonNumber
|
return detail.seasonNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseEpisode(detail) {
|
function parseEpisode(detail) {
|
||||||
if (!detail.episodeNumber) return null
|
if (!detail.episodeNumber) return null
|
||||||
if (String(detail.episodeNumber).length > 3) return null
|
if (String(detail.episodeNumber).length > 3) return null
|
||||||
return detail.episodeNumber
|
return detail.episodeNumber
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,81 +1,81 @@
|
||||||
// npx epg-grabber --config=sites/transvision.co.id/transvision.co.id.config.js --channels=sites/transvision.co.id/transvision.co.id_id.channels.xml --output=guide.xml --days=2
|
// npx epg-grabber --config=sites/transvision.co.id/transvision.co.id.config.js --channels=sites/transvision.co.id/transvision.co.id_id.channels.xml --output=guide.xml --days=2
|
||||||
|
|
||||||
const { parser, url, request } = require('./transvision.co.id.config.js')
|
const { parser, url, request } = require('./transvision.co.id.config.js')
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
const utc = require('dayjs/plugin/utc')
|
const utc = require('dayjs/plugin/utc')
|
||||||
dayjs.extend(utc)
|
dayjs.extend(utc)
|
||||||
|
|
||||||
const date = dayjs.utc('2022-03-10', 'YYYY-MM-DD').startOf('d')
|
const date = dayjs.utc('2022-03-10', 'YYYY-MM-DD').startOf('d')
|
||||||
const channel = {
|
const channel = {
|
||||||
site_id: 'TRIS',
|
site_id: 'TRIS',
|
||||||
xmltv_id: 'nsert.id'
|
xmltv_id: 'nsert.id'
|
||||||
}
|
}
|
||||||
const content = `<!doctype html><html class="no-js" lang="zxx"> <head></head> <body> <div class="wrapper"> <div id="content"> <div class="epg-area bg-white ptb-80"> <div class="container"> <div class="row"> <div class="col-sm-12"> <div class="component"> <div style="overflow: auto;"> <table> <tbody> <tr> <th>00:00:00</th> <td>Insert Today</td><td>Insert adalah program infotainment yang menceritakan berita-berita kehidupan selebriti serta gosip-gosipnya dan disajikan secara aktual dan faktual dengan suasana yang santai.</td></tr><tr> <th>01:00:00</th> <td>Brownis</td><td>Brownis atau obrolan manis merupakan program talkshow segar yang dipandu oleh Ruben Onsu bersama Ivan Gunawan.</td></tr><tr> <th>01:30:00</th> <td>Warga +62</td><td>Warga +62 menghadirkan trend penyebaran video/momen lucu yang juga dikenal sebagai video lucu Indonesia yang tersebar di media sosial.</td></tr><tr> <th>23:00:00</th> <td>Insert</td><td>Insert adalah program infotainment yang menceritakan berita-berita kehidupan selebriti serta gosip-gosipnya dan disajikan secara aktual dan faktual dengan suasana yang santai.</td></tr></tbody> </table> </div></div></div></div></div></div></div></div></body></html>`
|
const content = `<!doctype html><html class="no-js" lang="zxx"> <head></head> <body> <div class="wrapper"> <div id="content"> <div class="epg-area bg-white ptb-80"> <div class="container"> <div class="row"> <div class="col-sm-12"> <div class="component"> <div style="overflow: auto;"> <table> <tbody> <tr> <th>00:00:00</th> <td>Insert Today</td><td>Insert adalah program infotainment yang menceritakan berita-berita kehidupan selebriti serta gosip-gosipnya dan disajikan secara aktual dan faktual dengan suasana yang santai.</td></tr><tr> <th>01:00:00</th> <td>Brownis</td><td>Brownis atau obrolan manis merupakan program talkshow segar yang dipandu oleh Ruben Onsu bersama Ivan Gunawan.</td></tr><tr> <th>01:30:00</th> <td>Warga +62</td><td>Warga +62 menghadirkan trend penyebaran video/momen lucu yang juga dikenal sebagai video lucu Indonesia yang tersebar di media sosial.</td></tr><tr> <th>23:00:00</th> <td>Insert</td><td>Insert adalah program infotainment yang menceritakan berita-berita kehidupan selebriti serta gosip-gosipnya dan disajikan secara aktual dan faktual dengan suasana yang santai.</td></tr></tbody> </table> </div></div></div></div></div></div></div></div></body></html>`
|
||||||
|
|
||||||
it('can generate valid url', () => {
|
it('can generate valid url', () => {
|
||||||
expect(url).toBe('https://www.transvision.co.id/jadwalacara/epg')
|
expect(url).toBe('https://www.transvision.co.id/jadwalacara/epg')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can generate valid request method', () => {
|
it('can generate valid request method', () => {
|
||||||
expect(request.method).toBe('POST')
|
expect(request.method).toBe('POST')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can generate valid request headers', () => {
|
it('can generate valid request headers', () => {
|
||||||
expect(request.headers).toMatchObject({
|
expect(request.headers).toMatchObject({
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can generate valid request data', () => {
|
it('can generate valid request data', () => {
|
||||||
const result = request.data({ channel, date })
|
const result = request.data({ channel, date })
|
||||||
expect(result.get('ValidateEPG[channel_name]')).toBe('TRIS')
|
expect(result.get('ValidateEPG[channel_name]')).toBe('TRIS')
|
||||||
expect(result.get('ValidateEPG[tanggal]')).toBe('2022-03-10')
|
expect(result.get('ValidateEPG[tanggal]')).toBe('2022-03-10')
|
||||||
expect(result.get('ValidateEPG[sinopsis]')).toBe('')
|
expect(result.get('ValidateEPG[sinopsis]')).toBe('')
|
||||||
expect(result.get('yt0')).toBe('PROSES')
|
expect(result.get('yt0')).toBe('PROSES')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can parse response', () => {
|
it('can parse response', () => {
|
||||||
const result = parser({ content, channel, date }).map(p => {
|
const result = parser({ content, channel, date }).map(p => {
|
||||||
p.start = p.start.toJSON()
|
p.start = p.start.toJSON()
|
||||||
p.stop = p.stop.toJSON()
|
p.stop = p.stop.toJSON()
|
||||||
return p
|
return p
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toMatchObject([
|
expect(result).toMatchObject([
|
||||||
{
|
{
|
||||||
title: 'Insert Today',
|
title: 'Insert Today',
|
||||||
description:
|
description:
|
||||||
'Insert adalah program infotainment yang menceritakan berita-berita kehidupan selebriti serta gosip-gosipnya dan disajikan secara aktual dan faktual dengan suasana yang santai.',
|
'Insert adalah program infotainment yang menceritakan berita-berita kehidupan selebriti serta gosip-gosipnya dan disajikan secara aktual dan faktual dengan suasana yang santai.',
|
||||||
start: '2022-03-09T17:00:00.000Z',
|
start: '2022-03-09T17:00:00.000Z',
|
||||||
stop: '2022-03-09T18:00:00.000Z'
|
stop: '2022-03-09T18:00:00.000Z'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Brownis',
|
title: 'Brownis',
|
||||||
description:
|
description:
|
||||||
'Brownis atau obrolan manis merupakan program talkshow segar yang dipandu oleh Ruben Onsu bersama Ivan Gunawan.',
|
'Brownis atau obrolan manis merupakan program talkshow segar yang dipandu oleh Ruben Onsu bersama Ivan Gunawan.',
|
||||||
start: '2022-03-09T18:00:00.000Z',
|
start: '2022-03-09T18:00:00.000Z',
|
||||||
stop: '2022-03-09T18:30:00.000Z'
|
stop: '2022-03-09T18:30:00.000Z'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Warga +62',
|
title: 'Warga +62',
|
||||||
description:
|
description:
|
||||||
'Warga +62 menghadirkan trend penyebaran video/momen lucu yang juga dikenal sebagai video lucu Indonesia yang tersebar di media sosial.',
|
'Warga +62 menghadirkan trend penyebaran video/momen lucu yang juga dikenal sebagai video lucu Indonesia yang tersebar di media sosial.',
|
||||||
start: '2022-03-09T18:30:00.000Z',
|
start: '2022-03-09T18:30:00.000Z',
|
||||||
stop: '2022-03-10T16:00:00.000Z'
|
stop: '2022-03-10T16:00:00.000Z'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Insert',
|
title: 'Insert',
|
||||||
description:
|
description:
|
||||||
'Insert adalah program infotainment yang menceritakan berita-berita kehidupan selebriti serta gosip-gosipnya dan disajikan secara aktual dan faktual dengan suasana yang santai.',
|
'Insert adalah program infotainment yang menceritakan berita-berita kehidupan selebriti serta gosip-gosipnya dan disajikan secara aktual dan faktual dengan suasana yang santai.',
|
||||||
start: '2022-03-10T16:00:00.000Z',
|
start: '2022-03-10T16:00:00.000Z',
|
||||||
stop: '2022-03-10T16:30:00.000Z'
|
stop: '2022-03-10T16:30:00.000Z'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can handle empty guide', () => {
|
it('can handle empty guide', () => {
|
||||||
const result = parser({
|
const result = parser({
|
||||||
content: `<!doctype html><html class="no-js" lang="zxx"><head></head><body></body></html>`
|
content: `<!doctype html><html class="no-js" lang="zxx"><head></head><body></body></html>`
|
||||||
})
|
})
|
||||||
expect(result).toMatchObject([])
|
expect(result).toMatchObject([])
|
||||||
})
|
})
|
||||||
|
|
|
@ -35,8 +35,8 @@ it('can parse response', () => {
|
||||||
description:
|
description:
|
||||||
'Hellseherin Sedona Wiley wird tot aufgefunden. Die Ermittlungen führen zu einem alten Mord. Gordon Wallace wurde vor 15 Jahren beschuldigt, seine Frau getötet zu haben, jedoch wurde nie eine Leiche gefunden.',
|
'Hellseherin Sedona Wiley wird tot aufgefunden. Die Ermittlungen führen zu einem alten Mord. Gordon Wallace wurde vor 15 Jahren beschuldigt, seine Frau getötet zu haben, jedoch wurde nie eine Leiche gefunden.',
|
||||||
icon: 'https://new.static.tv.nu/13119997',
|
icon: 'https://new.static.tv.nu/13119997',
|
||||||
category: ['Action', 'Kriminaldrama', 'Mysterium', 'Spänning','Thriller'],
|
category: ['Action', 'Kriminaldrama', 'Mysterium', 'Spänning', 'Thriller'],
|
||||||
season : 6,
|
season: 6,
|
||||||
episode: 19
|
episode: 19
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
|
@ -1,57 +1,57 @@
|
||||||
// npx epg-grabber --config=sites/useetv.com/useetv.com.config.js --channels=sites/useetv.com/useetv.com_id.channels.xml --output=guide.xml --timeout=30000 --days=2
|
// npx epg-grabber --config=sites/useetv.com/useetv.com.config.js --channels=sites/useetv.com/useetv.com_id.channels.xml --output=guide.xml --timeout=30000 --days=2
|
||||||
|
|
||||||
const { parser, url, request } = require('./useetv.com.config.js')
|
const { parser, url, request } = require('./useetv.com.config.js')
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
const utc = require('dayjs/plugin/utc')
|
const utc = require('dayjs/plugin/utc')
|
||||||
dayjs.extend(utc)
|
dayjs.extend(utc)
|
||||||
|
|
||||||
const date = dayjs.utc('2022-08-08', 'YYYY-MM-DD').startOf('d')
|
const date = dayjs.utc('2022-08-08', 'YYYY-MM-DD').startOf('d')
|
||||||
const channel = {
|
const channel = {
|
||||||
site_id: 'metrotv',
|
site_id: 'metrotv',
|
||||||
xmltv_id: 'MetroTV.id'
|
xmltv_id: 'MetroTV.id'
|
||||||
}
|
}
|
||||||
const content = `<!DOCTYPE html><html><head></head><body><section class="live-tv-channels" id="top"><div><div class="schedule-list"><div id="pills-2022-08-08"><div class="row"><div><a class="schedule-item"><span class="replay"></span><p>07:00 - 07:05</p><b>Headline News</b></a></div><div><a class="schedule-item"><span class="replay"></span><p>07:05 - 07:30</p><b>Editorial Media Indonesia</b></a></div><div><a class="schedule-item"><span class="replay"></span><p>07:30 - 07:45</p><b>Editorial Media Indonesia</b></a></div><div><a class="schedule-item"><span class="replay"></span><p>07:45 - 08:00</p><b>Editorial Media Indonesia</b></a></div></div></div></div></div></section></body>`
|
const content = `<!DOCTYPE html><html><head></head><body><section class="live-tv-channels" id="top"><div><div class="schedule-list"><div id="pills-2022-08-08"><div class="row"><div><a class="schedule-item"><span class="replay"></span><p>07:00 - 07:05</p><b>Headline News</b></a></div><div><a class="schedule-item"><span class="replay"></span><p>07:05 - 07:30</p><b>Editorial Media Indonesia</b></a></div><div><a class="schedule-item"><span class="replay"></span><p>07:30 - 07:45</p><b>Editorial Media Indonesia</b></a></div><div><a class="schedule-item"><span class="replay"></span><p>07:45 - 08:00</p><b>Editorial Media Indonesia</b></a></div></div></div></div></div></section></body>`
|
||||||
|
|
||||||
it('can generate valid url', () => {
|
it('can generate valid url', () => {
|
||||||
expect(url({ channel })).toBe('https://www.useetv.com/tvod/metrotv')
|
expect(url({ channel })).toBe('https://www.useetv.com/tvod/metrotv')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can parse response', () => {
|
it('can parse response', () => {
|
||||||
const result = parser({ content, channel, date }).map(p => {
|
const result = parser({ content, channel, date }).map(p => {
|
||||||
p.start = p.start.toJSON()
|
p.start = p.start.toJSON()
|
||||||
p.stop = p.stop.toJSON()
|
p.stop = p.stop.toJSON()
|
||||||
return p
|
return p
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result).toMatchObject([
|
expect(result).toMatchObject([
|
||||||
{
|
{
|
||||||
title: 'Headline News',
|
title: 'Headline News',
|
||||||
start: '2022-08-08T00:00:00.000Z',
|
start: '2022-08-08T00:00:00.000Z',
|
||||||
stop: '2022-08-08T00:05:00.000Z'
|
stop: '2022-08-08T00:05:00.000Z'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Editorial Media Indonesia',
|
title: 'Editorial Media Indonesia',
|
||||||
start: '2022-08-08T00:05:00.000Z',
|
start: '2022-08-08T00:05:00.000Z',
|
||||||
stop: '2022-08-08T00:30:00.000Z'
|
stop: '2022-08-08T00:30:00.000Z'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Editorial Media Indonesia',
|
title: 'Editorial Media Indonesia',
|
||||||
start: '2022-08-08T00:30:00.000Z',
|
start: '2022-08-08T00:30:00.000Z',
|
||||||
stop: '2022-08-08T00:45:00.000Z'
|
stop: '2022-08-08T00:45:00.000Z'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Editorial Media Indonesia',
|
title: 'Editorial Media Indonesia',
|
||||||
start: '2022-08-08T00:45:00.000Z',
|
start: '2022-08-08T00:45:00.000Z',
|
||||||
stop: '2022-08-08T01:00:00.000Z'
|
stop: '2022-08-08T01:00:00.000Z'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can handle empty guide', () => {
|
it('can handle empty guide', () => {
|
||||||
const result = parser({
|
const result = parser({
|
||||||
date,
|
date,
|
||||||
channel,
|
channel,
|
||||||
content: `<!DOCTYPE html><html><head></head><body></body></html>`
|
content: `<!DOCTYPE html><html><head></head><body></body></html>`
|
||||||
})
|
})
|
||||||
expect(result).toMatchObject([])
|
expect(result).toMatchObject([])
|
||||||
})
|
})
|
||||||
|
|
|
@ -29,16 +29,16 @@ module.exports = {
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
// items.forEach(item => {
|
// items.forEach(item => {
|
||||||
for (let item of items) {
|
for (let item of items) {
|
||||||
const detail = await loadProgramDetails(item)
|
const detail = await loadProgramDetails(item)
|
||||||
programs.push({
|
programs.push({
|
||||||
title: item.t,
|
title: item.t,
|
||||||
description: parseDescription(detail),
|
description: parseDescription(detail),
|
||||||
category: parseCategory(detail),
|
category: parseCategory(detail),
|
||||||
season: parseSeason(detail),
|
season: parseSeason(detail),
|
||||||
episode: parseEpisode(detail),
|
episode: parseEpisode(detail),
|
||||||
start: parseStart(item),
|
start: parseStart(item),
|
||||||
stop: parseStop(item)
|
stop: parseStop(item)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
//)
|
//)
|
||||||
|
|
||||||
|
@ -61,14 +61,14 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadProgramDetails(item) {
|
async function loadProgramDetails(item) {
|
||||||
if (!item.i) return {}
|
if (!item.i) return {}
|
||||||
const url = `${API_ENDPOINT}/listings/${item.i}`
|
const url = `${API_ENDPOINT}/listings/${item.i}`
|
||||||
const data = await axios
|
const data = await axios
|
||||||
.get(url)
|
.get(url)
|
||||||
.then(r => r.data)
|
.then(r => r.data)
|
||||||
.catch(console.log)
|
.catch(console.log)
|
||||||
return data || {}
|
return data || {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseStart(item) {
|
function parseStart(item) {
|
||||||
return dayjs(item.s)
|
return dayjs(item.s)
|
||||||
|
@ -86,27 +86,26 @@ function parseItems(content, channel) {
|
||||||
return entity ? entity.l : []
|
return entity ? entity.l : []
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseDescription(detail){
|
function parseDescription(detail) {
|
||||||
return detail.program.longDescription || null
|
return detail.program.longDescription || null
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseCategory(detail) {
|
function parseCategory(detail) {
|
||||||
let categories = []
|
let categories = []
|
||||||
detail.program.categories.forEach(category => {
|
detail.program.categories.forEach(category => {
|
||||||
categories.push(category.title)
|
categories.push(category.title)
|
||||||
});
|
})
|
||||||
return categories
|
return categories
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSeason(detail) {
|
function parseSeason(detail) {
|
||||||
if (!detail.program.seriesNumber) return null
|
if (!detail.program.seriesNumber) return null
|
||||||
if (String(detail.program.seriesNumber).length > 2) return null
|
if (String(detail.program.seriesNumber).length > 2) return null
|
||||||
return detail.program.seriesNumber
|
return detail.program.seriesNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseEpisode(detail) {
|
function parseEpisode(detail) {
|
||||||
if (!detail.program.seriesEpisodeNumber) return null
|
if (!detail.program.seriesEpisodeNumber) return null
|
||||||
if (String(detail.program.seriesEpisodeNumber).length > 3) return null
|
if (String(detail.program.seriesEpisodeNumber).length > 3) return null
|
||||||
return detail.program.seriesEpisodeNumber
|
return detail.program.seriesEpisodeNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,121 +13,143 @@ jest.mock('axios')
|
||||||
|
|
||||||
const date = dayjs.utc('2022-03-17', 'YYYY-MM-DD').startOf('d')
|
const date = dayjs.utc('2022-03-17', 'YYYY-MM-DD').startOf('d')
|
||||||
const channel = {
|
const channel = {
|
||||||
site_id: '1761',
|
site_id: '1761',
|
||||||
xmltv_id: 'ViaplaySports1.uk'
|
xmltv_id: 'ViaplaySports1.uk'
|
||||||
}
|
}
|
||||||
|
|
||||||
it('can generate valid url', () => {
|
it('can generate valid url', () => {
|
||||||
expect(url({ date })).toBe(
|
expect(url({ date })).toBe(
|
||||||
'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/programschedules/20220317/1'
|
'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/programschedules/20220317/1'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can parse response', done => {
|
it('can parse response', done => {
|
||||||
const content = `{"entryCount":410,"totalResults":410,"updated":1647459686755,"expires":1647460298218,"title":"EPG","periods":4,"periodStartTime":1647475200000,"periodEndTime":1647496800000,"entries":[{"o":"lgi-gb-prodobo-master:1761","l":[{"i":"crid:~~2F~~2Fgn.tv~~2F21763419~~2FEP013520125005,imi:de610af9a9b049c8a0245173f273136d36458f6f","t":"Live: NHL Hockey","s":1647473400000,"e":1647484200000,"c":"lgi-gb-prodobo-master:genre-27","a":false,"r":true,"rm":true,"rs":0,"re":2592000,"rst":"cloud","ra":false,"ad":[],"sl":[]}]}]}`
|
const content = `{"entryCount":410,"totalResults":410,"updated":1647459686755,"expires":1647460298218,"title":"EPG","periods":4,"periodStartTime":1647475200000,"periodEndTime":1647496800000,"entries":[{"o":"lgi-gb-prodobo-master:1761","l":[{"i":"crid:~~2F~~2Fgn.tv~~2F21763419~~2FEP013520125005,imi:de610af9a9b049c8a0245173f273136d36458f6f","t":"Live: NHL Hockey","s":1647473400000,"e":1647484200000,"c":"lgi-gb-prodobo-master:genre-27","a":false,"r":true,"rm":true,"rs":0,"re":2592000,"rst":"cloud","ra":false,"ad":[],"sl":[]}]}]}`
|
||||||
|
|
||||||
axios.get.mockImplementation(url => {
|
axios.get.mockImplementation(url => {
|
||||||
if (url === 'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/programschedules/20220317/2') {
|
if (
|
||||||
return Promise.resolve({
|
url === 'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/programschedules/20220317/2'
|
||||||
data: JSON.parse(
|
) {
|
||||||
`{"entryCount":410,"totalResults":410,"updated":1647460887411,"expires":1647461895572,"title":"EPG","periods":4,"periodStartTime":1647496800000,"periodEndTime":1647518400000,"entries":[{"o":"lgi-gb-prodobo-master:1761","l":[{"i":"crid:~~2F~~2Fgn.tv~~2F21720572~~2FEP021779870005,imi:d4324f579ad36992f0c3f6e6d35a9b93e98cb78a","t":"Challenge Cup Ice Hockey","s":1647484200000,"e":1647496800000,"c":"lgi-gb-prodobo-master:genre-123","a":false,"r":true,"rm":true,"rs":0,"re":2592000,"rst":"cloud","ra":false,"ad":[],"sl":[]}]}]}`
|
return Promise.resolve({
|
||||||
)
|
data: JSON.parse(
|
||||||
})
|
`{"entryCount":410,"totalResults":410,"updated":1647460887411,"expires":1647461895572,"title":"EPG","periods":4,"periodStartTime":1647496800000,"periodEndTime":1647518400000,"entries":[{"o":"lgi-gb-prodobo-master:1761","l":[{"i":"crid:~~2F~~2Fgn.tv~~2F21720572~~2FEP021779870005,imi:d4324f579ad36992f0c3f6e6d35a9b93e98cb78a","t":"Challenge Cup Ice Hockey","s":1647484200000,"e":1647496800000,"c":"lgi-gb-prodobo-master:genre-123","a":false,"r":true,"rm":true,"rs":0,"re":2592000,"rst":"cloud","ra":false,"ad":[],"sl":[]}]}]}`
|
||||||
} else if (url === 'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/programschedules/20220317/3') {
|
)
|
||||||
return Promise.resolve({
|
})
|
||||||
data: JSON.parse(
|
} else if (
|
||||||
`{"entryCount":410,"totalResults":410,"updated":1647460871713,"expires":1647461910282,"title":"EPG","periods":4,"periodStartTime":1647518400000,"periodEndTime":1647540000000,"entries":[{"o":"lgi-gb-prodobo-master:1761","l":[{"i":"crid:~~2F~~2Fgn.tv~~2F21763550~~2FEP012830215435,imi:9692f5ceb0b63354262339e8529e3a9cb57add9c","t":"NHL Hockey","s":1647511200000,"e":1647518400000,"c":"lgi-gb-prodobo-master:genre-27","a":false,"r":true,"rm":true,"rs":0,"re":2592000,"rst":"cloud","ra":false,"ad":[],"sl":[]}]}]}`
|
url === 'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/programschedules/20220317/3'
|
||||||
)
|
) {
|
||||||
})
|
return Promise.resolve({
|
||||||
} else if (url === 'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/programschedules/20220317/4') {
|
data: JSON.parse(
|
||||||
return Promise.resolve({
|
`{"entryCount":410,"totalResults":410,"updated":1647460871713,"expires":1647461910282,"title":"EPG","periods":4,"periodStartTime":1647518400000,"periodEndTime":1647540000000,"entries":[{"o":"lgi-gb-prodobo-master:1761","l":[{"i":"crid:~~2F~~2Fgn.tv~~2F21763550~~2FEP012830215435,imi:9692f5ceb0b63354262339e8529e3a9cb57add9c","t":"NHL Hockey","s":1647511200000,"e":1647518400000,"c":"lgi-gb-prodobo-master:genre-27","a":false,"r":true,"rm":true,"rs":0,"re":2592000,"rst":"cloud","ra":false,"ad":[],"sl":[]}]}]}`
|
||||||
data: JSON.parse(
|
)
|
||||||
`{"entryCount":410,"totalResults":410,"updated":1647460871713,"expires":1647461920720,"title":"EPG","periods":4,"periodStartTime":1647540000000,"periodEndTime":1647561600000,"entries":[{"o":"lgi-gb-prodobo-master:1761","l":[{"i":"crid:~~2F~~2Fgn.tv~~2F21764379~~2FEP025886890145,imi:c02da14358110cec07d14dc154717ce62ba2f489","t":"Boxing World Weekly","s":1647539100000,"e":1647540900000,"c":"lgi-gb-prodobo-master:genre-27","a":false,"r":true,"rm":true,"rs":0,"re":2592000,"rst":"cloud","ra":false,"ad":[],"sl":[]}]}]}`
|
})
|
||||||
)
|
} else if (
|
||||||
})
|
url === 'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/programschedules/20220317/4'
|
||||||
} else if (url === 'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/listings/crid:~~2F~~2Fgn.tv~~2F21763419~~2FEP013520125005,imi:de610af9a9b049c8a0245173f273136d36458f6f') {
|
) {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
data: JSON.parse(
|
data: JSON.parse(
|
||||||
`{"id":"crid:~~2F~~2Fgn.tv~~2F21763419~~2FEP013520125005,imi:de610af9a9b049c8a0245173f273136d36458f6f","startTime":1647473400000,"endTime":1647484200000,"actualStartTime":1647473400000,"actualEndTime":1647484200000,"expirationDate":1648078200000,"stationId":"lgi-gb-prodobo-master:1761","imi":"imi:de610af9a9b049c8a0245173f273136d36458f6f","scCridImi":"crid:~~2F~~2Fgn.tv~~2F21763419~~2FEP013520125005,imi:de610af9a9b049c8a0245173f273136d36458f6f","mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F8396306~~2FSH013520120000","program":{"id":"crid:~~2F~~2Fgn.tv~~2F21763419~~2FEP013520125005","title":"Live: NHL Hockey","description":"The Boston Bruins make the trip to Xcel Energy Center for an NHL clash with the Minnesota Wild.","longDescription":"The Boston Bruins make the trip to Xcel Energy Center for an NHL clash with the Minnesota Wild.","medium":"TV","categories":[{"id":"lgi-gb-prodobo-master:genre-27","title":"Sport","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"},{"id":"lgi-gb-prodobo-master:genre-123","title":"Ice Hockey","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"}],"isAdult":false,"cast":[],"directors":[],"images":[{"assetType":"HighResLandscapeProductionStill","assetTypes":["HighResLandscapeProductionStill"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p21763419_tb2_h8_aa.jpg"},{"assetType":"HighResPortrait","assetTypes":["HighResPortrait"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p21763419_tb2_v12_aa.jpg"}],"parentId":"crid:~~2F~~2Fgn.tv~~2F123456789~~2FSH013520120000","rootId":"crid:~~2F~~2Fgn.tv~~2F8396306~~2FSH013520120000","parentalRatingDescription":[],"resolutions":[],"mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F8396306~~2FSH013520120000","shortDescription":"The Boston Bruins make the trip to Xcel Energy Center for an NHL clash with the Minnesota Wild.","mediaType":"Episode","year":"2022","seriesEpisodeNumber":"2022031605","seriesNumber":"20120000","videos":[],"videoStreams":[],"entitlements":["VIP","_OPEN_"],"currentProductIds":[],"currentTvodProductIds":[],"secondaryTitle":"Boston Bruins at Minnesota Wild"},"parentId":"crid:~~2F~~2Fgn.tv~~2F123456789~~2FSH013520120000","rootId":"crid:~~2F~~2Fgn.tv~~2F8396306~~2FSH013520120000","replayTvAvailable":true,"audioTracks":[{"lang":"en","audioPurpose":"main"}],"ratings":[],"offersLatestExpirationDate":1647484200000,"replayTvStartOffset":0,"replayTvEndOffset":2592000,"replayEnabledOnMobileClients":true,"replaySource":"cloud","isGoReplayableViaExternalApp":false,"mergedId":"21763419|en-GB"}`
|
`{"entryCount":410,"totalResults":410,"updated":1647460871713,"expires":1647461920720,"title":"EPG","periods":4,"periodStartTime":1647540000000,"periodEndTime":1647561600000,"entries":[{"o":"lgi-gb-prodobo-master:1761","l":[{"i":"crid:~~2F~~2Fgn.tv~~2F21764379~~2FEP025886890145,imi:c02da14358110cec07d14dc154717ce62ba2f489","t":"Boxing World Weekly","s":1647539100000,"e":1647540900000,"c":"lgi-gb-prodobo-master:genre-27","a":false,"r":true,"rm":true,"rs":0,"re":2592000,"rst":"cloud","ra":false,"ad":[],"sl":[]}]}]}`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
} else if (url === 'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/listings/crid:~~2F~~2Fgn.tv~~2F21720572~~2FEP021779870005,imi:d4324f579ad36992f0c3f6e6d35a9b93e98cb78a') {
|
} else if (
|
||||||
return Promise.resolve({
|
url ===
|
||||||
data: JSON.parse(
|
'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/listings/crid:~~2F~~2Fgn.tv~~2F21763419~~2FEP013520125005,imi:de610af9a9b049c8a0245173f273136d36458f6f'
|
||||||
`{"id":"crid:~~2F~~2Fgn.tv~~2F21720572~~2FEP021779870005,imi:d4324f579ad36992f0c3f6e6d35a9b93e98cb78a","startTime":1647484200000,"endTime":1647496800000,"actualStartTime":1647484200000,"actualEndTime":1647496800000,"expirationDate":1648089000000,"stationId":"lgi-gb-prodobo-master:1761","imi":"imi:d4324f579ad36992f0c3f6e6d35a9b93e98cb78a","scCridImi":"crid:~~2F~~2Fgn.tv~~2F21720572~~2FEP021779870005,imi:d4324f579ad36992f0c3f6e6d35a9b93e98cb78a","mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F11743980~~2FSH021779870000","program":{"id":"crid:~~2F~~2Fgn.tv~~2F21720572~~2FEP021779870005","title":"Challenge Cup Ice Hockey","description":"Exclusive coverage from SSE Arena of the Premier Sports Challenge Final between Belfast Giants and Cardiff Devils.","longDescription":"Exclusive coverage from SSE Arena of the Premier Sports Challenge Final between Belfast Giants and Cardiff Devils.","medium":"TV","categories":[{"id":"lgi-gb-prodobo-master:genre-123","title":"Ice Hockey","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"}],"isAdult":false,"cast":[],"directors":[],"images":[{"assetType":"HighResPortrait","assetTypes":["HighResPortrait"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p11743980_b_v12_aa.jpg"}],"parentId":"crid:~~2F~~2Fgn.tv~~2F123456789~~2FSH021779870000","rootId":"crid:~~2F~~2Fgn.tv~~2F11743980~~2FSH021779870000","parentalRatingDescription":[],"resolutions":[],"mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F11743980~~2FSH021779870000","shortDescription":"Exclusive coverage from SSE Arena of the Premier Sports Challenge Final between Belfast Giants and Cardiff Devils.","mediaType":"Episode","year":"2022","seriesEpisodeNumber":"2022031605","seriesNumber":"79870000","videos":[],"videoStreams":[],"entitlements":["VIP","_OPEN_"],"currentProductIds":[],"currentTvodProductIds":[],"secondaryTitle":"Final: Belfast Giants v Cardiff Devils"},"parentId":"crid:~~2F~~2Fgn.tv~~2F123456789~~2FSH021779870000","rootId":"crid:~~2F~~2Fgn.tv~~2F11743980~~2FSH021779870000","replayTvAvailable":true,"audioTracks":[{"lang":"en","audioPurpose":"main"}],"ratings":[],"offersLatestExpirationDate":1647928800000,"replayTvStartOffset":0,"replayTvEndOffset":2592000,"replayEnabledOnMobileClients":true,"replaySource":"cloud","isGoReplayableViaExternalApp":false,"mergedId":"21720572|en-GB"}`
|
) {
|
||||||
)
|
return Promise.resolve({
|
||||||
})
|
data: JSON.parse(
|
||||||
} else if (url === 'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/listings/crid:~~2F~~2Fgn.tv~~2F21763550~~2FEP012830215435,imi:9692f5ceb0b63354262339e8529e3a9cb57add9c') {
|
`{"id":"crid:~~2F~~2Fgn.tv~~2F21763419~~2FEP013520125005,imi:de610af9a9b049c8a0245173f273136d36458f6f","startTime":1647473400000,"endTime":1647484200000,"actualStartTime":1647473400000,"actualEndTime":1647484200000,"expirationDate":1648078200000,"stationId":"lgi-gb-prodobo-master:1761","imi":"imi:de610af9a9b049c8a0245173f273136d36458f6f","scCridImi":"crid:~~2F~~2Fgn.tv~~2F21763419~~2FEP013520125005,imi:de610af9a9b049c8a0245173f273136d36458f6f","mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F8396306~~2FSH013520120000","program":{"id":"crid:~~2F~~2Fgn.tv~~2F21763419~~2FEP013520125005","title":"Live: NHL Hockey","description":"The Boston Bruins make the trip to Xcel Energy Center for an NHL clash with the Minnesota Wild.","longDescription":"The Boston Bruins make the trip to Xcel Energy Center for an NHL clash with the Minnesota Wild.","medium":"TV","categories":[{"id":"lgi-gb-prodobo-master:genre-27","title":"Sport","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"},{"id":"lgi-gb-prodobo-master:genre-123","title":"Ice Hockey","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"}],"isAdult":false,"cast":[],"directors":[],"images":[{"assetType":"HighResLandscapeProductionStill","assetTypes":["HighResLandscapeProductionStill"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p21763419_tb2_h8_aa.jpg"},{"assetType":"HighResPortrait","assetTypes":["HighResPortrait"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p21763419_tb2_v12_aa.jpg"}],"parentId":"crid:~~2F~~2Fgn.tv~~2F123456789~~2FSH013520120000","rootId":"crid:~~2F~~2Fgn.tv~~2F8396306~~2FSH013520120000","parentalRatingDescription":[],"resolutions":[],"mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F8396306~~2FSH013520120000","shortDescription":"The Boston Bruins make the trip to Xcel Energy Center for an NHL clash with the Minnesota Wild.","mediaType":"Episode","year":"2022","seriesEpisodeNumber":"2022031605","seriesNumber":"20120000","videos":[],"videoStreams":[],"entitlements":["VIP","_OPEN_"],"currentProductIds":[],"currentTvodProductIds":[],"secondaryTitle":"Boston Bruins at Minnesota Wild"},"parentId":"crid:~~2F~~2Fgn.tv~~2F123456789~~2FSH013520120000","rootId":"crid:~~2F~~2Fgn.tv~~2F8396306~~2FSH013520120000","replayTvAvailable":true,"audioTracks":[{"lang":"en","audioPurpose":"main"}],"ratings":[],"offersLatestExpirationDate":1647484200000,"replayTvStartOffset":0,"replayTvEndOffset":2592000,"replayEnabledOnMobileClients":true,"replaySource":"cloud","isGoReplayableViaExternalApp":false,"mergedId":"21763419|en-GB"}`
|
||||||
return Promise.resolve({
|
)
|
||||||
data: JSON.parse(
|
})
|
||||||
`{"id":"crid:~~2F~~2Fgn.tv~~2F21763550~~2FEP012830215435,imi:9692f5ceb0b63354262339e8529e3a9cb57add9c","startTime":1647511200000,"endTime":1647518400000,"actualStartTime":1647511200000,"actualEndTime":1647518400000,"expirationDate":1648116000000,"stationId":"lgi-gb-prodobo-master:1761","imi":"imi:9692f5ceb0b63354262339e8529e3a9cb57add9c","scCridImi":"crid:~~2F~~2Fgn.tv~~2F21763550~~2FEP012830215435,imi:9692f5ceb0b63354262339e8529e3a9cb57add9c","mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F448880~~2FSH012830210000","program":{"id":"crid:~~2F~~2Fgn.tv~~2F21763550~~2FEP012830215435","title":"NHL Hockey","description":"The Calgary Flames play host to the New Jersey Devils in this NHL encounter from Scotiabank Saddledome.","longDescription":"The Calgary Flames play host to the New Jersey Devils in this NHL encounter from Scotiabank Saddledome.","medium":"TV","categories":[{"id":"lgi-gb-prodobo-master:genre-27","title":"Sport","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"},{"id":"lgi-gb-prodobo-master:genre-123","title":"Ice Hockey","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"}],"isAdult":false,"cast":[],"directors":[],"images":[{"assetType":"HighResLandscapeProductionStill","assetTypes":["HighResLandscapeProductionStill"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p448880_b_h8_ak.jpg"},{"assetType":"HighResPortrait","assetTypes":["HighResPortrait"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p448880_b_v12_ak.jpg"}],"parentId":"crid:~~2F~~2Fgn.tv~~2F21275201~~2FSH012830210000","rootId":"crid:~~2F~~2Fgn.tv~~2F448880~~2FSH012830210000","parentalRatingDescription":[],"resolutions":[],"mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F448880~~2FSH012830210000","shortDescription":"The Calgary Flames play host to the New Jersey Devils in this NHL encounter from Scotiabank Saddledome.","mediaType":"Episode","year":"2022","seriesEpisodeNumber":"194","seriesNumber":"102022","videos":[],"videoStreams":[],"entitlements":["VIP","_OPEN_"],"currentProductIds":[],"currentTvodProductIds":[],"secondaryTitle":"New Jersey Devils at Calgary Flames"},"parentId":"crid:~~2F~~2Fgn.tv~~2F21275201~~2FSH012830210000","rootId":"crid:~~2F~~2Fgn.tv~~2F448880~~2FSH012830210000","replayTvAvailable":true,"audioTracks":[{"lang":"en","audioPurpose":"main"}],"ratings":[],"offersLatestExpirationDate":1647583200000,"replayTvStartOffset":0,"replayTvEndOffset":2592000,"replayEnabledOnMobileClients":true,"replaySource":"cloud","isGoReplayableViaExternalApp":false,"mergedId":"21763550|en-GB"}`
|
} else if (
|
||||||
)
|
url ===
|
||||||
})
|
'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/listings/crid:~~2F~~2Fgn.tv~~2F21720572~~2FEP021779870005,imi:d4324f579ad36992f0c3f6e6d35a9b93e98cb78a'
|
||||||
} else if (url === 'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/listings/crid:~~2F~~2Fgn.tv~~2F21764379~~2FEP025886890145,imi:c02da14358110cec07d14dc154717ce62ba2f489') {
|
) {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
data: JSON.parse(
|
data: JSON.parse(
|
||||||
`{"id":"crid:~~2F~~2Fgn.tv~~2F21764379~~2FEP025886890145,imi:c02da14358110cec07d14dc154717ce62ba2f489","startTime":1647539100000,"endTime":1647540900000,"actualStartTime":1647539100000,"actualEndTime":1647540900000,"expirationDate":1648143900000,"stationId":"lgi-gb-prodobo-master:1761","imi":"imi:c02da14358110cec07d14dc154717ce62ba2f489","scCridImi":"crid:~~2F~~2Fgn.tv~~2F21764379~~2FEP025886890145,imi:c02da14358110cec07d14dc154717ce62ba2f489","mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F13641079~~2FSH025886890000","program":{"id":"crid:~~2F~~2Fgn.tv~~2F21764379~~2FEP025886890145","title":"Boxing World Weekly","description":"A weekly series designed to showcase the best of our sport. Boxing World features news, highlights, previews and profiles from the world of pro boxing.","longDescription":"A weekly series designed to showcase the best of our sport. Boxing World features news, highlights, previews and profiles from the world of pro boxing.","medium":"TV","categories":[{"id":"lgi-gb-prodobo-master:genre-27","title":"Sport","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"},{"id":"lgi-gb-prodobo-master:genre-83","title":"Boxing","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"}],"isAdult":false,"cast":[],"directors":[],"images":[{"assetType":"HighResPortrait","assetTypes":["HighResPortrait"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p19340143_b_v8_aa.jpg"},{"assetType":"TitleTreatment","assetTypes":["TitleTreatment"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p13641079_ttl_h95_aa.png"}],"parentId":"crid:~~2F~~2Fgn.tv~~2F19340143~~2FSH025886890000","rootId":"crid:~~2F~~2Fgn.tv~~2F13641079~~2FSH025886890000","parentalRatingDescription":[],"resolutions":[],"mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F13641079~~2FSH025886890000","shortDescription":"A weekly series designed to showcase the best of our sport. Boxing World features news, highlights, previews and profiles from the world of pro boxing.","mediaType":"Episode","year":"2022","seriesEpisodeNumber":"60","seriesNumber":"4","videos":[],"videoStreams":[],"entitlements":["VIP","_OPEN_"],"currentProductIds":[],"currentTvodProductIds":[]},"parentId":"crid:~~2F~~2Fgn.tv~~2F19340143~~2FSH025886890000","rootId":"crid:~~2F~~2Fgn.tv~~2F13641079~~2FSH025886890000","replayTvAvailable":true,"audioTracks":[{"lang":"en","audioPurpose":"main"}],"ratings":[],"offersLatestExpirationDate":1648142400000,"replayTvStartOffset":0,"replayTvEndOffset":2592000,"replayEnabledOnMobileClients":true,"replaySource":"cloud","isGoReplayableViaExternalApp":false,"mergedId":"21764379|en-GB"}`
|
`{"id":"crid:~~2F~~2Fgn.tv~~2F21720572~~2FEP021779870005,imi:d4324f579ad36992f0c3f6e6d35a9b93e98cb78a","startTime":1647484200000,"endTime":1647496800000,"actualStartTime":1647484200000,"actualEndTime":1647496800000,"expirationDate":1648089000000,"stationId":"lgi-gb-prodobo-master:1761","imi":"imi:d4324f579ad36992f0c3f6e6d35a9b93e98cb78a","scCridImi":"crid:~~2F~~2Fgn.tv~~2F21720572~~2FEP021779870005,imi:d4324f579ad36992f0c3f6e6d35a9b93e98cb78a","mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F11743980~~2FSH021779870000","program":{"id":"crid:~~2F~~2Fgn.tv~~2F21720572~~2FEP021779870005","title":"Challenge Cup Ice Hockey","description":"Exclusive coverage from SSE Arena of the Premier Sports Challenge Final between Belfast Giants and Cardiff Devils.","longDescription":"Exclusive coverage from SSE Arena of the Premier Sports Challenge Final between Belfast Giants and Cardiff Devils.","medium":"TV","categories":[{"id":"lgi-gb-prodobo-master:genre-123","title":"Ice Hockey","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"}],"isAdult":false,"cast":[],"directors":[],"images":[{"assetType":"HighResPortrait","assetTypes":["HighResPortrait"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p11743980_b_v12_aa.jpg"}],"parentId":"crid:~~2F~~2Fgn.tv~~2F123456789~~2FSH021779870000","rootId":"crid:~~2F~~2Fgn.tv~~2F11743980~~2FSH021779870000","parentalRatingDescription":[],"resolutions":[],"mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F11743980~~2FSH021779870000","shortDescription":"Exclusive coverage from SSE Arena of the Premier Sports Challenge Final between Belfast Giants and Cardiff Devils.","mediaType":"Episode","year":"2022","seriesEpisodeNumber":"2022031605","seriesNumber":"79870000","videos":[],"videoStreams":[],"entitlements":["VIP","_OPEN_"],"currentProductIds":[],"currentTvodProductIds":[],"secondaryTitle":"Final: Belfast Giants v Cardiff Devils"},"parentId":"crid:~~2F~~2Fgn.tv~~2F123456789~~2FSH021779870000","rootId":"crid:~~2F~~2Fgn.tv~~2F11743980~~2FSH021779870000","replayTvAvailable":true,"audioTracks":[{"lang":"en","audioPurpose":"main"}],"ratings":[],"offersLatestExpirationDate":1647928800000,"replayTvStartOffset":0,"replayTvEndOffset":2592000,"replayEnabledOnMobileClients":true,"replaySource":"cloud","isGoReplayableViaExternalApp":false,"mergedId":"21720572|en-GB"}`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
} else {
|
} else if (
|
||||||
return Promise.resolve({ data: '' })
|
url ===
|
||||||
|
'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/listings/crid:~~2F~~2Fgn.tv~~2F21763550~~2FEP012830215435,imi:9692f5ceb0b63354262339e8529e3a9cb57add9c'
|
||||||
|
) {
|
||||||
|
return Promise.resolve({
|
||||||
|
data: JSON.parse(
|
||||||
|
`{"id":"crid:~~2F~~2Fgn.tv~~2F21763550~~2FEP012830215435,imi:9692f5ceb0b63354262339e8529e3a9cb57add9c","startTime":1647511200000,"endTime":1647518400000,"actualStartTime":1647511200000,"actualEndTime":1647518400000,"expirationDate":1648116000000,"stationId":"lgi-gb-prodobo-master:1761","imi":"imi:9692f5ceb0b63354262339e8529e3a9cb57add9c","scCridImi":"crid:~~2F~~2Fgn.tv~~2F21763550~~2FEP012830215435,imi:9692f5ceb0b63354262339e8529e3a9cb57add9c","mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F448880~~2FSH012830210000","program":{"id":"crid:~~2F~~2Fgn.tv~~2F21763550~~2FEP012830215435","title":"NHL Hockey","description":"The Calgary Flames play host to the New Jersey Devils in this NHL encounter from Scotiabank Saddledome.","longDescription":"The Calgary Flames play host to the New Jersey Devils in this NHL encounter from Scotiabank Saddledome.","medium":"TV","categories":[{"id":"lgi-gb-prodobo-master:genre-27","title":"Sport","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"},{"id":"lgi-gb-prodobo-master:genre-123","title":"Ice Hockey","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"}],"isAdult":false,"cast":[],"directors":[],"images":[{"assetType":"HighResLandscapeProductionStill","assetTypes":["HighResLandscapeProductionStill"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p448880_b_h8_ak.jpg"},{"assetType":"HighResPortrait","assetTypes":["HighResPortrait"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p448880_b_v12_ak.jpg"}],"parentId":"crid:~~2F~~2Fgn.tv~~2F21275201~~2FSH012830210000","rootId":"crid:~~2F~~2Fgn.tv~~2F448880~~2FSH012830210000","parentalRatingDescription":[],"resolutions":[],"mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F448880~~2FSH012830210000","shortDescription":"The Calgary Flames play host to the New Jersey Devils in this NHL encounter from Scotiabank Saddledome.","mediaType":"Episode","year":"2022","seriesEpisodeNumber":"194","seriesNumber":"102022","videos":[],"videoStreams":[],"entitlements":["VIP","_OPEN_"],"currentProductIds":[],"currentTvodProductIds":[],"secondaryTitle":"New Jersey Devils at Calgary Flames"},"parentId":"crid:~~2F~~2Fgn.tv~~2F21275201~~2FSH012830210000","rootId":"crid:~~2F~~2Fgn.tv~~2F448880~~2FSH012830210000","replayTvAvailable":true,"audioTracks":[{"lang":"en","audioPurpose":"main"}],"ratings":[],"offersLatestExpirationDate":1647583200000,"replayTvStartOffset":0,"replayTvEndOffset":2592000,"replayEnabledOnMobileClients":true,"replaySource":"cloud","isGoReplayableViaExternalApp":false,"mergedId":"21763550|en-GB"}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
} else if (
|
||||||
|
url ===
|
||||||
|
'https://prod.oesp.virginmedia.com/oesp/v4/GB/eng/web/listings/crid:~~2F~~2Fgn.tv~~2F21764379~~2FEP025886890145,imi:c02da14358110cec07d14dc154717ce62ba2f489'
|
||||||
|
) {
|
||||||
|
return Promise.resolve({
|
||||||
|
data: JSON.parse(
|
||||||
|
`{"id":"crid:~~2F~~2Fgn.tv~~2F21764379~~2FEP025886890145,imi:c02da14358110cec07d14dc154717ce62ba2f489","startTime":1647539100000,"endTime":1647540900000,"actualStartTime":1647539100000,"actualEndTime":1647540900000,"expirationDate":1648143900000,"stationId":"lgi-gb-prodobo-master:1761","imi":"imi:c02da14358110cec07d14dc154717ce62ba2f489","scCridImi":"crid:~~2F~~2Fgn.tv~~2F21764379~~2FEP025886890145,imi:c02da14358110cec07d14dc154717ce62ba2f489","mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F13641079~~2FSH025886890000","program":{"id":"crid:~~2F~~2Fgn.tv~~2F21764379~~2FEP025886890145","title":"Boxing World Weekly","description":"A weekly series designed to showcase the best of our sport. Boxing World features news, highlights, previews and profiles from the world of pro boxing.","longDescription":"A weekly series designed to showcase the best of our sport. Boxing World features news, highlights, previews and profiles from the world of pro boxing.","medium":"TV","categories":[{"id":"lgi-gb-prodobo-master:genre-27","title":"Sport","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"},{"id":"lgi-gb-prodobo-master:genre-83","title":"Boxing","scheme":"urn:libertyglobal:metadata:cs:ContentCS:2014_1"}],"isAdult":false,"cast":[],"directors":[],"images":[{"assetType":"HighResPortrait","assetTypes":["HighResPortrait"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p19340143_b_v8_aa.jpg"},{"assetType":"TitleTreatment","assetTypes":["TitleTreatment"],"url":"https://staticqbr-gb-prod.prod.cdn.dmdsdp.com/image-service/ImagesEPG/EventImages/p13641079_ttl_h95_aa.png"}],"parentId":"crid:~~2F~~2Fgn.tv~~2F19340143~~2FSH025886890000","rootId":"crid:~~2F~~2Fgn.tv~~2F13641079~~2FSH025886890000","parentalRatingDescription":[],"resolutions":[],"mediaGroupId":"crid:~~2F~~2Fgn.tv~~2F13641079~~2FSH025886890000","shortDescription":"A weekly series designed to showcase the best of our sport. Boxing World features news, highlights, previews and profiles from the world of pro boxing.","mediaType":"Episode","year":"2022","seriesEpisodeNumber":"60","seriesNumber":"4","videos":[],"videoStreams":[],"entitlements":["VIP","_OPEN_"],"currentProductIds":[],"currentTvodProductIds":[]},"parentId":"crid:~~2F~~2Fgn.tv~~2F19340143~~2FSH025886890000","rootId":"crid:~~2F~~2Fgn.tv~~2F13641079~~2FSH025886890000","replayTvAvailable":true,"audioTracks":[{"lang":"en","audioPurpose":"main"}],"ratings":[],"offersLatestExpirationDate":1648142400000,"replayTvStartOffset":0,"replayTvEndOffset":2592000,"replayEnabledOnMobileClients":true,"replaySource":"cloud","isGoReplayableViaExternalApp":false,"mergedId":"21764379|en-GB"}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return Promise.resolve({ data: '' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
parser({ content, channel, date })
|
||||||
|
.then(result => {
|
||||||
|
result = result.map(p => {
|
||||||
|
p.start = p.start.toJSON()
|
||||||
|
p.stop = p.stop.toJSON()
|
||||||
|
return p
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result).toMatchObject([
|
||||||
|
{
|
||||||
|
start: '2022-03-16T23:30:00.000Z',
|
||||||
|
stop: '2022-03-17T02:30:00.000Z',
|
||||||
|
title: 'Live: NHL Hockey',
|
||||||
|
description:
|
||||||
|
'The Boston Bruins make the trip to Xcel Energy Center for an NHL clash with the Minnesota Wild.',
|
||||||
|
category: ['Sport', 'Ice Hockey']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: '2022-03-17T02:30:00.000Z',
|
||||||
|
stop: '2022-03-17T06:00:00.000Z',
|
||||||
|
title: 'Challenge Cup Ice Hockey',
|
||||||
|
description:
|
||||||
|
'Exclusive coverage from SSE Arena of the Premier Sports Challenge Final between Belfast Giants and Cardiff Devils.',
|
||||||
|
category: ['Ice Hockey']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: '2022-03-17T10:00:00.000Z',
|
||||||
|
stop: '2022-03-17T12:00:00.000Z',
|
||||||
|
title: 'NHL Hockey',
|
||||||
|
description:
|
||||||
|
'The Calgary Flames play host to the New Jersey Devils in this NHL encounter from Scotiabank Saddledome.',
|
||||||
|
category: ['Sport', 'Ice Hockey']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: '2022-03-17T17:45:00.000Z',
|
||||||
|
stop: '2022-03-17T18:15:00.000Z',
|
||||||
|
title: 'Boxing World Weekly',
|
||||||
|
description:
|
||||||
|
'A weekly series designed to showcase the best of our sport. Boxing World features news, highlights, previews and profiles from the world of pro boxing.',
|
||||||
|
category: ['Sport', 'Boxing'],
|
||||||
|
season: '4',
|
||||||
|
episode: '60'
|
||||||
}
|
}
|
||||||
|
])
|
||||||
|
done()
|
||||||
})
|
})
|
||||||
|
.catch(done)
|
||||||
parser({ content, channel, date })
|
|
||||||
.then(result => {
|
|
||||||
result = result.map(p => {
|
|
||||||
p.start = p.start.toJSON()
|
|
||||||
p.stop = p.stop.toJSON()
|
|
||||||
return p
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(result).toMatchObject([
|
|
||||||
{
|
|
||||||
start: '2022-03-16T23:30:00.000Z',
|
|
||||||
stop: '2022-03-17T02:30:00.000Z',
|
|
||||||
title: 'Live: NHL Hockey',
|
|
||||||
description: 'The Boston Bruins make the trip to Xcel Energy Center for an NHL clash with the Minnesota Wild.',
|
|
||||||
category: ['Sport', 'Ice Hockey']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: '2022-03-17T02:30:00.000Z',
|
|
||||||
stop: '2022-03-17T06:00:00.000Z',
|
|
||||||
title: 'Challenge Cup Ice Hockey',
|
|
||||||
description: 'Exclusive coverage from SSE Arena of the Premier Sports Challenge Final between Belfast Giants and Cardiff Devils.',
|
|
||||||
category: ['Ice Hockey']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: '2022-03-17T10:00:00.000Z',
|
|
||||||
stop: '2022-03-17T12:00:00.000Z',
|
|
||||||
title: 'NHL Hockey',
|
|
||||||
description: 'The Calgary Flames play host to the New Jersey Devils in this NHL encounter from Scotiabank Saddledome.',
|
|
||||||
category: ['Sport', 'Ice Hockey']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: '2022-03-17T17:45:00.000Z',
|
|
||||||
stop: '2022-03-17T18:15:00.000Z',
|
|
||||||
title: 'Boxing World Weekly',
|
|
||||||
description: 'A weekly series designed to showcase the best of our sport. Boxing World features news, highlights, previews and profiles from the world of pro boxing.',
|
|
||||||
category: ['Sport', 'Boxing'],
|
|
||||||
season: '4',
|
|
||||||
episode: '60'
|
|
||||||
}
|
|
||||||
])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
.catch(done)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can handle empty guide', done => {
|
it('can handle empty guide', done => {
|
||||||
parser({
|
parser({
|
||||||
content: `[{"type":"PATH_PARAM","code":"period","reason":"INVALID"}]`,
|
content: `[{"type":"PATH_PARAM","code":"period","reason":"INVALID"}]`,
|
||||||
channel,
|
channel,
|
||||||
date
|
date
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
expect(result).toMatchObject([])
|
||||||
|
done()
|
||||||
})
|
})
|
||||||
.then(result => {
|
.catch(done)
|
||||||
expect(result).toMatchObject([])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
.catch(done)
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -120,13 +120,13 @@ function parseItems(content, channel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSeason(detail) {
|
function parseSeason(detail) {
|
||||||
if (!detail.seasonNumber) return null
|
if (!detail.seasonNumber) return null
|
||||||
if (String(detail.seasonNumber).length > 2) return null
|
if (String(detail.seasonNumber).length > 2) return null
|
||||||
return detail.seasonNumber
|
return detail.seasonNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseEpisode(detail) {
|
function parseEpisode(detail) {
|
||||||
if (!detail.episodeNumber) return null
|
if (!detail.episodeNumber) return null
|
||||||
if (String(detail.episodeNumber).length > 3) return null
|
if (String(detail.episodeNumber).length > 3) return null
|
||||||
return detail.episodeNumber
|
return detail.episodeNumber
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue