export const dynamic = 'force-dynamic' export const runtime = 'nodejs' import { NextResponse } from 'next/server' import { voiceBus } from '@/lib/voice-bus' import { addTimer, removeTimer, listActive } from '@/lib/timers' function bearerOk(req: Request): boolean { const expected = process.env.VOICE_API_KEY if (!expected) return false const auth = req.headers.get('authorization') || '' const token = auth.replace(/^Bearer\s+/i, '').trim() return token === expected } export async function GET(req: Request) { // Browser (cookie auth via middleware) will reach here — listing is public to logged-in user. // Script with bearer can also GET it. return NextResponse.json({ timers: listActive() }) } export async function POST(req: Request) { if (!bearerOk(req)) { return NextResponse.json({ error: 'unauthorized' }, { status: 401 }) } const body = await req.json().catch(() => null) if (!body || typeof body.action !== 'string') { return NextResponse.json({ error: 'action required' }, { status: 400 }) } if (body.action === 'start') { const seconds = Number(body.seconds) const label = typeof body.label === 'string' ? body.label.slice(0, 80) : 'Таймер' const agent = body.agent === 'lusya' ? 'lusya' : 'cosmo' if (!Number.isFinite(seconds) || seconds < 1 || seconds > 24 * 3600) { return NextResponse.json({ error: 'seconds must be 1..86400' }, { status: 400 }) } const endsAt = new Date(Date.now() + seconds * 1000).toISOString() const t = addTimer({ label, endsAt, agent }) voiceBus.emit('voice', { event: 'timer_start', timer: t, timestamp: new Date().toISOString(), }) return NextResponse.json({ timer: t }) } if (body.action === 'cancel') { const id = typeof body.id === 'string' ? body.id : '' if (!id) return NextResponse.json({ error: 'id required' }, { status: 400 }) const ok = removeTimer(id) if (ok) { voiceBus.emit('voice', { event: 'timer_cancel', id, timestamp: new Date().toISOString(), }) } return NextResponse.json({ cancelled: ok }) } return NextResponse.json({ error: `unknown action: ${body.action}` }, { status: 400 }) }