diff --git a/.DS_Store b/.DS_Store index 974caec..fd52eef 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.env.development b/.env.development index 345948f..3e28db4 100644 --- a/.env.development +++ b/.env.development @@ -1,12 +1,12 @@ -DATABASE=test_FreePlanet +DATABASE=test_PiuCheBuono UDB=paofreeplanet PDB=mypassword@1A SEND_EMAIL=0 SEND_EMAIL_ORDERS=1 PORT=3000 -appTelegram_TEST=["1","13"] -appTelegram=["1","13"] -appTelegram_DEVELOP=["13"] +appTelegram_TEST=["1","17"] +appTelegram=["1","17"] +appTelegram_DEVELOP=["17"] DOMAIN=mongodb://localhost:27017/ AUTH_MONGODB=1 MONGODB_USER=admin @@ -41,4 +41,7 @@ FTPSERVER_USER=ftpusrsrv_ FTPSERVER_PWD=ftpmypwd@1A_ AUTH_NEW_SITES=123123123 SCRIPTS_DIR=admin_scripts -CLOUDFLARE_TOKENS=[{"label":"Paolo.arena77@gmail.com","value":"M9EM309v8WFquJKpYgZCw-TViM2wX6vB3wlK6GD0"},{"label":"gruppomacro.com","value":"bqmzGShoX7WqOBzkXocoECyBkPq3GfqcM5t6VFd8"}] \ No newline at end of file +CLOUDFLARE_TOKENS=[{"label":"Paolo.arena77@gmail.com","value":"M9EM309v8WFquJKpYgZCw-TViM2wX6vB3wlK6GD0"},{"label":"gruppomacro.com","value":"bqmzGShoX7WqOBzkXocoECyBkPq3GfqcM5t6VFd8"}] +MIAB_HOST=box.lamiaposta.org +MIAB_ADMIN_EMAIL=admin@lamiaposta.org +MIAB_ADMIN_PASSWORD=passpao1pabox@1A \ No newline at end of file diff --git a/public/upload/catalogo/background.png b/public/upload/catalogo/background.png new file mode 100644 index 0000000..5e287cb Binary files /dev/null and b/public/upload/catalogo/background.png differ diff --git a/public/upload/catalogo/background_stampa.jpg b/public/upload/catalogo/background_stampa.jpg new file mode 100644 index 0000000..7247483 Binary files /dev/null and b/public/upload/catalogo/background_stampa.jpg differ diff --git a/public/upload/pages/home/logo-new-121x121_gaia_terra.png b/public/upload/pages/home/logo-new-121x121_gaia_terra.png new file mode 100644 index 0000000..c23b938 Binary files /dev/null and b/public/upload/pages/home/logo-new-121x121_gaia_terra.png differ diff --git a/src/server/models/myelem.js b/src/server/models/myelem.js index ba0a829..3beea0e 100755 --- a/src/server/models/myelem.js +++ b/src/server/models/myelem.js @@ -53,6 +53,20 @@ const catalogo = new Schema( excludeproductTypes: [{ type: Number }], Editore: [{ type: String }], pdf: { type: Boolean }, + printable: { type: Boolean }, + backgroundimage: { type: String }, + backgroundimage_printable: { type: String }, + widthpag: { type: Number }, + widthpagPrintable: { type: Number }, + width: { type: String }, + widthscheda: { type: String }, + height: { type: String }, + numschede_perRiga: { type: Number }, + numschede_perCol: { type: Number }, + margine_pagina: { type: String }, + margine_riga: { type: String }, + margine_paginaPrintable: { type: String }, + margine_rigaPrintable: { type: String }, // formato: [{ type: String, default: '' }], // categoria: [{ type: String, default: '' }], } diff --git a/src/server/router/admin_router.js b/src/server/router/admin_router.js index e8e63c8..c7c2438 100755 --- a/src/server/router/admin_router.js +++ b/src/server/router/admin_router.js @@ -60,28 +60,59 @@ async function downloadImgIfMissing(productInfo) { if (!productInfo.image_link) return { prodInfo: null, aggiornatoimg: false }; + const relativeimg = productInfo.image_link.split('/').pop(); const img = 'upload/products/' + productInfo.image_link.split('/').pop(); const savePath = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine - if (!productInfo.imagefile || !fs.existsSync(savePath)) { + let scaricaimg = !productInfo.imagefile || !fs.existsSync(savePath); + + if (!productInfo.imagefile && fs.existsSync(savePath)) { + // esiste il file, ma sul DB non è corretto + const stats = fs.statSync(savePath); // Ottieni informazioni sul file + + if (stats.size > 0) { // Controlla se la dimensione del file è maggiore di zero + // Esiste il file ed è non vuoto, ma sul DB non è corretto + productInfo.imagefile = relativeimg; + return { prodInfo: productInfo, aggiornatoimg: true }; + } else { + scaricaimg = true; + } + } + + if (productInfo.imagefile && fs.existsSync(savePath)) { + // esiste il file, ma sul DB non è corretto + const stats = fs.statSync(savePath); // Ottieni informazioni sul file + + if (stats.size <= 0) { // Controlla se la dimensione del file è maggiore di zero + scaricaimg = true; + } + } + + if (scaricaimg) { // Download image from the URL productInfo.image_link - productInfo.imagefile = img; + productInfo.imagefile = relativeimg; const downloader = new ImageDownloader(); - const aggiornatoimg = await downloader.downloadImage(productInfo.image_link, savePath).then(result => { - if (result) { - // console.log('Download completato con successo!'); - } else { - console.log('Download non riuscito.'); - } + const aggiornatoimg = await downloader.downloadImage(productInfo.image_link, savePath, + { + maxRetries: 3, + initialDelay: 300, + timeout: 15000, + }).then(result => { + if (result) { + // console.log('Download completato con successo!'); + } else { + console.log('Download non riuscito.'); + } - return result; + return result; - }); + }); return { prodInfo: productInfo, aggiornatoimg }; } + return { prodInfo: null, aggiornatoimg: false }; } @@ -1046,7 +1077,7 @@ router.post('/import', authenticate, async (req, res) => { if (productInfo.productTypes.length === 1 && productInfo.productTypes[0] === undefined) { productInfo.productTypes = [shared_consts.PRODUCTTYPE.PRODUCT]; } - + let esisteindb = await ProductInfo.findOne({ code: productInfo.code }).lean(); // Update ProductInfo diff --git a/src/server/tools/general.js b/src/server/tools/general.js index ef8de35..1a5587b 100755 --- a/src/server/tools/general.js +++ b/src/server/tools/general.js @@ -423,44 +423,99 @@ class ImageDownloader { * @param {number} delay - Ritardo in millisecondi tra i tentativi (default: 1000) * @returns {Promise} */ - async downloadImage(url, filepath, maxRetries = 1, delay = 1000) { + async downloadImage(url, filepath, options = {}) { + const { + maxRetries = 3, // Aumentato il numero di tentativi predefiniti + initialDelay = 1000, // Ritardo iniziale + maxDelay = 10000, // Ritardo massimo + timeout = 30000, // Timeout della richiesta + validateContentType = true // Verifica del tipo di contenuto + } = options; + + // Funzione per il backoff esponenziale + const getDelay = (attempt) => { + return Math.min(initialDelay * Math.pow(2, attempt - 1), maxDelay); + }; + for (let attempt = 1; attempt <= maxRetries; attempt++) { try { - const writer = fs.createWriteStream(filepath); + // Verifica se il filepath esiste già + if (fs.existsSync(filepath)) { + fs.unlinkSync(filepath); + } - console.log('url da scaricare:', url); + const writer = fs.createWriteStream(filepath); + if (attempt > 1) + console.log(`📥 Tentativo ${attempt}/${maxRetries} - Scaricamento: ${url}`); const response = await axios({ url, method: 'GET', responseType: 'stream', + timeout: timeout, + maxRedirects: 5, headers: { - 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Accept': 'image/jpeg,image/png,image/webp,image/gif,image/*', // Specifico per immagini + 'Cache-Control': 'no-cache', // Evita problemi di caching + 'Connection': 'keep-alive' + }, + validateStatus: (status) => status === 200, // Per immagini ci aspettiamo 200 + maxContentLength: 10 * 1024 * 1024 // Limite di 10MB per immagine + }); + + // Verifica del content-type se richiesto + if (validateContentType) { + const contentType = response.headers['content-type']; + if (!contentType || !contentType.startsWith('image/')) { + throw new Error(`Content-Type non valido: ${contentType}`); } + } + + // Verifica della dimensione del file + const contentLength = parseInt(response.headers['content-length']); + if (contentLength && contentLength > 100 * 1024 * 1024) { // 100MB limit + throw new Error('File troppo grande'); + } + + let downloadedBytes = 0; + response.data.on('data', chunk => { + downloadedBytes += chunk.length; }); response.data.pipe(writer); await new Promise((resolve, reject) => { - writer.on('finish', () => { - console.info('✅ Immagine scaricata ' + url + ' in ' + filepath); - resolve(true); + writer.on('finish', resolve); + writer.on('error', error => { + fs.unlink(filepath, () => { }); // Pulizia in caso di errore + reject(error); + }); + response.data.on('error', error => { + fs.unlink(filepath, () => { }); + reject(error); }); - writer.on('error', reject); }); - + console.info(`✅ Immagine scaricata con successo in ${filepath}`); return true; + } catch (error) { - console.error(`❌ Tentativo ${attempt} fallito per l'URL ${url}. Errore:`, error.message); + console.error(`❌ Errore nel tentativo ${attempt}/${maxRetries}:`, error.message); + + // Pulizia del file in caso di errore + if (fs.existsSync(filepath)) { + fs.unlinkSync(filepath); + } if (attempt === maxRetries) { - console.error('❌ Tutti i tentativi sono falliti. Scaricamento interrotto.'); + console.error(`Download fallito dopo ${maxRetries} tentativi: ${error.message}`); return false; - } else { - console.info(`🔁 Ritentando... (${attempt + 1} di ${maxRetries})`); - await sleep(delay); } + + const delay = getDelay(attempt); + console.info(`🔄 Attendo ${delay}ms prima del prossimo tentativo...`); + await new Promise(resolve => setTimeout(resolve, delay)); } } }