jefflix-website/app/api/music/search/route.ts

73 lines
1.8 KiB
TypeScript

import { NextResponse } from 'next/server'
import { navidromeGet } from '@/lib/navidrome'
interface SubsonicSong {
id: string
title: string
artist: string
album: string
albumId: string
duration: number
track: number
year: number
coverArt: string
suffix: string
bitRate: number
}
interface SearchResult {
searchResult3?: {
song?: SubsonicSong[]
}
}
export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const q = searchParams.get('q')
if (!q || q.length < 2) {
return NextResponse.json({ songs: [] })
}
try {
const data = await navidromeGet<SearchResult>('search3.view', {
query: q,
songCount: '50',
albumCount: '0',
artistCount: '0',
})
const rawSongs = data.searchResult3?.song || []
// Dedup by title+artist, keeping highest bitRate (then most recent year)
const seen = new Map<string, SubsonicSong>()
for (const s of rawSongs) {
const key = `${s.title.toLowerCase().trim()}|||${s.artist.toLowerCase().trim()}`
const existing = seen.get(key)
if (!existing ||
(s.bitRate || 0) > (existing.bitRate || 0) ||
((s.bitRate || 0) === (existing.bitRate || 0) && (s.year || 0) > (existing.year || 0))) {
seen.set(key, s)
}
}
const songs = Array.from(seen.values()).map((s) => ({
id: s.id,
title: s.title,
artist: s.artist,
album: s.album,
albumId: s.albumId,
duration: s.duration,
track: s.track,
year: s.year,
coverArt: s.coverArt,
suffix: s.suffix,
}))
return NextResponse.json({ songs })
} catch (error) {
console.error('Music search error:', error)
return NextResponse.json({ error: 'Search failed' }, { status: 502 })
}
}