← back to Norma
app/api/slack/route.ts
92 lines
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
import { getBrand } from '@/lib/brand';
export async function POST(request: NextRequest) {
// Slack sends form-encoded data for slash commands
const formData = await request.formData();
const token = formData.get('token') as string;
const command = formData.get('command') as string;
const text = formData.get('text') as string;
// Validate verification token — fail closed if not configured
const verifyToken = process.env.SLACK_VERIFICATION_TOKEN;
if (!verifyToken || token !== verifyToken) {
return NextResponse.json(
{ response_type: 'ephemeral', text: 'Invalid token' },
{ status: 401 },
);
}
// Handle /norma-status command (also accept legacy /sdcc-status)
if (command === '/norma-status' || command === '/sdcc-status') {
const brand = await getBrand();
const [draftStats, partnerStats, newsStats] = await Promise.all([
query(
"SELECT COUNT(*) as total, COUNT(*) FILTER (WHERE status='sent') as sent, COUNT(*) FILTER (WHERE status='draft') as drafts FROM drafts",
).catch(() => ({ rows: [{ total: 0, sent: 0, drafts: 0 }] })),
query(
"SELECT COUNT(*) as total, COUNT(*) FILTER (WHERE status='active') as active FROM partners",
).catch(() => ({ rows: [{ total: 0, active: 0 }] })),
query(
"SELECT COUNT(*) as total, COUNT(*) FILTER (WHERE created_at > NOW() - INTERVAL '7 days') as recent FROM news_items",
).catch(() => ({ rows: [{ total: 0, recent: 0 }] })),
]);
const d = draftStats.rows[0];
const p = partnerStats.rows[0];
const n = newsStats.rows[0];
return NextResponse.json({
response_type: 'in_channel',
blocks: [
{
type: 'header',
text: { type: 'plain_text', text: `${brand.shortName} Platform Status` },
},
{
type: 'section',
fields: [
{
type: 'mrkdwn',
text: `*Email Drafts*\n${d.total} total (${d.drafts} drafts, ${d.sent} sent)`,
},
{
type: 'mrkdwn',
text: `*Partners*\n${p.total} total (${p.active} active)`,
},
],
},
{
type: 'section',
fields: [
{
type: 'mrkdwn',
text: `*News Items*\n${n.total} total (${n.recent} this week)`,
},
{
type: 'mrkdwn',
text: `*Platform*\n<http://45.61.58.125:7400|Open ${brand.shortName} App>`,
},
],
},
{
type: 'context',
elements: [
{
type: 'mrkdwn',
text: `Updated: <!date^${Math.floor(Date.now() / 1000)}^{date_short} at {time}|${new Date().toISOString()}>`,
},
],
},
],
});
}
// Unknown command
return NextResponse.json({
response_type: 'ephemeral',
text: `Unknown command: ${command}. Available: /norma-status (status dashboard)`,
});
}