import LidarrAPI from '@server/api/servarr/lidarr'; import { getSettings } from '@server/lib/settings'; import logger from '@server/logger'; import { Router } from 'express'; const musicRoutes = Router(); musicRoutes.get('/search', async (req, res, next) => { const { query } = req.query; if (!query || typeof query !== 'string') { return res.status(400).json({ error: 'Query parameter is required' }); } try { const settings = getSettings(); const lidarrSettings = settings.lidarr.find((l) => l.isDefault); if (!lidarrSettings) { return res.status(404).json({ error: 'No default Lidarr server configured' }); } const lidarr = new LidarrAPI({ apiKey: lidarrSettings.apiKey, url: LidarrAPI.buildUrl(lidarrSettings, '/api/v1'), }); const artists = await lidarr.searchArtist(query); const results = artists.slice(0, 20).map((artist) => ({ id: artist.foreignArtistId, mediaType: 'music', name: artist.artistName, artistType: artist.artistType, disambiguation: artist.disambiguation, status: artist.status, images: artist.images, genres: artist.genres, foreignArtistId: artist.foreignArtistId, statistics: artist.statistics, inLibrary: !!artist.id && artist.id > 0, })); return res.status(200).json({ results, totalResults: results.length, }); } catch (e) { logger.error('Failed to search music', { label: 'Music API', message: e.message, }); next({ status: 500, message: 'Failed to search music' }); } }); musicRoutes.get('/artist/:mbId', async (req, res, next) => { try { const settings = getSettings(); const lidarrSettings = settings.lidarr.find((l) => l.isDefault); if (!lidarrSettings) { return res.status(404).json({ error: 'No default Lidarr server configured' }); } const lidarr = new LidarrAPI({ apiKey: lidarrSettings.apiKey, url: LidarrAPI.buildUrl(lidarrSettings, '/api/v1'), }); // Search by MusicBrainz ID const artists = await lidarr.searchArtist(`lidarr:${req.params.mbId}`); const artist = artists[0]; if (!artist) { return res.status(404).json({ error: 'Artist not found' }); } // Get albums if artist is in library let albums: any[] = []; const existingArtist = await lidarr.getArtistByMbId(req.params.mbId); if (existingArtist) { albums = await lidarr.getAlbums(existingArtist.id); } return res.status(200).json({ ...artist, albums, inLibrary: !!existingArtist, }); } catch (e) { logger.error('Failed to get artist details', { label: 'Music API', message: e.message, }); next({ status: 500, message: 'Failed to get artist details' }); } }); musicRoutes.get('/album/search', async (req, res, next) => { const { query } = req.query; if (!query || typeof query !== 'string') { return res.status(400).json({ error: 'Query parameter is required' }); } try { const settings = getSettings(); const lidarrSettings = settings.lidarr.find((l) => l.isDefault); if (!lidarrSettings) { return res.status(404).json({ error: 'No default Lidarr server configured' }); } const lidarr = new LidarrAPI({ apiKey: lidarrSettings.apiKey, url: LidarrAPI.buildUrl(lidarrSettings, '/api/v1'), }); const albums = await lidarr.searchAlbum(query); return res.status(200).json({ results: albums.slice(0, 20), totalResults: albums.length, }); } catch (e) { logger.error('Failed to search albums', { label: 'Music API', message: e.message, }); next({ status: 500, message: 'Failed to search albums' }); } }); export default musicRoutes;