feat(frontend): YouTube Music search, playback and playlist saving

This commit is contained in:
2026-07-16 01:06:20 +02:00
parent 73826b9d08
commit 3baac742d0
8 changed files with 856 additions and 133 deletions
@@ -0,0 +1,27 @@
import type { RequestHandler } from './$types';
import { json, error } from '@sveltejs/kit';
import { createApiClient } from '$lib/server/api';
export const GET: RequestHandler = async ({ url, locals, fetch }) => {
if (!locals.accessToken) {
error(401, 'Inicia sesión para buscar.');
}
const query = url.searchParams.get('query')?.trim() ?? '';
if (!query) {
error(400, 'Falta el término de búsqueda.');
}
const continuation = url.searchParams.get('continuation') ?? undefined;
const api = createApiClient({ fetch, accessToken: locals.accessToken });
const { data, error: err, response } = await api.GET('/youtube/search', {
params: { query: { query, continuation } }
});
if (err || !data) {
error(response?.status ?? 502, 'No se pudo buscar en YouTube Music.');
}
return json(data);
};
@@ -0,0 +1,20 @@
import type { RequestHandler } from './$types';
import { json, error } from '@sveltejs/kit';
import { createApiClient } from '$lib/server/api';
export const GET: RequestHandler = async ({ params, locals, fetch }) => {
if (!locals.accessToken) {
error(401, 'Inicia sesión para reproducir.');
}
const api = createApiClient({ fetch, accessToken: locals.accessToken });
const { data, error: err, response } = await api.GET('/youtube/tracks/{videoId}/stream', {
params: { path: { videoId: params.videoId } }
});
if (err || !data) {
error(response?.status ?? 502, 'No se pudo obtener el stream de YouTube.');
}
return json(data);
};