diff options
-rw-r--r-- | lib/login.js | 6 | ||||
-rw-r--r-- | lib/videos.js | 93 | ||||
-rw-r--r-- | mongo-edu.js | 13 | ||||
-rw-r--r-- | package.json | 6 |
4 files changed, 96 insertions, 22 deletions
diff --git a/lib/login.js b/lib/login.js index 87066f5..d1b2d8c 100644 --- a/lib/login.js +++ b/lib/login.js @@ -100,17 +100,17 @@ module.exports = { }); }, - getList: function getList(opt, callback) { + getList: function getList(opt, argv, callback) { request({ url: opt.url, jar: jar }, function get(err, res, body) { if (err !== null) { return callback(err, null); } if (res.statusCode === 200) { - var list = [], getCourses = [], $ = cheerio.load(body), tag = opt.url.replace('course_', ''); + var list = [], getCourses = [], $ = cheerio.load(body), tag = opt.url.replace('course_', ''), options = (!argv.h)? 'Video' : 'Handout'; $('div.wiki-article p').children().filter('a').map(function map(i, item) { var current = $(item); - if (current.text().indexOf('Video') !== -1) { list.push(current.attr('href')); } + if (current.text().indexOf(options) !== -1) { list.push(current.attr('href')); } }); getCourses = _.filter(list, function map(item) { return item.match(/(wiki\/M101|wiki\/M102|wiki\/C100|wiki\/M202)/); }); diff --git a/lib/videos.js b/lib/videos.js index eec817c..2ddeb7b 100644 --- a/lib/videos.js +++ b/lib/videos.js @@ -6,36 +6,90 @@ * https://github.com/przemyslawpluta/mongo-edu/blob/master/LICENSE */ -var youtubedl = require('youtube-dl'), +var path = require('path'), + fs = require('fs'), + youtubedl = require('youtube-dl'), + filesize = require('filesize'), ProgressBar = require('progress'), + request = require('request'), + progress = require('request-progress'), colors = require('colors'), _ = require('lodash'); -var downloadPath = '', ncc = false; +var downloadPath = '', ncc = false, handout = false; var handleList = function handleList(list) { var currentList = list, opt = (!ncc) ? ['--max-quality=18'] : ['--max-quality=18', '--no-check-certificate'], + getHandouts = function getHandouts(item) { + + var name = path.basename(item), bar, dounloadFile, dlh, left, + + downloadItem = function downloadItem() { + + dlh = progress(request(item), { throttle: 0 }); + + console.log('[' + 'i'.magenta + '] Downloading: ' + name.cyan); + + dlh.on('progress', function(state) { + if (!bar) { + bar = new ProgressBar('[' + '>'.green + '] ' + filesize(state.total) + ' [:bar] :percent :etas', { complete: '=', incomplete: ' ', width: 20, total: 100.0 }); + } + if (!bar.complete) { bar.tick(parseInt(state.percent, 10)); } + }); + + dlh.on('error', function error(err) { + return console.log(err.stack); + }); + + dounloadFile = dlh.pipe(fs.createWriteStream(downloadPath + name)); + + dounloadFile.on('close', function close() { + console.log('[' + 'i'.green + '] Done.' + left); + handleList(currentList); + }); + + dounloadFile.on('error', function error(err) { + return console.log(err.stack); + }); + }; + + fs.exists(downloadPath + name, function (exists) { + left = (currentList.length)? ' ' + currentList.length + ' left ...' : ''; + + if (exists) { + console.log('[' + '>'.magenta + '] ' + name + ' has already been downloaded.' + left); + return handleList(currentList); + } + + downloadItem(); + + }); + + }, + getVideos = function getVideos(item) { + if (handout) { return getHandouts(item); } + var dl = youtubedl.download(item, downloadPath, opt), bar; - dl.on('download', function(data) { + dl.on('download', function download(data) { console.log('[' + 'i'.magenta + '] Downloading: ' + data.filename.cyan + ' > ' + item); bar = new ProgressBar('[' + '>'.green + '] ' + data.size + ' [:bar] :percent :etas', { complete: '=', incomplete: ' ', width: 20, total: 100.0 }); }); - dl.on('progress', function(data) { + dl.on('progress', function progress(data) { if (!bar.complete) { bar.tick(parseInt(data.percent, 10)); } }); - dl.on('error', function(err) { + dl.on('error', function error(err) { return console.log(err.stack); }); - dl.on('end', function(data) { + dl.on('end', function end(data) { var left = (currentList.length)? ' ' + currentList.length + ' left ...' : ''; if (data.filename) { if (data.filename.indexOf('has already been downloaded') !== -1) { @@ -62,14 +116,32 @@ module.exports = { downloadPath = argv.d; if (argv.ncc) { ncc = true; } + if (argv.h) { handout = true; } var bar = new ProgressBar('[' + '>'.magenta + '] Collecting [:bar] :percent', { complete: '=', incomplete: ' ', width: 20, total: opt.length }), options = (!ncc) ? [] : ['--no-check-certificate']; - var getDetails = function getDetails(item, i) { + var isFinished = function isFinished(count, items) { + if (count === 0) { + + var sortedList = _.map(_.sortBy(items, 'id')); + + sortedList.unshift({name: 'All', value: 'all', checked: true}, {name: 'Cancel', value: 'cancel'}); + callback(null, sortedList); + } + }, + + getDetails = function getDetails(item, i) { function getInfo() { + if (handout) { + items.push({name: path.basename(item), value: item, id: i}); + count = count - 1; + bar.tick(); + return isFinished(count, items); + } + youtubedl.getInfo(item, options, function(err, info) { items.push((!err)?{name: info.title + ' - ' + info.resolution, value: item, id: i}:{name: 'No info: ' + item, value: item, id: i}); @@ -78,13 +150,8 @@ module.exports = { bar.tick(); - if (count === 0) { - - var sortedList = _.map(_.sortBy(items, 'id')); + isFinished(count, items); - sortedList.unshift({name: 'All', value: 'all', checked: true}, {name: 'Cancel', value: 'cancel'}); - callback(null, sortedList); - } }); } diff --git a/mongo-edu.js b/mongo-edu.js index 6a5d1e1..ad9059c 100644 --- a/mongo-edu.js +++ b/mongo-edu.js @@ -14,11 +14,14 @@ var mdbvideos = require('./lib/login'), argv = require('optimist') .usage('Usage: $0 -u [user name] -d [download path] --ncc [no check certificate]') .describe('d', 'download path').describe('u', 'email address') + .describe('h', 'switch from videos (default) to handouts').boolean('h') .describe('ncc', 'no check certificate with py3.x').boolean('ncc') .demand('d').argv; exports.create = function start() { + var lookFor = ((!argv.h)? 'Videos' : 'Handouts'); + validate.init(argv, function (err, profile) { if (err !== null) { throw err; } run(profile); @@ -52,7 +55,7 @@ exports.create = function start() { function currentList() { inquirer.prompt(classes, function prompt(answers) { - mdbvideos.getList(answers, function get(err, data) { + mdbvideos.getList(answers, argv, function get(err, data) { if (err !== null) { throw err; } if (data.length) { @@ -64,7 +67,8 @@ exports.create = function start() { } - return console.log('[' + 'i'.red + '] Unable to locate any lists in the wiki. Is course available?'); + return console.log('[' + 'i'.red + '] Unable to locate any ' + lookFor.toLowerCase() + ' lists in the wiki. Is course available / ' + + lookFor.toLowerCase() + ' list present in the wiki?'); }); }); @@ -84,8 +88,9 @@ exports.create = function start() { function showDetails(err, data) { if (err !== null) { throw err; } + if (data.length) { - check[0].message = 'Select From ' + (data.length - 2) + ' Videos. Download:'; + check[0].message = 'Select From ' + (data.length - 2) + ' ' + lookFor + '. Download:'; check[0].choices = data; return inquirer.prompt(check, function prompt(answers) { @@ -94,7 +99,7 @@ exports.create = function start() { } - console.log('[' + 'i'.red + '] Could not locate any videos.'); process.exit(0); + console.log('[' + 'i'.red + '] Could not locate any ' + lookFor.toLowerCase() + '.'); process.exit(0); } }); diff --git a/package.json b/package.json index 848be6e..39f2967 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongo-edu", "preferGlobal": true, - "version": "0.1.5", + "version": "0.1.6", "author": "Przemyslaw Pluta <przemyslawplutadev@gmail.com> (http://przemyslawpluta.com)", "description": "Select and download video courses from education.mongodb.com", "main": "./mongo-edu", @@ -34,7 +34,9 @@ "inquirer": "~0.4.0", "progress": "~1.1.3", "mkdirp": "~0.3.5", - "optimist": "~0.6.1" + "optimist": "~0.6.1", + "request-progress": "^0.3.1", + "filesize": "^2.0.3" }, "engines": { "node": ">= 0.8.x" |