import type { TwitchTarget } from '../../../shared/utils/twitch' // Öffentliche Client-ID der Twitch-Web-App (gql.twitch.tv wird von twitch.tv selbst genutzt) const TWITCH_CLIENT_ID = 'kimne78kx3ncx6brgo4mv6wki5h1ko' function gqlStr(value: string): string { return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"') } interface TwitchPreview { image: string | null title: string | null } // Echtes Twitch-Thumbnail/-Titel via öffentlicher GQL-API — og:image liefert // bei Twitch nur das generische Logo export async function fetchTwitchPreview(target: TwitchTarget): Promise { try { const query = target.kind === 'video' ? `{ video(id: "${gqlStr(target.id)}") { previewThumbnailURL(height: 360, width: 640) title } }` : target.kind === 'clip' ? `{ clip(slug: "${gqlStr(target.id)}") { thumbnailURL title } }` : `{ user(login: "${gqlStr(target.id.toLowerCase())}") { displayName broadcastSettings { title } profileImageURL(width: 300) stream { previewImageURL(width: 640, height: 360) } } }` const res = await fetch('https://gql.twitch.tv/gql', { method: 'POST', signal: AbortSignal.timeout(5000), headers: { 'content-type': 'application/json', 'client-id': TWITCH_CLIENT_ID, }, body: JSON.stringify({ query }), }) if (!res.ok) return { image: null, title: null } const data = (await res.json())?.data if (!data) return { image: null, title: null } if (target.kind === 'video') { return { image: data.video?.previewThumbnailURL ?? null, title: data.video?.title ?? null } } if (target.kind === 'clip') { return { image: data.clip?.thumbnailURL ?? null, title: data.clip?.title ?? null } } const u = data.user return { image: u?.stream?.previewImageURL ?? u?.profileImageURL ?? null, title: u?.broadcastSettings?.title ?? u?.displayName ?? null, } } catch { return { image: null, title: null } } }