From 94b8f867f4c2785b9dbf4db180473835105b8e39 Mon Sep 17 00:00:00 2001 From: Maximilian Gaedig Date: Fri, 12 Aug 2022 14:42:30 +0200 Subject: [PATCH] Add ntfy webhook notifier --- .github/workflows/deploy.yml | 9 +++++++++ README.md | 16 ++++++++++++++++ config.yaml | 1 + src/functions/cronTrigger.js | 10 ++++++++++ src/functions/helpers.js | 25 +++++++++++++++++++++++++ 5 files changed, 61 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ccfa3c403..73f6bdfaf 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -33,6 +33,9 @@ jobs: echo "kv_namespaces = [{binding=\"KV_STATUS_PAGE\", id=\"${KV_NAMESPACE_ID}\"}]" >> wrangler.toml [ -z "$SECRET_SLACK_WEBHOOK_URL" ] && echo "Secret SECRET_SLACK_WEBHOOK_URL not set, creating dummy one..." && SECRET_SLACK_WEBHOOK_URL="default-gh-action-secret" || true [ -z "$SECRET_TELEGRAM_API_TOKEN" ] && echo "Secret SECRET_TELEGRAM_API_TOKEN not set, creating dummy one..." && SECRET_TELEGRAM_API_TOKEN="default-gh-action-secret" || true + [ -z "$SECRET_NTFY_WEBHOOK_URL" ] && echo "Secret SECRET_NTFY_WEBHOOK_URL not set, creating dummy one..." && SECRET_NTFY_WEBHOOK_URL="default-gh-action-secret" || true + [ -z "$SECRET_NTFY_USERNAME" ] && echo "Secret SECRET_NTFY_USERNAME not set, creating dummy one..." && SECRET_NTFY_USERNAME="default-gh-action-secret" || true + [ -z "$SECRET_NTFY_PASSWORD" ] && echo "Secret SECRET_NTFY_PASSWORD not set, creating dummy one..." && SECRET_NTFY_PASSWORD="default-gh-action-secret" || true [ -z "$SECRET_TELEGRAM_CHAT_ID" ] && echo "Secret SECRET_TELEGRAM_CHAT_ID not set, creating dummy one..." && SECRET_TELEGRAM_CHAT_ID="default-gh-action-secret" || true [ -z "$SECRET_DISCORD_WEBHOOK_URL" ] && echo "Secret SECRET_DISCORD_WEBHOOK_URL not set, creating dummy one..." && SECRET_DISCORD_WEBHOOK_URL="default-gh-action-secret" || true postCommands: | @@ -40,6 +43,9 @@ jobs: secrets: | SECRET_SLACK_WEBHOOK_URL SECRET_TELEGRAM_API_TOKEN + SECRET_NTFY_WEBHOOK_URL + SECRET_NTFY_USERNAME + SECRET_NTFY_PASSWORD SECRET_TELEGRAM_CHAT_ID SECRET_DISCORD_WEBHOOK_URL environment: production @@ -47,5 +53,8 @@ jobs: CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} SECRET_SLACK_WEBHOOK_URL: ${{secrets.SECRET_SLACK_WEBHOOK_URL}} SECRET_TELEGRAM_API_TOKEN: ${{secrets.SECRET_TELEGRAM_API_TOKEN}} + SECRET_NTFY_WEBHOOK_URL: ${{secrets.SECRET_NTFY_WEBHOOK_URL}} + SECRET_NTFY_USERNAME: ${{secrets.SECRET_NTFY_USERNAME}} + SECRET_NTFY_PASSWORD: ${{secrets.SECRET_NTFY_PASSWORD}} SECRET_TELEGRAM_CHAT_ID: ${{secrets.SECRET_TELEGRAM_CHAT_ID}} SECRET_DISCORD_WEBHOOK_URL: ${{secrets.SECRET_DISCORD_WEBHOOK_URL}} diff --git a/README.md b/README.md index 1a2ad1a68..58433b2a8 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,9 @@ Also, prepare the following secrets - Cloudflare API token with `Edit Cloudflare Workers` permissions - Slack incoming webhook \(optional\) - Discord incoming webhook \(optional\) +- Ntfy incoming webhook \(optional\) +- Ntfy username \(optional\) +- Ntfy password \(optional\) ## Getting started @@ -42,6 +45,15 @@ You can either deploy with **Cloudflare Deploy Button** using GitHub Actions or - Name: SECRET_DISCORD_WEBHOOK_URL (optional) - Value: your-discord-webhook-url + + - Name: SECRET_NTFY_WEBHOOK_URL (optional) + - Value: your-ntfy-webhook-url + + - Name: SECRET_NTFY_USERNAME (optional) + - Value: your-ntfy-username + + - Name: SECRET_NTFY_PASSWORD (optional) + - Value: your-ntfy-password ``` 3. Navigate to the **Actions** settings in your repository and enable them @@ -54,6 +66,7 @@ You can either deploy with **Cloudflare Deploy Button** using GitHub Actions or logo: logo-192x192.png # image in ./public/ folder daysInHistogram: 90 # number of days you want to display in histogram collectResponseTimes: false # experimental feature, enable only for <5 monitors or on paid plans + ntfyPriority: 'urgent' # priority for ntfy notifications # configurable texts across the status page allmonitorsOperational: 'All Systems Operational' @@ -102,6 +115,9 @@ You can clone the repository yourself and use Wrangler CLI to develop/deploy, ex - create Worker secrets _\(optional\)_ - `SECRET_SLACK_WEBHOOK_URL` - `SECRET_DISCORD_WEBHOOK_URL` + - `SECRET_NTFY_WEBHOOK_URL` + - `SECRET_NTFY_USERNAME` + - `SECRET_NTFY_PASSWORD` ## Workers KV free tier diff --git a/config.yaml b/config.yaml index 1c1e7db42..718438847 100644 --- a/config.yaml +++ b/config.yaml @@ -4,6 +4,7 @@ settings: logo: icon.png # image in ./public/ folder daysInHistogram: 90 # number of days you want to display in histogram collectResponseTimes: true # collects avg response times from CRON locations + ntfyPriority: 'urgent' allmonitorsOperational: 'All Systems Operational' notAllmonitorsOperational: 'Not All Systems Operational' diff --git a/src/functions/cronTrigger.js b/src/functions/cronTrigger.js index 671f1a310..d34dffd9e 100644 --- a/src/functions/cronTrigger.js +++ b/src/functions/cronTrigger.js @@ -7,6 +7,7 @@ import { getKVMonitors, setKVMonitors, notifyDiscord, + notifyNtfy } from './helpers' function getDate() { @@ -89,6 +90,15 @@ export async function processCronTrigger(event) { event.waitUntil(notifyTelegram(monitor, monitorOperational)) } + // Send ntfy message on monitor change + if ( + monitorStatusChanged && + typeof SECRET_NTFY_WEBHOOK_URL !== 'undefined' && + SECRET_NTFY_WEBHOOK_URL !== 'default-gh-action-secret' + ) { + event.waitUntil(notifyNtfy(monitor, monitorOperational)) + } + // Send Discord message on monitor change if ( monitorStatusChanged && diff --git a/src/functions/helpers.js b/src/functions/helpers.js index 95d556135..46115be78 100644 --- a/src/functions/helpers.js +++ b/src/functions/helpers.js @@ -80,7 +80,32 @@ export async function notifyTelegram(monitor, operational) { const telegramUrl = `https://api.telegram.org/bot${SECRET_TELEGRAM_API_TOKEN}/sendMessage` return fetch(telegramUrl, { body: payload, + method: 'POST' + }) +} + +export async function notifyNtfy(monitor, operational) { + const text = `${monitor.method ? monitor.method : 'GET'} ${ + monitor.url + }` + const headers = { + 'Title': `Monitor ${monitor.name} changed status to ${getOperationalLabel(operational)} ${operational ? '✅' : '❌'}`, + 'Priority': config.settings.ntfyPriority, + 'Click': `${config.settings.url}`, + 'Tags': 'status-page' + } + + if (typeof SECRET_NTFY_USERNAME !== 'undefined' && + SECRET_NTFY_USERNAME !== 'default-gh-action-secret' && + typeof SECRET_NTFY_PASSWORD !== 'undefined' && + SECRET_NTFY_PASSWORD !== 'default-gh-action-secret') { + headers.authorization = `Basic ${Buffer.from(`${SECRET_NTFY_USERNAME}:${SECRET_NTFY_PASSWORD}`).toString('base64')}` + } + + fetch(SECRET_NTFY_WEBHOOK_URL, { + body: text, method: 'POST', + headers }) }