161 lines
No EOL
4.3 KiB
JavaScript
161 lines
No EOL
4.3 KiB
JavaScript
// api_v1/scanner/scanPhotosUser.js
|
|
const path = require('path');
|
|
const fsp = require('fs/promises');
|
|
const scanPhoto = require('./scanPhoto');
|
|
const { log } = require('./logger');
|
|
const { WEB_ROOT, SUPPORTED_EXTS } = require('../config');
|
|
|
|
// ---------------------------------------------------------
|
|
// ETA CALCULATOR
|
|
// ---------------------------------------------------------
|
|
function computeETA(startTime, current, total) {
|
|
if (current === 0) return "calcolo...";
|
|
|
|
const elapsed = (Date.now() - startTime) / 1000; // sec
|
|
const rate = current / elapsed;
|
|
const remaining = (total - current) / rate;
|
|
|
|
const m = Math.floor(remaining / 60);
|
|
const s = Math.floor(remaining % 60);
|
|
|
|
return `${m}m ${s}s`;
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// PRIMA PASSATA: conta TUTTI i file reali (ricorsiva)
|
|
// ---------------------------------------------------------
|
|
async function countFilesUser(rootDir) {
|
|
let count = 0;
|
|
|
|
async function walk(dir) {
|
|
let entries = [];
|
|
try {
|
|
entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
} catch {
|
|
return;
|
|
}
|
|
|
|
for (const e of entries) {
|
|
const abs = path.join(dir, e.name);
|
|
|
|
if (e.isDirectory()) {
|
|
await walk(abs);
|
|
} else {
|
|
const ext = path.extname(e.name).toLowerCase();
|
|
if (SUPPORTED_EXTS.has(ext)) {
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
await walk(rootDir);
|
|
return count;
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// SECONDA PASSATA: scansiona SOLO le cartelle vere
|
|
// ---------------------------------------------------------
|
|
async function scanPhotosUser(userName, db) {
|
|
log(`🔵 Inizio scan TUTTE le cartelle per user=${userName}`);
|
|
|
|
const photosRoot = path.resolve(__dirname, '..', '..', WEB_ROOT, 'photos');
|
|
const userDir = path.join(photosRoot, userName, 'original');
|
|
const statusPath = path.join(photosRoot, "scan_status.json");
|
|
|
|
let entries = [];
|
|
try {
|
|
entries = await fsp.readdir(userDir, { withFileTypes: true });
|
|
} catch {
|
|
log(`❌ Nessuna directory per utente ${userName}`);
|
|
return [];
|
|
}
|
|
|
|
// 🔥 Filtra SOLO cartelle vere dentro "original"
|
|
const folders = entries.filter(e => e.isDirectory()).map(e => e.name);
|
|
|
|
// ---------------------------------------------------------
|
|
// 🔥 RIMOZIONE CARTELLE CANCELLATE DAL FILESYSTEM
|
|
// ---------------------------------------------------------
|
|
const createDeleteFolderFunctions = require('./deleteFolder');
|
|
const { deleteFolderForUser } = createDeleteFolderFunctions(db);
|
|
|
|
const dbFolders = await db('photos')
|
|
.where({ user: userName })
|
|
.distinct('cartella')
|
|
.pluck('cartella');
|
|
|
|
for (const dbFolder of dbFolders) {
|
|
if (!folders.includes(dbFolder)) {
|
|
log(`🗑️ Cartella rimossa dal filesystem: ${dbFolder}`);
|
|
await deleteFolderForUser(userName, dbFolder);
|
|
}
|
|
}
|
|
|
|
// 🔥 PRIMA PASSATA: conta i file reali
|
|
const TOTAL_FILES = await countFilesUser(userDir);
|
|
const CURRENT = { value: 0 };
|
|
const start = Date.now();
|
|
|
|
log(`📊 File totali da scansionare: ${TOTAL_FILES}`);
|
|
|
|
// Scrivi stato iniziale
|
|
await fsp.writeFile(
|
|
statusPath,
|
|
JSON.stringify({
|
|
current: 0,
|
|
total: TOTAL_FILES,
|
|
percent: 0,
|
|
eta: "calcolo..."
|
|
}, null, 2)
|
|
);
|
|
|
|
const allNewFiles = [];
|
|
|
|
// 🔥 SECONDA PASSATA: UNA SOLA SCANSIONE PER CARTELLA
|
|
for (const cartella of folders) {
|
|
log(`📁 Scan cartella utente: ${cartella}`);
|
|
|
|
const newFiles = await scanPhoto(
|
|
cartella,
|
|
userName,
|
|
db,
|
|
CURRENT,
|
|
TOTAL_FILES,
|
|
start,
|
|
async () => {
|
|
// 🔥 Callback di aggiornamento progresso
|
|
await fsp.writeFile(
|
|
statusPath,
|
|
JSON.stringify({
|
|
current: CURRENT.value,
|
|
total: TOTAL_FILES,
|
|
percent: Math.round((CURRENT.value / TOTAL_FILES) * 100),
|
|
eta: computeETA(start, CURRENT.value, TOTAL_FILES)
|
|
}, null, 2)
|
|
);
|
|
}
|
|
);
|
|
|
|
if (newFiles?.length) {
|
|
allNewFiles.push(...newFiles);
|
|
}
|
|
}
|
|
|
|
// Stato finale
|
|
await fsp.writeFile(
|
|
statusPath,
|
|
JSON.stringify({
|
|
current: TOTAL_FILES,
|
|
total: TOTAL_FILES,
|
|
percent: 100,
|
|
eta: "0m 0s"
|
|
}, null, 2)
|
|
);
|
|
|
|
log(`🟣 Scan COMPLETATO per user=${userName}. Nuovi file totali: ${allNewFiles.length}`);
|
|
|
|
return allNewFiles;
|
|
}
|
|
|
|
module.exports = scanPhotosUser; |