This commit is contained in:
1 parent
d7aea0be65
commit
91f22b54b4
30 files changed
+2475
No files matched your search
@@ -0,0 +1,116 @@
|
||||
'use strict';
|
||||
|
||||
const { settings } = require('./settings');
|
||||
const { compareEvents } = require('./events');
|
||||
|
||||
const EPG_HORIZON_MS = 14 * 24 * 60 * 60 * 1000;
|
||||
const EPG_PAST_MS = 6 * 60 * 60 * 1000;
|
||||
|
||||
function xmlEscape(value) {
|
||||
return String(value == null ? '' : value)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function xmltvDate(date) {
|
||||
return `${date.toISOString().slice(0, 19).replace(/[-:T]/g, '')} +0000`;
|
||||
}
|
||||
|
||||
function buildXmltv(scheduler, now = Date.now()) {
|
||||
const state = scheduler.state;
|
||||
const count = state.slots.length;
|
||||
const programmes = [];
|
||||
const slotEnds = new Array(count).fill(now);
|
||||
const assignedKeys = new Set();
|
||||
|
||||
for (let index = 0; index < count; index += 1) {
|
||||
const slot = state.slots[index];
|
||||
const event = slot && slot.eventKey ? state.events.get(slot.eventKey) : null;
|
||||
if (!event) continue;
|
||||
assignedKeys.add(event.key);
|
||||
programmes.push({ slot: index, event, startAt: event.startAt, endAt: event.endAt });
|
||||
slotEnds[index] = Math.max(slotEnds[index], event.endAt.getTime());
|
||||
}
|
||||
|
||||
const future = (state.upcoming || [])
|
||||
.filter((event) => !assignedKeys.has(event.key))
|
||||
.filter((event) => event.endAt.getTime() > now)
|
||||
.filter((event) => event.startAt.getTime() <= now + EPG_HORIZON_MS)
|
||||
.slice()
|
||||
.sort(compareEvents);
|
||||
|
||||
for (const event of future) {
|
||||
const duration = event.endAt.getTime() - event.startAt.getTime();
|
||||
let bestSlot = -1;
|
||||
let bestEnd = Infinity;
|
||||
for (let index = 0; index < count; index += 1) {
|
||||
if (slotEnds[index] <= event.startAt.getTime()) {
|
||||
if (slotEnds[index] < bestEnd) {
|
||||
bestEnd = slotEnds[index];
|
||||
bestSlot = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestSlot === -1) {
|
||||
for (let index = 0; index < count; index += 1) {
|
||||
if (slotEnds[index] < bestEnd) {
|
||||
bestEnd = slotEnds[index];
|
||||
bestSlot = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestSlot === -1) continue;
|
||||
const startAt = Math.max(event.startAt.getTime(), bestEnd);
|
||||
const endAt = startAt + duration;
|
||||
if (event.endAt.getTime() <= bestEnd) continue;
|
||||
programmes.push({
|
||||
slot: bestSlot,
|
||||
event,
|
||||
startAt: new Date(startAt),
|
||||
endAt: new Date(endAt),
|
||||
});
|
||||
slotEnds[bestSlot] = endAt;
|
||||
}
|
||||
|
||||
const bySlot = Array.from({ length: count }, () => []);
|
||||
for (const programme of programmes) {
|
||||
if (programme.endAt.getTime() < now - EPG_PAST_MS) continue;
|
||||
bySlot[programme.slot].push(programme);
|
||||
}
|
||||
for (const list of bySlot) {
|
||||
list.sort((a, b) => a.startAt.getTime() - b.startAt.getTime());
|
||||
}
|
||||
|
||||
const lines = ['<?xml version="1.0" encoding="UTF-8"?>'];
|
||||
lines.push('<!DOCTYPE tv SYSTEM "xmltv.dtd">');
|
||||
lines.push('<tv generator-info-name="xtream-ppv-bundler">');
|
||||
for (let index = 0; index < count; index += 1) {
|
||||
lines.push(` <channel id="jupiler-${index + 1}">`);
|
||||
lines.push(` <display-name>Jupiler ${index + 1}</display-name>`);
|
||||
lines.push(' </channel>');
|
||||
}
|
||||
for (let index = 0; index < count; index += 1) {
|
||||
for (const programme of bySlot[index]) {
|
||||
const event = programme.event;
|
||||
lines.push(
|
||||
` <programme start="${xmltvDate(programme.startAt)}" stop="${xmltvDate(programme.endAt)}" channel="jupiler-${index + 1}">`
|
||||
);
|
||||
lines.push(` <title lang="nl">${xmlEscape(event.title)}</title>`);
|
||||
if (event.league) {
|
||||
lines.push(` <sub-title lang="nl">${xmlEscape(event.league)}</sub-title>`);
|
||||
}
|
||||
lines.push(
|
||||
` <desc lang="nl">${xmlEscape(`[${event.league || settings.searchTerm}] ${event.title}`)}</desc>`
|
||||
);
|
||||
lines.push(` <category lang="nl">Sport</category>`);
|
||||
lines.push(' </programme>');
|
||||
}
|
||||
}
|
||||
lines.push('</tv>');
|
||||
return `${lines.join('\n')}\n`;
|
||||
}
|
||||
|
||||
module.exports = { buildXmltv, xmlEscape, xmltvDate };
|
||||
Reference in new issue
Block a user