import type { PlaylistMetadata, SelectableVideoMetadata, VideoMetadata } from '../types/media' export function detectMixUrl(url: string): boolean { return url.includes('v=') && url.includes('list=') } export function stripPlaylistContext(rawUrl: string): string { try { const url = new URL(rawUrl) url.searchParams.delete('list') url.searchParams.delete('index') url.searchParams.delete('start_radio') return url.toString() } catch { return rawUrl .replace(/[?&]list=[^&]+/g, '') .replace(/[?&]index=[^&]+/g, '') .replace(/[?&]start_radio=[^&]+/g, '') .replace('?&', '?') .replace(/&&+/g, '&') .replace(/[?&]$/, '') } } export function isLikelyHttpUrl(input: string): boolean { return input.startsWith('http://') || input.startsWith('https://') } export function normalizeBatchLinks(input: string): string[] { return input .split('\n') .map(line => line.trim()) .filter(Boolean) .filter(isLikelyHttpUrl) .filter(link => !link.includes('list=') || detectMixUrl(link)) .map(link => detectMixUrl(link) ? stripPlaylistContext(link) : link) } export function toSelectableEntries(entries: VideoMetadata[]): SelectableVideoMetadata[] { return entries.map(entry => ({ ...entry, selected: true })) } export function countSelectedEntries(metadata: PlaylistMetadata | null): number { return metadata?.entries.filter(entry => entry.selected).length ?? 0 }