diff --git a/api_v1/scanphoto.js b/api_v1/scanphoto.js new file mode 100644 index 0000000..d91f1a7 --- /dev/null +++ b/api_v1/scanphoto.js @@ -0,0 +1,144 @@ +require('dotenv').config(); + +const fs = require('fs'); +const path = require('path'); +const ExifReader = require('exifreader'); +const sharp = require('sharp'); +const axios = require('axios'); + +const BASE_URL = process.env.BASE_URL; +const EMAIL = process.env.EMAIL; +const PASSWORD = process.env.PASSWORD; + +// ----------------------------------------------------- +// LOGIN → ottiene token JWT +// ----------------------------------------------------- +async function getToken() { + try { + const res = await axios.post(`${BASE_URL}/auth/login`, { + email: EMAIL, + password: PASSWORD + }); + return res.data.token; + } catch (err) { + console.error("ERRORE LOGIN:", err.message); + return null; + } +} + +// ----------------------------------------------------- +// INVIA FOTO AL SERVER +// ----------------------------------------------------- +async function sendPhoto(json) { + const token = await getToken(); + if (!token) { + console.error("Token non ottenuto, impossibile inviare foto"); + return; + } + + try { + await axios.post(`${BASE_URL}/photos`, json, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json" + } + }); + } catch (err) { + console.error("Errore invio foto:", err.message); + } +} + +// ----------------------------------------------------- +// CREA THUMBNAILS +// ----------------------------------------------------- +async function createThumbnails(filePath, thumbMinPath, thumbAvgPath) { + try { + await sharp(filePath) + .resize(100, 100, { fit: "inside" }) + .withMetadata() + .toFile(thumbMinPath); + + await sharp(filePath) + .resize(400) + .withMetadata() + .toFile(thumbAvgPath); + } catch (err) { + console.error("Errore creazione thumbnails:", err.message); + } +} + +// ----------------------------------------------------- +// SCANSIONE RICORSIVA +// ----------------------------------------------------- +async function scanDir(dir, ext, results = []) { + const files = fs.readdirSync(dir); + + for (const file of files) { + const filePath = path.join(dir, file); + const stat = fs.statSync(filePath); + + if (stat.isDirectory()) { + await scanDir(filePath, ext, results); + continue; + } + + if (path.extname(file).toLowerCase() !== ext) continue; + + console.log("Trovato:", file); + + const relDir = dir.replace("public/", ""); + const thumbDir = path.join("public", relDir.replace("original", "thumbs")); + + if (!fs.existsSync(thumbDir)) { + fs.mkdirSync(thumbDir, { recursive: true }); + } + + const baseName = path.parse(file).name; + const extName = path.parse(file).ext; + + const thumbMin = path.join(thumbDir, `${baseName}_min${extName}`); + const thumbAvg = path.join(thumbDir, `${baseName}_avg${extName}`); + + await createThumbnails(filePath, thumbMin, thumbAvg); + + // EXIF + let tags = {}; + try { + tags = await ExifReader.load(filePath, { expanded: true }); + } catch {} + + const time = tags?.exif?.DateTimeOriginal?.value?.[0] || null; + const gps = tags?.gps || null; + + results.push({ + name: file, + path: relDir + "/" + file, + thub1: thumbMin.replace("public/", ""), + thub2: thumbAvg.replace("public/", ""), + gps, + data: time, + location: null + }); + } + + return results; +} + +// ----------------------------------------------------- +// FUNZIONE PRINCIPALE +// ----------------------------------------------------- +async function scanPhoto(dir) { + console.log("Inizio scansione:", dir); + + const photos = await scanDir(dir, ".jpg"); + + console.log("Trovate", photos.length, "foto"); + + for (const p of photos) { + await sendPhoto(p); + } + + console.log("Scansione completata"); +} + +module.exports = scanPhoto;