diff --git a/package-lock.json b/package-lock.json index 586b0d6a4..c6ac11343 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,6 +61,7 @@ "node-radius-client": "~1.0.0", "nodemailer": "~6.9.13", "nostr-tools": "^2.10.4", + "notifications-node-client": "^8.2.1", "notp": "~2.0.3", "openid-client": "^5.4.2", "password-hash": "~1.2.2", @@ -12625,6 +12626,31 @@ "license": "MIT", "optional": true }, + "node_modules/notifications-node-client": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/notifications-node-client/-/notifications-node-client-8.2.1.tgz", + "integrity": "sha512-wyZh/NbjN8S2uQX18utYtCyC726BBaGeTc4HeUpdhZv5sYKuaQY94N31v9syh8SzVgehyMzW37y08EePmi+k3Q==", + "license": "MIT", + "dependencies": { + "axios": "^1.7.2", + "jsonwebtoken": "^9.0.2" + }, + "engines": { + "node": ">=14.17.3", + "npm": ">=6.14.13" + } + }, + "node_modules/notifications-node-client/node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/notp": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/notp/-/notp-2.0.3.tgz", diff --git a/package.json b/package.json index ef6456b4a..43adeb858 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,7 @@ "node-radius-client": "~1.0.0", "nodemailer": "~6.9.13", "nostr-tools": "^2.10.4", + "notifications-node-client": "^8.2.1", "notp": "~2.0.3", "openid-client": "^5.4.2", "password-hash": "~1.2.2", diff --git a/server/notification-providers/gov-notify.js b/server/notification-providers/gov-notify.js new file mode 100644 index 000000000..aa49ac903 --- /dev/null +++ b/server/notification-providers/gov-notify.js @@ -0,0 +1,52 @@ +const NotificationProvider = require("./notification-provider"); +const NotifyClient = require("notifications-node-client").NotifyClient; + +class GovNotify extends NotificationProvider { + name = "GovNotify"; + + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + try { + const apiKey = notification.apiKey; + const emailRecipients = (typeof notification.emailRecipients === "string" && notification.emailRecipients.trim()) + ? notification.emailRecipients.split(",").map(e => e.trim()).filter(e => e) + : []; + const smsRecipients = (typeof notification.smsRecipients === "string" && notification.smsRecipients.trim()) + ? notification.smsRecipients.split(",").map(n => n.trim()).filter(n => n) + : []; + const message = notification.messageTemplate || msg; + const emailTemplateID = notification.emailTemplateId; + const smsTemplateID = notification.smsTemplateId; + + const notifyClient = new NotifyClient(apiKey); + + // Send Emails + for (const email of emailRecipients) { + await notifyClient.sendEmail( + emailTemplateID, + email, + { + personalisation: { message }, + reference: "Uptime-Kuma" + }); + } + + // Send SMS + for (const number of smsRecipients) { + await notifyClient.sendSms( + smsTemplateID, + number, + { + personalisation: { message }, + reference: "Uptime-Kuma" + }); + } + + return "Notification sent successfully"; + } catch (error) { + console.error("GovNotify Error:", error.response ? error.response.data : error.message); + throw new Error("Failed to send notification via GOV Notify"); + } + } +} + +module.exports = GovNotify; diff --git a/server/notification.js b/server/notification.js index e7977eb4a..efe67bf35 100644 --- a/server/notification.js +++ b/server/notification.js @@ -69,6 +69,7 @@ const Cellsynt = require("./notification-providers/cellsynt"); const Onesender = require("./notification-providers/onesender"); const Wpush = require("./notification-providers/wpush"); const SendGrid = require("./notification-providers/send-grid"); +const GovNotify = require("./notification-providers/gov-notify"); class Notification { @@ -154,7 +155,8 @@ class Notification { new GtxMessaging(), new Cellsynt(), new Wpush(), - new SendGrid() + new SendGrid(), + new GovNotify(), ]; for (let item of list) { if (! item.name) { @@ -181,7 +183,7 @@ class Notification { if (this.providerList[notification.type]) { return this.providerList[notification.type].send(notification, msg, monitorJSON, heartbeatJSON); } else { - throw new Error("Notification type is not supported"); + throw new Error(`Notification type <${notification.type}> is not supported`); } } diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index f6d728029..d97e033a6 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -121,6 +121,7 @@ export default { "Elks": "46elks", "GoogleChat": "Google Chat (Google Workspace)", "gorush": "Gorush", + "GovNotify": "GOV Notify", "gotify": "Gotify", "GrafanaOncall": "Grafana Oncall", "HeiiOnCall": "Heii On-Call", @@ -262,7 +263,7 @@ export default { this.id = null; this.notification = { name: "", - type: "telegram", + type: "GovNotify", isDefault: false, }; } diff --git a/src/components/notifications/GovNotify.vue b/src/components/notifications/GovNotify.vue new file mode 100644 index 000000000..d1b5a85a0 --- /dev/null +++ b/src/components/notifications/GovNotify.vue @@ -0,0 +1,47 @@ + + diff --git a/src/components/notifications/index.js b/src/components/notifications/index.js index efa2af5c4..76df2af65 100644 --- a/src/components/notifications/index.js +++ b/src/components/notifications/index.js @@ -67,6 +67,7 @@ import Cellsynt from "./Cellsynt.vue"; import WPush from "./WPush.vue"; import SIGNL4 from "./SIGNL4.vue"; import SendGrid from "./SendGrid.vue"; +import GovNotify from "./GovNotify.vue"; /** * Manage all notification form. @@ -142,6 +143,7 @@ const NotificationFormList = { "Cellsynt": Cellsynt, "WPush": WPush, "SendGrid": SendGrid, + "GovNotify": GovNotify }; export default NotificationFormList;