diff --git a/server/notification-providers/bale.js b/server/notification-providers/bale.js new file mode 100644 index 000000000..4b06ab27b --- /dev/null +++ b/server/notification-providers/bale.js @@ -0,0 +1,34 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); + +class Bale extends NotificationProvider { + name = "bale"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + const url = "https://tapi.bale.ai"; + + try { + await axios.post( + `${url}/bot${notification.baleBotToken}/sendMessage`, + { + chat_id: notification.baleChatID, + text: msg + }, + { + headers: { + "content-type": "application/json", + }, + } + ); + return okMsg; + } catch (error) { + this.throwGeneralAxiosError(error); + } + } +} + +module.exports = Bale; diff --git a/server/notification-providers/dingding.js b/server/notification-providers/dingding.js index c66f270a7..cfacd45ed 100644 --- a/server/notification-providers/dingding.js +++ b/server/notification-providers/dingding.js @@ -11,17 +11,23 @@ class DingDing extends NotificationProvider { */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { const okMsg = "Sent Successfully."; - + const mentionAll = notification.mentioning === "everyone"; + const mobileList = notification.mentioning === "specify-mobiles" ? notification.mobileList : []; + const userList = notification.mentioning === "specify-users" ? notification.userList : []; + const finalList = [ ...mobileList || [], ...userList || [] ]; + const mentionStr = finalList.length > 0 ? "\n" : "" + finalList.map(item => `@${item}`).join(" "); try { if (heartbeatJSON != null) { let params = { msgtype: "markdown", markdown: { title: `[${this.statusToString(heartbeatJSON["status"])}] ${monitorJSON["name"]}`, - text: `## [${this.statusToString(heartbeatJSON["status"])}] ${monitorJSON["name"]} \n> ${heartbeatJSON["msg"]}\n> Time (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`, + text: `## [${this.statusToString(heartbeatJSON["status"])}] ${monitorJSON["name"]} \n> ${heartbeatJSON["msg"]}\n> Time (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}${mentionStr}`, }, - "at": { - "isAtAll": notification.mentioning === "everyone" + at: { + isAtAll: mentionAll, + atUserIds: userList, + atMobiles: mobileList } }; if (await this.sendToDingDing(notification, params)) { @@ -31,7 +37,12 @@ class DingDing extends NotificationProvider { let params = { msgtype: "text", text: { - content: msg + content: `${msg}${mentionStr}` + }, + at: { + isAtAll: mentionAll, + atUserIds: userList, + atMobiles: mobileList } }; if (await this.sendToDingDing(notification, params)) { diff --git a/server/notification.js b/server/notification.js index e7977eb4a..7a1fd4ab6 100644 --- a/server/notification.js +++ b/server/notification.js @@ -4,6 +4,7 @@ const Alerta = require("./notification-providers/alerta"); const AlertNow = require("./notification-providers/alertnow"); const AliyunSms = require("./notification-providers/aliyun-sms"); const Apprise = require("./notification-providers/apprise"); +const Bale = require("./notification-providers/bale"); const Bark = require("./notification-providers/bark"); const Bitrix24 = require("./notification-providers/bitrix24"); const ClickSendSMS = require("./notification-providers/clicksendsms"); @@ -71,7 +72,6 @@ const Wpush = require("./notification-providers/wpush"); const SendGrid = require("./notification-providers/send-grid"); class Notification { - providerList = {}; /** @@ -90,6 +90,7 @@ class Notification { new AlertNow(), new AliyunSms(), new Apprise(), + new Bale(), new Bark(), new Bitrix24(), new ClickSendSMS(), @@ -154,10 +155,10 @@ class Notification { new GtxMessaging(), new Cellsynt(), new Wpush(), - new SendGrid() + new SendGrid(), ]; for (let item of list) { - if (! item.name) { + if (!item.name) { throw new Error("Notification provider without name"); } @@ -177,9 +178,19 @@ class Notification { * @returns {Promise} Successful msg * @throws Error with fail msg */ - static async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + static async send( + notification, + msg, + monitorJSON = null, + heartbeatJSON = null + ) { if (this.providerList[notification.type]) { - return this.providerList[notification.type].send(notification, msg, monitorJSON, heartbeatJSON); + return this.providerList[notification.type].send( + notification, + msg, + monitorJSON, + heartbeatJSON + ); } else { throw new Error("Notification type is not supported"); } @@ -201,10 +212,9 @@ class Notification { userID, ]); - if (! bean) { + if (!bean) { throw new Error("notification not found"); } - } else { bean = R.dispense("notification"); } @@ -234,7 +244,7 @@ class Notification { userID, ]); - if (! bean) { + if (!bean) { throw new Error("notification not found"); } @@ -250,7 +260,6 @@ class Notification { let exists = commandExistsSync("apprise"); return exists; } - } /** @@ -261,16 +270,17 @@ class Notification { */ async function applyNotificationEveryMonitor(notificationID, userID) { let monitors = await R.getAll("SELECT id FROM monitor WHERE user_id = ?", [ - userID + userID, ]); for (let i = 0; i < monitors.length; i++) { - let checkNotification = await R.findOne("monitor_notification", " monitor_id = ? AND notification_id = ? ", [ - monitors[i].id, - notificationID, - ]); + let checkNotification = await R.findOne( + "monitor_notification", + " monitor_id = ? AND notification_id = ? ", + [ monitors[i].id, notificationID ] + ); - if (! checkNotification) { + if (!checkNotification) { let relation = R.dispense("monitor_notification"); relation.monitor_id = monitors[i].id; relation.notification_id = notificationID; diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index f6d728029..307b09910 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -113,6 +113,7 @@ export default { "alerta": "Alerta", "AlertNow": "AlertNow", "apprise": this.$t("apprise"), + "bale": "Bale", "Bark": "Bark", "Bitrix24": "Bitrix24", "clicksendsms": "ClickSend SMS", diff --git a/src/components/notifications/Bale.vue b/src/components/notifications/Bale.vue new file mode 100644 index 000000000..ea69e21b1 --- /dev/null +++ b/src/components/notifications/Bale.vue @@ -0,0 +1,93 @@ + + + diff --git a/src/components/notifications/DingDing.vue b/src/components/notifications/DingDing.vue index 710677fd7..a5fd3c82b 100644 --- a/src/components/notifications/DingDing.vue +++ b/src/components/notifications/DingDing.vue @@ -16,22 +16,128 @@
- + +
+
+ + +
+
+ + +
diff --git a/src/components/notifications/index.js b/src/components/notifications/index.js index efa2af5c4..d2e2364eb 100644 --- a/src/components/notifications/index.js +++ b/src/components/notifications/index.js @@ -2,6 +2,7 @@ import Alerta from "./Alerta.vue"; import AlertNow from "./AlertNow.vue"; import AliyunSMS from "./AliyunSms.vue"; import Apprise from "./Apprise.vue"; +import Bale from "./Bale.vue"; import Bark from "./Bark.vue"; import Bitrix24 from "./Bitrix24.vue"; import ClickSendSMS from "./ClickSendSMS.vue"; @@ -73,75 +74,76 @@ import SendGrid from "./SendGrid.vue"; * @type { Record } */ const NotificationFormList = { - "alerta": Alerta, - "AlertNow": AlertNow, - "AliyunSMS": AliyunSMS, - "apprise": Apprise, - "Bark": Bark, - "Bitrix24": Bitrix24, - "clicksendsms": ClickSendSMS, - "CallMeBot": CallMeBot, - "smsc": SMSC, - "DingDing": DingDing, - "discord": Discord, - "Elks": Elks, - "Feishu": Feishu, - "FreeMobile": FreeMobile, - "GoogleChat": GoogleChat, - "gorush": Gorush, - "gotify": Gotify, - "GrafanaOncall": GrafanaOncall, - "HomeAssistant": HomeAssistant, - "HeiiOnCall": HeiiOnCall, - "Keep": Keep, - "Kook": Kook, - "line": Line, - "LineNotify": LineNotify, - "lunasea": LunaSea, - "matrix": Matrix, - "mattermost": Mattermost, - "nostr": Nostr, - "ntfy": Ntfy, - "octopush": Octopush, - "OneBot": OneBot, - "Onesender": Onesender, - "Opsgenie": Opsgenie, - "PagerDuty": PagerDuty, - "FlashDuty": FlashDuty, - "PagerTree": PagerTree, - "promosms": PromoSMS, - "pushbullet": Pushbullet, - "PushByTechulus": TechulusPush, - "PushDeer": PushDeer, - "pushover": Pushover, - "pushy": Pushy, + alerta: Alerta, + AlertNow: AlertNow, + AliyunSMS: AliyunSMS, + apprise: Apprise, + bale: Bale, + Bark: Bark, + Bitrix24: Bitrix24, + clicksendsms: ClickSendSMS, + CallMeBot: CallMeBot, + smsc: SMSC, + DingDing: DingDing, + discord: Discord, + Elks: Elks, + Feishu: Feishu, + FreeMobile: FreeMobile, + GoogleChat: GoogleChat, + gorush: Gorush, + gotify: Gotify, + GrafanaOncall: GrafanaOncall, + HomeAssistant: HomeAssistant, + HeiiOnCall: HeiiOnCall, + Keep: Keep, + Kook: Kook, + line: Line, + LineNotify: LineNotify, + lunasea: LunaSea, + matrix: Matrix, + mattermost: Mattermost, + nostr: Nostr, + ntfy: Ntfy, + octopush: Octopush, + OneBot: OneBot, + Onesender: Onesender, + Opsgenie: Opsgenie, + PagerDuty: PagerDuty, + FlashDuty: FlashDuty, + PagerTree: PagerTree, + promosms: PromoSMS, + pushbullet: Pushbullet, + PushByTechulus: TechulusPush, + PushDeer: PushDeer, + pushover: Pushover, + pushy: Pushy, "rocket.chat": RocketChat, - "serwersms": SerwerSMS, - "signal": Signal, - "SIGNL4": SIGNL4, - "SMSManager": SMSManager, - "SMSPartner": SMSPartner, - "slack": Slack, - "squadcast": Squadcast, - "SMSEagle": SMSEagle, - "smtp": STMP, - "stackfield": Stackfield, - "teams": Teams, - "telegram": Telegram, - "threema": Threema, - "twilio": Twilio, - "Splunk": Splunk, - "webhook": Webhook, - "WeCom": WeCom, - "GoAlert": GoAlert, - "ServerChan": ServerChan, - "ZohoCliq": ZohoCliq, - "SevenIO": SevenIO, - "whapi": Whapi, - "gtxmessaging": GtxMessaging, - "Cellsynt": Cellsynt, - "WPush": WPush, - "SendGrid": SendGrid, + serwersms: SerwerSMS, + signal: Signal, + SIGNL4: SIGNL4, + SMSManager: SMSManager, + SMSPartner: SMSPartner, + slack: Slack, + squadcast: Squadcast, + SMSEagle: SMSEagle, + smtp: STMP, + stackfield: Stackfield, + teams: Teams, + telegram: Telegram, + threema: Threema, + twilio: Twilio, + Splunk: Splunk, + webhook: Webhook, + WeCom: WeCom, + GoAlert: GoAlert, + ServerChan: ServerChan, + ZohoCliq: ZohoCliq, + SevenIO: SevenIO, + whapi: Whapi, + gtxmessaging: GtxMessaging, + Cellsynt: Cellsynt, + WPush: WPush, + SendGrid: SendGrid, }; export default NotificationFormList; diff --git a/src/lang/en.json b/src/lang/en.json index e215f1031..112979bd6 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -429,6 +429,9 @@ "trustProxyDescription": "Trust 'X-Forwarded-*' headers. If you want to get the correct client IP and your Uptime Kuma is behind a proxy such as Nginx or Apache, you should enable this.", "wayToGetLineNotifyToken": "You can get an access token from {0}", "Examples": "Examples", + "supportBaleChatID": "Support Direct Chat / Group / Channel's Chat ID", + "wayToGetBaleChatID": "You can get your chat ID by sending a message to the bot and going to this URL to view the chat_id:", + "wayToGetBaleToken": "You can get a token from {0}.", "Home Assistant URL": "Home Assistant URL", "Long-Lived Access Token": "Long-Lived Access Token", "Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ", @@ -687,6 +690,14 @@ "Mentioning": "Mentioning", "Don't mention people": "Don't mention people", "Mention group": "Mention {group}", + "Mention Mobile List": "Mention mobile list", + "Mention User List": "Mention user id list", + "Dingtalk Mobile List": "Mobile list", + "Dingtalk User List": "User ID list", + "Enter a list of userId": "Enter a list of userId", + "Enter a list of mobile": "Enter a list of mobile", + "Invalid mobile": "Invalid mobile [{mobile}]", + "Invalid userId": "Invalid userId [{userId}]", "Device Token": "Device Token", "Platform": "Platform", "Huawei": "Huawei",