Przeglądaj źródła

async/await updates

Timothy Pomeroy 6 lat temu
rodzic
commit
50bed807d6
1 zmienionych plików z 198 dodań i 106 usunięć
  1. 198 106
      index.js

+ 198 - 106
index.js

@@ -1,29 +1,29 @@
-"use strict";
+'use strict';
 
-const fs = require("fs");
-const path = require("path");
-const minimist = require("minimist");
-const low = require("lowdb");
+const fs = require('fs');
+const path = require('path');
+const minimist = require('minimist');
+const low = require('lowdb');
 const Queue = require('better-queue');
-const FileSync = require("lowdb/adapters/FileSync");
+const FileSync = require('lowdb/adapters/FileSync');
 
-const chokidar = require("chokidar");
-const hbjs = require("handbrake-js");
+const chokidar = require('chokidar');
+const hbjs = require('handbrake-js');
 
 const args = minimist(process.argv.slice(2), {
   alias: {
-    h: "help",
-    v: "version",
-    c: "config",
-    i: "ignoreInitial",
-    t: "test"
-  }
+    h: 'help',
+    v: 'version',
+    c: 'config',
+    i: 'ignoreInitial',
+    t: 'test',
+  },
 });
 
 const version = () => {
   const pkg = require('./package.json');
   return console.log(pkg.version);
-}
+};
 
 const help = () => {
   let message = `Usage:
@@ -32,9 +32,9 @@ const help = () => {
 \tnpm run pr0n
 \tnpm run all
 \tnpm run help
-\tnpm run version\n`
+\tnpm run version\n`;
   return console.log(message);
-}
+};
 
 String.prototype.toTitleCase = function() {
   var i, j, str, lowers, uppers;
@@ -43,18 +43,36 @@ String.prototype.toTitleCase = function() {
   });
   // Certain minor words should be left lowercase unless
   // they are the first or last words in the string
-  lowers = ['A', 'An', 'The', 'And', 'But', 'Or', 'For', 'Nor', 'As', 'At',
-  'By', 'For', 'From', 'In', 'Into', 'Near', 'Of', 'On', 'Onto', 'To', 'With'];
+  lowers = [
+    'A',
+    'An',
+    'The',
+    'And',
+    'But',
+    'Or',
+    'For',
+    'Nor',
+    'As',
+    'At',
+    'By',
+    'For',
+    'From',
+    'In',
+    'Into',
+    'Near',
+    'Of',
+    'On',
+    'Onto',
+    'To',
+    'With',
+  ];
   for (i = 0, j = lowers.length; i < j; i++)
-    str = str.replace(new RegExp('\\s' + lowers[i] + '\\s', 'g'),
-      function(txt) {
-        return txt.toLowerCase();
-      });
+    str = str.replace(new RegExp('\\s' + lowers[i] + '\\s', 'g'), function(txt) {
+      return txt.toLowerCase();
+    });
   // Certain words such as initialisms or acronyms should be left uppercase
   uppers = ['Id', 'Tv'];
-  for (i = 0, j = uppers.length; i < j; i++)
-    str = str.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'),
-      uppers[i].toUpperCase());
+  for (i = 0, j = uppers.length; i < j; i++) str = str.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'), uppers[i].toUpperCase());
   return str;
 };
 
@@ -62,29 +80,48 @@ String.prototype.toTitleCase = function() {
 const getDbForDir = (dir, opts) => {
   let options = opts || Object.assign({}, defaults, paths[dir]); // baseline the options
   let adapter = new FileSync(options.database); // init the db adapter
-  let db = low(adapter);  // connect the db
+  let db = low(adapter); // connect the db
   return db;
 };
 
 // find a file in the db
 const findFile = (db, file) => {
-  return db.get('files').find({ input:file }).value();	// does it already exist?
+  return db
+    .get('files')
+    .find({
+      input: file,
+    })
+    .value(); // does it already exist?
 };
 
 // set a file in the db
 const setFile = (db, file, payload) => {
   if (!payload && typeof file === 'object')
-    return db.get('files').push(file).write();
-  return db.get('files').find({ input: file }).assign(payload).write();
+    return db
+      .get('files')
+      .push(file)
+      .write();
+  return db
+    .get('files')
+    .find({
+      input: file,
+    })
+    .assign(payload)
+    .write();
 };
 
 // remove a file from the db
 const removeFile = (db, file) => {
-  return db.get('files').remove({ input: file }).write(); // remove file from database
+  return db
+    .get('files')
+    .remove({
+      input: file,
+    })
+    .write(); // remove file from database
 };
 
 // write process output
-const processOutput = (str) => {
+const processOutput = str => {
   process.stdout.clearLine();
   process.stdout.cursorTo(0);
   process.stdout.write(str);
@@ -93,34 +130,41 @@ const processOutput = (str) => {
 // spawn a handbrake
 const processWithHandbrake = (input, output, preset) => {
   return new Promise((resolve, reject) => {
-    const filename = path.basename(input);
-    hbjs.spawn({
-    	input: input,
-    	output: output,
-    	preset: preset
-    }).on('start', (err) => {
-      processOutput(` --> processing "${filename}" to "${output}" with "${preset}"`);
-    }).on('error', (err) => {
-      processOutput(` --> processing ${output} error: ${err.message || err}.\n`);
-      reject(err);
-    }).on('progress', (progress) => {
-      processOutput(` --> processing ${output} - ${progress.percentComplete}%, ETA: ${progress.eta}`);
-    }).on('cancelled', () => {
-      processOutput(` --> processing ${output} cancelled\n`);
-      reject(new Error(`Processing ${output} cancelled`));
-    }).on('complete', () => {
-      processOutput(` --> processing ${output} complete\n`);
-      resolve(true);
-    });
+    const inputName = path.basename(input);
+    const outputName = path.basename(output);
+    hbjs
+      .spawn({
+        input: input,
+        output: output,
+        preset: preset,
+      })
+      .on('start', err => {
+        processOutput(` -> processing "${inputName}" to "${outputName}" with "${preset}"`);
+      })
+      .on('error', err => {
+        processOutput(` -> processing ${outputName} error: ${err.message || err}.\n`);
+        reject(err);
+      })
+      .on('progress', progress => {
+        processOutput(` -> processing ${outputName} - ${progress.percentComplete}%, ETA: ${progress.eta}`);
+      })
+      .on('cancelled', () => {
+        processOutput(` -> processing ${outputName} cancelled\n`);
+        reject(new Error(`Processing ${outputName} cancelled`));
+      })
+      .on('complete', () => {
+        processOutput(` -> processing ${outputName} complete\n`);
+        resolve(true);
+      });
   });
 };
 
-const processFile = async (file) => {
+const processFile = async file => {
   let db,
     options,
     preset = 'Fast 1080p30',
     clean = {
-      '.': ' '
+      '.': ' ',
     },
     ext = 'm4v',
     filename = path.parse(file).name,
@@ -129,23 +173,33 @@ const processFile = async (file) => {
     titlecase = false,
     folder = 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?
+    if (file && dir && file.indexOf(dir) > -1) {
+      // is this in this path?
       options = Object.assign({}, defaults, paths[dir]); // baseline the options
       db = getDbForDir(dir, options); // init the db connection
-      let found = findFile(db, file);	// does it already exist?
-      if (found && found.status && found.status === 'success') {	// was it already processed?
+      let found = findFile(db, file); // does it already exist?
+      if (found && found.status && found.status === 'success') {
+        // was it already processed?
         //console.log(`File ${file} has already been successfully processed.`);
-        return false;	// break this loop
-      } else if (!found) {	// was it found?
-        processOutput(`-> ${path.basename(file)} [processing]`);
-        setFile(db, { input:file, output:'', status:'', date:new Date() }); // push onto the list an entry
+        return false; // break this loop
+      } else if (!found) {
+        // was it found?
+        processOutput(` -> ${path.basename(file)} [processing]`);
+        setFile(db, {
+          input: file,
+          output: '',
+          status: '',
+          date: new Date(),
+        }); // push onto the list an entry
       } else {
-        processOutput(`-> ${path.basename(file)} [re-processing]`);
-        setFile(db, file, { status:'', date:new Date() }); // set the status to blank
+        processOutput(` -> ${path.basename(file)} [re-processing]`);
+        setFile(db, file, {
+          status: '',
+          date: new Date(),
+        }); // set the status to blank
       }
       preset = options.preset; // apply the specifics ...
       clean = options.clean; // ...
@@ -170,48 +224,61 @@ const processFile = async (file) => {
   // 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
+    folder = match && match.length > 0 ? match[0].slice(0, -1) : false; // get just the stuff before the dot ... or false
   }
   // do we have title case enabled?
-  if (options.titlecase) output = output.toTitleCase();  // titlecase that string
+  if (options.titlecase) output = output.toTitleCase(); // titlecase that string
   // baseline the target
-  let target = destination + ((folder) ? '/' + folder : ''); // setup the target location
+  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 (fs.existsSync(output)) {
-    processOutput(`-> ${path.basename(file)} [skipping ... already processed]\n`);
-    setFile(db, file, { output: output, status: 'success', date:new Date() }); // update database with status
+    processOutput(` -> ${path.basename(file)} [skipping ... already processed]\n`);
+    setFile(db, file, {
+      output: output,
+      status: 'success',
+      date: new Date(),
+    }); // update database with status
     return false;
   } else {
     processOutput('\n'); // send a new line
   }
   // update database with output name
-  setFile(db, file, { output: output });
+  setFile(db, file, {
+    output: output,
+  });
   // create parent if required
   if (target && !fs.existsSync(target)) {
-    console.log(' --> creating parent directory:', target);
+    processOutput(` -> creating parent directory: ${target}\n`);
     fs.mkdirSync(target, {
-      recursive: true
+      recursive: true,
     });
   }
   // spawn handbrake
   if (!test) {
     try {
       await processWithHandbrake(input, output, preset);
-      setFile(db, file, { status: 'success', date:new Date() }); // update database with status
+      setFile(db, file, {
+        status: 'success',
+        date: new Date(),
+      }); // update database with status
     } catch (err) {
-      setFile(db, file, { status: 'failure', date:new Date() }); 	// update database with status
+      setFile(db, file, {
+        status: 'failure',
+        date: new Date(),
+      }); // update database with status
     }
   }
   return true; // when complete return true
 };
 
 // cleanup removes from the db
-const cleanup = (file) => {
+const cleanup = file => {
   let db;
   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?
+    if (file && dir && file.indexOf(dir) > -1) {
+      // is this in this path?
       db = getDbForDir(dir); // init the db connection
       removeFile(db, file); // remove file form database
     }
@@ -221,20 +288,20 @@ const cleanup = (file) => {
 // handle args
 if (args.version) return version(); // show version
 if (args.help || !args.config) return help(); // show help
-const ignoreInitial = (args.hasOwnProperty('ignoreInitial')) ? args.ignoreInitial : false;  // ignore initial files
-const test = (args.hasOwnProperty('test')) ? args.test : false; // do a dry run ... just log
+const ignoreInitial = args.hasOwnProperty('ignoreInitial') ? args.ignoreInitial : false; // ignore initial files
+const test = args.hasOwnProperty('test') ? args.test : false; // do a dry run ... just log
 
 // get our paths
 const paths = require(args.config);
 
 // init our defaults
 const defaults = {
-  "preset": "Fast 1080p30",
-  "clean": {},
-  "titlecase": false,
-  "folder": false,
-  "database": "data/db.json"
-}
+  preset: 'Fast 1080p30',
+  clean: {},
+  titlecase: false,
+  folder: false,
+  database: 'data/db.json',
+};
 
 // setup watcher options
 const opts = {
@@ -246,44 +313,69 @@ const opts = {
   depth: 1,
   awaitWriteFinish: {
     stabilityThreshold: 3000,
-    pollInterval: 1000
+    pollInterval: 1000,
   },
   ignorePermissionErrors: false,
-  atomic: true
+  atomic: true,
 };
 
 // parse the paths to dirs
 const dirs = Object.keys(paths);
 
 // initialize watches and db then start the watcher
-const main = () => {
-  var queue = new Queue((input,cb) => {  // init the queue
-    let result = processFile(input); // process the queue
-    cb(null,result);
-  });
+const main = async () => {
+  var queue = new Queue(
+    async (input, cb) => {
+      // init the queue
+      let result = await processFile(input); // process the queue
+      cb(null, result);
+    },
+    {
+      batchSize: 1,
+      concurrent: 1,
+      maxRetries: 3,
+      retryDelay: 5000,
+    }
+  );
   var watches = []; // array of things to watch
-  for (let d in dirs) { // loop the dirs
+  for (let d in dirs) {
+    // loop the dirs
     let dir = dirs[d]; // pointer
     let options = Object.assign({}, defaults, paths[dir]); // baseline the options
     let db = getDbForDir(dir);
-    db.defaults({ files: [] }).write(); // init the database
-    for (let e in options.exts) { // loop the exts to watch
+    db.defaults({
+      files: [],
+    }).write(); // init the database
+    for (let e in options.exts) {
+      // loop the exts to watch
       let ext = options.exts[e]; // alias the ext
       watches.push(`${dir}/**/*.${ext}`); // push the watch
     }
   }
   const watcher = chokidar.watch(watches, opts); // init our watcher
-  console.log('Watching', watches);
-  watcher.on('add', async (file) => { // when a new file is added ...
-    queue.push(file); // push the file onto the queue to be processed
-  }).on('change', (file) => { // when a file changes ...
-    console.log(` -> ${file} has been changed`);
-  }).on('unlink', async (file) => { // when a file is removed ...
-    console.log(` -> ${file} has been removed`);
-    cleanup(file);
-  }).on('error', (error) => { // on errors ..
-    console.error(` -> Error: ${error.message || error}`);
-  });
-}
+  console.log('Watching:', watches, '\n');
+  watcher
+    .on('add', async file => {
+      // when a new file is added ...
+      queue.push(file); // push the file onto the queue to be processed
+    })
+    .on('change', file => {
+      // when a file changes ...
+      console.log(` -> ${file} has been changed`);
+    })
+    .on('unlink', async file => {
+      // when a file is removed ...
+      console.log(` -> ${file} has been removed`);
+      cleanup(file);
+    })
+    .on('error', error => {
+      // on errors ..
+      console.error(` -> Error: ${error.message || error}`);
+    });
+};
 
-main();
+(async () => {
+  main();
+})().catch(err => {
+  console.log('Error:', err.message || err);
+});