feat: multiple delivery targets (FTP/SFTP), per-preset wiring; The Frame -> TheFrame-Backgrounds gallery
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNQ8ghPfzAfsyVYd6HgFb6
This commit is contained in:
+15
-3
@@ -1,6 +1,6 @@
|
||||
import { one, query } from './db';
|
||||
import { getObject } from './storage';
|
||||
import { loadConfig, uploadBuffer } from './picdrop';
|
||||
import { loadConfig, loadTargetConfig, uploadBuffer, type PicdropCfg } from './picdrop';
|
||||
|
||||
// Standard-Galerie wie initial gebrieft.
|
||||
const DEFAULT_GALLERY = process.env.PICDROP_DEFAULT_GALLERY || 'POSTER LEA';
|
||||
@@ -17,12 +17,24 @@ async function galleryFor(item: { folder_id: string | null; job_id: string }): P
|
||||
return s?.picdrop_default_gallery || DEFAULT_GALLERY;
|
||||
}
|
||||
|
||||
/** Ziel-Zugang: 1) Ordner-Ziel 2) Rezept-Ziel 3) Standard-Picdrop (Einstellungen). */
|
||||
async function targetFor(item: { folder_id: string | null; job_id: string }): Promise<PicdropCfg | null> {
|
||||
if (item.folder_id) {
|
||||
const f = await one<{ delivery_target_id: string | null }>('SELECT delivery_target_id FROM folders WHERE id=$1', [item.folder_id]).catch(() => null);
|
||||
if (f?.delivery_target_id) { const c = await loadTargetConfig(f.delivery_target_id); if (c) return c; }
|
||||
}
|
||||
const j = await one<{ recipe_snapshot: any }>('SELECT recipe_snapshot FROM jobs WHERE id=$1', [item.job_id]);
|
||||
const tid = j?.recipe_snapshot?.delivery_target_id;
|
||||
if (tid) { const c = await loadTargetConfig(tid); if (c) return c; }
|
||||
return loadConfig(); // Standard-Picdrop
|
||||
}
|
||||
|
||||
/** 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.' }; }
|
||||
const cfg = await targetFor(it);
|
||||
if (!cfg) { await query(`UPDATE items SET delivery_status='failed' WHERE id=$1`, [itemId]); return { ok: false, message: 'Kein Auslieferungsziel konfiguriert.' }; }
|
||||
|
||||
await query(`UPDATE items SET delivery_status='pending' WHERE id=$1`, [itemId]);
|
||||
try {
|
||||
|
||||
@@ -22,6 +22,20 @@ export async function loadConfig(): Promise<PicdropCfg | null> {
|
||||
};
|
||||
}
|
||||
|
||||
/** Zusätzliches Auslieferungsziel aus delivery_targets. */
|
||||
export async function loadTargetConfig(id: string): Promise<PicdropCfg | null> {
|
||||
const s = await one<any>(`SELECT protocol, host, port, username, password_enc, base_path
|
||||
FROM delivery_targets WHERE id=$1`, [id]);
|
||||
if (!s?.host || !s?.username || !s?.password_enc) return null;
|
||||
let password = '';
|
||||
try { password = decrypt(s.password_enc); } catch { return null; }
|
||||
return {
|
||||
host: s.host, protocol: (s.protocol || 'sftp'),
|
||||
port: s.port || (s.protocol === 'ftps' ? 21 : 22),
|
||||
user: s.username, password, basePath: s.base_path || '/',
|
||||
};
|
||||
}
|
||||
|
||||
/** Verbindung testen: verbinden + Basisordner listen. */
|
||||
export async function testConnection(cfg: PicdropCfg): Promise<{ ok: boolean; message: string }> {
|
||||
try {
|
||||
|
||||
+7
-1
@@ -48,8 +48,14 @@ export async function seed(): Promise<void> {
|
||||
|
||||
await R('Nur bereinigen', ['clean'], 'keep', 'landscape', { is_default: true });
|
||||
await R('Poster 30×40', ['clean', 'format'], '30x40', 'portrait');
|
||||
await R('The Frame', ['clean', 'format'], 'theframe', 'landscape');
|
||||
await R('The Frame', ['clean', 'format'], 'theframe', 'landscape',
|
||||
{ delivery: 'both', picdrop_gallery: 'TheFrame-Backgrounds' });
|
||||
await R('Sticker 5 cm', ['clean', 'cutout', 'format', 'contour'], 'sticker5', 'landscape',
|
||||
{ contour_mm: 3 });
|
||||
}
|
||||
|
||||
// The-Frame-Rezept auf die eigene Galerie verdrahten (auch für bestehende Installationen).
|
||||
await query(
|
||||
`UPDATE recipes SET picdrop_gallery='TheFrame-Backgrounds', delivery='both'
|
||||
WHERE output_format='theframe' AND (picdrop_gallery IS NULL OR picdrop_gallery='')`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user