From 72d6f9ae3e7ed463c8998ce70faebd2f6d62f920 Mon Sep 17 00:00:00 2001 From: Purple Date: Sun, 18 Jan 2026 11:40:06 +0000 Subject: [PATCH] fixed n8n webhooks --- .DS_Store | Bin 8196 -> 8196 bytes webapp/api.php | 57 +++++++++++++++++++++++++++++++++++++-- webapp/config.php | 60 ++++++++++++++++++++++++++++++++++++++--- webapp/includes/app.js | 30 +++++++++++++++++++++ webapp/settings.php | 28 ++++++++++++++----- 5 files changed, 163 insertions(+), 12 deletions(-) diff --git a/.DS_Store b/.DS_Store index 4a75b98342c658edcc95024b62eefc990b524d26..425a4c817882d46914975e82e5578b7f5d4a354a 100644 GIT binary patch delta 672 zcmZ`#OH30{6rJyVT2?w!beF0YJa*JFZIJ6ZM|4{}Z^P-b>MnBa>uVVs;JPC^Gs3Oh zQ|#Hxw3scY1=YR5rhS?gyDCji?R*ATdf=eO;%VIwY0CW@M&VYCCB{X@mX=A+dgSp+ zjU|Vz(b1fHr0tRI9gJPd`<~NnCo(2XH`9t|e$wsr+bKOGA`_;_c&hd=5gXh9gQ=s*O$xPT}Ik%GhsY)oPr*Kq?kaSOL`2Y2xh3wVUb zc!EVd#|tduC0=6%Z}1lH@Cl#s1z)j_-}r;Sq?lBZ5UD;vc9I6tNSa6s36mq_DCr>) rk|a7AAr_fb3Xfm|m5UyFK&F}M diff --git a/webapp/api.php b/webapp/api.php index 9f24772..fa4d750 100644 --- a/webapp/api.php +++ b/webapp/api.php @@ -118,6 +118,10 @@ try { handleWebhookQueueStatus($db); break; + case 'webhook_queue_clear': + handleWebhookQueueClear($db); + break; + case 'update_sort_order': handleUpdateSortOrder($db); break; @@ -1173,7 +1177,7 @@ function handleWebhookSettingsGet($db) { $settings = [ 'webhook_url' => getSetting($db, 'n8n_webhook_url', ''), 'webhook_enabled' => getSetting($db, 'n8n_webhook_enabled', '0') === '1', - 'webhook_delay_minutes' => intval(getSetting($db, 'n8n_webhook_delay_minutes', '3')) + 'webhook_delay_minutes' => intval(getSetting($db, 'n8n_webhook_delay_minutes', '0')) ]; jsonResponse(['success' => true, 'data' => $settings]); @@ -1196,7 +1200,7 @@ function handleWebhookSettingsSave($db) { $webhookUrl = trim($input['webhook_url'] ?? ''); $webhookEnabled = !empty($input['webhook_enabled']) ? '1' : '0'; - $delayMinutes = max(1, min(60, intval($input['webhook_delay_minutes'] ?? 3))); + $delayMinutes = max(0, min(60, intval($input['webhook_delay_minutes'] ?? 0))); // Validate URL if provided if (!empty($webhookUrl) && !filter_var($webhookUrl, FILTER_VALIDATE_URL)) { @@ -1362,6 +1366,55 @@ function handleWebhookQueueStatus($db) { ]); } +/** + * Clear webhook queue + */ +function handleWebhookQueueClear($db) { + if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + jsonResponse(['error' => 'Method not allowed'], 405); + } + + $input = json_decode(file_get_contents('php://input'), true); + + // Validate CSRF + if (!validateCSRFToken($input['csrf_token'] ?? '')) { + jsonResponse(['error' => 'Invalid CSRF token'], 403); + } + + $clearType = $input['clear_type'] ?? 'pending'; + + try { + switch ($clearType) { + case 'pending': + $stmt = $db->prepare("DELETE FROM webhook_queue WHERE status IN ('pending', 'processing')"); + $stmt->execute(); + $message = 'Pending webhooks cleared'; + break; + case 'failed': + $stmt = $db->prepare("DELETE FROM webhook_queue WHERE status = 'failed'"); + $stmt->execute(); + $message = 'Failed webhooks cleared'; + break; + case 'all': + $stmt = $db->prepare("DELETE FROM webhook_queue"); + $stmt->execute(); + $message = 'All webhook history cleared'; + break; + default: + jsonResponse(['error' => 'Invalid clear type'], 400); + } + + $deletedCount = $stmt->rowCount(); + jsonResponse([ + 'success' => true, + 'message' => $message, + 'deleted' => $deletedCount + ]); + } catch (Exception $e) { + jsonResponse(['error' => 'Failed to clear queue: ' . $e->getMessage()], 500); + } +} + /** * Update sort order for entries */ diff --git a/webapp/config.php b/webapp/config.php index 67699cb..4ed3f59 100644 --- a/webapp/config.php +++ b/webapp/config.php @@ -171,7 +171,13 @@ function queueWebhookNotification($db, $reason = 'manual', $entriesAffected = 1) return false; } - $delayMinutes = intval(getSetting($db, 'n8n_webhook_delay_minutes', '3')); + $delayMinutes = intval(getSetting($db, 'n8n_webhook_delay_minutes', '0')); + + // If delay is 0, send immediately without queuing + if ($delayMinutes <= 0) { + return sendWebhookImmediately($db, $webhookUrl, $reason, $entriesAffected); + } + $scheduledFor = date('Y-m-d H:i:s', strtotime("+{$delayMinutes} minutes")); // Check if there's already a pending webhook scheduled @@ -198,7 +204,7 @@ function queueWebhookNotification($db, $reason = 'manual', $entriesAffected = 1) ':reason' => $reason, ':id' => $existing['id'] ]); - return $existing['id']; + $queueId = $existing['id']; } else { // Create new webhook queue entry $stmt = $db->prepare(" @@ -210,8 +216,56 @@ function queueWebhookNotification($db, $reason = 'manual', $entriesAffected = 1) ':entries' => $entriesAffected, ':scheduled_for' => $scheduledFor ]); - return $db->lastInsertId(); + $queueId = $db->lastInsertId(); } + + // Also process any due webhooks opportunistically + processWebhookQueue($db); + + return $queueId; +} + +/** + * Send webhook immediately without queuing (for zero-delay mode) + */ +function sendWebhookImmediately($db, $webhookUrl, $reason, $entriesAffected) { + // Log to queue for history purposes + $stmt = $db->prepare(" + INSERT INTO webhook_queue (webhook_type, trigger_reason, entries_affected, scheduled_for, status) + VALUES ('geofeed_update', :reason, :entries, NOW(), 'processing') + "); + $stmt->execute([ + ':reason' => $reason, + ':entries' => $entriesAffected + ]); + $queueId = $db->lastInsertId(); + + // Send the webhook immediately + $payload = [ + 'event' => 'geofeed_update', + 'queue_id' => $queueId, + 'trigger_reason' => $reason, + 'entries_affected' => $entriesAffected, + 'timestamp' => date('c') + ]; + + $result = sendWebhook($webhookUrl, $payload); + + // Update status + $finalStatus = $result['success'] ? 'completed' : 'failed'; + $updateStmt = $db->prepare(" + UPDATE webhook_queue + SET status = :status, processed_at = NOW(), response_code = :code, response_body = :body + WHERE id = :id + "); + $updateStmt->execute([ + ':status' => $finalStatus, + ':code' => $result['http_code'], + ':body' => substr($result['response'] ?? '', 0, 1000), + ':id' => $queueId + ]); + + return $queueId; } /** diff --git a/webapp/includes/app.js b/webapp/includes/app.js index d92e3e8..72e65ca 100644 --- a/webapp/includes/app.js +++ b/webapp/includes/app.js @@ -784,6 +784,36 @@ function renderWebhookQueueStatus(data) { container.innerHTML = html; } +// Clear webhook queue +async function clearWebhookQueue() { + const clearType = document.getElementById('clearQueueType')?.value || 'pending'; + const typeLabels = { + 'pending': 'pending webhooks', + 'failed': 'failed webhooks', + 'all': 'all webhook history' + }; + + if (!confirm(`Are you sure you want to clear ${typeLabels[clearType]}?`)) { + return; + } + + try { + const result = await api('webhook_queue_clear', { + csrf_token: CSRF_TOKEN, + clear_type: clearType + }); + + if (result.success) { + showToast(`${result.message} (${result.deleted} removed)`, 'success'); + loadWebhookQueueStatus(); + } else { + showToast(result.error || 'Failed to clear queue', 'error'); + } + } catch (error) { + showToast('Network error', 'error'); + } +} + // Get time until a future date function getTimeUntil(date) { const seconds = Math.floor((date - new Date()) / 1000); diff --git a/webapp/settings.php b/webapp/settings.php index 401448e..5d2f119 100644 --- a/webapp/settings.php +++ b/webapp/settings.php @@ -279,13 +279,27 @@ require_once __DIR__ . '/includes/header.php';

Webhook Queue

- +
+ + + +