'use strict'; const Readable = require('stream').Readable; const fs = require('fs-extra'); const path = require('path'); const config = require('config'); const fetch = require('node-fetch'); const interpolate = require('./interpolate.js'); function saveItemToDisk(stream, filepath) { const file = fs.createWriteStream(filepath); return new Promise((resolve, reject) => { stream.pipe(file).on('error', error => { reject(error); }).on('finish', () => { console.log(`Saved '${filepath}'`); resolve(filepath); }); }); }; function textPostToStream(item) { const stream = new Readable(); stream.push(item.text); stream.push(null); return Object.assign(item, { stream: stream }); }; function fetchItem(item, post, attempt) { function retry(error) { console.log(error); if(attempt < 3) { console.log('Retrying...'); return fetchItem(item, post, ++attempt); } }; return fetch(item.url).then(res => { return res.ok ? res : Promise.reject(`Failed to fetch ${item.url}`); }).then(res => { console.log(`Fetched '${item.url}'`); return Object.assign({}, item, { stream: res.body }); }).catch(retry); }; module.exports = function(posts) { return Promise.all(posts.map(post => { return Promise.resolve().then(() => { return Promise.all(post.content.items.map((item, index) => { item.index = index; if(item.self) { return textPostToStream(item); } return fetchItem(item, post, 0); })); }).then(items => { return Promise.all(items.map(item => { const type = item.type.split('/')[0]; const filepath = post.content.album ? interpolate(config.patterns.album[type], post, item) : interpolate(config.patterns[type], post, item); return Promise.resolve().then(() => { return fs.ensureDir(path.dirname(filepath)); }).then(() => { return saveItemToDisk(item.stream, filepath) }); })); }); })); };