← 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 });
}