mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-10 18:36:15 -08:00
Load the complete ITV channel list once per portal (Ministra get_all_channels with a paged crawl fallback) and use it for: full local search across every channel, per-genre category count badges, an all-channels paginated grid on Live TV entry, and eager bulk EPG so row previews appear without playing a channel. Censored (adult) genres absent from get_all_channels fall back to the legacy paged flow and show no badge. Includes mock-server support, unit + E2E coverage, and architecture docs.
84 lines
2.3 KiB
TypeScript
84 lines
2.3 KiB
TypeScript
import { type Page } from '@playwright/test';
|
|
|
|
interface ProviderTargetPayload {
|
|
readonly url: string;
|
|
}
|
|
|
|
const BACKEND_ORIGIN = 'http://localhost:3000';
|
|
const APP_ORIGIN = process.env['BASE_URL']
|
|
? new URL(process.env['BASE_URL']).origin
|
|
: 'http://localhost:4200';
|
|
const CORS_HEADERS = {
|
|
'access-control-allow-headers': 'content-type',
|
|
'access-control-allow-methods': 'POST, OPTIONS',
|
|
'access-control-allow-origin': APP_ORIGIN,
|
|
} as const;
|
|
|
|
export async function interceptProviderTargetRegistration(
|
|
page: Page
|
|
): Promise<Map<string, string>> {
|
|
const providerTargets = new Map<string, string>();
|
|
|
|
await page.route(`${BACKEND_ORIGIN}/provider-targets**`, async (route) => {
|
|
if (route.request().method() === 'OPTIONS') {
|
|
await route.fulfill({
|
|
body: '',
|
|
headers: CORS_HEADERS,
|
|
status: 200,
|
|
});
|
|
return;
|
|
}
|
|
|
|
const providerUrl = getProviderUrl(route.request().postDataJSON());
|
|
if (!providerUrl) {
|
|
await route.fulfill({
|
|
body: JSON.stringify({
|
|
message: 'Missing url',
|
|
status: 400,
|
|
}),
|
|
contentType: 'application/json',
|
|
headers: CORS_HEADERS,
|
|
status: 400,
|
|
});
|
|
return;
|
|
}
|
|
|
|
const targetId = Buffer.from(providerUrl).toString('base64url');
|
|
providerTargets.set(targetId, providerUrl);
|
|
|
|
await route.fulfill({
|
|
body: JSON.stringify({ targetId }),
|
|
contentType: 'application/json',
|
|
headers: CORS_HEADERS,
|
|
status: 200,
|
|
});
|
|
});
|
|
|
|
return providerTargets;
|
|
}
|
|
|
|
export function getRegisteredProviderUrl(
|
|
url: URL,
|
|
providerTargets: ReadonlyMap<string, string>
|
|
): string | null {
|
|
const targetId = url.searchParams.get('targetId');
|
|
if (!targetId) {
|
|
return url.searchParams.get('url');
|
|
}
|
|
|
|
return providerTargets.get(targetId) ?? null;
|
|
}
|
|
|
|
function getProviderUrl(value: unknown): string | null {
|
|
if (
|
|
value &&
|
|
typeof value === 'object' &&
|
|
'url' in value &&
|
|
typeof (value as Partial<ProviderTargetPayload>).url === 'string'
|
|
) {
|
|
return (value as ProviderTargetPayload).url;
|
|
}
|
|
|
|
return null;
|
|
}
|