Files
buzz-sheet/app/api/commission/tickets/[id]/reactions/route.ts
T
2026-10-02 17:33:14 +07:00

36 lines
2.0 KiB
TypeScript

import { and, eq } from "drizzle-orm";
import { getDb } from "@/db";
import { commissionMessages, commissionReactions } from "@/db/schema";
import { notifyCommission } from "@/lib/commission/server";
import { authorizeTicket } from "@/lib/commission/tickets";
import { errorResponse, HttpError, readJson, requireSameOrigin } from "@/lib/security/http";
import { limitRequest } from "@/lib/security/rate-limit";
import { isSingleEmoji } from "@/lib/commission/reaction";
import * as z from "zod";
const inputSchema = z.object({ messageId: z.uuid(), emoji: z.string().refine(isSingleEmoji) });
export async function POST(request: Request, context: RouteContext<"/api/commission/tickets/[id]/reactions">) {
try {
requireSameOrigin(request);
const { id } = await context.params;
const { ticket, user } = await authorizeTicket(id);
if (ticket.status !== "open") throw new HttpError(409, "ticket-closed");
await limitRequest("commission-reaction", user.id, 60);
const parsed = inputSchema.safeParse(await readJson(request));
if (!parsed.success) throw new HttpError(400, "invalid-reaction");
const [message] = await getDb().select({ id: commissionMessages.id }).from(commissionMessages)
.where(and(eq(commissionMessages.id, parsed.data.messageId), eq(commissionMessages.ticketId, id))).limit(1);
if (!message) throw new HttpError(404, "message-not-found");
const where = and(eq(commissionReactions.messageId, message.id),
eq(commissionReactions.userId, user.id), eq(commissionReactions.emoji, parsed.data.emoji));
const [existing] = await getDb().select().from(commissionReactions).where(where).limit(1);
if (existing) await getDb().delete(commissionReactions).where(where);
else await getDb().insert(commissionReactions).values({
messageId: message.id, userId: user.id, emoji: parsed.data.emoji,
}).onConflictDoNothing();
await notifyCommission(id, ticket.userId);
return Response.json({ active: !existing });
} catch (cause) { return errorResponse(cause); }
}