mirror of
https://github.com/iptv-org/epg
synced 2026-03-22 03:41:02 -04:00
finish france.tv configuration, tests
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
|
const axios = require('axios')
|
||||||
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')
|
||||||
@@ -16,12 +17,49 @@ module.exports = {
|
|||||||
url: function ({ channel, date }) {
|
url: function ({ channel, date }) {
|
||||||
return `https://www.france.tv/api/epg/videos/?date=${date.format('YYYY-MM-DD')}&channel=${channel.site_id}`
|
return `https://www.france.tv/api/epg/videos/?date=${date.format('YYYY-MM-DD')}&channel=${channel.site_id}`
|
||||||
},
|
},
|
||||||
parser: function ({ content, date }) {
|
parser: async function ({ channel, content, date }) {
|
||||||
const programs = []
|
const programs = []
|
||||||
let items = []
|
let items = []
|
||||||
|
|
||||||
|
const dayBefore = date.subtract(1, 'd').format('YYYY-MM-DD')
|
||||||
|
const linkDayBefore = `https://www.france.tv/api/epg/videos/?date=${dayBefore}&channel=${channel.site_id}`
|
||||||
|
|
||||||
try {
|
try {
|
||||||
items = JSON.parse(content)
|
const responseDayBefore = await axios.get(linkDayBefore)
|
||||||
|
const programmingDayBefore = responseDayBefore.data || []
|
||||||
|
|
||||||
|
// The broadcast day starts at ~6 AM. Programs with hour < 6 in the day-before API
|
||||||
|
// are actually early morning programs (00:00-05:59) of our target date.
|
||||||
|
if (Array.isArray(programmingDayBefore)) {
|
||||||
|
programmingDayBefore.forEach(item => {
|
||||||
|
const time = item?.content?.broadcastBeginDate
|
||||||
|
if (!time) return
|
||||||
|
const hour = parseInt(time.split('h')[0])
|
||||||
|
|
||||||
|
if (hour < 6) {
|
||||||
|
items.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Day before data unavailable, continue with current day only
|
||||||
|
}
|
||||||
|
|
||||||
|
// From the current day's API, only include programs starting from 6h onwards.
|
||||||
|
// Programs with hour < 6 belong to the next calendar day's schedule.
|
||||||
|
try {
|
||||||
|
const currentDayItems = JSON.parse(content) || []
|
||||||
|
if (Array.isArray(currentDayItems)) {
|
||||||
|
currentDayItems.forEach(item => {
|
||||||
|
const time = item?.content?.broadcastBeginDate
|
||||||
|
if (!time) return
|
||||||
|
const hour = parseInt(time.split('h')[0])
|
||||||
|
|
||||||
|
if (hour >= 6) {
|
||||||
|
items.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
return programs
|
return programs
|
||||||
}
|
}
|
||||||
@@ -62,8 +100,6 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let reachedNextDay = false
|
|
||||||
|
|
||||||
function parseDuration(date, item) {
|
function parseDuration(date, item) {
|
||||||
const current_date = date.format('YYYY-MM-DD')
|
const current_date = date.format('YYYY-MM-DD')
|
||||||
const time = item.content?.broadcastBeginDate
|
const time = item.content?.broadcastBeginDate
|
||||||
@@ -72,17 +108,6 @@ function parseDuration(date, item) {
|
|||||||
if (!time) return { start: dayjs(null), stop: dayjs(null) }
|
if (!time) return { start: dayjs(null), stop: dayjs(null) }
|
||||||
|
|
||||||
const timeParts = time.split('h')
|
const timeParts = time.split('h')
|
||||||
const hour = parseInt(timeParts[0])
|
|
||||||
|
|
||||||
// Once we've seen programs and encounter 00h, mark as next day
|
|
||||||
if (reachedNextDay) {
|
|
||||||
return { start: dayjs(null), stop: dayjs(null) }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hour === 0) {
|
|
||||||
reachedNextDay = true
|
|
||||||
return { start: dayjs(null), stop: dayjs(null) }
|
|
||||||
}
|
|
||||||
|
|
||||||
let durationInSeconds = 0
|
let durationInSeconds = 0
|
||||||
if (duration) {
|
if (duration) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
const { parser, url } = require('./france.tv.config.js')
|
const { parser, url } = require('./france.tv.config.js')
|
||||||
|
const axios = require('axios')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
@@ -7,19 +8,22 @@ const customParseFormat = require('dayjs/plugin/customParseFormat')
|
|||||||
dayjs.extend(customParseFormat)
|
dayjs.extend(customParseFormat)
|
||||||
dayjs.extend(utc)
|
dayjs.extend(utc)
|
||||||
|
|
||||||
|
jest.mock('axios')
|
||||||
|
|
||||||
const date = dayjs.utc('2026-02-19', 'YYYY-MM-DD').startOf('d')
|
const date = dayjs.utc('2026-02-19', 'YYYY-MM-DD').startOf('d')
|
||||||
const channel = {
|
const channel = {
|
||||||
site_id: 'france2',
|
site_id: 'france-2',
|
||||||
xmltv_id: 'France2.fr@HD'
|
xmltv_id: 'France2.fr@HD'
|
||||||
}
|
}
|
||||||
|
|
||||||
it('can generate valid url', () => {
|
it('can generate valid url', () => {
|
||||||
expect(url({ channel, date })).toBe('https://www.france.tv/api/epg/videos/?date=2026-02-19&channel=france2')
|
expect(url({ channel, date })).toBe('https://www.france.tv/api/epg/videos/?date=2026-02-19&channel=france-2')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can parse response', () => {
|
it('can parse response', async () => {
|
||||||
|
axios.get.mockResolvedValue({ data: [] })
|
||||||
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'))
|
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'))
|
||||||
const results = parser({ content, date }).map(p => {
|
const results = (await parser({ content, date, 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
|
||||||
@@ -42,8 +46,9 @@ it('can parse response', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can handle empty guide', () => {
|
it('can handle empty guide', async () => {
|
||||||
const results = parser({ content: [], date })
|
axios.get.mockResolvedValue({ data: [] })
|
||||||
|
const results = await parser({ content: [], date, channel })
|
||||||
|
|
||||||
expect(results).toMatchObject([])
|
expect(results).toMatchObject([])
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user