176 lines
7 KiB
Text
176 lines
7 KiB
Text
// 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}`);
|
||
|
||
// Log di configurazione (utile per diagnosi)
|
||
console.log('[SCAN] Config:', {
|
||
WEB_ROOT,
|
||
SEND_PHOTOS,
|
||
BASE_URL,
|
||
WRITE_INDEX
|
||
});
|
||
|
||
// 1) Carico l’indice precedente (fonte unica durante la run)
|
||
const previousIndexTree = await loadPreviousIndex(); // <— RAM source
|
||
// 2) Clono l’indice per costruire il nuovo
|
||
const nextIndexTree = JSON.parse(JSON.stringify(previousIndexTree || {}));
|
||
|
||
// Funzioni di cleanup (solo thumbs + DB)
|
||
// NOTA: con Opzione A NON leggiamo più l'indice da file e NON aggiorniamo index.json "in itinere"
|
||
const {
|
||
// buildIdsListForFolder, // <— NON usato in Opzione A
|
||
removeIdFromList,
|
||
deleteThumbsById,
|
||
deleteFromDB
|
||
// deleteFromIndexById // <— NON usato in Opzione A
|
||
} = createCleanupFunctions(db); // [1](https://electrolux-my.sharepoint.com/personal/fabio_micheluz_electrolux_com/Documents/File%20di%20Microsoft%20Copilot%20Chat/orphanCleanup.js.txt)
|
||
|
||
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("==============================================");
|
||
|
||
// Costruisci idsIndex dall'indice in RAM (previousIndexTree)
|
||
// Fonte unica di verità per questa run → evita drift con il file su disco.
|
||
let idsIndex = Object.keys(previousIndexTree?.[user]?.[cartella] || {})
|
||
.filter(k => k !== '_folderHash'); // <— niente metadati
|
||
console.log(`[ORPHAN] ID iniziali in RAM (${idsIndex.length}):`);
|
||
idsIndex.forEach(id => console.log(" -", id));
|
||
|
||
// File reali trovati nella cartella
|
||
const folderFiles = await scanCartella(
|
||
user,
|
||
cartella,
|
||
absCartella,
|
||
previousIndexTree
|
||
); // [2](https://electrolux-my.sharepoint.com/personal/fabio_micheluz_electrolux_com/Documents/File%20di%20Microsoft%20Copilot%20Chat/scanCartella.js.txt)
|
||
|
||
for (const m of folderFiles) {
|
||
const prev = previousIndexTree?.[m.user]?.[m.cartella]?.[m.id];
|
||
|
||
// 🔥 FILE INVARIATO
|
||
if (prev && prev.hash === m._indexHash) {
|
||
console.log(`[SCAN] SKIP (unchanged) → ${m.path}`);
|
||
// Rimuovo SOLO dalla lista orfani (dalla RAM)
|
||
idsIndex = removeIdFromList(idsIndex, m.id); // [1](https://electrolux-my.sharepoint.com/personal/fabio_micheluz_electrolux_com/Documents/File%20di%20Microsoft%20Copilot%20Chat/orphanCleanup.js.txt)
|
||
continue;
|
||
}
|
||
|
||
// 🔥 FILE NUOVO O MODIFICATO → aggiorno nextIndexTree
|
||
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
|
||
};
|
||
|
||
// Rimuovo dalla lista orfani (in RAM)
|
||
idsIndex = removeIdFromList(idsIndex, m.id); // [1](https://electrolux-my.sharepoint.com/personal/fabio_micheluz_electrolux_com/Documents/File%20di%20Microsoft%20Copilot%20Chat/orphanCleanup.js.txt)
|
||
changes.push(m);
|
||
}
|
||
|
||
// ---------------------------------------------------------
|
||
// ORFANI → rimuovo SOLO da nextIndexTree + thumbs + DB
|
||
// ---------------------------------------------------------
|
||
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}`);
|
||
|
||
// 1) Cancello thumbs
|
||
const thumbsDeleted = await deleteThumbsById(orphanId); // [1](https://electrolux-my.sharepoint.com/personal/fabio_micheluz_electrolux_com/Documents/File%20di%20Microsoft%20Copilot%20Chat/orphanCleanup.js.txt)
|
||
console.log(` → thumbsDeleted = ${thumbsDeleted}`);
|
||
|
||
// 2) Cancello dal DB
|
||
const dbDeleted = deleteFromDB(orphanId); // [1](https://electrolux-my.sharepoint.com/personal/fabio_micheluz_electrolux_com/Documents/File%20di%20Microsoft%20Copilot%20Chat/orphanCleanup.js.txt)
|
||
console.log(` → dbDeleted = ${dbDeleted}`);
|
||
|
||
// 3) Cancello SOLO da nextIndexTree (in RAM)
|
||
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 SOLO SOTTOCARTELLE — niente _root
|
||
// ---------------------------------------------------------
|
||
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 SOLO nextIndexTree (scrittura unica a fine run)
|
||
// ---------------------------------------------------------
|
||
if (WRITE_INDEX) {
|
||
await saveIndex(nextIndexTree); // [1](https://electrolux-my.sharepoint.com/personal/fabio_micheluz_electrolux_com/Documents/File%20di%20Microsoft%20Copilot%20Chat/orphanCleanup.js.txt)
|
||
}
|
||
|
||
// ---------------------------------------------------------
|
||
// 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;
|