Fix firstmedia.com schedule mislead.

The retrieved schedules from firstmedia.com api indeed confusing. Taken for example
the following snippet:

```
{
  channelNo: '245',
  title: 'News Bulletin',
  date: '2023-11-07 17:00:00',
  startTime: '2023-11-07 17:00:00',
  endTime: '2023-11-07 17:30:00',
  description: 'News Bulletin',
  long_description: 'Hourly update of international news with an emphasis on the Arab world.'
}
```

Neither `startTime` nor `endTime` is an actual time but an offset from `date`.
If its an actual time then it would overlap with each others.

The workaround is to calculate the start and stop time offset, sort the schedules
based on those offset, and last skip overlapped schedules.

Signed-off-by: Toha <tohenk@yahoo.com>
This commit is contained in:
Toha 2023-11-07 14:40:01 +07:00
parent 960b057611
commit 4540181187
No known key found for this signature in database
GPG key ID: 2D7AA6389D44DCAB
2 changed files with 50 additions and 24 deletions

View file

@ -7,24 +7,36 @@ dayjs.extend(utc)
module.exports = { module.exports = {
site: 'firstmedia.com', site: 'firstmedia.com',
days: 1, days: 2,
url: function ({ channel, date }) { url({ channel, date }) {
return `https://api.firstmedia.com/api/content/tv-guide/list?date=${date.format('DD/MM/YYYY')}&channel=${ return `https://api.firstmedia.com/api/content/tv-guide/list?date=${date.format('DD/MM/YYYY')}&channel=${
channel.site_id channel.site_id
}&startTime=0&endTime=24` }&startTime=0&endTime=24`
}, },
parser: function ({ content, channel }) { parser({ content, channel, date }) {
if (!content || !channel) return [] if (!content || !channel || !date) return []
let programs = [] const programs = []
const items = parseItems(content, channel.site_id) const items = parseItems(content, channel.site_id)
items.forEach(item => { .map(item => {
programs.push({ item.start = toDelta(item.date, item.startTime)
title: parseTitle(item), item.stop = toDelta(item.date, item.endTime)
description: parseDescription(item), return item
start: parseStart(item).toISOString(),
stop: parseStop(item).toISOString()
}) })
.sort((a, b) => a.start - b.start)
const dt = date.tz('Asia/Jakarta').startOf('d')
let lastStop
items.forEach(item => {
if (lastStop === undefined || item.start >= lastStop) {
lastStop = item.stop
programs.push({
title: parseTitle(item),
description: parseDescription(item),
start: asDate(parseStart({ item, date: dt })),
stop: asDate(parseStop({ item, date: dt }))
})
}
}) })
return programs return programs
@ -66,10 +78,22 @@ function parseDescription(item) {
return item.long_description return item.long_description
} }
function parseStart(item) { function parseStart({ item, date }) {
return dayjs.tz(item.startTime, 'YYYY-MM-DD HH:mm:ss', 'Asia/Jakarta') return date.add(item.start, 'ms')
} }
function parseStop(item) { function parseStop({ item, date }) {
return dayjs.tz(item.endTime, 'YYYY-MM-DD HH:mm:ss', 'Asia/Jakarta') return date.add(item.stop, 'ms')
}
function toDelta(from, to) {
return toDate(to).diff(toDate(from), 'milliseconds')
}
function toDate(date) {
return dayjs(date, 'YYYY-MM-DD HH:mm:ss')
}
function asDate(date) {
return date.toISOString()
} }

View file

@ -3,27 +3,29 @@ 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('2023-11-04', 'DD/MM/YYYY').startOf('d') const date = dayjs.utc('2023-11-08').startOf('d')
const channel = { site_id: '243', xmltv_id: 'AlJazeeraEnglish.qa', lang: 'id' } const channel = { site_id: '243', xmltv_id: 'AlJazeeraEnglish.qa', lang: 'id' }
it('can generate valid url', () => { it('can generate valid url', () => {
expect(url({ channel, date })).toBe( expect(url({ channel, date })).toBe(
'https://api.firstmedia.com/api/content/tv-guide/list?date=04/11/2023&channel=243&startTime=0&endTime=24' 'https://api.firstmedia.com/api/content/tv-guide/list?date=08/11/2023&channel=243&startTime=0&endTime=24'
) )
}) })
it('can parse response', () => { it('can parse response', () => {
const content = const content =
'{"data":{"entries":{"243":[{"createdAt":"2023-10-29T17:01:52.000Z","updatedAt":"2023-10-29T17:01:52.000Z","id":"044aebf7-7e14-4a8b-a7da-c401498d83f2","channelNo":"243","programmeId":null,"title":"People and Power: The Launderer P3","episode":null,"slug":"people-and-power-the-launderer-p3","date":"2023-11-03 17:00:00","startTime":"2023-11-04 12:30:00","endTime":"2023-11-04 13:00:00","length":1800,"description":"People and Power: The Launderer P3","long_description":"The concluding episode of a three part investigation into Mafia money laundering.","status":true,"channel":{"id":"7fd7a9a6-af32-c861-d2b0-4ddc7846fad2","key":"AljaInt","no":243,"name":"Al Jazeera International","slug":"al-jazeera-international","website":null,"description":"<p>An international 24-hour English-language It is the first English-language news channel brings you the latest global news stories, analysis from the Middle East &amp; worldwide.</p>","shortDescription":null,"logo":"files/logos/channels/11-NEWS/AlJazeera Int SD-FirstMedia-Chl-243.jpg","externalId":"132","type":"radio","status":true,"chanel":"SD","locale":"id","relationId":"5a6ea4ae-a008-4889-9c68-7a6f1838e81d","onlyfm":null,"genress":[{"id":"1db3bb43-b00d-49af-b272-6c058a8c0b49","name":"International Free View"},{"id":"2e81a4bd-9719-4186-820a-7e035e07be13","name":"News"}]}}]}}}' '{"data":{"entries":{"243":[{"createdAt":"2023-11-05T17:09:34.000Z","updatedAt":"2023-11-05T17:09:34.000Z","id":"009f3a34-8164-4ff9-b981-9dcab1a518fc","channelNo":"243","programmeId":null,"title":"News Live","episode":null,"slug":"news-live","date":"2023-11-08 17:00:00","startTime":"2023-11-08 20:00:00","endTime":"2023-11-08 20:30:00","length":1800,"description":"News Live","long_description":"Up to date news and analysis from around the world.","status":true,"channel":{"id":"7fd7a9a6-af32-c861-d2b0-4ddc7846fad2","key":"AljaInt","no":243,"name":"Al Jazeera International","slug":"al-jazeera-international","website":null,"description":"<p>An international 24-hour English-language It is the first English-language news channel brings you the latest global news stories, analysis from the Middle East &amp; worldwide.</p>","shortDescription":null,"logo":"files/logos/channels/11-NEWS/AlJazeera Int SD-FirstMedia-Chl-243.jpg","externalId":"132","type":"radio","status":true,"chanel":"SD","locale":"id","relationId":"5a6ea4ae-a008-4889-9c68-7a6f1838e81d","onlyfm":null,"genress":[{"id":"1db3bb43-b00d-49af-b272-6c058a8c0b49","name":"International Free View"},{"id":"2e81a4bd-9719-4186-820a-7e035e07be13","name":"News"}]}}]}}}'
const results = parser({ content, channel }) const results = parser({ content, channel, date })
// All time in Asia/Jakarta
// 2023-11-08 17:00:00 -> 2023-11-08 20:00:00 = 2023-11-08 03:00:00
// 2023-11-08 17:00:00 -> 2023-11-08 20:30:00 = 2023-11-08 03:30:00
expect(results).toMatchObject([ expect(results).toMatchObject([
{ {
start: '2023-11-04T05:30:00.000Z', start: '2023-11-07T20:00:00.000Z',
stop: '2023-11-04T06:00:00.000Z', stop: '2023-11-07T20:30:00.000Z',
title: 'People and Power: The Launderer P3', title: 'News Live',
description: description: 'Up to date news and analysis from around the world.'
"The concluding episode of a three part investigation into Mafia money laundering."
} }
]) ])
}) })