const got = require("got"); const { createWriteStream, existsSync } = require("fs"); const { pipeline } = require('stream/promises'); const fsp = require('fs').promises; const { dirname } = require('path'); /** * config example: { * endpoint: "https://bla.com", * directory: "dir/to/save/to", * override: true, // optional * extension: "jpg" // optional * } **/ async function getPictures(webmentions, config) { const pics = await Promise.all( [...new Set(webmentions.filter(wm => wm.author && wm.author.picture).map(wm => wm.author.picture))] .map(async picture => { let fileName = `${config.directory}/${picture}` if(config.extension && !fileName.endsWith(config.extension)) { fileName += `.${config.extension}` } // TODO existsSync does not work, wrapped in Promise.all - does not wait for it! if(config.override || !existsSync(fileName)) { try { await fsp.mkdir(dirname(fileName), { recursive: true }), // retry API with streams is ridiculously complicated: https://github.com/sindresorhus/got/blob/main/documentation/7-retry.md await pipeline( got.stream(`${config.endpoint}/${picture}`), createWriteStream(fileName) ) } catch(err) { console.log(` !! unable to download ${picture}: ${err.message}`) try { await fsp.unlink(fileName) } catch { } } } return fileName }) ) return pics } module.exports = { getPictures }