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