email provider

This commit is contained in:
Alex Holliday
2026-01-19 19:30:46 +00:00
parent f7f764fd68
commit fd33b903ed
4 changed files with 96 additions and 13 deletions
+13 -2
View File
@@ -7,7 +7,7 @@ import EmailService from "../service/infrastructure/emailService.js";
import BufferService from "../service/infrastructure/bufferService.js";
import NotificationUtils from "../service/infrastructure/notificationUtils.js";
import NotificationService from "../service/infrastructure/notificationService.js";
import { NotificationsService, StatusService } from "@/service/index.js";
import { NotificationsService, StatusService, WebhookProvider, SlackProvider, EmailProvider, DiscordProvider } from "@/service/index.js";
import ErrorService from "../service/infrastructure/errorService.js";
import SuperSimpleQueueHelper from "../service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js";
import SuperSimpleQueue from "../service/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js";
@@ -228,7 +228,17 @@ export const initializeServices = async ({
notificationUtils,
});
const notificationsService = new NotificationsService(notificationsRepository);
const webhookProvider = new WebhookProvider();
const slackProvider = new SlackProvider();
const emailProvider = new EmailProvider(emailService);
const discordProvider = new DiscordProvider();
const notificationsService = new NotificationsService(notificationsRepository, {
webhookProvider,
slackProvider,
emailProvider,
discordProvider,
});
const superSimpleQueueHelper = new SuperSimpleQueueHelper({
db,
@@ -323,6 +333,7 @@ export const initializeServices = async ({
invitesRepository,
recoveryTokensRepository,
settingsRepository,
notificationsRepository,
notificationsService,
};
@@ -1,9 +1,35 @@
import type { Monitor, Notification, MonitorStatusResponse } from "@/types/index.js";
import { INotificationProvider } from "@/service/index.js";
import { buildHardwareAlerts, buildHardwareEmail, buildEmail } from "@/service/infrastructure/notificationProviders/utils.js";
export class EmailProvider implements INotificationProvider {
private emailService: any;
constructor(emailService: any) {
this.emailService = emailService;
}
private buildHardwareEmail = (monitor: Monitor, monitorStatusResponse: MonitorStatusResponse) => {
const { alertsToSend } = buildHardwareAlerts("HOST_PLACEHOLDER", monitor, monitorStatusResponse);
const html = buildHardwareEmail(this.emailService, monitor, alertsToSend);
return html;
};
async sendAlert(notification: Notification, monitor: Monitor, monitorStatusResponse: MonitorStatusResponse): Promise<boolean> {
return false;
const subject = `Monitor ${monitor.name} infrastructure alerts`;
let html;
if (monitor.type === "hardware") {
html = this.buildHardwareEmail(monitor, monitorStatusResponse);
} else {
html = await buildEmail(this.emailService, monitor);
}
if (!notification.address) {
return false;
}
const messageId = await this.emailService.sendEmail(notification.address, subject, html);
if (!messageId) return false;
return true;
}
async sendTestAlert(notification: Notification): Promise<boolean> {
@@ -134,6 +134,34 @@ export const shouldSendHardwareAlert = (monitor: Monitor, networkResponse: Monit
export const buildWebhookBody = (monitor: Monitor, monitorStatusResponse: MonitorStatusResponse) => {
const { status, code } = monitorStatusResponse;
const formattedTime = Date.now().toLocaleString();
return `Monitor: ${monitor.name}\nTime: ${formattedTime}\nStatus: ${status ? "UP" : "DOWN"}\n Status Code: ${code}\n\u200B\n`;
const now = new Date();
const localTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const localTime = new Intl.DateTimeFormat(undefined, {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
timeZone: localTimeZone,
timeZoneName: "short",
}).format(now);
const utcTime = now.toUTCString();
return `Monitor: ${monitor.name}\nLocal Time (${localTimeZone}): ${localTime}\nUTC Time: ${utcTime}\nStatus: ${status ? "UP" : "DOWN"}\nStatus Code: ${code}\n\u200B\n`;
};
export const buildHardwareEmail = async (emailService: any, monitor: Monitor, alerts: string[]) => {
const template = "hardwareIncidentTemplate";
const context = { monitor: monitor.name, url: monitor.url, alerts };
const html = await emailService.buildEmail(template, context);
return html;
};
export const buildEmail = async (emailService: any, monitor: Monitor): Promise<string> => {
const template = monitor.status === false ? "serverIsUpTemplate" : "serverIsDownTemplate";
const context = { monitor: monitor.name, url: monitor.url };
const html = await emailService.buildEmail(template, context);
console.log({ html: typeof html });
return html;
};
@@ -1,7 +1,7 @@
import type { HardwareStatusPayload, Monitor, MonitorStatusResponse, Notification } from "@/types/index.js";
import { shouldSendHardwareAlert } from "@/service/infrastructure/notificationProviders/utils.js";
import { INotificationsRepository } from "@/repositories/index.js";
import { WebhookProvider } from "@/service/index.js";
import { DiscordProvider, EmailProvider, SlackProvider, WebhookProvider } from "@/service/index.js";
export interface INotificationsService {
handleNotifications: (
monitor: Monitor,
@@ -14,21 +14,39 @@ export interface INotificationsService {
export class NotificationsService implements INotificationsService {
private notificationsRepository: INotificationsRepository;
private webhookProvider: WebhookProvider;
private emailProvider: EmailProvider;
private slackProvider: SlackProvider;
private discordProvider: DiscordProvider;
constructor(notificationsRepository: INotificationsRepository, webhookProvider: WebhookProvider) {
constructor(
notificationsRepository: INotificationsRepository,
providers: {
webhookProvider: WebhookProvider;
emailProvider: EmailProvider;
slackProvider: SlackProvider;
discordProvider: DiscordProvider;
}
) {
this.notificationsRepository = notificationsRepository;
this.webhookProvider = webhookProvider;
this.webhookProvider = providers.webhookProvider;
this.emailProvider = providers.emailProvider;
this.slackProvider = providers.slackProvider;
this.discordProvider = providers.discordProvider;
}
private send = async (notification: Notification, monitor: Monitor, monitorStatusResponse: MonitorStatusResponse): Promise<boolean> => {
switch (notification.type) {
case " email": {
}
case "webhook": {
case "email":
return await this.emailProvider.sendAlert(notification, monitor, monitorStatusResponse);
case "slack":
return await this.slackProvider.sendAlert(notification, monitor, monitorStatusResponse);
case "discord":
return await this.discordProvider.sendAlert(notification, monitor, monitorStatusResponse);
case "webhook":
return await this.webhookProvider.sendAlert(notification, monitor, monitorStatusResponse);
}
default:
return false;
}
return false;
};
private sendNotifications = async (monitor: Monitor, monitorStatusResponse: MonitorStatusResponse) => {