import { and, eq, sql } from 'drizzle-orm' import { z } from 'zod' import { threadSubscriptions, uploadReactions, uploads } from '../../../db/schema' const bodySchema = z.object({ emoji: z.string().min(1).max(32), }) export default defineEventHandler(async (event) => { const user = await requireUser(event) const uploadId = getRouterParam(event, 'id') ?? '' const { emoji } = await readValidatedBody(event, bodySchema.parse) const db = useDb() const [upload] = await db .select({ id: uploads.id }) .from(uploads) .where(eq(uploads.id, uploadId)) .limit(1) if (!upload) { throw createError({ statusCode: 404, statusMessage: 'Upload nicht gefunden' }) } const existing = await db .select({ userId: uploadReactions.userId }) .from(uploadReactions) .where(and( eq(uploadReactions.uploadId, uploadId), eq(uploadReactions.userId, user.id), eq(uploadReactions.emoji, emoji), )) .limit(1) let active: boolean if (existing.length) { await db.delete(uploadReactions).where(and( eq(uploadReactions.uploadId, uploadId), eq(uploadReactions.userId, user.id), eq(uploadReactions.emoji, emoji), )) active = false } else { await db.transaction(async (tx) => { await tx.insert(uploadReactions).values({ uploadId, userId: user.id, emoji }) await ensureThreadSubscription(uploadId, user.id, tx) }) active = true } const [result] = await db .select({ total: sql`count(*)` }) .from(uploadReactions) .where(and(eq(uploadReactions.uploadId, uploadId), eq(uploadReactions.emoji, emoji))) const count = Number(result?.total ?? 0) broadcastToAll({ type: 'upload-reaction', uploadId, emoji, actorId: user.id, actorName: user.name, active, count, }) const [subscription] = await db.select({ enabled: threadSubscriptions.enabled }).from(threadSubscriptions) .where(and(eq(threadSubscriptions.uploadId, uploadId), eq(threadSubscriptions.userId, user.id))).limit(1) return { active, count, isSubscribed: subscription?.enabled ?? false } })