Merge pull request #3822 from mdiniz97/feat/rocket-chat-notifications
feat: Rocket.Chat notifications
This commit is contained in:
15 files changed
+379
-3
No files matched your search
@@ -23,6 +23,15 @@ export const createNotificationBodyValidation = z.discriminatedUnion("type", [
|
||||
roomId: z.union([z.string(), z.literal("")]).optional(),
|
||||
accessToken: z.union([z.string(), z.literal("")]).optional(),
|
||||
}),
|
||||
// Rocket.Chat notification
|
||||
z.object({
|
||||
notificationName: z.string().min(1, "Notification name is required"),
|
||||
type: z.literal("rocket_chat"),
|
||||
address: z.url({
|
||||
protocol: /^https?$/,
|
||||
message: "Please enter a valid Rocket.Chat webhook URL",
|
||||
}),
|
||||
}),
|
||||
// Slack notification
|
||||
z.object({
|
||||
notificationName: z.string().min(1, "Notification name is required"),
|
||||
|
||||
@@ -23,6 +23,7 @@ import { ILogger } from "@/utils/logger.js";
|
||||
// Notification providers
|
||||
import type { NotificationProviderRegistry } from "@/domain/notifications/notification.service.js";
|
||||
import { WebhookProvider } from "@/domain/notifications/providers/webhook.js";
|
||||
import { RocketChatProvider } from "@/domain/notifications/providers/rocketChat.js";
|
||||
import { SlackProvider } from "@/domain/notifications/providers/slack.js";
|
||||
import { EmailProvider } from "@/domain/notifications/providers/email.js";
|
||||
import { DiscordProvider } from "@/domain/notifications/providers/discord.js";
|
||||
@@ -157,6 +158,7 @@ export const buildShared = async ({
|
||||
});
|
||||
|
||||
const webhookProvider = new WebhookProvider(logger);
|
||||
const rocketChatProvider = new RocketChatProvider(logger);
|
||||
const slackProvider = new SlackProvider(logger);
|
||||
const emailProvider = new EmailProvider(emailService, logger);
|
||||
const discordProvider = new DiscordProvider(logger);
|
||||
@@ -170,6 +172,7 @@ export const buildShared = async ({
|
||||
|
||||
const notificationProviders: NotificationProviderRegistry = {
|
||||
webhook: webhookProvider,
|
||||
rocket_chat: rocketChatProvider,
|
||||
email: emailProvider,
|
||||
slack: slackProvider,
|
||||
discord: discordProvider,
|
||||
|
||||
@@ -30,6 +30,7 @@ const NotificationSchema = new Schema<NotificationDocument>(
|
||||
"slack",
|
||||
"discord",
|
||||
"webhook",
|
||||
"rocket_chat",
|
||||
"pager_duty",
|
||||
"matrix",
|
||||
"teams",
|
||||
|
||||
@@ -3,6 +3,7 @@ export const NotificationChannels = [
|
||||
"slack",
|
||||
"discord",
|
||||
"webhook",
|
||||
"rocket_chat",
|
||||
"pager_duty",
|
||||
"matrix",
|
||||
"teams",
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
const SERVICE_NAME = "RocketChatProvider";
|
||||
import type { Notification, NotificationMessage } from "@/domain/notifications/notification.type.js";
|
||||
import { NotificationProvider } from "@/domain/notifications/providers/INotificationProvider.js";
|
||||
import { getTestMessage } from "@/domain/notifications/providers/utils.js";
|
||||
import got from "got";
|
||||
|
||||
export class RocketChatProvider extends NotificationProvider {
|
||||
async sendTestAlert(notification: Partial<Notification>): Promise<boolean> {
|
||||
if (!notification.address) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
await got.post(notification.address, {
|
||||
json: { text: getTestMessage() },
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
...this.gotRequestOptions(),
|
||||
});
|
||||
return true;
|
||||
} catch (error) {
|
||||
const err = error as Error;
|
||||
this.logger.warn({
|
||||
message: "Rocket.Chat test alert failed",
|
||||
service: SERVICE_NAME,
|
||||
method: "sendTestAlert",
|
||||
stack: err?.stack,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async sendMessage(notification: Notification, message: NotificationMessage): Promise<boolean> {
|
||||
if (!notification.address) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
await got.post(notification.address, {
|
||||
json: { text: this.buildText(message) },
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
...this.gotRequestOptions(),
|
||||
});
|
||||
return true;
|
||||
} catch (error) {
|
||||
const err = error as Error;
|
||||
this.logger.warn({
|
||||
message: "Rocket.Chat notification failed",
|
||||
service: SERVICE_NAME,
|
||||
method: "sendMessage",
|
||||
stack: err?.stack,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private buildText(message: NotificationMessage): string {
|
||||
const lines = [
|
||||
message.content.title,
|
||||
message.content.summary,
|
||||
"",
|
||||
`Monitor: ${message.monitor.name}`,
|
||||
`Type: ${message.monitor.type}`,
|
||||
`Status: ${message.monitor.status}`,
|
||||
`URL: ${message.monitor.url}`,
|
||||
];
|
||||
|
||||
if (message.content.details?.length) {
|
||||
lines.push("", "Details:", ...message.content.details.map((detail) => `- ${detail}`));
|
||||
}
|
||||
if (message.content.thresholds?.length) {
|
||||
lines.push(
|
||||
"",
|
||||
"Thresholds:",
|
||||
...message.content.thresholds.map(
|
||||
(threshold) => `- ${threshold.metric.toUpperCase()}: ${threshold.formattedValue} (threshold: ${threshold.threshold}${threshold.unit})`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (message.content.incident) {
|
||||
lines.push("", `Incident: ${message.clientHost}/infrastructure/${message.monitor.id}`);
|
||||
}
|
||||
|
||||
return lines.join("\n");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user