import { restoreAgent } from '@/lib/oauth' import { requireSession } from '@/lib/session' import { createBlockEvent } from '@/lib/lexicon' import { canStartJobForDid, MAX_ACTIVE_JOBS_PER_USER, startBlockJob } from '@/lib/queue' import { generateId } from '@/lib/utils' import type { BlockCriteria } from '@/types' interface BlockRequestBody { postUri: string postUrl: string dids: string[] criteria: BlockCriteria } export async function POST(request: Request) { let session: { did: string } try { session = await requireSession() } catch { return Response.json({ error: 'Not authenticated' }, { status: 401 }) } let body: BlockRequestBody try { body = await request.json() } catch { return Response.json({ error: 'Invalid request body' }, { status: 400 }) } const { postUri, postUrl, dids, criteria } = body if (!postUri || !dids?.length) { return Response.json({ error: 'postUri and dids are required' }, { status: 400 }) } try { if (!canStartJobForDid(session.did)) { return Response.json( { error: `Too many active block jobs. Wait for one to finish before starting another. Limit: ${MAX_ACTIVE_JOBS_PER_USER}.` }, { status: 429 } ) } const agent = await restoreAgent(session.did) // Create the block event record in the user's PDS before starting the queue. // This records intent upfront — if the server restarts mid-queue, the record // still exists and can be used for status checking and retry. const { rkey: eventRkey } = await createBlockEvent(agent, session.did, { sourcePostUri: postUri, sourcePostUrl: postUrl, createdAt: new Date().toISOString(), criteria, stats: { total: dids.length, completed: 0, failed: 0 }, pendingDids: dids, blockedDids: [], failedDids: [], blockedRkeys: [], }) const jobId = generateId() await startBlockJob(jobId, session.did, eventRkey, dids) return Response.json({ jobId, eventRkey, total: dids.length }) } catch (err) { console.error('[api/blocks] failed:', err) return Response.json({ error: 'Failed to start block job' }, { status: 500 }) } }