export interface TwitchTarget { kind: 'video' | 'channel' | 'clip' id: string } // Twitch-Pfade, die keine Kanalnamen sind const RESERVED_PATHS = new Set([ 'directory', 'downloads', 'drops', 'friends', 'inventory', 'jobs', 'messages', 'moderator', 'notifications', 'p', 'payments', 'popout', 'products', 'settings', 'subscriptions', 'turbo', 'videos', 'wallet', 'broadcast', 'search', 'activate', ]) export function getTwitchTarget(href: string): TwitchTarget | null { try { const url = new URL(href) const host = url.hostname.replace(/^(www\.|m\.)/, '') // clips.twitch.tv/{slug} if (host === 'clips.twitch.tv') { const slug = url.pathname.split('/').filter(Boolean)[0] return slug ? { kind: 'clip', id: slug } : null } if (host !== 'twitch.tv') return null const seg = url.pathname.split('/').filter(Boolean) // twitch.tv/videos/{id} if (seg[0] === 'videos' && /^\d+$/.test(seg[1] ?? '')) { return { kind: 'video', id: seg[1]! } } // twitch.tv/{channel}/clip/{slug} if (seg.length === 3 && seg[1] === 'clip') { return { kind: 'clip', id: seg[2]! } } // twitch.tv/{channel} if (seg.length === 1 && /^[\w]{2,25}$/.test(seg[0]!) && !RESERVED_PATHS.has(seg[0]!.toLowerCase())) { return { kind: 'channel', id: seg[0]! } } return null } catch { return null } } export function serializeTwitchTarget(t: TwitchTarget | null): string | null { return t ? `${t.kind}:${t.id}` : null } export function parseTwitchTarget(value: string): TwitchTarget | null { const i = value.indexOf(':') if (i < 0) return null const kind = value.slice(0, i) const id = value.slice(i + 1) if ((kind !== 'video' && kind !== 'channel' && kind !== 'clip') || !id) return null return { kind, id } } // Twitch-Embeds brauchen zwingend ?parent= export function twitchEmbedUrl(target: TwitchTarget | string | null, parent: string): string | null { const t = typeof target === 'string' ? parseTwitchTarget(target) : target if (!t) return null const p = `parent=${encodeURIComponent(parent)}` const id = encodeURIComponent(t.id) if (t.kind === 'clip') return `https://clips.twitch.tv/embed?clip=${id}&${p}&autoplay=false` if (t.kind === 'channel') return `https://player.twitch.tv/?channel=${id}&${p}` return `https://player.twitch.tv/?video=${id}&${p}&autoplay=false` }