77 lines
2.1 KiB
JavaScript
77 lines
2.1 KiB
JavaScript
'use strict';
|
|
|
|
const { parseChannelName, normalizeText } = require('./channel-name');
|
|
const { liveUrlCandidates } = require('./xtream-client');
|
|
|
|
function defaultUrlBuilder(streamId) {
|
|
return liveUrlCandidates(streamId);
|
|
}
|
|
|
|
function compareEvents(a, b) {
|
|
const byStart = a.startAt.getTime() - b.startAt.getTime();
|
|
if (byStart !== 0) return byStart;
|
|
const bySeq = (a.firstSeenSeq ?? 0) - (b.firstSeenSeq ?? 0);
|
|
if (bySeq !== 0) return bySeq;
|
|
return a.key.localeCompare(b.key);
|
|
}
|
|
|
|
function isEligible(event, now, { startGraceMs }) {
|
|
return now >= event.startAt.getTime() - startGraceMs && now < event.endAt.getTime();
|
|
}
|
|
|
|
function buildEvents(streams, options) {
|
|
const {
|
|
searchTerm,
|
|
language,
|
|
timezone,
|
|
eventDurationMs,
|
|
urlBuilder = defaultUrlBuilder,
|
|
} = options;
|
|
|
|
const term = normalizeText(searchTerm);
|
|
const events = new Map();
|
|
const warnings = [];
|
|
|
|
for (const stream of streams || []) {
|
|
const rawName = String(stream && stream.name ? stream.name : '');
|
|
if (!rawName) continue;
|
|
if (!term || !normalizeText(rawName).includes(term)) continue;
|
|
|
|
const parsed = parseChannelName(rawName, { timezone });
|
|
if (!parsed) {
|
|
warnings.push({ streamId: stream.stream_id, name: rawName, reason: 'unparseable_name' });
|
|
continue;
|
|
}
|
|
|
|
if (parsed.language && parsed.language !== language) continue;
|
|
|
|
const key = `${normalizeText(parsed.title)}|${parsed.startAt.toISOString()}`;
|
|
let event = events.get(key);
|
|
if (!event) {
|
|
event = {
|
|
key,
|
|
title: parsed.title,
|
|
league: parsed.league,
|
|
language: parsed.language || language,
|
|
startAt: parsed.startAt,
|
|
endAt: new Date(parsed.startAt.getTime() + eventDurationMs),
|
|
sources: [],
|
|
};
|
|
events.set(key, event);
|
|
}
|
|
|
|
const streamId = String(stream.stream_id);
|
|
if (!event.sources.some((source) => source.streamId === streamId)) {
|
|
event.sources.push({
|
|
streamId,
|
|
name: rawName,
|
|
candidates: urlBuilder(stream.stream_id).slice(),
|
|
});
|
|
}
|
|
}
|
|
|
|
return { events, warnings };
|
|
}
|
|
|
|
module.exports = { buildEvents, isEligible, compareEvents };
|