← back to Norma

app/api/social/competitors/posts/route.ts

69 lines

import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
import { requireRole } from '@/lib/require-role';

/**
 * GET /api/social/competitors/posts
 *   ?competitor_id=  — filter to one competitor
 *   ?platform=       — filter by platform
 *   ?breaking_only=true — only posts flagged as breaking news
 *   ?days=7          — only posts from the last N days (default: no limit)
 *   ?limit=50        — max rows (default 50, max 200)
 *
 * Sorted by engagement_score DESC.
 * Returns competitor handle and display_name via JOIN.
 */
export async function GET(request: NextRequest) {
  const auth = requireRole(request, 'admin', 'staff');
  if (auth instanceof NextResponse) return auth;

  const { searchParams } = new URL(request.url);
  const competitor_id  = searchParams.get('competitor_id');
  const platform       = searchParams.get('platform');
  const breaking_only  = searchParams.get('breaking_only');
  const days           = searchParams.get('days');
  const limit          = Math.min(parseInt(searchParams.get('limit') || '50', 10), 200);

  const conditions: string[] = [];
  const values: unknown[] = [];
  let idx = 1;

  if (competitor_id) {
    conditions.push(`p.competitor_id = $${idx++}`);
    values.push(competitor_id);
  }
  if (platform) {
    conditions.push(`p.platform = $${idx++}`);
    values.push(platform);
  }
  if (breaking_only === 'true') {
    conditions.push(`p.is_breaking_news = true`);
  }
  if (days) {
    const n = parseInt(days, 10);
    if (!isNaN(n) && n > 0) {
      conditions.push(`p.published_at >= NOW() - ($${idx++} || ' days')::interval`);
      values.push(n);
    }
  }

  const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';

  const result = await query(
    `SELECT
       p.*,
       c.handle         AS competitor_handle,
       c.display_name   AS competitor_display_name,
       c.avatar_url     AS competitor_avatar_url,
       c.category       AS competitor_category
     FROM social_competitor_posts p
     JOIN social_competitors c ON c.id = p.competitor_id
     ${where}
     ORDER BY p.engagement_score DESC, p.published_at DESC
     LIMIT $${idx}`,
    [...values, limit]
  );

  return NextResponse.json({ posts: result.rows, count: result.rows.length });
}