1dccda529a
- Add Ombi requests tab UI with movie/TV request display - Add showAll parameter support for Ombi requests (API and SSE) - Add Ombi webhook panel with enable/test functionality - Add Ombi webhook status endpoint with metrics - Add Ombi webhook test endpoint - Change GET /api/ombi/requests to use OmbiRetriever instead of cache - Add Ombi webhook state and API functions to frontend - Update SSE payload to include Ombi baseUrl and requests
293 lines
14 KiB
JavaScript
293 lines
14 KiB
JavaScript
// Copyright (c) 2026 Gordon Bolton. MIT License.
|
|
|
|
import { state } from '../state.js';
|
|
import { fetchWebhookStatus as apiFetchWebhookStatus, enableSonarrWebhook as apiEnableSonarrWebhook, enableRadarrWebhook as apiEnableRadarrWebhook, enableOmbiWebhook as apiEnableOmbiWebhook, testSonarrWebhook as apiTestSonarrWebhook, testRadarrWebhook as apiTestRadarrWebhook, testOmbiWebhook as apiTestOmbiWebhook } from '../api.js';
|
|
import { formatTimeAgo } from '../utils/format.js';
|
|
|
|
export function initWebhooks() {
|
|
const webhooksSection = document.getElementById('webhooks-section');
|
|
if (!webhooksSection) return;
|
|
|
|
// Note: visibility is controlled by showDashboard() based on isAdmin
|
|
|
|
document.getElementById('webhooks-header').addEventListener('click', toggleWebhookSection);
|
|
document.getElementById('enable-sonarr-webhook').addEventListener('click', enableSonarrWebhook);
|
|
document.getElementById('enable-radarr-webhook').addEventListener('click', enableRadarrWebhook);
|
|
document.getElementById('enable-ombi-webhook').addEventListener('click', enableOmbiWebhook);
|
|
document.getElementById('test-sonarr-webhook').addEventListener('click', testSonarrWebhook);
|
|
document.getElementById('test-radarr-webhook').addEventListener('click', testRadarrWebhook);
|
|
document.getElementById('test-ombi-webhook').addEventListener('click', testOmbiWebhook);
|
|
}
|
|
|
|
export function toggleWebhookSection() {
|
|
state.webhookSectionExpanded = !state.webhookSectionExpanded;
|
|
const content = document.getElementById('webhooks-content');
|
|
const toggle = document.getElementById('webhooks-toggle');
|
|
|
|
if (state.webhookSectionExpanded) {
|
|
content.classList.remove('hidden');
|
|
} else {
|
|
content.classList.add('hidden');
|
|
}
|
|
toggle.classList.toggle('expanded', state.webhookSectionExpanded);
|
|
|
|
if (state.webhookSectionExpanded) {
|
|
fetchWebhookStatus();
|
|
}
|
|
}
|
|
|
|
export async function fetchWebhookStatus() {
|
|
const loadingEl = document.getElementById('webhook-loading');
|
|
loadingEl.classList.remove('hidden');
|
|
|
|
try {
|
|
const result = await apiFetchWebhookStatus();
|
|
if (result.success) {
|
|
renderWebhookStatus();
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to fetch webhook status:', err);
|
|
} finally {
|
|
loadingEl.classList.add('hidden');
|
|
}
|
|
}
|
|
|
|
export function renderWebhookStatus() {
|
|
// Sonarr
|
|
const sonarrStatus = document.getElementById('sonarr-status');
|
|
const sonarrEnableBtn = document.getElementById('enable-sonarr-webhook');
|
|
const sonarrTestBtn = document.getElementById('test-sonarr-webhook');
|
|
const sonarrTriggers = document.getElementById('sonarr-triggers');
|
|
const sonarrStats = document.getElementById('sonarr-stats');
|
|
|
|
sonarrStatus.textContent = state.sonarrWebhook.enabled ? '● Enabled' : '○ Disabled';
|
|
sonarrStatus.className = 'status-indicator ' + (state.sonarrWebhook.enabled ? 'enabled' : 'disabled');
|
|
if (state.sonarrWebhook.enabled) {
|
|
sonarrEnableBtn.classList.add('hidden');
|
|
sonarrTestBtn.classList.remove('hidden');
|
|
sonarrTriggers.classList.remove('hidden');
|
|
} else {
|
|
sonarrEnableBtn.classList.remove('hidden');
|
|
sonarrTestBtn.classList.add('hidden');
|
|
sonarrTriggers.classList.add('hidden');
|
|
}
|
|
|
|
if (state.sonarrWebhook.enabled) {
|
|
document.getElementById('sonarr-onGrab').textContent = state.sonarrWebhook.triggers.onGrab ? '✓' : '✗';
|
|
document.getElementById('sonarr-onGrab').className = 'trigger-value ' + (state.sonarrWebhook.triggers.onGrab ? 'active' : 'inactive');
|
|
document.getElementById('sonarr-onDownload').textContent = state.sonarrWebhook.triggers.onDownload ? '✓' : '✗';
|
|
document.getElementById('sonarr-onDownload').className = 'trigger-value ' + (state.sonarrWebhook.triggers.onDownload ? 'active' : 'inactive');
|
|
document.getElementById('sonarr-onImport').textContent = state.sonarrWebhook.triggers.onImport ? '✓' : '✗';
|
|
document.getElementById('sonarr-onImport').className = 'trigger-value ' + (state.sonarrWebhook.triggers.onImport ? 'active' : 'inactive');
|
|
document.getElementById('sonarr-onUpgrade').textContent = state.sonarrWebhook.triggers.onUpgrade ? '✓' : '✗';
|
|
document.getElementById('sonarr-onUpgrade').className = 'trigger-value ' + (state.sonarrWebhook.triggers.onUpgrade ? 'active' : 'inactive');
|
|
}
|
|
|
|
if (state.sonarrWebhook.stats) {
|
|
sonarrStats.classList.remove('hidden');
|
|
document.getElementById('sonarr-events').textContent = state.sonarrWebhook.stats.eventsReceived ?? 0;
|
|
document.getElementById('sonarr-polls').textContent = state.sonarrWebhook.stats.pollsSkipped ?? 0;
|
|
document.getElementById('sonarr-last').textContent = formatTimeAgo(state.sonarrWebhook.stats.lastWebhookTimestamp);
|
|
} else {
|
|
sonarrStats.classList.add('hidden');
|
|
}
|
|
|
|
// Radarr
|
|
const radarrStatus = document.getElementById('radarr-status');
|
|
const radarrEnableBtn = document.getElementById('enable-radarr-webhook');
|
|
const radarrTestBtn = document.getElementById('test-radarr-webhook');
|
|
const radarrTriggers = document.getElementById('radarr-triggers');
|
|
const radarrStats = document.getElementById('radarr-stats');
|
|
|
|
radarrStatus.textContent = state.radarrWebhook.enabled ? '● Enabled' : '○ Disabled';
|
|
radarrStatus.className = 'status-indicator ' + (state.radarrWebhook.enabled ? 'enabled' : 'disabled');
|
|
if (state.radarrWebhook.enabled) {
|
|
radarrEnableBtn.classList.add('hidden');
|
|
radarrTestBtn.classList.remove('hidden');
|
|
radarrTriggers.classList.remove('hidden');
|
|
} else {
|
|
radarrEnableBtn.classList.remove('hidden');
|
|
radarrTestBtn.classList.add('hidden');
|
|
radarrTriggers.classList.add('hidden');
|
|
}
|
|
|
|
if (state.radarrWebhook.enabled) {
|
|
document.getElementById('radarr-onGrab').textContent = state.radarrWebhook.triggers.onGrab ? '✓' : '✗';
|
|
document.getElementById('radarr-onGrab').className = 'trigger-value ' + (state.radarrWebhook.triggers.onGrab ? 'active' : 'inactive');
|
|
document.getElementById('radarr-onDownload').textContent = state.radarrWebhook.triggers.onDownload ? '✓' : '✗';
|
|
document.getElementById('radarr-onDownload').className = 'trigger-value ' + (state.radarrWebhook.triggers.onDownload ? 'active' : 'inactive');
|
|
document.getElementById('radarr-onImport').textContent = state.radarrWebhook.triggers.onImport ? '✓' : '✗';
|
|
document.getElementById('radarr-onImport').className = 'trigger-value ' + (state.radarrWebhook.triggers.onImport ? 'active' : 'inactive');
|
|
document.getElementById('radarr-onUpgrade').textContent = state.radarrWebhook.triggers.onUpgrade ? '✓' : '✗';
|
|
document.getElementById('radarr-onUpgrade').className = 'trigger-value ' + (state.radarrWebhook.triggers.onUpgrade ? 'active' : 'inactive');
|
|
}
|
|
|
|
if (state.radarrWebhook.stats) {
|
|
radarrStats.classList.remove('hidden');
|
|
document.getElementById('radarr-events').textContent = state.radarrWebhook.stats.eventsReceived ?? 0;
|
|
document.getElementById('radarr-polls').textContent = state.radarrWebhook.stats.pollsSkipped ?? 0;
|
|
document.getElementById('radarr-last').textContent = formatTimeAgo(state.radarrWebhook.stats.lastWebhookTimestamp);
|
|
} else {
|
|
radarrStats.classList.add('hidden');
|
|
}
|
|
|
|
// Ombi
|
|
const ombiStatus = document.getElementById('ombi-status');
|
|
const ombiEnableBtn = document.getElementById('enable-ombi-webhook');
|
|
const ombiTestBtn = document.getElementById('test-ombi-webhook');
|
|
const ombiTriggers = document.getElementById('ombi-triggers');
|
|
const ombiStats = document.getElementById('ombi-stats');
|
|
|
|
ombiStatus.textContent = state.ombiWebhook.enabled ? '● Enabled' : '○ Disabled';
|
|
ombiStatus.className = 'status-indicator ' + (state.ombiWebhook.enabled ? 'enabled' : 'disabled');
|
|
if (state.ombiWebhook.enabled) {
|
|
ombiEnableBtn.classList.add('hidden');
|
|
ombiTestBtn.classList.remove('hidden');
|
|
ombiTriggers.classList.remove('hidden');
|
|
} else {
|
|
ombiEnableBtn.classList.remove('hidden');
|
|
ombiTestBtn.classList.add('hidden');
|
|
ombiTriggers.classList.add('hidden');
|
|
}
|
|
|
|
if (state.ombiWebhook.enabled) {
|
|
document.getElementById('ombi-requestAvailable').textContent = state.ombiWebhook.triggers.requestAvailable ? '✓' : '✗';
|
|
document.getElementById('ombi-requestAvailable').className = 'trigger-value ' + (state.ombiWebhook.triggers.requestAvailable ? 'active' : 'inactive');
|
|
document.getElementById('ombi-requestApproved').textContent = state.ombiWebhook.triggers.requestApproved ? '✓' : '✗';
|
|
document.getElementById('ombi-requestApproved').className = 'trigger-value ' + (state.ombiWebhook.triggers.requestApproved ? 'active' : 'inactive');
|
|
document.getElementById('ombi-requestDeclined').textContent = state.ombiWebhook.triggers.requestDeclined ? '✓' : '✗';
|
|
document.getElementById('ombi-requestDeclined').className = 'trigger-value ' + (state.ombiWebhook.triggers.requestDeclined ? 'active' : 'inactive');
|
|
document.getElementById('ombi-requestPending').textContent = state.ombiWebhook.triggers.requestPending ? '✓' : '✗';
|
|
document.getElementById('ombi-requestPending').className = 'trigger-value ' + (state.ombiWebhook.triggers.requestPending ? 'active' : 'inactive');
|
|
document.getElementById('ombi-requestProcessing').textContent = state.ombiWebhook.triggers.requestProcessing ? '✓' : '✗';
|
|
document.getElementById('ombi-requestProcessing').className = 'trigger-value ' + (state.ombiWebhook.triggers.requestProcessing ? 'active' : 'inactive');
|
|
}
|
|
|
|
if (state.ombiWebhook.stats) {
|
|
ombiStats.classList.remove('hidden');
|
|
document.getElementById('ombi-events').textContent = state.ombiWebhook.stats.eventsReceived ?? 0;
|
|
document.getElementById('ombi-polls').textContent = state.ombiWebhook.stats.pollsSkipped ?? 0;
|
|
document.getElementById('ombi-last').textContent = formatTimeAgo(state.ombiWebhook.stats.lastWebhookTimestamp);
|
|
} else {
|
|
ombiStats.classList.add('hidden');
|
|
}
|
|
}
|
|
|
|
export async function enableSonarrWebhook() {
|
|
setWebhookLoading(true);
|
|
try {
|
|
const result = await apiEnableSonarrWebhook();
|
|
if (!result.success) {
|
|
console.error('Failed to enable Sonarr webhook:', result.error);
|
|
alert('Failed to enable Sonarr webhook. Check console for details.');
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to enable Sonarr webhook:', err);
|
|
alert('Failed to enable Sonarr webhook. Check console for details.');
|
|
} finally {
|
|
setWebhookLoading(false);
|
|
}
|
|
}
|
|
|
|
export async function enableRadarrWebhook() {
|
|
setWebhookLoading(true);
|
|
try {
|
|
const result = await apiEnableRadarrWebhook();
|
|
if (!result.success) {
|
|
console.error('Failed to enable Radarr webhook:', result.error);
|
|
alert('Failed to enable Radarr webhook. Check console for details.');
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to enable Radarr webhook:', err);
|
|
alert('Failed to enable Radarr webhook. Check console for details.');
|
|
} finally {
|
|
setWebhookLoading(false);
|
|
}
|
|
}
|
|
|
|
export async function testSonarrWebhook() {
|
|
setWebhookLoading(true);
|
|
try {
|
|
const result = await apiTestSonarrWebhook();
|
|
if (result.success) {
|
|
alert('Sonarr webhook test sent successfully!');
|
|
} else {
|
|
console.error('Failed to test Sonarr webhook:', result.error);
|
|
alert('Failed to test Sonarr webhook. Check console for details.');
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to test Sonarr webhook:', err);
|
|
alert('Failed to test Sonarr webhook. Check console for details.');
|
|
} finally {
|
|
setWebhookLoading(false);
|
|
}
|
|
}
|
|
|
|
export async function testRadarrWebhook() {
|
|
setWebhookLoading(true);
|
|
try {
|
|
const result = await apiTestRadarrWebhook();
|
|
if (result.success) {
|
|
alert('Radarr webhook test sent successfully!');
|
|
} else {
|
|
console.error('Failed to test Radarr webhook:', result.error);
|
|
alert('Failed to test Radarr webhook. Check console for details.');
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to test Radarr webhook:', err);
|
|
alert('Failed to test Radarr webhook. Check console for details.');
|
|
} finally {
|
|
setWebhookLoading(false);
|
|
}
|
|
}
|
|
|
|
export async function enableOmbiWebhook() {
|
|
setWebhookLoading(true);
|
|
try {
|
|
const result = await apiEnableOmbiWebhook();
|
|
if (!result.success) {
|
|
console.error('Failed to enable Ombi webhook:', result.error);
|
|
alert('Failed to enable Ombi webhook. Check console for details.');
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to enable Ombi webhook:', err);
|
|
alert('Failed to enable Ombi webhook. Check console for details.');
|
|
} finally {
|
|
setWebhookLoading(false);
|
|
}
|
|
}
|
|
|
|
export async function testOmbiWebhook() {
|
|
setWebhookLoading(true);
|
|
try {
|
|
const result = await apiTestOmbiWebhook();
|
|
if (result.success) {
|
|
alert('Ombi webhook test sent successfully!');
|
|
} else {
|
|
console.error('Failed to test Ombi webhook:', result.error);
|
|
alert('Failed to test Ombi webhook. Check console for details.');
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to test Ombi webhook:', err);
|
|
alert('Failed to test Ombi webhook. Check console for details.');
|
|
} finally {
|
|
setWebhookLoading(false);
|
|
}
|
|
}
|
|
|
|
export function setWebhookLoading(loading) {
|
|
state.webhookLoading = loading;
|
|
document.getElementById('enable-sonarr-webhook').disabled = loading;
|
|
document.getElementById('enable-radarr-webhook').disabled = loading;
|
|
document.getElementById('enable-ombi-webhook').disabled = loading;
|
|
document.getElementById('test-sonarr-webhook').disabled = loading;
|
|
document.getElementById('test-radarr-webhook').disabled = loading;
|
|
document.getElementById('test-ombi-webhook').disabled = loading;
|
|
const loadingEl = document.getElementById('webhook-loading');
|
|
if (loading) {
|
|
loadingEl.classList.remove('hidden');
|
|
} else {
|
|
loadingEl.classList.add('hidden');
|
|
}
|
|
}
|