Fix: reuse base template renderer and escape MarkdownV2 output

This commit is contained in:
GivenBY 2026-01-03 23:05:36 +05:30
parent e69a427791
commit e83039f30b

View File

@ -1,7 +1,5 @@
const NotificationProvider = require("./notification-provider"); const NotificationProvider = require("./notification-provider");
const axios = require("axios"); const axios = require("axios");
const { Liquid } = require("liquidjs");
const { DOWN } = require("../../src/util");
class Telegram extends NotificationProvider { class Telegram extends NotificationProvider {
name = "telegram"; name = "telegram";
@ -22,61 +20,29 @@ class Telegram extends NotificationProvider {
} }
/** /**
* Renders template with optional MarkdownV2 escaping * Recursively escapes string properties of an object for Telegram MarkdownV2
* @param {string} template The template * @param {object|string} obj Object or string to escape
* @param {string} msg Base message * @returns {object|string} Escaped object or string
* @param {?object} monitorJSON Monitor details
* @param {?object} heartbeatJSON Heartbeat details
* @param {boolean} escapeMarkdown Whether to escape for MarkdownV2
* @returns {Promise<string>} Rendered template
*/ */
async renderTemplate(template, msg, monitorJSON, heartbeatJSON, escapeMarkdown = false) { escapeObjectRecursive(obj) {
const engine = new Liquid({ if (typeof obj === "string") {
root: "./no-such-directory-uptime-kuma", return this.escapeMarkdownV2(obj);
relativeReference: false,
dynamicPartials: false,
});
const parsedTpl = engine.parse(template);
// Defaults
let monitorName = "Monitor Name not available";
let monitorHostnameOrURL = "testing.hostname";
if (monitorJSON !== null) {
monitorName = monitorJSON.name;
monitorHostnameOrURL = this.extractAddress(monitorJSON);
} }
if (typeof obj === "object" && obj !== null) {
// Check if array
if (Array.isArray(obj)) {
return obj.map(item => this.escapeObjectRecursive(item));
}
let serviceStatus = "⚠️ Test"; const newObj = {};
if (heartbeatJSON !== null) { for (const key in obj) {
serviceStatus = heartbeatJSON.status === DOWN ? "🔴 Down" : "✅ Up"; if (Object.prototype.hasOwnProperty.call(obj, key)) {
newObj[key] = this.escapeObjectRecursive(obj[key]);
}
}
return newObj;
} }
return obj;
// Escape values only when MarkdownV2 is enabled
if (escapeMarkdown) {
msg = this.escapeMarkdownV2(msg);
monitorName = this.escapeMarkdownV2(monitorName);
monitorHostnameOrURL = this.escapeMarkdownV2(monitorHostnameOrURL);
serviceStatus = this.escapeMarkdownV2(serviceStatus);
}
const context = {
// v1 compatibility (remove in v3)
STATUS: serviceStatus,
NAME: monitorName,
HOSTNAME_OR_URL: monitorHostnameOrURL,
// Official variables
status: serviceStatus,
name: monitorName,
hostnameOrURL: monitorHostnameOrURL,
monitorJSON,
heartbeatJSON,
msg,
};
return engine.render(parsedTpl, context);
} }
/** /**
@ -99,8 +65,29 @@ class Telegram extends NotificationProvider {
} }
if (notification.telegramUseTemplate) { if (notification.telegramUseTemplate) {
const escapeMarkdown = notification.telegramTemplateParseMode === "MarkdownV2"; let monitorJSONCopy = monitorJSON;
params.text = await this.renderTemplate(notification.telegramTemplate, msg, monitorJSON, heartbeatJSON, escapeMarkdown); let heartbeatJSONCopy = heartbeatJSON;
if (notification.telegramTemplateParseMode === "MarkdownV2") {
msg = this.escapeMarkdownV2(msg);
if (monitorJSONCopy) {
monitorJSONCopy = this.escapeObjectRecursive(monitorJSONCopy);
} else {
// for testing monitorJSON is null, provide escaped defaults
monitorJSONCopy = {
name: this.escapeMarkdownV2("Monitor Name not available"),
hostname: this.escapeMarkdownV2("testing.hostname"),
url: this.escapeMarkdownV2("testing.hostname"),
};
}
if (heartbeatJSONCopy) {
heartbeatJSONCopy = this.escapeObjectRecursive(heartbeatJSONCopy);
}
}
params.text = await this.renderTemplate(notification.telegramTemplate, msg, monitorJSONCopy, heartbeatJSONCopy);
if (notification.telegramTemplateParseMode !== "plain") { if (notification.telegramTemplateParseMode !== "plain") {
params.parse_mode = notification.telegramTemplateParseMode; params.parse_mode = notification.telegramTemplateParseMode;