import { API_URL } from "../config/api.ts"; /** Mirrors one entry of GET /api/youtube/playlist. */ export interface YouTubeTrack { videoId: string; title: string; /** Seconds. */ duration?: number; } /** * The playlist an embed URL plays, if any. * * Covers both embed shapes the provider produces: `/embed/videoseries?list=…` * for a bare playlist, and `/embed/?list=…` for a video opened in one. */ export function embedListId(embedUrl: string): string | null { try { return new URL(embedUrl).searchParams.get("list"); } catch { return null; } } /** * Add the parameters the IFrame Player API needs to talk to the embed. * * `enablejsapi` has to be in the src the iframe was created with — it cannot be * turned on afterwards — so it is added for every playlist embed, whether or * not the API script ends up loading. */ export function withJsApi(url: string): string { try { const u = new URL(url); u.searchParams.set("enablejsapi", "1"); u.searchParams.set("origin", globalThis.location.origin); return u.toString(); } catch { return url; } } /** Titles and lengths for a playlist. Throws; callers fall back to no list. */ export async function fetchPlaylistTracks( listId: string, ): Promise { const res = await fetch( `${API_URL}/api/youtube/playlist?list=${encodeURIComponent(listId)}`, ); if (!res.ok) throw new Error(`playlist fetch failed: ${res.status}`); const body = await res.json() as { success: boolean; data?: { tracks?: YouTubeTrack[] }; }; const tracks = body.data?.tracks; if (!body.success || !tracks?.length) throw new Error("no tracks"); return tracks; }