import { db } from '../config/database.js'; import { events, galleryImages, contentSections } from '../db/schema.js'; import { AssetService } from './asset.service.js'; const assets = new AssetService(); /** * Loescht eine Bilddatei, sofern sie von keinem Datensatz mehr benutzt wird. * Muss NACH dem Loeschen bzw. Aktualisieren der Zeile aufgerufen werden. */ export async function dropImageIfUnused(url: string | null | undefined): Promise { if (!url) return false; const referenced = await collectReferencedImageUrls(); if (referenced.has(url)) return false; return assets.deleteImage(url); } /** * Sammelt jede Bild-URL, die irgendwo in der Datenbank vorkommt. * * Bewusst ueber ALLE Zeilen, nicht nur die veroeffentlichten - sonst wuerde * ein unveroeffentlichtes Event sein Bild verlieren, sobald jemand publisht. * * Die Content-Sections enthalten beliebiges JSON (Welcome-Bild, Monatshit, * Whiskey-Bilder), deshalb wird es rekursiv nach Bildpfaden durchsucht. */ export async function collectReferencedImageUrls(): Promise> { const urls = new Set(); for (const row of (await db.select().from(events)) as any[]) { if (row.imageUrl) urls.add(row.imageUrl); } for (const row of (await db.select().from(galleryImages)) as any[]) { if (row.imageUrl) urls.add(row.imageUrl); } for (const row of (await db.select().from(contentSections)) as any[]) { collectFromJson(row.contentJson, urls); } return urls; } /** Alle Bildpfade aus einem beliebigen Content-JSON. */ export function extractImageUrls(value: any): Set { const out = new Set(); collectFromJson(value, out); return out; } function collectFromJson(value: any, out: Set): void { if (typeof value === 'string') { if (value.startsWith('/images/')) { out.add(value); return; } // Je nach Treiber kommt das JSON als String zurueck if (value.startsWith('{') || value.startsWith('[')) { try { collectFromJson(JSON.parse(value), out); } catch { // kein JSON - ignorieren } } return; } if (Array.isArray(value)) { for (const entry of value) collectFromJson(entry, out); return; } if (value && typeof value === 'object') { for (const entry of Object.values(value)) collectFromJson(entry, out); } }