mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-06-01 19:32:34 +02:00
Merge branch 'master' into telegram-custom-server
# Conflicts: # src/components/notifications/Telegram.vue
This commit is contained in:
commit
6dd37e1ab1
19 changed files with 465 additions and 91 deletions
|
@ -41,7 +41,7 @@
|
||||||
"build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test2 --target pr-test2 . --push",
|
"build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test2 --target pr-test2 . --push",
|
||||||
"upload-artifacts": "node extra/release/upload-artifacts.mjs",
|
"upload-artifacts": "node extra/release/upload-artifacts.mjs",
|
||||||
"upload-artifacts-beta": "node extra/release/upload-artifacts-beta.mjs",
|
"upload-artifacts-beta": "node extra/release/upload-artifacts-beta.mjs",
|
||||||
"setup": "git checkout 1.23.16 && npm ci --production && npm run download-dist",
|
"setup": "git checkout 1.23.16 && npm ci --omit dev && npm run download-dist",
|
||||||
"download-dist": "node extra/download-dist.js",
|
"download-dist": "node extra/download-dist.js",
|
||||||
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
||||||
"reset-password": "node extra/reset-password.js",
|
"reset-password": "node extra/reset-password.js",
|
||||||
|
|
|
@ -1434,7 +1434,7 @@ class Monitor extends BeanModel {
|
||||||
for (let notification of notificationList) {
|
for (let notification of notificationList) {
|
||||||
try {
|
try {
|
||||||
log.debug("monitor", "Sending to " + notification.name);
|
log.debug("monitor", "Sending to " + notification.name);
|
||||||
await Notification.send(JSON.parse(notification.config), `[${this.name}][${this.url}] ${certType} certificate ${certCN} will be expired in ${daysRemaining} days`);
|
await Notification.send(JSON.parse(notification.config), `[${this.name}][${this.url}] ${certType} certificate ${certCN} will expire in ${daysRemaining} days`);
|
||||||
sent = true;
|
sent = true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error("monitor", "Cannot send cert notification to " + notification.name);
|
log.error("monitor", "Cannot send cert notification to " + notification.name);
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
const { Liquid } = require("liquidjs");
|
||||||
|
const { DOWN } = require("../../src/util");
|
||||||
|
|
||||||
class NotificationProvider {
|
class NotificationProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,6 +52,50 @@ class NotificationProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a message template with notification context
|
||||||
|
* @param {string} template the template
|
||||||
|
* @param {string} msg the message that will be included in the context
|
||||||
|
* @param {?object} monitorJSON Monitor details (For Up/Down/Cert-Expiry only)
|
||||||
|
* @param {?object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||||
|
* @returns {Promise<string>} rendered template
|
||||||
|
*/
|
||||||
|
async renderTemplate(template, msg, monitorJSON, heartbeatJSON) {
|
||||||
|
const engine = new Liquid();
|
||||||
|
const parsedTpl = engine.parse(template);
|
||||||
|
|
||||||
|
// Let's start with dummy values to simplify code
|
||||||
|
let monitorName = "Monitor Name not available";
|
||||||
|
let monitorHostnameOrURL = "testing.hostname";
|
||||||
|
|
||||||
|
if (monitorJSON !== null) {
|
||||||
|
monitorName = monitorJSON["name"];
|
||||||
|
monitorHostnameOrURL = this.extractAddress(monitorJSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
let serviceStatus = "⚠️ Test";
|
||||||
|
if (heartbeatJSON !== null) {
|
||||||
|
serviceStatus = (heartbeatJSON["status"] === DOWN) ? "🔴 Down" : "✅ Up";
|
||||||
|
}
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
// for v1 compatibility, to be removed in v3
|
||||||
|
"STATUS": serviceStatus,
|
||||||
|
"NAME": monitorName,
|
||||||
|
"HOSTNAME_OR_URL": monitorHostnameOrURL,
|
||||||
|
|
||||||
|
// variables which are officially supported
|
||||||
|
"status": serviceStatus,
|
||||||
|
"name": monitorName,
|
||||||
|
"hostnameOrURL": monitorHostnameOrURL,
|
||||||
|
monitorJSON,
|
||||||
|
heartbeatJSON,
|
||||||
|
msg,
|
||||||
|
};
|
||||||
|
|
||||||
|
return engine.render(parsedTpl, context);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throws an error
|
* Throws an error
|
||||||
* @param {any} error The error to throw
|
* @param {any} error The error to throw
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
const nodemailer = require("nodemailer");
|
const nodemailer = require("nodemailer");
|
||||||
const NotificationProvider = require("./notification-provider");
|
const NotificationProvider = require("./notification-provider");
|
||||||
const { DOWN } = require("../../src/util");
|
|
||||||
const { Liquid } = require("liquidjs");
|
|
||||||
|
|
||||||
class SMTP extends NotificationProvider {
|
class SMTP extends NotificationProvider {
|
||||||
name = "smtp";
|
name = "smtp";
|
||||||
|
@ -53,15 +51,11 @@ class SMTP extends NotificationProvider {
|
||||||
const customSubject = notification.customSubject?.trim() || "";
|
const customSubject = notification.customSubject?.trim() || "";
|
||||||
const customBody = notification.customBody?.trim() || "";
|
const customBody = notification.customBody?.trim() || "";
|
||||||
|
|
||||||
const context = this.generateContext(msg, monitorJSON, heartbeatJSON);
|
|
||||||
const engine = new Liquid();
|
|
||||||
if (customSubject !== "") {
|
if (customSubject !== "") {
|
||||||
const tpl = engine.parse(customSubject);
|
subject = await this.renderTemplate(customSubject, msg, monitorJSON, heartbeatJSON);
|
||||||
subject = await engine.render(tpl, context);
|
|
||||||
}
|
}
|
||||||
if (customBody !== "") {
|
if (customBody !== "") {
|
||||||
const tpl = engine.parse(customBody);
|
body = await this.renderTemplate(customBody, msg, monitorJSON, heartbeatJSON);
|
||||||
body = await engine.render(tpl, context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,43 +72,6 @@ class SMTP extends NotificationProvider {
|
||||||
|
|
||||||
return okMsg;
|
return okMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate context for LiquidJS
|
|
||||||
* @param {string} msg the message that will be included in the context
|
|
||||||
* @param {?object} monitorJSON Monitor details (For Up/Down/Cert-Expiry only)
|
|
||||||
* @param {?object} heartbeatJSON Heartbeat details (For Up/Down only)
|
|
||||||
* @returns {{STATUS: string, status: string, HOSTNAME_OR_URL: string, hostnameOrUrl: string, NAME: string, name: string, monitorJSON: ?object, heartbeatJSON: ?object, msg: string}} the context
|
|
||||||
*/
|
|
||||||
generateContext(msg, monitorJSON, heartbeatJSON) {
|
|
||||||
// Let's start with dummy values to simplify code
|
|
||||||
let monitorName = "Monitor Name not available";
|
|
||||||
let monitorHostnameOrURL = "testing.hostname";
|
|
||||||
|
|
||||||
if (monitorJSON !== null) {
|
|
||||||
monitorName = monitorJSON["name"];
|
|
||||||
monitorHostnameOrURL = this.extractAddress(monitorJSON);
|
|
||||||
}
|
|
||||||
|
|
||||||
let serviceStatus = "⚠️ Test";
|
|
||||||
if (heartbeatJSON !== null) {
|
|
||||||
serviceStatus = (heartbeatJSON["status"] === DOWN) ? "🔴 Down" : "✅ Up";
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
// for v1 compatibility, to be removed in v3
|
|
||||||
"STATUS": serviceStatus,
|
|
||||||
"NAME": monitorName,
|
|
||||||
"HOSTNAME_OR_URL": monitorHostnameOrURL,
|
|
||||||
|
|
||||||
// variables which are officially supported
|
|
||||||
"status": serviceStatus,
|
|
||||||
"name": monitorName,
|
|
||||||
"hostnameOrURL": monitorHostnameOrURL,
|
|
||||||
monitorJSON,
|
|
||||||
heartbeatJSON,
|
|
||||||
msg,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = SMTP;
|
module.exports = SMTP;
|
||||||
|
|
|
@ -22,6 +22,14 @@ class Telegram extends NotificationProvider {
|
||||||
params.message_thread_id = notification.telegramMessageThreadID;
|
params.message_thread_id = notification.telegramMessageThreadID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (notification.telegramUseTemplate) {
|
||||||
|
params.text = await this.renderTemplate(notification.telegramTemplate, msg, monitorJSON, heartbeatJSON);
|
||||||
|
|
||||||
|
if (notification.telegramTemplateParseMode !== "plain") {
|
||||||
|
params.parse_mode = notification.telegramTemplateParseMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await axios.get(`${url}/bot${notification.telegramBotToken}/sendMessage`, {
|
await axios.get(`${url}/bot${notification.telegramBotToken}/sendMessage`, {
|
||||||
params: params,
|
params: params,
|
||||||
});
|
});
|
||||||
|
|
40
server/notification-providers/waha.js
Normal file
40
server/notification-providers/waha.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
class WAHA extends NotificationProvider {
|
||||||
|
name = "waha";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
const okMsg = "Sent Successfully.";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const config = {
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Api-Key": notification.wahaApiKey,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = {
|
||||||
|
"session": notification.wahaSession,
|
||||||
|
"chatId": notification.wahaChatId,
|
||||||
|
"text": msg,
|
||||||
|
};
|
||||||
|
|
||||||
|
let url = notification.wahaApiUrl.replace(/([^/])\/+$/, "$1") + "/api/sendText";
|
||||||
|
|
||||||
|
await axios.post(url, data, config);
|
||||||
|
|
||||||
|
return okMsg;
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = WAHA;
|
|
@ -1,7 +1,6 @@
|
||||||
const NotificationProvider = require("./notification-provider");
|
const NotificationProvider = require("./notification-provider");
|
||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
const FormData = require("form-data");
|
const FormData = require("form-data");
|
||||||
const { Liquid } = require("liquidjs");
|
|
||||||
|
|
||||||
class Webhook extends NotificationProvider {
|
class Webhook extends NotificationProvider {
|
||||||
name = "webhook";
|
name = "webhook";
|
||||||
|
@ -28,17 +27,7 @@ class Webhook extends NotificationProvider {
|
||||||
config.headers = formData.getHeaders();
|
config.headers = formData.getHeaders();
|
||||||
data = formData;
|
data = formData;
|
||||||
} else if (notification.webhookContentType === "custom") {
|
} else if (notification.webhookContentType === "custom") {
|
||||||
// Initialize LiquidJS and parse the custom Body Template
|
data = await this.renderTemplate(notification.webhookCustomBody, msg, monitorJSON, heartbeatJSON);
|
||||||
const engine = new Liquid();
|
|
||||||
const tpl = engine.parse(notification.webhookCustomBody);
|
|
||||||
|
|
||||||
// Insert templated values into Body
|
|
||||||
data = await engine.render(tpl,
|
|
||||||
{
|
|
||||||
msg,
|
|
||||||
heartbeatJSON,
|
|
||||||
monitorJSON
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notification.webhookAdditionalHeaders) {
|
if (notification.webhookAdditionalHeaders) {
|
||||||
|
|
57
server/notification-providers/yzj.js
Normal file
57
server/notification-providers/yzj.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const { DOWN, UP } = require("../../src/util");
|
||||||
|
const { default: axios } = require("axios");
|
||||||
|
|
||||||
|
class YZJ extends NotificationProvider {
|
||||||
|
name = "YZJ";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||||
|
let okMsg = "Sent Successfully.";
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (heartbeatJSON !== null) {
|
||||||
|
msg = `${this.statusToString(heartbeatJSON["status"])} ${monitorJSON["name"]} \n> ${heartbeatJSON["msg"]}\n> Time (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const params = {
|
||||||
|
content: msg
|
||||||
|
};
|
||||||
|
// yzjtype=0 => general robot
|
||||||
|
const url = `${notification.yzjWebHookUrl}?yzjtype=0&yzjtoken=${notification.yzjToken}`;
|
||||||
|
|
||||||
|
const result = await axios.post(url, params, config);
|
||||||
|
if (!result.data?.success) {
|
||||||
|
throw new Error(result.data?.errmsg ?? "yzj's server did not respond with the expected result");
|
||||||
|
}
|
||||||
|
return okMsg;
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert status constant to string
|
||||||
|
* @param {string} status The status constant
|
||||||
|
* @returns {string} status
|
||||||
|
*/
|
||||||
|
statusToString(status) {
|
||||||
|
switch (status) {
|
||||||
|
case DOWN:
|
||||||
|
return "❌";
|
||||||
|
case UP:
|
||||||
|
return "✅";
|
||||||
|
default:
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = YZJ;
|
|
@ -64,11 +64,13 @@ const ServerChan = require("./notification-providers/serverchan");
|
||||||
const ZohoCliq = require("./notification-providers/zoho-cliq");
|
const ZohoCliq = require("./notification-providers/zoho-cliq");
|
||||||
const SevenIO = require("./notification-providers/sevenio");
|
const SevenIO = require("./notification-providers/sevenio");
|
||||||
const Whapi = require("./notification-providers/whapi");
|
const Whapi = require("./notification-providers/whapi");
|
||||||
|
const WAHA = require("./notification-providers/waha");
|
||||||
const GtxMessaging = require("./notification-providers/gtx-messaging");
|
const GtxMessaging = require("./notification-providers/gtx-messaging");
|
||||||
const Cellsynt = require("./notification-providers/cellsynt");
|
const Cellsynt = require("./notification-providers/cellsynt");
|
||||||
const Onesender = require("./notification-providers/onesender");
|
const Onesender = require("./notification-providers/onesender");
|
||||||
const Wpush = require("./notification-providers/wpush");
|
const Wpush = require("./notification-providers/wpush");
|
||||||
const SendGrid = require("./notification-providers/send-grid");
|
const SendGrid = require("./notification-providers/send-grid");
|
||||||
|
const YZJ = require("./notification-providers/yzj");
|
||||||
|
|
||||||
class Notification {
|
class Notification {
|
||||||
|
|
||||||
|
@ -151,10 +153,12 @@ class Notification {
|
||||||
new ZohoCliq(),
|
new ZohoCliq(),
|
||||||
new SevenIO(),
|
new SevenIO(),
|
||||||
new Whapi(),
|
new Whapi(),
|
||||||
|
new WAHA(),
|
||||||
new GtxMessaging(),
|
new GtxMessaging(),
|
||||||
new Cellsynt(),
|
new Cellsynt(),
|
||||||
new Wpush(),
|
new Wpush(),
|
||||||
new SendGrid()
|
new SendGrid(),
|
||||||
|
new YZJ()
|
||||||
];
|
];
|
||||||
for (let item of list) {
|
for (let item of list) {
|
||||||
if (! item.name) {
|
if (! item.name) {
|
||||||
|
|
|
@ -163,6 +163,7 @@ export default {
|
||||||
"ZohoCliq": "ZohoCliq",
|
"ZohoCliq": "ZohoCliq",
|
||||||
"SevenIO": "SevenIO",
|
"SevenIO": "SevenIO",
|
||||||
"whapi": "WhatsApp (Whapi)",
|
"whapi": "WhatsApp (Whapi)",
|
||||||
|
"waha": "WhatsApp (WAHA)",
|
||||||
"gtxmessaging": "GtxMessaging",
|
"gtxmessaging": "GtxMessaging",
|
||||||
"Cellsynt": "Cellsynt",
|
"Cellsynt": "Cellsynt",
|
||||||
"SendGrid": "SendGrid"
|
"SendGrid": "SendGrid"
|
||||||
|
@ -183,6 +184,7 @@ export default {
|
||||||
"ServerChan": "ServerChan (Server酱)",
|
"ServerChan": "ServerChan (Server酱)",
|
||||||
"smsc": "SMSC",
|
"smsc": "SMSC",
|
||||||
"WPush": "WPush(wpush.cn)",
|
"WPush": "WPush(wpush.cn)",
|
||||||
|
"YZJ": "YZJ (云之家自定义机器人)"
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sort by notification name
|
// Sort by notification name
|
||||||
|
|
75
src/components/TemplatedInput.vue
Normal file
75
src/components/TemplatedInput.vue
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
<template>
|
||||||
|
<div class="form-text mb-2">
|
||||||
|
<i18n-t tag="div" keypath="liquidIntroduction">
|
||||||
|
<a href="https://liquidjs.com/" target="_blank">{{ $t("documentation") }}</a>
|
||||||
|
</i18n-t>
|
||||||
|
|
||||||
|
<code v-pre>{{ msg }}</code>: {{ $t("templateMsg") }}<br />
|
||||||
|
<code v-pre>{{ name }}</code>: {{ $t("templateServiceName") }}<br />
|
||||||
|
<code v-pre>{{ status }}</code>: {{ $t("templateStatus") }}<br />
|
||||||
|
<code v-pre>{{ hostnameOrURL }}</code>: {{ $t("templateHostnameOrURL") }}<br />
|
||||||
|
<code v-pre>{{ heartbeatJSON }}</code>: {{ $t("templateHeartbeatJSON") }} <b>({{ $t("templateLimitedToUpDownNotifications") }})</b><br />
|
||||||
|
<code v-pre>{{ monitorJSON }}</code>: {{ $t("templateMonitorJSON") }} <b>({{ $t("templateLimitedToUpDownCertNotifications") }})</b><br />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input
|
||||||
|
:id="id"
|
||||||
|
ref="templatedInput"
|
||||||
|
v-model="model"
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:required="required"
|
||||||
|
autocomplete="false"
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
/**
|
||||||
|
* The value of the templated input.
|
||||||
|
*/
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: ""
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* id for the templated input.
|
||||||
|
*/
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Whether the templated input is required.
|
||||||
|
* @example true
|
||||||
|
*/
|
||||||
|
required: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Placeholder text for the templated input.
|
||||||
|
*/
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: ""
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: [ "update:modelValue" ],
|
||||||
|
computed: {
|
||||||
|
/**
|
||||||
|
* Send value update to parent on change.
|
||||||
|
*/
|
||||||
|
model: {
|
||||||
|
get() {
|
||||||
|
return this.modelValue;
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
this.$emit("update:modelValue", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
80
src/components/TemplatedTextarea.vue
Normal file
80
src/components/TemplatedTextarea.vue
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
<template>
|
||||||
|
<div class="form-text mb-2">
|
||||||
|
<i18n-t tag="div" keypath="liquidIntroduction">
|
||||||
|
<a href="https://liquidjs.com/" target="_blank">{{ $t("documentation") }}</a>
|
||||||
|
</i18n-t>
|
||||||
|
|
||||||
|
<code v-pre>{{ msg }}</code>: {{ $t("templateMsg") }}<br />
|
||||||
|
<code v-pre>{{ name }}</code>: {{ $t("templateServiceName") }}<br />
|
||||||
|
<code v-pre>{{ status }}</code>: {{ $t("templateStatus") }}<br />
|
||||||
|
<code v-pre>{{ hostnameOrURL }}</code>: {{ $t("templateHostnameOrURL") }}<br />
|
||||||
|
<code v-pre>{{ heartbeatJSON }}</code>: {{ $t("templateHeartbeatJSON") }} <b>({{ $t("templateLimitedToUpDownNotifications") }})</b><br />
|
||||||
|
<code v-pre>{{ monitorJSON }}</code>: {{ $t("templateMonitorJSON") }} <b>({{ $t("templateLimitedToUpDownCertNotifications") }})</b><br />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<textarea
|
||||||
|
:id="id"
|
||||||
|
ref="templatedTextarea"
|
||||||
|
v-model="model"
|
||||||
|
class="form-control"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:required="required"
|
||||||
|
autocomplete="false"
|
||||||
|
></textarea>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
/**
|
||||||
|
* The value of the templated textarea.
|
||||||
|
*/
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: ""
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* id for the templated textarea.
|
||||||
|
*/
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Whether the templated textarea is required.
|
||||||
|
* @example true
|
||||||
|
*/
|
||||||
|
required: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Placeholder text for the templated textarea.
|
||||||
|
*/
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: ""
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: [ "update:modelValue" ],
|
||||||
|
computed: {
|
||||||
|
/**
|
||||||
|
* Send value update to parent on change.
|
||||||
|
*/
|
||||||
|
model: {
|
||||||
|
get() {
|
||||||
|
return this.modelValue;
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
this.$emit("update:modelValue", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
textarea {
|
||||||
|
min-height: 150px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -67,25 +67,15 @@
|
||||||
<input id="to-bcc" v-model="$parent.notification.smtpBCC" type="text" class="form-control" autocomplete="false" :required="!hasRecipient">
|
<input id="to-bcc" v-model="$parent.notification.smtpBCC" type="text" class="form-control" autocomplete="false" :required="!hasRecipient">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="form-text">
|
|
||||||
<i18n-t tag="div" keypath="smtpLiquidIntroduction" class="form-text mb-3">
|
|
||||||
<a href="https://liquidjs.com/" target="_blank">{{ $t("documentation") }}</a>
|
|
||||||
</i18n-t>
|
|
||||||
<code v-pre>{{name}}</code>: {{ $t("emailTemplateServiceName") }}<br />
|
|
||||||
<code v-pre>{{msg}}</code>: {{ $t("emailTemplateMsg") }}<br />
|
|
||||||
<code v-pre>{{status}}</code>: {{ $t("emailTemplateStatus") }}<br />
|
|
||||||
<code v-pre>{{heartbeatJSON}}</code>: {{ $t("emailTemplateHeartbeatJSON") }}<b>{{ $t("emailTemplateLimitedToUpDownNotification") }}</b><br />
|
|
||||||
<code v-pre>{{monitorJSON}}</code>: {{ $t("emailTemplateMonitorJSON") }} <b>{{ $t("emailTemplateLimitedToUpDownNotification") }}</b><br />
|
|
||||||
<code v-pre>{{hostnameOrURL}}</code>: {{ $t("emailTemplateHostnameOrURL") }}<br />
|
|
||||||
</p>
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="subject-email" class="form-label">{{ $t("emailCustomSubject") }}</label>
|
<label for="subject-email" class="form-label">{{ $t("emailCustomSubject") }}</label>
|
||||||
<input id="subject-email" v-model="$parent.notification.customSubject" type="text" class="form-control" autocomplete="false" placeholder="">
|
<TemplatedInput id="subject-email" v-model="$parent.notification.customSubject" :required="false" placeholder=""></TemplatedInput>
|
||||||
<div class="form-text">{{ $t("leave blank for default subject") }}</div>
|
<div class="form-text">{{ $t("leave blank for default subject") }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="body-email" class="form-label">{{ $t("emailCustomBody") }}</label>
|
<label for="body-email" class="form-label">{{ $t("emailCustomBody") }}</label>
|
||||||
<textarea id="body-email" v-model="$parent.notification.customBody" type="text" class="form-control" autocomplete="false" placeholder=""></textarea>
|
<TemplatedTextarea id="body-email" v-model="$parent.notification.customBody" :required="false" placeholder=""></TemplatedTextarea>
|
||||||
<div class="form-text">{{ $t("leave blank for default body") }}</div>
|
<div class="form-text">{{ $t("leave blank for default body") }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -124,11 +114,15 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import HiddenInput from "../HiddenInput.vue";
|
import HiddenInput from "../HiddenInput.vue";
|
||||||
|
import TemplatedInput from "../TemplatedInput.vue";
|
||||||
|
import TemplatedTextarea from "../TemplatedTextarea.vue";
|
||||||
import ToggleSection from "../ToggleSection.vue";
|
import ToggleSection from "../ToggleSection.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
HiddenInput,
|
HiddenInput,
|
||||||
|
TemplatedInput,
|
||||||
|
TemplatedTextarea,
|
||||||
ToggleSection,
|
ToggleSection,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
@ -36,7 +36,42 @@
|
||||||
<label for="server_url" class="form-label">{{ $t("telegramServerUrl") }}</label>
|
<label for="server_url" class="form-label">{{ $t("telegramServerUrl") }}</label>
|
||||||
<input id="server_url" v-model="$parent.notification.telegramServerUrl" type="text" class="form-control">
|
<input id="server_url" v-model="$parent.notification.telegramServerUrl" type="text" class="form-control">
|
||||||
<p class="form-text">{{ $t("telegramServerUrlDescription") }}</p>
|
<p class="form-text">{{ $t("telegramServerUrlDescription") }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input v-model="$parent.notification.telegramUseTemplate" class="form-check-input" type="checkbox">
|
||||||
|
<label class="form-check-label">{{ $t("telegramUseTemplate") }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-text">
|
||||||
|
{{ $t("telegramUseTemplateDescription") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-if="$parent.notification.telegramUseTemplate">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="message_parse_mode">{{ $t("Message Format") }}</label>
|
||||||
|
<select
|
||||||
|
id="message_parse_mode"
|
||||||
|
v-model="$parent.notification.telegramTemplateParseMode"
|
||||||
|
class="form-select"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<option value="plain">{{ $t("Plain Text") }}</option>
|
||||||
|
<option value="HTML">HTML</option>
|
||||||
|
<option value="MarkdownV2">MarkdownV2</option>
|
||||||
|
</select>
|
||||||
|
<i18n-t tag="p" keypath="telegramTemplateFormatDescription" class="form-text">
|
||||||
|
<a href="https://core.telegram.org/bots/api#formatting-options" target="_blank">{{ $t("documentation") }}</a>
|
||||||
|
</i18n-t>
|
||||||
|
|
||||||
|
<label class="form-label" for="message_template">{{ $t('Message Template') }}</label>
|
||||||
|
<TemplatedTextarea id="message_template" v-model="$parent.notification.telegramTemplate" :required="true" :placeholder="telegramTemplatedTextareaPlaceholder"></TemplatedTextarea>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
<div class="form-check form-switch">
|
<div class="form-check form-switch">
|
||||||
<input v-model="$parent.notification.telegramSendSilently" class="form-check-input" type="checkbox">
|
<input v-model="$parent.notification.telegramSendSilently" class="form-check-input" type="checkbox">
|
||||||
<label class="form-check-label">{{ $t("telegramSendSilently") }}</label>
|
<label class="form-check-label">{{ $t("telegramSendSilently") }}</label>
|
||||||
|
@ -61,15 +96,28 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import HiddenInput from "../HiddenInput.vue";
|
import HiddenInput from "../HiddenInput.vue";
|
||||||
|
import TemplatedTextarea from "../TemplatedTextarea.vue";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
HiddenInput,
|
HiddenInput,
|
||||||
|
TemplatedTextarea,
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$parent.notification.telegramServerUrl ||= "https://api.telegram.org";
|
this.$parent.notification.telegramServerUrl ||= "https://api.telegram.org";
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
telegramTemplatedTextareaPlaceholder() {
|
||||||
|
return this.$t("Example:", [
|
||||||
|
`
|
||||||
|
Uptime Kuma Alert{% if monitorJSON %} - {{ monitorJSON['name'] }}{% endif %}
|
||||||
|
|
||||||
|
{{ msg }}
|
||||||
|
`,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
/**
|
||||||
* Get the URL for telegram updates
|
* Get the URL for telegram updates
|
||||||
|
@ -123,3 +171,9 @@ export default {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
textarea {
|
||||||
|
min-height: 150px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
38
src/components/notifications/WAHA.vue
Normal file
38
src/components/notifications/WAHA.vue
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<template>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="waha-api-url" class="form-label">{{ $t("API URL") }}</label>
|
||||||
|
<input id="waha-api-url" v-model="$parent.notification.wahaApiUrl" placeholder="http://localhost:3000/" type="url" class="form-control" required>
|
||||||
|
<div class="form-text">{{ $t("wayToGetWahaApiUrl") }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="waha-api-key" class="form-label">{{ $t("API Key") }}</label>
|
||||||
|
<HiddenInput id="waha-api-key" v-model="$parent.notification.wahaApiKey" :required="false" autocomplete="new-password"></HiddenInput>
|
||||||
|
<div class="form-text">{{ $t("wayToGetWahaApiKey") }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="waha-session" class="form-label">{{ $t("wahaSession") }}</label>
|
||||||
|
<input id="waha-session" v-model="$parent.notification.wahaSession" type="text" placeholder="default" class="form-control" required>
|
||||||
|
<div class="form-text">{{ $t("wayToGetWahaSession") }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="waha-chat-id" class="form-label">{{ $t("wahaChatId") }}</label>
|
||||||
|
<input id="waha-chat-id" v-model="$parent.notification.wahaChatId" type="text" pattern="^[\d-]{10,31}$" class="form-control" required>
|
||||||
|
<div class="form-text">{{ $t("wayToWriteWahaChatId", ["00117612345678", "00117612345678@c.us", "123456789012345678@g.us"]) }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<i18n-t tag="div" keypath="More info on:" class="mb-3 form-text">
|
||||||
|
<a href="https://waha.devlike.pro/" target="_blank">https://waha.devlike.pro/</a>
|
||||||
|
</i18n-t>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import HiddenInput from "../HiddenInput.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
HiddenInput,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -32,20 +32,7 @@
|
||||||
</template>
|
</template>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
<template v-else-if="$parent.notification.webhookContentType == 'custom'">
|
<template v-else-if="$parent.notification.webhookContentType == 'custom'">
|
||||||
<i18n-t tag="div" keypath="liquidIntroduction" class="form-text">
|
<TemplatedTextarea id="customBody" v-model="$parent.notification.webhookCustomBody" :required="true" :placeholder="customBodyPlaceholder"></TemplatedTextarea>
|
||||||
<a href="https://liquidjs.com/" target="_blank">{{ $t("documentation") }}</a>
|
|
||||||
</i18n-t>
|
|
||||||
<code v-pre>{{msg}}</code>: {{ $t("templateMsg") }}<br />
|
|
||||||
<code v-pre>{{heartbeatJSON}}</code>: {{ $t("templateHeartbeatJSON") }} <b>({{ $t("templateLimitedToUpDownNotifications") }})</b><br />
|
|
||||||
<code v-pre>{{monitorJSON}}</code>: {{ $t("templateMonitorJSON") }} <b>({{ $t("templateLimitedToUpDownCertNotifications") }})</b><br />
|
|
||||||
|
|
||||||
<textarea
|
|
||||||
id="customBody"
|
|
||||||
v-model="$parent.notification.webhookCustomBody"
|
|
||||||
class="form-control"
|
|
||||||
:placeholder="customBodyPlaceholder"
|
|
||||||
required
|
|
||||||
></textarea>
|
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -67,7 +54,12 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import TemplatedTextarea from "../TemplatedTextarea.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
TemplatedTextarea,
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showAdditionalHeadersField: this.$parent.notification.webhookAdditionalHeaders != null,
|
showAdditionalHeadersField: this.$parent.notification.webhookAdditionalHeaders != null,
|
||||||
|
|
19
src/components/notifications/YZJ.vue
Normal file
19
src/components/notifications/YZJ.vue
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<template>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="yzjWebHookUrl" class="form-label">{{ $t("YZJ Webhook URL") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||||
|
<input id="yzjWebHookUrl" v-model="$parent.notification.yzjWebHookUrl" type="url" class="form-control" required />
|
||||||
|
<i18n-t class="form-text" keypath="wayToGetTeamsURL">
|
||||||
|
<a href="https://www.yunzhijia.com/opendocs/docs.html#/tutorial/index/robot" target="_blank">{{ $t("here") }}</a>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="yzjToken" class="form-label">{{ $t("YZJ Robot Token") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||||
|
<HiddenInput id="yzjToken" v-model="$parent.notification.yzjToken" :required="true" autocomplete="new-password"></HiddenInput>
|
||||||
|
<i18n-t class="form-text" keypath="wayToGetLineNotifyToken">
|
||||||
|
<a href="https://www.yunzhijia.com/opendocs/docs.html#/server-api/im/index?id=%e6%8e%a5%e5%8f%a3%e5%9c%b0%e5%9d%80%e5%92%8c%e6%8e%88%e6%9d%83%e7%a0%81" target="_blank">{{ $t("here") }}</a>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import HiddenInput from "../HiddenInput.vue";
|
||||||
|
</script>
|
|
@ -63,10 +63,12 @@ import ZohoCliq from "./ZohoCliq.vue";
|
||||||
import Splunk from "./Splunk.vue";
|
import Splunk from "./Splunk.vue";
|
||||||
import SevenIO from "./SevenIO.vue";
|
import SevenIO from "./SevenIO.vue";
|
||||||
import Whapi from "./Whapi.vue";
|
import Whapi from "./Whapi.vue";
|
||||||
|
import WAHA from "./WAHA.vue";
|
||||||
import Cellsynt from "./Cellsynt.vue";
|
import Cellsynt from "./Cellsynt.vue";
|
||||||
import WPush from "./WPush.vue";
|
import WPush from "./WPush.vue";
|
||||||
import SIGNL4 from "./SIGNL4.vue";
|
import SIGNL4 from "./SIGNL4.vue";
|
||||||
import SendGrid from "./SendGrid.vue";
|
import SendGrid from "./SendGrid.vue";
|
||||||
|
import YZJ from "./YZJ.vue";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage all notification form.
|
* Manage all notification form.
|
||||||
|
@ -138,10 +140,12 @@ const NotificationFormList = {
|
||||||
"ZohoCliq": ZohoCliq,
|
"ZohoCliq": ZohoCliq,
|
||||||
"SevenIO": SevenIO,
|
"SevenIO": SevenIO,
|
||||||
"whapi": Whapi,
|
"whapi": Whapi,
|
||||||
|
"waha": WAHA,
|
||||||
"gtxmessaging": GtxMessaging,
|
"gtxmessaging": GtxMessaging,
|
||||||
"Cellsynt": Cellsynt,
|
"Cellsynt": Cellsynt,
|
||||||
"WPush": WPush,
|
"WPush": WPush,
|
||||||
"SendGrid": SendGrid,
|
"SendGrid": SendGrid,
|
||||||
|
"YZJ": YZJ,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default NotificationFormList;
|
export default NotificationFormList;
|
||||||
|
|
|
@ -231,6 +231,9 @@
|
||||||
"templateMonitorJSON": "object describing the monitor",
|
"templateMonitorJSON": "object describing the monitor",
|
||||||
"templateLimitedToUpDownCertNotifications": "only available for UP/DOWN/Certificate expiry notifications",
|
"templateLimitedToUpDownCertNotifications": "only available for UP/DOWN/Certificate expiry notifications",
|
||||||
"templateLimitedToUpDownNotifications": "only available for UP/DOWN notifications",
|
"templateLimitedToUpDownNotifications": "only available for UP/DOWN notifications",
|
||||||
|
"templateServiceName": "service name",
|
||||||
|
"templateHostnameOrURL": "hostname or URL",
|
||||||
|
"templateStatus": "status",
|
||||||
"webhookAdditionalHeadersTitle": "Additional Headers",
|
"webhookAdditionalHeadersTitle": "Additional Headers",
|
||||||
"webhookAdditionalHeadersDesc": "Sets additional headers sent with the webhook. Each header should be defined as a JSON key/value.",
|
"webhookAdditionalHeadersDesc": "Sets additional headers sent with the webhook. Each header should be defined as a JSON key/value.",
|
||||||
"webhookBodyPresetOption": "Preset - {0}",
|
"webhookBodyPresetOption": "Preset - {0}",
|
||||||
|
@ -421,6 +424,9 @@
|
||||||
"telegramSendSilentlyDescription": "Sends the message silently. Users will receive a notification with no sound.",
|
"telegramSendSilentlyDescription": "Sends the message silently. Users will receive a notification with no sound.",
|
||||||
"telegramProtectContent": "Protect Forwarding/Saving",
|
"telegramProtectContent": "Protect Forwarding/Saving",
|
||||||
"telegramProtectContentDescription": "If enabled, the bot messages in Telegram will be protected from forwarding and saving.",
|
"telegramProtectContentDescription": "If enabled, the bot messages in Telegram will be protected from forwarding and saving.",
|
||||||
|
"telegramUseTemplate": "Use custom message template",
|
||||||
|
"telegramUseTemplateDescription": "If enabled, the message will be sent using a custom template.",
|
||||||
|
"telegramTemplateFormatDescription": "Telegram allows using different markup languages for messages, see Telegram {0} for specifc details.",
|
||||||
"supportTelegramChatID": "Support Direct Chat / Group / Channel's Chat ID",
|
"supportTelegramChatID": "Support Direct Chat / Group / Channel's Chat ID",
|
||||||
"wayToGetTelegramChatID": "You can get your chat ID by sending a message to the bot and going to this URL to view the chat_id:",
|
"wayToGetTelegramChatID": "You can get your chat ID by sending a message to the bot and going to this URL to view the chat_id:",
|
||||||
"telegramServerUrl": "(Optional) Server Url",
|
"telegramServerUrl": "(Optional) Server Url",
|
||||||
|
@ -521,9 +527,6 @@
|
||||||
"leave blank for default subject": "leave blank for default subject",
|
"leave blank for default subject": "leave blank for default subject",
|
||||||
"emailCustomBody": "Custom Body",
|
"emailCustomBody": "Custom Body",
|
||||||
"leave blank for default body": "leave blank for default body",
|
"leave blank for default body": "leave blank for default body",
|
||||||
"emailTemplateServiceName": "Service Name",
|
|
||||||
"emailTemplateHostnameOrURL": "Hostname or URL",
|
|
||||||
"emailTemplateStatus": "Status",
|
|
||||||
"emailTemplateMonitorJSON": "object describing the monitor",
|
"emailTemplateMonitorJSON": "object describing the monitor",
|
||||||
"emailTemplateHeartbeatJSON": "object describing the heartbeat",
|
"emailTemplateHeartbeatJSON": "object describing the heartbeat",
|
||||||
"emailTemplateMsg": "message of the notification",
|
"emailTemplateMsg": "message of the notification",
|
||||||
|
@ -1053,5 +1056,16 @@
|
||||||
"RabbitMQ Password": "RabbitMQ Password",
|
"RabbitMQ Password": "RabbitMQ Password",
|
||||||
"rabbitmqHelpText": "To use the monitor, you will need to enable the Management Plugin in your RabbitMQ setup. For more information, please consult the {rabitmq_documentation}.",
|
"rabbitmqHelpText": "To use the monitor, you will need to enable the Management Plugin in your RabbitMQ setup. For more information, please consult the {rabitmq_documentation}.",
|
||||||
"SendGrid API Key": "SendGrid API Key",
|
"SendGrid API Key": "SendGrid API Key",
|
||||||
"Separate multiple email addresses with commas": "Separate multiple email addresses with commas"
|
"Separate multiple email addresses with commas": "Separate multiple email addresses with commas",
|
||||||
|
"wahaSession": "Session",
|
||||||
|
"wahaChatId": "Chat ID (Phone Number / Contact ID / Group ID)",
|
||||||
|
"wayToGetWahaApiUrl": "Your WAHA Instance URL.",
|
||||||
|
"wayToGetWahaApiKey": "API Key is WHATSAPP_API_KEY environment variable value you used to run WAHA.",
|
||||||
|
"wayToGetWahaSession": "From this session WAHA sends notifications to Chat ID. You can find it in WAHA Dashboard.",
|
||||||
|
"wayToWriteWahaChatId": "The phone number with the international prefix, but without the plus sign at the start ({0}), the Contact ID ({1}) or the Group ID ({2}). Notifications are sent to this Chat ID from WAHA Session.",
|
||||||
|
"YZJ Webhook URL": "YZJ Webhook URL",
|
||||||
|
"YZJ Robot Token": "YZJ Robot token",
|
||||||
|
"Plain Text": "Plain Text",
|
||||||
|
"Message Template": "Message Template",
|
||||||
|
"Template Format": "Template Format"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue