import { usePrisma } from "../utils/prisma"; import { randomBytes } from "crypto"; // ─── Rooms ──────────────────────────────────────────────────────────────────── export async function listRooms(userId: string) { const db = usePrisma(); // Public rooms + private rooms user is member of return db.chatRoom.findMany({ where: { OR: [ { isPublic: true }, { members: { some: { userId, status: "active" } } }, ], }, orderBy: { updatedAt: "desc" }, include: { // Only include current user's membership to correctly determine isMember/myRole members: { where: { userId, status: "active" }, select: { userId: true, role: true }, }, messages: { orderBy: { createdAt: "desc" }, take: 1, select: { content: true, createdAt: true, userId: true }, }, }, }); } export async function getRoom(roomId: string) { const db = usePrisma(); return db.chatRoom.findUnique({ where: { id: roomId }, include: { members: { where: { status: "active" }, select: { userId: true, role: true, joinedAt: true }, }, }, }); } export async function createRoom(data: { name: string; description?: string; isPublic: boolean; joinMode: string; createdBy: string; avatarUrl?: string; }) { const db = usePrisma(); const inviteCode = randomBytes(4).toString("hex"); return db.chatRoom.create({ data: { name: data.name, description: data.description, isPublic: data.isPublic, joinMode: data.joinMode, inviteCode, createdBy: data.createdBy, avatarUrl: data.avatarUrl, memberCount: 1, members: { create: { userId: data.createdBy, role: "owner", status: "active" }, }, }, }); } export async function updateRoom( roomId: string, data: { name?: string; description?: string; joinMode?: string; avatarUrl?: string | null; }, ) { const db = usePrisma(); return db.chatRoom.update({ where: { id: roomId }, data }); } export async function deleteRoom(roomId: string) { const db = usePrisma(); return db.chatRoom.delete({ where: { id: roomId } }); } // ─── Membership ─────────────────────────────────────────────────────────────── export async function getMember(roomId: string, userId: string) { const db = usePrisma(); return db.chatRoomMember.findUnique({ where: { roomId_userId: { roomId, userId } }, }); } export async function getRoomMembers(roomId: string) { const db = usePrisma(); return db.chatRoomMember.findMany({ where: { roomId, status: "active" }, orderBy: { joinedAt: "asc" }, select: { userId: true, role: true, joinedAt: true }, }); } export async function joinRoom( roomId: string, userId: string, status: "active" | "pending" = "active", ) { const db = usePrisma(); const member = await db.chatRoomMember.upsert({ where: { roomId_userId: { roomId, userId } }, create: { roomId, userId, role: "member", status }, update: { status }, }); if (status === "active") { await db.chatRoom.update({ where: { id: roomId }, data: { memberCount: { increment: 1 } }, }); } return member; } export async function leaveRoom(roomId: string, userId: string) { const db = usePrisma(); await db.chatRoomMember.delete({ where: { roomId_userId: { roomId, userId } }, }); await db.chatRoom.update({ where: { id: roomId }, data: { memberCount: { decrement: 1 } }, }); } export async function approveRequest(roomId: string, userId: string) { const db = usePrisma(); await db.chatRoomMember.update({ where: { roomId_userId: { roomId, userId } }, data: { status: "active" }, }); await db.chatRoom.update({ where: { id: roomId }, data: { memberCount: { increment: 1 } }, }); } export async function rejectRequest(roomId: string, userId: string) { const db = usePrisma(); await db.chatRoomMember.delete({ where: { roomId_userId: { roomId, userId } }, }); } export async function getPendingRequests(roomId: string) { const db = usePrisma(); return db.chatRoomMember.findMany({ where: { roomId, status: "pending" }, orderBy: { joinedAt: "asc" }, select: { userId: true, joinedAt: true }, }); } export async function findRoomByInviteCode(code: string) { const db = usePrisma(); return db.chatRoom.findUnique({ where: { inviteCode: code } }); } export async function banMember(roomId: string, userId: string) { const db = usePrisma(); const member = await db.chatRoomMember.findUnique({ where: { roomId_userId: { roomId, userId } }, }); if (!member) return; await db.chatRoomMember.update({ where: { roomId_userId: { roomId, userId } }, data: { status: "banned" }, }); if (member.status === "active") { await db.chatRoom.update({ where: { id: roomId }, data: { memberCount: { decrement: 1 } }, }); } } export async function setMemberRole( roomId: string, userId: string, role: "admin" | "member", ) { const db = usePrisma(); return db.chatRoomMember.update({ where: { roomId_userId: { roomId, userId } }, data: { role }, }); } // ─── Room Messages ──────────────────────────────────────────────────────────── export async function getRoomMessages( roomId: string, cursor?: string, limit = 50, ) { const db = usePrisma(); return db.chatMessage.findMany({ where: { roomId }, orderBy: { createdAt: "desc" }, take: limit, ...(cursor ? { cursor: { id: cursor }, skip: 1 } : {}), select: { id: true, userId: true, content: true, replyToId: true, attachmentUrl: true, attachmentType: true, attachmentName: true, likesCount: true, createdAt: true, replyTo: { select: { id: true, userId: true, content: true }, }, }, }); } export async function createRoomMessage(data: { userId: string; roomId: string; content: string; replyToId?: string; attachmentUrl?: string; attachmentType?: string; attachmentName?: string; }) { const db = usePrisma(); const msg = await db.chatMessage.create({ data: { userId: data.userId, content: data.content, roomId: data.roomId, replyToId: data.replyToId || null, attachmentUrl: data.attachmentUrl || null, attachmentType: data.attachmentType || null, attachmentName: data.attachmentName || null, }, select: { id: true, userId: true, content: true, replyToId: true, attachmentUrl: true, attachmentType: true, attachmentName: true, likesCount: true, createdAt: true, replyTo: { select: { id: true, userId: true, content: true }, }, }, }); // Bump room updatedAt await db.chatRoom.update({ where: { id: data.roomId }, data: { updatedAt: new Date() }, }); return msg; } // ─── Likes ──────────────────────────────────────────────────────────────────── export async function toggleChatMessageLike(userId: string, messageId: string) { const db = usePrisma(); const existing = await db.chatMessageLike.findUnique({ where: { userId_messageId: { userId, messageId } }, }); if (existing) { await db.chatMessageLike.delete({ where: { userId_messageId: { userId, messageId } }, }); await db.chatMessage.update({ where: { id: messageId }, data: { likesCount: { decrement: 1 } }, }); return false; } await db.chatMessageLike.create({ data: { userId, messageId } }); await db.chatMessage.update({ where: { id: messageId }, data: { likesCount: { increment: 1 } }, }); return true; } export async function toggleDmLike(userId: string, messageId: string) { const db = usePrisma(); const existing = await db.directMessageLike.findUnique({ where: { userId_messageId: { userId, messageId } }, }); if (existing) { await db.directMessageLike.delete({ where: { userId_messageId: { userId, messageId } }, }); await db.directMessage.update({ where: { id: messageId }, data: { likesCount: { decrement: 1 } }, }); return false; } await db.directMessageLike.create({ data: { userId, messageId } }); await db.directMessage.update({ where: { id: messageId }, data: { likesCount: { increment: 1 } }, }); return true; } // ─── Seed Default Groups ────────────────────────────────────────────────────── const SYSTEM_USER = "00000000-0000-0000-0000-000000000000"; const DEFAULT_ROOMS = [ { name: "Erfolge & Meilensteine", description: "Teile deine Fortschritte und feiere mit der Community.", isPublic: true, }, { name: "Gemeinsam stark", description: "Der offene Raum – Austausch, Motivation und Zusammenhalt.", isPublic: true, }, ]; export async function seedDefaultRooms() { const db = usePrisma(); const existing = await db.chatRoom.findMany({ where: { isDefault: true }, select: { id: true }, }); if (existing.length >= DEFAULT_ROOMS.length) return; for (const room of DEFAULT_ROOMS) { const exists = await db.chatRoom.findFirst({ where: { name: room.name, isDefault: true }, }); if (exists) continue; await db.chatRoom.create({ data: { name: room.name, description: room.description, isPublic: true, isDefault: true, joinMode: "open", createdBy: SYSTEM_USER, inviteCode: randomBytes(4).toString("hex"), memberCount: 0, }, }); } }