Przeglądaj źródła

Added batch mode and CLI interface.

Roel van Uden 9 lat temu
rodzic
commit
66f62d3aa1
7 zmienionych plików z 118 dodań i 55 usunięć
  1. 4 3
      README.md
  2. 0 26
      app.js
  3. 7 0
      index.js
  4. 1 0
      package.json
  5. 77 0
      src/batch.js
  6. 24 26
      src/episode.js
  7. 5 0
      src/index.js

+ 4 - 3
README.md

@@ -36,13 +36,14 @@ prior to using this application.
 * Add ASS support.
 * Add muxing (MP4+ASS=MKV).
 * Add series API to save an entire series rather than per-episode.
+* Add support for incremental saves.
+* Add batch-mode to queue a bunch of series.
+* Add CLI interface with all the options.
 
 ### Pending Implementation
 
-* Add batch-mode to queue a bunch of series.
-* Add support for incremental saves; currently just overwriting stuff, bad.
+* Support scheduled merging; if it fails now, the video is probably being watched.
 * Add authentication to the entire stack to support premium content.
-* Add CLI interface with all the options.
 * Enjoy beautiful anime series from disk when internet is down.
 
 ## Work In Progress

+ 0 - 26
app.js

@@ -1,26 +0,0 @@
-'use strict';
-var config = {
-	format: 'ass', 			 // defaults to srt
-	merge: true, 				 // defaults to false
-	path: 'F:\\Anime', 	 // defaults to process.cwd(),
-	title: 'Fairy Tail', // defaults to series title.
-	tag: undefined,  		 // defaults to CrunchyRoll
-};
-
-/*var episode = require('./src/episode');
-episode(
-	config,
-	'http://www.crunchyroll.com/fairy-tail/episode-1-the-dragon-king-652167',
-	function(err) {
-	if (err) return console.log(err);
-	console.log('All done!');
-});*/
-
-var series = require('./src/series');
-series(
-	config,
-	'http://www.crunchyroll.com/fairy-tail',
-	function(err) {
-		if (err) return console.log(err.stack || err);
-		console.log('All done!');
-});

+ 7 - 0
index.js

@@ -0,0 +1,7 @@
+'use strict';
+var src = require('./src');
+
+src.batch(process.argv, function(err) {
+  if (err) return console.error(err.stack || err);
+  console.log('Finished.');
+});

+ 1 - 0
package.json

@@ -11,6 +11,7 @@
   "dependencies": {
     "big-integer": "^1.4.1",
     "cheerio": "^0.18.0",
+    "commander": "^2.6.0",
     "mkdirp": "^0.5.0",
     "request": "^2.51.0",
     "xml2js": "^0.4.4"

+ 77 - 0
src/batch.js

@@ -0,0 +1,77 @@
+'use strict';
+var Command = require('commander').Command;
+var fs = require('fs');
+var path = require('path');
+var series = require('./series');
+
+/**
+ * Streams the batch of series to disk.
+ * @param {Array.<string>} args
+ * @param {function(Error)} done
+ */
+module.exports = function(args, done) {
+  var config = _parse(args);
+  var batchPath = path.join(config.output || process.cwd(), 'CrunchyRoll.txt');
+  _tasks(config, batchPath, function(err, tasks) {
+    if (err) return done(err);
+    var i = 0;
+    (function next() {
+      if (i >= tasks.length) return done();
+      series(tasks[i].config, tasks[i].address, function(err) {
+        if (err) return done(err);
+        i += 1;
+        next();
+      });
+    })();
+  });
+};
+
+/**
+ * Parses the configuration or reads the batch-mode file for tasks.
+ * @private
+ * @param {Object} config
+ * @param {string} batchPath
+ * @param {function(Error, Object=} done
+ */
+function _tasks(config, batchPath, done) {
+  if (config.args.length) {
+    return done(undefined, config.args.map(function(address) {
+      return {address: address, config: config};
+    }));
+  }
+  fs.exists(batchPath, function(exists) {
+    if (!exists) return done(undefined, []);
+    fs.readFile(batchPath, 'utf8', function(err, data) {
+      if (err) return done(err);
+      var map = [];
+      data.split(/\r?\n/).forEach(function(line) {
+        var lineConfig = _parse(process.argv.concat(line.split(' ')));
+        lineConfig.args.forEach(function(address) {
+          if (!address) return;
+          map.push({address: address, config: lineConfig});
+        });
+      });
+      done(undefined, map);
+    });
+  });
+}
+
+/**
+ * Parses the arguments and returns a configuration.
+ * @private
+ * @param {Array.<string>} args
+ * @returns {Object}
+ */
+function _parse(args) {
+  return new Command().version(require('../package').version)
+    // Disables
+    .option('-c, --cache', 'Disables the cache.')
+    .option('-m, --merge', 'Disables merging subtitles and videos.')
+    // Settings
+    .option('-f, --format <s>', 'The subtitle format. (Default: ass)')
+    .option('-o, --output <s>', 'The output path.')
+    .option('-s, --series <s>', 'The series override.')
+    .option('-t, --tag <s>', 'The subgroup. (Default: CrunchyRoll)')
+    .option('-v, --volume <i>', 'The volume.')
+    .parse(args);
+}

+ 24 - 26
src/episode.js

@@ -24,21 +24,6 @@ module.exports = function (config, address, done) {
   });
 };
 
-/**
- * Affixes zero-padding to the value.
- * @private
- * @param {(number|string)} value
- * @param {number} length
- * @returns {string}
- */
-function _affix(value, length) {
-  if (typeof value !== 'string') value = String(value);
-  var suffix = value.indexOf('.') !== -1;
-  var add = length - (suffix ? value.indexOf('.') : value.length);
-  while ((add -= 1) >= 0) value = '0' + value;
-  return value;
-}
-
 /**
  * Completes a download and writes the message with an elapsed time.
  * @param {string} message
@@ -47,9 +32,9 @@ function _affix(value, length) {
  */
 function _complete(message, begin, done) {
   var timeInMs = Date.now() - begin;
-  var seconds = _affix(Math.floor(timeInMs / 1000) % 60, 2);
-  var minutes = _affix(Math.floor(timeInMs / 1000 / 60) % 60, 2);
-  var hours = _affix(Math.floor(timeInMs / 1000 / 60 / 60), 2);
+  var seconds = _prefix(Math.floor(timeInMs / 1000) % 60, 2);
+  var minutes = _prefix(Math.floor(timeInMs / 1000 / 60) % 60, 2);
+  var hours = _prefix(Math.floor(timeInMs / 1000 / 60 / 60), 2);
   console.log(message + ' (' + hours + ':' + minutes + ':' + seconds + ')');
   done();
 }
@@ -86,17 +71,17 @@ function _download(config, page, player, done) {
 }
 
 /**
-* Names the file based on the config, page, series and tag.
-* @param {Object} config
-* @param {Object} page
-* @param {string} series
-* @param {string} tag
-* @returns {string}
-*/
+ * Names the file based on the config, page, series and tag.
+ * @param {Object} config
+ * @param {Object} page
+ * @param {string} series
+ * @param {string} tag
+ * @returns {string}
+ */
 function _name(config, page, series, tag) {
   var v = config.volume ? (config.volume < 10 ? '0' : '') + config.volume : '';
   var e = (page.episode < 10 ? '0' : '') + page.episode;
-  return series + ' - ' + (v ? v + 'x' : '') + e + ' [' + tag + ']';
+  return series + ' ' + (v ? v + 'x' : '') + e + ' [' + tag + ']';
 }
 
 /**
@@ -123,6 +108,19 @@ function _page(address, done) {
   });
 }
 
+/**
+ * Prefixes a value.
+ * @private
+ * @param {(number|string)} value
+ * @param {number} length
+ * @returns {string}
+ */
+function _prefix(value, length) {
+  if (typeof value !== 'string') value = String(value);
+  while (value.length < length) value = '0' + value;
+  return value;
+}
+
 /**
  * Requests the player data and scrapes the subtitle and video data.
  * @private

+ 5 - 0
src/index.js

@@ -0,0 +1,5 @@
+module.exports = {
+  batch: require('./batch'),
+  episode: require('./episode'),
+  series: require('./series')
+};