import { eq } from 'drizzle-orm'; import type { FastifyInstance } from 'fastify'; import { STREAMING_SERVICES, openUrl, type StreamingService, type TrackSearchResultDTO } from '@musicshare/shared'; import { db, schema } from '../db'; import { HttpError } from '../lib/http'; import { deezerSearch } from '../providers/catalog'; import { resolveTrackLinks } from '../services/resolver'; import { getTrackDTOs } from '../services/tracks'; export async function trackRoutes(app: FastifyInstance) { app.get<{ Querystring: { q?: string } }>( '/tracks/search', { config: { rateLimit: { max: 30, timeWindow: '1 minute' } } }, async (req): Promise => { const q = (req.query.q ?? '').trim(); if (q.length < 2) return []; const results = await deezerSearch(q, 15); return results.map((r) => ({ deezerId: String(r.id), title: r.title, artist: r.artist.name, album: r.album.title, artworkUrl: r.album.cover_big ?? null, durationMs: r.duration * 1000, })); }, ); app.get<{ Params: { id: string } }>('/tracks/:id', async (req) => { const track = (await getTrackDTOs([req.params.id])).get(req.params.id); if (!track) throw new HttpError(404, 'Track not found'); return track; }); /** Shareable redirect: /tracks/:id/open?service=spotify (defaults to the viewer's preferred service). */ app.get<{ Params: { id: string }; Querystring: { service?: string } }>('/tracks/:id/open', async (req, reply) => { const service = (req.query.service ?? req.user?.preferredService ?? 'spotify') as StreamingService; if (!STREAMING_SERVICES.includes(service)) throw new HttpError(400, 'Unknown service'); let track = (await getTrackDTOs([req.params.id])).get(req.params.id); if (!track) throw new HttpError(404, 'Track not found'); if (!track.links[service]) { const [row] = await db .select({ resolved: schema.tracks.linksResolvedAt }) .from(schema.tracks) .where(eq(schema.tracks.id, track.id)); if (!row?.resolved) { await resolveTrackLinks(track.id).catch((e) => req.log.warn(e, 'inline resolve failed')); track = (await getTrackDTOs([track.id])).get(track.id)!; } } return reply.redirect(openUrl(track, service).url); }); }