Added batch mode and CLI interface.

This commit is contained in:
Roel van Uden 2015-01-24 12:29:12 +01:00
parent 7d0c8f2ecd
commit 66f62d3aa1
7 changed files with 118 additions and 55 deletions

View File

@ -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

26
app.js
View File

@ -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
index.js Normal file
View File

@ -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.');
});

View File

@ -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
src/batch.js Normal file
View File

@ -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);
}

View File

@ -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
src/index.js Normal file
View File

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