KI-AGENT: Matrix Sync Push für eingehende Nachrichten ergänzen

This commit is contained in:
2026-05-22 18:39:15 +02:00
parent 0328a4586a
commit c56fb6b571

View File

@@ -1,7 +1,7 @@
import { createHash } from "node:crypto"
import { FastifyInstance } from "fastify"
import multipart from "@fastify/multipart"
import { and, eq, inArray, ne } from "drizzle-orm"
import { and, desc, eq, inArray, ne } from "drizzle-orm"
import { authProfiles, authTenantUsers, authUsers, notificationsItems, projects } from "../../db/schema"
import { matrixService } from "../modules/matrix.service"
import { NotificationService, UserDirectory } from "../modules/notification.service"
@@ -98,6 +98,30 @@ export default async function communicationRoutes(server: FastifyInstance) {
))
}
const getTenantUser = async (tenantId: number, userId: string): Promise<ChatRecipient | null> => {
const [user] = await server.db
.select({
userId: authTenantUsers.user_id,
email: authUsers.email,
firstName: authProfiles.first_name,
lastName: authProfiles.last_name,
fullName: authProfiles.full_name,
})
.from(authTenantUsers)
.innerJoin(authUsers, eq(authUsers.id, authTenantUsers.user_id))
.leftJoin(authProfiles, and(
eq(authProfiles.user_id, authTenantUsers.user_id),
eq(authProfiles.tenant_id, tenantId)
))
.where(and(
eq(authTenantUsers.tenant_id, tenantId),
eq(authTenantUsers.user_id, userId)
))
.limit(1)
return user || null
}
const getSenderName = async (tenantId: number, senderUserId: string) => {
const [sender] = await server.db
.select({
@@ -195,6 +219,67 @@ export default async function communicationRoutes(server: FastifyInstance) {
}
}
const hasChatNotificationForMessage = async (tenantId: number, userId: string, messageId: string) => {
const rows = await server.db
.select({
payload: notificationsItems.payload,
})
.from(notificationsItems)
.where(and(
eq(notificationsItems.tenantId, tenantId),
eq(notificationsItems.userId, userId),
eq(notificationsItems.eventType, "communication.message.new")
))
.orderBy(desc(notificationsItems.createdAt))
.limit(200)
return rows.some((row) => (row.payload as any)?.messageId === messageId)
}
const notifyCurrentUserAboutIncomingMatrixMessages = async (req: any, room: any, messages: any[]) => {
if (!req.user.tenant_id || !messages.length) return
try {
const currentUser = await getTenantUser(req.user.tenant_id, req.user.user_id)
if (!currentUser) return
for (const message of messages) {
if (message.own || !message.id) continue
const text = message.body || message.attachment?.fileName || "Neue Nachricht"
const mentioned = mentionedRecipientIds(text, [currentUser]).includes(currentUser.userId)
const direct = room?.type === "direct"
if (!direct && !mentioned) continue
if (await hasChatNotificationForMessage(req.user.tenant_id, req.user.user_id, message.id)) continue
const senderName = message.senderDisplayName || message.sender || "Matrix"
const preview = text.length > 160 ? `${text.slice(0, 157)}...` : text
await notifications.trigger({
tenantId: req.user.tenant_id,
userId: req.user.user_id,
eventType: "communication.message.new",
title: mentioned ? `${senderName} hat dich erwähnt` : `Neue Direktnachricht von ${senderName}`,
message: preview,
payload: {
link: `/communication/chat?room=${encodeURIComponent(room.key)}`,
roomKey: room.key,
roomName: room.name,
roomType: room.type,
messageId: message.id,
matrixSender: message.sender,
mentioned,
direct,
},
channels: ["inapp", "push"],
})
}
} catch (err) {
req.log.error({ err }, "Eingehende Matrix-Benachrichtigung konnte nicht ausgelöst werden")
}
}
const unreadChatNotifications = async (tenantId: number, userId: string) => {
return await server.db
.select({
@@ -739,13 +824,19 @@ export default async function communicationRoutes(server: FastifyInstance) {
server.get("/communication/matrix/rooms/:roomKey/sync", async (req, reply) => {
try {
const query = req.query as { since?: string; initial?: string }
return await matrix.syncTenantRoomEvents(
const result = await matrix.syncTenantRoomEvents(
req.user.user_id,
req.user.tenant_id,
roomOptionsFromRequest(req),
query.since,
query.initial === "1"
)
if (query.since && query.initial !== "1" && result.messages?.length) {
const room = await matrix.getTenantRoomStatus(req.user.tenant_id, result.key, result.name)
await notifyCurrentUserAboutIncomingMatrixMessages(req, room, result.messages)
}
return result
} catch (err: any) {
return handleMatrixError(req, reply, err, "Matrix sync failed")
}