export const runtime = "nodejs"; import { NextResponse } from "next/server"; import { requireSession } from "@/lib/auth/require"; import { listMessages, sendMessage } from "@/lib/chat/service"; import { saveChatAttachment } from "@/lib/chat/attachments"; export async function GET(_request: Request, { params }: { params: Promise<{ id: string }> }) { const { session, response } = await requireSession(); if (!session) return response; const { id } = await params; const messages = await listMessages(id, session.user.id); if (messages === null) return NextResponse.json({ error: "Forbidden" }, { status: 403 }); return NextResponse.json(messages); } const MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024; /** Один эндпоинт на текст/вложение/голосовое — форма всегда multipart, поля опциональны в зависимости от того, что отправляет клиент. */ export async function POST(request: Request, { params }: { params: Promise<{ id: string }> }) { const { session, response } = await requireSession(); if (!session) return response; const { id } = await params; const form = await request.formData().catch(() => null); if (!form) return NextResponse.json({ error: "Некорректные данные" }, { status: 400 }); const body = form.get("body"); const replyToMessageId = form.get("replyToMessageId"); const file = form.get("file"); const kindRaw = form.get("kind"); const bodyText = typeof body === "string" && body.trim() ? body.trim() : undefined; if (!bodyText && !(file instanceof File)) { return NextResponse.json({ error: "Пустое сообщение" }, { status: 400 }); } if (file instanceof File && file.size > MAX_ATTACHMENT_BYTES) { return NextResponse.json({ error: "Файл слишком большой (максимум 25 МБ)" }, { status: 400 }); } let message; try { message = await sendMessage(id, session.user.id, { body: bodyText, replyToMessageId: typeof replyToMessageId === "string" && replyToMessageId ? replyToMessageId : undefined, }); } catch (err) { const msg = err instanceof Error ? err.message : "Не удалось отправить сообщение"; return NextResponse.json({ error: msg }, { status: 403 }); } let attachment = null; if (file instanceof File) { const kind = kindRaw === "voice" ? "voice" : file.type.startsWith("image/") ? "image" : "file"; const durationRaw = form.get("durationSeconds"); const content = Buffer.from(await file.arrayBuffer()); attachment = await saveChatAttachment({ messageId: message.id, kind, fileName: file.name || (kind === "voice" ? "voice-message.webm" : "file"), mimeType: file.type || "application/octet-stream", content, durationSeconds: typeof durationRaw === "string" ? Number(durationRaw) : undefined, }); } return NextResponse.json({ message, attachment }, { status: 201 }); }