const fs = require('fs'); const path = require('path'); const paths = require('../data/paths.json'); // get our paths const settings = require('../data/settings.json'); // get the settings const { log, toTitleCase } = require('./utils'); const db = require('./db'); const handbrake = require('./handbrake'); const tvdb = require('./tvdb'); const dirs = Object.keys(paths); // get a list of the paths from the keys const defaults = settings.defaults || {}; // load the defaults const exists = async file => fs.existsSync(file); const stat = async file => fs.statSync(file); const mkdir = async file => fs.mkdirSync(file, { recursive: true }); const remove = async file => fs.unlinkSync(file); const fileSize = async file => { let stats = (await exists(file)) ? await stat(file) : false; let bytes = stats ? stats['size'] : 0; return bytes && bytes > 0 ? bytes / 1024 : 0; }; const cleanFileName = async (output='', clean = {}) => { // clean the output name let cleanKeys = Object.keys(clean); for (let c in cleanKeys) { let key = cleanKeys[c]; let val = clean[key]; let re = new RegExp(key, 'gi'); output = output.replace(re, val); } // baseline the output name output = output.trim(); // trim the whitespace output = output.replace(/(\d{4})$/, `($1)`); // if there is a date at the end wrap it return output; }; const process = async file => { let database, options, type = 'movie', preset = 'Fast 1080p30', clean = { '.': ' ', }, ext = 'm4v', filename = path.parse(file).name, input = file, output = filename, titlecase = false, folder = false, genre = false, destination = ''; // determine the presets and clean object for (let i = 0, l = dirs.length; i < l; i++) { let dir = dirs[i]; // pointer to the dir if (file && dir && file.indexOf(dir) > -1) { // is this in this path? options = Object.assign({}, defaults, paths[dir]); // baseline the options database = db.connect(dir, options); // init the db connection let found = db.find(database, file); // does it already exist? if (found && found.status && found.status === 'success') { // was it already processed? return false; // break this loop } else if (!found) { // was it found? .. nope log(` -> "${path.basename(file)}" [processing]`); db.set(database, { input: file, output: '', status: '', date: new Date(), }); // push onto the list an entry } else { log(` -> "${path.basename(file)}" [re-processing]`); db.set(database, file, { status: '', date: new Date(), }); // set the status to blank } type = options.type; // apply the specifics ... preset = options.preset; // apply the specifics ... clean = options.clean; // ... ext = options.ext; // ... titlecase = !!options.titlecase; // ... folder = !!options.folder; // ... genre = !!options.genre; // ... destination = options.destination; // ... break; // break the loop } } // clean the output name output = await cleanFileName(output,clean); // do we have a sub folder option? if (folder) { let match = output.match(/^(.*?)?\./gm); // get the name for the file before the first . folder = match && match.length > 0 ? match[0].slice(0, -1) : false; // get just the stuff before the dot ... or false } // do we want to use the genre for a parent folder? if (genre) { folder = await tvdb.genre(output, type); // lookup the genre name } // do we have title case enabled? if (options.titlecase) output = toTitleCase(output); // titlecase that string // baseline the target let target = destination + (folder ? '/' + folder : ''); // setup the target location output = target + '/' + output + '.' + ext; // update the new name // do we already have an existing output that matches? if (exists(output)) { let outputSize = await fileSize(output); //get output filesize if (outputSize > 100) { //make sure its bigger than 100k log(` -> "${path.basename(file)}" [skipping] (already processed)\n`); db.set(database, file, { output: output, status: 'success', date: new Date(), }); // update database with status return false; } } //process.stdout.write('\n'); // send a new line // update database with output name db.set(database, file, { output: output, }); // create parent if required if (!exists(target)) { log(` -> "${path.basename(file)}" [creating parent directory] ("${target}")`); await mkdir(target); } // spawn handbrake if (!test) { try { await handbrake.process(input, output, preset); db.set(database, file, { status: 'success', date: new Date(), }); // update database with status } catch (err) { if (exists(output)) remove(output); // remove file on failure db.set(database, file, { status: 'failure', date: new Date(), }); // update database with status } } return true; // when complete return true }; /* * cleanup removes from the db * * @async * @param Array dirs list of dirs. * @param String file file name to find/match. * * @return Boolean did we clean it up */ const cleanup = async (dirs, file) => { let database, result; // loop the dirs for matches for (let i = 0, l = dirs.length; i < l; i++) { let dir = dirs[i]; // pointer to the dir // is this in this path? if (file && dir && file.indexOf(dir) > -1) { database = await db.connect(dir); // init the database connection result = await db.remove(database, file); // remove file form database break; } } return result; }; module.exports = { cleanup, exists, fileSize, mkdir, process, stat };