2026-07-19 00:29:30 +08:00
import { NextResponse } from "next/server" ;
import { db } from "@/lib/db" ;
import { withinRateLimit } from "@/lib/rate-limit" ;
import { webhookSecretMatches } from "@/lib/webhook" ;
2026-07-19 01:12:16 +08:00
import { queuePull } from "@/lib/sync" ;
2026-07-19 00:29:30 +08:00
export async function POST ( request : Request , { params } : { params : Promise < { sourceId : string ; secret : string } > }) {
const { sourceId , secret } = await params ;
const id = Number ( sourceId );
2026-07-19 01:12:16 +08:00
const source = db . prepare ( "SELECT id, webhook_secret_hash FROM sources WHERE id=? AND is_enabled=1" ). get ( id ) as { id : number ; webhook_secret_hash : string | null } | undefined ;
2026-07-19 00:29:30 +08:00
if ( ! source || ! webhookSecretMatches ( secret , source . webhook_secret_hash )) return NextResponse . json ({ error : "Not found" }, { status : 404 });
const forwarded = request . headers . get ( "x-forwarded-for" ) ? . split ( "," )[ 0 ]. trim () || "unknown" ;
if ( ! withinRateLimit ( `webhook: ${ id } : ${ forwarded } ` )) return NextResponse . json ({ error : "Too many requests" }, { status : 429 });
let payload : unknown = {};
try { payload = await request . json (); } catch { /* Memos payload is optional; a pull reconciles source state. */ }
db . prepare ( "UPDATE sources SET last_webhook_at=CURRENT_TIMESTAMP WHERE id=?" ). run ( id );
2026-07-19 01:12:16 +08:00
const queued = queuePull ( id , "webhook" , payload );
return NextResponse . json ({ ok : true , queued });
2026-07-19 00:29:30 +08:00
}