Update notification service

This commit is contained in:
MacRimi
2026-02-21 21:36:27 +01:00
parent 06c9ff481e
commit fccd4c12ca
2 changed files with 13 additions and 10 deletions

View File

@@ -232,7 +232,7 @@ def _pve_remove_our_blocks(text, headers_to_remove):
def _build_webhook_fallback(): def _build_webhook_fallback():
"""Build fallback manual commands for webhook setup.""" """Build fallback manual commands for webhook setup."""
import base64 import base64
body_tpl = '{"title":"{{ title }}","message":"{{ message }}","severity":"{{ severity }}","timestamp":"{{ timestamp }}"}' body_tpl = '{"title":"{{ escape title }}","message":"{{ escape message }}","severity":"{{ severity }}","timestamp":"{{ timestamp }}","type":"{{ escape type }}","hostname":"{{ escape hostname }}"}'
body_b64 = base64.b64encode(body_tpl.encode()).decode() body_b64 = base64.b64encode(body_tpl.encode()).decode()
return [ return [
"# 1. Append to END of /etc/pve/notifications.cfg", "# 1. Append to END of /etc/pve/notifications.cfg",
@@ -311,10 +311,12 @@ def setup_pve_webhook_core() -> dict:
# Neither is needed for localhost calls. # Neither is needed for localhost calls.
# PVE stores body as base64 in the config file. We encode it here # PVE stores body as base64 in the config file. We encode it here
# so the config parser reads it correctly. The plain-text template: # so the config parser reads it correctly.
# {"title":"{{ title }}","message":"{{ message }}","severity":"{{ severity }}","timestamp":"{{ timestamp }}"} # IMPORTANT: use {{ escape X }} for title/message -- PVE's escape
# helper JSON-escapes quotes and newlines. Without it, multi-line
# backup messages break the JSON and our handler can't parse it.
import base64 import base64
body_template = '{"title":"{{ title }}","message":"{{ message }}","severity":"{{ severity }}","timestamp":"{{ timestamp }}"}' body_template = '{"title":"{{ escape title }}","message":"{{ escape message }}","severity":"{{ severity }}","timestamp":"{{ timestamp }}","type":"{{ escape type }}","hostname":"{{ escape hostname }}"}'
body_b64 = base64.b64encode(body_template.encode()).decode() body_b64 = base64.b64encode(body_template.encode()).decode()
endpoint_block = ( endpoint_block = (
@@ -655,14 +657,15 @@ def proxmox_webhook():
except (json.JSONDecodeError, ValueError): except (json.JSONDecodeError, ValueError):
pass pass
# If still empty, create a minimal test event from raw data # If still empty, try to salvage data from raw body
if not payload: if not payload:
if raw_data: if raw_data:
# Last resort: treat raw text as the message body
payload = { payload = {
'type': 'webhook_test', 'title': 'PVE Notification',
'title': 'PVE Webhook Test', 'body': raw_data[:1000],
'body': raw_data[:500],
'severity': 'info', 'severity': 'info',
'source': 'proxmox_hook',
} }
else: else:
return _reject(400, 'empty_payload', 400) return _reject(400, 'empty_payload', 400)

View File

@@ -1055,7 +1055,7 @@ class ProxmoxHookWatcher:
# ── PVE native notification types ── # ── PVE native notification types ──
# When PVE sends via our webhook body template, fields.type is one of: # When PVE sends via our webhook body template, fields.type is one of:
# vzdump, fencing, replication, package-updates, system-mail # vzdump, fencing, replication, package-updates, system-mail
pve_type = payload.get('type', '').lower() pve_type = payload.get('type', '').lower().strip()
if pve_type == 'vzdump': if pve_type == 'vzdump':
# Backup notification -- determine success or failure from severity # Backup notification -- determine success or failure from severity
@@ -1163,6 +1163,6 @@ class ProxmoxHookWatcher:
raw_l = str(raw).lower() raw_l = str(raw).lower()
if raw_l in ('critical', 'emergency', 'alert', 'crit', 'err', 'error'): if raw_l in ('critical', 'emergency', 'alert', 'crit', 'err', 'error'):
return 'CRITICAL' return 'CRITICAL'
if raw_l in ('warning', 'warn'): if raw_l in ('warning', 'warn', 'notice'):
return 'WARNING' return 'WARNING'
return 'INFO' return 'INFO'