Skip to content
Draft

2.1.X #5487

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions server/notification-providers/bale.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");

class Bale extends NotificationProvider {
name = "bale";

/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
const okMsg = "Sent Successfully.";
const url = "https://tapi.bale.ai";

try {
await axios.post(
`${url}/bot${notification.baleBotToken}/sendMessage`,
{
chat_id: notification.baleChatID,
text: msg
},
{
headers: {
"content-type": "application/json",
},
}
);
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}

module.exports = Bale;
21 changes: 16 additions & 5 deletions server/notification-providers/dingding.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,23 @@ class DingDing extends NotificationProvider {
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
const okMsg = "Sent Successfully.";

const mentionAll = notification.mentioning === "everyone";
const mobileList = notification.mentioning === "specify-mobiles" ? notification.mobileList : [];
const userList = notification.mentioning === "specify-users" ? notification.userList : [];
const finalList = [ ...mobileList || [], ...userList || [] ];
const mentionStr = finalList.length > 0 ? "\n" : "" + finalList.map(item => `@${item}`).join(" ");
try {
if (heartbeatJSON != null) {
let params = {
msgtype: "markdown",
markdown: {
title: `[${this.statusToString(heartbeatJSON["status"])}] ${monitorJSON["name"]}`,
text: `## [${this.statusToString(heartbeatJSON["status"])}] ${monitorJSON["name"]} \n> ${heartbeatJSON["msg"]}\n> Time (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`,
text: `## [${this.statusToString(heartbeatJSON["status"])}] ${monitorJSON["name"]} \n> ${heartbeatJSON["msg"]}\n> Time (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}${mentionStr}`,
},
"at": {
"isAtAll": notification.mentioning === "everyone"
at: {
isAtAll: mentionAll,
atUserIds: userList,
atMobiles: mobileList
}
};
if (await this.sendToDingDing(notification, params)) {
Expand All @@ -31,7 +37,12 @@ class DingDing extends NotificationProvider {
let params = {
msgtype: "text",
text: {
content: msg
content: `${msg}${mentionStr}`
},
at: {
isAtAll: mentionAll,
atUserIds: userList,
atMobiles: mobileList
}
};
if (await this.sendToDingDing(notification, params)) {
Expand Down
38 changes: 24 additions & 14 deletions server/notification.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Alerta = require("./notification-providers/alerta");
const AlertNow = require("./notification-providers/alertnow");
const AliyunSms = require("./notification-providers/aliyun-sms");
const Apprise = require("./notification-providers/apprise");
const Bale = require("./notification-providers/bale");
const Bark = require("./notification-providers/bark");
const Bitrix24 = require("./notification-providers/bitrix24");
const ClickSendSMS = require("./notification-providers/clicksendsms");
Expand Down Expand Up @@ -82,7 +83,6 @@ const SMSPlanet = require("./notification-providers/sms-planet");
const SpugPush = require("./notification-providers/spugpush");

class Notification {

providerList = {};

/**
Expand All @@ -101,6 +101,7 @@ class Notification {
new AlertNow(),
new AliyunSms(),
new Apprise(),
new Bale(),
new Bark(),
new Bitrix24(),
new ClickSendSMS(),
Expand Down Expand Up @@ -179,7 +180,7 @@ class Notification {
new Notifery(),
];
for (let item of list) {
if (! item.name) {
if (!item.name) {
throw new Error("Notification provider without name");
}

Expand All @@ -199,9 +200,19 @@ class Notification {
* @returns {Promise<string>} Successful msg
* @throws Error with fail msg
*/
static async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
static async send(
notification,
msg,
monitorJSON = null,
heartbeatJSON = null
) {
if (this.providerList[notification.type]) {
return this.providerList[notification.type].send(notification, msg, monitorJSON, heartbeatJSON);
return this.providerList[notification.type].send(
notification,
msg,
monitorJSON,
heartbeatJSON
);
} else {
throw new Error("Notification type is not supported");
}
Expand All @@ -223,10 +234,9 @@ class Notification {
userID,
]);

if (! bean) {
if (!bean) {
throw new Error("notification not found");
}

} else {
bean = R.dispense("notification");
}
Expand Down Expand Up @@ -256,7 +266,7 @@ class Notification {
userID,
]);

if (! bean) {
if (!bean) {
throw new Error("notification not found");
}

Expand All @@ -272,7 +282,6 @@ class Notification {
let exists = commandExistsSync("apprise");
return exists;
}

}

/**
Expand All @@ -283,16 +292,17 @@ class Notification {
*/
async function applyNotificationEveryMonitor(notificationID, userID) {
let monitors = await R.getAll("SELECT id FROM monitor WHERE user_id = ?", [
userID
userID,
]);

for (let i = 0; i < monitors.length; i++) {
let checkNotification = await R.findOne("monitor_notification", " monitor_id = ? AND notification_id = ? ", [
monitors[i].id,
notificationID,
]);
let checkNotification = await R.findOne(
"monitor_notification",
" monitor_id = ? AND notification_id = ? ",
[ monitors[i].id, notificationID ]
);

if (! checkNotification) {
if (!checkNotification) {
let relation = R.dispense("monitor_notification");
relation.monitor_id = monitors[i].id;
relation.notification_id = notificationID;
Expand Down
1 change: 1 addition & 0 deletions src/components/NotificationDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export default {
"alerta": "Alerta",
"AlertNow": "AlertNow",
"apprise": this.$t("apprise"),
"bale": "Bale",
"Bark": "Bark",
"Bitrix24": "Bitrix24",
"clicksendsms": "ClickSend SMS",
Expand Down
93 changes: 93 additions & 0 deletions src/components/notifications/Bale.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<template>
<div class="mb-3">
<label for="bale-bot-token" class="form-label">{{ $t("Bot Token") }}</label>
<HiddenInput id="bale-bot-token" v-model="$parent.notification.baleBotToken" :required="true" autocomplete="new-password"></HiddenInput>
<i18n-t tag="div" keypath="wayToGetBaleToken" class="form-text">
<a href="https://ble.ir/BotFather" target="_blank">https://ble.ir/BotFather</a>
</i18n-t>
</div>

<div class="mb-3">
<label for="bale-chat-id" class="form-label">{{ $t("Chat ID") }}</label>

<div class="input-group mb-3">
<input id="bale-chat-id" v-model="$parent.notification.baleChatID" type="text" class="form-control" required>
<button v-if="$parent.notification.baleBotToken" class="btn btn-outline-secondary" type="button" @click="autoGetBaleChatID">
{{ $t("Auto Get") }}
</button>
</div>

<div class="form-text">
{{ $t("supportBaleChatID") }}

<p style="margin-top: 8px;">
{{ $t("wayToGetBaleChatID") }}
</p>

<p style="margin-top: 8px;">
<a :href="baleGetUpdatesURL('withToken')" target="_blank" style="word-break: break-word;">{{ baleGetUpdatesURL("masked") }}</a>
</p>
</div>
</div>
</template>

<script>
import HiddenInput from "../HiddenInput.vue";
import axios from "axios";

export default {
components: {
HiddenInput,
},
methods: {
/**
* Get the URL for bale updates
* @param {string} mode Should the token be masked?
* @returns {string} formatted URL
*/
baleGetUpdatesURL(mode = "masked") {
let token = `<${this.$t("YOUR BOT TOKEN HERE")}>`;

if (this.$parent.notification.baleBotToken) {
if (mode === "withToken") {
token = this.$parent.notification.baleBotToken;
} else if (mode === "masked") {
token = "*".repeat(this.$parent.notification.baleBotToken.length);
}
}

return `https://tapi.bale.ai/bot${token}/getUpdates`;
},

/**
* Get the bale chat ID
* @returns {Promise<void>}
* @throws The chat ID could not be found
*/
async autoGetBaleChatID() {
try {
let res = await axios.get(this.baleGetUpdatesURL("withToken"));

if (res.data.result.length >= 1) {
let update = res.data.result[res.data.result.length - 1];

if (update.channel_post) {
this.$parent.notification.baleChatID = update.channel_post.chat.id;
} else if (update.message) {
this.$parent.notification.baleChatID = update.message.chat.id;
} else {
throw new Error(this.$t("chatIDNotFound"));
}

} else {
throw new Error(this.$t("chatIDNotFound"));
}

} catch (error) {
this.$root.toastError(error.message);
}

},
}
};
</script>
Loading
Loading