// scanner/scanPhoto.js const path = require('path'); const fs = require('fs'); const fsp = require('fs/promises'); const { loadPreviousIndex, saveIndex } = require('./indexStore'); const scanCartella = require('./scanCartella'); const postWithAuth = require('./postWithAuth'); const { WEB_ROOT, SEND_PHOTOS, BASE_URL, WRITE_INDEX } = require('../config'); const createCleanupFunctions = require('./orphanCleanup'); async function scanPhoto(dir, userName, db) { console.log(`[SCAN] Avvio scanPhoto per user=${userName}`); const previousIndexTree = await loadPreviousIndex(); const nextIndexTree = JSON.parse(JSON.stringify(previousIndexTree || {})); const { buildIdsListForFolder, removeIdFromList, deleteThumbsById, deleteFromDB } = createCleanupFunctions(db); const photosRoot = path.resolve(__dirname, '..', '..', WEB_ROOT, 'photos'); const userDir = path.join(photosRoot, userName, 'original'); let changes = []; // --------------------------------------------------------- // SCAN DI UNA SINGOLA CARTELLA // --------------------------------------------------------- async function scanSingleFolder(user, cartella, absCartella) { console.log(`\n==============================================`); console.log(`[SCAN] CARTELLA → ${user}/${cartella}`); console.log(`[DEBUG] SCANSIONE CARTELLA PATH: ${absCartella}`); console.log("=============================================="); let idsIndex = await buildIdsListForFolder(user, cartella); const folderFiles = await scanCartella( user, cartella, absCartella, previousIndexTree ); for (const m of folderFiles) { const prev = previousIndexTree?.[m.user]?.[m.cartella]?.[m.id]; // 🔥 FILE INVARIATO if (prev && prev.hash === m._indexHash) { console.log("\n================ FILE INVARIATO ================"); console.log("[FILE]:", m.path); console.log("[ID OGGI]:", JSON.stringify(m.id)); console.log("[ID INDEX]:", JSON.stringify(prev.id)); console.log("[UGUALI?]:", m.id === prev.id); console.log("[LEN OGGI]:", m.id.length); console.log("[LEN INDEX]:", prev.id.length); console.log("----- BYTE PER BYTE -----"); const max = Math.min(m.id.length, prev.id.length, 64); for (let i = 0; i < max; i++) { const a = m.id[i]; const b = prev.id[i]; console.log( i.toString().padStart(2, "0"), a, b, a === b ? "==" : "!=" ); } console.log("----- idsIndex PRIMA -----"); console.log(idsIndex.map(x => JSON.stringify(x))); const found = idsIndex.includes(m.id); console.log("[ID PRESENTE IN idsIndex?]:", found); const newList = idsIndex.filter(x => x !== m.id); console.log("----- idsIndex DOPO -----"); console.log(newList.map(x => JSON.stringify(x))); idsIndex = newList; console.log("=================================================\n"); continue; } // 🔥 FILE NUOVO O MODIFICATO nextIndexTree[m.user] ??= {}; nextIndexTree[m.user][m.cartella] ??= {}; nextIndexTree[m.user][m.cartella][m.id] = { id: m.id, user: m.user, cartella: m.cartella, path: m.path, hash: m._indexHash }; idsIndex = removeIdFromList(idsIndex, m.id); changes.push(m); } // --------------------------------------------------------- // ORFANI // --------------------------------------------------------- if (idsIndex.length > 0) { console.log(`[ORPHAN] ID orfani trovati nella cartella ${cartella}:`); idsIndex.forEach(id => console.log(" -", id)); } else { console.log(`[ORPHAN] Nessun ID orfano nella cartella ${cartella}`); } for (const orphanId of idsIndex) { console.log(`\n[ORPHAN] Eliminazione ID → ${orphanId}`); const thumbsDeleted = await deleteThumbsById(orphanId); console.log(` → thumbsDeleted = ${thumbsDeleted}`); const dbDeleted = deleteFromDB(orphanId); console.log(` → dbDeleted = ${dbDeleted}`); const userTree = nextIndexTree[user]; if (userTree && userTree[cartella] && userTree[cartella][orphanId]) { delete userTree[cartella][orphanId]; console.log(` → nextIndexTree updated (removed ${orphanId})`); } console.log(`[ORPHAN] COMPLETATO → ${orphanId}`); } console.log(`==============================================\n`); } // --------------------------------------------------------- // SCAN SOTTOCARTELLE // --------------------------------------------------------- let entries = []; try { entries = await fsp.readdir(userDir, { withFileTypes: true }); } catch { console.log(`[SCAN] Nessuna directory per utente ${userName}`); return []; } for (const e of entries) { if (!e.isDirectory()) continue; const cartella = e.name; const absCartella = path.join(userDir, cartella); await scanSingleFolder(userName, cartella, absCartella); } // --------------------------------------------------------- // SALVO INDEX // --------------------------------------------------------- if (WRITE_INDEX) { await saveIndex(nextIndexTree); } // --------------------------------------------------------- // INVIO AL SERVER // --------------------------------------------------------- if (SEND_PHOTOS && BASE_URL && changes.length) { for (const p of changes) { try { await postWithAuth(`${BASE_URL}/photos`, p); } catch (err) { console.error('Errore invio:', err.message); } } } console.log(`SCAN COMPLETATA: ${changes.length} file aggiornati`); return changes; } module.exports = scanPhoto;