Files
Checkmate/server/service/notificationService.js
2025-06-19 12:12:55 +08:00

124 lines
3.7 KiB
JavaScript

class NotificationService {
constructor({
emailService,
db,
logger,
networkService,
stringService,
notificationUtils,
}) {
this.emailService = emailService;
this.db = db;
this.logger = logger;
this.networkService = networkService;
this.stringService = stringService;
this.notificationUtils = notificationUtils;
}
sendNotification = async ({ notification, subject, content, html }) => {
const { type, address } = notification;
if (type === "email") {
const messageId = await this.emailService.sendEmail(address, subject, html);
if (!messageId) return false;
return true;
}
// Create a body for webhooks
let body = { text: content };
if (type === "discord") {
body = { content };
}
if (type === "slack" || type === "discord" || type === "webhook") {
const response = await this.networkService.requestWebhook(type, address, body);
return response.status;
}
if (type === "pager_duty") {
const response = await this.networkService.requestPagerDuty({
message: content,
monitorUrl: subject,
routingKey: address,
});
return response;
}
};
async handleNotifications(networkResponse) {
const { monitor, statusChanged, prevStatus } = networkResponse;
const { type } = monitor;
if (type !== "hardware" && statusChanged === false) return false;
// if prevStatus is undefined, monitor is resuming, we're done
if (type !== "hardware" && prevStatus === undefined) return false;
const notificationIDs = networkResponse.monitor?.notifications ?? [];
if (notificationIDs.length === 0) return false;
if (networkResponse.monitor.type === "hardware") {
const thresholds = networkResponse?.monitor?.thresholds;
if (thresholds === undefined) return false; // No thresholds set, we're done
const metrics = networkResponse?.payload?.data ?? null;
if (metrics === null) return false; // No metrics, we're done
const alerts = await this.notificationUtils.buildHardwareAlerts(networkResponse);
if (alerts.length === 0) return false;
const { subject, html } = await this.notificationUtils.buildHardwareEmail(
networkResponse,
alerts
);
const content =
await this.notificationUtils.buildHardwareNotificationMessage(alerts);
const success = await this.notifyAll({ notificationIDs, subject, html, content });
return success;
}
// Status monitors
const { subject, html } =
await this.notificationUtils.buildStatusEmail(networkResponse);
const content = await this.notificationUtils.buildWebhookMessage(networkResponse);
const success = this.notifyAll({ notificationIDs, subject, html, content });
return success;
}
async notifyAll({ notificationIDs, subject, html, content }) {
const notifications = await this.db.getNotificationsByIds(notificationIDs);
// Map each notification to a test promise
const promises = notifications.map(async (notification) => {
try {
await this.sendNotification({ notification, subject, content, html });
return true;
} catch (err) {
return false;
}
});
const results = await Promise.all(promises);
return results.every((r) => r === true);
}
async getTestNotification() {
const html = await this.notificationUtils.buildTestEmail();
const content = "This is a test notification";
const subject = "Test Notification";
return { subject, html, content };
}
async testAllNotifications(notificationIDs) {
const { subject, html, content } = await this.getTestNotification();
return this.notifyAll({ notificationIDs, subject, html, content });
}
async sendTestNotification(notification) {
const { subject, html, content } = await this.getTestNotification();
const success = await this.sendNotification({ notification, subject, content, html });
return success;
}
}
export default NotificationService;