feat: Add VKTeams bot notification provider (#7365)

This commit is contained in:
Alexey
2026-05-08 16:15:46 +07:00
committed by GitHub
parent d60feb909c
commit 74c43a33f3
6 changed files with 155 additions and 1 deletions

View File

@@ -0,0 +1,48 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class VKTeams extends NotificationProvider {
name = "VKTeams";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
const okMsg = "Sent Successfully.";
const baseUrl = (notification.vkteamsBaseUrl || "https://myteam.mail.ru").replace(/\/$/, "");
try {
const rawParams = {
token: notification.vkteamsBotToken,
chatId: notification.vkteamsChatId,
text: msg,
};
if (notification.vkteamsUseTemplate && notification.vkteamsTemplate) {
rawParams.text = await this.renderTemplate(
notification.vkteamsTemplate,
msg,
monitorJSON,
heartbeatJSON
);
if (notification.vkteamsTemplateFormat && notification.vkteamsTemplateFormat !== "plain") {
rawParams.parseMode = notification.vkteamsTemplateFormat;
}
}
const params = new URLSearchParams(rawParams).toString();
const config = this.getAxiosConfigWithProxy({});
const response = await axios.get(`${baseUrl}/bot/v1/messages/sendText?${params}`, config);
if (response.data?.ok === false) {
throw new Error(`VKTeams API returned error: ${response.data.description}`);
}
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = VKTeams;

View File

@@ -93,6 +93,7 @@ const Webpush = require("./notification-providers/Webpush");
const HaloPSA = require("./notification-providers/HaloPSA");
const Max = require("./notification-providers/max");
const VK = require("./notification-providers/vk");
const VKTeams = require("./notification-providers/vkteams");
class Notification {
providerList = {};
@@ -201,6 +202,7 @@ class Notification {
new HaloPSA(),
new Max(),
new VK(),
new VKTeams(),
];
for (let item of list) {
if (!item.name) {

View File

@@ -336,6 +336,7 @@ export default {
YZJ: "YZJ (云之家自定义机器人)",
SMSPlanet: "SMSPlanet.pl",
VK: "VK",
VKTeams: "VKTeams",
};
// Sort by notification name alphabetically

View File

@@ -0,0 +1,95 @@
<template>
<div class="mb-3">
<label for="vkteams-bot-token" class="form-label">{{ $t("Bot Token") }}</label>
<HiddenInput
id="vkteams-bot-token"
v-model="$parent.notification.vkteamsBotToken"
:required="true"
autocomplete="new-password"
></HiddenInput>
<i18n-t tag="div" keypath="VKTeams Bot Token Description" class="form-text">
<a href="https://teams.vk.com/botapi/" target="_blank">https://teams.vk.com/botapi/</a>
</i18n-t>
</div>
<div class="mb-3">
<label for="vkteams-bot-chat-id" class="form-label">{{ $t("Chat ID") }}</label>
<input
id="vkteams-bot-chat-id"
v-model="$parent.notification.vkteamsChatId"
type="text"
class="form-control"
placeholder="*****@chat.agent"
required
/>
<div class="form-text">
{{ $t("VKTeams Chat Id Description") }}
</div>
</div>
<div class="mb-3">
<label for="vkteams-api-url" class="form-label">{{ $t("API URL") }}</label>
<input
id="vkteams-api-url"
v-model="$parent.notification.vkteamsBaseUrl"
type="text"
class="form-control"
required
/>
<div class="form-text">
{{ $t("VKTeams Base Url Description") }}
</div>
</div>
<div class="mb-3">
<div class="form-check form-switch">
<input v-model="$parent.notification.vkteamsUseTemplate" class="form-check-input" type="checkbox" />
<label class="form-check-label">{{ $t("VKTeams Use Template") }}</label>
</div>
<div class="form-text">
{{ $t("VKTeams Use Template Description") }}
</div>
</div>
<template v-if="$parent.notification.vkteamsUseTemplate">
<div class="mb-3">
<label class="form-label" for="vkteams-message-format">{{ $t("Message Format") }}</label>
<select
id="vkteams-message-format"
v-model="$parent.notification.vkteamsTemplateFormat"
class="form-select"
required
>
<option value="plain">{{ $t("Plain Text") }}</option>
<option value="MarkdownV2">MarkdownV2</option>
<option value="HTML">HTML</option>
</select>
<p class="form-text">
{{ $t("VKTeams Template Format Description") }}
</p>
<label class="form-label" for="vkteams-message-template">{{ $t("Message Template") }}</label>
<TemplatedTextarea
id="vkteams-message-template"
v-model="$parent.notification.vkteamsTemplate"
:required="true"
></TemplatedTextarea>
</div>
</template>
</template>
<script>
import HiddenInput from "../HiddenInput.vue";
import TemplatedTextarea from "../TemplatedTextarea.vue";
export default {
components: {
TemplatedTextarea,
HiddenInput,
},
mounted() {
this.$parent.notification.vkteamsBaseUrl ||= "https://myteam.mail.ru";
this.$parent.notification.vkteamsTemplateFormat ||= "plain";
},
};
</script>

View File

@@ -90,6 +90,7 @@ import HaloPSA from "./HaloPSA.vue";
import Resend from "./Resend.vue";
import Max from "./Max.vue";
import VK from "./VK.vue";
import VKTeams from "./VKTeams.vue";
/**
* Manage all notification form.
@@ -188,6 +189,7 @@ const NotificationFormList = {
HaloPSA: HaloPSA,
max: Max,
VK: VK,
VKTeams: VKTeams,
};
export default NotificationFormList;

View File

@@ -1532,5 +1532,11 @@
"teltonikaModem": "Modem Id",
"teltonikaModemHelptext": "The id of the SMS modem, must be in the format {0}. Refer to https://developers.teltonika-networks.com/reference/ for guidance.",
"teltonikaPhoneNumber": "Phone number",
"teltonikaPhoneNumberHelptext": "The number must be in the international format {0}, {1}. Only one number is allowed."
"teltonikaPhoneNumberHelptext": "The number must be in the international format {0}, {1}. Only one number is allowed.",
"VKTeams Bot Token Description": "You can find out how to get a bot token and other details at {0}.",
"VKTeams Base Url Description": "VKTeams base API URL, may differ in On-Premise solution. Default: https://myteam.mail.ru",
"VKTeams Chat Id Description": "For users, this is their email address. For groups and channels, get the ID from their settings and append {'@'}chat.agent",
"VKTeams Use Template": "Use custom message template",
"VKTeams Use Template Description": "If enabled, the message will be sent using a custom template.",
"VKTeams Template Format Description": "For message styling, VKTeams supports plain text, MarkdownV2, and HTML formatting."
}