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:
+37
-1
@@ -9,8 +9,13 @@ import { getJobDir } from "../lib/storage";
|
||||
import type { VideoJobData } from "../lib/types";
|
||||
import { formatYouTubeErrorForUser } from "../lib/youtube/errors";
|
||||
import { uploadToYouTube } from "../lib/youtube/upload";
|
||||
import { deliverJobWebhook } from "../lib/webhooks";
|
||||
|
||||
async function updateJobStatus(jobId: string) {
|
||||
const job = await prisma.job.findUniqueOrThrow({
|
||||
where: { id: jobId },
|
||||
select: { webhookUrl: true },
|
||||
});
|
||||
const items = await prisma.jobItem.findMany({ where: { jobId } });
|
||||
const completed = items.filter((i) => i.status === JobItemStatus.COMPLETED).length;
|
||||
const failed = items.filter((i) => i.status === JobItemStatus.FAILED).length;
|
||||
@@ -23,13 +28,29 @@ async function updateJobStatus(jobId: string) {
|
||||
else status = JobStatus.PARTIAL;
|
||||
}
|
||||
|
||||
const completedAt = completed + failed === total ? new Date() : null;
|
||||
await prisma.job.update({
|
||||
where: { id: jobId },
|
||||
data: {
|
||||
status,
|
||||
completedAt: completed + failed === total ? new Date() : null,
|
||||
completedAt,
|
||||
},
|
||||
});
|
||||
|
||||
if (completedAt) {
|
||||
const event =
|
||||
status === JobStatus.COMPLETED
|
||||
? "job.completed"
|
||||
: status === JobStatus.FAILED
|
||||
? "job.failed"
|
||||
: "job.partial";
|
||||
await deliverJobWebhook(job.webhookUrl, {
|
||||
event,
|
||||
jobId,
|
||||
status,
|
||||
completedAt: completedAt.toISOString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function processJobItem(data: VideoJobData) {
|
||||
@@ -136,6 +157,14 @@ async function processJobItem(data: VideoJobData) {
|
||||
data: { createdVideoCount: { increment: 1 } },
|
||||
});
|
||||
|
||||
await deliverJobWebhook(item.job.webhookUrl, {
|
||||
event: "job.item.completed",
|
||||
jobId: data.jobId,
|
||||
status: "COMPLETED",
|
||||
itemId: item.id,
|
||||
youtubeVideoId,
|
||||
});
|
||||
|
||||
await cleanupFiles([outputPath]);
|
||||
} catch (err) {
|
||||
const message = formatYouTubeErrorForUser(err);
|
||||
@@ -144,6 +173,13 @@ async function processJobItem(data: VideoJobData) {
|
||||
where: { id: item.id },
|
||||
data: { status: JobItemStatus.FAILED, error: message },
|
||||
});
|
||||
await deliverJobWebhook(item.job.webhookUrl, {
|
||||
event: "job.item.failed",
|
||||
jobId: data.jobId,
|
||||
status: "FAILED",
|
||||
itemId: item.id,
|
||||
error: message,
|
||||
});
|
||||
throw new Error(message);
|
||||
} finally {
|
||||
await updateJobStatus(data.jobId);
|
||||
|
||||
Reference in New Issue
Block a user