uptime-kuma/server/notification-providers/aliyun-sms.js

141 lines
4.4 KiB
JavaScript
Raw Normal View History

2021-10-13 03:55:01 +00:00
const NotificationProvider = require("./notification-provider");
const { DOWN, UP } = require("../../src/util");
2021-10-13 06:41:59 +00:00
const { default: axios } = require("axios");
const Crypto = require("crypto");
const qs = require("qs");
2021-10-13 03:55:01 +00:00
class AliyunSMS extends NotificationProvider {
name = "AliyunSMS";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully.";
try {
if (heartbeatJSON != null) {
2021-10-14 08:24:03 +00:00
let msgBody = JSON.stringify({
2021-10-13 03:55:01 +00:00
name: monitorJSON["name"],
time: heartbeatJSON["time"],
status: this.statusToString(heartbeatJSON["status"]),
msg: heartbeatJSON["msg"],
});
if (await this.sendSms(notification, msgBody)) {
2021-10-13 06:41:59 +00:00
return okMsg;
}
} else {
2021-10-14 08:24:03 +00:00
let msgBody = JSON.stringify({
2021-10-13 06:41:59 +00:00
name: "",
time: "",
status: "",
msg: msg,
});
if (await this.sendSms(notification, msgBody)) {
2021-10-13 03:55:01 +00:00
return okMsg;
}
2021-10-13 06:41:59 +00:00
}
2021-10-13 03:55:01 +00:00
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
/**
* Send the SMS notification
* @param {BeanModel} notification Notification details
* @param {string} msgbody Message template
* @returns {boolean} True if successful else false
*/
2021-10-13 06:41:59 +00:00
async sendSms(notification, msgbody) {
2021-10-14 08:24:03 +00:00
let params = {
2021-10-13 06:41:59 +00:00
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);
2021-10-14 08:24:03 +00:00
let config = {
2021-10-13 06:41:59 +00:00
method: "POST",
url: "http://dysmsapi.aliyuncs.com/",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
data: qs.stringify(params),
};
2021-10-14 08:24:03 +00:00
let result = await axios(config);
2022-04-17 07:43:03 +00:00
if (result.data.Message === "OK") {
2021-10-13 06:41:59 +00:00
return true;
}
throw new Error(result.data.Message);
2021-10-13 06:41:59 +00:00
}
/**
* Aliyun request sign
* @param {Object} param Parameters object to sign
* @param {string} AccessKeySecret Secret key to sign parameters with
* @returns {string}
*/
2021-10-13 06:41:59 +00:00
sign(param, AccessKeySecret) {
2021-10-14 08:24:03 +00:00
let param2 = {};
let data = [];
2021-10-13 06:41:59 +00:00
2021-10-14 08:24:03 +00:00
let oa = Object.keys(param).sort();
2021-10-13 06:41:59 +00:00
2021-10-14 08:24:03 +00:00
for (let i = 0; i < oa.length; i++) {
let key = oa[i];
2021-10-13 06:41:59 +00:00
param2[key] = param[key];
}
2022-04-30 02:45:38 +00:00
// 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
2022-05-01 04:10:47 +00:00
// This encoding methods as known as RFC 3986 (https://tools.ietf.org/html/rfc3986)
2022-04-29 22:28:16 +00:00
let moreEscapesTable = function (m) {
return {
2022-04-29 22:28:16 +00:00
"!": "%21",
"*": "%2A",
"'": "%27",
"(": "%28",
")": "%29"
2022-04-29 22:28:16 +00:00
}[m];
};
2021-10-13 06:41:59 +00:00
2021-10-14 08:24:03 +00:00
for (let key in param2) {
let value = encodeURIComponent(param2[key]).replace(/[!*'()]/g, moreEscapesTable);
data.push(`${encodeURIComponent(key)}=${value}`);
2021-10-13 06:41:59 +00:00
}
2021-10-14 08:24:03 +00:00
let StringToSign = `POST&${encodeURIComponent("/")}&${encodeURIComponent(data.join("&"))}`;
2021-10-13 06:41:59 +00:00
return Crypto
.createHmac("sha1", `${AccessKeySecret}&`)
.update(Buffer.from(StringToSign))
.digest("base64");
}
/**
* Convert status constant to string
* @param {const} status The status constant
* @returns {string}
*/
2021-10-13 03:55:01 +00:00
statusToString(status) {
switch (status) {
case DOWN:
return "DOWN";
case UP:
return "UP";
default:
return status;
}
}
}
module.exports = AliyunSMS;