mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
feat(stalker): refactor epg handling to use get_epg_info
- Implemented unit tests for StalkerCollectionChannelsListComponent to verify EPG program loading and state management. - Created unit tests for StalkerLiveStreamLayoutComponent to ensure proper rendering of EPG lists and handling of channel playback. - Refactored EPG loading logic in StalkerLiveStreamLayoutComponent to improve performance and maintainability. - Updated HTML template in StalkerLiveStreamLayoutComponent to replace deprecated components with new EPG list component. - Enhanced EPG program handling by introducing methods for timestamp parsing and current program detection.
This commit is contained in:
1 parent
bf427f7226
commit
545dfd8c67
14 files changed
+1542
-255
No files matched your search
@@ -135,15 +135,6 @@ function logoUrl(seed: string): string {
|
||||
return `https://picsum.photos/seed/logo-${seed}/100/100`;
|
||||
}
|
||||
|
||||
function isoNow(offsetMinutes: number): string {
|
||||
const d = new Date(Date.now() + offsetMinutes * 60 * 1000);
|
||||
return d.toISOString();
|
||||
}
|
||||
|
||||
function unixNow(offsetMinutes: number): number {
|
||||
return Math.floor((Date.now() + offsetMinutes * 60 * 1000) / 1000);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Generator
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -390,29 +381,44 @@ export function generateSeasons(
|
||||
// EPG generator
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const EPG_PROGRAM_TYPES = ['News', 'Movie', 'Documentary', 'Entertainment', 'Sports', 'Kids', 'Series'];
|
||||
const EPG_PROGRAM_TYPES = [
|
||||
'News',
|
||||
'Movie',
|
||||
'Documentary',
|
||||
'Entertainment',
|
||||
'Sports',
|
||||
'Kids',
|
||||
'Series',
|
||||
];
|
||||
|
||||
export function generateEpg(channelName: string): RawEpgProgram[] {
|
||||
const programs: RawEpgProgram[] = [];
|
||||
// Generate 12 programs: 6 past, current, 5 future (30-min slots)
|
||||
const SLOT_MINUTES = 30;
|
||||
const startOffset = -6 * SLOT_MINUTES; // start 3 hours ago
|
||||
const SLOT_MINUTES = 120;
|
||||
const SLOTS_PER_DAY = (24 * 60) / SLOT_MINUTES;
|
||||
const TOTAL_DAYS = 7;
|
||||
const dayStart = new Date();
|
||||
dayStart.setUTCHours(0, 0, 0, 0);
|
||||
|
||||
for (let i = 0; i < 12; i++) {
|
||||
const startMin = startOffset + i * SLOT_MINUTES;
|
||||
const stopMin = startMin + SLOT_MINUTES;
|
||||
for (let i = 0; i < SLOTS_PER_DAY * TOTAL_DAYS; i++) {
|
||||
const startDate = new Date(
|
||||
dayStart.getTime() + i * SLOT_MINUTES * 60 * 1000
|
||||
);
|
||||
const stopDate = new Date(
|
||||
startDate.getTime() + SLOT_MINUTES * 60 * 1000
|
||||
);
|
||||
const category = EPG_PROGRAM_TYPES[i % EPG_PROGRAM_TYPES.length];
|
||||
programs.push({
|
||||
id: String(i + 1),
|
||||
name: `${channelName}: ${faker.company.catchPhrase()}`,
|
||||
start: isoNow(startMin),
|
||||
stop: isoNow(stopMin),
|
||||
start_timestamp: unixNow(startMin),
|
||||
stop_timestamp: unixNow(stopMin),
|
||||
start: startDate.toISOString(),
|
||||
stop: stopDate.toISOString(),
|
||||
start_timestamp: Math.floor(startDate.getTime() / 1000),
|
||||
stop_timestamp: Math.floor(stopDate.getTime() / 1000),
|
||||
descr: faker.lorem.sentence(),
|
||||
category,
|
||||
});
|
||||
}
|
||||
|
||||
return programs;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Request, Response } from 'express';
|
||||
import { getPortalData } from '../data-store.js';
|
||||
import { extractMac } from './get-categories.handler.js';
|
||||
|
||||
/**
|
||||
* Stalker get_epg_info — returns bulk EPG keyed by channel id.
|
||||
*
|
||||
* Query params:
|
||||
* period: number of future hours to include (default 168)
|
||||
*/
|
||||
export function handleGetEpgInfo(req: Request, res: Response): void {
|
||||
const mac = extractMac(req);
|
||||
const period = parseInt((req.query['period'] as string) ?? '168', 10);
|
||||
const data = getPortalData(mac);
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const currentDayStart = new Date();
|
||||
currentDayStart.setUTCHours(0, 0, 0, 0);
|
||||
const startTimestamp = Math.floor(currentDayStart.getTime() / 1000);
|
||||
const endTimestamp = now + Math.max(period, 1) * 60 * 60;
|
||||
|
||||
const epgByChannel = Object.fromEntries(
|
||||
[...data.epg.entries()].map(([channelId, programs]) => [
|
||||
channelId,
|
||||
programs.filter(
|
||||
(program) =>
|
||||
program.stop_timestamp >= startTimestamp &&
|
||||
program.start_timestamp <= endTimestamp
|
||||
),
|
||||
])
|
||||
);
|
||||
|
||||
res.json({
|
||||
js: {
|
||||
data: epgByChannel,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -24,9 +24,15 @@ export function handleGetShortEpg(req: Request, res: Response): void {
|
||||
data.epg.set(channelId, programs);
|
||||
}
|
||||
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const currentIndex = programs.findIndex(
|
||||
(program) => program.stop_timestamp > now
|
||||
);
|
||||
const startIndex = currentIndex >= 0 ? currentIndex : 0;
|
||||
|
||||
res.json({
|
||||
js: {
|
||||
data: programs.slice(0, size),
|
||||
data: programs.slice(startIndex, startIndex + size),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import { handleGetOrderedList } from '../handlers/get-ordered-list.handler.js';
|
||||
import { handleGetSeasons } from '../handlers/get-seasons.handler.js';
|
||||
import { handleCreateLink } from '../handlers/create-link.handler.js';
|
||||
import { handleFavorites } from '../handlers/favorites.handler.js';
|
||||
import { handleGetEpgInfo } from '../handlers/get-epg-info.handler.js';
|
||||
import { handleGetShortEpg } from '../handlers/get-short-epg.handler.js';
|
||||
import { handleGetGenres } from '../handlers/get-genres.handler.js';
|
||||
|
||||
@@ -45,9 +46,11 @@ export default function dispatchPortalAction(req: Request, res: Response): void
|
||||
handleFavorites(req, res);
|
||||
break;
|
||||
case 'get_short_epg':
|
||||
case 'get_epg_info':
|
||||
handleGetShortEpg(req, res);
|
||||
break;
|
||||
case 'get_epg_info':
|
||||
handleGetEpgInfo(req, res);
|
||||
break;
|
||||
default:
|
||||
console.warn(`[portal] Unknown action: ${action}`);
|
||||
res.json({ js: { error: `Unknown action: ${action}` } });
|
||||
|
||||
Reference in new issue
Block a user