|
|
|
@ -1,6 +1,6 @@
|
|
|
|
|
var async = require('async');
|
|
|
|
|
const { uuid } = require('uuidv4');
|
|
|
|
|
var fs = require('fs-extra');
|
|
|
|
|
var { promisify } = require('util');
|
|
|
|
|
var auth_api = require('./authentication/auth');
|
|
|
|
|
var winston = require('winston');
|
|
|
|
|
var path = require('path');
|
|
|
|
@ -18,7 +18,6 @@ var utils = require('./utils')
|
|
|
|
|
var mergeFiles = require('merge-files');
|
|
|
|
|
const low = require('lowdb')
|
|
|
|
|
var ProgressBar = require('progress');
|
|
|
|
|
var md5 = require('md5');
|
|
|
|
|
const NodeID3 = require('node-id3')
|
|
|
|
|
const downloader = require('youtube-dl/lib/downloader')
|
|
|
|
|
const fetch = require('node-fetch');
|
|
|
|
@ -195,35 +194,41 @@ app.use(auth_api.passport.initialize());
|
|
|
|
|
|
|
|
|
|
// actual functions
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* setTimeout, but its a promise.
|
|
|
|
|
* @param {number} ms
|
|
|
|
|
*/
|
|
|
|
|
async function wait(ms) {
|
|
|
|
|
await new Promise(resolve => {
|
|
|
|
|
setTimeout(resolve, ms);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function checkMigrations() {
|
|
|
|
|
return new Promise(async resolve => {
|
|
|
|
|
// 3.5->3.6 migration
|
|
|
|
|
const files_to_db_migration_complete = true; // migration phased out! previous code: db.get('files_to_db_migration_complete').value();
|
|
|
|
|
|
|
|
|
|
if (!files_to_db_migration_complete) {
|
|
|
|
|
logger.info('Beginning migration: 3.5->3.6+')
|
|
|
|
|
runFilesToDBMigration().then(success => {
|
|
|
|
|
const success = await runFilesToDBMigration()
|
|
|
|
|
if (success) { logger.info('3.5->3.6+ migration complete!'); }
|
|
|
|
|
else { logger.error('Migration failed: 3.5->3.6+'); }
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resolve(true);
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function runFilesToDBMigration() {
|
|
|
|
|
return new Promise(async resolve => {
|
|
|
|
|
try {
|
|
|
|
|
let mp3s = getMp3s();
|
|
|
|
|
let mp4s = getMp4s();
|
|
|
|
|
let mp3s = await getMp3s();
|
|
|
|
|
let mp4s = await getMp4s();
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < mp3s.length; i++) {
|
|
|
|
|
let file_obj = mp3s[i];
|
|
|
|
|
const file_already_in_db = db.get('files.audio').find({id: file_obj.id}).value();
|
|
|
|
|
if (!file_already_in_db) {
|
|
|
|
|
logger.verbose(`Migrating file ${file_obj.id}`);
|
|
|
|
|
db_api.registerFileDB(file_obj.id + '.mp3', 'audio');
|
|
|
|
|
await db_api.registerFileDB(file_obj.id + '.mp3', 'audio');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -232,18 +237,17 @@ async function runFilesToDBMigration() {
|
|
|
|
|
const file_already_in_db = db.get('files.video').find({id: file_obj.id}).value();
|
|
|
|
|
if (!file_already_in_db) {
|
|
|
|
|
logger.verbose(`Migrating file ${file_obj.id}`);
|
|
|
|
|
db_api.registerFileDB(file_obj.id + '.mp4', 'video');
|
|
|
|
|
await db_api.registerFileDB(file_obj.id + '.mp4', 'video');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sets migration to complete
|
|
|
|
|
db.set('files_to_db_migration_complete', true).write();
|
|
|
|
|
resolve(true);
|
|
|
|
|
return true;
|
|
|
|
|
} catch(err) {
|
|
|
|
|
logger.error(err);
|
|
|
|
|
resolve(false);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function startServer() {
|
|
|
|
@ -418,20 +422,20 @@ async function downloadReleaseZip(tag) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function installDependencies() {
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
|
var child_process = require('child_process');
|
|
|
|
|
child_process.execSync('npm install',{stdio:[0,1,2]});
|
|
|
|
|
resolve(true);
|
|
|
|
|
});
|
|
|
|
|
var exec = promisify(child_process.exec);
|
|
|
|
|
|
|
|
|
|
await exec('npm install',{stdio:[0,1,2]});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function backupServerLite() {
|
|
|
|
|
return new Promise(async resolve => {
|
|
|
|
|
fs.ensureDirSync(path.join(__dirname, 'appdata', 'backups'));
|
|
|
|
|
await fs.ensureDir(path.join(__dirname, 'appdata', 'backups'));
|
|
|
|
|
let output_path = path.join('appdata', 'backups', `backup-${Date.now()}.zip`);
|
|
|
|
|
logger.info(`Backing up your non-video/audio files to ${output_path}. This may take up to a few seconds/minutes.`);
|
|
|
|
|
let output = fs.createWriteStream(path.join(__dirname, output_path));
|
|
|
|
|
|
|
|
|
|
await new Promise(resolve => {
|
|
|
|
|
var archive = archiver('zip', {
|
|
|
|
|
gzip: true,
|
|
|
|
|
zlib: { level: 9 } // Sets the compression level.
|
|
|
|
@ -455,58 +459,53 @@ async function backupServerLite() {
|
|
|
|
|
ignore: files_to_ignore
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
await archive.finalize();
|
|
|
|
|
resolve(archive.finalize());
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// wait a tiny bit for the zip to reload in fs
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
resolve(true);
|
|
|
|
|
}, 100);
|
|
|
|
|
});
|
|
|
|
|
await wait(100);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function isNewVersionAvailable() {
|
|
|
|
|
return new Promise(async resolve => {
|
|
|
|
|
// gets tag of the latest version of youtubedl-material, compare to current version
|
|
|
|
|
const latest_tag = await getLatestVersion();
|
|
|
|
|
const current_tag = CONSTS['CURRENT_VERSION'];
|
|
|
|
|
if (latest_tag > current_tag) {
|
|
|
|
|
resolve(true);
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
resolve(false);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function getLatestVersion() {
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
|
fetch('https://api.github.com/repos/tzahi12345/youtubedl-material/releases/latest', {method: 'Get'})
|
|
|
|
|
.then(async res => res.json())
|
|
|
|
|
.then(async (json) => {
|
|
|
|
|
const res = await fetch('https://api.github.com/repos/tzahi12345/youtubedl-material/releases/latest', {method: 'Get'});
|
|
|
|
|
const json = await res.json();
|
|
|
|
|
|
|
|
|
|
if (json['message']) {
|
|
|
|
|
// means there's an error in getting latest version
|
|
|
|
|
logger.error(`ERROR: Received the following message from GitHub's API:`);
|
|
|
|
|
logger.error(json['message']);
|
|
|
|
|
if (json['documentation_url']) logger.error(`Associated URL: ${json['documentation_url']}`)
|
|
|
|
|
}
|
|
|
|
|
resolve(json['tag_name']);
|
|
|
|
|
return;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
return json['tag_name'];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function killAllDownloads() {
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
|
ps.lookup({
|
|
|
|
|
command: 'youtube-dl',
|
|
|
|
|
}, function(err, resultList ) {
|
|
|
|
|
if (err) {
|
|
|
|
|
const lookupAsync = promisify(ps.lookup);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
await lookupAsync({
|
|
|
|
|
command: 'youtube-dl'
|
|
|
|
|
});
|
|
|
|
|
} catch (err) {
|
|
|
|
|
// failed to get list of processes
|
|
|
|
|
logger.error('Failed to get a list of running youtube-dl processes.');
|
|
|
|
|
logger.error(err);
|
|
|
|
|
resolve({
|
|
|
|
|
return {
|
|
|
|
|
details: err,
|
|
|
|
|
success: false
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// processes that contain the string 'youtube-dl' in the name will be looped
|
|
|
|
@ -524,18 +523,16 @@ async function killAllDownloads() {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
resolve({
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
success: true
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function setPortItemFromENV() {
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
|
config_api.setConfigItem('ytdl_port', backendPort.toString());
|
|
|
|
|
setTimeout(() => resolve(true), 100);
|
|
|
|
|
});
|
|
|
|
|
await wait(100);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function setAndLoadConfig() {
|
|
|
|
@ -544,27 +541,23 @@ async function setAndLoadConfig() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function setConfigFromEnv() {
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
|
let config_items = getEnvConfigItems();
|
|
|
|
|
let success = config_api.setConfigItems(config_items);
|
|
|
|
|
if (success) {
|
|
|
|
|
logger.info('Config items set using ENV variables.');
|
|
|
|
|
setTimeout(() => resolve(true), 100);
|
|
|
|
|
await wait(100);
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
logger.error('ERROR: Failed to set config items using ENV variables.');
|
|
|
|
|
resolve(false);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function loadConfig() {
|
|
|
|
|
return new Promise(async resolve => {
|
|
|
|
|
loadConfigValues();
|
|
|
|
|
|
|
|
|
|
// creates archive path if missing
|
|
|
|
|
if (!fs.existsSync(archivePath)){
|
|
|
|
|
fs.mkdirSync(archivePath);
|
|
|
|
|
}
|
|
|
|
|
await fs.ensureDir(archivePath);
|
|
|
|
|
|
|
|
|
|
// get subscriptions
|
|
|
|
|
if (allowSubscriptions) {
|
|
|
|
@ -586,9 +579,7 @@ async function loadConfig() {
|
|
|
|
|
// start the server here
|
|
|
|
|
startServer();
|
|
|
|
|
|
|
|
|
|
resolve(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function loadConfigValues() {
|
|
|
|
@ -705,17 +696,17 @@ function generateEnvVarConfigItem(key) {
|
|
|
|
|
return {key: key, value: process['env'][key]};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getMp3s() {
|
|
|
|
|
async function getMp3s() {
|
|
|
|
|
let mp3s = [];
|
|
|
|
|
var files = utils.recFindByExt(audioFolderPath, 'mp3'); // fs.readdirSync(audioFolderPath);
|
|
|
|
|
var files = await utils.recFindByExt(audioFolderPath, 'mp3'); // fs.readdirSync(audioFolderPath);
|
|
|
|
|
for (let i = 0; i < files.length; i++) {
|
|
|
|
|
let file = files[i];
|
|
|
|
|
var file_path = file.substring(audioFolderPath.length, file.length);
|
|
|
|
|
|
|
|
|
|
var stats = fs.statSync(file);
|
|
|
|
|
var stats = await fs.stat(file);
|
|
|
|
|
|
|
|
|
|
var id = file_path.substring(0, file_path.length-4);
|
|
|
|
|
var jsonobj = utils.getJSONMp3(id, audioFolderPath);
|
|
|
|
|
var jsonobj = await utils.getJSONMp3(id, audioFolderPath);
|
|
|
|
|
if (!jsonobj) continue;
|
|
|
|
|
var title = jsonobj.title;
|
|
|
|
|
var url = jsonobj.webpage_url;
|
|
|
|
@ -734,9 +725,9 @@ function getMp3s() {
|
|
|
|
|
return mp3s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getMp4s(relative_path = true) {
|
|
|
|
|
async function getMp4s(relative_path = true) {
|
|
|
|
|
let mp4s = [];
|
|
|
|
|
var files = utils.recFindByExt(videoFolderPath, 'mp4');
|
|
|
|
|
var files = await utils.recFindByExt(videoFolderPath, 'mp4');
|
|
|
|
|
for (let i = 0; i < files.length; i++) {
|
|
|
|
|
let file = files[i];
|
|
|
|
|
var file_path = file.substring(videoFolderPath.length, file.length);
|
|
|
|
@ -744,7 +735,7 @@ function getMp4s(relative_path = true) {
|
|
|
|
|
var stats = fs.statSync(file);
|
|
|
|
|
|
|
|
|
|
var id = file_path.substring(0, file_path.length-4);
|
|
|
|
|
var jsonobj = utils.getJSONMp4(id, videoFolderPath);
|
|
|
|
|
var jsonobj = await utils.getJSONMp4(id, videoFolderPath);
|
|
|
|
|
if (!jsonobj) continue;
|
|
|
|
|
var title = jsonobj.title;
|
|
|
|
|
var url = jsonobj.webpage_url;
|
|
|
|
@ -850,11 +841,10 @@ function getVideoFormatID(name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function createPlaylistZipFile(fileNames, type, outputName, fullPathProvided = null, user_uid = null) {
|
|
|
|
|
return new Promise(async resolve => {
|
|
|
|
|
let zipFolderPath = null;
|
|
|
|
|
|
|
|
|
|
if (!fullPathProvided) {
|
|
|
|
|
zipFolderPath = path.join(type === 'audio' ? audioFolderPath : videoFolderPath);
|
|
|
|
|
zipFolderPath = path.join(__dirname, (type === 'audio') ? audioFolderPath : videoFolderPath);
|
|
|
|
|
if (user_uid) zipFolderPath = path.join(config_api.getConfigItem('ytdl_users_base_path'), user_uid, zipFolderPath);
|
|
|
|
|
} else {
|
|
|
|
|
zipFolderPath = path.join(__dirname, config_api.getConfigItem('ytdl_subscriptions_base_path'));
|
|
|
|
@ -887,17 +877,11 @@ async function createPlaylistZipFile(fileNames, type, outputName, fullPathProvid
|
|
|
|
|
await archive.finalize();
|
|
|
|
|
|
|
|
|
|
// wait a tiny bit for the zip to reload in fs
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
resolve(path.join(zipFolderPath,outputName + '.zip'));
|
|
|
|
|
}, 100);
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await wait(100);
|
|
|
|
|
return path.join(zipFolderPath,outputName + '.zip');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function deleteAudioFile(name, customPath = null, blacklistMode = false) {
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
|
let filePath = customPath ? customPath : audioFolderPath;
|
|
|
|
|
|
|
|
|
|
var jsonPath = path.join(filePath,name+'.mp3.info.json');
|
|
|
|
@ -910,24 +894,24 @@ async function deleteAudioFile(name, customPath = null, blacklistMode = false) {
|
|
|
|
|
altJSONPath = path.join(__dirname, altJSONPath);
|
|
|
|
|
audioFilePath = path.join(__dirname, audioFilePath);
|
|
|
|
|
|
|
|
|
|
let jsonExists = fs.existsSync(jsonPath);
|
|
|
|
|
let thumbnailExists = fs.existsSync(thumbnailPath);
|
|
|
|
|
let jsonExists = await fs.pathExists(jsonPath);
|
|
|
|
|
let thumbnailExists = await fs.pathExists(thumbnailPath);
|
|
|
|
|
|
|
|
|
|
if (!jsonExists) {
|
|
|
|
|
if (fs.existsSync(altJSONPath)) {
|
|
|
|
|
if (await fs.pathExists(altJSONPath)) {
|
|
|
|
|
jsonExists = true;
|
|
|
|
|
jsonPath = altJSONPath;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!thumbnailExists) {
|
|
|
|
|
if (fs.existsSync(altThumbnailPath)) {
|
|
|
|
|
if (await fs.pathExists(altThumbnailPath)) {
|
|
|
|
|
thumbnailExists = true;
|
|
|
|
|
thumbnailPath = altThumbnailPath;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let audioFileExists = fs.existsSync(audioFilePath);
|
|
|
|
|
let audioFileExists = await fs.pathExists(audioFilePath);
|
|
|
|
|
|
|
|
|
|
if (config_api.descriptors[name]) {
|
|
|
|
|
try {
|
|
|
|
@ -945,40 +929,36 @@ async function deleteAudioFile(name, customPath = null, blacklistMode = false) {
|
|
|
|
|
|
|
|
|
|
// get ID from JSON
|
|
|
|
|
|
|
|
|
|
var jsonobj = utils.getJSONMp3(name, filePath);
|
|
|
|
|
var jsonobj = await utils.getJSONMp3(name, filePath);
|
|
|
|
|
let id = null;
|
|
|
|
|
if (jsonobj) id = jsonobj.id;
|
|
|
|
|
|
|
|
|
|
// use subscriptions API to remove video from the archive file, and write it to the blacklist
|
|
|
|
|
if (fs.existsSync(archive_path)) {
|
|
|
|
|
const line = id ? subscriptions_api.removeIDFromArchive(archive_path, id) : null;
|
|
|
|
|
if (blacklistMode && line) writeToBlacklist('audio', line);
|
|
|
|
|
if (await fs.pathExists(archive_path)) {
|
|
|
|
|
const line = id ? await subscriptions_api.removeIDFromArchive(archive_path, id) : null;
|
|
|
|
|
if (blacklistMode && line) await writeToBlacklist('audio', line);
|
|
|
|
|
} else {
|
|
|
|
|
logger.info('Could not find archive file for audio files. Creating...');
|
|
|
|
|
fs.closeSync(fs.openSync(archive_path, 'w'));
|
|
|
|
|
await fs.close(await fs.open(archive_path, 'w'));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (jsonExists) fs.unlinkSync(jsonPath);
|
|
|
|
|
if (thumbnailExists) fs.unlinkSync(thumbnailPath);
|
|
|
|
|
if (jsonExists) await fs.unlink(jsonPath);
|
|
|
|
|
if (thumbnailExists) await fs.unlink(thumbnailPath);
|
|
|
|
|
if (audioFileExists) {
|
|
|
|
|
fs.unlink(audioFilePath, function(err) {
|
|
|
|
|
if (fs.existsSync(jsonPath) || fs.existsSync(audioFilePath)) {
|
|
|
|
|
resolve(false);
|
|
|
|
|
await fs.unlink(audioFilePath);
|
|
|
|
|
if (await fs.pathExists(jsonPath) || await fs.pathExists(audioFilePath)) {
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
resolve(true);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: tell user that the file didn't exist
|
|
|
|
|
resolve(true);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function deleteVideoFile(name, customPath = null, blacklistMode = false) {
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
|
let filePath = customPath ? customPath : videoFolderPath;
|
|
|
|
|
var jsonPath = path.join(filePath,name+'.info.json');
|
|
|
|
|
|
|
|
|
@ -990,19 +970,19 @@ async function deleteVideoFile(name, customPath = null, blacklistMode = false) {
|
|
|
|
|
jsonPath = path.join(__dirname, jsonPath);
|
|
|
|
|
videoFilePath = path.join(__dirname, videoFilePath);
|
|
|
|
|
|
|
|
|
|
let jsonExists = fs.existsSync(jsonPath);
|
|
|
|
|
let videoFileExists = fs.existsSync(videoFilePath);
|
|
|
|
|
let thumbnailExists = fs.existsSync(thumbnailPath);
|
|
|
|
|
let jsonExists = await fs.pathExists(jsonPath);
|
|
|
|
|
let videoFileExists = await fs.pathExists(videoFilePath);
|
|
|
|
|
let thumbnailExists = await fs.pathExists(thumbnailPath);
|
|
|
|
|
|
|
|
|
|
if (!jsonExists) {
|
|
|
|
|
if (fs.existsSync(altJSONPath)) {
|
|
|
|
|
if (await fs.pathExists(altJSONPath)) {
|
|
|
|
|
jsonExists = true;
|
|
|
|
|
jsonPath = altJSONPath;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!thumbnailExists) {
|
|
|
|
|
if (fs.existsSync(altThumbnailPath)) {
|
|
|
|
|
if (await fs.pathExists(altThumbnailPath)) {
|
|
|
|
|
thumbnailExists = true;
|
|
|
|
|
thumbnailPath = altThumbnailPath;
|
|
|
|
|
}
|
|
|
|
@ -1024,86 +1004,67 @@ async function deleteVideoFile(name, customPath = null, blacklistMode = false) {
|
|
|
|
|
|
|
|
|
|
// get ID from JSON
|
|
|
|
|
|
|
|
|
|
var jsonobj = utils.getJSONMp4(name, filePath);
|
|
|
|
|
var jsonobj = await utils.getJSONMp4(name, filePath);
|
|
|
|
|
let id = null;
|
|
|
|
|
if (jsonobj) id = jsonobj.id;
|
|
|
|
|
|
|
|
|
|
// use subscriptions API to remove video from the archive file, and write it to the blacklist
|
|
|
|
|
if (fs.existsSync(archive_path)) {
|
|
|
|
|
const line = id ? subscriptions_api.removeIDFromArchive(archive_path, id) : null;
|
|
|
|
|
if (blacklistMode && line) writeToBlacklist('video', line);
|
|
|
|
|
if (await fs.pathExists(archive_path)) {
|
|
|
|
|
const line = id ? await subscriptions_api.removeIDFromArchive(archive_path, id) : null;
|
|
|
|
|
if (blacklistMode && line) await writeToBlacklist('video', line);
|
|
|
|
|
} else {
|
|
|
|
|
logger.info('Could not find archive file for videos. Creating...');
|
|
|
|
|
fs.closeSync(fs.openSync(archive_path, 'w'));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (jsonExists) fs.unlinkSync(jsonPath);
|
|
|
|
|
if (thumbnailExists) fs.unlinkSync(thumbnailPath);
|
|
|
|
|
if (jsonExists) await fs.unlink(jsonPath);
|
|
|
|
|
if (thumbnailExists) await fs.unlink(thumbnailPath);
|
|
|
|
|
if (videoFileExists) {
|
|
|
|
|
fs.unlink(videoFilePath, function(err) {
|
|
|
|
|
if (fs.existsSync(jsonPath) || fs.existsSync(videoFilePath)) {
|
|
|
|
|
resolve(false);
|
|
|
|
|
await fs.unlink(videoFilePath);
|
|
|
|
|
if (await fs.pathExists(jsonPath) || await fs.pathExists(videoFilePath)) {
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
resolve(true);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: tell user that the file didn't exist
|
|
|
|
|
resolve(true);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// replaces .webm with appropriate extension
|
|
|
|
|
function getTrueFileName(unfixed_path, type) {
|
|
|
|
|
let fixed_path = unfixed_path;
|
|
|
|
|
|
|
|
|
|
const new_ext = (type === 'audio' ? 'mp3' : 'mp4');
|
|
|
|
|
let unfixed_parts = unfixed_path.split('.');
|
|
|
|
|
const old_ext = unfixed_parts[unfixed_parts.length-1];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (old_ext !== new_ext) {
|
|
|
|
|
unfixed_parts[unfixed_parts.length-1] = new_ext;
|
|
|
|
|
fixed_path = unfixed_parts.join('.');
|
|
|
|
|
}
|
|
|
|
|
return fixed_path;
|
|
|
|
|
/**
|
|
|
|
|
* @param {'audio' | 'video'} type
|
|
|
|
|
* @param {string[]} fileNames
|
|
|
|
|
*/
|
|
|
|
|
async function getAudioOrVideoInfos(type, fileNames) {
|
|
|
|
|
let result = await Promise.all(fileNames.map(async fileName => {
|
|
|
|
|
let fileLocation = videoFolderPath+fileName;
|
|
|
|
|
if (type === 'audio') {
|
|
|
|
|
fileLocation += '.mp3.info.json';
|
|
|
|
|
} else if (type === 'video') {
|
|
|
|
|
fileLocation += '.info.json';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getAudioInfos(fileNames) {
|
|
|
|
|
let result = [];
|
|
|
|
|
for (let i = 0; i < fileNames.length; i++) {
|
|
|
|
|
let fileName = fileNames[i];
|
|
|
|
|
let fileLocation = audioFolderPath+fileName+'.mp3.info.json';
|
|
|
|
|
if (fs.existsSync(fileLocation)) {
|
|
|
|
|
let data = fs.readFileSync(fileLocation);
|
|
|
|
|
if (await fs.pathExists(fileLocation)) {
|
|
|
|
|
let data = await fs.readFile(fileLocation);
|
|
|
|
|
try {
|
|
|
|
|
result.push(JSON.parse(data));
|
|
|
|
|
return JSON.parse(data);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
logger.error(`Could not find info for file ${fileName}.mp3`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
let suffix;
|
|
|
|
|
if (type === 'audio') {
|
|
|
|
|
suffix += '.mp3';
|
|
|
|
|
} else if (type === 'video') {
|
|
|
|
|
suffix += '.mp4';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getVideoInfos(fileNames) {
|
|
|
|
|
let result = [];
|
|
|
|
|
for (let i = 0; i < fileNames.length; i++) {
|
|
|
|
|
let fileName = fileNames[i];
|
|
|
|
|
let fileLocation = videoFolderPath+fileName+'.info.json';
|
|
|
|
|
if (fs.existsSync(fileLocation)) {
|
|
|
|
|
let data = fs.readFileSync(fileLocation);
|
|
|
|
|
try {
|
|
|
|
|
result.push(JSON.parse(data));
|
|
|
|
|
} catch(e) {
|
|
|
|
|
logger.error(`Could not find info for file ${fileName}.mp4`);
|
|
|
|
|
}
|
|
|
|
|
logger.error(`Could not find info for file ${fileName}${suffix}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
return null;
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
return result.filter(data => data != null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// downloads
|
|
|
|
@ -1401,7 +1362,6 @@ async function downloadFileByURL_normal(url, type, options, sessionID = null) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function generateArgs(url, type, options) {
|
|
|
|
|
return new Promise(async resolve => {
|
|
|
|
|
var videopath = '%(title)s';
|
|
|
|
|
var globalArgs = config_api.getConfigItem('ytdl_custom_args');
|
|
|
|
|
let useCookies = config_api.getConfigItem('ytdl_use_cookies');
|
|
|
|
@ -1463,7 +1423,7 @@ async function generateArgs(url, type, options) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (useCookies) {
|
|
|
|
|
if (fs.existsSync(path.join(__dirname, 'appdata', 'cookies.txt'))) {
|
|
|
|
|
if (await fs.pathExists(path.join(__dirname, 'appdata', 'cookies.txt'))) {
|
|
|
|
|
downloadConfig.push('--cookies', path.join('appdata', 'cookies.txt'));
|
|
|
|
|
} else {
|
|
|
|
|
logger.warn('Cookies file could not be found. You can either upload one, or disable \'use cookies\' in the Advanced tab in the settings.');
|
|
|
|
@ -1479,26 +1439,26 @@ async function generateArgs(url, type, options) {
|
|
|
|
|
const archive_folder = options.user ? path.join(fileFolderPath, 'archives') : archivePath;
|
|
|
|
|
const archive_path = path.join(archive_folder, `archive_${type}.txt`);
|
|
|
|
|
|
|
|
|
|
fs.ensureDirSync(archive_folder);
|
|
|
|
|
await fs.ensureDir(archive_folder);
|
|
|
|
|
|
|
|
|
|
// create archive file if it doesn't exist
|
|
|
|
|
if (!fs.existsSync(archive_path)) {
|
|
|
|
|
fs.closeSync(fs.openSync(archive_path, 'w'));
|
|
|
|
|
if (!(await fs.pathExists(archive_path))) {
|
|
|
|
|
await fs.close(await fs.open(archive_path, 'w'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let blacklist_path = options.user ? path.join(fileFolderPath, 'archives', `blacklist_${type}.txt`) : path.join(archivePath, `blacklist_${type}.txt`);
|
|
|
|
|
// create blacklist file if it doesn't exist
|
|
|
|
|
if (!fs.existsSync(blacklist_path)) {
|
|
|
|
|
fs.closeSync(fs.openSync(blacklist_path, 'w'));
|
|
|
|
|
if (!(await fs.pathExists(blacklist_path))) {
|
|
|
|
|
await fs.close(await fs.open(blacklist_path, 'w'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let merged_path = path.join(fileFolderPath, `merged_${type}.txt`);
|
|
|
|
|
fs.ensureFileSync(merged_path);
|
|
|
|
|
await fs.ensureFile(merged_path);
|
|
|
|
|
// merges blacklist and regular archive
|
|
|
|
|
let inputPathList = [archive_path, blacklist_path];
|
|
|
|
|
let status = await mergeFiles(inputPathList, merged_path);
|
|
|
|
|
|
|
|
|
|
options.merged_string = fs.readFileSync(merged_path, "utf8");
|
|
|
|
|
options.merged_string = await fs.readFile(merged_path, "utf8");
|
|
|
|
|
|
|
|
|
|
downloadConfig.push('--download-archive', merged_path);
|
|
|
|
|
}
|
|
|
|
@ -1519,8 +1479,7 @@ async function generateArgs(url, type, options) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
logger.verbose(`youtube-dl args being used: ${downloadConfig.join(',')}`);
|
|
|
|
|
resolve(downloadConfig);
|
|
|
|
|
});
|
|
|
|
|
return downloadConfig;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function getVideoInfoByURL(url, args = [], download = null) {
|
|
|
|
@ -1593,11 +1552,11 @@ async function convertFileToMp3(input_file, output_file) {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function writeToBlacklist(type, line) {
|
|
|
|
|
async function writeToBlacklist(type, line) {
|
|
|
|
|
let blacklistPath = path.join(archivePath, (type === 'audio') ? 'blacklist_audio.txt' : 'blacklist_video.txt');
|
|
|
|
|
// adds newline to the beginning of the line
|
|
|
|
|
line = '\n' + line;
|
|
|
|
|
fs.appendFileSync(blacklistPath, line);
|
|
|
|
|
await fs.appendFile(blacklistPath, line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// download management functions
|
|
|
|
@ -1741,21 +1700,6 @@ function removeFileExtension(filename) {
|
|
|
|
|
return filename_parts.join('.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// https://stackoverflow.com/a/32197381/8088021
|
|
|
|
|
const deleteFolderRecursive = function(folder_to_delete) {
|
|
|
|
|
if (fs.existsSync(folder_to_delete)) {
|
|
|
|
|
fs.readdirSync(folder_to_delete).forEach((file, index) => {
|
|
|
|
|
const curPath = path.join(folder_to_delete, file);
|
|
|
|
|
if (fs.lstatSync(curPath).isDirectory()) { // recurse
|
|
|
|
|
deleteFolderRecursive(curPath);
|
|
|
|
|
} else { // delete file
|
|
|
|
|
fs.unlinkSync(curPath);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
fs.rmdirSync(folder_to_delete);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
app.use(function(req, res, next) {
|
|
|
|
|
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
|
|
|
|
|
res.header("Access-Control-Allow-Origin", getOrigin());
|
|
|
|
@ -1771,8 +1715,12 @@ app.use(function(req, res, next) {
|
|
|
|
|
next();
|
|
|
|
|
} else if (req.query.apiKey === admin_token) {
|
|
|
|
|
next();
|
|
|
|
|
} else if (req.query.apiKey && config_api.getConfigItem('ytdl_use_api_key') && req.query.apiKey === config_api.getConfigItem('ytdl_api_key')) {
|
|
|
|
|
} else if (req.query.apiKey && config_api.getConfigItem('ytdl_use_api_key')) {
|
|
|
|
|
if (req.query.apiKey === config_api.getConfigItem('ytdl_api_key')) {
|
|
|
|
|
next();
|
|
|
|
|
} else {
|
|
|
|
|
res.status(401).send('Invalid API key');
|
|
|
|
|
}
|
|
|
|
|
} else if (req.path.includes('/api/video/') || req.path.includes('/api/audio/')) {
|
|
|
|
|
next();
|
|
|
|
|
} else {
|
|
|
|
@ -1900,8 +1848,21 @@ app.post('/api/killAllDownloads', optionalJwt, async function(req, res) {
|
|
|
|
|
res.send(result_obj);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* add thumbnails if present
|
|
|
|
|
* @param files - List of files with thumbnailPath property.
|
|
|
|
|
*/
|
|
|
|
|
async function addThumbnails(files) {
|
|
|
|
|
await Promise.all(files.map(async file => {
|
|
|
|
|
const thumbnailPath = file['thumbnailPath'];
|
|
|
|
|
if (thumbnailPath && (await fs.pathExists(thumbnailPath))) {
|
|
|
|
|
file['thumbnailBlob'] = await fs.readFile(thumbnailPath);
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// gets all download mp3s
|
|
|
|
|
app.get('/api/getMp3s', optionalJwt, function(req, res) {
|
|
|
|
|
app.get('/api/getMp3s', optionalJwt, async function(req, res) {
|
|
|
|
|
var mp3s = db.get('files.audio').value(); // getMp3s();
|
|
|
|
|
var playlists = db.get('playlists.audio').value();
|
|
|
|
|
const is_authenticated = req.isAuthenticated();
|
|
|
|
@ -1915,10 +1876,7 @@ app.get('/api/getMp3s', optionalJwt, function(req, res) {
|
|
|
|
|
mp3s = JSON.parse(JSON.stringify(mp3s));
|
|
|
|
|
|
|
|
|
|
// add thumbnails if present
|
|
|
|
|
mp3s.forEach(mp3 => {
|
|
|
|
|
if (mp3['thumbnailPath'] && fs.existsSync(mp3['thumbnailPath']))
|
|
|
|
|
mp3['thumbnailBlob'] = fs.readFileSync(mp3['thumbnailPath']);
|
|
|
|
|
});
|
|
|
|
|
await addThumbnails(mp3s);
|
|
|
|
|
|
|
|
|
|
res.send({
|
|
|
|
|
mp3s: mp3s,
|
|
|
|
@ -1927,7 +1885,7 @@ app.get('/api/getMp3s', optionalJwt, function(req, res) {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// gets all download mp4s
|
|
|
|
|
app.get('/api/getMp4s', optionalJwt, function(req, res) {
|
|
|
|
|
app.get('/api/getMp4s', optionalJwt, async function(req, res) {
|
|
|
|
|
var mp4s = db.get('files.video').value(); // getMp4s();
|
|
|
|
|
var playlists = db.get('playlists.video').value();
|
|
|
|
|
|
|
|
|
@ -1942,10 +1900,7 @@ app.get('/api/getMp4s', optionalJwt, function(req, res) {
|
|
|
|
|
mp4s = JSON.parse(JSON.stringify(mp4s));
|
|
|
|
|
|
|
|
|
|
// add thumbnails if present
|
|
|
|
|
mp4s.forEach(mp4 => {
|
|
|
|
|
if (mp4['thumbnailPath'] && fs.existsSync(mp4['thumbnailPath']))
|
|
|
|
|
mp4['thumbnailBlob'] = fs.readFileSync(mp4['thumbnailPath']);
|
|
|
|
|
});
|
|
|
|
|
await addThumbnails(mp4s);
|
|
|
|
|
|
|
|
|
|
res.send({
|
|
|
|
|
mp4s: mp4s,
|
|
|
|
@ -1991,7 +1946,7 @@ app.post('/api/getFile', optionalJwt, function (req, res) {
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.post('/api/getAllFiles', optionalJwt, function (req, res) {
|
|
|
|
|
app.post('/api/getAllFiles', optionalJwt, async function (req, res) {
|
|
|
|
|
// these are returned
|
|
|
|
|
let files = [];
|
|
|
|
|
let playlists = [];
|
|
|
|
@ -2034,10 +1989,7 @@ app.post('/api/getAllFiles', optionalJwt, function (req, res) {
|
|
|
|
|
files = JSON.parse(JSON.stringify(files));
|
|
|
|
|
|
|
|
|
|
// add thumbnails if present
|
|
|
|
|
files.forEach(file => {
|
|
|
|
|
if (file['thumbnailPath'] && fs.existsSync(file['thumbnailPath']))
|
|
|
|
|
file['thumbnailBlob'] = fs.readFileSync(file['thumbnailPath']);
|
|
|
|
|
});
|
|
|
|
|
await addThumbnails(files);
|
|
|
|
|
|
|
|
|
|
res.send({
|
|
|
|
|
files: files,
|
|
|
|
@ -2241,7 +2193,7 @@ app.post('/api/getSubscription', optionalJwt, async (req, res) => {
|
|
|
|
|
let appended_base_path = path.join(base_path, (subscription.isPlaylist ? 'playlists' : 'channels'), subscription.name, '/');
|
|
|
|
|
let files;
|
|
|
|
|
try {
|
|
|
|
|
files = utils.recFindByExt(appended_base_path, 'mp4');
|
|
|
|
|
files = await utils.recFindByExt(appended_base_path, 'mp4');
|
|
|
|
|
} catch(e) {
|
|
|
|
|
files = null;
|
|
|
|
|
logger.info('Failed to get folder for subscription: ' + subscription.name + ' at path ' + appended_base_path);
|
|
|
|
@ -2456,7 +2408,7 @@ app.post('/api/deleteMp3', optionalJwt, async (req, res) => {
|
|
|
|
|
var blacklistMode = req.body.blacklistMode;
|
|
|
|
|
|
|
|
|
|
if (req.isAuthenticated()) {
|
|
|
|
|
let success = auth_api.deleteUserFile(req.user.uid, uid, 'audio', blacklistMode);
|
|
|
|
|
let success = await auth_api.deleteUserFile(req.user.uid, uid, 'audio', blacklistMode);
|
|
|
|
|
res.send(success);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -2465,7 +2417,7 @@ app.post('/api/deleteMp3', optionalJwt, async (req, res) => {
|
|
|
|
|
var name = audio_obj.id;
|
|
|
|
|
var fullpath = audioFolderPath + name + ".mp3";
|
|
|
|
|
var wasDeleted = false;
|
|
|
|
|
if (fs.existsSync(fullpath))
|
|
|
|
|
if (await fs.pathExists(fullpath))
|
|
|
|
|
{
|
|
|
|
|
deleteAudioFile(name, null, blacklistMode);
|
|
|
|
|
db.get('files.audio').remove({uid: uid}).write();
|
|
|
|
@ -2487,7 +2439,7 @@ app.post('/api/deleteMp4', optionalJwt, async (req, res) => {
|
|
|
|
|
var blacklistMode = req.body.blacklistMode;
|
|
|
|
|
|
|
|
|
|
if (req.isAuthenticated()) {
|
|
|
|
|
let success = auth_api.deleteUserFile(req.user.uid, uid, 'video', blacklistMode);
|
|
|
|
|
let success = await auth_api.deleteUserFile(req.user.uid, uid, 'video', blacklistMode);
|
|
|
|
|
res.send(success);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -2496,7 +2448,7 @@ app.post('/api/deleteMp4', optionalJwt, async (req, res) => {
|
|
|
|
|
var name = video_obj.id;
|
|
|
|
|
var fullpath = videoFolderPath + name + ".mp4";
|
|
|
|
|
var wasDeleted = false;
|
|
|
|
|
if (fs.existsSync(fullpath))
|
|
|
|
|
if (await fs.pathExists(fullpath))
|
|
|
|
|
{
|
|
|
|
|
wasDeleted = await deleteVideoFile(name, null, blacklistMode);
|
|
|
|
|
db.get('files.video').remove({uid: uid}).write();
|
|
|
|
@ -2582,7 +2534,7 @@ app.post('/api/downloadArchive', async (req, res) => {
|
|
|
|
|
|
|
|
|
|
let full_archive_path = path.join(archive_dir, 'archive.txt');
|
|
|
|
|
|
|
|
|
|
if (fs.existsSync(full_archive_path)) {
|
|
|
|
|
if (await fs.pathExists(full_archive_path)) {
|
|
|
|
|
res.sendFile(full_archive_path);
|
|
|
|
|
} else {
|
|
|
|
|
res.sendStatus(404);
|
|
|
|
@ -2594,14 +2546,14 @@ var upload_multer = multer({ dest: __dirname + '/appdata/' });
|
|
|
|
|
app.post('/api/uploadCookies', upload_multer.single('cookies'), async (req, res) => {
|
|
|
|
|
const new_path = path.join(__dirname, 'appdata', 'cookies.txt');
|
|
|
|
|
|
|
|
|
|
if (fs.existsSync(req.file.path)) {
|
|
|
|
|
fs.renameSync(req.file.path, new_path);
|
|
|
|
|
if (await fs.pathExists(req.file.path)) {
|
|
|
|
|
await fs.rename(req.file.path, new_path);
|
|
|
|
|
} else {
|
|
|
|
|
res.sendStatus(500);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fs.existsSync(new_path)) {
|
|
|
|
|
if (await fs.pathExists(new_path)) {
|
|
|
|
|
res.send({success: true});
|
|
|
|
|
} else {
|
|
|
|
|
res.sendStatus(500);
|
|
|
|
@ -2824,9 +2776,9 @@ app.post('/api/logs', async function(req, res) {
|
|
|
|
|
let logs = null;
|
|
|
|
|
let lines = req.body.lines;
|
|
|
|
|
logs_path = path.join('appdata', 'logs', 'combined.log')
|
|
|
|
|
if (fs.existsSync(logs_path)) {
|
|
|
|
|
if (await fs.pathExists(logs_path)) {
|
|
|
|
|
if (lines) logs = await read_last_lines.read(logs_path, lines);
|
|
|
|
|
else logs = fs.readFileSync(logs_path, 'utf8');
|
|
|
|
|
else logs = await fs.readFile(logs_path, 'utf8');
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
logger.error(`Failed to find logs file at the expected location: ${logs_path}`)
|
|
|
|
@ -2842,8 +2794,10 @@ app.post('/api/clearAllLogs', async function(req, res) {
|
|
|
|
|
logs_err_path = path.join('appdata', 'logs', 'error.log');
|
|
|
|
|
let success = false;
|
|
|
|
|
try {
|
|
|
|
|
fs.writeFileSync(logs_path, '');
|
|
|
|
|
fs.writeFileSync(logs_err_path, '');
|
|
|
|
|
await Promise.all([
|
|
|
|
|
fs.writeFile(logs_path, ''),
|
|
|
|
|
fs.writeFile(logs_err_path, '')
|
|
|
|
|
])
|
|
|
|
|
success = true;
|
|
|
|
|
} catch(e) {
|
|
|
|
|
logger.error(e);
|
|
|
|
@ -2860,10 +2814,8 @@ app.post('/api/clearAllLogs', async function(req, res) {
|
|
|
|
|
let type = req.body.type;
|
|
|
|
|
let result = null;
|
|
|
|
|
if (!urlMode) {
|
|
|
|
|
if (type === 'audio') {
|
|
|
|
|
result = getAudioInfos(fileNames)
|
|
|
|
|
} else if (type === 'video') {
|
|
|
|
|
result = getVideoInfos(fileNames);
|
|
|
|
|
if (type === 'audio' || type === 'video') {
|
|
|
|
|
result = await getAudioOrVideoInfos(type, fileNames);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
result = await getUrlInfos(fileNames);
|
|
|
|
@ -2936,7 +2888,7 @@ app.post('/api/deleteUser', optionalJwt, async (req, res) => {
|
|
|
|
|
const user_db_obj = users_db.get('users').find({uid: uid});
|
|
|
|
|
if (user_db_obj.value()) {
|
|
|
|
|
// user exists, let's delete
|
|
|
|
|
deleteFolderRecursive(user_folder);
|
|
|
|
|
await fs.remove(user_folder);
|
|
|
|
|
users_db.get('users').remove({uid: uid}).write();
|
|
|
|
|
}
|
|
|
|
|
res.send({success: true});
|
|
|
|
|