71 lines
2.7 KiB
TypeScript
71 lines
2.7 KiB
TypeScript
import { randomUUID } from 'node:crypto';
|
|
import { getDatabase } from '$lib/server/database';
|
|
import { createNotification } from '$lib/server/notifications';
|
|
|
|
export const AUTOMATED_MESSAGE_EVENTS = [
|
|
{ value: 'account.created', label: 'ACCOUNT CREATED', description: 'After a new SHD.build account is created' }
|
|
] as const;
|
|
export type AutomatedMessageEvent = (typeof AUTOMATED_MESSAGE_EVENTS)[number]['value'];
|
|
|
|
type MessageRow = Record<string, unknown>;
|
|
|
|
function parseActions(value: unknown): Array<{ label: string; href: string }> {
|
|
try {
|
|
const parsed = JSON.parse(String(value ?? '[]'));
|
|
if (!Array.isArray(parsed)) return [];
|
|
return parsed
|
|
.filter((item) => item && typeof item.label === 'string' && typeof item.href === 'string')
|
|
.map((item) => ({ label: item.label.slice(0, 60), href: item.href.slice(0, 500) }))
|
|
.slice(0, 8);
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
async function deliver(message: MessageRow, deliveryId: string, userId: string) {
|
|
const notificationId = await createNotification({
|
|
userId,
|
|
category: 'isac',
|
|
source: String(message.source),
|
|
title: String(message.title),
|
|
body: String(message.body),
|
|
link: typeof message.link === 'string' ? message.link : null,
|
|
actions: parseActions(message.actions_json),
|
|
mandatory: true
|
|
});
|
|
if (!notificationId) return;
|
|
const database = await getDatabase();
|
|
await (await database.prepare(`UPDATE automated_system_message_deliveries
|
|
SET delivered_at=?,notification_id=? WHERE id=? AND delivered_at IS NULL`))
|
|
.run(new Date().toISOString(), notificationId, deliveryId);
|
|
}
|
|
|
|
export async function triggerAutomatedSystemMessages(input: {
|
|
eventKey: AutomatedMessageEvent;
|
|
userId: string;
|
|
eventId: string;
|
|
}) {
|
|
const database = await getDatabase();
|
|
const messages = await (await database.prepare(
|
|
'SELECT * FROM automated_system_messages WHERE event_key=? AND enabled=1 ORDER BY name'
|
|
)).all(input.eventKey);
|
|
const now = new Date();
|
|
for (const message of messages) {
|
|
const existing = await (await database.prepare(`SELECT id FROM automated_system_message_deliveries
|
|
WHERE message_id=? AND user_id=? AND event_key=? AND event_id=?`))
|
|
.get(message.id, input.userId, input.eventKey, input.eventId);
|
|
if (existing) continue;
|
|
const deliveryId = randomUUID();
|
|
const scheduledFor = new Date(now.getTime() + Number(message.send_delay_minutes ?? 0) * 60_000);
|
|
await (await database.prepare(`INSERT OR IGNORE INTO automated_system_message_deliveries
|
|
(id,message_id,user_id,event_key,event_id,scheduled_for,created_at)
|
|
VALUES(?,?,?,?,?,?,?)`)).run(
|
|
deliveryId, message.id, input.userId, input.eventKey, input.eventId,
|
|
scheduledFor.toISOString(), now.toISOString()
|
|
);
|
|
if (Number(message.send_delay_minutes ?? 0) === 0) {
|
|
await deliver(message, deliveryId, input.userId);
|
|
}
|
|
}
|
|
}
|