Add Lidarr/Readarr backend support
- Add MUSIC and BOOK to MediaType enum - Add permission flags for music/book requests - Create Lidarr API adapter (artist/album search, add, remove) - Create Readarr API adapter (book/author search, add, remove) - Add Lidarr/Readarr settings interfaces and routes - Add music and book API routes for search/detail - Register all new routes in main router and settings router
This commit is contained in:
94
server/routes/book.ts
Normal file
94
server/routes/book.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import ReadarrAPI from '@server/api/servarr/readarr';
|
||||
import { getSettings } from '@server/lib/settings';
|
||||
import logger from '@server/logger';
|
||||
import { Router } from 'express';
|
||||
|
||||
const bookRoutes = Router();
|
||||
|
||||
bookRoutes.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 readarrSettings = settings.readarr.find((r) => r.isDefault);
|
||||
|
||||
if (!readarrSettings) {
|
||||
return res.status(404).json({ error: 'No default Readarr server configured' });
|
||||
}
|
||||
|
||||
const readarr = new ReadarrAPI({
|
||||
apiKey: readarrSettings.apiKey,
|
||||
url: ReadarrAPI.buildUrl(readarrSettings, '/api/v1'),
|
||||
});
|
||||
|
||||
const books = await readarr.searchBook(query);
|
||||
|
||||
const results = books.slice(0, 20).map((book) => ({
|
||||
id: book.foreignBookId,
|
||||
mediaType: 'book',
|
||||
title: book.title,
|
||||
overview: book.overview,
|
||||
releaseDate: book.releaseDate,
|
||||
images: book.images,
|
||||
genres: book.genres,
|
||||
pageCount: book.pageCount,
|
||||
author: book.author ? {
|
||||
id: book.author.foreignAuthorId,
|
||||
name: book.author.authorName,
|
||||
} : null,
|
||||
foreignBookId: book.foreignBookId,
|
||||
}));
|
||||
|
||||
return res.status(200).json({
|
||||
results,
|
||||
totalResults: results.length,
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error('Failed to search books', {
|
||||
label: 'Book API',
|
||||
message: e.message,
|
||||
});
|
||||
next({ status: 500, message: 'Failed to search books' });
|
||||
}
|
||||
});
|
||||
|
||||
bookRoutes.get('/author/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 readarrSettings = settings.readarr.find((r) => r.isDefault);
|
||||
|
||||
if (!readarrSettings) {
|
||||
return res.status(404).json({ error: 'No default Readarr server configured' });
|
||||
}
|
||||
|
||||
const readarr = new ReadarrAPI({
|
||||
apiKey: readarrSettings.apiKey,
|
||||
url: ReadarrAPI.buildUrl(readarrSettings, '/api/v1'),
|
||||
});
|
||||
|
||||
const authors = await readarr.searchAuthor(query);
|
||||
|
||||
return res.status(200).json({
|
||||
results: authors.slice(0, 20),
|
||||
totalResults: authors.length,
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error('Failed to search authors', {
|
||||
label: 'Book API',
|
||||
message: e.message,
|
||||
});
|
||||
next({ status: 500, message: 'Failed to search authors' });
|
||||
}
|
||||
});
|
||||
|
||||
export default bookRoutes;
|
||||
Reference in New Issue
Block a user