const https = require('https'); const fs = require('fs-extra'); const path = require('path'); module.exports = Self => { Self.remoteMethod('downloadImages', { description: 'Returns last entries', accessType: 'WRITE', returns: { type: ['Object'], root: true }, http: { path: `/downloadImages`, verb: 'POST' } }); Self.downloadImages = async() => { const models = Self.app.models; const container = await models.TempContainer.container('salix-image'); const tempPath = path.join(container.client.root, container.name); const maxAttempts = 3; const images = await Self.find({ where: {attempts: {eq: maxAttempts}} }); for (let image of images) { const currentStamp = new Date().getTime(); const updatedStamp = image.updated.getTime(); const graceTime = Math.abs(currentStamp - updatedStamp); const maxTTL = 3600 * 48 * 1000; // 48 hours in ms; if (graceTime >= maxTTL) await Self.destroyById(image.itemFk); } download(); async function download() { const image = await Self.findOne({ where: {url: {neq: null}, attempts: {lt: maxAttempts}}, order: 'priority, attempts, updated' }); if (!image) return; const srcFile = image.url; const fileName = srcFile.replace(/\.|\/|:|\?|\\|=|%/g, ''); const file = `${fileName}.png`; const filePath = path.join(tempPath, file); https.get(image.url, async response => { if (response.statusCode != 200) { const error = new Error(`Could not download the image. Status code ${response.statusCode}`); return await errorHandler(image.itemFk, error, filePath); } const writeStream = fs.createWriteStream(filePath); writeStream.on('open', () => { response.pipe(writeStream); }); writeStream.on('error', async error => { await errorHandler(image.itemFk, error, filePath); }); writeStream.on('finish', async function() { writeStream.end(); }); writeStream.on('close', async function() { try { await models.Image.registerImage('catalog', filePath, fileName, image.itemFk); await image.destroy(); download(); } catch (error) { await errorHandler(image.itemFk, error, filePath); } }); }).on('error', async error => { await errorHandler(image.itemFk, error, filePath); }); } async function errorHandler(rowId, error, filePath) { try { const row = await Self.findById(rowId); if (!row) return; if (row.attempts < maxAttempts) { await row.updateAttributes({ error: error, attempts: row.attempts + 1, updated: new Date() }); } if (filePath && fs.existsSync(filePath)) await fs.unlink(filePath); download(); } catch (err) { throw new Error(`Image download failed: ${err}`); } } }; };