feat: rework notification templating and add support for telegram (#5637)

This commit is contained in:
Sergio Conde Gómez
2025-03-14 12:51:07 +01:00
committed by GitHub
parent fce824f5a8
commit 9857770cc7
10 changed files with 290 additions and 88 deletions

View 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>

View 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>

View File

@@ -67,25 +67,15 @@
<input id="to-bcc" v-model="$parent.notification.smtpBCC" type="text" class="form-control" autocomplete="false" :required="!hasRecipient">
</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">
<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>
<div class="mb-3">
<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>
@@ -124,11 +114,15 @@
<script>
import HiddenInput from "../HiddenInput.vue";
import TemplatedInput from "../TemplatedInput.vue";
import TemplatedTextarea from "../TemplatedTextarea.vue";
import ToggleSection from "../ToggleSection.vue";
export default {
components: {
HiddenInput,
TemplatedInput,
TemplatedTextarea,
ToggleSection,
},
computed: {

View File

@@ -32,7 +32,42 @@
<label for="message_thread_id" class="form-label">{{ $t("telegramMessageThreadID") }}</label>
<input id="message_thread_id" v-model="$parent.notification.telegramMessageThreadID" type="text" class="form-control">
<p class="form-text">{{ $t("telegramMessageThreadIDDescription") }}</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">
<input v-model="$parent.notification.telegramSendSilently" class="form-check-input" type="checkbox">
<label class="form-check-label">{{ $t("telegramSendSilently") }}</label>
@@ -57,11 +92,24 @@
<script>
import HiddenInput from "../HiddenInput.vue";
import TemplatedTextarea from "../TemplatedTextarea.vue";
import axios from "axios";
export default {
components: {
HiddenInput,
TemplatedTextarea,
},
computed: {
telegramTemplatedTextareaPlaceholder() {
return this.$t("Example:", [
`
Uptime Kuma Alert{% if monitorJSON %} - {{ monitorJSON['name'] }}{% endif %}
{{ msg }}
`,
]);
}
},
methods: {
/**
@@ -115,3 +163,9 @@ export default {
}
};
</script>
<style lang="scss" scoped>
textarea {
min-height: 150px;
}
</style>

View File

@@ -32,20 +32,7 @@
</template>
</i18n-t>
<template v-else-if="$parent.notification.webhookContentType == 'custom'">
<i18n-t tag="div" keypath="liquidIntroduction" class="form-text">
<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>
<TemplatedTextarea id="customBody" v-model="$parent.notification.webhookCustomBody" :required="true" :placeholder="customBodyPlaceholder"></TemplatedTextarea>
</template>
</div>
@@ -67,7 +54,12 @@
</template>
<script>
import TemplatedTextarea from "../TemplatedTextarea.vue";
export default {
components: {
TemplatedTextarea,
},
data() {
return {
showAdditionalHeadersField: this.$parent.notification.webhookAdditionalHeaders != null,

View File

@@ -231,6 +231,9 @@
"templateMonitorJSON": "object describing the monitor",
"templateLimitedToUpDownCertNotifications": "only available for UP/DOWN/Certificate expiry notifications",
"templateLimitedToUpDownNotifications": "only available for UP/DOWN notifications",
"templateServiceName": "service name",
"templateHostnameOrURL": "hostname or URL",
"templateStatus": "status",
"webhookAdditionalHeadersTitle": "Additional Headers",
"webhookAdditionalHeadersDesc": "Sets additional headers sent with the webhook. Each header should be defined as a JSON key/value.",
"webhookBodyPresetOption": "Preset - {0}",
@@ -421,6 +424,9 @@
"telegramSendSilentlyDescription": "Sends the message silently. Users will receive a notification with no sound.",
"telegramProtectContent": "Protect Forwarding/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",
"wayToGetTelegramChatID": "You can get your chat ID by sending a message to the bot and going to this URL to view the chat_id:",
"YOUR BOT TOKEN HERE": "YOUR BOT TOKEN HERE",
@@ -519,9 +525,6 @@
"leave blank for default subject": "leave blank for default subject",
"emailCustomBody": "Custom 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",
"emailTemplateHeartbeatJSON": "object describing the heartbeat",
"emailTemplateMsg": "message of the notification",
@@ -1053,5 +1056,8 @@
"SendGrid API Key": "SendGrid API Key",
"Separate multiple email addresses with commas": "Separate multiple email addresses with commas",
"YZJ Webhook URL": "YZJ Webhook URL",
"YZJ Robot Token": "YZJ Robot token"
"YZJ Robot Token": "YZJ Robot token",
"Plain Text": "Plain Text",
"Message Template": "Message Template",
"Template Format": "Template Format"
}