diff --git a/server/notification-providers/notification-provider.js b/server/notification-providers/notification-provider.js index b9fb3d86..42e8e616 100644 --- a/server/notification-providers/notification-provider.js +++ b/server/notification-providers/notification-provider.js @@ -1,3 +1,6 @@ +const { Liquid } = require("liquidjs"); +const { DOWN } = require("../../src/util"); + class NotificationProvider { /** @@ -49,6 +52,50 @@ class NotificationProvider { } } + /** + * Renders a message template with notification context + * @param {string} template the template + * @param {string} msg the message that will be included in the context + * @param {?object} monitorJSON Monitor details (For Up/Down/Cert-Expiry only) + * @param {?object} heartbeatJSON Heartbeat details (For Up/Down only) + * @returns {Promise} rendered template + */ + async renderTemplate(template, msg, monitorJSON, heartbeatJSON) { + const engine = new Liquid(); + const parsedTpl = engine.parse(template); + + // Let's start with dummy values to simplify code + let monitorName = "Monitor Name not available"; + let monitorHostnameOrURL = "testing.hostname"; + + if (monitorJSON !== null) { + monitorName = monitorJSON["name"]; + monitorHostnameOrURL = this.extractAddress(monitorJSON); + } + + let serviceStatus = "⚠️ Test"; + if (heartbeatJSON !== null) { + serviceStatus = (heartbeatJSON["status"] === DOWN) ? "🔴 Down" : "✅ Up"; + } + + const context = { + // for v1 compatibility, to be removed in v3 + "STATUS": serviceStatus, + "NAME": monitorName, + "HOSTNAME_OR_URL": monitorHostnameOrURL, + + // variables which are officially supported + "status": serviceStatus, + "name": monitorName, + "hostnameOrURL": monitorHostnameOrURL, + monitorJSON, + heartbeatJSON, + msg, + }; + + return engine.render(parsedTpl, context); + } + /** * Throws an error * @param {any} error The error to throw diff --git a/server/notification-providers/smtp.js b/server/notification-providers/smtp.js index 9f3defa5..980c7dfd 100644 --- a/server/notification-providers/smtp.js +++ b/server/notification-providers/smtp.js @@ -1,7 +1,5 @@ const nodemailer = require("nodemailer"); const NotificationProvider = require("./notification-provider"); -const { DOWN } = require("../../src/util"); -const { Liquid } = require("liquidjs"); class SMTP extends NotificationProvider { name = "smtp"; @@ -53,15 +51,11 @@ class SMTP extends NotificationProvider { const customSubject = notification.customSubject?.trim() || ""; const customBody = notification.customBody?.trim() || ""; - const context = this.generateContext(msg, monitorJSON, heartbeatJSON); - const engine = new Liquid(); if (customSubject !== "") { - const tpl = engine.parse(customSubject); - subject = await engine.render(tpl, context); + subject = await this.renderTemplate(customSubject, msg, monitorJSON, heartbeatJSON); } if (customBody !== "") { - const tpl = engine.parse(customBody); - body = await engine.render(tpl, context); + body = await this.renderTemplate(customBody, msg, monitorJSON, heartbeatJSON); } } @@ -78,43 +72,6 @@ class SMTP extends NotificationProvider { return okMsg; } - - /** - * Generate context for LiquidJS - * @param {string} msg the message that will be included in the context - * @param {?object} monitorJSON Monitor details (For Up/Down/Cert-Expiry only) - * @param {?object} heartbeatJSON Heartbeat details (For Up/Down only) - * @returns {{STATUS: string, status: string, HOSTNAME_OR_URL: string, hostnameOrUrl: string, NAME: string, name: string, monitorJSON: ?object, heartbeatJSON: ?object, msg: string}} the context - */ - generateContext(msg, monitorJSON, heartbeatJSON) { - // Let's start with dummy values to simplify code - let monitorName = "Monitor Name not available"; - let monitorHostnameOrURL = "testing.hostname"; - - if (monitorJSON !== null) { - monitorName = monitorJSON["name"]; - monitorHostnameOrURL = this.extractAddress(monitorJSON); - } - - let serviceStatus = "⚠️ Test"; - if (heartbeatJSON !== null) { - serviceStatus = (heartbeatJSON["status"] === DOWN) ? "🔴 Down" : "✅ Up"; - } - return { - // for v1 compatibility, to be removed in v3 - "STATUS": serviceStatus, - "NAME": monitorName, - "HOSTNAME_OR_URL": monitorHostnameOrURL, - - // variables which are officially supported - "status": serviceStatus, - "name": monitorName, - "hostnameOrURL": monitorHostnameOrURL, - monitorJSON, - heartbeatJSON, - msg, - }; - } } module.exports = SMTP; diff --git a/server/notification-providers/telegram.js b/server/notification-providers/telegram.js index c5bbb190..62263db0 100644 --- a/server/notification-providers/telegram.js +++ b/server/notification-providers/telegram.js @@ -22,6 +22,14 @@ class Telegram extends NotificationProvider { params.message_thread_id = notification.telegramMessageThreadID; } + if (notification.telegramUseTemplate) { + params.text = await this.renderTemplate(notification.telegramTemplate, msg, monitorJSON, heartbeatJSON); + + if (notification.telegramTemplateParseMode !== "plain") { + params.parse_mode = notification.telegramTemplateParseMode; + } + } + await axios.get(`${url}/bot${notification.telegramBotToken}/sendMessage`, { params: params, }); diff --git a/server/notification-providers/webhook.js b/server/notification-providers/webhook.js index 986986d4..537f94bd 100644 --- a/server/notification-providers/webhook.js +++ b/server/notification-providers/webhook.js @@ -1,7 +1,6 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); const FormData = require("form-data"); -const { Liquid } = require("liquidjs"); class Webhook extends NotificationProvider { name = "webhook"; @@ -28,17 +27,7 @@ class Webhook extends NotificationProvider { config.headers = formData.getHeaders(); data = formData; } else if (notification.webhookContentType === "custom") { - // Initialize LiquidJS and parse the custom Body Template - const engine = new Liquid(); - const tpl = engine.parse(notification.webhookCustomBody); - - // Insert templated values into Body - data = await engine.render(tpl, - { - msg, - heartbeatJSON, - monitorJSON - }); + data = await this.renderTemplate(notification.webhookCustomBody, msg, monitorJSON, heartbeatJSON); } if (notification.webhookAdditionalHeaders) { diff --git a/src/components/TemplatedInput.vue b/src/components/TemplatedInput.vue new file mode 100644 index 00000000..43c5382e --- /dev/null +++ b/src/components/TemplatedInput.vue @@ -0,0 +1,75 @@ + + + diff --git a/src/components/TemplatedTextarea.vue b/src/components/TemplatedTextarea.vue new file mode 100644 index 00000000..ff0c0f9f --- /dev/null +++ b/src/components/TemplatedTextarea.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/src/components/notifications/SMTP.vue b/src/components/notifications/SMTP.vue index 003f9055..4e0fb4b5 100644 --- a/src/components/notifications/SMTP.vue +++ b/src/components/notifications/SMTP.vue @@ -67,25 +67,15 @@ -

- - {{ $t("documentation") }} - - {{name}}: {{ $t("emailTemplateServiceName") }}
- {{msg}}: {{ $t("emailTemplateMsg") }}
- {{status}}: {{ $t("emailTemplateStatus") }}
- {{heartbeatJSON}}: {{ $t("emailTemplateHeartbeatJSON") }}{{ $t("emailTemplateLimitedToUpDownNotification") }}
- {{monitorJSON}}: {{ $t("emailTemplateMonitorJSON") }} {{ $t("emailTemplateLimitedToUpDownNotification") }}
- {{hostnameOrURL}}: {{ $t("emailTemplateHostnameOrURL") }}
-

- +
{{ $t("leave blank for default subject") }}
+
- +
{{ $t("leave blank for default body") }}
@@ -124,11 +114,15 @@ + + diff --git a/src/components/notifications/Webhook.vue b/src/components/notifications/Webhook.vue index 8c67a274..7775a3fd 100644 --- a/src/components/notifications/Webhook.vue +++ b/src/components/notifications/Webhook.vue @@ -32,20 +32,7 @@ @@ -67,7 +54,12 @@