ramirez/src/data/attachments.js

113 lines
3.0 KiB
JavaScript
Raw Normal View History

2017-02-09 23:36:47 -05:00
const Eris = require('eris');
2017-02-09 21:56:36 -05:00
const fs = require('fs');
const https = require('https');
const config = require('../config');
const {promisify} = require('util');
2017-09-19 13:23:55 -04:00
const getUtils = () => require('../utils');
2017-02-09 21:56:36 -05:00
const access = promisify(fs.access);
const readFile = promisify(fs.readFile);
const attachmentDir = config.attachmentDir || `${__dirname}/../../attachments`;
2017-02-09 21:56:36 -05:00
const attachmentSavePromises = {};
2017-02-09 23:36:47 -05:00
/**
* Returns the filesystem path for the given attachment id
* @param {String} attachmentId
* @returns {String}
*/
function getPath(attachmentId) {
return `${attachmentDir}/${attachmentId}`;
2017-02-09 21:56:36 -05:00
}
2017-02-09 23:36:47 -05:00
/**
* Attempts to download and save the given attachement
* @param {Object} attachment
* @param {Number=0} tries
* @returns {Promise}
*/
async function saveAttachment(attachment) {
if (attachmentSavePromises[attachment.id]) {
return attachmentSavePromises[attachment.id];
}
const filepath = getPath(attachment.id);
try {
// If the file already exists, resolve immediately
await access(filepath);
return;
} catch (e) {}
attachmentSavePromises[attachment.id] = saveAttachmentInner(attachment);
attachmentSavePromises[attachment.id]
.then(() => {
delete attachmentSavePromises[attachment.id];
}, () => {
delete attachmentSavePromises[attachment.id];
});
return attachmentSavePromises[attachment.id];
}
function saveAttachmentInner(attachment, tries = 0) {
2017-02-09 21:56:36 -05:00
return new Promise((resolve, reject) => {
if (tries > 3) {
console.error('Attachment download failed after 3 tries:', attachment);
reject('Attachment download failed after 3 tries');
return;
}
2017-02-09 23:36:47 -05:00
const filepath = getPath(attachment.id);
2017-02-09 21:56:36 -05:00
const writeStream = fs.createWriteStream(filepath);
https.get(attachment.url, (res) => {
res.pipe(writeStream);
writeStream.on('finish', () => {
writeStream.end();
2017-02-09 21:56:36 -05:00
resolve();
});
}).on('error', (err) => {
fs.unlink(filepath);
console.error('Error downloading attachment, retrying');
resolve(saveAttachmentInner(attachment, tries++));
2017-02-09 21:56:36 -05:00
});
});
}
2017-02-09 23:36:47 -05:00
/**
* Attempts to download and save all attachments in the given message
* @param {Eris.Message} msg
* @returns {Promise}
*/
function saveAttachmentsInMessage(msg) {
2017-02-09 21:56:36 -05:00
if (! msg.attachments || msg.attachments.length === 0) return Promise.resolve();
return Promise.all(msg.attachments.map(saveAttachment));
}
2017-02-09 23:36:47 -05:00
/**
* Returns the self-hosted URL to the given attachment ID
* @param {String} attachmentId
* @param {String=null} desiredName Custom name for the attachment as a hint for the browser
* @returns {String}
*/
function getUrl(attachmentId, desiredName = null) {
2017-02-09 21:56:36 -05:00
if (desiredName == null) desiredName = 'file.bin';
2017-09-19 13:23:55 -04:00
return getUtils().getSelfUrl(`attachments/${attachmentId}/${desiredName}`);
2017-02-09 21:56:36 -05:00
}
async function attachmentToFile(attachment) {
await saveAttachment(attachment);
const data = await readFile(getPath(attachment.id));
return {file: data, name: attachment.filename};
}
2017-02-09 21:56:36 -05:00
module.exports = {
2017-02-09 23:36:47 -05:00
getPath,
2017-02-09 21:56:36 -05:00
saveAttachment,
2017-02-09 23:36:47 -05:00
saveAttachmentsInMessage,
getUrl,
attachmentToFile
2017-02-09 21:56:36 -05:00
};