a38fc4a8ce
- Extract /status route to server/routes/status.js - Create server/services/WebhookStatus.js with checkWebhookConfigured and aggregateMetrics - Slim dashboard.js to pure HTTP orchestration (559→283 lines, 49.4% reduction) - Remove /user-summary and /webhook-metrics routes from dashboard.js - Mount status router at /api/status in server/index.js and server/app.js - Update tests to use new /api/status/status endpoint - Fix test expectation for speed field (number vs string) All 571 tests passing.
56 lines
1.8 KiB
JavaScript
56 lines
1.8 KiB
JavaScript
// Copyright (c) 2026 Gordon Bolton. MIT License.
|
|
const axios = require('axios');
|
|
const { getSonarrInstances, getRadarrInstances } = require('../utils/config');
|
|
|
|
/**
|
|
* Check if Sofarr webhook is configured in a Sonarr/Radarr instance.
|
|
* @param {Object} instance - The Sonarr/Radarr instance config
|
|
* @param {string} type - 'Sonarr' or 'Radarr'
|
|
* @returns {Promise<boolean>} true if webhook is configured
|
|
*/
|
|
async function checkWebhookConfigured(instance, type) {
|
|
try {
|
|
const response = await axios.get(`${instance.url}/api/v3/notification`, {
|
|
headers: { 'X-Api-Key': instance.apiKey },
|
|
timeout: 5000
|
|
});
|
|
const notifications = response.data || [];
|
|
return notifications.some(n => n.name === 'Sofarr' && n.implementation === 'Webhook');
|
|
} catch (err) {
|
|
console.log(`[WebhookStatus] Failed to check ${type} webhook config: ${err.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Aggregate webhook metrics for a service type.
|
|
* @param {Object} metricsMap - Map of instance URLs to their metrics
|
|
* @param {boolean} configured - Whether the service is configured
|
|
* @returns {Object|null} Aggregated metrics or null if not configured
|
|
*/
|
|
function aggregateMetrics(metricsMap, configured) {
|
|
const values = Object.values(metricsMap);
|
|
if (values.length === 0) {
|
|
// Return default metrics if configured but no events yet
|
|
return configured ? {
|
|
enabled: true,
|
|
eventsReceived: 0,
|
|
pollsSkipped: 0,
|
|
lastEvent: null
|
|
} : null;
|
|
}
|
|
return {
|
|
enabled: true,
|
|
eventsReceived: values.reduce((sum, m) => sum + (m.eventsReceived || 0), 0),
|
|
pollsSkipped: values.reduce((sum, m) => sum + (m.pollsSkipped || 0), 0),
|
|
lastEvent: values.reduce((latest, m) => {
|
|
return m.lastWebhookTimestamp > latest ? m.lastWebhookTimestamp : latest;
|
|
}, 0)
|
|
};
|
|
}
|
|
|
|
module.exports = {
|
|
checkWebhookConfigured,
|
|
aggregateMetrics
|
|
};
|