diff --git a/server/notification-providers/bark.js b/server/notification-providers/bark.js new file mode 100644 index 00000000..4ebe978a --- /dev/null +++ b/server/notification-providers/bark.js @@ -0,0 +1,89 @@ +// +// bark.js +// UptimeKuma +// +// Created by Lakr Aream on 2021/10/24. +// Copyright © 2021 Lakr Aream. All rights reserved. +// + +const NotificationProvider = require("./notification-provider"); +const { DOWN, UP } = require("../../src/util"); +const { default: axios } = require("axios"); + +// bark is an APN bridge that sends notifications to Apple devices. + +const barkNotificationGroup = "UptimeKuma"; +const barkNotificationAvatar = "https://github.com/louislam/uptime-kuma/raw/master/public/icon.png"; +const barkNotificationSound = "telegraph"; +const successMessage = "Successes!"; + +class Bark extends NotificationProvider { + name = "Bark"; + + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + try { + var barkEndpoint = notification.barkEndpoint; + + // check if the endpoint has a "/" suffix, if so, delete it first + if (barkEndpoint.endsWith("/")) { + barkEndpoint = barkEndpoint.substring(0, barkEndpoint.length - 1); + } + + if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == UP) { + let title = "UptimeKuma Monitor Up"; + return await this.postNotification(title, msg, barkEndpoint); + } + + if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == DOWN) { + let title = "UptimeKuma Monitor Down"; + return await this.postNotification(title, msg, barkEndpoint); + } + + if (msg != null) { + let title = "UptimeKuma Message"; + return await this.postNotification(title, msg, barkEndpoint); + } + + } catch (error) { + throw error; + } + } + + // add additional parameter for better on device styles (iOS 15 optimized) + appendAdditionalParameters(postUrl) { + // grouping all our notifications + postUrl += "?group=" + barkNotificationGroup; + // set icon to uptime kuma icon, 11kb should be fine + postUrl += "&icon=" + barkNotificationAvatar; + // picked a sound, this should follow system's mute status when arrival + postUrl += "&sound=" + barkNotificationSound; + return postUrl; + } + + // thrown if failed to check result, result code should be in range 2xx + checkResult(result) { + if (result.status == null) { + throw new Error("Bark notification failed with invalid response!"); + } + if (result.status < 200 || result.status >= 300) { + throw new Error("Bark notification failed with status code " + result.status); + } + } + + async postNotification(title, subtitle, endpoint) { + // url encode title and subtitle + title = encodeURIComponent(title); + subtitle = encodeURIComponent(subtitle); + let postUrl = endpoint + "/" + title + "/" + subtitle; + postUrl = this.appendAdditionalParameters(postUrl); + let result = await axios.get(postUrl); + this.checkResult(result); + if (result.statusText != null) { + return "Bark notification succeed: " + result.statusText; + } + // because returned in range 200 ..< 300 + return successMessage; + } +} + +module.exports = Bark; diff --git a/server/notification.js b/server/notification.js index 658216f9..57453c4a 100644 --- a/server/notification.js +++ b/server/notification.js @@ -21,6 +21,7 @@ const Webhook = require("./notification-providers/webhook"); const Feishu = require("./notification-providers/feishu"); const AliyunSms = require("./notification-providers/aliyun-sms"); const DingDing = require("./notification-providers/dingding"); +const Bark = require("./notification-providers/bark"); class Notification { @@ -54,6 +55,7 @@ class Notification { new SMTP(), new Telegram(), new Webhook(), + new Bark(), ]; for (let item of list) { diff --git a/src/components/notifications/Bark.vue b/src/components/notifications/Bark.vue new file mode 100644 index 00000000..014450de --- /dev/null +++ b/src/components/notifications/Bark.vue @@ -0,0 +1,15 @@ + diff --git a/src/components/notifications/index.js b/src/components/notifications/index.js index 96ee2824..2d8c9c09 100644 --- a/src/components/notifications/index.js +++ b/src/components/notifications/index.js @@ -20,6 +20,7 @@ import Mattermost from "./Mattermost.vue"; import Matrix from "./Matrix.vue"; import AliyunSMS from "./AliyunSms.vue"; import DingDing from "./DingDing.vue"; +import Bark from "./Bark.vue"; /** * Manage all notification form. @@ -48,7 +49,8 @@ const NotificationFormList = { "line": Line, "mattermost": Mattermost, "matrix": Matrix, - "DingDing": DingDing + "DingDing": DingDing, + "Bark": Bark } export default NotificationFormList