photo_server_json_flutter_c.../api_v1/scanner/scanAuto.js

210 lines
No EOL
5.5 KiB
JavaScript

const path = require('path');
const fsp = require('fs/promises');
const scanCartella = require('./scanCartella');
const processFile = require('./processFile');
const { sha256 } = require('./utils');
const createCleanupFunctions = require('./orphanCleanup');
const { WEB_ROOT } = require('../config');
const { log } = require('./logger');
// ---------------------------------------------------------
// NORMALIZZAZIONE PATH (toglie /app/...)
// ---------------------------------------------------------
function normalizeRelPath(user, dirPath, fileName) {
if (!dirPath) return "";
let rel = dirPath.replace(/\\/g, "/");
// Rimuove tutto fino a /photos/
rel = rel.replace(/^.*\/photos\//, "");
// Ora rel = "Fabio/original/2017Irlanda/.../"
const prefix = `${user}/original/`;
if (rel.startsWith(prefix)) {
rel = rel.slice(prefix.length);
}
if (rel.startsWith("/")) rel = rel.slice(1);
// Aggiunge il file
if (fileName) {
rel = `${rel}/${fileName}`.replace(/\/+/g, "/");
}
return rel; // es: "2017Irlanda19-29ago/IMG_0120.JPG"
}
// ---------------------------------------------------------
// CALCOLO ID IDENTICO AL VECCHIO SCAN
// ---------------------------------------------------------
function computeId(user, relPath) {
const parts = relPath.split('/').filter(Boolean);
const cartella = parts[0];
const fileRelPath = parts.slice(1).join('/');
const id = sha256(`${user}/${cartella}/${fileRelPath}`);
return { id, cartella, fileRelPath };
}
// ---------------------------------------------------------
// 1) ADD FILE
// ---------------------------------------------------------
async function handleAddFile(user, dirPath, fileName, db) {
const relPath = normalizeRelPath(user, dirPath, fileName);
log(`🟦 [ADD] user=${user} file=${relPath}`);
// 🔥 Ricostruzione identica al vecchio scanPhoto
const parts = relPath.split('/');
const cartella = parts[0]; // es: "2017Irlanda19-29ago"
const fileRelPath = parts.slice(1).join('/'); // es: "IMG_0116.JPG"
const photosRoot = path.resolve(__dirname, '..', '..', WEB_ROOT, 'photos');
const absPath = path.join(photosRoot, user, 'original', cartella, fileRelPath);
const ext = path.extname(fileName).toLowerCase();
const st = await fsp.stat(absPath);
// 🔥 FIX: processFile deve ricevere fileRelPath completo di "original/"
const meta = await processFile(
user,
cartella,
path.posix.join('original', cartella, fileRelPath),
absPath,
ext,
st
);
// Inserimento identico al vecchio scanPhoto
const row = {
id: meta.id,
user,
cartella,
name: meta.name,
path: meta.path,
thub1: meta.thub1,
thub2: meta.thub2,
mime_type: meta.mime_type,
width: meta.width,
height: meta.height,
rotation: meta.rotation,
size_bytes: meta.size_bytes,
mtimeMs: meta.mtimeMs,
duration_ms: meta.duration_ms ?? null,
taken_at: meta.taken_at ?? null,
data: meta.data ?? null,
lat: meta.gps?.lat ?? null,
lon: meta.gps?.lng ?? null,
alt: meta.gps?.alt ?? null,
location: meta.location ? JSON.stringify(meta.location) : null
};
await db('photos')
.insert(row)
.onConflict('id')
.merge();
log(`🟢 [ADD] Inserito/aggiornato id=${meta.id}`);
return row;
}
// ---------------------------------------------------------
// 2) DELETE FILE
// ---------------------------------------------------------
async function handleDeleteFile(user, dirPath, fileName, db) {
const relPath = normalizeRelPath(user, dirPath, fileName);
log(`🟥 [DEL] user=${user} file=${relPath}`);
const { id } = computeId(user, relPath);
const { deleteThumbsById, deleteFromDB } = createCleanupFunctions(db);
await deleteThumbsById(id);
await deleteFromDB(id, user);
log(`🔴 [DEL] File eliminato id=${id}`);
return { deleted: id };
}
// ---------------------------------------------------------
// 3) ADD DIRECTORY
// ---------------------------------------------------------
async function handleAddDir(user, dir, db) {
log(`🟦 [ADD_DIR] user=${user} dir=${dir}`);
const photosRoot = path.resolve(__dirname, '..', '..', WEB_ROOT, 'photos');
const absDir = path.join(photosRoot, user, 'original', dir);
log(`📁 [ADD_DIR] absDir=${absDir}`);
let results = [];
for await (const f of scanCartella(user, dir, absDir, db)) {
log(`📄 [ADD_DIR] File trovato: ${f.relPath}`);
const meta = await processFile(
user,
dir,
f.relPath,
f.absPath,
f.ext,
f.stat
);
await db('photos').insert(meta).onConflict('id').merge();
log(`🟢 [ADD_DIR] Inserito/aggiornato id=${meta.id} name=${meta.name}`);
results.push(meta);
}
log(`🟣 [ADD_DIR] Completato. Files=${results.length}`);
return results;
}
// ---------------------------------------------------------
// 4) DELETE DIRECTORY
// ---------------------------------------------------------
async function handleDeleteDir(user, dir, db) {
log(`🟥 [DEL_DIR] user=${user} dir=${dir}`);
const rows = await db('photos')
.where({ user, cartella: dir })
.select('id');
const { deleteThumbsById, deleteFromDB } = createCleanupFunctions(db);
log(`📁 [DEL_DIR] Trovati ${rows.length} file da eliminare`);
for (const r of rows) {
log(`🗑️ [DEL_DIR] Eliminazione id=${r.id}`);
await deleteThumbsById(r.id);
await deleteFromDB(r.id, user);
}
log(`🔴 [DEL_DIR] Cartella eliminata. Totale file=${rows.length}`);
return { deleted: rows.length };
}
module.exports = {
handleAddFile,
handleDeleteFile,
handleAddDir,
handleDeleteDir
};