#!/usr/bin/env bash set -Eeuo pipefail APP_DIR="${APP_DIR:-/opt/proxpanel}" SECRET_FILE="${SECRET_FILE:-$APP_DIR/.backup.env}" EVENT="${EVENT:-}" SEVERITY="${SEVERITY:-warning}" STATUS="${STATUS:-failed}" MESSAGE="${MESSAGE:-}" SOURCE="${SOURCE:-backup-jobs}" CONTEXT_JSON="${CONTEXT_JSON:-{}}" usage() { cat <<'EOF' Usage: APP_DIR=/opt/proxpanel /opt/proxpanel/infra/deploy/notify-backup-alert.sh \ --event \ --severity \ --status \ --message "" \ [--source backup-cron] \ [--context-json '{"key":"value"}'] Alert destinations are read from /opt/proxpanel/.backup.env: BACKUP_ALERT_WEBHOOK_URL= BACKUP_ALERT_EMAIL_WEBHOOK_URL= BACKUP_ALERT_EMAIL_TO= BACKUP_ALERT_SUBJECT_PREFIX=[ProxPanel Backup] EOF } log() { printf '[%s] %s\n' "$(date -u +'%Y-%m-%d %H:%M:%S UTC')" "$*" } require_command() { command -v "$1" >/dev/null 2>&1 || { printf '[WARN] Missing command: %s\n' "$1" >&2 return 1 } } parse_args() { while [[ $# -gt 0 ]]; do case "$1" in --event) EVENT="${2:-}" shift 2 ;; --severity) SEVERITY="${2:-}" shift 2 ;; --status) STATUS="${2:-}" shift 2 ;; --message) MESSAGE="${2:-}" shift 2 ;; --source) SOURCE="${2:-}" shift 2 ;; --context-json) CONTEXT_JSON="${2:-{}}" shift 2 ;; -h|--help) usage exit 0 ;; *) printf '[WARN] Ignoring unknown argument: %s\n' "$1" >&2 shift ;; esac done } main() { parse_args "$@" require_command curl || exit 0 require_command jq || exit 0 if [[ -f "$SECRET_FILE" ]]; then # shellcheck disable=SC1090 source "$SECRET_FILE" fi [[ -n "$EVENT" ]] || EVENT="backup_job_event" [[ -n "$MESSAGE" ]] || MESSAGE="Backup alert event raised" local context context="$(printf '%s' "$CONTEXT_JSON" | jq -c '.' 2>/dev/null || printf '{}')" local payload now now="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" payload="$( jq -n \ --arg type "backup.alert" \ --arg event "$EVENT" \ --arg severity "$SEVERITY" \ --arg status "$STATUS" \ --arg message "$MESSAGE" \ --arg source "$SOURCE" \ --arg timestamp "$now" \ --argjson context "$context" \ '{ type: $type, event: $event, severity: $severity, status: $status, source: $source, message: $message, timestamp: $timestamp, context: $context }' )" local webhook_url email_webhook email_to subject_prefix subject status_webhook status_email webhook_url="${BACKUP_ALERT_WEBHOOK_URL:-}" email_webhook="${BACKUP_ALERT_EMAIL_WEBHOOK_URL:-}" email_to="${BACKUP_ALERT_EMAIL_TO:-${OPS_EMAIL:-}}" subject_prefix="${BACKUP_ALERT_SUBJECT_PREFIX:-[ProxPanel Backup]}" subject="${subject_prefix} ${EVENT} (${SEVERITY})" status_webhook="skipped" status_email="skipped" if [[ -n "$webhook_url" ]]; then if curl -fsS -X POST "$webhook_url" -H "Content-Type: application/json" -d "$payload" >/dev/null; then status_webhook="sent" else status_webhook="failed" fi fi if [[ -n "$email_webhook" && -n "$email_to" ]]; then local email_payload email_payload="$( jq -n \ --arg type "backup.alert.email" \ --arg to "$email_to" \ --arg subject "$subject" \ --arg message "$MESSAGE" \ --argjson payload "$payload" \ '{ type: $type, to: $to, subject: $subject, message: $message, payload: $payload }' )" if curl -fsS -X POST "$email_webhook" -H "Content-Type: application/json" -d "$email_payload" >/dev/null; then status_email="sent" else status_email="failed" fi fi log "Alert dispatch result: webhook=${status_webhook}, email=${status_email}" } main "$@"