feat(discord): add custom message and format presets for notifications (#6843)

Co-authored-by: epifeny <epifeny@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Epifeny
2026-01-30 18:38:53 +02:00
committed by GitHub
parent 8b244d4fe9
commit aca6d02dc1
4 changed files with 107 additions and 2 deletions

View File

@@ -1,9 +1,10 @@
{
"description": "RDAP bootstrap file for Domain Name System registrations",
"publication": "2025-12-11T00:00:01Z",
"publication": "2026-01-30T00:00:01Z",
"services": [
[["kg"], ["http://rdap.cctld.kg/"]],
[["mg"], ["http://rdap.nic.mg/"]],
[["ng"], ["http://rdap.nic.net.ng/"]],
[["xn--kpry57d"], ["https://ccrdap.twnic.tw/taiwan/"]],
[["tw"], ["https://ccrdap.twnic.tw/tw/"]],
[["na"], ["https://keetmans.omadhina.co.na/"]],

View File

@@ -34,11 +34,23 @@ class Discord extends NotificationProvider {
webhookHasAvatar = true;
}
const messageFormat =
notification.discordMessageFormat || (notification.discordUseMessageTemplate ? "custom" : "normal");
// If heartbeatJSON is null, assume we're testing.
if (heartbeatJSON == null) {
let content = msg;
if (messageFormat === "minimalist") {
content = "Test: " + msg;
} else if (messageFormat === "custom") {
const customMessage = notification.discordMessageTemplate?.trim() || "";
if (customMessage !== "") {
content = await this.renderTemplate(customMessage, msg, monitorJSON, heartbeatJSON);
}
}
let discordtestdata = {
username: discordDisplayName,
content: msg,
content: content,
};
if (!webhookHasAvatar) {
discordtestdata.avatar_url = "https://github.com/louislam/uptime-kuma/raw/master/public/icon.png";
@@ -55,6 +67,57 @@ class Discord extends NotificationProvider {
// If heartbeatJSON is not null, we go into the normal alerting loop.
let addess = this.extractAddress(monitorJSON);
// Minimalist: status + name only (is down / is up; no "back up" — may be first trigger)
if (messageFormat === "minimalist") {
const content =
heartbeatJSON["status"] === DOWN
? "🔴 " + monitorJSON["name"] + " is down."
: "🟢 " + monitorJSON["name"] + " is up.";
let payload = {
username: discordDisplayName,
content: content,
};
if (!webhookHasAvatar) {
payload.avatar_url = "https://github.com/louislam/uptime-kuma/raw/master/public/icon.png";
}
if (notification.discordChannelType === "createNewForumPost") {
payload.thread_name = notification.postName;
}
if (notification.discordSuppressNotifications) {
payload.flags = SUPPRESS_NOTIFICATIONS_FLAG;
}
await axios.post(webhookUrl.toString(), payload, config);
return okMsg;
}
// Custom template: send only content (no embeds)
const useCustomTemplate =
messageFormat === "custom" && (notification.discordMessageTemplate?.trim() || "") !== "";
if (useCustomTemplate) {
const content = await this.renderTemplate(
notification.discordMessageTemplate.trim(),
msg,
monitorJSON,
heartbeatJSON
);
let payload = {
username: discordDisplayName,
content: content,
};
if (!webhookHasAvatar) {
payload.avatar_url = "https://github.com/louislam/uptime-kuma/raw/master/public/icon.png";
}
if (notification.discordChannelType === "createNewForumPost") {
payload.thread_name = notification.postName;
}
if (notification.discordSuppressNotifications) {
payload.flags = SUPPRESS_NOTIFICATIONS_FLAG;
}
await axios.post(webhookUrl.toString(), payload, config);
return okMsg;
}
if (heartbeatJSON["status"] === DOWN) {
const wentOfflineTimestamp = Math.floor(new Date(heartbeatJSON["time"]).getTime() / 1000);

View File

@@ -38,6 +38,28 @@
/>
</div>
<div class="mb-3">
<label for="discord-message-format" class="form-label">{{ $t("discordMessageFormat") }}</label>
<select id="discord-message-format" v-model="$parent.notification.discordMessageFormat" class="form-select">
<option value="normal">{{ $t("discordMessageFormatNormal") }}</option>
<option value="minimalist">{{ $t("discordMessageFormatMinimalist") }}</option>
<option value="custom">{{ $t("discordMessageFormatCustom") }}</option>
</select>
</div>
<div v-show="$parent.notification.discordMessageFormat === 'custom'">
<div class="mb-3">
<label for="discord-message-template" class="form-label">{{ $t("discordMessageTemplate") }}</label>
<TemplatedTextarea
id="discord-message-template"
v-model="$parent.notification.discordMessageTemplate"
:required="false"
placeholder=""
></TemplatedTextarea>
<div class="form-text">{{ $t("discordUseMessageTemplateDescription") }}</div>
</div>
</div>
<div class="mb-3">
<label for="discord-message-type" class="form-label">{{ $t("Select message type") }}</label>
<select id="discord-message-type" v-model="$parent.notification.discordChannelType" class="form-select">
@@ -122,7 +144,12 @@
</div>
</template>
<script>
import TemplatedTextarea from "../TemplatedTextarea.vue";
export default {
components: {
TemplatedTextarea,
},
mounted() {
if (!this.$parent.notification.discordChannelType) {
this.$parent.notification.discordChannelType = "channel";
@@ -133,6 +160,13 @@ export default {
if (this.$parent.notification.discordSuppressNotifications === undefined) {
this.$parent.notification.discordSuppressNotifications = false;
}
// Message format: default "normal"; migrate from old checkbox
if (typeof this.$parent.notification.discordMessageFormat === "undefined") {
const hadCustom =
this.$parent.notification.discordUseMessageTemplate === true ||
!!this.$parent.notification.discordMessageTemplate?.trim();
this.$parent.notification.discordMessageFormat = hadCustom ? "custom" : "normal";
}
},
};
</script>

View File

@@ -1323,6 +1323,13 @@
"Disable URL in Notification": "Disable URL in Notification",
"Suppress Notifications": "Suppress Notifications",
"discordSuppressNotificationsHelptext": "When enabled, messages will be posted to the channel but won't trigger push or desktop notifications for recipients.",
"discordMessageFormat": "Message Format",
"discordMessageFormatNormal": "Normal (rich embeds)",
"discordMessageFormatMinimalist": "Minimalist (short status)",
"discordMessageFormatCustom": "Custom template",
"discordUseMessageTemplate": "Use custom message template",
"discordUseMessageTemplateDescription": "If enabled, the message will be sent using a custom template (LiquidJS). Leave blank to use the default Uptime Kuma format.",
"discordMessageTemplate": "Message Template",
"Ip Family": "IP Family",
"ipFamilyDescriptionAutoSelect": "Uses the {happyEyeballs} for determining the IP family.",
"Happy Eyeballs algorithm": "Happy Eyeballs algorithm",