mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-30 18:24:03 +00:00
convert notifications into modules
This commit is contained in:
parent
850563442a
commit
da74391c3e
20 changed files with 918 additions and 654 deletions
|
@ -17,7 +17,8 @@ module.exports = {
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
"camelcase": ["warn", {
|
"camelcase": ["warn", {
|
||||||
"properties": "never"
|
"properties": "never",
|
||||||
|
"ignoreImports": true
|
||||||
}],
|
}],
|
||||||
// override/add rules settings here, such as:
|
// override/add rules settings here, such as:
|
||||||
// 'vue/no-unused-vars': 'error'
|
// 'vue/no-unused-vars': 'error'
|
||||||
|
|
26
server/notification-providers/apprise.js
Normal file
26
server/notification-providers/apprise.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const child_process = 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 output = (s.stdout) ? s.stdout.toString() : "ERROR: maybe apprise not found";
|
||||||
|
|
||||||
|
if (output) {
|
||||||
|
|
||||||
|
if (! output.includes("ERROR")) {
|
||||||
|
return "Sent Successfully";
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(output)
|
||||||
|
} else {
|
||||||
|
return "No output from apprise";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Apprise;
|
105
server/notification-providers/discord.js
Normal file
105
server/notification-providers/discord.js
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
const { DOWN, UP } = require("../../src/util");
|
||||||
|
|
||||||
|
class Discord extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "discord";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const discordDisplayName = notification.discordUsername || "Uptime Kuma";
|
||||||
|
|
||||||
|
// If heartbeatJSON is null, assume we're testing.
|
||||||
|
if (heartbeatJSON == null) {
|
||||||
|
let discordtestdata = {
|
||||||
|
username: discordDisplayName,
|
||||||
|
content: msg,
|
||||||
|
}
|
||||||
|
await axios.post(notification.discordWebhookUrl, discordtestdata)
|
||||||
|
return okMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
let url;
|
||||||
|
|
||||||
|
if (monitorJSON["type"] === "port") {
|
||||||
|
url = monitorJSON["hostname"];
|
||||||
|
if (monitorJSON["port"]) {
|
||||||
|
url += ":" + monitorJSON["port"];
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
url = monitorJSON["url"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If heartbeatJSON is not null, we go into the normal alerting loop.
|
||||||
|
if (heartbeatJSON["status"] == DOWN) {
|
||||||
|
let discorddowndata = {
|
||||||
|
username: discordDisplayName,
|
||||||
|
embeds: [{
|
||||||
|
title: "❌ Your service " + monitorJSON["name"] + " went down. ❌",
|
||||||
|
color: 16711680,
|
||||||
|
timestamp: heartbeatJSON["time"],
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "Service Name",
|
||||||
|
value: monitorJSON["name"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service URL",
|
||||||
|
value: url,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Time (UTC)",
|
||||||
|
value: heartbeatJSON["time"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Error",
|
||||||
|
value: heartbeatJSON["msg"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
await axios.post(notification.discordWebhookUrl, discorddowndata)
|
||||||
|
return okMsg;
|
||||||
|
|
||||||
|
} else if (heartbeatJSON["status"] == UP) {
|
||||||
|
let discordupdata = {
|
||||||
|
username: discordDisplayName,
|
||||||
|
embeds: [{
|
||||||
|
title: "✅ Your service " + monitorJSON["name"] + " is up! ✅",
|
||||||
|
color: 65280,
|
||||||
|
timestamp: heartbeatJSON["time"],
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "Service Name",
|
||||||
|
value: monitorJSON["name"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service URL",
|
||||||
|
value: url.startsWith("http") ? "[Visit Service](" + url + ")" : url,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Time (UTC)",
|
||||||
|
value: heartbeatJSON["time"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Ping",
|
||||||
|
value: heartbeatJSON["ping"] + "ms",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
await axios.post(notification.discordWebhookUrl, discordupdata)
|
||||||
|
return okMsg;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Discord;
|
28
server/notification-providers/gotify.js
Normal file
28
server/notification-providers/gotify.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
class Gotify extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "gotify";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
try {
|
||||||
|
if (notification.gotifyserverurl && notification.gotifyserverurl.endsWith("/")) {
|
||||||
|
notification.gotifyserverurl = notification.gotifyserverurl.slice(0, -1);
|
||||||
|
}
|
||||||
|
await axios.post(`${notification.gotifyserverurl}/message?token=${notification.gotifyapplicationToken}`, {
|
||||||
|
"message": msg,
|
||||||
|
"priority": notification.gotifyPriority || 8,
|
||||||
|
"title": "Uptime-Kuma",
|
||||||
|
})
|
||||||
|
|
||||||
|
return okMsg;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Gotify;
|
60
server/notification-providers/line.js
Normal file
60
server/notification-providers/line.js
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
const { DOWN, UP } = require("../../src/util");
|
||||||
|
|
||||||
|
class Line extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "line";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
try {
|
||||||
|
let lineAPIUrl = "https://api.line.me/v2/bot/message/push";
|
||||||
|
let config = {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": "Bearer " + notification.lineChannelAccessToken
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (heartbeatJSON == null) {
|
||||||
|
let testMessage = {
|
||||||
|
"to": notification.lineUserID,
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": "Test Successful!"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
await axios.post(lineAPIUrl, testMessage, config)
|
||||||
|
} else if (heartbeatJSON["status"] == DOWN) {
|
||||||
|
let downMessage = {
|
||||||
|
"to": notification.lineUserID,
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": "UptimeKuma Alert: [🔴 Down]\n" + "Name: " + monitorJSON["name"] + " \n" + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
await axios.post(lineAPIUrl, downMessage, config)
|
||||||
|
} else if (heartbeatJSON["status"] == UP) {
|
||||||
|
let upMessage = {
|
||||||
|
"to": notification.lineUserID,
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": "UptimeKuma Alert: [✅ Up]\n" + "Name: " + monitorJSON["name"] + " \n" + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
await axios.post(lineAPIUrl, upMessage, config)
|
||||||
|
}
|
||||||
|
return okMsg;
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Line;
|
48
server/notification-providers/lunasea.js
Normal file
48
server/notification-providers/lunasea.js
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
const { DOWN, UP } = require("../../src/util");
|
||||||
|
|
||||||
|
class LunaSea extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "lunasea";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
let lunaseadevice = "https://notify.lunasea.app/v1/custom/device/" + notification.lunaseaDevice
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (heartbeatJSON == null) {
|
||||||
|
let testdata = {
|
||||||
|
"title": "Uptime Kuma Alert",
|
||||||
|
"body": "Testing Successful.",
|
||||||
|
}
|
||||||
|
await axios.post(lunaseadevice, testdata)
|
||||||
|
return okMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heartbeatJSON["status"] == DOWN) {
|
||||||
|
let downdata = {
|
||||||
|
"title": "UptimeKuma Alert: " + monitorJSON["name"],
|
||||||
|
"body": "[🔴 Down] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
|
||||||
|
}
|
||||||
|
await axios.post(lunaseadevice, downdata)
|
||||||
|
return okMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heartbeatJSON["status"] == UP) {
|
||||||
|
let updata = {
|
||||||
|
"title": "UptimeKuma Alert: " + monitorJSON["name"],
|
||||||
|
"body": "[✅ Up] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
|
||||||
|
}
|
||||||
|
await axios.post(lunaseadevice, updata)
|
||||||
|
return okMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = LunaSea;
|
123
server/notification-providers/mattermost.js
Normal file
123
server/notification-providers/mattermost.js
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
const { DOWN, UP } = require("../../src/util");
|
||||||
|
|
||||||
|
class Mattermost extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "mattermost";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
try {
|
||||||
|
const mattermostUserName = notification.mattermostusername || "Uptime Kuma";
|
||||||
|
// If heartbeatJSON is null, assume we're testing.
|
||||||
|
if (heartbeatJSON == null) {
|
||||||
|
let mattermostTestData = {
|
||||||
|
username: mattermostUserName,
|
||||||
|
text: msg,
|
||||||
|
}
|
||||||
|
await axios.post(notification.mattermostWebhookUrl, mattermostTestData)
|
||||||
|
return okMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mattermostChannel = notification.mattermostchannel;
|
||||||
|
const mattermostIconEmoji = notification.mattermosticonemo;
|
||||||
|
const mattermostIconUrl = notification.mattermosticonurl;
|
||||||
|
|
||||||
|
if (heartbeatJSON["status"] == DOWN) {
|
||||||
|
let mattermostdowndata = {
|
||||||
|
username: mattermostUserName,
|
||||||
|
text: "Uptime Kuma Alert",
|
||||||
|
channel: mattermostChannel,
|
||||||
|
icon_emoji: mattermostIconEmoji,
|
||||||
|
icon_url: mattermostIconUrl,
|
||||||
|
attachments: [
|
||||||
|
{
|
||||||
|
fallback:
|
||||||
|
"Your " +
|
||||||
|
monitorJSON["name"] +
|
||||||
|
" service went down.",
|
||||||
|
color: "#FF0000",
|
||||||
|
title:
|
||||||
|
"❌ " +
|
||||||
|
monitorJSON["name"] +
|
||||||
|
" service went down. ❌",
|
||||||
|
title_link: monitorJSON["url"],
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
short: true,
|
||||||
|
title: "Service Name",
|
||||||
|
value: monitorJSON["name"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
short: true,
|
||||||
|
title: "Time (UTC)",
|
||||||
|
value: heartbeatJSON["time"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
short: false,
|
||||||
|
title: "Error",
|
||||||
|
value: heartbeatJSON["msg"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
await axios.post(
|
||||||
|
notification.mattermostWebhookUrl,
|
||||||
|
mattermostdowndata
|
||||||
|
);
|
||||||
|
return okMsg;
|
||||||
|
} else if (heartbeatJSON["status"] == UP) {
|
||||||
|
let mattermostupdata = {
|
||||||
|
username: mattermostUserName,
|
||||||
|
text: "Uptime Kuma Alert",
|
||||||
|
channel: mattermostChannel,
|
||||||
|
icon_emoji: mattermostIconEmoji,
|
||||||
|
icon_url: mattermostIconUrl,
|
||||||
|
attachments: [
|
||||||
|
{
|
||||||
|
fallback:
|
||||||
|
"Your " +
|
||||||
|
monitorJSON["name"] +
|
||||||
|
" service went up!",
|
||||||
|
color: "#32CD32",
|
||||||
|
title:
|
||||||
|
"✅ " +
|
||||||
|
monitorJSON["name"] +
|
||||||
|
" service went up! ✅",
|
||||||
|
title_link: monitorJSON["url"],
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
short: true,
|
||||||
|
title: "Service Name",
|
||||||
|
value: monitorJSON["name"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
short: true,
|
||||||
|
title: "Time (UTC)",
|
||||||
|
value: heartbeatJSON["time"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
short: false,
|
||||||
|
title: "Ping",
|
||||||
|
value: heartbeatJSON["ping"] + "ms",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
await axios.post(
|
||||||
|
notification.mattermostWebhookUrl,
|
||||||
|
mattermostupdata
|
||||||
|
);
|
||||||
|
return okMsg;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Mattermost;
|
36
server/notification-providers/notification-provider.js
Normal file
36
server/notification-providers/notification-provider.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
class NotificationProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification Provider Name
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
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)
|
||||||
|
* @returns {Promise<string>} Return Successful Message
|
||||||
|
* Throw Error with fail msg
|
||||||
|
*/
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
throw new Error("Have to override Notification.send(...)");
|
||||||
|
}
|
||||||
|
|
||||||
|
throwGeneralAxiosError(error) {
|
||||||
|
let msg = "Error: " + error + " ";
|
||||||
|
|
||||||
|
if (error.response && error.response.data) {
|
||||||
|
if (typeof error.response.data === "string") {
|
||||||
|
msg += error.response.data;
|
||||||
|
} else {
|
||||||
|
msg += JSON.stringify(error.response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = NotificationProvider;
|
40
server/notification-providers/octopush.js
Normal file
40
server/notification-providers/octopush.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
class Octopush extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "octopush";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
|
||||||
|
try {
|
||||||
|
let config = {
|
||||||
|
headers: {
|
||||||
|
"api-key": notification.octopushAPIKey,
|
||||||
|
"api-login": notification.octopushLogin,
|
||||||
|
"cache-control": "no-cache"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let data = {
|
||||||
|
"recipients": [
|
||||||
|
{
|
||||||
|
"phone_number": notification.octopushPhoneNumber
|
||||||
|
}
|
||||||
|
],
|
||||||
|
//octopush not supporting non ascii char
|
||||||
|
"text": msg.replace(/[^\x00-\x7F]/g, ""),
|
||||||
|
"type": notification.octopushSMSType,
|
||||||
|
"purpose": "alert",
|
||||||
|
"sender": notification.octopushSenderName
|
||||||
|
};
|
||||||
|
|
||||||
|
await axios.post("https://api.octopush.com/v1/public/sms-campaign/send", data, config)
|
||||||
|
return okMsg;
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Octopush;
|
50
server/notification-providers/pushbullet.js
Normal file
50
server/notification-providers/pushbullet.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
const { DOWN, UP } = require("../../src/util");
|
||||||
|
|
||||||
|
class Pushbullet extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "pushbullet";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
|
||||||
|
try {
|
||||||
|
let pushbulletUrl = "https://api.pushbullet.com/v2/pushes";
|
||||||
|
let config = {
|
||||||
|
headers: {
|
||||||
|
"Access-Token": notification.pushbulletAccessToken,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (heartbeatJSON == null) {
|
||||||
|
let testdata = {
|
||||||
|
"type": "note",
|
||||||
|
"title": "Uptime Kuma Alert",
|
||||||
|
"body": "Testing Successful.",
|
||||||
|
}
|
||||||
|
await axios.post(pushbulletUrl, testdata, config)
|
||||||
|
} 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) {
|
||||||
|
let updata = {
|
||||||
|
"type": "note",
|
||||||
|
"title": "UptimeKuma Alert: " + monitorJSON["name"],
|
||||||
|
"body": "[✅ Up] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
|
||||||
|
}
|
||||||
|
await axios.post(pushbulletUrl, updata, config)
|
||||||
|
}
|
||||||
|
return okMsg;
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Pushbullet;
|
49
server/notification-providers/pushover.js
Normal file
49
server/notification-providers/pushover.js
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
class Pushover extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "pushover";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
let pushoverlink = "https://api.pushover.net/1/messages.json"
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (heartbeatJSON == null) {
|
||||||
|
let data = {
|
||||||
|
"message": "<b>Uptime Kuma Pushover testing successful.</b>",
|
||||||
|
"user": notification.pushoveruserkey,
|
||||||
|
"token": notification.pushoverapptoken,
|
||||||
|
"sound": notification.pushoversounds,
|
||||||
|
"priority": notification.pushoverpriority,
|
||||||
|
"title": notification.pushovertitle,
|
||||||
|
"retry": "30",
|
||||||
|
"expire": "3600",
|
||||||
|
"html": 1,
|
||||||
|
}
|
||||||
|
await axios.post(pushoverlink, data)
|
||||||
|
return okMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = {
|
||||||
|
"message": "<b>Uptime Kuma Alert</b>\n\n<b>Message</b>:" + msg + "\n<b>Time (UTC)</b>:" + heartbeatJSON["time"],
|
||||||
|
"user": notification.pushoveruserkey,
|
||||||
|
"token": notification.pushoverapptoken,
|
||||||
|
"sound": notification.pushoversounds,
|
||||||
|
"priority": notification.pushoverpriority,
|
||||||
|
"title": notification.pushovertitle,
|
||||||
|
"retry": "30",
|
||||||
|
"expire": "3600",
|
||||||
|
"html": 1,
|
||||||
|
}
|
||||||
|
await axios.post(pushoverlink, data)
|
||||||
|
return okMsg;
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Pushover;
|
30
server/notification-providers/pushy.js
Normal file
30
server/notification-providers/pushy.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
class Pushy extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "pushy";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post(`https://api.pushy.me/push?api_key=${notification.pushyAPIKey}`, {
|
||||||
|
"to": notification.pushyToken,
|
||||||
|
"data": {
|
||||||
|
"message": "Uptime-Kuma"
|
||||||
|
},
|
||||||
|
"notification": {
|
||||||
|
"body": msg,
|
||||||
|
"badge": 1,
|
||||||
|
"sound": "ping.aiff"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return okMsg;
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Pushy;
|
46
server/notification-providers/rocket-chat.js
Normal file
46
server/notification-providers/rocket-chat.js
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
class RocketChat extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "rocket.chat";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
try {
|
||||||
|
if (heartbeatJSON == null) {
|
||||||
|
let data = {
|
||||||
|
"text": "Uptime Kuma Rocket.chat testing successful.",
|
||||||
|
"channel": notification.rocketchannel,
|
||||||
|
"username": notification.rocketusername,
|
||||||
|
"icon_emoji": notification.rocketiconemo,
|
||||||
|
}
|
||||||
|
await axios.post(notification.rocketwebhookURL, data)
|
||||||
|
return okMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
const time = heartbeatJSON["time"];
|
||||||
|
let data = {
|
||||||
|
"text": "Uptime Kuma Alert",
|
||||||
|
"channel": notification.rocketchannel,
|
||||||
|
"username": notification.rocketusername,
|
||||||
|
"icon_emoji": notification.rocketiconemo,
|
||||||
|
"attachments": [
|
||||||
|
{
|
||||||
|
"title": "Uptime Kuma Alert *Time (UTC)*\n" + time,
|
||||||
|
"title_link": notification.rocketbutton,
|
||||||
|
"text": "*Message*\n" + msg,
|
||||||
|
"color": "#32cd32"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
await axios.post(notification.rocketwebhookURL, data)
|
||||||
|
return okMsg;
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = RocketChat;
|
27
server/notification-providers/signal.js
Normal file
27
server/notification-providers/signal.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
class Signal extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "signal";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
|
||||||
|
try {
|
||||||
|
let data = {
|
||||||
|
"message": msg,
|
||||||
|
"number": notification.signalNumber,
|
||||||
|
"recipients": notification.signalRecipients.replace(/\s/g, "").split(","),
|
||||||
|
};
|
||||||
|
let config = {};
|
||||||
|
|
||||||
|
await axios.post(notification.signalURL, data, config)
|
||||||
|
return okMsg;
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Signal;
|
70
server/notification-providers/slack.js
Normal file
70
server/notification-providers/slack.js
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
class Slack extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "slack";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
try {
|
||||||
|
if (heartbeatJSON == null) {
|
||||||
|
let data = {
|
||||||
|
"text": "Uptime Kuma Slack testing successful.",
|
||||||
|
"channel": notification.slackchannel,
|
||||||
|
"username": notification.slackusername,
|
||||||
|
"icon_emoji": notification.slackiconemo,
|
||||||
|
}
|
||||||
|
await axios.post(notification.slackwebhookURL, data)
|
||||||
|
return okMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
const time = heartbeatJSON["time"];
|
||||||
|
let data = {
|
||||||
|
"text": "Uptime Kuma Alert",
|
||||||
|
"channel": notification.slackchannel,
|
||||||
|
"username": notification.slackusername,
|
||||||
|
"icon_emoji": notification.slackiconemo,
|
||||||
|
"blocks": [{
|
||||||
|
"type": "header",
|
||||||
|
"text": {
|
||||||
|
"type": "plain_text",
|
||||||
|
"text": "Uptime Kuma Alert",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "section",
|
||||||
|
"fields": [{
|
||||||
|
"type": "mrkdwn",
|
||||||
|
"text": "*Message*\n" + msg,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mrkdwn",
|
||||||
|
"text": "*Time (UTC)*\n" + time,
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "actions",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"text": {
|
||||||
|
"type": "plain_text",
|
||||||
|
"text": "Visit Uptime Kuma",
|
||||||
|
},
|
||||||
|
"value": "Uptime-Kuma",
|
||||||
|
"url": notification.slackbutton || "https://github.com/louislam/uptime-kuma",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
await axios.post(notification.slackwebhookURL, data)
|
||||||
|
return okMsg;
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Slack;
|
43
server/notification-providers/smtp.js
Normal file
43
server/notification-providers/smtp.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
const nodemailer = require("nodemailer");
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
|
||||||
|
class SMTP extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "smtp";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
host: notification.smtpHost,
|
||||||
|
port: notification.smtpPort,
|
||||||
|
secure: notification.smtpSecure,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Should fix the issue in https://github.com/louislam/uptime-kuma/issues/26#issuecomment-896373904
|
||||||
|
if (notification.smtpUsername || notification.smtpPassword) {
|
||||||
|
config.auth = {
|
||||||
|
user: notification.smtpUsername,
|
||||||
|
pass: notification.smtpPassword,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let transporter = nodemailer.createTransport(config);
|
||||||
|
|
||||||
|
let bodyTextContent = msg;
|
||||||
|
if (heartbeatJSON) {
|
||||||
|
bodyTextContent = `${msg}\nTime (UTC): ${heartbeatJSON["time"]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send mail with defined transport object
|
||||||
|
await transporter.sendMail({
|
||||||
|
from: `"Uptime Kuma" <${notification.smtpFrom}>`,
|
||||||
|
to: notification.smtpTo,
|
||||||
|
subject: msg,
|
||||||
|
text: bodyTextContent,
|
||||||
|
});
|
||||||
|
|
||||||
|
return "Sent Successfully.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = SMTP;
|
27
server/notification-providers/telegram.js
Normal file
27
server/notification-providers/telegram.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
class Telegram extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "telegram";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.get(`https://api.telegram.org/bot${notification.telegramBotToken}/sendMessage`, {
|
||||||
|
params: {
|
||||||
|
chat_id: notification.telegramChatID,
|
||||||
|
text: msg,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return okMsg;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
let msg = (error.response.data.description) ? error.response.data.description : "Error without description"
|
||||||
|
throw new Error(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Telegram;
|
44
server/notification-providers/webhook.js
Normal file
44
server/notification-providers/webhook.js
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
const FormData = require("form-data");
|
||||||
|
|
||||||
|
class Webhook extends NotificationProvider {
|
||||||
|
|
||||||
|
name = "webhook";
|
||||||
|
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully. ";
|
||||||
|
|
||||||
|
try {
|
||||||
|
let data = {
|
||||||
|
heartbeat: heartbeatJSON,
|
||||||
|
monitor: monitorJSON,
|
||||||
|
msg,
|
||||||
|
};
|
||||||
|
let finalData;
|
||||||
|
let config = {};
|
||||||
|
|
||||||
|
if (notification.webhookContentType === "form-data") {
|
||||||
|
finalData = new FormData();
|
||||||
|
finalData.append("data", JSON.stringify(data));
|
||||||
|
|
||||||
|
config = {
|
||||||
|
headers: finalData.getHeaders(),
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
finalData = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
await axios.post(notification.webhookURL, finalData, config)
|
||||||
|
return okMsg;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Webhook;
|
|
@ -1,602 +1,75 @@
|
||||||
const axios = require("axios");
|
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const FormData = require("form-data");
|
const Apprise = require("./notification-providers/apprise");
|
||||||
const nodemailer = require("nodemailer");
|
const Discord = require("./notification-providers/discord");
|
||||||
const child_process = require("child_process");
|
const Gotify = require("./notification-providers/gotify");
|
||||||
|
const Line = require("./notification-providers/line");
|
||||||
const { UP, DOWN } = require("../src/util");
|
const LunaSea = require("./notification-providers/lunasea");
|
||||||
|
const Mattermost = require("./notification-providers/mattermost");
|
||||||
|
const Octopush = require("./notification-providers/octopush");
|
||||||
|
const Pushbullet = require("./notification-providers/pushbullet");
|
||||||
|
const Pushover = require("./notification-providers/pushover");
|
||||||
|
const Pushy = require("./notification-providers/pushy");
|
||||||
|
const RocketChat = require("./notification-providers/rocket-chat");
|
||||||
|
const Signal = require("./notification-providers/signal");
|
||||||
|
const Slack = require("./notification-providers/slack");
|
||||||
|
const SMTP = require("./notification-providers/smtp");
|
||||||
|
const Telegram = require("./notification-providers/telegram");
|
||||||
|
const Webhook = require("./notification-providers/webhook");
|
||||||
|
|
||||||
class Notification {
|
class Notification {
|
||||||
|
|
||||||
|
providerList = {};
|
||||||
|
|
||||||
|
static init() {
|
||||||
|
console.log("Prepare Notification Providers");
|
||||||
|
|
||||||
|
this.providerList = {};
|
||||||
|
|
||||||
|
const list = [
|
||||||
|
new Apprise(),
|
||||||
|
new Discord(),
|
||||||
|
new Gotify(),
|
||||||
|
new Line(),
|
||||||
|
new LunaSea(),
|
||||||
|
new Mattermost(),
|
||||||
|
new Octopush(),
|
||||||
|
new Pushbullet(),
|
||||||
|
new Pushover(),
|
||||||
|
new Pushy(),
|
||||||
|
new RocketChat(),
|
||||||
|
new Signal(),
|
||||||
|
new Slack(),
|
||||||
|
new SMTP(),
|
||||||
|
new Telegram(),
|
||||||
|
new Webhook(),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let item of list) {
|
||||||
|
if (! item.name) {
|
||||||
|
throw new Error("Notification provider without name");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.providerList[item.name]) {
|
||||||
|
throw new Error("Duplicate notification provider name");
|
||||||
|
}
|
||||||
|
this.providerList[item.name] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param notification
|
* @param notification : BeanModel
|
||||||
* @param msg
|
* @param msg : string General Message
|
||||||
* @param monitorJSON
|
* @param monitorJSON : object Monitor details (For Up/Down only)
|
||||||
* @param heartbeatJSON
|
* @param heartbeatJSON : object Heartbeat details (For Up/Down only)
|
||||||
* @returns {Promise<string>} Successful msg
|
* @returns {Promise<string>} Successful msg
|
||||||
* Throw Error with fail msg
|
* Throw Error with fail msg
|
||||||
*/
|
*/
|
||||||
static async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
static async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
let okMsg = "Sent Successfully. ";
|
if (this.providerList[notification.type]) {
|
||||||
|
return this.providerList[notification.type].send(notification, msg, monitorJSON, heartbeatJSON);
|
||||||
if (notification.type === "telegram") {
|
|
||||||
try {
|
|
||||||
await axios.get(`https://api.telegram.org/bot${notification.telegramBotToken}/sendMessage`, {
|
|
||||||
params: {
|
|
||||||
chat_id: notification.telegramChatID,
|
|
||||||
text: msg,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return okMsg;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
let msg = (error.response.data.description) ? error.response.data.description : "Error without description"
|
|
||||||
throw new Error(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (notification.type === "gotify") {
|
|
||||||
try {
|
|
||||||
if (notification.gotifyserverurl && notification.gotifyserverurl.endsWith("/")) {
|
|
||||||
notification.gotifyserverurl = notification.gotifyserverurl.slice(0, -1);
|
|
||||||
}
|
|
||||||
await axios.post(`${notification.gotifyserverurl}/message?token=${notification.gotifyapplicationToken}`, {
|
|
||||||
"message": msg,
|
|
||||||
"priority": notification.gotifyPriority || 8,
|
|
||||||
"title": "Uptime-Kuma",
|
|
||||||
})
|
|
||||||
|
|
||||||
return okMsg;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
throwGeneralAxiosError(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (notification.type === "webhook") {
|
|
||||||
try {
|
|
||||||
let data = {
|
|
||||||
heartbeat: heartbeatJSON,
|
|
||||||
monitor: monitorJSON,
|
|
||||||
msg,
|
|
||||||
};
|
|
||||||
let finalData;
|
|
||||||
let config = {};
|
|
||||||
|
|
||||||
if (notification.webhookContentType === "form-data") {
|
|
||||||
finalData = new FormData();
|
|
||||||
finalData.append("data", JSON.stringify(data));
|
|
||||||
|
|
||||||
config = {
|
|
||||||
headers: finalData.getHeaders(),
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
finalData = data;
|
throw new Error("Notification type is not supported");
|
||||||
}
|
|
||||||
|
|
||||||
await axios.post(notification.webhookURL, finalData, config)
|
|
||||||
return okMsg;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
throwGeneralAxiosError(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (notification.type === "smtp") {
|
|
||||||
return await Notification.smtp(notification, msg, heartbeatJSON)
|
|
||||||
|
|
||||||
} else if (notification.type === "discord") {
|
|
||||||
try {
|
|
||||||
const discordDisplayName = notification.discordUsername || "Uptime Kuma";
|
|
||||||
|
|
||||||
// If heartbeatJSON is null, assume we're testing.
|
|
||||||
if (heartbeatJSON == null) {
|
|
||||||
let discordtestdata = {
|
|
||||||
username: discordDisplayName,
|
|
||||||
content: msg,
|
|
||||||
}
|
|
||||||
await axios.post(notification.discordWebhookUrl, discordtestdata)
|
|
||||||
return okMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
let url;
|
|
||||||
|
|
||||||
if (monitorJSON["type"] === "port") {
|
|
||||||
url = monitorJSON["hostname"];
|
|
||||||
if (monitorJSON["port"]) {
|
|
||||||
url += ":" + monitorJSON["port"];
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
url = monitorJSON["url"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// If heartbeatJSON is not null, we go into the normal alerting loop.
|
|
||||||
if (heartbeatJSON["status"] == DOWN) {
|
|
||||||
let discorddowndata = {
|
|
||||||
username: discordDisplayName,
|
|
||||||
embeds: [{
|
|
||||||
title: "❌ Your service " + monitorJSON["name"] + " went down. ❌",
|
|
||||||
color: 16711680,
|
|
||||||
timestamp: heartbeatJSON["time"],
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
name: "Service Name",
|
|
||||||
value: monitorJSON["name"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Service URL",
|
|
||||||
value: url,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Time (UTC)",
|
|
||||||
value: heartbeatJSON["time"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Error",
|
|
||||||
value: heartbeatJSON["msg"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
}
|
|
||||||
await axios.post(notification.discordWebhookUrl, discorddowndata)
|
|
||||||
return okMsg;
|
|
||||||
|
|
||||||
} else if (heartbeatJSON["status"] == UP) {
|
|
||||||
let discordupdata = {
|
|
||||||
username: discordDisplayName,
|
|
||||||
embeds: [{
|
|
||||||
title: "✅ Your service " + monitorJSON["name"] + " is up! ✅",
|
|
||||||
color: 65280,
|
|
||||||
timestamp: heartbeatJSON["time"],
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
name: "Service Name",
|
|
||||||
value: monitorJSON["name"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Service URL",
|
|
||||||
value: url.startsWith("http") ? "[Visit Service](" + url + ")" : url,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Time (UTC)",
|
|
||||||
value: heartbeatJSON["time"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Ping",
|
|
||||||
value: heartbeatJSON["ping"] + "ms",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
}
|
|
||||||
await axios.post(notification.discordWebhookUrl, discordupdata)
|
|
||||||
return okMsg;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
throwGeneralAxiosError(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (notification.type === "signal") {
|
|
||||||
try {
|
|
||||||
let data = {
|
|
||||||
"message": msg,
|
|
||||||
"number": notification.signalNumber,
|
|
||||||
"recipients": notification.signalRecipients.replace(/\s/g, "").split(","),
|
|
||||||
};
|
|
||||||
let config = {};
|
|
||||||
|
|
||||||
await axios.post(notification.signalURL, data, config)
|
|
||||||
return okMsg;
|
|
||||||
} catch (error) {
|
|
||||||
throwGeneralAxiosError(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (notification.type === "pushy") {
|
|
||||||
try {
|
|
||||||
await axios.post(`https://api.pushy.me/push?api_key=${notification.pushyAPIKey}`, {
|
|
||||||
"to": notification.pushyToken,
|
|
||||||
"data": {
|
|
||||||
"message": "Uptime-Kuma"
|
|
||||||
},
|
|
||||||
"notification": {
|
|
||||||
"body": msg,
|
|
||||||
"badge": 1,
|
|
||||||
"sound": "ping.aiff"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (notification.type === "octopush") {
|
|
||||||
try {
|
|
||||||
let config = {
|
|
||||||
headers: {
|
|
||||||
"api-key": notification.octopushAPIKey,
|
|
||||||
"api-login": notification.octopushLogin,
|
|
||||||
"cache-control": "no-cache"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let data = {
|
|
||||||
"recipients": [
|
|
||||||
{
|
|
||||||
"phone_number": notification.octopushPhoneNumber
|
|
||||||
}
|
|
||||||
],
|
|
||||||
//octopush not supporting non ascii char
|
|
||||||
"text": msg.replace(/[^\x00-\x7F]/g, ""),
|
|
||||||
"type": notification.octopushSMSType,
|
|
||||||
"purpose": "alert",
|
|
||||||
"sender": notification.octopushSenderName
|
|
||||||
};
|
|
||||||
|
|
||||||
await axios.post("https://api.octopush.com/v1/public/sms-campaign/send", data, config)
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (notification.type === "slack") {
|
|
||||||
try {
|
|
||||||
if (heartbeatJSON == null) {
|
|
||||||
let data = {
|
|
||||||
"text": "Uptime Kuma Slack testing successful.",
|
|
||||||
"channel": notification.slackchannel,
|
|
||||||
"username": notification.slackusername,
|
|
||||||
"icon_emoji": notification.slackiconemo,
|
|
||||||
}
|
|
||||||
await axios.post(notification.slackwebhookURL, data)
|
|
||||||
return okMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
const time = heartbeatJSON["time"];
|
|
||||||
let data = {
|
|
||||||
"text": "Uptime Kuma Alert",
|
|
||||||
"channel": notification.slackchannel,
|
|
||||||
"username": notification.slackusername,
|
|
||||||
"icon_emoji": notification.slackiconemo,
|
|
||||||
"blocks": [{
|
|
||||||
"type": "header",
|
|
||||||
"text": {
|
|
||||||
"type": "plain_text",
|
|
||||||
"text": "Uptime Kuma Alert",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "section",
|
|
||||||
"fields": [{
|
|
||||||
"type": "mrkdwn",
|
|
||||||
"text": "*Message*\n" + msg,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "mrkdwn",
|
|
||||||
"text": "*Time (UTC)*\n" + time,
|
|
||||||
}],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "actions",
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"type": "button",
|
|
||||||
"text": {
|
|
||||||
"type": "plain_text",
|
|
||||||
"text": "Visit Uptime Kuma",
|
|
||||||
},
|
|
||||||
"value": "Uptime-Kuma",
|
|
||||||
"url": notification.slackbutton || "https://github.com/louislam/uptime-kuma",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
}
|
|
||||||
await axios.post(notification.slackwebhookURL, data)
|
|
||||||
return okMsg;
|
|
||||||
} catch (error) {
|
|
||||||
throwGeneralAxiosError(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (notification.type === "rocket.chat") {
|
|
||||||
try {
|
|
||||||
if (heartbeatJSON == null) {
|
|
||||||
let data = {
|
|
||||||
"text": "Uptime Kuma Rocket.chat testing successful.",
|
|
||||||
"channel": notification.rocketchannel,
|
|
||||||
"username": notification.rocketusername,
|
|
||||||
"icon_emoji": notification.rocketiconemo,
|
|
||||||
}
|
|
||||||
await axios.post(notification.rocketwebhookURL, data)
|
|
||||||
return okMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
const time = heartbeatJSON["time"];
|
|
||||||
let data = {
|
|
||||||
"text": "Uptime Kuma Alert",
|
|
||||||
"channel": notification.rocketchannel,
|
|
||||||
"username": notification.rocketusername,
|
|
||||||
"icon_emoji": notification.rocketiconemo,
|
|
||||||
"attachments": [
|
|
||||||
{
|
|
||||||
"title": "Uptime Kuma Alert *Time (UTC)*\n" + time,
|
|
||||||
"title_link": notification.rocketbutton,
|
|
||||||
"text": "*Message*\n" + msg,
|
|
||||||
"color": "#32cd32"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
await axios.post(notification.rocketwebhookURL, data)
|
|
||||||
return okMsg;
|
|
||||||
} catch (error) {
|
|
||||||
throwGeneralAxiosError(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (notification.type === "mattermost") {
|
|
||||||
try {
|
|
||||||
const mattermostUserName = notification.mattermostusername || "Uptime Kuma";
|
|
||||||
// If heartbeatJSON is null, assume we're testing.
|
|
||||||
if (heartbeatJSON == null) {
|
|
||||||
let mattermostTestData = {
|
|
||||||
username: mattermostUserName,
|
|
||||||
text: msg,
|
|
||||||
}
|
|
||||||
await axios.post(notification.mattermostWebhookUrl, mattermostTestData)
|
|
||||||
return okMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mattermostChannel = notification.mattermostchannel;
|
|
||||||
const mattermostIconEmoji = notification.mattermosticonemo;
|
|
||||||
const mattermostIconUrl = notification.mattermosticonurl;
|
|
||||||
|
|
||||||
if (heartbeatJSON["status"] == DOWN) {
|
|
||||||
let mattermostdowndata = {
|
|
||||||
username: mattermostUserName,
|
|
||||||
text: "Uptime Kuma Alert",
|
|
||||||
channel: mattermostChannel,
|
|
||||||
icon_emoji: mattermostIconEmoji,
|
|
||||||
icon_url: mattermostIconUrl,
|
|
||||||
attachments: [
|
|
||||||
{
|
|
||||||
fallback:
|
|
||||||
"Your " +
|
|
||||||
monitorJSON["name"] +
|
|
||||||
" service went down.",
|
|
||||||
color: "#FF0000",
|
|
||||||
title:
|
|
||||||
"❌ " +
|
|
||||||
monitorJSON["name"] +
|
|
||||||
" service went down. ❌",
|
|
||||||
title_link: monitorJSON["url"],
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
short: true,
|
|
||||||
title: "Service Name",
|
|
||||||
value: monitorJSON["name"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
short: true,
|
|
||||||
title: "Time (UTC)",
|
|
||||||
value: heartbeatJSON["time"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
short: false,
|
|
||||||
title: "Error",
|
|
||||||
value: heartbeatJSON["msg"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
await axios.post(
|
|
||||||
notification.mattermostWebhookUrl,
|
|
||||||
mattermostdowndata
|
|
||||||
);
|
|
||||||
return okMsg;
|
|
||||||
} else if (heartbeatJSON["status"] == UP) {
|
|
||||||
let mattermostupdata = {
|
|
||||||
username: mattermostUserName,
|
|
||||||
text: "Uptime Kuma Alert",
|
|
||||||
channel: mattermostChannel,
|
|
||||||
icon_emoji: mattermostIconEmoji,
|
|
||||||
icon_url: mattermostIconUrl,
|
|
||||||
attachments: [
|
|
||||||
{
|
|
||||||
fallback:
|
|
||||||
"Your " +
|
|
||||||
monitorJSON["name"] +
|
|
||||||
" service went up!",
|
|
||||||
color: "#32CD32",
|
|
||||||
title:
|
|
||||||
"✅ " +
|
|
||||||
monitorJSON["name"] +
|
|
||||||
" service went up! ✅",
|
|
||||||
title_link: monitorJSON["url"],
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
short: true,
|
|
||||||
title: "Service Name",
|
|
||||||
value: monitorJSON["name"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
short: true,
|
|
||||||
title: "Time (UTC)",
|
|
||||||
value: heartbeatJSON["time"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
short: false,
|
|
||||||
title: "Ping",
|
|
||||||
value: heartbeatJSON["ping"] + "ms",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
await axios.post(
|
|
||||||
notification.mattermostWebhookUrl,
|
|
||||||
mattermostupdata
|
|
||||||
);
|
|
||||||
return okMsg;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
throwGeneralAxiosError(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (notification.type === "pushover") {
|
|
||||||
let pushoverlink = "https://api.pushover.net/1/messages.json"
|
|
||||||
try {
|
|
||||||
if (heartbeatJSON == null) {
|
|
||||||
let data = {
|
|
||||||
"message": "<b>Uptime Kuma Pushover testing successful.</b>",
|
|
||||||
"user": notification.pushoveruserkey,
|
|
||||||
"token": notification.pushoverapptoken,
|
|
||||||
"sound": notification.pushoversounds,
|
|
||||||
"priority": notification.pushoverpriority,
|
|
||||||
"title": notification.pushovertitle,
|
|
||||||
"retry": "30",
|
|
||||||
"expire": "3600",
|
|
||||||
"html": 1,
|
|
||||||
}
|
|
||||||
await axios.post(pushoverlink, data)
|
|
||||||
return okMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = {
|
|
||||||
"message": "<b>Uptime Kuma Alert</b>\n\n<b>Message</b>:" + msg + "\n<b>Time (UTC)</b>:" + heartbeatJSON["time"],
|
|
||||||
"user": notification.pushoveruserkey,
|
|
||||||
"token": notification.pushoverapptoken,
|
|
||||||
"sound": notification.pushoversounds,
|
|
||||||
"priority": notification.pushoverpriority,
|
|
||||||
"title": notification.pushovertitle,
|
|
||||||
"retry": "30",
|
|
||||||
"expire": "3600",
|
|
||||||
"html": 1,
|
|
||||||
}
|
|
||||||
await axios.post(pushoverlink, data)
|
|
||||||
return okMsg;
|
|
||||||
} catch (error) {
|
|
||||||
throwGeneralAxiosError(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (notification.type === "apprise") {
|
|
||||||
|
|
||||||
return Notification.apprise(notification, msg)
|
|
||||||
|
|
||||||
} else if (notification.type === "lunasea") {
|
|
||||||
let lunaseadevice = "https://notify.lunasea.app/v1/custom/device/" + notification.lunaseaDevice
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (heartbeatJSON == null) {
|
|
||||||
let testdata = {
|
|
||||||
"title": "Uptime Kuma Alert",
|
|
||||||
"body": "Testing Successful.",
|
|
||||||
}
|
|
||||||
await axios.post(lunaseadevice, testdata)
|
|
||||||
return okMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heartbeatJSON["status"] == DOWN) {
|
|
||||||
let downdata = {
|
|
||||||
"title": "UptimeKuma Alert: " + monitorJSON["name"],
|
|
||||||
"body": "[🔴 Down] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
|
|
||||||
}
|
|
||||||
await axios.post(lunaseadevice, downdata)
|
|
||||||
return okMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heartbeatJSON["status"] == UP) {
|
|
||||||
let updata = {
|
|
||||||
"title": "UptimeKuma Alert: " + monitorJSON["name"],
|
|
||||||
"body": "[✅ Up] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
|
|
||||||
}
|
|
||||||
await axios.post(lunaseadevice, updata)
|
|
||||||
return okMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
throwGeneralAxiosError(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (notification.type === "pushbullet") {
|
|
||||||
try {
|
|
||||||
let pushbulletUrl = "https://api.pushbullet.com/v2/pushes";
|
|
||||||
let config = {
|
|
||||||
headers: {
|
|
||||||
"Access-Token": notification.pushbulletAccessToken,
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (heartbeatJSON == null) {
|
|
||||||
let testdata = {
|
|
||||||
"type": "note",
|
|
||||||
"title": "Uptime Kuma Alert",
|
|
||||||
"body": "Testing Successful.",
|
|
||||||
}
|
|
||||||
await axios.post(pushbulletUrl, testdata, config)
|
|
||||||
} 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) {
|
|
||||||
let updata = {
|
|
||||||
"type": "note",
|
|
||||||
"title": "UptimeKuma Alert: " + monitorJSON["name"],
|
|
||||||
"body": "[✅ Up] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
|
|
||||||
}
|
|
||||||
await axios.post(pushbulletUrl, updata, config)
|
|
||||||
}
|
|
||||||
return okMsg;
|
|
||||||
} catch (error) {
|
|
||||||
throwGeneralAxiosError(error)
|
|
||||||
}
|
|
||||||
} else if (notification.type === "line") {
|
|
||||||
try {
|
|
||||||
let lineAPIUrl = "https://api.line.me/v2/bot/message/push";
|
|
||||||
let config = {
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"Authorization": "Bearer " + notification.lineChannelAccessToken
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (heartbeatJSON == null) {
|
|
||||||
let testMessage = {
|
|
||||||
"to": notification.lineUserID,
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"text": "Test Successful!"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
await axios.post(lineAPIUrl, testMessage, config)
|
|
||||||
} else if (heartbeatJSON["status"] == DOWN) {
|
|
||||||
let downMessage = {
|
|
||||||
"to": notification.lineUserID,
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"text": "UptimeKuma Alert: [🔴 Down]\n" + "Name: " + monitorJSON["name"] + " \n" + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
await axios.post(lineAPIUrl, downMessage, config)
|
|
||||||
} else if (heartbeatJSON["status"] == UP) {
|
|
||||||
let upMessage = {
|
|
||||||
"to": notification.lineUserID,
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"text": "UptimeKuma Alert: [✅ Up]\n" + "Name: " + monitorJSON["name"] + " \n" + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
await axios.post(lineAPIUrl, upMessage, config)
|
|
||||||
}
|
|
||||||
return okMsg;
|
|
||||||
} catch (error) {
|
|
||||||
throwGeneralAxiosError(error)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Error("Notification type is not supported")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,57 +109,6 @@ class Notification {
|
||||||
await R.trash(bean)
|
await R.trash(bean)
|
||||||
}
|
}
|
||||||
|
|
||||||
static async smtp(notification, msg, heartbeatJSON = null) {
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
host: notification.smtpHost,
|
|
||||||
port: notification.smtpPort,
|
|
||||||
secure: notification.smtpSecure,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Should fix the issue in https://github.com/louislam/uptime-kuma/issues/26#issuecomment-896373904
|
|
||||||
if (notification.smtpUsername || notification.smtpPassword) {
|
|
||||||
config.auth = {
|
|
||||||
user: notification.smtpUsername,
|
|
||||||
pass: notification.smtpPassword,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let transporter = nodemailer.createTransport(config);
|
|
||||||
|
|
||||||
let bodyTextContent = msg;
|
|
||||||
if(heartbeatJSON) {
|
|
||||||
bodyTextContent = `${msg}\nTime (UTC): ${heartbeatJSON["time"]}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send mail with defined transport object
|
|
||||||
await transporter.sendMail({
|
|
||||||
from: `"Uptime Kuma" <${notification.smtpFrom}>`,
|
|
||||||
to: notification.smtpTo,
|
|
||||||
subject: msg,
|
|
||||||
text: bodyTextContent,
|
|
||||||
});
|
|
||||||
|
|
||||||
return "Sent Successfully.";
|
|
||||||
}
|
|
||||||
|
|
||||||
static async apprise(notification, msg) {
|
|
||||||
let s = child_process.spawnSync("apprise", [ "-vv", "-b", msg, notification.appriseURL])
|
|
||||||
|
|
||||||
let output = (s.stdout) ? s.stdout.toString() : "ERROR: maybe apprise not found";
|
|
||||||
|
|
||||||
if (output) {
|
|
||||||
|
|
||||||
if (! output.includes("ERROR")) {
|
|
||||||
return "Sent Successfully";
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(output)
|
|
||||||
} else {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static checkApprise() {
|
static checkApprise() {
|
||||||
let commandExistsSync = require("command-exists").sync;
|
let commandExistsSync = require("command-exists").sync;
|
||||||
let exists = commandExistsSync("apprise");
|
let exists = commandExistsSync("apprise");
|
||||||
|
@ -695,20 +117,6 @@ class Notification {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function throwGeneralAxiosError(error) {
|
|
||||||
let msg = "Error: " + error + " ";
|
|
||||||
|
|
||||||
if (error.response && error.response.data) {
|
|
||||||
if (typeof error.response.data === "string") {
|
|
||||||
msg += error.response.data;
|
|
||||||
} else {
|
|
||||||
msg += JSON.stringify(error.response.data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Notification,
|
Notification,
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,11 @@ debug("Importing Monitor");
|
||||||
const Monitor = require("./model/monitor");
|
const Monitor = require("./model/monitor");
|
||||||
debug("Importing Settings");
|
debug("Importing Settings");
|
||||||
const { getSettings, setSettings, setting, initJWTSecret } = require("./util-server");
|
const { getSettings, setSettings, setting, initJWTSecret } = require("./util-server");
|
||||||
|
|
||||||
debug("Importing Notification");
|
debug("Importing Notification");
|
||||||
const { Notification } = require("./notification");
|
const { Notification } = require("./notification");
|
||||||
|
Notification.init();
|
||||||
|
|
||||||
debug("Importing Database");
|
debug("Importing Database");
|
||||||
const Database = require("./database");
|
const Database = require("./database");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue