← back to Norma
app/api/social/publish/route.ts
71 lines
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
import { requireRole } from '@/lib/require-role';
import { buildInternalAuthHeader } from '@/lib/cron-auth';
/**
* POST /api/social/publish
* Publish a draft post to its target platform.
* Dispatches to Twitter (9804), Bluesky (9806), Facebook (9808), or Instagram (9810) agents.
*/
export async function POST(request: NextRequest) {
const auth = requireRole(request, 'admin');
if (auth instanceof NextResponse) return auth;
const { post_id, cross_post_group } = await request.json();
if (cross_post_group) {
const result = await query(
`UPDATE social_posts
SET status = 'queued', updated_at = NOW()
WHERE cross_post_group = $1 AND status IN ('draft', 'scheduled')
RETURNING *`,
[cross_post_group]
);
return NextResponse.json({ published: result.rows, count: result.rows.length });
}
if (!post_id) {
return NextResponse.json({ error: 'post_id or cross_post_group required' }, { status: 400 });
}
const postResult = await query(`SELECT * FROM social_posts WHERE id = $1`, [post_id]);
if (postResult.rows.length === 0) {
return NextResponse.json({ error: 'Post not found' }, { status: 404 });
}
const post = postResult.rows[0];
const agentPorts: Record<string, number> = { twitter: 9804, bluesky: 9806, facebook: 9808, instagram: 9810 };
const agentPort = agentPorts[post.platform];
let agentResult = null;
if (agentPort) {
try {
const res = await fetch(`http://127.0.0.1:${agentPort}/skills/post`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: buildInternalAuthHeader(),
},
body: JSON.stringify({
text: post.body,
hashtags: post.hashtags,
link_url: post.link_url,
}),
signal: AbortSignal.timeout(15000),
});
agentResult = await res.json();
} catch (err) {
console.error(`[social/publish] Agent call failed for ${post.platform}:`, (err as Error).message);
}
}
const newStatus = agentResult?.success ? 'published' : 'queued';
await query(
`UPDATE social_posts SET status = $1, published_at = CASE WHEN $1 = 'published' THEN NOW() ELSE published_at END, updated_at = NOW() WHERE id = $2`,
[newStatus, post_id]
);
return NextResponse.json({ post_id, platform: post.platform, status: newStatus, agent_result: agentResult });
}