Skip to content

Commit e83039f

Browse files
committed
Fix: reuse base template renderer and escape MarkdownV2 output
1 parent e69a427 commit e83039f

File tree

1 file changed

+42
-55
lines changed

1 file changed

+42
-55
lines changed

server/notification-providers/telegram.js

Lines changed: 42 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
const NotificationProvider = require("./notification-provider");
22
const axios = require("axios");
3-
const { Liquid } = require("liquidjs");
4-
const { DOWN } = require("../../src/util");
53

64
class Telegram extends NotificationProvider {
75
name = "telegram";
@@ -22,61 +20,29 @@ class Telegram extends NotificationProvider {
2220
}
2321

2422
/**
25-
* Renders template with optional MarkdownV2 escaping
26-
* @param {string} template The template
27-
* @param {string} msg Base message
28-
* @param {?object} monitorJSON Monitor details
29-
* @param {?object} heartbeatJSON Heartbeat details
30-
* @param {boolean} escapeMarkdown Whether to escape for MarkdownV2
31-
* @returns {Promise<string>} Rendered template
23+
* Recursively escapes string properties of an object for Telegram MarkdownV2
24+
* @param {object|string} obj Object or string to escape
25+
* @returns {object|string} Escaped object or string
3226
*/
33-
async renderTemplate(template, msg, monitorJSON, heartbeatJSON, escapeMarkdown = false) {
34-
const engine = new Liquid({
35-
root: "./no-such-directory-uptime-kuma",
36-
relativeReference: false,
37-
dynamicPartials: false,
38-
});
39-
40-
const parsedTpl = engine.parse(template);
41-
42-
// Defaults
43-
let monitorName = "Monitor Name not available";
44-
let monitorHostnameOrURL = "testing.hostname";
45-
46-
if (monitorJSON !== null) {
47-
monitorName = monitorJSON.name;
48-
monitorHostnameOrURL = this.extractAddress(monitorJSON);
49-
}
50-
51-
let serviceStatus = "⚠️ Test";
52-
if (heartbeatJSON !== null) {
53-
serviceStatus = heartbeatJSON.status === DOWN ? "🔴 Down" : "✅ Up";
27+
escapeObjectRecursive(obj) {
28+
if (typeof obj === "string") {
29+
return this.escapeMarkdownV2(obj);
5430
}
31+
if (typeof obj === "object" && obj !== null) {
32+
// Check if array
33+
if (Array.isArray(obj)) {
34+
return obj.map(item => this.escapeObjectRecursive(item));
35+
}
5536

56-
// Escape values only when MarkdownV2 is enabled
57-
if (escapeMarkdown) {
58-
msg = this.escapeMarkdownV2(msg);
59-
monitorName = this.escapeMarkdownV2(monitorName);
60-
monitorHostnameOrURL = this.escapeMarkdownV2(monitorHostnameOrURL);
61-
serviceStatus = this.escapeMarkdownV2(serviceStatus);
37+
const newObj = {};
38+
for (const key in obj) {
39+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
40+
newObj[key] = this.escapeObjectRecursive(obj[key]);
41+
}
42+
}
43+
return newObj;
6244
}
63-
64-
const context = {
65-
// v1 compatibility (remove in v3)
66-
STATUS: serviceStatus,
67-
NAME: monitorName,
68-
HOSTNAME_OR_URL: monitorHostnameOrURL,
69-
70-
// Official variables
71-
status: serviceStatus,
72-
name: monitorName,
73-
hostnameOrURL: monitorHostnameOrURL,
74-
monitorJSON,
75-
heartbeatJSON,
76-
msg,
77-
};
78-
79-
return engine.render(parsedTpl, context);
45+
return obj;
8046
}
8147

8248
/**
@@ -99,8 +65,29 @@ class Telegram extends NotificationProvider {
9965
}
10066

10167
if (notification.telegramUseTemplate) {
102-
const escapeMarkdown = notification.telegramTemplateParseMode === "MarkdownV2";
103-
params.text = await this.renderTemplate(notification.telegramTemplate, msg, monitorJSON, heartbeatJSON, escapeMarkdown);
68+
let monitorJSONCopy = monitorJSON;
69+
let heartbeatJSONCopy = heartbeatJSON;
70+
71+
if (notification.telegramTemplateParseMode === "MarkdownV2") {
72+
msg = this.escapeMarkdownV2(msg);
73+
74+
if (monitorJSONCopy) {
75+
monitorJSONCopy = this.escapeObjectRecursive(monitorJSONCopy);
76+
} else {
77+
// for testing monitorJSON is null, provide escaped defaults
78+
monitorJSONCopy = {
79+
name: this.escapeMarkdownV2("Monitor Name not available"),
80+
hostname: this.escapeMarkdownV2("testing.hostname"),
81+
url: this.escapeMarkdownV2("testing.hostname"),
82+
};
83+
}
84+
85+
if (heartbeatJSONCopy) {
86+
heartbeatJSONCopy = this.escapeObjectRecursive(heartbeatJSONCopy);
87+
}
88+
}
89+
90+
params.text = await this.renderTemplate(notification.telegramTemplate, msg, monitorJSONCopy, heartbeatJSONCopy);
10491

10592
if (notification.telegramTemplateParseMode !== "plain") {
10693
params.parse_mode = notification.telegramTemplateParseMode;

0 commit comments

Comments
 (0)