103 lines
3.2 KiB
TypeScript
103 lines
3.2 KiB
TypeScript
// Follow this setup guide to integrate the Deno language server with your editor:
|
|
// https://deno.land/manual/getting_started/setup_your_environment
|
|
// This enables autocomplete, go to definition, etc.
|
|
|
|
// Setup type definitions for built-in Supabase Runtime APIs
|
|
import "@supabase/functions-js/edge-runtime.d.ts";
|
|
import OpenAI from "openai";
|
|
import { ResponseMetadata } from "../_shared/utils.ts";
|
|
import { handlePlanesEstudioResponse } from "./planes_estudio/index.ts";
|
|
|
|
console.log("Starting OpenAI webhook responses function");
|
|
const client = new OpenAI({
|
|
webhookSecret: Deno.env.get("OPENAI_WEBHOOK_SECRET"),
|
|
});
|
|
|
|
async function handleCompletedResponse(
|
|
event: OpenAI.Webhooks.ResponseCompletedWebhookEvent,
|
|
) {
|
|
const response_id = event.data.id;
|
|
const response = await client.responses.retrieve(response_id);
|
|
const metadata = response.metadata as ResponseMetadata | null;
|
|
|
|
if (!metadata || !metadata.tabla) {
|
|
console.warn("No se recibió metadata o tabla en la respuesta");
|
|
return;
|
|
}
|
|
|
|
switch (metadata.tabla) {
|
|
case "planes_estudio":
|
|
handlePlanesEstudioResponse(response);
|
|
break;
|
|
default:
|
|
console.warn("Tabla no reconocida:", metadata.tabla);
|
|
}
|
|
|
|
const output_text = response.output
|
|
.filter((item: any) => item.type === "message")
|
|
.flatMap((item: any) => item.content)
|
|
.filter((contentItem: any) => contentItem.type === "output_text")
|
|
.map((contentItem: any) => contentItem.text)
|
|
.join("");
|
|
|
|
console.log("Response output:", output_text);
|
|
}
|
|
|
|
Deno.serve(async (req) => {
|
|
const url = new URL(req.url);
|
|
const functionName = url.pathname.split("/").pop();
|
|
console.log(
|
|
`[${new Date().toISOString()}][${functionName}]: Request received`,
|
|
);
|
|
|
|
// Opcional: Solo permitir POST
|
|
if (req.method !== "POST") {
|
|
return new Response("Method Not Allowed", { status: 405 });
|
|
}
|
|
|
|
try {
|
|
// OpenAI requiere el body como texto crudo (string) para verificar la firma criptográfica
|
|
const payload = await req.text();
|
|
|
|
// Validar firma y parsear el evento. Deno maneja req.headers compatiblemente
|
|
const event = await client.webhooks.unwrap(payload, req.headers);
|
|
|
|
switch (event.type) {
|
|
case "response.completed": {
|
|
EdgeRuntime.waitUntil(handleCompletedResponse(event));
|
|
break;
|
|
}
|
|
case "response.cancelled": {
|
|
console.warn("Response cancelled:", event.data);
|
|
break;
|
|
}
|
|
case "response.failed": {
|
|
console.error("Response failed:", event.data);
|
|
break;
|
|
}
|
|
case "response.incomplete": {
|
|
console.warn("Response incomplete:", event.data);
|
|
break;
|
|
}
|
|
default: {
|
|
throw new Error(`Unhandled event type: ${event.type}`);
|
|
}
|
|
}
|
|
|
|
console.log(
|
|
`[${
|
|
new Date().toISOString()
|
|
}][${functionName}]: Request processed successfully`,
|
|
);
|
|
return new Response("OK", { status: 200 });
|
|
} catch (error) {
|
|
if (error instanceof OpenAI.InvalidWebhookSignatureError) {
|
|
console.error("Invalid signature:", error.message);
|
|
return new Response("Invalid signature", { status: 400 });
|
|
} else {
|
|
console.error("Internal Error:", error);
|
|
return new Response("Internal Server Error", { status: 500 });
|
|
}
|
|
}
|
|
});
|