From 5e3ea3293c5d1f37ba65ab94182075b788608b45 Mon Sep 17 00:00:00 2001
From: Lukas <35193662+NixNotCastey@users.noreply.github.com>
Date: Sat, 9 Oct 2021 20:32:45 +0200
Subject: [PATCH 01/26] Very basic email subject customization
---
server/notification-providers/smtp.js | 10 +++++++++-
src/components/notifications/SMTP.vue | 5 +++++
src/languages/en.js | 1 +
3 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/server/notification-providers/smtp.js b/server/notification-providers/smtp.js
index ecb583eb7..e5fd53e46 100644
--- a/server/notification-providers/smtp.js
+++ b/server/notification-providers/smtp.js
@@ -20,6 +20,14 @@ class SMTP extends NotificationProvider {
pass: notification.smtpPassword,
};
}
+ // Lets start with default subject
+ let subject = msg;
+ // Our subject cannot end with whitespace it's often raise spam score
+ let customsubject = notification.customsubject.trim()
+ // If custom subject is not empty, change subject for notification
+ if (customsubject !== "") {
+ subject = customsubject
+ }
let transporter = nodemailer.createTransport(config);
@@ -34,7 +42,7 @@ class SMTP extends NotificationProvider {
cc: notification.smtpCC,
bcc: notification.smtpBCC,
to: notification.smtpTo,
- subject: msg,
+ subject: subject,
text: bodyTextContent,
tls: {
rejectUnauthorized: notification.smtpIgnoreTLSError || false,
diff --git a/src/components/notifications/SMTP.vue b/src/components/notifications/SMTP.vue
index 72934cdaf..165d39c67 100644
--- a/src/components/notifications/SMTP.vue
+++ b/src/components/notifications/SMTP.vue
@@ -43,6 +43,11 @@
+
+
+
+
+
diff --git a/src/languages/en.js b/src/languages/en.js
index 2ce8f46be..b59cdb73f 100644
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -201,6 +201,7 @@ export default {
secureOptionTLS: "TLS (465)",
"Ignore TLS Error": "Ignore TLS Error",
"From Email": "From Email",
+ "Custom Email subject": "Custom Email Subject (leave blank for default one)",
"To Email": "To Email",
smtpCC: "CC",
smtpBCC: "BCC",
From 792f3c7c5c17a2db80e7f9638e272b4607f3d4c6 Mon Sep 17 00:00:00 2001
From: Lukas <35193662+NixNotCastey@users.noreply.github.com>
Date: Sat, 9 Oct 2021 21:48:28 +0200
Subject: [PATCH 02/26] Add support for values of Name, Hostname and Status
---
server/notification-providers/smtp.js | 30 +++++++++++++++++++++++++++
src/components/notifications/SMTP.vue | 4 ++--
src/languages/en.js | 2 +-
3 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/server/notification-providers/smtp.js b/server/notification-providers/smtp.js
index e5fd53e46..2bbec5848 100644
--- a/server/notification-providers/smtp.js
+++ b/server/notification-providers/smtp.js
@@ -22,10 +22,40 @@ class SMTP extends NotificationProvider {
}
// Lets start with default subject
let subject = msg;
+
// Our subject cannot end with whitespace it's often raise spam score
let customsubject = notification.customsubject.trim()
+
// If custom subject is not empty, change subject for notification
if (customsubject !== "") {
+
+ // Replace "MACROS" with coresponding variable
+ let replaceName = new RegExp("{NAME}", "g");
+ let replaceHostname = new RegExp("{HOSTNAME}", "g");
+ let replaceStatus = new RegExp("{STATUS}", "g");
+
+ let serviceStatus;
+
+ if (monitorJSON !== null) {
+ customsubject = customsubject.replace(replaceName,monitorJSON["name"]);
+ customsubject = customsubject.replace(replaceHostname,monitorJSON["hostname"]);
+ } else {
+ // Insert dummy values during test
+ customsubject = customsubject.replace(replaceName,"Test");
+ customsubject = customsubject.replace(replaceHostname,"example.com");
+ }
+ if (heartbeatJSON !== null) {
+ if (heartbeatJSON["status"] === 0) {
+ serviceStatus = "🔴 Down"
+ } else {
+ serviceStatus = "✅ Up"
+ }
+ customsubject = customsubject.replace(replaceStatus,serviceStatus);
+ } else {
+ // Insert dummy values during test
+ customsubject = customsubject.replace(replaceStatus,"TEST");
+ }
+
subject = customsubject
}
diff --git a/src/components/notifications/SMTP.vue b/src/components/notifications/SMTP.vue
index 165d39c67..01bdf8607 100644
--- a/src/components/notifications/SMTP.vue
+++ b/src/components/notifications/SMTP.vue
@@ -44,8 +44,8 @@
-
-
+
+
diff --git a/src/languages/en.js b/src/languages/en.js
index b59cdb73f..0e8e92302 100644
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -201,7 +201,7 @@ export default {
secureOptionTLS: "TLS (465)",
"Ignore TLS Error": "Ignore TLS Error",
"From Email": "From Email",
- "Custom Email subject": "Custom Email Subject (leave blank for default one)",
+ "Email Subject": "Subject (leave blank for default one)",
"To Email": "To Email",
smtpCC: "CC",
smtpBCC: "BCC",
From d733ec018e6698f45f17b53d19cc725e71eec279 Mon Sep 17 00:00:00 2001
From: giacomo892
Date: Tue, 12 Oct 2021 19:37:58 +0200
Subject: [PATCH 03/26] Prioritize host arg
Otherwise launching the program with the --host argument does nothing
---
server/server.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/server.js b/server/server.js
index 67095ff53..3e8ddd319 100644
--- a/server/server.js
+++ b/server/server.js
@@ -61,7 +61,7 @@ console.info("Version: " + checkVersion.version);
// If host is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available and the unspecified IPv4 address (0.0.0.0) otherwise.
// Dual-stack support for (::)
-const hostname = process.env.HOST || args.host;
+const hostname = args.host || process.env.HOST;
const port = parseInt(process.env.PORT || args.port || 3001);
// SSL
From 30d8aadf12af55198679960685130321507af865 Mon Sep 17 00:00:00 2001
From: Lukas <35193662+NixNotCastey@users.noreply.github.com>
Date: Tue, 12 Oct 2021 23:24:34 +0200
Subject: [PATCH 04/26] Slightly refactor
---
server/notification-providers/smtp.js | 33 ++++++++++++---------------
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/server/notification-providers/smtp.js b/server/notification-providers/smtp.js
index 2bbec5848..7def06940 100644
--- a/server/notification-providers/smtp.js
+++ b/server/notification-providers/smtp.js
@@ -1,5 +1,6 @@
const nodemailer = require("nodemailer");
const NotificationProvider = require("./notification-provider");
+const { DOWN, UP } = require("../../src/util");
class SMTP extends NotificationProvider {
@@ -28,33 +29,29 @@ class SMTP extends NotificationProvider {
// If custom subject is not empty, change subject for notification
if (customsubject !== "") {
-
- // Replace "MACROS" with coresponding variable
+
+ // Replace "MACROS" with coresponding variable
let replaceName = new RegExp("{NAME}", "g");
let replaceHostname = new RegExp("{HOSTNAME}", "g");
let replaceStatus = new RegExp("{STATUS}", "g");
- let serviceStatus;
+ // Lets start with dummy values to simplify code
+ let monitorName = "Test"
+ let monitorHostname = "example.com"
+ let serviceStatus = "⚠️ Test";
if (monitorJSON !== null) {
- customsubject = customsubject.replace(replaceName,monitorJSON["name"]);
- customsubject = customsubject.replace(replaceHostname,monitorJSON["hostname"]);
- } else {
- // Insert dummy values during test
- customsubject = customsubject.replace(replaceName,"Test");
- customsubject = customsubject.replace(replaceHostname,"example.com");
+ monitorName = monitorJSON["name"];
+ monitorHostname = monitorJSON["hostname"];
}
+
if (heartbeatJSON !== null) {
- if (heartbeatJSON["status"] === 0) {
- serviceStatus = "🔴 Down"
- } else {
- serviceStatus = "✅ Up"
- }
- customsubject = customsubject.replace(replaceStatus,serviceStatus);
- } else {
- // Insert dummy values during test
- customsubject = customsubject.replace(replaceStatus,"TEST");
+ serviceStatus = heartbeatJSON["status"] == DOWN ? "🔴 Down":"✅ Up";
}
+ // Break replace to one by line for better readability
+ customsubject = customsubject.replace(replaceStatus,serviceStatus);
+ customsubject = customsubject.replace(replaceName,monitorName);
+ customsubject = customsubject.replace(replaceHostname,monitorHostname);
subject = customsubject
}
From a2f22532213353da4dd5b6d1b543602102ddc7a6 Mon Sep 17 00:00:00 2001
From: wuwenjing
Date: Wed, 13 Oct 2021 11:55:01 +0800
Subject: [PATCH 05/26] Add aliyun sms notification
---
package.json | 1 +
server/notification-providers/aliyun-sms.js | 70 +++++++++++++++++++++
server/notification.js | 2 +
src/components/notifications/AliyunSms.vue | 24 +++++++
src/components/notifications/index.js | 2 +
5 files changed, 99 insertions(+)
create mode 100644 server/notification-providers/aliyun-sms.js
create mode 100644 src/components/notifications/AliyunSms.vue
diff --git a/package.json b/package.json
index 03112518a..1dd79e905 100644
--- a/package.json
+++ b/package.json
@@ -52,6 +52,7 @@
"update-language-files": "cd extra/update-language-files && node index.js && eslint ../../src/languages/**.js --fix"
},
"dependencies": {
+ "@alicloud/pop-core": "^1.7.10",
"@fortawesome/fontawesome-svg-core": "~1.2.36",
"@fortawesome/free-regular-svg-icons": "~5.15.4",
"@fortawesome/free-solid-svg-icons": "~5.15.4",
diff --git a/server/notification-providers/aliyun-sms.js b/server/notification-providers/aliyun-sms.js
new file mode 100644
index 000000000..9111c429a
--- /dev/null
+++ b/server/notification-providers/aliyun-sms.js
@@ -0,0 +1,70 @@
+const NotificationProvider = require("./notification-provider");
+const { DOWN, UP } = require("../../src/util");
+const Core = require("@alicloud/pop-core");
+
+class AliyunSMS extends NotificationProvider {
+ name = "AliyunSMS";
+
+ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
+ let okMsg = "Sent Successfully.";
+
+ try {
+ var client = new Core({
+ accessKeyId: notification.accessKeyId,
+ accessKeySecret: notification.secretAccessKey,
+ endpoint: "https://dysmsapi.aliyuncs.com",
+ apiVersion: "2017-05-25",
+ });
+
+ var params = {
+ PhoneNumbers: notification.phonenumber,
+ TemplateCode: notification.templateCode,
+ SignName: notification.signName,
+ TemplateParam: JSON.stringify({
+ name: "",
+ time: "",
+ status: "",
+ msg: msg,
+ }),
+ };
+
+ if (heartbeatJSON != null) {
+ params.TemplateParam = JSON.stringify({
+ name: monitorJSON["name"],
+ time: heartbeatJSON["time"],
+ status: this.statusToString(heartbeatJSON["status"]),
+ msg: heartbeatJSON["msg"],
+ });
+ }
+
+ var requestOption = {
+ method: "POST",
+ };
+
+ await client.request("SendSms", params, requestOption).then(
+ (result) => {
+ console.log(JSON.stringify(result));
+ return okMsg;
+ },
+ (ex) => {
+ console.log(ex);
+ }
+ );
+ } catch (error) {
+ this.throwGeneralAxiosError(error);
+ }
+ }
+
+ statusToString(status) {
+ switch (status) {
+ case DOWN:
+ return "DOWN";
+ case UP:
+ return "UP";
+ default:
+ return status;
+ }
+ }
+}
+
+module.exports = AliyunSMS;
diff --git a/server/notification.js b/server/notification.js
index 41a0063c3..21bd2b1e6 100644
--- a/server/notification.js
+++ b/server/notification.js
@@ -19,6 +19,7 @@ const Teams = require("./notification-providers/teams");
const Telegram = require("./notification-providers/telegram");
const Webhook = require("./notification-providers/webhook");
const Feishu = require("./notification-providers/feishu");
+const AliyunSms = require("./notification-providers/aliyun-sms");
class Notification {
@@ -31,6 +32,7 @@ class Notification {
const list = [
new Apprise(),
+ new AliyunSms(),
new Discord(),
new Teams(),
new Gotify(),
diff --git a/src/components/notifications/AliyunSms.vue b/src/components/notifications/AliyunSms.vue
new file mode 100644
index 000000000..07dca8bbb
--- /dev/null
+++ b/src/components/notifications/AliyunSms.vue
@@ -0,0 +1,24 @@
+
+
+
diff --git a/src/components/notifications/index.js b/src/components/notifications/index.js
index 140c1180c..74fe0df38 100644
--- a/src/components/notifications/index.js
+++ b/src/components/notifications/index.js
@@ -18,6 +18,7 @@ import Pushbullet from "./Pushbullet.vue";
import Line from "./Line.vue";
import Mattermost from "./Mattermost.vue";
import Matrix from "./Matrix.vue";
+import AliyunSMS from "./AliyunSms.vue";
/**
* Manage all notification form.
@@ -40,6 +41,7 @@ const NotificationFormList = {
"promosms": PromoSMS,
"lunasea": LunaSea,
"Feishu": Feishu,
+ "AliyunSMS":AliyunSMS,
"apprise": Apprise,
"pushbullet": Pushbullet,
"line": Line,
From 330cd6e058b77cda9444482d184474af48a39424 Mon Sep 17 00:00:00 2001
From: Lukas <35193662+NixNotCastey@users.noreply.github.com>
Date: Wed, 13 Oct 2021 07:32:09 +0200
Subject: [PATCH 06/26] Minor rehabilitanty impedyment
Co-authored-by: Adam Stachowicz
---
server/notification-providers/smtp.js | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/server/notification-providers/smtp.js b/server/notification-providers/smtp.js
index 7def06940..dd1cd10a7 100644
--- a/server/notification-providers/smtp.js
+++ b/server/notification-providers/smtp.js
@@ -46,12 +46,13 @@ class SMTP extends NotificationProvider {
}
if (heartbeatJSON !== null) {
- serviceStatus = heartbeatJSON["status"] == DOWN ? "🔴 Down":"✅ Up";
+ serviceStatus = heartbeatJSON["status"] == DOWN ? "🔴 Down" : "✅ Up";
}
+
// Break replace to one by line for better readability
- customsubject = customsubject.replace(replaceStatus,serviceStatus);
- customsubject = customsubject.replace(replaceName,monitorName);
- customsubject = customsubject.replace(replaceHostname,monitorHostname);
+ customsubject = customsubject.replace(replaceStatus, serviceStatus);
+ customsubject = customsubject.replace(replaceName, monitorName);
+ customsubject = customsubject.replace(replaceHostname, monitorHostname);
subject = customsubject
}
From 3fe34505332ee6f8a51188fcc2111f7721ade2c0 Mon Sep 17 00:00:00 2001
From: giacomo892
Date: Wed, 13 Oct 2021 08:29:55 +0200
Subject: [PATCH 07/26] Prioritize port passed from args
Co-authored-by: Adam Stachowicz
---
server/server.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/server.js b/server/server.js
index 3e8ddd319..7dbd6155f 100644
--- a/server/server.js
+++ b/server/server.js
@@ -62,7 +62,7 @@ console.info("Version: " + checkVersion.version);
// If host is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available and the unspecified IPv4 address (0.0.0.0) otherwise.
// Dual-stack support for (::)
const hostname = args.host || process.env.HOST;
-const port = parseInt(process.env.PORT || args.port || 3001);
+const port = parseInt(args.port || process.env.PORT || 3001);
// SSL
const sslKey = process.env.SSL_KEY || args["ssl-key"] || undefined;
From 57a76e6129145bdeb75755885ca31099795473e5 Mon Sep 17 00:00:00 2001
From: wuwenjing
Date: Wed, 13 Oct 2021 14:41:59 +0800
Subject: [PATCH 08/26] remove `alicloud/pop-core` keep simple
---
package.json | 1 -
server/notification-providers/aliyun-sms.js | 106 +++++++++++++-------
src/components/notifications/AliyunSms.vue | 1 +
3 files changed, 73 insertions(+), 35 deletions(-)
diff --git a/package.json b/package.json
index 1dd79e905..03112518a 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,6 @@
"update-language-files": "cd extra/update-language-files && node index.js && eslint ../../src/languages/**.js --fix"
},
"dependencies": {
- "@alicloud/pop-core": "^1.7.10",
"@fortawesome/fontawesome-svg-core": "~1.2.36",
"@fortawesome/free-regular-svg-icons": "~5.15.4",
"@fortawesome/free-solid-svg-icons": "~5.15.4",
diff --git a/server/notification-providers/aliyun-sms.js b/server/notification-providers/aliyun-sms.js
index 9111c429a..d5d59be91 100644
--- a/server/notification-providers/aliyun-sms.js
+++ b/server/notification-providers/aliyun-sms.js
@@ -1,6 +1,8 @@
const NotificationProvider = require("./notification-provider");
const { DOWN, UP } = require("../../src/util");
-const Core = require("@alicloud/pop-core");
+const { default: axios } = require("axios");
+const Crypto = require("crypto");
+const qs = require("qs");
class AliyunSMS extends NotificationProvider {
name = "AliyunSMS";
@@ -9,52 +11,88 @@ class AliyunSMS extends NotificationProvider {
let okMsg = "Sent Successfully.";
try {
- var client = new Core({
- accessKeyId: notification.accessKeyId,
- accessKeySecret: notification.secretAccessKey,
- endpoint: "https://dysmsapi.aliyuncs.com",
- apiVersion: "2017-05-25",
- });
-
- var params = {
- PhoneNumbers: notification.phonenumber,
- TemplateCode: notification.templateCode,
- SignName: notification.signName,
- TemplateParam: JSON.stringify({
- name: "",
- time: "",
- status: "",
- msg: msg,
- }),
- };
-
if (heartbeatJSON != null) {
- params.TemplateParam = JSON.stringify({
+ var msgBody = JSON.stringify({
name: monitorJSON["name"],
time: heartbeatJSON["time"],
status: this.statusToString(heartbeatJSON["status"]),
msg: heartbeatJSON["msg"],
});
- }
-
- var requestOption = {
- method: "POST",
- };
-
- await client.request("SendSms", params, requestOption).then(
- (result) => {
- console.log(JSON.stringify(result));
+ if (this.sendSms(notification, msgBody)) {
return okMsg;
- },
- (ex) => {
- console.log(ex);
}
- );
+ } else {
+ var msgBody = JSON.stringify({
+ name: "",
+ time: "",
+ status: "",
+ msg: msg,
+ });
+ if (this.sendSms(notification, msgBody)) {
+ return okMsg;
+ }
+ }
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
+ async sendSms(notification, msgbody) {
+ var params = {
+ PhoneNumbers: notification.phonenumber,
+ TemplateCode: notification.templateCode,
+ SignName: notification.signName,
+ TemplateParam: msgbody,
+ AccessKeyId: notification.accessKeyId,
+ Format: "JSON",
+ SignatureMethod: "HMAC-SHA1",
+ SignatureVersion: "1.0",
+ SignatureNonce: Math.random().toString(),
+ Timestamp: new Date().toISOString(),
+ Action: "SendSms",
+ Version: "2017-05-25",
+ };
+
+ params.Signature = this.sign(params, notification.secretAccessKey);
+ var config = {
+ method: "POST",
+ url: "http://dysmsapi.aliyuncs.com/",
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded",
+ },
+ data: qs.stringify(params),
+ };
+
+ var result = await axios(config);
+ if (result.data.Message == "OK") {
+ return true;
+ }
+ return false;
+ }
+
+ /** Aliyun request sign */
+ sign(param, AccessKeySecret) {
+ var param2 = {},
+ data = [];
+
+ var oa = Object.keys(param).sort();
+
+ for (var i = 0; i < oa.length; i++) {
+ var key = oa[i];
+ param2[key] = param[key];
+ }
+
+ for (var key in param2) {
+ data.push(`${encodeURIComponent(key)}=${encodeURIComponent(param2[key])}`);
+ }
+
+ var StringToSign = `POST&${encodeURIComponent("/")}&${encodeURIComponent(data.join("&"))}`;
+ return Crypto
+ .createHmac("sha1", `${AccessKeySecret}&`)
+ .update(Buffer.from(StringToSign))
+ .digest("base64");
+ }
+
statusToString(status) {
switch (status) {
case DOWN:
diff --git a/src/components/notifications/AliyunSms.vue b/src/components/notifications/AliyunSms.vue
index 07dca8bbb..3f65b3464 100644
--- a/src/components/notifications/AliyunSms.vue
+++ b/src/components/notifications/AliyunSms.vue
@@ -16,6 +16,7 @@
+
Sms template must contain parameters:
${name} ${time} ${status} ${msg}
https://help.aliyun.com/document_detail/101414.html
From 843992c4104160b76439c455e414dbe6cb8a678c Mon Sep 17 00:00:00 2001
From: wuwenjing
Date: Wed, 13 Oct 2021 16:13:46 +0800
Subject: [PATCH 09/26] Add DingDing notification
---
server/notification-providers/dingding.js | 79 +++++++++++++++++++++++
server/notification.js | 2 +
src/components/notifications/DingDing.vue | 16 +++++
src/components/notifications/index.js | 2 +
4 files changed, 99 insertions(+)
create mode 100644 server/notification-providers/dingding.js
create mode 100644 src/components/notifications/DingDing.vue
diff --git a/server/notification-providers/dingding.js b/server/notification-providers/dingding.js
new file mode 100644
index 000000000..5a64f4aaf
--- /dev/null
+++ b/server/notification-providers/dingding.js
@@ -0,0 +1,79 @@
+const NotificationProvider = require("./notification-provider");
+const { DOWN, UP } = require("../../src/util");
+const { default: axios } = require("axios");
+const Crypto = require("crypto");
+
+class DingDing extends NotificationProvider {
+ name = "DingDing";
+
+ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
+ let okMsg = "Sent Successfully.";
+
+ try {
+ if (heartbeatJSON != null) {
+ var params = {
+ msgtype:"markdown",
+ markdown:{
+ title: monitorJSON["name"],
+ text: `## [${this.statusToString(heartbeatJSON["status"])}] \n > ${heartbeatJSON["msg"]} \n > Time(UTC):${heartbeatJSON["time"]}`,
+ }
+ };
+ if (this.sendToDingDing(notification, params)) {
+ return okMsg;
+ }
+ } else {
+ var params = {
+ msgtype:"text",
+ text:{
+ content:msg
+ }
+ };
+ if (this.sendToDingDing(notification, params)) {
+ return okMsg;
+ }
+ }
+ } catch (error) {
+ this.throwGeneralAxiosError(error);
+ }
+ }
+
+ async sendToDingDing(notification, params) {
+ var timestamp=Date.now()
+
+ var config = {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ url: `${notification.webHookUrl}×tamp=${timestamp}&sign=${encodeURIComponent(this.sign(timestamp, notification.secretKey))}`,
+ data: JSON.stringify(params),
+ };
+
+ var result = await axios(config);
+ if (result.data.errmsg == "ok") {
+ return true;
+ }
+ return false;
+ }
+
+ /** DingDing sign */
+ sign(timestamp,secretKey) {
+ return Crypto
+ .createHmac("sha256",Buffer.from(secretKey, 'utf8'))
+ .update(Buffer.from(`${timestamp}\n${secretKey}`, 'utf8'))
+ .digest("base64");
+ }
+
+ statusToString(status) {
+ switch (status) {
+ case DOWN:
+ return "DOWN";
+ case UP:
+ return "UP";
+ default:
+ return status;
+ }
+ }
+}
+
+module.exports = DingDing;
diff --git a/server/notification.js b/server/notification.js
index 21bd2b1e6..658216f91 100644
--- a/server/notification.js
+++ b/server/notification.js
@@ -20,6 +20,7 @@ const Telegram = require("./notification-providers/telegram");
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");
class Notification {
@@ -33,6 +34,7 @@ class Notification {
const list = [
new Apprise(),
new AliyunSms(),
+ new DingDing(),
new Discord(),
new Teams(),
new Gotify(),
diff --git a/src/components/notifications/DingDing.vue b/src/components/notifications/DingDing.vue
new file mode 100644
index 000000000..3ee475c80
--- /dev/null
+++ b/src/components/notifications/DingDing.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/notifications/index.js b/src/components/notifications/index.js
index 74fe0df38..ff0acc6a5 100644
--- a/src/components/notifications/index.js
+++ b/src/components/notifications/index.js
@@ -19,6 +19,7 @@ import Line from "./Line.vue";
import Mattermost from "./Mattermost.vue";
import Matrix from "./Matrix.vue";
import AliyunSMS from "./AliyunSms.vue";
+import DingDing from "./DingDing.vue";
/**
* Manage all notification form.
@@ -47,6 +48,7 @@ const NotificationFormList = {
"line": Line,
"mattermost": Mattermost,
"matrix": Matrix,
+ "DingDing":DingDing
}
export default NotificationFormList
From 2ff7c4de5d65b62ed2a81a7206605c6725de30d5 Mon Sep 17 00:00:00 2001
From: Louis Lam
Date: Wed, 13 Oct 2021 22:16:46 +0800
Subject: [PATCH 10/26] [test] genSecret
---
test/backend.spec.js | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/test/backend.spec.js b/test/backend.spec.js
index 4f00c0b13..ea04439a8 100644
--- a/test/backend.spec.js
+++ b/test/backend.spec.js
@@ -1,10 +1,37 @@
+const { genSecret } = require("../src/util");
+
beforeAll(() => {
});
-describe("", () => {
+describe("Test genSecret", () => {
- it("should ", () => {
+ it("should be correct length", () => {
+ let secret = genSecret(-1);
+ expect(secret).toEqual("");
+ secret = genSecret(0);
+ expect(secret).toEqual("");
+
+ secret = genSecret(1);
+ expect(secret.length).toEqual(1);
+
+ secret = genSecret(2);
+ expect(secret.length).toEqual(2);
+
+ secret = genSecret(64);
+ expect(secret.length).toEqual(64);
+
+ secret = genSecret(9000);
+ expect(secret.length).toEqual(9000);
+
+ secret = genSecret(90000);
+ expect(secret.length).toEqual(90000);
+ });
+
+ it("should contain first and last possible chars", () => {
+ let secret = genSecret(90000);
+ expect(secret).toContain("A");
+ expect(secret).toContain("9");
});
});
From 9b05e86c253b23a95c3c173ba2b2911248ea49c8 Mon Sep 17 00:00:00 2001
From: Louis Lam
Date: Wed, 13 Oct 2021 22:31:36 +0800
Subject: [PATCH 11/26] set newLine to LF for ts compiler
---
tsconfig.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/tsconfig.json b/tsconfig.json
index b7637c3c9..c54546424 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,7 @@
{
"compileOnSave": true,
"compilerOptions": {
+ "newLine": "LF",
"target": "es2018",
"module": "commonjs",
"lib": [
From 89b34b57484d5dfba7913b9bf2c56c1ec5c80763 Mon Sep 17 00:00:00 2001
From: Lukas <35193662+NixNotCastey@users.noreply.github.com>
Date: Wed, 13 Oct 2021 18:05:18 +0200
Subject: [PATCH 12/26] Use double curly brackets and sanity check for
customSubject
---
server/notification-providers/smtp.js | 24 ++++++++++++++----------
src/components/notifications/SMTP.vue | 2 +-
2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/server/notification-providers/smtp.js b/server/notification-providers/smtp.js
index dd1cd10a7..a74b48cc1 100644
--- a/server/notification-providers/smtp.js
+++ b/server/notification-providers/smtp.js
@@ -21,19 +21,23 @@ class SMTP extends NotificationProvider {
pass: notification.smtpPassword,
};
}
- // Lets start with default subject
+ // Lets start with default subject and empty string for custom one
let subject = msg;
+ let customSubject = "";
// Our subject cannot end with whitespace it's often raise spam score
- let customsubject = notification.customsubject.trim()
+ // Once I got "Cannot read property 'trim' of undefined", better be safe than sorry
+ if (notification.customSubject) {
+ customSubject = notification.customSubject.trim()
+ }
// If custom subject is not empty, change subject for notification
- if (customsubject !== "") {
+ if (customSubject !== "") {
// Replace "MACROS" with coresponding variable
- let replaceName = new RegExp("{NAME}", "g");
- let replaceHostname = new RegExp("{HOSTNAME}", "g");
- let replaceStatus = new RegExp("{STATUS}", "g");
+ let replaceName = new RegExp("{{NAME}}", "g");
+ let replaceHostname = new RegExp("{{HOSTNAME}}", "g");
+ let replaceStatus = new RegExp("{{STATUS}}", "g");
// Lets start with dummy values to simplify code
let monitorName = "Test"
@@ -50,11 +54,11 @@ class SMTP extends NotificationProvider {
}
// Break replace to one by line for better readability
- customsubject = customsubject.replace(replaceStatus, serviceStatus);
- customsubject = customsubject.replace(replaceName, monitorName);
- customsubject = customsubject.replace(replaceHostname, monitorHostname);
+ customSubject = customSubject.replace(replaceStatus, serviceStatus);
+ customSubject = customSubject.replace(replaceName, monitorName);
+ customSubject = customSubject.replace(replaceHostname, monitorHostname);
- subject = customsubject
+ subject = customSubject
}
let transporter = nodemailer.createTransport(config);
diff --git a/src/components/notifications/SMTP.vue b/src/components/notifications/SMTP.vue
index 01bdf8607..79efd9f9a 100644
--- a/src/components/notifications/SMTP.vue
+++ b/src/components/notifications/SMTP.vue
@@ -45,7 +45,7 @@
-
+
From e2dbacb383acdd981a5f09d07c3a4e6ee96770d5 Mon Sep 17 00:00:00 2001
From: Louis Lam
Date: Thu, 14 Oct 2021 00:22:49 +0800
Subject: [PATCH 13/26] Fix encoding problem of ping result for non-English
Windows
---
package-lock.json | 93 ++++++++++++++++++++++++++++++++++++++-----
package.json | 4 +-
server/ping-lite.js | 24 +++++++++++
server/util-server.js | 13 ++++++
4 files changed, 124 insertions(+), 10 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 296362633..31eeb4c6e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,6 +19,7 @@
"axios": "~0.21.4",
"bcryptjs": "~2.4.3",
"bootstrap": "~5.1.1",
+ "chardet": "^1.3.0",
"chart.js": "~3.5.1",
"chartjs-adapter-dayjs": "~1.0.0",
"command-exists": "~1.2.9",
@@ -28,6 +29,7 @@
"express-basic-auth": "~1.2.0",
"form-data": "~4.0.0",
"http-graceful-shutdown": "~3.1.4",
+ "iconv-lite": "^0.6.3",
"jsonwebtoken": "~8.5.1",
"nodemailer": "~6.6.5",
"notp": "~2.0.3",
@@ -64,7 +66,7 @@
"@vitejs/plugin-legacy": "~1.6.1",
"@vitejs/plugin-vue": "~1.9.2",
"@vue/compiler-sfc": "~3.2.19",
- "babel-plugin-rewire": "^1.2.0",
+ "babel-plugin-rewire": "~1.2.0",
"core-js": "~3.18.1",
"cross-env": "~7.0.3",
"dns2": "~2.0.1",
@@ -3551,6 +3553,17 @@
"ms": "2.0.0"
}
},
+ "node_modules/body-parser/node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/body-parser/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -3813,6 +3826,11 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/chardet": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-1.3.0.tgz",
+ "integrity": "sha512-cyTQGGptIjIT+CMGT5J/0l9c6Fb+565GCFjjeUTKxUO7w3oR+FcNCMEKTn5xtVKaLFmladN7QF68IiQsv5Fbdw=="
+ },
"node_modules/chart.js": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.5.1.tgz",
@@ -6303,11 +6321,11 @@
}
},
"node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
@@ -9527,6 +9545,17 @@
"node": ">= 0.8"
}
},
+ "node_modules/raw-body/node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -11978,6 +12007,18 @@
"iconv-lite": "0.4.24"
}
},
+ "node_modules/whatwg-encoding/node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/whatwg-mimetype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
@@ -14905,6 +14946,14 @@
"ms": "2.0.0"
}
},
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -15090,6 +15139,11 @@
"integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
"dev": true
},
+ "chardet": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-1.3.0.tgz",
+ "integrity": "sha512-cyTQGGptIjIT+CMGT5J/0l9c6Fb+565GCFjjeUTKxUO7w3oR+FcNCMEKTn5xtVKaLFmladN7QF68IiQsv5Fbdw=="
+ },
"chart.js": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.5.1.tgz",
@@ -16967,11 +17021,11 @@
"dev": true
},
"iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"requires": {
- "safer-buffer": ">= 2.1.2 < 3"
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
}
},
"ieee754": {
@@ -19393,6 +19447,16 @@
"http-errors": "1.7.2",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
+ },
+ "dependencies": {
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ }
}
},
"react-is": {
@@ -21251,6 +21315,17 @@
"dev": true,
"requires": {
"iconv-lite": "0.4.24"
+ },
+ "dependencies": {
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ }
}
},
"whatwg-mimetype": {
diff --git a/package.json b/package.json
index 03112518a..d117e7f2b 100644
--- a/package.json
+++ b/package.json
@@ -60,9 +60,9 @@
"@popperjs/core": "~2.10.2",
"args-parser": "~1.3.0",
"axios": "~0.21.4",
- "babel-plugin-rewire": "~1.2.0",
"bcryptjs": "~2.4.3",
"bootstrap": "~5.1.1",
+ "chardet": "^1.3.0",
"chart.js": "~3.5.1",
"chartjs-adapter-dayjs": "~1.0.0",
"command-exists": "~1.2.9",
@@ -72,6 +72,7 @@
"express-basic-auth": "~1.2.0",
"form-data": "~4.0.0",
"http-graceful-shutdown": "~3.1.4",
+ "iconv-lite": "^0.6.3",
"jsonwebtoken": "~8.5.1",
"nodemailer": "~6.6.5",
"notp": "~2.0.3",
@@ -108,6 +109,7 @@
"@vitejs/plugin-legacy": "~1.6.1",
"@vitejs/plugin-vue": "~1.9.2",
"@vue/compiler-sfc": "~3.2.19",
+ "babel-plugin-rewire": "~1.2.0",
"core-js": "~3.18.1",
"cross-env": "~7.0.3",
"dns2": "~2.0.1",
diff --git a/server/ping-lite.js b/server/ping-lite.js
index 0af0e9706..291bf20d3 100644
--- a/server/ping-lite.js
+++ b/server/ping-lite.js
@@ -4,6 +4,8 @@ const net = require("net");
const spawn = require("child_process").spawn;
const events = require("events");
const fs = require("fs");
+const util = require("./util-server");
+
const WIN = /^win/.test(process.platform);
const LIN = /^linux/.test(process.platform);
const MAC = /^darwin/.test(process.platform);
@@ -101,6 +103,9 @@ Ping.prototype.send = function (callback) {
});
this._ping.stdout.on("data", function (data) { // log stdout
+ if (WIN) {
+ data = convertOutput(data);
+ }
this._stdout = (this._stdout || "") + data;
});
@@ -112,6 +117,9 @@ Ping.prototype.send = function (callback) {
});
this._ping.stderr.on("data", function (data) { // log stderr
+ if (WIN) {
+ data = convertOutput(data);
+ }
this._stderr = (this._stderr || "") + data;
});
@@ -157,3 +165,19 @@ Ping.prototype.start = function (callback) {
Ping.prototype.stop = function () {
clearInterval(this._i);
};
+
+/**
+ * Try to convert to UTF-8 for Windows, as the ping's output on Windows is not UTF-8 and could be in other languages
+ * Thank @pemassi
+ * https://github.com/louislam/uptime-kuma/issues/570#issuecomment-941984094
+ * @param data
+ * @returns {string}
+ */
+function convertOutput(data) {
+ if (WIN) {
+ if (data) {
+ return util.convertToUTF8(data);
+ }
+ }
+ return data;
+}
diff --git a/server/util-server.js b/server/util-server.js
index 5620d674b..aecb74e8e 100644
--- a/server/util-server.js
+++ b/server/util-server.js
@@ -6,6 +6,8 @@ const passwordHash = require("./password-hash");
const dayjs = require("dayjs");
const { Resolver } = require("dns");
const child_process = require("child_process");
+const iconv = require("iconv-lite");
+const chardet = require("chardet");
/**
* Init or reset JWT secret
@@ -312,3 +314,14 @@ exports.startUnitTest = async () => {
process.exit(code);
});
};
+
+/**
+ * @param body : Buffer
+ * @returns {string}
+ */
+exports.convertToUTF8 = (body) => {
+ const guessEncoding = chardet.detect(body);
+ debug("Guess Encoding: " + guessEncoding);
+ const str = iconv.decode(body, guessEncoding);
+ return str.toString();
+};
From 655ccc86b9dce6c7f334456175de5de6a2d98b99 Mon Sep 17 00:00:00 2001
From: Aaron Erkenswick
Date: Wed, 13 Oct 2021 11:47:23 -0700
Subject: [PATCH 14/26] Add monitor name context to Slack fallback text.
The text block of a slack notification payload is used for mobile
devices and plain text previews. This change allows slack users to see
the name of the failing service without having to open up Slack to read
the entire message.
---
server/notification-providers/slack.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/server/notification-providers/slack.js b/server/notification-providers/slack.js
index 5132ba977..b4dad6fe3 100644
--- a/server/notification-providers/slack.js
+++ b/server/notification-providers/slack.js
@@ -39,8 +39,9 @@ class Slack extends NotificationProvider {
}
const time = heartbeatJSON["time"];
+ const textMsg = "Uptime Kuma Alert";
let data = {
- "text": "Uptime Kuma Alert",
+ "text": monitorJSON ? textMsg + `: ${monitorJSON.name}` : textMsg,
"channel": notification.slackchannel,
"username": notification.slackusername,
"icon_emoji": notification.slackiconemo,
From cae194f58f9410beacf8ea255113f9c758ef3965 Mon Sep 17 00:00:00 2001
From: xJoker
Date: Thu, 14 Oct 2021 07:34:24 +0800
Subject: [PATCH 15/26] Update server/notification-providers/dingding.js
Co-authored-by: Adam Stachowicz
---
server/notification-providers/dingding.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/server/notification-providers/dingding.js b/server/notification-providers/dingding.js
index 5a64f4aaf..5fd21c415 100644
--- a/server/notification-providers/dingding.js
+++ b/server/notification-providers/dingding.js
@@ -12,8 +12,8 @@ class DingDing extends NotificationProvider {
try {
if (heartbeatJSON != null) {
var params = {
- msgtype:"markdown",
- markdown:{
+ msgtype: "markdown",
+ markdown: {
title: monitorJSON["name"],
text: `## [${this.statusToString(heartbeatJSON["status"])}] \n > ${heartbeatJSON["msg"]} \n > Time(UTC):${heartbeatJSON["time"]}`,
}
From 2d471a5e8461275c3c2c15c8cf0f8fc306e70c76 Mon Sep 17 00:00:00 2001
From: xJoker
Date: Thu, 14 Oct 2021 07:34:33 +0800
Subject: [PATCH 16/26] Update server/notification-providers/dingding.js
Co-authored-by: Adam Stachowicz
---
server/notification-providers/dingding.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/server/notification-providers/dingding.js b/server/notification-providers/dingding.js
index 5fd21c415..ef348e2f7 100644
--- a/server/notification-providers/dingding.js
+++ b/server/notification-providers/dingding.js
@@ -23,8 +23,8 @@ class DingDing extends NotificationProvider {
}
} else {
var params = {
- msgtype:"text",
- text:{
+ msgtype: "text",
+ text: {
content:msg
}
};
From 6e04ec436e8316665cadabd7a779dbebbeeb447d Mon Sep 17 00:00:00 2001
From: xJoker
Date: Thu, 14 Oct 2021 07:34:45 +0800
Subject: [PATCH 17/26] Update server/notification-providers/dingding.js
Co-authored-by: Adam Stachowicz
---
server/notification-providers/dingding.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/notification-providers/dingding.js b/server/notification-providers/dingding.js
index ef348e2f7..1dd52a526 100644
--- a/server/notification-providers/dingding.js
+++ b/server/notification-providers/dingding.js
@@ -59,7 +59,7 @@ class DingDing extends NotificationProvider {
/** DingDing sign */
sign(timestamp,secretKey) {
return Crypto
- .createHmac("sha256",Buffer.from(secretKey, 'utf8'))
+ .createHmac("sha256", Buffer.from(secretKey, 'utf8'))
.update(Buffer.from(`${timestamp}\n${secretKey}`, 'utf8'))
.digest("base64");
}
From 4e4ab0577ec5b763c093f1c5fdbb7fe21d01d244 Mon Sep 17 00:00:00 2001
From: xJoker
Date: Thu, 14 Oct 2021 09:33:31 +0800
Subject: [PATCH 18/26] Update src/components/notifications/index.js
Co-authored-by: Adam Stachowicz
---
src/components/notifications/index.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/notifications/index.js b/src/components/notifications/index.js
index ff0acc6a5..9018602cf 100644
--- a/src/components/notifications/index.js
+++ b/src/components/notifications/index.js
@@ -42,7 +42,7 @@ const NotificationFormList = {
"promosms": PromoSMS,
"lunasea": LunaSea,
"Feishu": Feishu,
- "AliyunSMS":AliyunSMS,
+ "AliyunSMS": AliyunSMS,
"apprise": Apprise,
"pushbullet": Pushbullet,
"line": Line,
From 8ab4788f80230d06e0a42764b27e50d806cc0bdb Mon Sep 17 00:00:00 2001
From: xJoker
Date: Thu, 14 Oct 2021 09:33:36 +0800
Subject: [PATCH 19/26] Update src/components/notifications/index.js
Co-authored-by: Adam Stachowicz
---
src/components/notifications/index.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/notifications/index.js b/src/components/notifications/index.js
index 9018602cf..96ee2824b 100644
--- a/src/components/notifications/index.js
+++ b/src/components/notifications/index.js
@@ -48,7 +48,7 @@ const NotificationFormList = {
"line": Line,
"mattermost": Mattermost,
"matrix": Matrix,
- "DingDing":DingDing
+ "DingDing": DingDing
}
export default NotificationFormList
From f75c9e4f0ca4f7417ea0c7f2184be4dd1332be05 Mon Sep 17 00:00:00 2001
From: Louis Lam
Date: Thu, 14 Oct 2021 14:09:16 +0800
Subject: [PATCH 20/26] add UPTIME_KUMA_HOST, UPTIME_KUMA_PORT and special
handling for FreeBSD
---
server/ping-lite.js | 5 +----
server/server.js | 20 +++++++++++++++-----
server/util-server.js | 6 ++++++
3 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/server/ping-lite.js b/server/ping-lite.js
index 0af0e9706..37709aaf4 100644
--- a/server/ping-lite.js
+++ b/server/ping-lite.js
@@ -4,10 +4,7 @@ const net = require("net");
const spawn = require("child_process").spawn;
const events = require("events");
const fs = require("fs");
-const WIN = /^win/.test(process.platform);
-const LIN = /^linux/.test(process.platform);
-const MAC = /^darwin/.test(process.platform);
-const FBSD = /^freebsd/.test(process.platform);
+const { MAC, FBSD, LIN, WIN } = require("./util-server");
module.exports = Ping;
diff --git a/server/server.js b/server/server.js
index 7dbd6155f..376e7bb3f 100644
--- a/server/server.js
+++ b/server/server.js
@@ -43,7 +43,7 @@ console.log("Importing this project modules");
debug("Importing Monitor");
const Monitor = require("./model/monitor");
debug("Importing Settings");
-const { getSettings, setSettings, setting, initJWTSecret, checkLogin, startUnitTest } = require("./util-server");
+const { getSettings, setSettings, setting, initJWTSecret, checkLogin, startUnitTest, FBSD } = require("./util-server");
debug("Importing Notification");
const { Notification } = require("./notification");
@@ -61,12 +61,22 @@ console.info("Version: " + checkVersion.version);
// If host is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available and the unspecified IPv4 address (0.0.0.0) otherwise.
// Dual-stack support for (::)
-const hostname = args.host || process.env.HOST;
-const port = parseInt(args.port || process.env.PORT || 3001);
+let hostname = process.env.UPTIME_KUMA_HOST || args.host;
+
+// Also read HOST if not FreeBSD, as HOST is a system environment variable in FreeBSD
+if (!hostname && !FBSD) {
+ hostname = process.env.HOST;
+}
+
+if (hostname) {
+ console.log("Custom hostname: " + hostname);
+}
+
+const port = parseInt(process.env.UPTIME_KUMA_PORT || process.env.PORT || args.port || 3001);
// SSL
-const sslKey = process.env.SSL_KEY || args["ssl-key"] || undefined;
-const sslCert = process.env.SSL_CERT || args["ssl-cert"] || undefined;
+const sslKey = process.env.UPTIME_KUMA_SSL_KEY || process.env.SSL_KEY || args["ssl-key"] || undefined;
+const sslCert = process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || args["ssl-cert"] || undefined;
/**
* Run unit test after the server is ready
diff --git a/server/util-server.js b/server/util-server.js
index 5620d674b..f6faa7a2f 100644
--- a/server/util-server.js
+++ b/server/util-server.js
@@ -7,6 +7,12 @@ const dayjs = require("dayjs");
const { Resolver } = require("dns");
const child_process = require("child_process");
+// From ping-lite
+exports.WIN = /^win/.test(process.platform);
+exports.LIN = /^linux/.test(process.platform);
+exports.MAC = /^darwin/.test(process.platform);
+exports.FBSD = /^freebsd/.test(process.platform);
+
/**
* Init or reset JWT secret
* @returns {Promise}
From 5ff9a64e5e162451ed1dd65c44b4f26532177ab9 Mon Sep 17 00:00:00 2001
From: Louis Lam
Date: Thu, 14 Oct 2021 14:42:34 +0800
Subject: [PATCH 21/26] [Push Type] Fix missing duration calculation (#685)
---
server/routers/api-router.js | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/server/routers/api-router.js b/server/routers/api-router.js
index 0da1fd705..927a54643 100644
--- a/server/routers/api-router.js
+++ b/server/routers/api-router.js
@@ -18,6 +18,7 @@ router.get("/api/entry-page", async (_, response) => {
router.get("/api/push/:pushToken", async (request, response) => {
try {
+
let pushToken = request.params.pushToken;
let msg = request.query.msg || "OK";
let ping = request.query.ping;
@@ -30,12 +31,20 @@ router.get("/api/push/:pushToken", async (request, response) => {
throw new Error("Monitor not found or not active.");
}
+ const previousHeartbeatTime = await R.getCell(`
+ SELECT time FROM heartbeat
+ WHERE id = (select MAX(id) from heartbeat where monitor_id = ?)
+ `, [
+ monitor.id
+ ]);
+
let bean = R.dispense("heartbeat");
bean.monitor_id = monitor.id;
bean.time = R.isoDateTime(dayjs.utc());
bean.status = UP;
bean.msg = msg;
bean.ping = ping;
+ bean.duration = dayjs(bean.time).diff(dayjs(previousHeartbeatTime), "second");
await R.store(bean);
From 83388819273e49e8773646a90cb6de3f0bfebd6d Mon Sep 17 00:00:00 2001
From: Louis Lam
Date: Thu, 14 Oct 2021 16:07:25 +0800
Subject: [PATCH 22/26] [SMTP] change {{HOSTNAME}} to {{HOSTNAME_OR_URL}},
support for http montior type, some UI improvements
---
server/notification-providers/smtp.js | 73 +++++++++++++++------------
src/components/notifications/SMTP.vue | 17 +++++--
src/languages/en.js | 2 +-
src/pages/EditMonitor.vue | 1 +
4 files changed, 56 insertions(+), 37 deletions(-)
diff --git a/server/notification-providers/smtp.js b/server/notification-providers/smtp.js
index a74b48cc1..60068eb77 100644
--- a/server/notification-providers/smtp.js
+++ b/server/notification-providers/smtp.js
@@ -23,42 +23,53 @@ class SMTP extends NotificationProvider {
}
// Lets start with default subject and empty string for custom one
let subject = msg;
- let customSubject = "";
- // Our subject cannot end with whitespace it's often raise spam score
- // Once I got "Cannot read property 'trim' of undefined", better be safe than sorry
- if (notification.customSubject) {
- customSubject = notification.customSubject.trim()
- }
+ // Change the subject if:
+ // - The msg ends with "Testing" or
+ // - Actual Up/Down Notification
+ if ((monitorJSON && heartbeatJSON) || msg.endsWith("Testing")) {
+ let customSubject = "";
- // If custom subject is not empty, change subject for notification
- if (customSubject !== "") {
-
- // Replace "MACROS" with coresponding variable
- let replaceName = new RegExp("{{NAME}}", "g");
- let replaceHostname = new RegExp("{{HOSTNAME}}", "g");
- let replaceStatus = new RegExp("{{STATUS}}", "g");
-
- // Lets start with dummy values to simplify code
- let monitorName = "Test"
- let monitorHostname = "example.com"
- let serviceStatus = "⚠️ Test";
-
- if (monitorJSON !== null) {
- monitorName = monitorJSON["name"];
- monitorHostname = monitorJSON["hostname"];
+ // Our subject cannot end with whitespace it's often raise spam score
+ // Once I got "Cannot read property 'trim' of undefined", better be safe than sorry
+ if (notification.customSubject) {
+ customSubject = notification.customSubject.trim();
}
- if (heartbeatJSON !== null) {
- serviceStatus = heartbeatJSON["status"] == DOWN ? "🔴 Down" : "✅ Up";
- }
-
- // Break replace to one by line for better readability
- customSubject = customSubject.replace(replaceStatus, serviceStatus);
- customSubject = customSubject.replace(replaceName, monitorName);
- customSubject = customSubject.replace(replaceHostname, monitorHostname);
+ // If custom subject is not empty, change subject for notification
+ if (customSubject !== "") {
- subject = customSubject
+ // Replace "MACROS" with corresponding variable
+ let replaceName = new RegExp("{{NAME}}", "g");
+ let replaceHostnameOrURL = new RegExp("{{HOSTNAME_OR_URL}}", "g");
+ let replaceStatus = new RegExp("{{STATUS}}", "g");
+
+ // Lets start with dummy values to simplify code
+ let monitorName = "Test";
+ let monitorHostnameOrURL = "testing.hostname";
+ let serviceStatus = "⚠️ Test";
+
+ if (monitorJSON !== null) {
+ monitorName = monitorJSON["name"];
+
+ if (monitorJSON["type"] === "http" || monitorJSON["type"] === "keyword") {
+ monitorHostnameOrURL = monitorJSON["url"];
+ } else {
+ monitorHostnameOrURL = monitorJSON["hostname"];
+ }
+ }
+
+ if (heartbeatJSON !== null) {
+ serviceStatus = (heartbeatJSON["status"] === DOWN) ? "🔴 Down" : "✅ Up";
+ }
+
+ // Break replace to one by line for better readability
+ customSubject = customSubject.replace(replaceStatus, serviceStatus);
+ customSubject = customSubject.replace(replaceName, monitorName);
+ customSubject = customSubject.replace(replaceHostnameOrURL, monitorHostnameOrURL);
+
+ subject = customSubject;
+ }
}
let transporter = nodemailer.createTransport(config);
diff --git a/src/components/notifications/SMTP.vue b/src/components/notifications/SMTP.vue
index 79efd9f9a..483917e3f 100644
--- a/src/components/notifications/SMTP.vue
+++ b/src/components/notifications/SMTP.vue
@@ -43,11 +43,6 @@
-
-
-
-
-
@@ -62,6 +57,18 @@
+
+
+
+
+
+ (leave blank for default one)
+ {{NAME}}: Service Name
+ {{HOSTNAME_OR_URL}}: Hostname or URL
+ {{URL}}: URL
+ {{STATUS}}: Status
+
+