210 lines
No EOL
5.5 KiB
JavaScript
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
|
|
}; |