import { getDmHistory, markDmsAsRead } from "../../../db/chat"; import { getProfile } from "../../../db/profile"; /** Roh-Reaktionen ({userId,emoji}[]) → aggregiert pro Emoji für die UI-Pills. */ function aggregateReactions( reactions: { userId: string; emoji: string }[], myId: string, ): { emoji: string; count: number; mine: boolean }[] { const map = new Map(); for (const r of reactions) { const e = map.get(r.emoji) ?? { emoji: r.emoji, count: 0, mine: false }; e.count++; if (r.userId === myId) e.mine = true; map.set(r.emoji, e); } return [...map.values()]; } /** GET /api/chat/dm/[userId]?page=1 */ export default defineEventHandler(async (event) => { const user = await requireUser(event); const partnerId = getRouterParam(event, "userId"); if (!partnerId) throw createError({ statusCode: 400, message: "userId fehlt" }); const page = Math.max(1, parseInt((getQuery(event).page as string) || "1")); const [messages, partnerProfile] = await Promise.all([ getDmHistory(user.id, partnerId, page), getProfile(partnerId), markDmsAsRead(partnerId, user.id), ]); return { partner: partnerProfile ? { id: partnerProfile.id, nickname: partnerProfile.nickname ?? partnerProfile.username ?? "Anonym", username: partnerProfile.username ?? "anonym", avatar: partnerProfile.avatar, } : { id: partnerId, nickname: "Anonym", username: "anonym", avatar: null }, messages: [...messages].reverse().map((m) => ({ id: m.id, senderId: m.senderId, receiverId: m.receiverId, // Bei Soft-Delete keinen Inhalt mehr ausliefern — Frontend zeigt Tombstone. content: m.deletedAt ? "" : m.content, createdAt: m.createdAt, isOwn: m.senderId === user.id, readAt: m.readAt, deleted: m.deletedAt != null, reactions: aggregateReactions(m.reactions, user.id), attachmentUrl: m.deletedAt ? null : m.attachmentUrl, attachmentType: m.deletedAt ? null : m.attachmentType, attachmentName: m.deletedAt ? null : m.attachmentName, likesCount: m.likesCount, replyTo: m.replyTo ? { id: m.replyTo.id, senderId: m.replyTo.senderId, content: m.replyTo.content, } : null, })), }; });