diff --git a/server/routes/radarr.js b/server/routes/radarr.js index 62ad882..77ed1b1 100644 --- a/server/routes/radarr.js +++ b/server/routes/radarr.js @@ -43,9 +43,13 @@ router.use(requireAuth); // Get queue router.get('/queue', async (req, res) => { + const instance = getFirstRadarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Radarr not configured' }); + } try { - const response = await axios.get(`${process.env.RADARR_URL}/api/v3/queue`, { - headers: { 'X-Api-Key': process.env.RADARR_API_KEY } + const response = await axios.get(`${instance.url}/api/v3/queue`, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -79,9 +83,13 @@ router.get('/queue', async (req, res) => { */ // Get history router.get('/history', async (req, res) => { + const instance = getFirstRadarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Radarr not configured' }); + } try { - const response = await axios.get(`${process.env.RADARR_URL}/api/v3/history`, { - headers: { 'X-Api-Key': process.env.RADARR_API_KEY }, + const response = await axios.get(`${instance.url}/api/v3/history`, { + headers: { 'X-Api-Key': instance.apiKey }, params: { pageSize: req.query.pageSize || 50 } }); res.json(response.data); @@ -92,9 +100,13 @@ router.get('/history', async (req, res) => { // Get movie details router.get('/movies/:id', async (req, res) => { + const instance = getFirstRadarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Radarr not configured' }); + } try { - const response = await axios.get(`${process.env.RADARR_URL}/api/v3/movie/${req.params.id}`, { - headers: { 'X-Api-Key': process.env.RADARR_API_KEY } + const response = await axios.get(`${instance.url}/api/v3/movie/${req.params.id}`, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -104,9 +116,13 @@ router.get('/movies/:id', async (req, res) => { // Get all movies with tags router.get('/movies', async (req, res) => { + const instance = getFirstRadarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Radarr not configured' }); + } try { - const response = await axios.get(`${process.env.RADARR_URL}/api/v3/movie`, { - headers: { 'X-Api-Key': process.env.RADARR_API_KEY } + const response = await axios.get(`${instance.url}/api/v3/movie`, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -164,9 +180,13 @@ router.get('/notifications', async (req, res) => { // GET /api/radarr/notifications/:id - get specific notification router.get('/notifications/:id', async (req, res) => { + const instance = getFirstRadarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Radarr not configured' }); + } try { - const response = await axios.get(`${process.env.RADARR_URL}/api/v3/notification/${req.params.id}`, { - headers: { 'X-Api-Key': process.env.RADARR_API_KEY } + const response = await axios.get(`${instance.url}/api/v3/notification/${req.params.id}`, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -176,9 +196,13 @@ router.get('/notifications/:id', async (req, res) => { // POST /api/radarr/notifications - create notification router.post('/notifications', async (req, res) => { + const instance = getFirstRadarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Radarr not configured' }); + } try { - const response = await axios.post(`${process.env.RADARR_URL}/api/v3/notification`, req.body, { - headers: { 'X-Api-Key': process.env.RADARR_API_KEY } + const response = await axios.post(`${instance.url}/api/v3/notification`, req.body, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -188,9 +212,13 @@ router.post('/notifications', async (req, res) => { // PUT /api/radarr/notifications/:id - update notification router.put('/notifications/:id', async (req, res) => { + const instance = getFirstRadarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Radarr not configured' }); + } try { - const response = await axios.put(`${process.env.RADARR_URL}/api/v3/notification/${req.params.id}`, req.body, { - headers: { 'X-Api-Key': process.env.RADARR_API_KEY } + const response = await axios.put(`${instance.url}/api/v3/notification/${req.params.id}`, req.body, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -200,9 +228,13 @@ router.put('/notifications/:id', async (req, res) => { // DELETE /api/radarr/notifications/:id - delete notification router.delete('/notifications/:id', async (req, res) => { + const instance = getFirstRadarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Radarr not configured' }); + } try { - const response = await axios.delete(`${process.env.RADARR_URL}/api/v3/notification/${req.params.id}`, { - headers: { 'X-Api-Key': process.env.RADARR_API_KEY } + const response = await axios.delete(`${instance.url}/api/v3/notification/${req.params.id}`, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -233,9 +265,13 @@ router.post('/notifications/test', async (req, res) => { // GET /api/radarr/notifications/schema - get notification schema router.get('/notifications/schema', async (req, res) => { + const instance = getFirstRadarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Radarr not configured' }); + } try { - const response = await axios.get(`${process.env.RADARR_URL}/api/v3/notification/schema`, { - headers: { 'X-Api-Key': process.env.RADARR_API_KEY } + const response = await axios.get(`${instance.url}/api/v3/notification/schema`, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { diff --git a/server/routes/sabnzbd.js b/server/routes/sabnzbd.js index 1584a9f..1199d3c 100644 --- a/server/routes/sabnzbd.js +++ b/server/routes/sabnzbd.js @@ -4,6 +4,16 @@ const axios = require('axios'); const router = express.Router(); const requireAuth = require('../middleware/requireAuth'); const sanitizeError = require('../utils/sanitizeError'); +const { getSABnzbdInstances } = require('../utils/config'); + +// Helper to get first SABnzbd instance +function getFirstSABnzbdInstance() { + const instances = getSABnzbdInstances(); + if (!instances || instances.length === 0) { + return null; + } + return instances[0]; +} /** * @openapi @@ -32,11 +42,15 @@ router.use(requireAuth); // GET /api/sabnzbd/queue router.get('/queue', async (req, res) => { + const instance = getFirstSABnzbdInstance(); + if (!instance) { + return res.status(503).json({ error: 'SABnzbd not configured' }); + } try { - const response = await axios.get(`${process.env.SABNZBD_URL}/api`, { + const response = await axios.get(`${instance.url}/api`, { params: { mode: 'queue', - apikey: process.env.SABNZBD_API_KEY, + apikey: instance.apiKey, output: 'json' } }); @@ -72,11 +86,15 @@ router.get('/queue', async (req, res) => { */ // GET /api/sabnzbd/history router.get('/history', async (req, res) => { + const instance = getFirstSABnzbdInstance(); + if (!instance) { + return res.status(503).json({ error: 'SABnzbd not configured' }); + } try { - const response = await axios.get(`${process.env.SABNZBD_URL}/api`, { + const response = await axios.get(`${instance.url}/api`, { params: { mode: 'history', - apikey: process.env.SABNZBD_API_KEY, + apikey: instance.apiKey, output: 'json', limit: req.query.limit || 50 } diff --git a/server/routes/sonarr.js b/server/routes/sonarr.js index be905d7..f5fe586 100644 --- a/server/routes/sonarr.js +++ b/server/routes/sonarr.js @@ -43,9 +43,13 @@ router.use(requireAuth); // Get queue router.get('/queue', async (req, res) => { + const instance = getFirstSonarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Sonarr not configured' }); + } try { - const response = await axios.get(`${process.env.SONARR_URL}/api/v3/queue`, { - headers: { 'X-Api-Key': process.env.SONARR_API_KEY } + const response = await axios.get(`${instance.url}/api/v3/queue`, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -79,9 +83,13 @@ router.get('/queue', async (req, res) => { */ // Get history router.get('/history', async (req, res) => { + const instance = getFirstSonarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Sonarr not configured' }); + } try { - const response = await axios.get(`${process.env.SONARR_URL}/api/v3/history`, { - headers: { 'X-Api-Key': process.env.SONARR_API_KEY }, + const response = await axios.get(`${instance.url}/api/v3/history`, { + headers: { 'X-Api-Key': instance.apiKey }, params: { pageSize: req.query.pageSize || 50 } }); res.json(response.data); @@ -92,9 +100,13 @@ router.get('/history', async (req, res) => { // Get series details router.get('/series/:id', async (req, res) => { + const instance = getFirstSonarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Sonarr not configured' }); + } try { - const response = await axios.get(`${process.env.SONARR_URL}/api/v3/series/${req.params.id}`, { - headers: { 'X-Api-Key': process.env.SONARR_API_KEY } + const response = await axios.get(`${instance.url}/api/v3/series/${req.params.id}`, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -104,9 +116,13 @@ router.get('/series/:id', async (req, res) => { // Get all series with tags router.get('/series', async (req, res) => { + const instance = getFirstSonarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Sonarr not configured' }); + } try { - const response = await axios.get(`${process.env.SONARR_URL}/api/v3/series`, { - headers: { 'X-Api-Key': process.env.SONARR_API_KEY } + const response = await axios.get(`${instance.url}/api/v3/series`, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -164,9 +180,13 @@ router.get('/notifications', async (req, res) => { // GET /api/sonarr/notifications/:id - get specific notification router.get('/notifications/:id', async (req, res) => { + const instance = getFirstSonarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Sonarr not configured' }); + } try { - const response = await axios.get(`${process.env.SONARR_URL}/api/v3/notification/${req.params.id}`, { - headers: { 'X-Api-Key': process.env.SONARR_API_KEY } + const response = await axios.get(`${instance.url}/api/v3/notification/${req.params.id}`, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -176,9 +196,13 @@ router.get('/notifications/:id', async (req, res) => { // POST /api/sonarr/notifications - create notification router.post('/notifications', async (req, res) => { + const instance = getFirstSonarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Sonarr not configured' }); + } try { - const response = await axios.post(`${process.env.SONARR_URL}/api/v3/notification`, req.body, { - headers: { 'X-Api-Key': process.env.SONARR_API_KEY } + const response = await axios.post(`${instance.url}/api/v3/notification`, req.body, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -188,9 +212,13 @@ router.post('/notifications', async (req, res) => { // PUT /api/sonarr/notifications/:id - update notification router.put('/notifications/:id', async (req, res) => { + const instance = getFirstSonarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Sonarr not configured' }); + } try { - const response = await axios.put(`${process.env.SONARR_URL}/api/v3/notification/${req.params.id}`, req.body, { - headers: { 'X-Api-Key': process.env.SONARR_API_KEY } + const response = await axios.put(`${instance.url}/api/v3/notification/${req.params.id}`, req.body, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -200,9 +228,13 @@ router.put('/notifications/:id', async (req, res) => { // DELETE /api/sonarr/notifications/:id - delete notification router.delete('/notifications/:id', async (req, res) => { + const instance = getFirstSonarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Sonarr not configured' }); + } try { - const response = await axios.delete(`${process.env.SONARR_URL}/api/v3/notification/${req.params.id}`, { - headers: { 'X-Api-Key': process.env.SONARR_API_KEY } + const response = await axios.delete(`${instance.url}/api/v3/notification/${req.params.id}`, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) { @@ -233,9 +265,13 @@ router.post('/notifications/test', async (req, res) => { // GET /api/sonarr/notifications/schema - get notification schema router.get('/notifications/schema', async (req, res) => { + const instance = getFirstSonarrInstance(); + if (!instance) { + return res.status(503).json({ error: 'Sonarr not configured' }); + } try { - const response = await axios.get(`${process.env.SONARR_URL}/api/v3/notification/schema`, { - headers: { 'X-Api-Key': process.env.SONARR_API_KEY } + const response = await axios.get(`${instance.url}/api/v3/notification/schema`, { + headers: { 'X-Api-Key': instance.apiKey } }); res.json(response.data); } catch (error) {