summaryrefslogtreecommitdiffstats
path: root/server/notification-providers/teams.js
diff options
context:
space:
mode:
Diffstat (limited to 'server/notification-providers/teams.js')
-rw-r--r--server/notification-providers/teams.js240
1 files changed, 240 insertions, 0 deletions
diff --git a/server/notification-providers/teams.js b/server/notification-providers/teams.js
new file mode 100644
index 0000000..2793604
--- /dev/null
+++ b/server/notification-providers/teams.js
@@ -0,0 +1,240 @@
+const NotificationProvider = require("./notification-provider");
+const axios = require("axios");
+const { setting } = require("../util-server");
+const { DOWN, UP, getMonitorRelativeURL } = require("../../src/util");
+
+class Teams extends NotificationProvider {
+ name = "teams";
+
+ /**
+ * Generate the message to send
+ * @param {const} status The status constant
+ * @param {string} monitorName Name of monitor
+ * @param {boolean} withStatusSymbol If the status should be prepended as symbol
+ * @returns {string} Status message
+ */
+ _statusMessageFactory = (status, monitorName, withStatusSymbol) => {
+ if (status === DOWN) {
+ return (withStatusSymbol ? "🔴 " : "") + `[${monitorName}] went down`;
+ } else if (status === UP) {
+ return (withStatusSymbol ? "✅ " : "") + `[${monitorName}] is back online`;
+ }
+ return "Notification";
+ };
+
+ /**
+ * Select the style to use based on status
+ * @param {const} status The status constant
+ * @returns {string} Selected style for adaptive cards
+ */
+ _getStyle = (status) => {
+ if (status === DOWN) {
+ return "attention";
+ }
+ if (status === UP) {
+ return "good";
+ }
+ return "emphasis";
+ };
+
+ /**
+ * Generate payload for notification
+ * @param {object} args Method arguments
+ * @param {object} args.heartbeatJSON Heartbeat details
+ * @param {string} args.monitorName Name of the monitor affected
+ * @param {string} args.monitorUrl URL of the monitor affected
+ * @param {string} args.dashboardUrl URL of the dashboard affected
+ * @returns {object} Notification payload
+ */
+ _notificationPayloadFactory = ({
+ heartbeatJSON,
+ monitorName,
+ monitorUrl,
+ dashboardUrl,
+ }) => {
+ const status = heartbeatJSON?.status;
+ const facts = [];
+ const actions = [];
+
+ if (dashboardUrl) {
+ actions.push({
+ "type": "Action.OpenUrl",
+ "title": "Visit Uptime Kuma",
+ "url": dashboardUrl
+ });
+ }
+
+ if (heartbeatJSON?.msg) {
+ facts.push({
+ title: "Description",
+ value: heartbeatJSON.msg,
+ });
+ }
+
+ if (monitorName) {
+ facts.push({
+ title: "Monitor",
+ value: monitorName,
+ });
+ }
+
+ if (monitorUrl && monitorUrl !== "https://") {
+ facts.push({
+ title: "URL",
+ // format URL as markdown syntax, to be clickable
+ value: `[${monitorUrl}](${monitorUrl})`,
+ });
+ actions.push({
+ "type": "Action.OpenUrl",
+ "title": "Visit Monitor URL",
+ "url": monitorUrl
+ });
+ }
+
+ if (heartbeatJSON?.localDateTime) {
+ facts.push({
+ title: "Time",
+ value: heartbeatJSON.localDateTime + (heartbeatJSON.timezone ? ` (${heartbeatJSON.timezone})` : ""),
+ });
+ }
+
+ const payload = {
+ "type": "message",
+ // message with status prefix as notification text
+ "summary": this._statusMessageFactory(status, monitorName, true),
+ "attachments": [
+ {
+ "contentType": "application/vnd.microsoft.card.adaptive",
+ "contentUrl": "",
+ "content": {
+ "type": "AdaptiveCard",
+ "body": [
+ {
+ "type": "Container",
+ "verticalContentAlignment": "Center",
+ "items": [
+ {
+ "type": "ColumnSet",
+ "style": this._getStyle(status),
+ "columns": [
+ {
+ "type": "Column",
+ "width": "auto",
+ "verticalContentAlignment": "Center",
+ "items": [
+ {
+ "type": "Image",
+ "width": "32px",
+ "style": "Person",
+ "url": "https://raw.githubusercontent.com/louislam/uptime-kuma/master/public/icon.png",
+ "altText": "Uptime Kuma Logo"
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "width": "stretch",
+ "items": [
+ {
+ "type": "TextBlock",
+ "size": "Medium",
+ "weight": "Bolder",
+ "text": `**${this._statusMessageFactory(status, monitorName, false)}**`,
+ },
+ {
+ "type": "TextBlock",
+ "size": "Small",
+ "weight": "Default",
+ "text": "Uptime Kuma Alert",
+ "isSubtle": true,
+ "spacing": "None"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "FactSet",
+ "separator": false,
+ "facts": facts
+ }
+ ],
+ "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
+ "version": "1.5"
+ }
+ }
+ ]
+ };
+
+ if (actions) {
+ payload.attachments[0].content.body.push({
+ "type": "ActionSet",
+ "actions": actions,
+ });
+ }
+
+ return payload;
+ };
+
+ /**
+ * Send the notification
+ * @param {string} webhookUrl URL to send the request to
+ * @param {object} payload Payload generated by _notificationPayloadFactory
+ * @returns {Promise<void>}
+ */
+ _sendNotification = async (webhookUrl, payload) => {
+ await axios.post(webhookUrl, payload);
+ };
+
+ /**
+ * Send a general notification
+ * @param {string} webhookUrl URL to send request to
+ * @param {string} msg Message to send
+ * @returns {Promise<void>}
+ */
+ _handleGeneralNotification = (webhookUrl, msg) => {
+ const payload = this._notificationPayloadFactory({
+ heartbeatJSON: {
+ msg: msg
+ }
+ });
+
+ return this._sendNotification(webhookUrl, payload);
+ };
+
+ /**
+ * @inheritdoc
+ */
+ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
+ const okMsg = "Sent Successfully.";
+
+ try {
+ if (heartbeatJSON == null) {
+ await this._handleGeneralNotification(notification.webhookUrl, msg);
+ return okMsg;
+ }
+
+ const baseURL = await setting("primaryBaseURL");
+ let dashboardUrl;
+ if (baseURL) {
+ dashboardUrl = baseURL + getMonitorRelativeURL(monitorJSON.id);
+ }
+
+ const payload = this._notificationPayloadFactory({
+ heartbeatJSON: heartbeatJSON,
+ monitorName: monitorJSON.name,
+ monitorUrl: this.extractAddress(monitorJSON),
+ dashboardUrl: dashboardUrl,
+ });
+
+ await this._sendNotification(notification.webhookUrl, payload);
+ return okMsg;
+ } catch (error) {
+ this.throwGeneralAxiosError(error);
+ }
+ }
+}
+
+module.exports = Teams;