feat(webhooks): add notification management API + one-click Sofarr webhook setup (Phase 3)
All checks were successful
All checks were successful
This commit is contained in:
@@ -4,6 +4,7 @@ const axios = require('axios');
|
||||
const router = express.Router();
|
||||
const requireAuth = require('../middleware/requireAuth');
|
||||
const sanitizeError = require('../utils/sanitizeError');
|
||||
const { getWebhookSecret, getSofarrBaseUrl } = require('../utils/config');
|
||||
|
||||
router.use(requireAuth);
|
||||
|
||||
@@ -56,4 +57,150 @@ router.get('/series', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Notification proxy routes (Phase 3)
|
||||
// GET /api/sonarr/notifications - list all notifications
|
||||
router.get('/notifications', async (req, res) => {
|
||||
try {
|
||||
const response = await axios.get(`${process.env.SONARR_URL}/api/v3/notification`, {
|
||||
headers: { 'X-Api-Key': process.env.SONARR_API_KEY }
|
||||
});
|
||||
res.json(response.data);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to fetch Sonarr notifications', details: sanitizeError(error) });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/sonarr/notifications/:id - get specific notification
|
||||
router.get('/notifications/:id', async (req, res) => {
|
||||
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 }
|
||||
});
|
||||
res.json(response.data);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to fetch Sonarr notification', details: sanitizeError(error) });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/sonarr/notifications - create notification
|
||||
router.post('/notifications', async (req, res) => {
|
||||
try {
|
||||
const response = await axios.post(`${process.env.SONARR_URL}/api/v3/notification`, req.body, {
|
||||
headers: { 'X-Api-Key': process.env.SONARR_API_KEY }
|
||||
});
|
||||
res.json(response.data);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to create Sonarr notification', details: sanitizeError(error) });
|
||||
}
|
||||
});
|
||||
|
||||
// PUT /api/sonarr/notifications/:id - update notification
|
||||
router.put('/notifications/:id', async (req, res) => {
|
||||
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 }
|
||||
});
|
||||
res.json(response.data);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to update Sonarr notification', details: sanitizeError(error) });
|
||||
}
|
||||
});
|
||||
|
||||
// DELETE /api/sonarr/notifications/:id - delete notification
|
||||
router.delete('/notifications/:id', async (req, res) => {
|
||||
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 }
|
||||
});
|
||||
res.json(response.data);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to delete Sonarr notification', details: sanitizeError(error) });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/sonarr/notifications/test - test notification
|
||||
router.post('/notifications/test', async (req, res) => {
|
||||
try {
|
||||
const response = await axios.post(`${process.env.SONARR_URL}/api/v3/notification/test`, req.body, {
|
||||
headers: { 'X-Api-Key': process.env.SONARR_API_KEY }
|
||||
});
|
||||
res.json(response.data);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to test Sonarr notification', details: sanitizeError(error) });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/sonarr/notifications/schema - get notification schema
|
||||
router.get('/notifications/schema', async (req, res) => {
|
||||
try {
|
||||
const response = await axios.get(`${process.env.SONARR_URL}/api/v3/notification/schema`, {
|
||||
headers: { 'X-Api-Key': process.env.SONARR_API_KEY }
|
||||
});
|
||||
res.json(response.data);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to fetch Sonarr notification schema', details: sanitizeError(error) });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/sonarr/notifications/sofarr-webhook - one-click Sofarr webhook setup
|
||||
router.post('/notifications/sofarr-webhook', async (req, res) => {
|
||||
try {
|
||||
const sofarrBaseUrl = getSofarrBaseUrl();
|
||||
const webhookSecret = getWebhookSecret();
|
||||
|
||||
if (!sofarrBaseUrl) {
|
||||
return res.status(400).json({ error: 'SOFARR_BASE_URL not configured' });
|
||||
}
|
||||
if (!webhookSecret) {
|
||||
return res.status(400).json({ error: 'SOFARR_WEBHOOK_SECRET not configured' });
|
||||
}
|
||||
|
||||
const webhookUrl = `${sofarrBaseUrl}/api/webhook/sonarr`;
|
||||
|
||||
// Check if Sofarr webhook already exists
|
||||
const listResponse = await axios.get(`${process.env.SONARR_URL}/api/v3/notification`, {
|
||||
headers: { 'X-Api-Key': process.env.SONARR_API_KEY }
|
||||
});
|
||||
const existingNotification = listResponse.data.find(n => n.name === 'Sofarr');
|
||||
|
||||
const notificationPayload = {
|
||||
name: 'Sofarr',
|
||||
implementation: 'Webhook',
|
||||
configContract: 'WebhookSettings',
|
||||
fields: [
|
||||
{ name: 'url', value: webhookUrl },
|
||||
{ name: 'method', value: 'POST' },
|
||||
{ name: 'headers', value: [{ key: 'X-Sofarr-Webhook-Secret', value: webhookSecret }] }
|
||||
],
|
||||
onGrab: true,
|
||||
onDownload: true,
|
||||
onImport: true,
|
||||
onUpgrade: true,
|
||||
onRename: false,
|
||||
onHealthIssue: false,
|
||||
onApplicationUpdate: false
|
||||
};
|
||||
|
||||
if (existingNotification) {
|
||||
// Update existing notification
|
||||
const response = await axios.put(
|
||||
`${process.env.SONARR_URL}/api/v3/notification/${existingNotification.id}`,
|
||||
{ ...notificationPayload, id: existingNotification.id },
|
||||
{ headers: { 'X-Api-Key': process.env.SONARR_API_KEY } }
|
||||
);
|
||||
res.json(response.data);
|
||||
} else {
|
||||
// Create new notification
|
||||
const response = await axios.post(
|
||||
`${process.env.SONARR_URL}/api/v3/notification`,
|
||||
notificationPayload,
|
||||
{ headers: { 'X-Api-Key': process.env.SONARR_API_KEY } }
|
||||
);
|
||||
res.json(response.data);
|
||||
}
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to configure Sofarr webhook', details: sanitizeError(error) });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
Reference in New Issue
Block a user