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