feat: picdrop delivery — worker delivers on job completion, /api/deliver for manual, gallery default 'POSTER LEA', library bulk send + status badges

This commit is contained in:
2026-07-23 15:41:04 +00:00
parent 25d0a5cd97
commit 26c3e0ef07
4 changed files with 81 additions and 3 deletions
+44
View File
@@ -0,0 +1,44 @@
import { one, query } from './db';
import { getObject } from './storage';
import { loadConfig, uploadBuffer } from './picdrop';
// Standard-Galerie wie initial gebrieft.
const DEFAULT_GALLERY = process.env.PICDROP_DEFAULT_GALLERY || 'POSTER LEA';
async function galleryFor(item: { folder_id: string | null; job_id: string }): Promise<string> {
if (item.folder_id) {
const f = await one<{ picdrop_gallery: string | null }>('SELECT picdrop_gallery FROM folders WHERE id=$1', [item.folder_id]);
if (f?.picdrop_gallery) return f.picdrop_gallery;
}
const j = await one<{ recipe_snapshot: any }>('SELECT recipe_snapshot FROM jobs WHERE id=$1', [item.job_id]);
const g = j?.recipe_snapshot?.picdrop_gallery;
return g || DEFAULT_GALLERY;
}
/** Liefert ein fertiges Item an die passende Picdrop-Galerie aus. */
export async function deliverItem(itemId: string): Promise<{ ok: boolean; message: string }> {
const it = await one<any>('SELECT id, result_path, filename, folder_id, job_id FROM items WHERE id=$1', [itemId]);
if (!it?.result_path) return { ok: false, message: 'Kein Ergebnis vorhanden.' };
const cfg = await loadConfig();
if (!cfg) { await query(`UPDATE items SET delivery_status='failed' WHERE id=$1`, [itemId]); return { ok: false, message: 'Picdrop nicht konfiguriert.' }; }
await query(`UPDATE items SET delivery_status='pending' WHERE id=$1`, [itemId]);
try {
const gallery = await galleryFor(it);
const buf = await getObject(it.result_path);
await uploadBuffer(cfg, gallery, it.filename || `${it.id}.png`, buf);
await query(`UPDATE items SET delivery_status='delivered', delivered_at=now() WHERE id=$1`, [itemId]);
return { ok: true, message: `Ausgeliefert nach „${gallery}".` };
} catch (e: any) {
console.error('[delivery] Item', itemId, 'fehlgeschlagen:', e?.message || e);
await query(`UPDATE items SET delivery_status='failed' WHERE id=$1`, [itemId]);
return { ok: false, message: e?.message || 'Auslieferung fehlgeschlagen.' };
}
}
/** Alle noch offenen (pending) Auslieferungen eines Auftrags abarbeiten. */
export async function deliverPendingForJob(jobId: string): Promise<void> {
const items = await query<{ id: string }>(
`SELECT id FROM items WHERE job_id=$1 AND delivery_status='pending' AND status='done'`, [jobId]);
for (const it of items) await deliverItem(it.id);
}