feature(dashboard): add integrations and notifications

This commit is contained in:
Carl-Gerhard Lindesvärd
2024-10-02 22:12:05 +02:00
parent d920f6951c
commit f65a633403
94 changed files with 3692 additions and 127 deletions

View File

@@ -6,6 +6,7 @@ import { getTime } from '@openpanel/common';
import {
type IServiceEvent,
TABLE_NAMES,
checkNotificationRulesForSessionEnd,
createEvent,
eventBuffer,
getEvents,
@@ -138,6 +139,8 @@ export async function createSessionEnd(
throw new Error('No last event found');
}
await checkNotificationRulesForSessionEnd(events);
return createEvent({
...sessionStart,
properties: {

View File

@@ -7,17 +7,17 @@ import { v4 as uuid } from 'uuid';
import { logger } from '@/utils/logger';
import { getTime, isSameDomain, parsePath } from '@openpanel/common';
import type { IServiceCreateEventPayload } from '@openpanel/db';
import { createEvent } from '@openpanel/db';
import { checkNotificationRulesForEvent, createEvent } from '@openpanel/db';
import { getLastScreenViewFromProfileId } from '@openpanel/db/src/services/event.service';
import type {
EventsQueuePayloadCreateSessionEnd,
EventsQueuePayloadIncomingEvent,
} from '@openpanel/queue';
import {
findJobByPrefix,
sessionsQueue,
sessionsQueueEvents,
} from '@openpanel/queue';
import type {
EventsQueuePayloadCreateSessionEnd,
EventsQueuePayloadIncomingEvent,
} from '@openpanel/queue';
import { getRedisQueue } from '@openpanel/redis';
const GLOBAL_PROPERTIES = ['__path', '__referrer'];
@@ -101,6 +101,8 @@ export async function incomingEvent(job: Job<EventsQueuePayloadIncomingEvent>) {
sdkVersion,
};
await checkNotificationRulesForEvent(payload);
return createEvent(payload);
}
@@ -185,6 +187,8 @@ export async function incomingEvent(job: Job<EventsQueuePayloadIncomingEvent>) {
});
}
await checkNotificationRulesForEvent(payload);
return createEvent(payload);
}

View File

@@ -0,0 +1,71 @@
import type { Job } from 'bullmq';
import { setSuperJson } from '@openpanel/common';
import { db } from '@openpanel/db';
import { sendDiscordNotification } from '@openpanel/integrations/src/discord';
import { sendSlackNotification } from '@openpanel/integrations/src/slack';
import type { NotificationQueuePayload } from '@openpanel/queue';
import { getRedisPub } from '@openpanel/redis';
export async function notificationJob(job: Job<NotificationQueuePayload>) {
switch (job.data.type) {
case 'sendNotification': {
const { notification } = job.data.payload;
if (notification.sendToApp) {
getRedisPub().publish('notification', setSuperJson(notification));
// empty for now
return;
}
if (notification.sendToEmail) {
// empty for now
return;
}
if (!notification.integrationId) {
throw new Error('No integrationId provided');
}
const integration = await db.integration.findUniqueOrThrow({
where: {
id: notification.integrationId,
},
});
switch (integration.config.type) {
case 'webhook': {
return fetch(integration.config.url, {
method: 'POST',
headers: {
...(integration.config.headers ?? {}),
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: notification.title,
message: notification.message,
}),
});
}
case 'discord': {
return sendDiscordNotification({
webhookUrl: integration.config.url,
message: [
`🔔 **${notification.title}**`,
notification.message,
].join('\n'),
});
}
case 'slack': {
return sendSlackNotification({
webhookUrl: integration.config.incoming_webhook.url,
message: [`🔔 *${notification.title}*`, notification.message].join(
'\n',
),
});
}
}
}
}
}