Add n8n community node, /api/v1/render alias, and job webhooks for OSS automation.
Payment-free self-hosted builds keep full API access with optional webhookUrl callbacks and the published n8n-nodes-songs2vid package source under integrations/n8n.
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Deliver optional job webhooks for n8n / automation consumers.
|
||||
* Fire-and-forget; failures are logged and never fail the encode/upload path.
|
||||
*/
|
||||
|
||||
type WebhookPayload = {
|
||||
event: "job.item.completed" | "job.item.failed" | "job.completed" | "job.failed" | "job.partial";
|
||||
jobId: string;
|
||||
status: string;
|
||||
itemId?: string;
|
||||
youtubeVideoId?: string | null;
|
||||
error?: string | null;
|
||||
completedAt?: string | null;
|
||||
};
|
||||
|
||||
export async function deliverJobWebhook(
|
||||
webhookUrl: string | null | undefined,
|
||||
payload: WebhookPayload,
|
||||
): Promise<void> {
|
||||
if (!webhookUrl?.trim()) return;
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(webhookUrl.trim());
|
||||
} catch {
|
||||
console.warn(`[webhook] invalid URL for job ${payload.jobId}`);
|
||||
return;
|
||||
}
|
||||
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
||||
console.warn(`[webhook] refused non-http(s) URL for job ${payload.jobId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch(url.toString(), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": "Songs2VID-Webhook/1.0",
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
signal: AbortSignal.timeout(8_000),
|
||||
});
|
||||
if (!res.ok) {
|
||||
console.warn(`[webhook] ${payload.jobId} → ${res.status}`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(
|
||||
`[webhook] delivery failed for ${payload.jobId}:`,
|
||||
err instanceof Error ? err.message : err,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user