mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-08-08 06:29:57 +08:00
Merge branch 'master' into fix-1448-discord-service-url
This commit is contained in:
@@ -40,17 +40,17 @@ class Alerta extends NotificationProvider {
|
||||
await axios.post(alertaUrl, postData, config);
|
||||
} else {
|
||||
let datadup = Object.assign( {
|
||||
correlate: ["service_up", "service_down"],
|
||||
correlate: [ "service_up", "service_down" ],
|
||||
event: monitorJSON["type"],
|
||||
group: "uptimekuma-" + monitorJSON["type"],
|
||||
resource: monitorJSON["name"],
|
||||
}, data );
|
||||
|
||||
if (heartbeatJSON["status"] == DOWN) {
|
||||
if (heartbeatJSON["status"] === DOWN) {
|
||||
datadup.severity = notification.alertaAlertState; // critical
|
||||
datadup.text = "Service " + monitorJSON["type"] + " is down.";
|
||||
await axios.post(alertaUrl, datadup, config);
|
||||
} else if (heartbeatJSON["status"] == UP) {
|
||||
} else if (heartbeatJSON["status"] === UP) {
|
||||
datadup.severity = notification.alertaRecoverState; // cleaned
|
||||
datadup.text = "Service " + monitorJSON["type"] + " is up.";
|
||||
await axios.post(alertaUrl, datadup, config);
|
||||
|
@@ -37,6 +37,12 @@ class AliyunSMS extends NotificationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the SMS notification
|
||||
* @param {BeanModel} notification Notification details
|
||||
* @param {string} msgbody Message template
|
||||
* @returns {boolean} True if successful else false
|
||||
*/
|
||||
async sendSms(notification, msgbody) {
|
||||
let params = {
|
||||
PhoneNumbers: notification.phonenumber,
|
||||
@@ -64,13 +70,18 @@ class AliyunSMS extends NotificationProvider {
|
||||
};
|
||||
|
||||
let result = await axios(config);
|
||||
if (result.data.Message == "OK") {
|
||||
if (result.data.Message === "OK") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Aliyun request sign */
|
||||
/**
|
||||
* Aliyun request sign
|
||||
* @param {Object} param Parameters object to sign
|
||||
* @param {string} AccessKeySecret Secret key to sign parameters with
|
||||
* @returns {string}
|
||||
*/
|
||||
sign(param, AccessKeySecret) {
|
||||
let param2 = {};
|
||||
let data = [];
|
||||
@@ -82,8 +93,23 @@ class AliyunSMS extends NotificationProvider {
|
||||
param2[key] = param[key];
|
||||
}
|
||||
|
||||
// Escape more characters than encodeURIComponent does.
|
||||
// For generating Aliyun signature, all characters except A-Za-z0-9~-._ are encoded.
|
||||
// See https://help.aliyun.com/document_detail/315526.html
|
||||
// This encoding methods as known as RFC 3986 (https://tools.ietf.org/html/rfc3986)
|
||||
let moreEscapesTable = function (m) {
|
||||
return {
|
||||
"!": "%21",
|
||||
"*": "%2A",
|
||||
"'": "%27",
|
||||
"(": "%28",
|
||||
")": "%29"
|
||||
}[m];
|
||||
};
|
||||
|
||||
for (let key in param2) {
|
||||
data.push(`${encodeURIComponent(key)}=${encodeURIComponent(param2[key])}`);
|
||||
let value = encodeURIComponent(param2[key]).replace(/[!*'()]/g, moreEscapesTable);
|
||||
data.push(`${encodeURIComponent(key)}=${value}`);
|
||||
}
|
||||
|
||||
let StringToSign = `POST&${encodeURIComponent("/")}&${encodeURIComponent(data.join("&"))}`;
|
||||
@@ -93,6 +119,11 @@ class AliyunSMS extends NotificationProvider {
|
||||
.digest("base64");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert status constant to string
|
||||
* @param {const} status The status constant
|
||||
* @returns {string}
|
||||
*/
|
||||
statusToString(status) {
|
||||
switch (status) {
|
||||
case DOWN:
|
||||
|
@@ -1,12 +1,12 @@
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const child_process = require("child_process");
|
||||
const childProcess = require("child_process");
|
||||
|
||||
class Apprise extends NotificationProvider {
|
||||
|
||||
name = "apprise";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let s = child_process.spawnSync("apprise", [ "-vv", "-b", msg, notification.appriseURL]);
|
||||
let s = childProcess.spawnSync("apprise", [ "-vv", "-b", msg, notification.appriseURL ]);
|
||||
|
||||
let output = (s.stdout) ? s.stdout.toString() : "ERROR: maybe apprise not found";
|
||||
|
||||
|
@@ -28,12 +28,12 @@ class Bark extends NotificationProvider {
|
||||
barkEndpoint = barkEndpoint.substring(0, barkEndpoint.length - 1);
|
||||
}
|
||||
|
||||
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == UP) {
|
||||
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) {
|
||||
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] === DOWN) {
|
||||
let title = "UptimeKuma Monitor Down";
|
||||
return await this.postNotification(title, msg, barkEndpoint);
|
||||
}
|
||||
@@ -44,7 +44,12 @@ class Bark extends NotificationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
// add additional parameter for better on device styles (iOS 15 optimized)
|
||||
/**
|
||||
* Add additional parameter for better on device styles (iOS 15
|
||||
* optimized)
|
||||
* @param {string} postUrl URL to append parameters to
|
||||
* @returns {string}
|
||||
*/
|
||||
appendAdditionalParameters(postUrl) {
|
||||
// grouping all our notifications
|
||||
postUrl += "?group=" + barkNotificationGroup;
|
||||
@@ -55,7 +60,11 @@ class Bark extends NotificationProvider {
|
||||
return postUrl;
|
||||
}
|
||||
|
||||
// thrown if failed to check result, result code should be in range 2xx
|
||||
/**
|
||||
* Check if result is successful
|
||||
* @param {Object} result Axios response object
|
||||
* @throws {Error} The status code is not in range 2xx
|
||||
*/
|
||||
checkResult(result) {
|
||||
if (result.status == null) {
|
||||
throw new Error("Bark notification failed with invalid response!");
|
||||
@@ -65,6 +74,13 @@ class Bark extends NotificationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the message
|
||||
* @param {string} title Message title
|
||||
* @param {string} subtitle Message
|
||||
* @param {string} endpoint Endpoint to send request to
|
||||
* @returns {string}
|
||||
*/
|
||||
async postNotification(title, subtitle, endpoint) {
|
||||
// url encode title and subtitle
|
||||
title = encodeURIComponent(title);
|
||||
|
@@ -37,6 +37,12 @@ class DingDing extends NotificationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message to DingDing
|
||||
* @param {BeanModel} notification
|
||||
* @param {Object} params Parameters of message
|
||||
* @returns {boolean} True if successful else false
|
||||
*/
|
||||
async sendToDingDing(notification, params) {
|
||||
let timestamp = Date.now();
|
||||
|
||||
@@ -50,13 +56,18 @@ class DingDing extends NotificationProvider {
|
||||
};
|
||||
|
||||
let result = await axios(config);
|
||||
if (result.data.errmsg == "ok") {
|
||||
if (result.data.errmsg === "ok") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** DingDing sign */
|
||||
/**
|
||||
* DingDing sign
|
||||
* @param {Date} timestamp Timestamp of message
|
||||
* @param {string} secretKey Secret key to sign data with
|
||||
* @returns {string}
|
||||
*/
|
||||
sign(timestamp, secretKey) {
|
||||
return Crypto
|
||||
.createHmac("sha256", Buffer.from(secretKey, "utf8"))
|
||||
@@ -64,7 +75,13 @@ class DingDing extends NotificationProvider {
|
||||
.digest("base64");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert status constant to string
|
||||
* @param {const} status The status constant
|
||||
* @returns {string}
|
||||
*/
|
||||
statusToString(status) {
|
||||
// TODO: Move to notification-provider.js to avoid repetition in classes
|
||||
switch (status) {
|
||||
case DOWN:
|
||||
return "DOWN";
|
||||
|
@@ -40,7 +40,7 @@ class Discord extends NotificationProvider {
|
||||
}
|
||||
|
||||
// If heartbeatJSON is not null, we go into the normal alerting loop.
|
||||
if (heartbeatJSON["status"] == DOWN) {
|
||||
if (heartbeatJSON["status"] === DOWN) {
|
||||
let discorddowndata = {
|
||||
username: discordDisplayName,
|
||||
embeds: [{
|
||||
@@ -75,7 +75,7 @@ class Discord extends NotificationProvider {
|
||||
await axios.post(notification.discordWebhookUrl, discorddowndata);
|
||||
return okMsg;
|
||||
|
||||
} else if (heartbeatJSON["status"] == UP) {
|
||||
} else if (heartbeatJSON["status"] === UP) {
|
||||
let discordupdata = {
|
||||
username: discordDisplayName,
|
||||
embeds: [{
|
||||
|
@@ -21,7 +21,7 @@ class Feishu extends NotificationProvider {
|
||||
return okMsg;
|
||||
}
|
||||
|
||||
if (heartbeatJSON["status"] == DOWN) {
|
||||
if (heartbeatJSON["status"] === DOWN) {
|
||||
let downdata = {
|
||||
msg_type: "post",
|
||||
content: {
|
||||
@@ -48,7 +48,7 @@ class Feishu extends NotificationProvider {
|
||||
return okMsg;
|
||||
}
|
||||
|
||||
if (heartbeatJSON["status"] == UP) {
|
||||
if (heartbeatJSON["status"] === UP) {
|
||||
let updata = {
|
||||
msg_type: "post",
|
||||
content: {
|
||||
|
@@ -18,7 +18,7 @@ class Gorush extends NotificationProvider {
|
||||
let data = {
|
||||
"notifications": [
|
||||
{
|
||||
"tokens": [notification.gorushDeviceToken],
|
||||
"tokens": [ notification.gorushDeviceToken ],
|
||||
"platform": platformMapping[notification.gorushPlatform],
|
||||
"message": msg,
|
||||
// Optional
|
||||
|
@@ -27,7 +27,7 @@ class Line extends NotificationProvider {
|
||||
]
|
||||
};
|
||||
await axios.post(lineAPIUrl, testMessage, config);
|
||||
} else if (heartbeatJSON["status"] == DOWN) {
|
||||
} else if (heartbeatJSON["status"] === DOWN) {
|
||||
let downMessage = {
|
||||
"to": notification.lineUserID,
|
||||
"messages": [
|
||||
@@ -38,7 +38,7 @@ class Line extends NotificationProvider {
|
||||
]
|
||||
};
|
||||
await axios.post(lineAPIUrl, downMessage, config);
|
||||
} else if (heartbeatJSON["status"] == UP) {
|
||||
} else if (heartbeatJSON["status"] === UP) {
|
||||
let upMessage = {
|
||||
"to": notification.lineUserID,
|
||||
"messages": [
|
||||
|
@@ -20,7 +20,7 @@ class LunaSea extends NotificationProvider {
|
||||
return okMsg;
|
||||
}
|
||||
|
||||
if (heartbeatJSON["status"] == DOWN) {
|
||||
if (heartbeatJSON["status"] === DOWN) {
|
||||
let downdata = {
|
||||
"title": "UptimeKuma Alert: " + monitorJSON["name"],
|
||||
"body": "[🔴 Down] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
|
||||
@@ -29,7 +29,7 @@ class LunaSea extends NotificationProvider {
|
||||
return okMsg;
|
||||
}
|
||||
|
||||
if (heartbeatJSON["status"] == UP) {
|
||||
if (heartbeatJSON["status"] === UP) {
|
||||
let updata = {
|
||||
"title": "UptimeKuma Alert: " + monitorJSON["name"],
|
||||
"body": "[✅ Up] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
|
||||
|
@@ -29,7 +29,7 @@ class Mattermost extends NotificationProvider {
|
||||
const mattermostIconEmoji = notification.mattermosticonemo;
|
||||
const mattermostIconUrl = notification.mattermosticonurl;
|
||||
|
||||
if (heartbeatJSON["status"] == DOWN) {
|
||||
if (heartbeatJSON["status"] === DOWN) {
|
||||
let mattermostdowndata = {
|
||||
username: mattermostUserName,
|
||||
text: "Uptime Kuma Alert",
|
||||
@@ -73,7 +73,7 @@ class Mattermost extends NotificationProvider {
|
||||
mattermostdowndata
|
||||
);
|
||||
return okMsg;
|
||||
} else if (heartbeatJSON["status"] == UP) {
|
||||
} else if (heartbeatJSON["status"] === UP) {
|
||||
let mattermostupdata = {
|
||||
username: mattermostUserName,
|
||||
text: "Uptime Kuma Alert",
|
||||
|
@@ -7,17 +7,23 @@ class NotificationProvider {
|
||||
name = undefined;
|
||||
|
||||
/**
|
||||
* @param notification : BeanModel
|
||||
* @param msg : string General Message
|
||||
* @param monitorJSON : object Monitor details (For Up/Down only)
|
||||
* @param heartbeatJSON : object Heartbeat details (For Up/Down only)
|
||||
* Send a notification
|
||||
* @param {BeanModel} notification
|
||||
* @param {string} msg General Message
|
||||
* @param {?Object} monitorJSON Monitor details (For Up/Down only)
|
||||
* @param {?Object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @returns {Promise<string>} Return Successful Message
|
||||
* Throw Error with fail msg
|
||||
* @throws Error with fail msg
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
throw new Error("Have to override Notification.send(...)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an error
|
||||
* @param {any} error The error to throw
|
||||
* @throws {any} The error specified
|
||||
*/
|
||||
throwGeneralAxiosError(error) {
|
||||
let msg = "Error: " + error + " ";
|
||||
|
||||
|
@@ -10,7 +10,7 @@ class Octopush extends NotificationProvider {
|
||||
|
||||
try {
|
||||
// Default - V2
|
||||
if (notification.octopushVersion == 2 || !notification.octopushVersion) {
|
||||
if (notification.octopushVersion === 2 || !notification.octopushVersion) {
|
||||
let config = {
|
||||
headers: {
|
||||
"api-key": notification.octopushAPIKey,
|
||||
@@ -31,13 +31,13 @@ class Octopush extends NotificationProvider {
|
||||
"sender": notification.octopushSenderName
|
||||
};
|
||||
await axios.post("https://api.octopush.com/v1/public/sms-campaign/send", data, config);
|
||||
} else if (notification.octopushVersion == 1) {
|
||||
} else if (notification.octopushVersion === 1) {
|
||||
let data = {
|
||||
"user_login": notification.octopushDMLogin,
|
||||
"api_key": notification.octopushDMAPIKey,
|
||||
"sms_recipients": notification.octopushDMPhoneNumber,
|
||||
"sms_sender": notification.octopushDMSenderName,
|
||||
"sms_type": (notification.octopushDMSMSType == "sms_premium") ? "FR" : "XXX",
|
||||
"sms_type": (notification.octopushDMSMSType === "sms_premium") ? "FR" : "XXX",
|
||||
"transactional": "1",
|
||||
//octopush not supporting non ascii char
|
||||
"sms_text": msg.replace(/[^\x00-\x7F]/g, ""),
|
||||
|
@@ -27,7 +27,7 @@ class OneBot extends NotificationProvider {
|
||||
"auto_escape": true,
|
||||
"message": pushText,
|
||||
};
|
||||
if (notification.msgType == "group") {
|
||||
if (notification.msgType === "group") {
|
||||
data["message_type"] = "group";
|
||||
data["group_id"] = notification.recieverId;
|
||||
} else {
|
||||
|
@@ -25,14 +25,14 @@ class Pushbullet extends NotificationProvider {
|
||||
"body": "Testing Successful.",
|
||||
};
|
||||
await axios.post(pushbulletUrl, testdata, config);
|
||||
} else if (heartbeatJSON["status"] == DOWN) {
|
||||
} else if (heartbeatJSON["status"] === DOWN) {
|
||||
let downdata = {
|
||||
"type": "note",
|
||||
"title": "UptimeKuma Alert: " + monitorJSON["name"],
|
||||
"body": "[🔴 Down] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
|
||||
};
|
||||
await axios.post(pushbulletUrl, downdata, config);
|
||||
} else if (heartbeatJSON["status"] == UP) {
|
||||
} else if (heartbeatJSON["status"] === UP) {
|
||||
let updata = {
|
||||
"type": "note",
|
||||
"title": "UptimeKuma Alert: " + monitorJSON["name"],
|
||||
|
@@ -13,9 +13,9 @@ class PushDeer extends NotificationProvider {
|
||||
let valid = msg != null && monitorJSON != null && heartbeatJSON != null;
|
||||
|
||||
let title;
|
||||
if (valid && heartbeatJSON.status == UP) {
|
||||
if (valid && heartbeatJSON.status === UP) {
|
||||
title = "## Uptime Kuma: " + monitorJSON.name + " up";
|
||||
} else if (valid && heartbeatJSON.status == DOWN) {
|
||||
} else if (valid && heartbeatJSON.status === DOWN) {
|
||||
title = "## Uptime Kuma: " + monitorJSON.name + " down";
|
||||
} else {
|
||||
title = "## Uptime Kuma Message";
|
||||
@@ -38,7 +38,7 @@ class PushDeer extends NotificationProvider {
|
||||
if (res.data.content.result.length === 0) {
|
||||
let error = "Invalid PushDeer key";
|
||||
this.throwGeneralAxiosError(error);
|
||||
} else if (JSON.parse(res.data.content.result[0]).success != "ok") {
|
||||
} else if (JSON.parse(res.data.content.result[0]).success !== "ok") {
|
||||
let error = "Unknown error";
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ class Slack extends NotificationProvider {
|
||||
/**
|
||||
* Deprecated property notification.slackbutton
|
||||
* Set it as primary base url if this is not yet set.
|
||||
* @param {string} url The primary base URL to use
|
||||
*/
|
||||
static async deprecateURL(url) {
|
||||
let currentPrimaryBaseURL = await setting("primaryBaseURL");
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const nodemailer = require("nodemailer");
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const { DOWN, UP } = require("../../src/util");
|
||||
const { DOWN } = require("../../src/util");
|
||||
|
||||
class SMTP extends NotificationProvider {
|
||||
|
||||
|
@@ -5,6 +5,12 @@ const { DOWN, UP } = 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
|
||||
* @returns {string}
|
||||
*/
|
||||
_statusMessageFactory = (status, monitorName) => {
|
||||
if (status === DOWN) {
|
||||
return `🔴 Application [${monitorName}] went down`;
|
||||
@@ -14,6 +20,11 @@ class Teams extends NotificationProvider {
|
||||
return "Notification";
|
||||
};
|
||||
|
||||
/**
|
||||
* Select theme color to use based on status
|
||||
* @param {const} status The status constant
|
||||
* @returns {string} Selected color in hex RGB format
|
||||
*/
|
||||
_getThemeColor = (status) => {
|
||||
if (status === DOWN) {
|
||||
return "ff0000";
|
||||
@@ -24,6 +35,14 @@ class Teams extends NotificationProvider {
|
||||
return "008cff";
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate payload for notification
|
||||
* @param {const} status The status of the monitor
|
||||
* @param {string} monitorMessage Message to send
|
||||
* @param {string} monitorName Name of monitor affected
|
||||
* @param {string} monitorUrl URL of monitor affected
|
||||
* @returns {Object}
|
||||
*/
|
||||
_notificationPayloadFactory = ({
|
||||
status,
|
||||
monitorMessage,
|
||||
@@ -74,10 +93,21 @@ class Teams extends NotificationProvider {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Send the notification
|
||||
* @param {string} webhookUrl URL to send the request to
|
||||
* @param {Object} payload Payload generated by _notificationPayloadFactory
|
||||
*/
|
||||
_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({
|
||||
monitorMessage: msg
|
||||
|
@@ -24,12 +24,18 @@ class WeCom extends NotificationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the message to send
|
||||
* @param {Object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @param {string} msg General message
|
||||
* @returns {Object}
|
||||
*/
|
||||
composeMessage(heartbeatJSON, msg) {
|
||||
let title;
|
||||
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == UP) {
|
||||
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] === UP) {
|
||||
title = "UptimeKuma Monitor Up";
|
||||
}
|
||||
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == DOWN) {
|
||||
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] === DOWN) {
|
||||
title = "UptimeKuma Monitor Down";
|
||||
}
|
||||
if (msg != null) {
|
||||
|
Reference in New Issue
Block a user