108 lines
2.6 KiB
JavaScript
108 lines
2.6 KiB
JavaScript
const path = require('path');
|
|
const fs = require('fs');
|
|
const spawn = require('cross-spawn');
|
|
const logger = require('./logger');
|
|
|
|
const sendError = (res, code) => {
|
|
res.writeHeader(code);
|
|
res.write(code === 400 ? 'Bad Request' : 'Internal Server Error');
|
|
res.end();
|
|
};
|
|
|
|
module.exports = async function server(req, res) {
|
|
let sent = false;
|
|
let filename;
|
|
const { url, format } = req.queryParams;
|
|
|
|
logger.info(`Request: ${req.url}`);
|
|
|
|
if (!url) {
|
|
sendError(res, 400);
|
|
return;
|
|
}
|
|
|
|
const dataPath = path.resolve(__dirname, '../data');
|
|
|
|
const params = [url];
|
|
|
|
if (format) {
|
|
params.unshift(format);
|
|
params.unshift('--format');
|
|
}
|
|
|
|
logger.info(`Downloading ${url}`);
|
|
const proc = spawn('youtube-dl', params, {
|
|
stdio: 'pipe',
|
|
cwd: dataPath,
|
|
});
|
|
|
|
proc.stdout.on('data', data => {
|
|
const match = data.toString().match(/\[download\] Destination: (.+)/i);
|
|
const existsMatch = data.toString().match(/\[download\] (.+) has already been downloaded/i);
|
|
|
|
if (match !== null) {
|
|
// eslint-disable-next-line prefer-destructuring
|
|
filename = match[1];
|
|
} else if (existsMatch !== null) {
|
|
// eslint-disable-next-line prefer-destructuring
|
|
filename = existsMatch[1];
|
|
}
|
|
});
|
|
|
|
proc.on('error', err => {
|
|
logger.error(err);
|
|
logger.info(`child process exited with code ${err.code}`);
|
|
if (!sent) {
|
|
sendError(res, 500);
|
|
sent = true;
|
|
}
|
|
});
|
|
|
|
proc.on('close', code => {
|
|
logger.info(`child process exited with code ${code}`);
|
|
|
|
if (!filename) {
|
|
logger.error('Failed to capture download filename');
|
|
sendError(res, 500);
|
|
sent = true;
|
|
return;
|
|
}
|
|
|
|
const dlFilepath = path.join(__dirname, '../data', filename);
|
|
logger.info(`Downloaded file is ${dlFilepath}`);
|
|
|
|
if (!sent) {
|
|
fs.readFile(dlFilepath, (err, fileBuffer) => {
|
|
if (err) {
|
|
sendError(res, 500);
|
|
sent = true;
|
|
return;
|
|
}
|
|
|
|
res.writeHead(200, {
|
|
'Content-Type': 'application/octet-stream',
|
|
'Content-Length': fileBuffer.length,
|
|
'Content-disposition': `attachment; filename=${filename}`,
|
|
});
|
|
res.write(fileBuffer);
|
|
res.end();
|
|
sent = true;
|
|
});
|
|
}
|
|
|
|
sent = true;
|
|
|
|
// clean up the download if told to
|
|
res.on('finish', () => {
|
|
const { REMOVE_DOWNLOAD } = process.env;
|
|
if (!REMOVE_DOWNLOAD) return;
|
|
|
|
const shouldRemove = REMOVE_DOWNLOAD === '1' || REMOVE_DOWNLOAD.toLowerCase() === 'true';
|
|
if (shouldRemove) {
|
|
logger.info('Removing local file:', dlFilepath);
|
|
fs.unlinkSync(dlFilepath);
|
|
}
|
|
});
|
|
});
|
|
};
|