├── .npmignore ├── src ├── index.js ├── const.js ├── utils │ ├── index.js │ ├── Glob.js │ ├── Hash.js │ ├── Logger.js │ ├── XML2JSON.js │ ├── FileWatcher.js │ ├── HttpRequest.js │ └── FileManager.js ├── NapijsFile.js ├── cmd.js ├── watcherCommand.js ├── NapijsOptions.js ├── napijs.js ├── napijsCommand.js └── download.js ├── dist ├── const.js ├── NapijsFile.js ├── index.js ├── utils │ ├── Glob.js │ ├── Hash.js │ ├── Logger.js │ ├── index.js │ ├── XML2JSON.js │ ├── FileWatcher.js │ ├── HttpRequest.js │ └── FileManager.js ├── cmd.js ├── watcherCommand.js ├── napijsCommand.js ├── napijs.js ├── NapijsOptions.js └── download.js ├── LICENSE ├── gulpfile.js ├── package.json ├── .gitignore └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-19. 3 | */ 4 | 'use strict'; 5 | export {default as watcher} from './utils/FileWatcher'; 6 | export {default as napijs} from './napijs'; 7 | export {default as NapijsOptions} from './NapijsOptions.js'; 8 | -------------------------------------------------------------------------------- /src/const.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 5 | 'use strict'; 6 | const CONST = { 7 | LANGUAGE: { 8 | PL : 'POL', 9 | ENG : 'ENG' 10 | }, 11 | LANGUAGE_ARRAY: ['POL','ENG'] 12 | }; 13 | export default CONST -------------------------------------------------------------------------------- /dist/const.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | Object.defineProperty(exports, "__esModule", { 8 | value: true 9 | }); 10 | var CONST = { 11 | LANGUAGE: { 12 | PL: 'POL', 13 | ENG: 'ENG' 14 | }, 15 | LANGUAGE_ARRAY: ['POL', 'ENG'] 16 | }; 17 | exports.default = CONST; -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | export {default as logger} from './Logger'; 6 | export {default as hash} from './Hash'; 7 | export {default as glob} from './Glob'; 8 | export {default as HttpRequest} from './HttpRequest'; 9 | export {default as XML2JSON} from './XML2JSON'; 10 | export {default as fileManager} from './FileManager'; 11 | export {default as fileWatcher} from './FileWatcher'; -------------------------------------------------------------------------------- /src/NapijsFile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 'use strict'; 5 | 6 | /** 7 | * Napijs file passed to napijs 8 | */ 9 | class NapijsFile { 10 | 11 | /** 12 | * Constructor 13 | * @param fileName 14 | */ 15 | constructor(fileName) { 16 | this.subtitleFileName = ''; 17 | this.subtitlesPresent = false; 18 | this.file = fileName; 19 | this.hash = ''; 20 | this.bytes = -1; 21 | this.responseString = ''; 22 | } 23 | } 24 | 25 | export default NapijsFile -------------------------------------------------------------------------------- /src/cmd.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * Created by kozervar on 2016-07-21. 4 | */ 5 | 'use strict'; 6 | import { logger } from './utils'; 7 | import * as p from './../package.json'; 8 | import yargs from 'yargs'; 9 | import _ from 'lodash'; 10 | import CONST from './const'; 11 | import watcherCommand from './watcherCommand'; 12 | import napijsCommand from './napijsCommand'; 13 | 14 | var argv = yargs.usage('$0 [args]') 15 | .command(napijsCommand) 16 | .command(watcherCommand) 17 | .version() 18 | .help('help') 19 | .alias('version', 'v') 20 | .alias('help', 'h') 21 | .epilog('For more information visit https://github.com/kozervar/napi-js') 22 | .argv; -------------------------------------------------------------------------------- /src/utils/Glob.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | import _ from 'underscore'; 6 | import glob from 'globby'; 7 | 8 | export default (files, options) => { 9 | options = options ? options : { caseSensitive : false }; 10 | return new Promise((resolve,reject)=> { 11 | if (_.isUndefined(files)) { 12 | throw new Error('File list cannot be undefined!'); 13 | } 14 | if (!_.isArray(files)) { 15 | files = [files]; 16 | } 17 | glob(files, { 18 | nocase: options.caseSensitive 19 | }) 20 | .then((files)=>resolve(files)) 21 | .catch((err)=>reject(err)) 22 | ; 23 | }); 24 | } -------------------------------------------------------------------------------- /dist/NapijsFile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 'use strict'; 5 | 6 | /** 7 | * Napijs file passed to napijs 8 | */ 9 | 10 | Object.defineProperty(exports, "__esModule", { 11 | value: true 12 | }); 13 | 14 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 15 | 16 | var NapijsFile = 17 | 18 | /** 19 | * Constructor 20 | * @param fileName 21 | */ 22 | function NapijsFile(fileName) { 23 | _classCallCheck(this, NapijsFile); 24 | 25 | this.subtitleFileName = ''; 26 | this.subtitlesPresent = false; 27 | this.file = fileName; 28 | this.hash = ''; 29 | this.bytes = -1; 30 | this.responseString = ''; 31 | }; 32 | 33 | exports.default = NapijsFile; -------------------------------------------------------------------------------- /src/utils/Hash.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | import fs from 'fs'; 6 | import { logger } from './index'; 7 | import md5pf from 'md5-part-file'; 8 | import NapijsFile from './../NapijsFile'; 9 | /** 10 | * 11 | * @param file 12 | * @returns {Promise} 13 | */ 14 | export default function(file){ 15 | return new Promise((resolve,reject)=> { 16 | var stats = fs.statSync(file); 17 | var fileSizeInBytes = stats['size']; 18 | var fileWithHash = new NapijsFile(file); 19 | md5pf(file, 0, 10485760, function (err, hash) { 20 | if (err) { 21 | reject('Something went wrong during md5 hash calculation for file ' + file); 22 | } else { 23 | fileWithHash.hash = hash; 24 | fileWithHash.bytes = fileSizeInBytes; 25 | resolve(fileWithHash); 26 | } 27 | }); 28 | }); 29 | } -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-19. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | var _FileWatcher = require('./utils/FileWatcher'); 11 | 12 | Object.defineProperty(exports, 'watcher', { 13 | enumerable: true, 14 | get: function get() { 15 | return _interopRequireDefault(_FileWatcher).default; 16 | } 17 | }); 18 | 19 | var _napijs = require('./napijs'); 20 | 21 | Object.defineProperty(exports, 'napijs', { 22 | enumerable: true, 23 | get: function get() { 24 | return _interopRequireDefault(_napijs).default; 25 | } 26 | }); 27 | 28 | var _NapijsOptions = require('./NapijsOptions.js'); 29 | 30 | Object.defineProperty(exports, 'NapijsOptions', { 31 | enumerable: true, 32 | get: function get() { 33 | return _interopRequireDefault(_NapijsOptions).default; 34 | } 35 | }); 36 | 37 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -------------------------------------------------------------------------------- /src/watcherCommand.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 'use strict'; 5 | import { fileWatcher } from './utils'; 6 | import NapijsOptions from './NapijsOptions'; 7 | import CONST from './const'; 8 | import napijsCommand from './napijsCommand'; 9 | 10 | var command = 'watch'; 11 | 12 | var describe = 'Watch directory for new files'; 13 | 14 | var builder = function(yargs){ 15 | return napijsCommand 16 | .builder(yargs) 17 | .option('p', { 18 | alias: 'path', 19 | description: 'Path for file watcher. Path will be combined with file patterns from --files parameter', 20 | default: '.' 21 | }) 22 | ; 23 | }; 24 | 25 | var handler = function (argv) { 26 | try { 27 | var options = new NapijsOptions(argv); 28 | fileWatcher(options); 29 | } catch (err) { 30 | console.error('Ups! Unexpected exception occurred... :( \n', err); 31 | } 32 | }; 33 | 34 | export default { 35 | command : command, 36 | describe : describe, 37 | builder : builder, 38 | handler : handler 39 | } -------------------------------------------------------------------------------- /src/utils/Logger.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | import * as winston from 'winston'; 6 | 7 | var logger = new (winston.Logger)({ 8 | transports: [ 9 | new (winston.transports.Console)({ 10 | handleExceptions: true, 11 | json: false, 12 | level: 'debug', 13 | timestamp: function() { 14 | return Date.now(); 15 | }, 16 | formatter: function(options) { 17 | // Return string will be passed to logger. 18 | //return options.timestamp() +' '+ options.level.toUpperCase() +' '+ (undefined !== options.message ? options.message : '') + 19 | // (options.meta && Object.keys(options.meta).length ? '\n\t'+ JSON.stringify(options.meta) : '' ); 20 | return ' ' + (undefined !== options.message ? options.message : '') + (options.meta && Object.keys(options.meta).length ? '\n\t'+ JSON.stringify(options.meta) : '' ); 21 | }, 22 | colorize: true 23 | }) 24 | ] 25 | }); 26 | 27 | export default logger -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2015 Marcin Kozaczyk. All rights reserved. 2 | Permission is hereby granted, free of charge, to any person obtaining a copy 3 | of this software and associated documentation files (the "Software"), to 4 | deal in the Software without restriction, including without limitation the 5 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 6 | sell copies of the Software, and to permit persons to whom the Software is 7 | furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in 10 | all copies or substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 18 | IN THE SOFTWARE. -------------------------------------------------------------------------------- /dist/utils/Glob.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | var _underscore = require('underscore'); 11 | 12 | var _underscore2 = _interopRequireDefault(_underscore); 13 | 14 | var _globby = require('globby'); 15 | 16 | var _globby2 = _interopRequireDefault(_globby); 17 | 18 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 19 | 20 | exports.default = function (files, options) { 21 | options = options ? options : { caseSensitive: false }; 22 | return new Promise(function (resolve, reject) { 23 | if (_underscore2.default.isUndefined(files)) { 24 | throw new Error('File list cannot be undefined!'); 25 | } 26 | if (!_underscore2.default.isArray(files)) { 27 | files = [files]; 28 | } 29 | (0, _globby2.default)(files, { 30 | nocase: options.caseSensitive 31 | }).then(function (files) { 32 | return resolve(files); 33 | }).catch(function (err) { 34 | return reject(err); 35 | }); 36 | }); 37 | }; -------------------------------------------------------------------------------- /src/NapijsOptions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 'use strict'; 5 | import _ from 'underscore'; 6 | const DEFAULT_LANG = 'POL'; 7 | const DEFAULT_SUBS_EXT = '.srt'; 8 | const DEFAULT_GLOB_EXT = ['*.mkv', '*.avi', '*.mp4', '*.mpeg', '*.wmv', '*.rmvb', '*.mov', '*.mpg']; 9 | 10 | /** 11 | * Options passed to napijs 12 | */ 13 | class NapijsOptions { 14 | 15 | /** 16 | * Constructor with yargs argument 17 | * @param argv - yargs argv 18 | */ 19 | constructor(argv) { 20 | this.lang = argv.language || DEFAULT_LANG; 21 | this.verbose = argv.verbose || false; 22 | this.file = argv.file || ''; 23 | 24 | this.files = argv.files || DEFAULT_GLOB_EXT; 25 | this.extension = DEFAULT_SUBS_EXT; 26 | this.overwrite = argv.save; 27 | 28 | this.watchPath = argv.path || DEFAULT_GLOB_EXT; 29 | 30 | this.validate(); 31 | } 32 | 33 | validate(){ 34 | let regexp = new RegExp(/^.[a-z4]*$/gmi); 35 | if(!this.extension.match(regexp)) { 36 | console.error('Subtitles extension is not correct'); 37 | this.extension = DEFAULT_SUBS_EXT; 38 | } 39 | if(_.isString(this.files)) { 40 | this.files = [this.files]; 41 | } 42 | } 43 | } 44 | 45 | export default NapijsOptions -------------------------------------------------------------------------------- /dist/utils/Hash.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | exports.default = function (file) { 11 | return new Promise(function (resolve, reject) { 12 | var stats = _fs2.default.statSync(file); 13 | var fileSizeInBytes = stats['size']; 14 | var fileWithHash = new _NapijsFile2.default(file); 15 | (0, _md5PartFile2.default)(file, 0, 10485760, function (err, hash) { 16 | if (err) { 17 | reject('Something went wrong during md5 hash calculation for file ' + file); 18 | } else { 19 | fileWithHash.hash = hash; 20 | fileWithHash.bytes = fileSizeInBytes; 21 | resolve(fileWithHash); 22 | } 23 | }); 24 | }); 25 | }; 26 | 27 | var _fs = require('fs'); 28 | 29 | var _fs2 = _interopRequireDefault(_fs); 30 | 31 | var _index = require('./index'); 32 | 33 | var _md5PartFile = require('md5-part-file'); 34 | 35 | var _md5PartFile2 = _interopRequireDefault(_md5PartFile); 36 | 37 | var _NapijsFile = require('./../NapijsFile'); 38 | 39 | var _NapijsFile2 = _interopRequireDefault(_NapijsFile); 40 | 41 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -------------------------------------------------------------------------------- /src/napijs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 5 | 'use strict'; 6 | import { logger } from './utils'; 7 | import _ from 'underscore'; 8 | import download from './download'; 9 | 10 | /** 11 | * Handle method for subtitles downloader 12 | * @param {NapijsOptions} options 13 | * @param {Function} resolve 14 | * @param {Function} reject 15 | */ 16 | function napijs(options, resolve, reject) { 17 | if (_.isUndefined(options)) { 18 | return reject('Could not find options! Exiting...'); 19 | } 20 | if(options.verbose) { 21 | logger.info('Starting with following options: ', options); 22 | } 23 | download(options) 24 | .then((response)=> { 25 | for(var r of response) { 26 | if(!r.subtitlesPresent) { 27 | logger.info('Could not download subtitles for file %s', r.file); 28 | } 29 | } 30 | if (options.verbose) { 31 | logger.info('Done'); 32 | } 33 | resolve(response); 34 | }) 35 | .catch((err)=> { 36 | reject(err); 37 | }); 38 | } 39 | 40 | /** 41 | * Main napijs method 42 | * @param {NapijsOptions} options 43 | * @returns {Promise} 44 | */ 45 | export default function (options) { 46 | return new Promise((resolve, reject)=>napijs(options, resolve, reject)); 47 | } -------------------------------------------------------------------------------- /dist/cmd.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Created by kozervar on 2016-07-21. 5 | */ 6 | 'use strict'; 7 | 8 | var _utils = require('./utils'); 9 | 10 | var _package = require('./../package.json'); 11 | 12 | var p = _interopRequireWildcard(_package); 13 | 14 | var _yargs = require('yargs'); 15 | 16 | var _yargs2 = _interopRequireDefault(_yargs); 17 | 18 | var _lodash = require('lodash'); 19 | 20 | var _lodash2 = _interopRequireDefault(_lodash); 21 | 22 | var _const = require('./const'); 23 | 24 | var _const2 = _interopRequireDefault(_const); 25 | 26 | var _watcherCommand = require('./watcherCommand'); 27 | 28 | var _watcherCommand2 = _interopRequireDefault(_watcherCommand); 29 | 30 | var _napijsCommand = require('./napijsCommand'); 31 | 32 | var _napijsCommand2 = _interopRequireDefault(_napijsCommand); 33 | 34 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 35 | 36 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 37 | 38 | var argv = _yargs2.default.usage('$0 [args]').command(_napijsCommand2.default).command(_watcherCommand2.default).version().help('help').alias('version', 'v').alias('help', 'h').epilog('For more information visit https://github.com/kozervar/napi-js').argv; -------------------------------------------------------------------------------- /dist/utils/Logger.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | var _winston = require('winston'); 11 | 12 | var winston = _interopRequireWildcard(_winston); 13 | 14 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 15 | 16 | var logger = new winston.Logger({ 17 | transports: [new winston.transports.Console({ 18 | handleExceptions: true, 19 | json: false, 20 | level: 'debug', 21 | timestamp: function timestamp() { 22 | return Date.now(); 23 | }, 24 | formatter: function formatter(options) { 25 | // Return string will be passed to logger. 26 | //return options.timestamp() +' '+ options.level.toUpperCase() +' '+ (undefined !== options.message ? options.message : '') + 27 | // (options.meta && Object.keys(options.meta).length ? '\n\t'+ JSON.stringify(options.meta) : '' ); 28 | return ' ' + (undefined !== options.message ? options.message : '') + (options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta) : ''); 29 | }, 30 | colorize: true 31 | })] 32 | }); 33 | 34 | exports.default = logger; -------------------------------------------------------------------------------- /dist/watcherCommand.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | var _utils = require('./utils'); 11 | 12 | var _NapijsOptions = require('./NapijsOptions'); 13 | 14 | var _NapijsOptions2 = _interopRequireDefault(_NapijsOptions); 15 | 16 | var _const = require('./const'); 17 | 18 | var _const2 = _interopRequireDefault(_const); 19 | 20 | var _napijsCommand = require('./napijsCommand'); 21 | 22 | var _napijsCommand2 = _interopRequireDefault(_napijsCommand); 23 | 24 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 25 | 26 | var command = 'watch'; 27 | 28 | var describe = 'Watch directory for new files'; 29 | 30 | var builder = function builder(yargs) { 31 | return _napijsCommand2.default.builder(yargs).option('p', { 32 | alias: 'path', 33 | description: 'Path for file watcher. Path will be combined with file patterns from --files parameter', 34 | default: '.' 35 | }); 36 | }; 37 | 38 | var handler = function handler(argv) { 39 | try { 40 | var options = new _NapijsOptions2.default(argv); 41 | (0, _utils.fileWatcher)(options); 42 | } catch (err) { 43 | console.error('Ups! Unexpected exception occurred... :( \n', err); 44 | } 45 | }; 46 | 47 | exports.default = { 48 | command: command, 49 | describe: describe, 50 | builder: builder, 51 | handler: handler 52 | }; -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | var gulp = require('gulp'); 6 | var babel = require('gulp-babel'); 7 | var rename = require('gulp-rename'); 8 | var clean = require('gulp-clean'); 9 | var nodemon = require('gulp-nodemon'); 10 | var Cache = require('gulp-file-cache'); 11 | var sourcemaps = require('gulp-sourcemaps'); 12 | 13 | var cache = new Cache(); 14 | 15 | var paths = { 16 | babel: [ 17 | './src/**/*.js' 18 | ], 19 | cache: './.gulp-cache', 20 | dist: './dist/', 21 | target: './dist/*' 22 | }; 23 | 24 | gulp.task('clean', function () { 25 | var stream = gulp 26 | .src([paths.target, paths.cache], {read: false}) 27 | .pipe(clean()); 28 | return stream; 29 | } 30 | ); 31 | 32 | gulp.task('compile', function () { 33 | var stream = gulp.src(paths.babel) 34 | //.pipe(cache.filter()) 35 | //.pipe(sourcemaps.init()) 36 | .pipe(babel({ 37 | presets: ['es2015'] 38 | })) 39 | //.pipe(sourcemaps.write()) 40 | //.pipe(cache.cache()) 41 | .pipe(gulp.dest(paths.dist)); 42 | return stream; 43 | }); 44 | 45 | gulp.task('watch', ['clean', 'compile'], function () { 46 | gulp.watch(paths.babel, ['compile']); 47 | }); 48 | //gulp.task('watch', ['compile'], function () { 49 | // nodemon({ 50 | // script: './dist/index.js', 51 | // ext: 'js', 52 | // env: { 'NODE_ENV': 'development' }, 53 | // tasks: ['compile'] 54 | // }); 55 | //}); -------------------------------------------------------------------------------- /src/utils/XML2JSON.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | import { logger, fileManager } from './index'; 6 | import xml2js from 'xml2js'; 7 | import path from 'path'; 8 | import fs from 'fs'; 9 | 10 | function parseAndSaveFile(options, fileWithHash, resolve, reject) { 11 | if (options.verbose) { 12 | logger.info('Processing file: %s', fileWithHash.file); 13 | } 14 | xml2js.parseString(fileWithHash.responseString, (err, result)=> { 15 | fileWithHash.subtitlesPresent = false; 16 | if (err) { 17 | return reject({err: err, fileWithHash: fileWithHash}); 18 | } 19 | if (!result || !result.result) { 20 | return reject({err: 'No Napiprojekt response for file ' + fileWithHash.file, fileWithHash: fileWithHash}); 21 | } 22 | if (!result.result.subtitles) { 23 | return reject({err: 'No subtitles found in response for file ' + fileWithHash.file, fileWithHash: fileWithHash}); 24 | } 25 | if (result.result.subtitles.length === 1) { 26 | fileManager.saveSubtitles(options, fileWithHash, result.result.subtitles[0]) 27 | .then(response => resolve(response)) 28 | .catch(err => reject({err: err, fileWithHash: fileWithHash})); 29 | } else { 30 | return reject({err: 'Wrong number of subtitles. Should be 1', fileWithHash: fileWithHash}); 31 | } 32 | }); 33 | } 34 | 35 | export default (options, fileWithHash) => { 36 | return new Promise((resolve, reject)=>parseAndSaveFile(options, fileWithHash, resolve, reject)); 37 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "napi-js", 3 | "version": "3.0.5", 4 | "private": false, 5 | "description": "A library for downloading movie subtitles using the NapiProjekt API.", 6 | "homepage": "https://github.com/kozervar/napi-js", 7 | "author": "Marcin Kozaczyk (http://github.com/kozervar)", 8 | "license": "MIT", 9 | "keywords": [ 10 | "napiprojekt", 11 | "napiproject", 12 | "js", 13 | "javascript", 14 | "napi", 15 | "project", 16 | "promise", 17 | "node" 18 | ], 19 | "contributors": [ 20 | "Michał Budzyński (http://github.com/michalbe)" 21 | ], 22 | "bugs": { 23 | "mail": "kozervar@gmail.com", 24 | "url": "http://github.com/kozervar/napi-js/issues" 25 | }, 26 | "bin": { 27 | "napijs": "dist/cmd.js" 28 | }, 29 | "main": "dist/index.js", 30 | "files": [ 31 | "LICENSE", 32 | "dist/*" 33 | ], 34 | "repository": { 35 | "type": "git", 36 | "url": "git://github.com/kozervar/napi-js.git" 37 | }, 38 | "engines": { 39 | "node": ">=0.6.0" 40 | }, 41 | "dependencies": { 42 | "chokidar": "^1.6.0", 43 | "globby": "5.0.0", 44 | "lodash": "4.13.1", 45 | "md5-part-file": "1.1.0", 46 | "winston": "^2.2.0", 47 | "xml2js": "*", 48 | "yargs": "^4.8.1", 49 | "underscore": "^1.8.3" 50 | }, 51 | "devDependencies": { 52 | "babel-preset-es2015": "^6.9.0", 53 | "gulp": "^3.9.1", 54 | "gulp-babel": "^6.1.2", 55 | "gulp-clean": "^0.3.2", 56 | "gulp-file-cache": "0.0.1", 57 | "gulp-nodemon": "^2.1.0", 58 | "gulp-rename": "^1.2.2", 59 | "gulp-sourcemaps": "^1.6.0" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /dist/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | var _Logger = require('./Logger'); 11 | 12 | Object.defineProperty(exports, 'logger', { 13 | enumerable: true, 14 | get: function get() { 15 | return _interopRequireDefault(_Logger).default; 16 | } 17 | }); 18 | 19 | var _Hash = require('./Hash'); 20 | 21 | Object.defineProperty(exports, 'hash', { 22 | enumerable: true, 23 | get: function get() { 24 | return _interopRequireDefault(_Hash).default; 25 | } 26 | }); 27 | 28 | var _Glob = require('./Glob'); 29 | 30 | Object.defineProperty(exports, 'glob', { 31 | enumerable: true, 32 | get: function get() { 33 | return _interopRequireDefault(_Glob).default; 34 | } 35 | }); 36 | 37 | var _HttpRequest = require('./HttpRequest'); 38 | 39 | Object.defineProperty(exports, 'HttpRequest', { 40 | enumerable: true, 41 | get: function get() { 42 | return _interopRequireDefault(_HttpRequest).default; 43 | } 44 | }); 45 | 46 | var _XML2JSON = require('./XML2JSON'); 47 | 48 | Object.defineProperty(exports, 'XML2JSON', { 49 | enumerable: true, 50 | get: function get() { 51 | return _interopRequireDefault(_XML2JSON).default; 52 | } 53 | }); 54 | 55 | var _FileManager = require('./FileManager'); 56 | 57 | Object.defineProperty(exports, 'fileManager', { 58 | enumerable: true, 59 | get: function get() { 60 | return _interopRequireDefault(_FileManager).default; 61 | } 62 | }); 63 | 64 | var _FileWatcher = require('./FileWatcher'); 65 | 66 | Object.defineProperty(exports, 'fileWatcher', { 67 | enumerable: true, 68 | get: function get() { 69 | return _interopRequireDefault(_FileWatcher).default; 70 | } 71 | }); 72 | 73 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # disable example video and downloaded subtitles 2 | *.mp4 3 | *.mkv 4 | *.txt 5 | *.srt 6 | 7 | # Created by https://www.gitignore.io 8 | 9 | ### Intellij ### 10 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 11 | 12 | *.iml 13 | 14 | ## Directory-based project format: 15 | .idea/ 16 | # if you remove the above rule, at least ignore the following: 17 | 18 | # User-specific stuff: 19 | # .idea/workspace.xml 20 | # .idea/tasks.xml 21 | # .idea/dictionaries 22 | 23 | # Sensitive or high-churn files: 24 | # .idea/dataSources.ids 25 | # .idea/dataSources.xml 26 | # .idea/sqlDataSources.xml 27 | # .idea/dynamic.xml 28 | # .idea/uiDesigner.xml 29 | 30 | # Gradle: 31 | # .idea/gradle.xml 32 | # .idea/libraries 33 | 34 | # Mongo Explorer plugin: 35 | # .idea/mongoSettings.xml 36 | 37 | ## File-based project format: 38 | *.ipr 39 | *.iws 40 | 41 | ## Plugin-specific files: 42 | 43 | # IntelliJ 44 | /out/ 45 | 46 | # mpeltonen/sbt-idea plugin 47 | .idea_modules/ 48 | 49 | # JIRA plugin 50 | atlassian-ide-plugin.xml 51 | 52 | # Crashlytics plugin (for Android Studio and IntelliJ) 53 | com_crashlytics_export_strings.xml 54 | crashlytics.properties 55 | crashlytics-build.properties 56 | 57 | 58 | ### Node ### 59 | # Logs 60 | logs 61 | *.log 62 | 63 | # Runtime data 64 | pids 65 | *.pid 66 | *.seed 67 | 68 | # Directory for instrumented libs generated by jscoverage/JSCover 69 | lib-cov 70 | 71 | # Coverage directory used by tools like istanbul 72 | coverage 73 | 74 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 75 | .grunt 76 | 77 | # node-waf configuration 78 | .lock-wscript 79 | 80 | # Compiled binary addons (http://nodejs.org/api/addons.html) 81 | build/Release 82 | 83 | # Dependency directory 84 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 85 | node_modules 86 | 87 | 88 | .jsbeautifyrc 89 | *.tar.gz 90 | *.tgz 91 | -------------------------------------------------------------------------------- /src/utils/FileWatcher.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 'use strict'; 5 | import napijs from './../napijs'; 6 | import { logger } from './'; 7 | import chokidar from 'chokidar'; 8 | import fs from 'fs'; 9 | import path from 'path'; 10 | import _ from 'underscore'; 11 | 12 | export default function (options) { 13 | var paths = []; 14 | for (var p of options.files) { 15 | paths.push(options.watchPath + '/' + p); 16 | } 17 | if (options.verbose) 18 | logger.info('Paths: %s', paths); 19 | logger.info('Watching...'); 20 | 21 | var watcher = chokidar.watch(paths, { 22 | persistent: true, 23 | ignoreInitial: true, 24 | awaitWriteFinish: true 25 | }); 26 | 27 | watcher 28 | .on('add', fp => { 29 | var opts = _.clone(options); 30 | opts.file = fp; 31 | if (opts.verbose) 32 | logger.info('File %s has been ADDED', fp); 33 | napijs(opts) 34 | .then(()=> { 35 | }) 36 | .catch((err)=> { 37 | logger.error('Could not download subtitles for file ' + fp, err); 38 | }); 39 | }) 40 | .on('change', fp => { 41 | var opts = _.clone(options); 42 | opts.file = fp; 43 | if (opts.verbose) 44 | logger.info('File %s has been CHANGED', fp); 45 | napijs(opts) 46 | .then(()=> { 47 | }) 48 | .catch((err)=> { 49 | logger.error('Could not download subtitles for file ' + fp, err); 50 | }); 51 | }) 52 | //.on('unlink', fp => logger.info('File ${fp} has been REMOVED')) 53 | .on('ready', () => { 54 | if (options.verbose) 55 | logger.info('Initial scan complete. Ready for changes'); 56 | }); 57 | 58 | return watcher; 59 | } -------------------------------------------------------------------------------- /src/napijsCommand.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 'use strict'; 5 | import { logger } from './utils'; 6 | import _ from 'underscore'; 7 | import napijs from './napijs'; 8 | import NapijsOptions from './NapijsOptions'; 9 | import CONST from './const'; 10 | 11 | var command = 'download'; 12 | 13 | var describe = 'Download subtitles'; 14 | 15 | var builder = function(yargs){ 16 | return yargs 17 | .option('l', { 18 | alias: 'language', 19 | description: 'Set subtitles language. Available languages: POL, ENG', 20 | default: CONST.LANGUAGE.PL, 21 | choices: CONST.LANGUAGE_ARRAY 22 | }) 23 | .option('verbose', { 24 | description: 'Show output', 25 | default: false 26 | }) 27 | .option('f', { 28 | array: true, 29 | description: 'An array of files separated by space char. Glob expression allowed.\nFor more information visit: https://github.com/isaacs/node-glob', 30 | alias: 'files', 31 | default: ['*.mkv', '*.avi', '*.mp4', '*.mpeg', '*.wmv', '*.rmvb', '*.mov', '*.mpg'] 32 | }) 33 | .option('file', { 34 | array: false, 35 | description: 'Path to single file. If provided then --files argument is ignored' 36 | }) 37 | .option('s', { 38 | boolean: true, 39 | description: 'Overwrite subtitles file if one exist', 40 | alias: 'save' 41 | }) 42 | ; 43 | }; 44 | 45 | var handler = function (argv) { 46 | try { 47 | var options = new NapijsOptions(argv); 48 | napijs(options) 49 | .then(()=>{ 50 | }) 51 | .catch((err)=>{ 52 | console.error('Error occurred: ', err); 53 | }); 54 | } catch(err){ 55 | console.error('Ups! Unexpected exception occurred... :( \n', err); 56 | } 57 | }; 58 | 59 | export default { 60 | command : command, 61 | describe : describe, 62 | builder : builder, 63 | handler : handler 64 | } -------------------------------------------------------------------------------- /dist/utils/XML2JSON.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | var _index = require('./index'); 11 | 12 | var _xml2js = require('xml2js'); 13 | 14 | var _xml2js2 = _interopRequireDefault(_xml2js); 15 | 16 | var _path = require('path'); 17 | 18 | var _path2 = _interopRequireDefault(_path); 19 | 20 | var _fs = require('fs'); 21 | 22 | var _fs2 = _interopRequireDefault(_fs); 23 | 24 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 25 | 26 | function parseAndSaveFile(options, fileWithHash, resolve, reject) { 27 | if (options.verbose) { 28 | _index.logger.info('Processing file: %s', fileWithHash.file); 29 | } 30 | _xml2js2.default.parseString(fileWithHash.responseString, function (err, result) { 31 | fileWithHash.subtitlesPresent = false; 32 | if (err) { 33 | return reject({ err: err, fileWithHash: fileWithHash }); 34 | } 35 | if (!result || !result.result) { 36 | return reject({ err: 'No Napiprojekt response for file ' + fileWithHash.file, fileWithHash: fileWithHash }); 37 | } 38 | if (!result.result.subtitles) { 39 | return reject({ err: 'No subtitles found in response for file ' + fileWithHash.file, fileWithHash: fileWithHash }); 40 | } 41 | if (result.result.subtitles.length === 1) { 42 | _index.fileManager.saveSubtitles(options, fileWithHash, result.result.subtitles[0]).then(function (response) { 43 | return resolve(response); 44 | }).catch(function (err) { 45 | return reject({ err: err, fileWithHash: fileWithHash }); 46 | }); 47 | } else { 48 | return reject({ err: 'Wrong number of subtitles. Should be 1', fileWithHash: fileWithHash }); 49 | } 50 | }); 51 | } 52 | 53 | exports.default = function (options, fileWithHash) { 54 | return new Promise(function (resolve, reject) { 55 | return parseAndSaveFile(options, fileWithHash, resolve, reject); 56 | }); 57 | }; -------------------------------------------------------------------------------- /src/utils/HttpRequest.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | import querystring from 'querystring'; 6 | import http from 'http'; 7 | 8 | class HttpRequest { 9 | constructor(options, fileWithHash){ 10 | this.fileWithHash = fileWithHash; 11 | this.postData = querystring.stringify({ 12 | //'mode': '32', 13 | //'client': 'AutoMove', 14 | //'client_ver': '1.0', 15 | //'downloaded_subtitles_id': this.fileWithHash.hash, 16 | //'downloaded_subtitles_lang': 'PL', 17 | //'downloaded_subtitles_txt': '2', 18 | //'advert_type': 'flashAllowed', 19 | //'video_info_hash': this.fileWithHash.hash, 20 | //'nazwa_pliku': this.fileWithHash.file, 21 | //'rozmiar_pliku_bajty': this.fileWithHash.bytes, 22 | //'the': 'end' 23 | 'downloaded_subtitles_lang': options.lang, 24 | 'downloaded_subtitles_txt': '1', 25 | 'client_ver': '2.2.0.2399', 26 | 'downloaded_subtitles_id': this.fileWithHash.hash, 27 | 'client': 'Napiprojekt', 28 | 'mode': '1' 29 | }); 30 | this.postOptions = { 31 | host: 'www.napiprojekt.pl', 32 | port: '80', 33 | path: '/api/api-napiprojekt3.php', 34 | method: 'POST', 35 | headers: { 36 | 'Content-Type': 'application/x-www-form-urlencoded', 37 | 'Content-Length': this.postData.length 38 | } 39 | }; 40 | } 41 | 42 | request(){ 43 | return new Promise((resolve,reject)=>{ 44 | var req = http.request(this.postOptions, (response)=>{ 45 | this.processResponse(resolve, response); 46 | }); 47 | req.on('error', function (e) { 48 | reject(e); 49 | }); 50 | req.write(this.postData); 51 | req.end(); 52 | }); 53 | } 54 | 55 | processResponse(resolve, res){ 56 | res.setEncoding('utf-8'); 57 | var responseString = ''; 58 | res.on('data', (data) => { 59 | responseString += data; 60 | }); 61 | res.on('end', () => { 62 | this.fileWithHash.responseString = responseString; 63 | resolve(this.fileWithHash); 64 | }); 65 | } 66 | 67 | } 68 | 69 | export default HttpRequest -------------------------------------------------------------------------------- /dist/napijsCommand.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | var _utils = require('./utils'); 11 | 12 | var _underscore = require('underscore'); 13 | 14 | var _underscore2 = _interopRequireDefault(_underscore); 15 | 16 | var _napijs = require('./napijs'); 17 | 18 | var _napijs2 = _interopRequireDefault(_napijs); 19 | 20 | var _NapijsOptions = require('./NapijsOptions'); 21 | 22 | var _NapijsOptions2 = _interopRequireDefault(_NapijsOptions); 23 | 24 | var _const = require('./const'); 25 | 26 | var _const2 = _interopRequireDefault(_const); 27 | 28 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 29 | 30 | var command = 'download'; 31 | 32 | var describe = 'Download subtitles'; 33 | 34 | var builder = function builder(yargs) { 35 | return yargs.option('l', { 36 | alias: 'language', 37 | description: 'Set subtitles language. Available languages: POL, ENG', 38 | default: _const2.default.LANGUAGE.PL, 39 | choices: _const2.default.LANGUAGE_ARRAY 40 | }).option('verbose', { 41 | description: 'Show output', 42 | default: false 43 | }).option('f', { 44 | array: true, 45 | description: 'An array of files separated by space char. Glob expression allowed.\nFor more information visit: https://github.com/isaacs/node-glob', 46 | alias: 'files', 47 | default: ['*.mkv', '*.avi', '*.mp4', '*.mpeg', '*.wmv', '*.rmvb', '*.mov', '*.mpg'] 48 | }).option('file', { 49 | array: false, 50 | description: 'Path to single file. If provided then --files argument is ignored' 51 | }).option('s', { 52 | boolean: true, 53 | description: 'Overwrite subtitles file if one exist', 54 | alias: 'save' 55 | }); 56 | }; 57 | 58 | var handler = function handler(argv) { 59 | try { 60 | var options = new _NapijsOptions2.default(argv); 61 | (0, _napijs2.default)(options).then(function () {}).catch(function (err) { 62 | console.error('Error occurred: ', err); 63 | }); 64 | } catch (err) { 65 | console.error('Ups! Unexpected exception occurred... :( \n', err); 66 | } 67 | }; 68 | 69 | exports.default = { 70 | command: command, 71 | describe: describe, 72 | builder: builder, 73 | handler: handler 74 | }; -------------------------------------------------------------------------------- /dist/napijs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | Object.defineProperty(exports, "__esModule", { 8 | value: true 9 | }); 10 | 11 | exports.default = function (options) { 12 | return new Promise(function (resolve, reject) { 13 | return napijs(options, resolve, reject); 14 | }); 15 | }; 16 | 17 | var _utils = require('./utils'); 18 | 19 | var _underscore = require('underscore'); 20 | 21 | var _underscore2 = _interopRequireDefault(_underscore); 22 | 23 | var _download = require('./download'); 24 | 25 | var _download2 = _interopRequireDefault(_download); 26 | 27 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 28 | 29 | /** 30 | * Handle method for subtitles downloader 31 | * @param {NapijsOptions} options 32 | * @param {Function} resolve 33 | * @param {Function} reject 34 | */ 35 | function napijs(options, resolve, reject) { 36 | if (_underscore2.default.isUndefined(options)) { 37 | return reject('Could not find options! Exiting...'); 38 | } 39 | if (options.verbose) { 40 | _utils.logger.info('Starting with following options: ', options); 41 | } 42 | (0, _download2.default)(options).then(function (response) { 43 | var _iteratorNormalCompletion = true; 44 | var _didIteratorError = false; 45 | var _iteratorError = undefined; 46 | 47 | try { 48 | for (var _iterator = response[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 49 | var r = _step.value; 50 | 51 | if (!r.subtitlesPresent) { 52 | _utils.logger.info('Could not download subtitles for file %s', r.file); 53 | } 54 | } 55 | } catch (err) { 56 | _didIteratorError = true; 57 | _iteratorError = err; 58 | } finally { 59 | try { 60 | if (!_iteratorNormalCompletion && _iterator.return) { 61 | _iterator.return(); 62 | } 63 | } finally { 64 | if (_didIteratorError) { 65 | throw _iteratorError; 66 | } 67 | } 68 | } 69 | 70 | if (options.verbose) { 71 | _utils.logger.info('Done'); 72 | } 73 | resolve(response); 74 | }).catch(function (err) { 75 | reject(err); 76 | }); 77 | } 78 | 79 | /** 80 | * Main napijs method 81 | * @param {NapijsOptions} options 82 | * @returns {Promise} 83 | */ -------------------------------------------------------------------------------- /dist/NapijsOptions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 11 | 12 | var _underscore = require('underscore'); 13 | 14 | var _underscore2 = _interopRequireDefault(_underscore); 15 | 16 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17 | 18 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 19 | 20 | var DEFAULT_LANG = 'POL'; 21 | var DEFAULT_SUBS_EXT = '.srt'; 22 | var DEFAULT_GLOB_EXT = ['*.mkv', '*.avi', '*.mp4', '*.mpeg', '*.wmv', '*.rmvb', '*.mov', '*.mpg']; 23 | 24 | /** 25 | * Options passed to napijs 26 | */ 27 | 28 | var NapijsOptions = function () { 29 | 30 | /** 31 | * Constructor with yargs argument 32 | * @param argv - yargs argv 33 | */ 34 | function NapijsOptions(argv) { 35 | _classCallCheck(this, NapijsOptions); 36 | 37 | this.lang = argv.language || DEFAULT_LANG; 38 | this.verbose = argv.verbose || false; 39 | this.file = argv.file || ''; 40 | 41 | this.files = argv.files || DEFAULT_GLOB_EXT; 42 | this.extension = DEFAULT_SUBS_EXT; 43 | this.overwrite = argv.save; 44 | 45 | this.watchPath = argv.path || DEFAULT_GLOB_EXT; 46 | 47 | this.validate(); 48 | } 49 | 50 | _createClass(NapijsOptions, [{ 51 | key: 'validate', 52 | value: function validate() { 53 | var regexp = new RegExp(/^.[a-z4]*$/gmi); 54 | if (!this.extension.match(regexp)) { 55 | console.error('Subtitles extension is not correct'); 56 | this.extension = DEFAULT_SUBS_EXT; 57 | } 58 | if (_underscore2.default.isString(this.files)) { 59 | this.files = [this.files]; 60 | } 61 | } 62 | }]); 63 | 64 | return NapijsOptions; 65 | }(); 66 | 67 | exports.default = NapijsOptions; -------------------------------------------------------------------------------- /dist/utils/FileWatcher.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | exports.default = function (options) { 11 | var paths = []; 12 | var _iteratorNormalCompletion = true; 13 | var _didIteratorError = false; 14 | var _iteratorError = undefined; 15 | 16 | try { 17 | for (var _iterator = options.files[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 18 | var p = _step.value; 19 | 20 | paths.push(options.watchPath + '/' + p); 21 | } 22 | } catch (err) { 23 | _didIteratorError = true; 24 | _iteratorError = err; 25 | } finally { 26 | try { 27 | if (!_iteratorNormalCompletion && _iterator.return) { 28 | _iterator.return(); 29 | } 30 | } finally { 31 | if (_didIteratorError) { 32 | throw _iteratorError; 33 | } 34 | } 35 | } 36 | 37 | if (options.verbose) _2.logger.info('Paths: %s', paths); 38 | _2.logger.info('Watching...'); 39 | 40 | var watcher = _chokidar2.default.watch(paths, { 41 | persistent: true, 42 | ignoreInitial: true, 43 | awaitWriteFinish: true 44 | }); 45 | 46 | watcher.on('add', function (fp) { 47 | var opts = _underscore2.default.clone(options); 48 | opts.file = fp; 49 | if (opts.verbose) _2.logger.info('File %s has been ADDED', fp); 50 | (0, _napijs2.default)(opts).then(function () {}).catch(function (err) { 51 | _2.logger.error('Could not download subtitles for file ' + fp, err); 52 | }); 53 | }).on('change', function (fp) { 54 | var opts = _underscore2.default.clone(options); 55 | opts.file = fp; 56 | if (opts.verbose) _2.logger.info('File %s has been CHANGED', fp); 57 | (0, _napijs2.default)(opts).then(function () {}).catch(function (err) { 58 | _2.logger.error('Could not download subtitles for file ' + fp, err); 59 | }); 60 | }) 61 | //.on('unlink', fp => logger.info('File ${fp} has been REMOVED')) 62 | .on('ready', function () { 63 | if (options.verbose) _2.logger.info('Initial scan complete. Ready for changes'); 64 | }); 65 | 66 | return watcher; 67 | }; 68 | 69 | var _napijs = require('./../napijs'); 70 | 71 | var _napijs2 = _interopRequireDefault(_napijs); 72 | 73 | var _2 = require('./'); 74 | 75 | var _chokidar = require('chokidar'); 76 | 77 | var _chokidar2 = _interopRequireDefault(_chokidar); 78 | 79 | var _fs = require('fs'); 80 | 81 | var _fs2 = _interopRequireDefault(_fs); 82 | 83 | var _path = require('path'); 84 | 85 | var _path2 = _interopRequireDefault(_path); 86 | 87 | var _underscore = require('underscore'); 88 | 89 | var _underscore2 = _interopRequireDefault(_underscore); 90 | 91 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -------------------------------------------------------------------------------- /src/utils/FileManager.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 'use strict'; 5 | import { logger } from './index'; 6 | import path from 'path'; 7 | import fs from 'fs'; 8 | import crypto from 'crypto'; 9 | import _ from 'underscore'; 10 | 11 | var fileExists = function (filename) { 12 | try { 13 | fs.statSync(filename); 14 | return true; 15 | } 16 | catch(e) { 17 | return false; 18 | } 19 | }; 20 | 21 | function checkIfFileExists(options, fileWithHash, resolve, reject) { 22 | const subsFileName = path.join( 23 | path.dirname(fileWithHash.file), 24 | path.basename(fileWithHash.file, path.extname(fileWithHash.file)) + options.extension 25 | ); 26 | if(fileExists(subsFileName)) { 27 | if(!options.overwrite) { 28 | if (options.verbose) { 29 | logger.info('File [ %s ] exist. Nothing to do!', subsFileName); 30 | } 31 | fileWithHash.subtitlesPresent = true; 32 | fileWithHash.subtitleFileName = subsFileName; 33 | return resolve(fileWithHash); 34 | } 35 | 36 | var current_date = (new Date()).valueOf().toString(); 37 | var random = Math.random().toString(); 38 | var digest = crypto.createHash('sha1').update(current_date + random).digest('hex'); 39 | const modifiedSubsFileName = path.join( 40 | path.dirname(fileWithHash.file), 41 | path.basename(fileWithHash.file, path.extname(fileWithHash.file)) + '-' + digest.substr(0, 4) + options.extension 42 | ); 43 | 44 | if (options.verbose) { 45 | logger.info('Renaming file [ %s ] to [ %s }', subsFileName, modifiedSubsFileName); 46 | } 47 | fs.renameSync(subsFileName, modifiedSubsFileName); 48 | } 49 | return resolve(fileWithHash); 50 | } 51 | 52 | function fileManager(options, fileWithHash, subtitles, resolve, reject) { 53 | if(fileWithHash.subtitlesPresent) { 54 | resolve(fileWithHash); 55 | } 56 | const subsFileName = path.join( 57 | path.dirname(fileWithHash.file), 58 | path.basename(fileWithHash.file, path.extname(fileWithHash.file)) + options.extension 59 | ); 60 | 61 | if (options.verbose) { 62 | logger.info('Saving file [ %s ]', subsFileName); 63 | } 64 | 65 | fileWithHash.subtitlesPresent = true; 66 | 67 | var file = fs.createWriteStream(subsFileName); 68 | 69 | file.on('error', (err) => { 70 | reject({err: err, fileWithHash: fileWithHash}); 71 | }); 72 | file.on('finish', () => { 73 | if (options.verbose) { 74 | logger.info('Subtitles file [ %s ] saved successfully', subsFileName); 75 | } 76 | fileWithHash.subtitleFileName = subsFileName; 77 | resolve(fileWithHash); 78 | }); 79 | var b = new Buffer(subtitles.content[0], 'base64'); 80 | file.write(b.toString('UTF-8')); 81 | file.end(); 82 | } 83 | 84 | var saveSubtitles = function (options, fileWithHash, subtitles){ 85 | return new Promise((resolve,reject)=>fileManager(options,fileWithHash,subtitles,resolve,reject)); 86 | }; 87 | var subtitleExists = function (options, fileWithHash){ 88 | return new Promise((resolve,reject)=>checkIfFileExists(options,fileWithHash,resolve,reject)); 89 | }; 90 | 91 | export default { 92 | saveSubtitles : saveSubtitles, 93 | subtitleExists : subtitleExists 94 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Napi-js 2 | ===== 3 | 4 | A Node.js library for downloading movie subtitles using the [NapiProjekt](http://www.napiprojekt.pl/) API. 5 | 6 | ## Usage 7 | ```bash 8 | npm install napi-js 9 | ``` 10 | 11 | Next just do something like this: 12 | 13 | ```javascript 14 | var napijs = require('napi-js'); 15 | 16 | var options = new NapijsOptions({ ... }); 17 | napijs.napijs(options) 18 | .then(()=>{ 19 | console.log('Done!'); 20 | }) 21 | .catch((err)=>{ 22 | console.error('Error occurred: ', err); 23 | }); 24 | 25 | ``` 26 | 27 | Subtitles are saved under the same directory and name as the movie file. 28 | 29 | Options 30 | ====== 31 | 32 | ### Commands 33 | 34 | There are two available commands: 35 | 36 | * `download`: download subtitles from Napirpojekt server 37 | * `watch`: watch directory for changes and if new file appears then download the subtitles 38 | 39 | ### napijs download 40 | 41 | Options: 42 | 43 | ```bash 44 | Options: 45 | --version, -v Show version number [boolean] 46 | --help, -h Show help [boolean] 47 | -l, --language Set subtitles language. Available languages: POL, ENG [choices: "POL", "ENG"] [default: "POL"] 48 | --verbose Show output [default: false] 49 | -f, --files An array of files separated by space char. Glob expression allowed. 50 | For more information visit: https://github.com/isaacs/node-glob [array] [default: ["*.mkv","*.avi","*.mp4","*.mpeg","*.wmv","*.rmvb","*.mov","*.mpg"]] 51 | --file Path to single file. If provided then --files argument is ignored 52 | -s, --save Overwrite subtitles file if one exist [boolean] 53 | ``` 54 | 55 | ### napijs watch 56 | 57 | Options: 58 | 59 | ```bash 60 | Options: 61 | --version, -v Show version number [boolean] 62 | --help, -h Show help [boolean] 63 | -l, --language Set subtitles language. Available languages: POL, ENG [choices: "POL", "ENG"] [default: "POL"] 64 | --verbose Show output [default: false] 65 | -f, --files An array of files separated by space char. Glob expression allowed. 66 | For more information visit: https://github.com/isaacs/node-glob [array] [default: ["*.mkv","*.avi","*.mp4","*.mpeg","*.wmv","*.rmvb","*.mov","*.mpg"]] 67 | --file Path to single file. If provided then --files argument is ignored 68 | -s, --save Overwrite subtitles file if one exist [boolean] 69 | -p, --path Path for file watcher. Path will be combined with file patterns from --files parameter [default: "."] 70 | ``` 71 | 72 | Command line usage 73 | ======== 74 | 75 | It's also possible to use `napijs` as a command line tool. To do so, install it as a global package. Example: 76 | 77 | ```bash 78 | npm i napijs -g 79 | napijs -h 80 | 81 | napijs download -f "**.mkv" Search subtitles for movies with .mkv 82 | extension in current folder 83 | napijs download -f "**/*.avi" Search subtitles for movies with .avi 84 | extension in current folder and subfolders. 85 | napijs download -f "**.mkv" "**/*.avi" This same but in one line. 86 | 87 | ``` 88 | 89 | Support 90 | ====== 91 | 92 | I strongly suggest to support [Napiprojekt](http://www.napiprojekt.pl/wsparcie). They do a great job! 93 | 94 | License 95 | ======= 96 | 97 | Copyright 2016 Marcin Kozaczyk MIT License (enclosed). 98 | -------------------------------------------------------------------------------- /dist/utils/HttpRequest.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-18. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 11 | 12 | var _querystring = require('querystring'); 13 | 14 | var _querystring2 = _interopRequireDefault(_querystring); 15 | 16 | var _http = require('http'); 17 | 18 | var _http2 = _interopRequireDefault(_http); 19 | 20 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 21 | 22 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 23 | 24 | var HttpRequest = function () { 25 | function HttpRequest(options, fileWithHash) { 26 | _classCallCheck(this, HttpRequest); 27 | 28 | this.fileWithHash = fileWithHash; 29 | this.postData = _querystring2.default.stringify({ 30 | //'mode': '32', 31 | //'client': 'AutoMove', 32 | //'client_ver': '1.0', 33 | //'downloaded_subtitles_id': this.fileWithHash.hash, 34 | //'downloaded_subtitles_lang': 'PL', 35 | //'downloaded_subtitles_txt': '2', 36 | //'advert_type': 'flashAllowed', 37 | //'video_info_hash': this.fileWithHash.hash, 38 | //'nazwa_pliku': this.fileWithHash.file, 39 | //'rozmiar_pliku_bajty': this.fileWithHash.bytes, 40 | //'the': 'end' 41 | 'downloaded_subtitles_lang': options.lang, 42 | 'downloaded_subtitles_txt': '1', 43 | 'client_ver': '2.2.0.2399', 44 | 'downloaded_subtitles_id': this.fileWithHash.hash, 45 | 'client': 'Napiprojekt', 46 | 'mode': '1' 47 | }); 48 | this.postOptions = { 49 | host: 'www.napiprojekt.pl', 50 | port: '80', 51 | path: '/api/api-napiprojekt3.php', 52 | method: 'POST', 53 | headers: { 54 | 'Content-Type': 'application/x-www-form-urlencoded', 55 | 'Content-Length': this.postData.length 56 | } 57 | }; 58 | } 59 | 60 | _createClass(HttpRequest, [{ 61 | key: 'request', 62 | value: function request() { 63 | var _this = this; 64 | 65 | return new Promise(function (resolve, reject) { 66 | var req = _http2.default.request(_this.postOptions, function (response) { 67 | _this.processResponse(resolve, response); 68 | }); 69 | req.on('error', function (e) { 70 | reject(e); 71 | }); 72 | req.write(_this.postData); 73 | req.end(); 74 | }); 75 | } 76 | }, { 77 | key: 'processResponse', 78 | value: function processResponse(resolve, res) { 79 | var _this2 = this; 80 | 81 | res.setEncoding('utf-8'); 82 | var responseString = ''; 83 | res.on('data', function (data) { 84 | responseString += data; 85 | }); 86 | res.on('end', function () { 87 | _this2.fileWithHash.responseString = responseString; 88 | resolve(_this2.fileWithHash); 89 | }); 90 | } 91 | }]); 92 | 93 | return HttpRequest; 94 | }(); 95 | 96 | exports.default = HttpRequest; -------------------------------------------------------------------------------- /dist/utils/FileManager.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-21. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | var _index = require('./index'); 11 | 12 | var _path = require('path'); 13 | 14 | var _path2 = _interopRequireDefault(_path); 15 | 16 | var _fs = require('fs'); 17 | 18 | var _fs2 = _interopRequireDefault(_fs); 19 | 20 | var _crypto = require('crypto'); 21 | 22 | var _crypto2 = _interopRequireDefault(_crypto); 23 | 24 | var _underscore = require('underscore'); 25 | 26 | var _underscore2 = _interopRequireDefault(_underscore); 27 | 28 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 29 | 30 | var fileExists = function fileExists(filename) { 31 | try { 32 | _fs2.default.statSync(filename); 33 | return true; 34 | } catch (e) { 35 | return false; 36 | } 37 | }; 38 | 39 | function checkIfFileExists(options, fileWithHash, resolve, reject) { 40 | var subsFileName = _path2.default.join(_path2.default.dirname(fileWithHash.file), _path2.default.basename(fileWithHash.file, _path2.default.extname(fileWithHash.file)) + options.extension); 41 | if (fileExists(subsFileName)) { 42 | if (!options.overwrite) { 43 | if (options.verbose) { 44 | _index.logger.info('File [ %s ] exist. Nothing to do!', subsFileName); 45 | } 46 | fileWithHash.subtitlesPresent = true; 47 | fileWithHash.subtitleFileName = subsFileName; 48 | return resolve(fileWithHash); 49 | } 50 | 51 | var current_date = new Date().valueOf().toString(); 52 | var random = Math.random().toString(); 53 | var digest = _crypto2.default.createHash('sha1').update(current_date + random).digest('hex'); 54 | var modifiedSubsFileName = _path2.default.join(_path2.default.dirname(fileWithHash.file), _path2.default.basename(fileWithHash.file, _path2.default.extname(fileWithHash.file)) + '-' + digest.substr(0, 4) + options.extension); 55 | 56 | if (options.verbose) { 57 | _index.logger.info('Renaming file [ %s ] to [ %s }', subsFileName, modifiedSubsFileName); 58 | } 59 | _fs2.default.renameSync(subsFileName, modifiedSubsFileName); 60 | } 61 | return resolve(fileWithHash); 62 | } 63 | 64 | function fileManager(options, fileWithHash, subtitles, resolve, reject) { 65 | if (fileWithHash.subtitlesPresent) { 66 | resolve(fileWithHash); 67 | } 68 | var subsFileName = _path2.default.join(_path2.default.dirname(fileWithHash.file), _path2.default.basename(fileWithHash.file, _path2.default.extname(fileWithHash.file)) + options.extension); 69 | 70 | if (options.verbose) { 71 | _index.logger.info('Saving file [ %s ]', subsFileName); 72 | } 73 | 74 | fileWithHash.subtitlesPresent = true; 75 | 76 | var file = _fs2.default.createWriteStream(subsFileName); 77 | 78 | file.on('error', function (err) { 79 | reject({ err: err, fileWithHash: fileWithHash }); 80 | }); 81 | file.on('finish', function () { 82 | if (options.verbose) { 83 | _index.logger.info('Subtitles file [ %s ] saved successfully', subsFileName); 84 | } 85 | fileWithHash.subtitleFileName = subsFileName; 86 | resolve(fileWithHash); 87 | }); 88 | var b = new Buffer(subtitles.content[0], 'base64'); 89 | file.write(b.toString('UTF-8')); 90 | file.end(); 91 | } 92 | 93 | var saveSubtitles = function saveSubtitles(options, fileWithHash, subtitles) { 94 | return new Promise(function (resolve, reject) { 95 | return fileManager(options, fileWithHash, subtitles, resolve, reject); 96 | }); 97 | }; 98 | var subtitleExists = function subtitleExists(options, fileWithHash) { 99 | return new Promise(function (resolve, reject) { 100 | return checkIfFileExists(options, fileWithHash, resolve, reject); 101 | }); 102 | }; 103 | 104 | exports.default = { 105 | saveSubtitles: saveSubtitles, 106 | subtitleExists: subtitleExists 107 | }; -------------------------------------------------------------------------------- /src/download.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-19. 3 | */ 4 | 'use strict'; 5 | import { logger, hash, glob, HttpRequest, XML2JSON, fileManager } from './utils'; 6 | 7 | /** 8 | * Generate MD5 partial hash for provided files 9 | * @param {NapijsOptions} options 10 | * @param files 11 | * @returns {Promise} 12 | */ 13 | var generateFileHashes = function (options, files) { 14 | if(options.verbose) { 15 | logger.info('Generating files hash...'); 16 | } 17 | if (files.length === 0) 18 | logger.info('No files found!'); 19 | else if (options.verbose) { 20 | logger.info('Files found: '); 21 | for (var file of files) { 22 | logger.info(file); 23 | } 24 | } 25 | 26 | var promises = []; 27 | for (var file of files) { 28 | promises.push(hash(file)); 29 | } 30 | return Promise.all(promises); 31 | }; 32 | /** 33 | * Check if files exist. If --save flag is on then rename existing file 34 | * @param {NapijsOptions} options 35 | * @param fileWithHashes 36 | * @returns {Promise} 37 | */ 38 | var checkSubtitleFiles = function (options, fileWithHashes) { 39 | if(options.verbose) { 40 | logger.info('Checking existing subtitles...'); 41 | } 42 | var promises = []; 43 | for (var file of fileWithHashes) { 44 | promises.push(fileManager.subtitleExists(options, file)); 45 | } 46 | return Promise.all(promises); 47 | }; 48 | 49 | /** 50 | * Perform HTTP request to Napiprojekt server 51 | * @param {NapijsOptions} options 52 | * @param fileHashes 53 | * @returns {Promise} 54 | */ 55 | var makeHttpRequests = function (options, fileHashes) { 56 | if(options.verbose) { 57 | logger.info('Performing HTTP requests...'); 58 | } 59 | var promises = []; 60 | for (var fileWithHash of fileHashes) { 61 | if(fileWithHash.subtitlesPresent) 62 | continue; 63 | if (options.verbose) { 64 | logger.info('Downloading subtitles for file [%s] with hash [%s]', fileWithHash.file, fileWithHash.hash); 65 | } 66 | var httpRequest = new HttpRequest(options, fileWithHash); 67 | promises.push(httpRequest.request()); 68 | } 69 | return Promise.all(promises); 70 | }; 71 | 72 | /** 73 | * Parse HTTP response from Napiprojekt server. Format XML response to JSON and save subtitles to file. 74 | * @param {NapijsOptions} options 75 | * @param filesWithHash 76 | * @returns {Promise} 77 | */ 78 | var parseHttpResponse = function (options, filesWithHash) { 79 | if(options.verbose) { 80 | logger.info('Parsing HTTP responses...'); 81 | } 82 | var promises = []; 83 | for (var fileWithHash of filesWithHash) { 84 | if(fileWithHash.subtitlesPresent) 85 | continue; 86 | var p = XML2JSON(options, fileWithHash).catch((err) => { 87 | if (options.verbose) { 88 | logger.info('Error in HTTP response: ', err.err); 89 | } 90 | return err.fileWithHash; 91 | }); 92 | promises.push(p); 93 | } 94 | return Promise.all(promises); 95 | }; 96 | 97 | /** 98 | * Main download function. Responsible for downloading subtitles from Napiprojekt server 99 | * Steps: 100 | * - find files provided in options 101 | * - generate partial MD5 hash for each file 102 | * - check if subtitles already exists. Rename old subtitles file if one exist 103 | * - call Napiprojekt server 104 | * - parse XML response to JSON format and save subtitles to disk 105 | * 106 | * @param {NapijsOptions} o options 107 | * @returns {Promise} 108 | */ 109 | function download(o) { 110 | return new Promise((resolve, reject) => { 111 | var promise; 112 | if(o.file.length > 0 ) { 113 | promise = generateFileHashes(o, [o.file]) 114 | .catch(err=> { 115 | reject(err); 116 | }); 117 | } else { 118 | promise = glob(o.files) 119 | .then((files)=> generateFileHashes(o, files)) 120 | .catch(err=> { 121 | reject(err); 122 | }); 123 | } 124 | promise 125 | .then((fileHashes)=> checkSubtitleFiles(o, fileHashes)) 126 | .then((fileHashes)=> makeHttpRequests(o, fileHashes)) 127 | .then((filesWithHash)=> parseHttpResponse(o, filesWithHash)) 128 | .then((responses)=> { 129 | resolve(responses); 130 | }) 131 | .catch(err=> { 132 | reject(err); 133 | }); 134 | }); 135 | } 136 | 137 | export default download -------------------------------------------------------------------------------- /dist/download.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kozervar on 2016-07-19. 3 | */ 4 | 'use strict'; 5 | 6 | Object.defineProperty(exports, "__esModule", { 7 | value: true 8 | }); 9 | 10 | var _utils = require('./utils'); 11 | 12 | /** 13 | * Generate MD5 partial hash for provided files 14 | * @param {NapijsOptions} options 15 | * @param files 16 | * @returns {Promise} 17 | */ 18 | var generateFileHashes = function generateFileHashes(options, files) { 19 | if (options.verbose) { 20 | _utils.logger.info('Generating files hash...'); 21 | } 22 | if (files.length === 0) _utils.logger.info('No files found!');else if (options.verbose) { 23 | _utils.logger.info('Files found: '); 24 | var _iteratorNormalCompletion = true; 25 | var _didIteratorError = false; 26 | var _iteratorError = undefined; 27 | 28 | try { 29 | for (var _iterator = files[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { 30 | var file = _step.value; 31 | 32 | _utils.logger.info(file); 33 | } 34 | } catch (err) { 35 | _didIteratorError = true; 36 | _iteratorError = err; 37 | } finally { 38 | try { 39 | if (!_iteratorNormalCompletion && _iterator.return) { 40 | _iterator.return(); 41 | } 42 | } finally { 43 | if (_didIteratorError) { 44 | throw _iteratorError; 45 | } 46 | } 47 | } 48 | } 49 | 50 | var promises = []; 51 | var _iteratorNormalCompletion2 = true; 52 | var _didIteratorError2 = false; 53 | var _iteratorError2 = undefined; 54 | 55 | try { 56 | for (var _iterator2 = files[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { 57 | var file = _step2.value; 58 | 59 | promises.push((0, _utils.hash)(file)); 60 | } 61 | } catch (err) { 62 | _didIteratorError2 = true; 63 | _iteratorError2 = err; 64 | } finally { 65 | try { 66 | if (!_iteratorNormalCompletion2 && _iterator2.return) { 67 | _iterator2.return(); 68 | } 69 | } finally { 70 | if (_didIteratorError2) { 71 | throw _iteratorError2; 72 | } 73 | } 74 | } 75 | 76 | return Promise.all(promises); 77 | }; 78 | /** 79 | * Check if files exist. If --save flag is on then rename existing file 80 | * @param {NapijsOptions} options 81 | * @param fileWithHashes 82 | * @returns {Promise} 83 | */ 84 | var checkSubtitleFiles = function checkSubtitleFiles(options, fileWithHashes) { 85 | if (options.verbose) { 86 | _utils.logger.info('Checking existing subtitles...'); 87 | } 88 | var promises = []; 89 | var _iteratorNormalCompletion3 = true; 90 | var _didIteratorError3 = false; 91 | var _iteratorError3 = undefined; 92 | 93 | try { 94 | for (var _iterator3 = fileWithHashes[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { 95 | var file = _step3.value; 96 | 97 | promises.push(_utils.fileManager.subtitleExists(options, file)); 98 | } 99 | } catch (err) { 100 | _didIteratorError3 = true; 101 | _iteratorError3 = err; 102 | } finally { 103 | try { 104 | if (!_iteratorNormalCompletion3 && _iterator3.return) { 105 | _iterator3.return(); 106 | } 107 | } finally { 108 | if (_didIteratorError3) { 109 | throw _iteratorError3; 110 | } 111 | } 112 | } 113 | 114 | return Promise.all(promises); 115 | }; 116 | 117 | /** 118 | * Perform HTTP request to Napiprojekt server 119 | * @param {NapijsOptions} options 120 | * @param fileHashes 121 | * @returns {Promise} 122 | */ 123 | var makeHttpRequests = function makeHttpRequests(options, fileHashes) { 124 | if (options.verbose) { 125 | _utils.logger.info('Performing HTTP requests...'); 126 | } 127 | var promises = []; 128 | var _iteratorNormalCompletion4 = true; 129 | var _didIteratorError4 = false; 130 | var _iteratorError4 = undefined; 131 | 132 | try { 133 | for (var _iterator4 = fileHashes[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { 134 | var fileWithHash = _step4.value; 135 | 136 | if (fileWithHash.subtitlesPresent) continue; 137 | if (options.verbose) { 138 | _utils.logger.info('Downloading subtitles for file [%s] with hash [%s]', fileWithHash.file, fileWithHash.hash); 139 | } 140 | var httpRequest = new _utils.HttpRequest(options, fileWithHash); 141 | promises.push(httpRequest.request()); 142 | } 143 | } catch (err) { 144 | _didIteratorError4 = true; 145 | _iteratorError4 = err; 146 | } finally { 147 | try { 148 | if (!_iteratorNormalCompletion4 && _iterator4.return) { 149 | _iterator4.return(); 150 | } 151 | } finally { 152 | if (_didIteratorError4) { 153 | throw _iteratorError4; 154 | } 155 | } 156 | } 157 | 158 | return Promise.all(promises); 159 | }; 160 | 161 | /** 162 | * Parse HTTP response from Napiprojekt server. Format XML response to JSON and save subtitles to file. 163 | * @param {NapijsOptions} options 164 | * @param filesWithHash 165 | * @returns {Promise} 166 | */ 167 | var parseHttpResponse = function parseHttpResponse(options, filesWithHash) { 168 | if (options.verbose) { 169 | _utils.logger.info('Parsing HTTP responses...'); 170 | } 171 | var promises = []; 172 | var _iteratorNormalCompletion5 = true; 173 | var _didIteratorError5 = false; 174 | var _iteratorError5 = undefined; 175 | 176 | try { 177 | for (var _iterator5 = filesWithHash[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { 178 | var fileWithHash = _step5.value; 179 | 180 | if (fileWithHash.subtitlesPresent) continue; 181 | var p = (0, _utils.XML2JSON)(options, fileWithHash).catch(function (err) { 182 | if (options.verbose) { 183 | _utils.logger.info('Error in HTTP response: ', err.err); 184 | } 185 | return err.fileWithHash; 186 | }); 187 | promises.push(p); 188 | } 189 | } catch (err) { 190 | _didIteratorError5 = true; 191 | _iteratorError5 = err; 192 | } finally { 193 | try { 194 | if (!_iteratorNormalCompletion5 && _iterator5.return) { 195 | _iterator5.return(); 196 | } 197 | } finally { 198 | if (_didIteratorError5) { 199 | throw _iteratorError5; 200 | } 201 | } 202 | } 203 | 204 | return Promise.all(promises); 205 | }; 206 | 207 | /** 208 | * Main download function. Responsible for downloading subtitles from Napiprojekt server 209 | * Steps: 210 | * - find files provided in options 211 | * - generate partial MD5 hash for each file 212 | * - check if subtitles already exists. Rename old subtitles file if one exist 213 | * - call Napiprojekt server 214 | * - parse XML response to JSON format and save subtitles to disk 215 | * 216 | * @param {NapijsOptions} o options 217 | * @returns {Promise} 218 | */ 219 | function download(o) { 220 | return new Promise(function (resolve, reject) { 221 | var promise; 222 | if (o.file.length > 0) { 223 | promise = generateFileHashes(o, [o.file]).catch(function (err) { 224 | reject(err); 225 | }); 226 | } else { 227 | promise = (0, _utils.glob)(o.files).then(function (files) { 228 | return generateFileHashes(o, files); 229 | }).catch(function (err) { 230 | reject(err); 231 | }); 232 | } 233 | promise.then(function (fileHashes) { 234 | return checkSubtitleFiles(o, fileHashes); 235 | }).then(function (fileHashes) { 236 | return makeHttpRequests(o, fileHashes); 237 | }).then(function (filesWithHash) { 238 | return parseHttpResponse(o, filesWithHash); 239 | }).then(function (responses) { 240 | resolve(responses); 241 | }).catch(function (err) { 242 | reject(err); 243 | }); 244 | }); 245 | } 246 | 247 | exports.default = download; --------------------------------------------------------------------------------