Browse Source

Basic Templates working for webhook and smtp

deefdragon/Template-Engine
Jeffrey Koehler 3 years ago
parent
commit
5a2c826058
  1. 6
      package-lock.json
  2. 4
      package.json
  3. 142
      server/notification.js
  4. 3
      server/server.js
  5. 27
      src/components/NotificationDialog.vue
  6. 11
      src/components/notifications/index.js
  7. 12
      src/languages/en.js

6
package-lock.json

@ -6041,9 +6041,9 @@
"dev": true
},
"liquidjs": {
"version": "9.28.0",
"resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-9.28.0.tgz",
"integrity": "sha512-BsLhHbv+dHH8hzac1/4tx2f4yPujD87wPOz9gnosPMoDgR0HiRrZXqPUVpfXJgZbWaqEJX1lawnS0GDyG/1r6Q=="
"version": "9.28.1",
"resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-9.28.1.tgz",
"integrity": "sha512-3nt07YdKCt/4u3D/B5ngBWvyCxENGH2+vcrlBzBdaUBlyX2htzj9MjWKqeXdJJfz7xtbcwbaWEuP84/SZvDSog=="
},
"locate-path": {
"version": "5.0.0",

4
package.json

@ -62,8 +62,8 @@
"axios": "~0.21.4",
"bcryptjs": "~2.4.3",
"bootstrap": "~5.1.1",
"chardet": "^1.3.0",
"bree": "~6.3.1",
"chardet": "^1.3.0",
"chart.js": "~3.5.1",
"chartjs-adapter-dayjs": "~1.0.0",
"command-exists": "~1.2.9",
@ -75,7 +75,7 @@
"http-graceful-shutdown": "~3.1.4",
"iconv-lite": "^0.6.3",
"jsonwebtoken": "~8.5.1",
"liquidjs": "^9.28.0",
"liquidjs": "^9.28.1",
"nodemailer": "~6.6.5",
"notp": "~2.0.3",
"password-hash": "~1.2.2",

142
server/notification.js

@ -27,8 +27,92 @@ const Feishu = require("./notification-providers/feishu");
const AliyunSms = require("./notification-providers/aliyun-sms");
const DingDing = require("./notification-providers/dingding");
const MinimalDetailTemplate = "{{monitor.name}}: {{monitor.health}}"
const LowDetailTemplate = "[{{monitor.name}}] [{{monitor.health}}] {{heartbeat.msg}}"
const MediumDetailTemplate = `Monitor: {{monitor.name}}
Health: {{monitor.health}}
Address: {{monitor.url}}
{% if heartbeat.status == 1 and monitor.upsideDown -%}
Your Upside down {{monitor.type}} monitor is unexpectedly connected
{%- elsif heartbeat.status == 1 and monitor.upsideDown==false -%}
Your {{monitor.type}} monitor is up
{%- elsif heartbeat.status == 0 and monitor.upsideDown -%}
Your Upside down {{monitor.type}} monitor is no longer connected
{%- elsif heartbeat.status == 0 and monitor.upsideDown == false -%}
Your {{monitor.type}} monitor is unexpectedly down.
{%- endif %}
Time: {{heartbeat.time}}
Uptime Message: {{heartbeat.msg}}`
const FullDetailTemplate = `Monitor: {{monitor.name}}
Health: {{monitor.health}}
Address: {{monitor.url}}
{% if heartbeat.status == 1 and monitor.upsideDown -%}
Your Upside down {{monitor.type}} monitor is unexpectedly connected
{%- elsif heartbeat.status == 1 and monitor.upsideDown==false -%}
Your {{monitor.type}} monitor is up
{%- elsif heartbeat.status == 0 and monitor.upsideDown -%}
Your Upside down {{monitor.type}} monitor is no longer connected
{%- elsif heartbeat.status == 0 and monitor.upsideDown == false -%}
Your {{monitor.type}} monitor is unexpectedly down.
{%- endif %}
Time: {{heartbeat.time}}
Uptime Message: {{heartbeat.msg}}
Tags
----------------------------------------
{% for tag in monitor.tags -%}
{{ tag.name }}
{%- if tag.value and tag.value != "" -%}
: {{tag.value}}
{%- endif %}
{% endfor -%}`
class Notification {
static generateTestHeartbeat(){
return {
monitorID: 5,
status: 1,
time: (new Date()).toLocaleString(),
msg: "TEST NOTIFICATION MESSAGE",
ping: 278,
important: true,
duration: 8,
};
}
static generateTestMonitor(){
return {
id: 5,
name: "Test Notification Monitor",
url: "https://www.example.com",
method: "Get",
body: "OK",
headers: null,
hostname: "www.example.com",
port: 443,
maxretries: 2,
weight: 2000,
active: 1,
type: "HTTP",
interval: 60,
retryInterval: this.retryInterval,
keyword: null,
ignoreTls: false,
upsideDown: false,
maxredirects: 10,
accepted_statuscodes: ["200-299"],
dns_resolve_type: "A",
dns_resolve_server: "1.1.1.1",
dns_last_result: null,
pushToken: null,
notificationIDList:{"1":true,"5":true},
tags: [{"id":21,"monitor_id":16,"tag_id":2,"value":"","name":"Internal","color":"#059669"}],
};
}
providerList = {};
static init() {
@ -73,6 +157,7 @@ class Notification {
}
}
/**
*
* @param notification : BeanModel
@ -82,34 +167,22 @@ class Notification {
* @returns {Promise<string>} Successful msg
* Throw Error with fail msg
*/
static async send(
notification,
msg,
monitorJSON = {
id: "this.id",
name: "this.name",
url: "this.url",
hostname: "this.hostname",
},
heartbeatJSON = {
status: UP,
message: "new message",
ping: "1ms",
duration:"5 seconds",
monitor:"asd",
}) {
static async send(notification, msg, monitorJSON, heartbeatJSON) {
if (this.providerList[notification.type]) {
//TODO need to check for errors.
try {
monitorJSON.health = ((heartbeatJSON.status == 1) !== monitorJSON.upsideDown) ? "✅ Healthy": "❌ Unhealthy"
let newmsg = await engine.parseandrender("{{msg}} {{monitor | json}} {{heartbeat | json}} {{notification | json}}", {
notification: notification,
msg: msg,
let parseData = {
// I actually dont think that it is necessary to put the notification in the data sent to the template.
// notification: notification,
monitor: monitorJSON,
heartbeat: heartbeatJSON,
})
return this.providerList[notification.type].send(notification, newmsg, monitorJSON, heartbeatJSON);
}
let template = this.getTemplateFromNotification(notification)
console.log(`Template: (${template})`)
let message = await engine.parseAndRender(template, parseData)
return this.providerList[notification.type].send(notification, message, monitorJSON, heartbeatJSON);
} catch (e) {
throw e
}
@ -119,6 +192,29 @@ class Notification {
}
}
static getTemplateFromNotification(notification){
let template = notification.template
let detail = notification.detail
console.log(`Detail: (${detail}) Template: (${template})`)
switch (detail) {
case "Minimal Detail":
return MinimalDetailTemplate
case "Low Detail":
return LowDetailTemplate
case "Medium Detail":
return MediumDetailTemplate
case "Full Detail":
return FullDetailTemplate
case "Custom Template":
if (template) {
return template
}
//returns low in the case of a template being empty string or undefined.
}
return LowDetailTemplate
}
static async save(notification, notificationID, userID) {
let bean

3
server/server.js

@ -970,7 +970,8 @@ exports.entryPage = "dashboard";
try {
checkLogin(socket);
let msg = await Notification.send(notification, notification.name + " Testing");
let notificationText = `[Monitor Name] [Up/Down] Status Message (${notification.name} Testing)`;
let msg = await Notification.send(notification, notificationText, Notification.generateTestMonitor(),Notification.generateTestHeartbeat());
callback({
ok: true,

27
src/components/NotificationDialog.vue

@ -22,6 +22,19 @@
<input id="notification-name" v-model="notification.name" type="text" class="form-control" required>
</div>
<div class="mb-3">
<label for="notification-detail" class="form-label">{{ $t("Notification Message Detail") }}</label>
<select id="notification-detail" v-model="notification.detail" class="form-select">
<option v-for="detail in detailLevels" :key="detail" :value="detail">{{ $t(detail) }}</option>
</select>
</div>
<!-- using show so that if the user toggels to a different template level, they dont loose what is in the field. -->
<div class="mb-3" v-show="notification.detail === 'Custom Template'">
<label for="notification-text" class="form-label">{{ $t("Custom Message Template") }}</label>
<textarea id="notification-text" v-model="notification.template" type="text" class="form-control" ></textarea>
</div>
<!-- form body -->
<component :is="currentForm" />
@ -72,7 +85,9 @@ import { Modal } from "bootstrap";
import { ucfirst } from "../util.ts";
import Confirm from "./Confirm.vue";
import NotificationFormList from "./notifications";
import {NotificationFormList, NotificationDetailList} from "./notifications";
// import from "./notifications";
export default {
components: {
@ -92,7 +107,9 @@ export default {
type: null,
isDefault: false,
// Do not set default value here, please scroll to show()
}
},
detailLevels: NotificationDetailList,
};
},
@ -118,6 +135,9 @@ export default {
this.notification.name = this.getUniqueDefaultName(to);
}
},
"notification.detail"(to,from){
this.notification.detail = to
}
},
mounted() {
this.modal = new Modal(this.$refs.modal);
@ -149,6 +169,9 @@ export default {
// Set Default value here
this.notification.type = this.notificationTypes[0];
this.notification.detail = this.detailLevels[0];
this.notification.template = "[{{monitor.name}}] [{{monitor.health}}] {{monitor.msg}}"
}
this.modal.show();

11
src/components/notifications/index.js

@ -26,7 +26,7 @@ import DingDing from "./DingDing.vue";
*
* @type { Record<string, any> }
*/
const NotificationFormList = {
export const NotificationFormList = {
"telegram": Telegram,
"webhook": Webhook,
"smtp": STMP,
@ -51,4 +51,11 @@ const NotificationFormList = {
"DingDing": DingDing
}
export default NotificationFormList
export const NotificationDetailList = [
"Minimal Detail",
"Low Detail",
"Medium Detail",
"Full Detail",
"Custom Template",
]

12
src/languages/en.js

@ -306,4 +306,16 @@ export default {
"One record": "One record",
"Showing {from} to {to} of {count} records": "Showing {from} to {to} of {count} records",
steamApiKeyDescription: "For monitoring a Steam Game Server you need a Steam Web-API key. You can register your API key here: ",
"Message Template":"Message Template",
"Default Template":"[{{monitor.name}}] [{{monitor.health}}] {{monitor.msg}}",
HealthyStatus:"✅ Healthy",
UnhealthyStatus:"❌ Unhealthy",
//template levels
"Notification Message Detail":"Notification Message Detail",
"Minimal Detail":"Minimal Detail",
"Low Detail":"Low Detail",
"Medium Detail":"Medium Detail",
"Full Detail":"Full Detail",
"Custom Template":"Custom Template",
};

Loading…
Cancel
Save