import type { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'; import { PlaylistDiscoveryService } from '../services/PlaylistDiscoveryService.js'; import { InvalidPlaylistUrlError } from '../services/playlistUrl.js'; /** Paramètres de requête acceptés par `GET /api/playlist`. */ interface GetPlaylistQuerystring { /** Lien de la playlist YouTube à parcourir. */ url: string; } const querystringSchema = { type: 'object', required: ['url'], properties: { url: { type: 'string', minLength: 1, maxLength: 300 }, }, } as const; /** * Plugin Fastify exposant les routes de découverte de playlist : * `GET /api/playlist` liste les vidéos d'une playlist YouTube. * * @param app - Instance Fastify sur laquelle enregistrer les routes. */ export const playlistRoutes: FastifyPluginAsync = async (app: FastifyInstance): Promise => { const discoveryService = new PlaylistDiscoveryService(app.log); app.get<{ Querystring: GetPlaylistQuerystring }>( '/api/playlist', { schema: { querystring: querystringSchema } }, async ( request: FastifyRequest<{ Querystring: GetPlaylistQuerystring }>, reply: FastifyReply, ) => { try { return await discoveryService.listPlaylist(request.query.url); } catch (error) { if (error instanceof InvalidPlaylistUrlError) { return reply.status(400).send({ error: error.message }); } // assertValidPlaylistUrl() lève InvalidPlaylistUrlError de façon // synchrone, avant tout appel à yt-dlp : toute autre erreur ici // vient forcément de runYtDlp (binaire introuvable, playlist // introuvable ou privée, sortie illisible...), qu'elle soit une // YtDlpError ou une erreur brute - toutes sont un échec côté // yt-dlp/YouTube. return reply.status(502).send({ error: 'Échec de la récupération de la playlist depuis YouTube (yt-dlp) : elle est peut-être introuvable ou privée.', }); } }, ); };