From 45ca4f7327181b911bb3f502e8d0a6ad249645db Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Fri, 22 May 2026 21:29:31 +0200 Subject: [PATCH] =?UTF-8?q?KI-AGENT:=20Matrix=20Service=20User=20automatis?= =?UTF-8?q?ch=20in=20R=C3=A4ume=20aufnehmen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/matrix-push-worker.service.ts | 13 +++ backend/src/modules/matrix.service.ts | 83 ++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/backend/src/modules/matrix-push-worker.service.ts b/backend/src/modules/matrix-push-worker.service.ts index e728155..308226e 100644 --- a/backend/src/modules/matrix-push-worker.service.ts +++ b/backend/src/modules/matrix-push-worker.service.ts @@ -72,6 +72,7 @@ export function startMatrixPushWorker(server: FastifyInstance) { let running = false let stopped = false let timer: ReturnType | undefined + let lastServiceJoinSyncAt = 0 const getTenantRecipients = async (tenantId: number) => { const rows = await server.db @@ -186,6 +187,18 @@ export function startMatrixPushWorker(server: FastifyInstance) { running = true try { + if (!lastServiceJoinSyncAt || Date.now() - lastServiceJoinSyncAt > 60_000) { + const joinResult = await matrix.syncServiceJoinedTenantRooms() + lastServiceJoinSyncAt = Date.now() + if (joinResult.failed) { + console.warn("Matrix-Push-Worker: Service-User konnte nicht alle Räume joinen", { + total: joinResult.total, + joined: joinResult.joined, + failed: joinResult.failed, + }) + } + } + const initial = !since const sync = await matrix.syncServiceRoomEvents(since, initial) since = sync.nextBatch || since diff --git a/backend/src/modules/matrix.service.ts b/backend/src/modules/matrix.service.ts index 19ab7ed..be37dc7 100644 --- a/backend/src/modules/matrix.service.ts +++ b/backend/src/modules/matrix.service.ts @@ -3,7 +3,7 @@ import { existsSync, readFileSync } from "node:fs" import { resolve } from "node:path" import { FastifyInstance } from "fastify" import { authProfiles, authTenantUsers, authUsers, communicationRooms, tenants } from "../../db/schema" -import { and, eq } from "drizzle-orm" +import { and, eq, isNotNull } from "drizzle-orm" import { secrets } from "../utils/secrets" import jwt from "jsonwebtoken" @@ -1126,6 +1126,86 @@ export function matrixService(server: FastifyInstance) { } } + const ensureServiceUserJoinedRoom = async (room: { roomId?: string | null; alias?: string | null }) => { + const target = room.roomId || room.alias + if (!target) return { ok: false, status: "missing_room" } + + const serviceLogin = await ensureServiceAccessToken() + + try { + await requestMatrixJson( + `/_synapse/admin/v1/join/${encodeURIComponent(target)}`, + serviceLogin.accessToken, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ user_id: serviceLogin.matrixUserId }), + } + ) + + return { ok: true, status: "joined_admin", roomId: target } + } catch (adminErr: any) { + try { + await requestMatrixJson( + `/_matrix/client/v3/join/${encodeURIComponent(target)}`, + serviceLogin.accessToken, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({}), + } + ) + + return { ok: true, status: "joined_client", roomId: target } + } catch (clientErr: any) { + return { + ok: false, + status: "failed", + roomId: target, + error: clientErr.message || adminErr.message || "Service-Join fehlgeschlagen", + } + } + } + } + + const syncServiceJoinedTenantRooms = async () => { + const rooms = await server.db + .select({ + id: communicationRooms.id, + tenantId: communicationRooms.tenantId, + key: communicationRooms.key, + name: communicationRooms.name, + matrixRoomId: communicationRooms.matrixRoomId, + matrixAlias: communicationRooms.matrixAlias, + }) + .from(communicationRooms) + .where(and( + eq(communicationRooms.archived, false), + isNotNull(communicationRooms.matrixRoomId) + )) + + const results = [] + for (const room of rooms) { + const result = await ensureServiceUserJoinedRoom({ + roomId: room.matrixRoomId, + alias: room.matrixAlias, + }) + results.push({ + roomId: room.matrixRoomId, + roomKey: room.key, + roomName: room.name, + ...result, + }) + } + + return { + total: results.length, + joined: results.filter((result) => result.ok).length, + failed: results.filter((result) => !result.ok).length, + results, + } + } + const ensureCurrentUserJoinedRoom = async ( userId: string, tenantId: number | null, @@ -2253,6 +2333,7 @@ export function matrixService(server: FastifyInstance) { searchTenantRoomMessages, syncTenantRoomEvents, syncServiceRoomEvents, + syncServiceJoinedTenantRooms, sendTenantRoomMessage, sendTenantRoomReaction, editTenantRoomMessage,