import Logger from "../../services/logger.js"; import { getResponse, StatusError } from "../../misc/fetch.js"; import { Webhooks } from "../../models/index.js"; import config from "../../config/index.js"; import { v4 as uuid } from "uuid"; import { createQueue, defaultJobOpts, processorTimeout } from "./index.js"; const logger = new Logger("webhook"); async function process(job) { if (job.data == null || Object.keys(job.data).length === 0) { job.opts.removeOnComplete = true; return "Skip (data was null or empty)"; } try { logger.debug(`delivering ${job.data.webhookId}`); const res = await getResponse({ url: job.data.to, method: "POST", headers: { "User-Agent": "Iceshrimp-Hooks", "X-Iceshrimp-Host": config.host, "X-Iceshrimp-Hook-Id": job.data.webhookId, "X-Iceshrimp-Hook-Secret": job.data.secret, "Content-Type": "application/json" }, body: JSON.stringify({ hookId: job.data.webhookId, userId: job.data.userId, eventId: job.data.eventId, createdAt: job.data.createdAt, type: job.data.type, body: job.data.content }) }); Webhooks.update({ id: job.data.webhookId }, { latestSentAt: new Date(), latestStatus: res.status }); return "Success"; } catch (res) { Webhooks.update({ id: job.data.webhookId }, { latestSentAt: new Date(), latestStatus: res instanceof StatusError ? res.statusCode : 1 }); if (res instanceof StatusError) { // 4xx if (!res.isRetryable) { return `${res.statusCode} ${res.statusMessage}`; } // 5xx etc. throw new Error(`${res.statusCode} ${res.statusMessage}`); } else { // DNS error, socket error, timeout ... throw res; } } } export const [webhookDeliverQueue, webhookDeliverInit] = createQueue("webhookDeliver", processorTimeout(process, 60), { limitPerSec: 64, concurrency: 64 }); export function webhookDeliverJob(webhook, type, content) { const data = { type, content, webhookId: webhook.id, userId: webhook.userId, to: webhook.url, secret: webhook.secret, createdAt: Date.now(), eventId: uuid() }; return webhookDeliverQueue.add("default", data, { attempts: 4, backoff: { type: "custom" }, ...defaultJobOpts }); }