Files
firecrawl/apps/api/src/services/webhook.ts
T

163 lines
4.4 KiB
TypeScript
Raw Normal View History

2024-09-01 13:44:36 -03:00
import axios from "axios";
import { logger } from "../lib/logger";
2024-04-15 17:01:47 -04:00
import { supabase_service } from "./supabase";
2024-09-01 13:44:36 -03:00
import { WebhookEventType } from "../types";
2024-09-04 15:57:57 -03:00
import { configDotenv } from "dotenv";
import { z } from "zod";
import { webhookSchema } from "../controllers/v1/types";
2024-09-04 15:57:57 -03:00
configDotenv();
2024-04-15 17:01:47 -04:00
2024-09-01 13:44:36 -03:00
export const callWebhook = async (
teamId: string,
id: string,
data: any | null,
specified?: z.infer<typeof webhookSchema>,
2024-09-01 13:44:36 -03:00
v1 = false,
2024-09-01 15:06:36 -03:00
eventType: WebhookEventType = "crawl.page",
2024-12-11 19:51:08 -03:00
awaitWebhook: boolean = false,
2024-09-01 13:44:36 -03:00
) => {
2025-01-30 18:43:37 +01:00
if (specified) {
let subType = eventType.split(".")[1];
if (!specified.events.includes(subType as any)) {
return false;
}
}
2024-04-20 19:37:45 -07:00
try {
2024-09-01 13:44:36 -03:00
const selfHostedUrl = process.env.SELF_HOSTED_WEBHOOK_URL?.replace(
"{{JOB_ID}}",
2024-12-11 19:51:08 -03:00
id,
2024-09-01 13:44:36 -03:00
);
const useDbAuthentication = process.env.USE_DB_AUTHENTICATION === "true";
2024-12-11 19:46:11 -03:00
let webhookUrl =
specified ??
(selfHostedUrl ? webhookSchema.parse({ url: selfHostedUrl }) : undefined);
2024-06-05 10:38:05 -07:00
2024-08-16 23:42:40 +02:00
// Only fetch the webhook URL from the database if the self-hosted webhook URL and specified webhook are not set
2024-06-10 17:03:10 -07:00
// and the USE_DB_AUTHENTICATION environment variable is set to true
2024-08-16 23:42:40 +02:00
if (!webhookUrl && useDbAuthentication) {
2024-06-05 10:38:05 -07:00
const { data: webhooksData, error } = await supabase_service
.from("webhooks")
.select("url")
.eq("team_id", teamId)
.limit(1);
if (error) {
2024-11-07 20:57:33 +01:00
logger.error(
2024-12-11 19:51:08 -03:00
`Error fetching webhook URL for team ID: ${teamId}, error: ${error.message}`,
2024-09-01 13:44:36 -03:00
);
2024-06-05 10:38:05 -07:00
return null;
}
if (!webhooksData || webhooksData.length === 0) {
return null;
}
webhookUrl = webhooksData[0].url;
}
2024-12-11 19:46:11 -03:00
logger.debug("Calling webhook...", {
webhookUrl,
teamId,
specified,
v1,
eventType,
2024-12-11 19:51:08 -03:00
awaitWebhook,
2024-12-11 19:46:11 -03:00
});
2024-11-15 21:43:02 +01:00
2024-11-07 20:57:33 +01:00
if (!webhookUrl) {
return null;
}
let dataToSend: any[] = [];
2024-09-01 13:52:34 -03:00
if (
data &&
data.result &&
data.result.links &&
data.result.links.length !== 0
) {
2024-06-05 10:38:05 -07:00
for (let i = 0; i < data.result.links.length; i++) {
2024-08-25 14:05:46 +02:00
if (v1) {
2024-12-11 19:46:11 -03:00
dataToSend.push(data.result.links[i].content);
2024-08-25 14:05:46 +02:00
} else {
dataToSend.push({
content: data.result.links[i].content.content,
markdown: data.result.links[i].content.markdown,
2024-12-11 19:51:08 -03:00
metadata: data.result.links[i].content.metadata,
2024-08-25 14:05:46 +02:00
});
}
2024-06-05 10:38:05 -07:00
}
2024-04-15 17:01:47 -04:00
}
2024-09-01 15:06:36 -03:00
if (awaitWebhook) {
try {
await axios.post(
webhookUrl.url,
2024-09-01 15:06:36 -03:00
{
success: !v1
? data.success
: eventType === "crawl.page"
2024-12-11 19:46:11 -03:00
? data.success
: true,
2024-09-01 15:06:36 -03:00
type: eventType,
[v1 ? "id" : "jobId"]: id,
data: dataToSend,
error: !v1
? data?.error || undefined
: eventType === "crawl.page"
2024-12-11 19:46:11 -03:00
? data?.error || undefined
2024-12-11 19:51:08 -03:00
: undefined,
2024-12-12 13:30:00 -03:00
metadata: webhookUrl.metadata || undefined,
2024-09-01 13:52:34 -03:00
},
2024-09-01 15:06:36 -03:00
{
headers: {
"Content-Type": "application/json",
2024-12-11 19:51:08 -03:00
...webhookUrl.headers,
2024-09-01 15:06:36 -03:00
},
2024-12-11 19:51:08 -03:00
timeout: v1 ? 10000 : 30000, // 10 seconds timeout (v1)
},
2024-09-01 15:06:36 -03:00
);
} catch (error) {
2024-11-07 20:57:33 +01:00
logger.error(
2024-12-11 19:51:08 -03:00
`Axios error (0) sending webhook for team ID: ${teamId}, error: ${error.message}`,
2024-09-01 13:52:34 -03:00
);
2024-09-01 15:06:36 -03:00
}
} else {
axios
.post(
webhookUrl.url,
2024-09-01 15:06:36 -03:00
{
success: !v1
? data.success
: eventType === "crawl.page"
2024-12-11 19:46:11 -03:00
? data.success
: true,
2024-09-01 15:06:36 -03:00
type: eventType,
[v1 ? "id" : "jobId"]: id,
data: dataToSend,
error: !v1
? data?.error || undefined
: eventType === "crawl.page"
2024-12-11 19:46:11 -03:00
? data?.error || undefined
2024-12-11 19:51:08 -03:00
: undefined,
2024-12-12 13:30:00 -03:00
metadata: webhookUrl.metadata || undefined,
2024-09-01 15:06:36 -03:00
},
{
headers: {
"Content-Type": "application/json",
2024-12-11 19:51:08 -03:00
...webhookUrl.headers,
},
},
2024-09-01 15:06:36 -03:00
)
.catch((error) => {
2024-11-07 20:57:33 +01:00
logger.error(
2024-12-11 19:51:08 -03:00
`Axios error sending webhook for team ID: ${teamId}, error: ${error.message}`,
2024-09-01 15:06:36 -03:00
);
});
}
2024-04-20 19:37:45 -07:00
} catch (error) {
2024-11-07 20:57:33 +01:00
logger.debug(
2024-12-11 19:51:08 -03:00
`Error sending webhook for team ID: ${teamId}, error: ${error.message}`,
2024-09-01 13:44:36 -03:00
);
2024-04-20 19:37:45 -07:00
}
};