Something went wrong. Try again.
FlockOff is a mass-block tool for the Atmosphere flockoff.app
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283import { requireSession } from '@/lib/session'import { restoreAgent } from '@/lib/oauth'import { requireListScopes } from '@/lib/scope-gate'import { getListSubscriptionRkey, unsubscribeFromList, listBlockEvents, updateBlockEvent } from '@/lib/lexicon'
export async function DELETE(request: Request) { let session: { did: string } try { session = await requireSession() } catch { return Response.json({ error: 'Not authenticated' }, { status: 401 }) }
let body: { listUri: string } try { body = await request.json() } catch { return Response.json({ error: 'Invalid request body' }, { status: 400 }) }
const { listUri } = body if (!listUri) { return Response.json({ error: 'listUri is required' }, { status: 400 }) }
// Validate this list belongs to the session user const ownerDid = listUri.split('/')[2] if (ownerDid !== session.did) { return Response.json({ error: 'You can only delete your own lists' }, { status: 403 }) }
const rkey = listUri.split('/').pop() if (!rkey) { return Response.json({ error: 'Invalid list URI' }, { status: 400 }) }
try { const scopeGate = await requireListScopes(session.did) if (scopeGate) return scopeGate
const agent = await restoreAgent(session.did)
// Unsubscribe first if subscribed (best-effort) try { const subscriptionRkey = await getListSubscriptionRkey(agent, session.did, listUri) if (subscriptionRkey) { await unsubscribeFromList(agent, session.did, subscriptionRkey) } } catch { // Non-fatal — proceed with deletion even if unsubscribe fails }
// Delete the list record itself await agent.com.atproto.repo.deleteRecord({ repo: session.did, collection: 'app.bsky.graph.list', rkey, })
// Listitem records are left orphaned (harmless without the list record)
// Clear listUri from any block event that references this list, so the // event detail page doesn't show a broken link after deletion. try { const events = await listBlockEvents(agent, session.did) const matches = events.filter((e) => e.record.listUri === listUri) for (const match of matches) { await updateBlockEvent(agent, session.did, match.rkey, { ...match.record, listUri: undefined, }) } } catch { // Non-fatal — list is deleted, event reference cleanup is best-effort }
return Response.json({ deleted: true }) } catch (err) { console.error('[api/list/delete]', err) return Response.json({ error: 'Failed to delete list' }, { status: 500 }) }}