diff --git a/controllers/api/v1/index.js b/controllers/api/v1/index.js index f5504ad85..b16eeb0f6 100644 --- a/controllers/api/v1/index.js +++ b/controllers/api/v1/index.js @@ -2,11 +2,14 @@ 'use strict' var express = require('express') + var router = express.Router() - router.use('/videos', require('./videos')) - router.use('/remotevideos', require('./remoteVideos')) router.use('/pods', require('./pods')) + router.use('/remotevideos', require('./remoteVideos')) + router.use('/videos', require('./videos')) + + // --------------------------------------------------------------------------- module.exports = router })() diff --git a/controllers/api/v1/pods.js b/controllers/api/v1/pods.js index 30385bd5a..b073e85af 100644 --- a/controllers/api/v1/pods.js +++ b/controllers/api/v1/pods.js @@ -2,20 +2,27 @@ 'use strict' var express = require('express') - var router = express.Router() + var middleware = require('../../../middlewares') var miscMiddleware = middleware.misc + var pods = require('../../../models/pods') var reqValidator = middleware.reqValidators.pods var secureRequest = middleware.reqValidators.remote.secureRequest - var pods = require('../../../models/pods') - function listPods (req, res, next) { - pods.list(function (err, pods_list) { - if (err) return next(err) + var router = express.Router() - res.json(pods_list) - }) - } + router.get('/', miscMiddleware.cache(false), listPods) + router.post('/', reqValidator.podsAdd, miscMiddleware.cache(false), addPods) + router.get('/makefriends', miscMiddleware.cache(false), makeFriends) + router.get('/quitfriends', miscMiddleware.cache(false), quitFriends) + // Post because this is a secured request + router.post('/remove', secureRequest, miscMiddleware.decryptBody, removePods) + + // --------------------------------------------------------------------------- + + module.exports = router + + // --------------------------------------------------------------------------- function addPods (req, res, next) { pods.add(req.body.data, function (err, json) { @@ -25,11 +32,11 @@ }) } - function removePods (req, res, next) { - pods.remove(req.body.signature.url, function (err) { + function listPods (req, res, next) { + pods.list(function (err, pods_list) { if (err) return next(err) - res.sendStatus(204) + res.json(pods_list) }) } @@ -50,6 +57,14 @@ }) } + function removePods (req, res, next) { + pods.remove(req.body.signature.url, function (err) { + if (err) return next(err) + + res.sendStatus(204) + }) + } + function quitFriends (req, res, next) { pods.quitFriends(function (err) { if (err) return next(err) @@ -57,13 +72,4 @@ res.sendStatus(204) }) } - - router.get('/', miscMiddleware.cache(false), listPods) - router.get('/makefriends', miscMiddleware.cache(false), makeFriends) - router.get('/quitfriends', miscMiddleware.cache(false), quitFriends) - router.post('/', reqValidator.podsAdd, miscMiddleware.cache(false), addPods) - // Post because this is a secured request - router.post('/remove', secureRequest, miscMiddleware.decryptBody, removePods) - - module.exports = router })() diff --git a/controllers/api/v1/remoteVideos.js b/controllers/api/v1/remoteVideos.js index d534d6792..2be2fc87e 100644 --- a/controllers/api/v1/remoteVideos.js +++ b/controllers/api/v1/remoteVideos.js @@ -2,7 +2,6 @@ 'use strict' var express = require('express') - var router = express.Router() var pluck = require('lodash-node/compat/collection/pluck') var middleware = require('../../../middlewares') @@ -10,6 +9,30 @@ var reqValidator = middleware.reqValidators.remote var videos = require('../../../models/videos') + var router = express.Router() + + router.post('/add', + reqValidator.secureRequest, + miscMiddleware.decryptBody, + reqValidator.remoteVideosAdd, + miscMiddleware.cache(false), + addRemoteVideos + ) + + router.post('/remove', + reqValidator.secureRequest, + miscMiddleware.decryptBody, + reqValidator.remoteVideosRemove, + miscMiddleware.cache(false), + removeRemoteVideo + ) + + // --------------------------------------------------------------------------- + + module.exports = router + + // --------------------------------------------------------------------------- + function addRemoteVideos (req, res, next) { videos.addRemotes(req.body.data, function (err, videos) { if (err) return next(err) @@ -25,9 +48,4 @@ res.sendStatus(204) }) } - - router.post('/add', reqValidator.secureRequest, miscMiddleware.decryptBody, reqValidator.remoteVideosAdd, miscMiddleware.cache(false), addRemoteVideos) - router.post('/remove', reqValidator.secureRequest, miscMiddleware.decryptBody, reqValidator.remoteVideosRemove, miscMiddleware.cache(false), removeRemoteVideo) - - module.exports = router })() diff --git a/controllers/api/v1/videos.js b/controllers/api/v1/videos.js index aa8cb466b..64b05e32b 100644 --- a/controllers/api/v1/videos.js +++ b/controllers/api/v1/videos.js @@ -1,34 +1,50 @@ ;(function () { 'use strict' - var express = require('express') var config = require('config') var crypto = require('crypto') + var express = require('express') var multer = require('multer') - var router = express.Router() var middleware = require('../../../middlewares') var miscMiddleware = middleware.misc var reqValidator = middleware.reqValidators.videos var videos = require('../../../models/videos') + var router = express.Router() var uploads = config.get('storage.uploads') - function listVideos (req, res, next) { - videos.list(function (err, videos_list) { - if (err) return next(err) + // multer configuration + var storage = multer.diskStorage({ + destination: function (req, file, cb) { + cb(null, uploads) + }, - res.json(videos_list) - }) - } + filename: function (req, file, cb) { + var extension = '' + if (file.mimetype === 'video/webm') extension = 'webm' + else if (file.mimetype === 'video/mp4') extension = 'mp4' + else if (file.mimetype === 'video/ogg') extension = 'ogv' + crypto.pseudoRandomBytes(16, function (err, raw) { + var fieldname = err ? undefined : raw.toString('hex') + cb(null, fieldname + '.' + extension) + }) + } + }) - function searchVideos (req, res, next) { - videos.search(req.params.name, function (err, videos_list) { - if (err) return next(err) + var reqFiles = multer({ storage: storage }).fields([{ name: 'input_video', maxCount: 1 }]) - res.json(videos_list) - }) - } + router.get('/', miscMiddleware.cache(false), listVideos) + router.post('/', reqFiles, reqValidator.videosAdd, miscMiddleware.cache(false), addVideos) + router.get('/:id', reqValidator.videosGet, miscMiddleware.cache(false), getVideos) + router.delete('/:id', reqValidator.videosRemove, miscMiddleware.cache(false), removeVideo) + router.get('/search/:name', reqValidator.videosSearch, miscMiddleware.cache(false), searchVideos) + + // --------------------------------------------------------------------------- + + module.exports = router + + // --------------------------------------------------------------------------- function addVideos (req, res, next) { videos.add({ video: req.files.input_video[0], data: req.body }, function (err) { @@ -51,6 +67,14 @@ }) } + function listVideos (req, res, next) { + videos.list(function (err, videos_list) { + if (err) return next(err) + + res.json(videos_list) + }) + } + function removeVideo (req, res, next) { videos.remove(req.params.id, function (err) { if (err) return next(err) @@ -59,30 +83,11 @@ }) } - // multer configuration - var storage = multer.diskStorage({ - destination: function (req, file, cb) { - cb(null, uploads) - }, + function searchVideos (req, res, next) { + videos.search(req.params.name, function (err, videos_list) { + if (err) return next(err) - filename: function (req, file, cb) { - var extension = '' - if (file.mimetype === 'video/webm') extension = 'webm' - else if (file.mimetype === 'video/mp4') extension = 'mp4' - else if (file.mimetype === 'video/ogg') extension = 'ogv' - crypto.pseudoRandomBytes(16, function (err, raw) { - var fieldname = err ? undefined : raw.toString('hex') - cb(null, fieldname + '.' + extension) - }) - } - }) - var reqFiles = multer({ storage: storage }).fields([{ name: 'input_video', maxCount: 1 }]) - - router.get('/', miscMiddleware.cache(false), listVideos) - router.post('/', reqFiles, reqValidator.videosAdd, miscMiddleware.cache(false), addVideos) - router.get('/search/:name', reqValidator.videosSearch, miscMiddleware.cache(false), searchVideos) - router.get('/:id', reqValidator.videosGet, miscMiddleware.cache(false), getVideos) - router.delete('/:id', reqValidator.videosRemove, miscMiddleware.cache(false), removeVideo) - - module.exports = router + res.json(videos_list) + }) + } })() diff --git a/controllers/index.js b/controllers/index.js index 7dca002ff..770d08248 100644 --- a/controllers/index.js +++ b/controllers/index.js @@ -3,10 +3,8 @@ var constants = require('../initializers/constants') - var routes = { + module.exports = { api: require('./api/' + constants.API_VERSION), views: require('./views') } - - module.exports = routes })() diff --git a/controllers/views.js b/controllers/views.js index ebd97380e..1bb4ffe70 100644 --- a/controllers/views.js +++ b/controllers/views.js @@ -1,24 +1,29 @@ ;(function () { 'use strict' + var express = require('express') + + var middleware = require('../middlewares').misc + + var router = express.Router() + + router.get(/^\/(index)?$/, middleware.cache(), getIndex) + router.get('/partials/:directory/:name', middleware.cache(), getPartial) + + // --------------------------------------------------------------------------- + + module.exports = router + + // --------------------------------------------------------------------------- + + function getIndex (req, res) { + res.render('index') + } + function getPartial (req, res) { var directory = req.params.directory var name = req.params.name res.render('partials/' + directory + '/' + name) } - - function getIndex (req, res) { - res.render('index') - } - - var express = require('express') - var middleware = require('../middlewares').misc - - var router = express.Router() - - router.get('/partials/:directory/:name', middleware.cache(), getPartial) - router.get(/^\/(index)?$/, middleware.cache(), getIndex) - - module.exports = router })() diff --git a/helpers/customValidators.js b/helpers/customValidators.js index 73c2f8461..c433e5c5d 100644 --- a/helpers/customValidators.js +++ b/helpers/customValidators.js @@ -3,9 +3,13 @@ var validator = require('validator') - var customValidators = {} + var customValidators = { + eachIsRemoteVideosAddValid: eachIsRemoteVideosAddValid, + eachIsRemoteVideosRemoveValid: eachIsRemoteVideosRemoveValid, + isArray: isArray + } - customValidators.eachIsRemoteVideosAddValid = function (values) { + function eachIsRemoteVideosAddValid (values) { return values.every(function (val) { return validator.isLength(val.name, 1, 50) && validator.isLength(val.description, 1, 50) && @@ -14,16 +18,17 @@ }) } - customValidators.eachIsRemoteVideosRemoveValid = function (values) { + function eachIsRemoteVideosRemoveValid (values) { return values.every(function (val) { return validator.isLength(val.magnetUri, 10) }) } - customValidators.isArray = function (value) { + function isArray (value) { return Array.isArray(value) } - // ----------- Export ----------- + // --------------------------------------------------------------------------- + module.exports = customValidators })() diff --git a/helpers/logger.js b/helpers/logger.js index 850af10cb..fa5b53708 100644 --- a/helpers/logger.js +++ b/helpers/logger.js @@ -4,11 +4,9 @@ var config = require('config') var winston = require('winston') - - var logDir = __dirname + '/../' + config.get('storage.logs') - winston.emitErrs = true + var logDir = __dirname + '/../' + config.get('storage.logs') var logger = new winston.Logger({ transports: [ new winston.transports.File({ @@ -31,10 +29,13 @@ exitOnError: true }) - module.exports = logger - module.exports.stream = { + logger.stream = { write: function (message, encoding) { logger.info(message) } } + + // --------------------------------------------------------------------------- + + module.exports = logger })() diff --git a/helpers/utils.js b/helpers/utils.js index 7cdb2600d..ec46631b1 100644 --- a/helpers/utils.js +++ b/helpers/utils.js @@ -13,47 +13,29 @@ var constants = require('../initializers/constants') var logger = require('./logger') - var utils = {} - + var certDir = __dirname + '/../' + config.get('storage.certs') var http = config.get('webserver.https') ? 'https' : 'http' var host = config.get('webserver.host') var port = config.get('webserver.port') var algorithm = 'aes-256-ctr' - // ----------- Private functions ---------- - - function makeRetryRequest (params, from_url, to_pod, signature, callbackEach) { - // Append the signature - if (signature) { - params.json.signature = { - url: from_url, - signature: signature - } - } - - logger.debug('Make retry requests to %s.', to_pod.url) - - replay( - request.post(params, function (err, response, body) { - callbackEach(err, response, body, params.url, to_pod) - }), - { - retries: constants.REQUEST_RETRIES, - factor: 3, - maxTimeout: Infinity, - errorCodes: [ 'EADDRINFO', 'ETIMEDOUT', 'ECONNRESET', 'ESOCKETTIMEDOUT', 'ENOTFOUND', 'ECONNREFUSED' ] - } - ).on('replay', function (replay) { - logger.info('Replaying request to %s. Request failed: %d %s. Replay number: #%d. Will retry in: %d ms.', - params.url, replay.error.code, replay.error.message, replay.number, replay.delay) - }) + var utils = { + getCertDir: getCertDir, + certsExist: certsExist, + cleanForExit: cleanForExit, + createCerts: createCerts, + createCertsIfNotExist: createCertsIfNotExist, + generatePassword: generatePassword, + makeMultipleRetryRequest: makeMultipleRetryRequest, + symetricEncrypt: symetricEncrypt, + symetricDecrypt: symetricDecrypt } - // ----------- Public attributes ---------- - utils.certDir = __dirname + '/../' + config.get('storage.certs') + function getCertDir () { + return certDir + } - // { path, data } - utils.makeMultipleRetryRequest = function (all_data, pods, callbackEach, callback) { + function makeMultipleRetryRequest (all_data, pods, callbackEach, callback) { if (!callback) { callback = callbackEach callbackEach = null @@ -64,7 +46,7 @@ // Add signature if it is specified in the params if (all_data.method === 'POST' && all_data.data && all_data.sign === true) { - var myKey = ursa.createPrivateKey(fs.readFileSync(utils.certDir + 'peertube.key.pem')) + var myKey = ursa.createPrivateKey(fs.readFileSync(certDir + 'peertube.key.pem')) signature = myKey.hashAndSign('sha256', url, 'utf8', 'hex') } @@ -93,7 +75,7 @@ // TODO: ES6 with let ;(function (crt_copy, copy_params, copy_url, copy_pod, copy_signature) { - utils.symetricEncrypt(JSON.stringify(all_data.data), function (err, dataEncrypted) { + symetricEncrypt(JSON.stringify(all_data.data), function (err, dataEncrypted) { if (err) throw err var passwordEncrypted = crt_copy.encrypt(dataEncrypted.password, 'utf8', 'hex') @@ -115,14 +97,14 @@ }, callback) } - utils.certsExist = function (callback) { - fs.exists(utils.certDir + 'peertube.key.pem', function (exists) { + function certsExist (callback) { + fs.exists(certDir + 'peertube.key.pem', function (exists) { return callback(exists) }) } - utils.createCerts = function (callback) { - utils.certsExist(function (exist) { + function createCerts (callback) { + certsExist(function (exist) { if (exist === true) { var string = 'Certs already exist.' logger.warning(string) @@ -130,7 +112,7 @@ } logger.info('Generating a RSA key...') - openssl.exec('genrsa', { 'out': utils.certDir + 'peertube.key.pem', '2048': false }, function (err) { + openssl.exec('genrsa', { 'out': certDir + 'peertube.key.pem', '2048': false }, function (err) { if (err) { logger.error('Cannot create private key on this pod.', { error: err }) return callback(err) @@ -138,7 +120,7 @@ logger.info('RSA key generated.') logger.info('Manage public key...') - openssl.exec('rsa', { 'in': utils.certDir + 'peertube.key.pem', 'pubout': true, 'out': utils.certDir + 'peertube.pub' }, function (err) { + openssl.exec('rsa', { 'in': certDir + 'peertube.key.pem', 'pubout': true, 'out': certDir + 'peertube.pub' }, function (err) { if (err) { logger.error('Cannot create public key on this pod .', { error: err }) return callback(err) @@ -151,19 +133,19 @@ }) } - utils.createCertsIfNotExist = function (callback) { - utils.certsExist(function (exist) { + function createCertsIfNotExist (callback) { + certsExist(function (exist) { if (exist === true) { return callback(null) } - utils.createCerts(function (err) { + createCerts(function (err) { return callback(err) }) }) } - utils.generatePassword = function (callback) { + function generatePassword (callback) { crypto.randomBytes(32, function (err, buf) { if (err) { return callback(err) @@ -173,8 +155,8 @@ }) } - utils.symetricEncrypt = function (text, callback) { - utils.generatePassword(function (err, password) { + function symetricEncrypt (text, callback) { + generatePassword(function (err, password) { if (err) { return callback(err) } @@ -186,17 +168,48 @@ }) } - utils.symetricDecrypt = function (text, password) { + function symetricDecrypt (text, password) { var decipher = crypto.createDecipher(algorithm, password) var dec = decipher.update(text, 'hex', 'utf8') dec += decipher.final('utf8') return dec } - utils.cleanForExit = function (webtorrent_process) { + function cleanForExit (webtorrent_process) { logger.info('Gracefully exiting') process.kill(-webtorrent_process.pid) } + // --------------------------------------------------------------------------- + module.exports = utils + + // --------------------------------------------------------------------------- + + function makeRetryRequest (params, from_url, to_pod, signature, callbackEach) { + // Append the signature + if (signature) { + params.json.signature = { + url: from_url, + signature: signature + } + } + + logger.debug('Make retry requests to %s.', to_pod.url) + + replay( + request.post(params, function (err, response, body) { + callbackEach(err, response, body, params.url, to_pod) + }), + { + retries: constants.REQUEST_RETRIES, + factor: 3, + maxTimeout: Infinity, + errorCodes: [ 'EADDRINFO', 'ETIMEDOUT', 'ECONNRESET', 'ESOCKETTIMEDOUT', 'ENOTFOUND', 'ECONNREFUSED' ] + } + ).on('replay', function (replay) { + logger.info('Replaying request to %s. Request failed: %d %s. Replay number: #%d. Will retry in: %d ms.', + params.url, replay.error.code, replay.error.message, replay.number, replay.delay) + }) + } })() diff --git a/initializers/checker.js b/initializers/checker.js index 7a3a53616..7a09c02d1 100644 --- a/initializers/checker.js +++ b/initializers/checker.js @@ -4,10 +4,13 @@ var config = require('config') var mkdirp = require('mkdirp') - var checker = {} + var checker = { + checkConfig: checkConfig, + createDirectoriesIfNotExist: createDirectoriesIfNotExist + } // Check the config files - checker.checkConfig = function () { + function checkConfig () { var required = [ 'listen.port', 'webserver.https', 'webserver.host', 'webserver.port', 'database.host', 'database.port', 'database.suffix', @@ -25,7 +28,7 @@ } // Create directories for the storage if it doesn't exist - checker.createDirectoriesIfNotExist = function () { + function createDirectoriesIfNotExist () { var storages = config.get('storage') for (var key of Object.keys(storages)) { @@ -40,6 +43,7 @@ } } - // ----------- Export ----------- + // --------------------------------------------------------------------------- + module.exports = checker })() diff --git a/initializers/constants.js b/initializers/constants.js index 00b713961..1e101a747 100644 --- a/initializers/constants.js +++ b/initializers/constants.js @@ -1,37 +1,44 @@ ;(function () { 'use strict' - var constants = {} - - function isTestInstance () { - return (process.env.NODE_ENV === 'test') - } - // API version of our pod - constants.API_VERSION = 'v1' + var API_VERSION = 'v1' // Score a pod has when we create it as a friend - constants.FRIEND_BASE_SCORE = 100 + var FRIEND_BASE_SCORE = 100 // Time to wait between requests to the friends - constants.INTERVAL = 60000 + var INTERVAL = 60000 // Number of points we add/remove from a friend after a successful/bad request - constants.PODS_SCORE = { + var PODS_SCORE = { MALUS: -10, BONUS: 10 } // Number of retries we make for the make retry requests (to friends...) - constants.REQUEST_RETRIES = 10 + var REQUEST_RETRIES = 10 // Special constants for a test instance if (isTestInstance() === true) { - constants.FRIEND_BASE_SCORE = 20 - constants.INTERVAL = 10000 - constants.REQUEST_RETRIES = 2 + FRIEND_BASE_SCORE = 20 + INTERVAL = 10000 + REQUEST_RETRIES = 2 } - // ----------- Export ----------- - module.exports = constants + // --------------------------------------------------------------------------- + + module.exports = { + API_VERSION: API_VERSION, + FRIEND_BASE_SCORE: FRIEND_BASE_SCORE, + INTERVAL: INTERVAL, + PODS_SCORE: PODS_SCORE, + REQUEST_RETRIES: REQUEST_RETRIES + } + + // --------------------------------------------------------------------------- + + function isTestInstance () { + return (process.env.NODE_ENV === 'test') + } })() diff --git a/initializers/database.js b/initializers/database.js index 4570d3739..e041d5c4b 100644 --- a/initializers/database.js +++ b/initializers/database.js @@ -11,17 +11,6 @@ var host = config.get('database.host') var port = config.get('database.port') - // ----------- Videos ----------- - var videosSchema = mongoose.Schema({ - name: String, - namePath: String, - description: String, - magnetUri: String, - podUrl: String - }) - - var VideosDB = mongoose.model('videos', videosSchema) - // ----------- Pods ----------- var podsSchema = mongoose.Schema({ url: String, @@ -40,6 +29,25 @@ var PoolRequestsDB = mongoose.model('poolRequests', poolRequestsSchema) + // ----------- Videos ----------- + var videosSchema = mongoose.Schema({ + name: String, + namePath: String, + description: String, + magnetUri: String, + podUrl: String + }) + + var VideosDB = mongoose.model('videos', videosSchema) + + // --------------------------------------------------------------------------- + + module.exports = { + PodsDB: PodsDB, + PoolRequestsDB: PoolRequestsDB, + VideosDB: VideosDB + } + // ----------- Connection ----------- mongoose.connect('mongodb://' + host + ':' + port + '/' + dbname) @@ -51,11 +59,4 @@ mongoose.connection.on('open', function () { logger.info('Connected to mongodb.') }) - - // ----------- Export ----------- - module.exports = { - VideosDB: VideosDB, - PodsDB: PodsDB, - PoolRequestsDB: PoolRequestsDB - } })() diff --git a/lib/poolRequests.js b/lib/poolRequests.js index 9c7f3238b..53f47d629 100644 --- a/lib/poolRequests.js +++ b/lib/poolRequests.js @@ -2,29 +2,114 @@ 'use strict' var async = require('async') + var pluck = require('lodash-node/compat/collection/pluck') var constants = require('../initializers/constants') - var logger = require('../helpers/logger') var database = require('../initializers/database') - var pluck = require('lodash-node/compat/collection/pluck') - var PoolRequestsDB = database.PoolRequestsDB + var logger = require('../helpers/logger') var PodsDB = database.PodsDB + var PoolRequestsDB = database.PoolRequestsDB var utils = require('../helpers/utils') var VideosDB = database.VideosDB - var poolRequests = {} - - // ----------- Private ----------- var timer = null - function removePoolRequestsFromDB (ids) { - PoolRequestsDB.remove({ _id: { $in: ids } }, function (err) { - if (err) { - logger.error('Cannot remove requests from the pool requests database.', { error: err }) - return + var poolRequests = { + activate: activate, + addToPoolRequests: addToPoolRequests, + deactivate: deactivate, + forceSend: forceSend + } + + function deactivate () { + logger.info('Pool requests deactivated.') + clearInterval(timer) + } + + function forceSend () { + logger.info('Force pool requests sending.') + makePoolRequests() + } + + function activate () { + logger.info('Pool requests activated.') + timer = setInterval(makePoolRequests, constants.INTERVAL) + } + + function addToPoolRequests (id, type, request) { + logger.debug('Add request to the pool requests.', { id: id, type: type, request: request }) + + PoolRequestsDB.findOne({ id: id }, function (err, entity) { + if (err) logger.error(err) + + if (entity) { + if (entity.type === type) { + logger.error(new Error('Cannot insert two same requests.')) + return + } + + // Remove the request of the other type + PoolRequestsDB.remove({ id: id }, function (err) { + if (err) logger.error(err) + }) + } else { + PoolRequestsDB.create({ id: id, type: type, request: request }, function (err) { + if (err) logger.error(err) + }) + } + }) + } + + // --------------------------------------------------------------------------- + + module.exports = poolRequests + + // --------------------------------------------------------------------------- + + function makePoolRequest (type, requests, callback) { + if (!callback) callback = function () {} + + PodsDB.find({}, { _id: 1, url: 1, publicKey: 1 }).exec(function (err, pods) { + if (err) throw err + + var params = { + encrypt: true, + sign: true, + method: 'POST', + path: null, + data: requests } - logger.info('Pool requests flushed.') + if (type === 'add') { + params.path = '/api/' + constants.API_VERSION + '/remotevideos/add' + } else if (type === 'remove') { + params.path = '/api/' + constants.API_VERSION + '/remotevideos/remove' + } else { + throw new Error('Unkown pool request type.') + } + + var bad_pods = [] + var good_pods = [] + + utils.makeMultipleRetryRequest(params, pods, callbackEachPodFinished, callbackAllPodsFinished) + + function callbackEachPodFinished (err, response, body, url, pod, callback_each_pod_finished) { + if (err || (response.statusCode !== 200 && response.statusCode !== 204)) { + bad_pods.push(pod._id) + logger.error('Error sending secure request to %s pod.', url, { error: err || new Error('Status code not 20x') }) + } else { + good_pods.push(pod._id) + } + + return callback_each_pod_finished() + } + + function callbackAllPodsFinished (err) { + if (err) return callback(err) + + updatePodsScore(good_pods, bad_pods) + callback(null) + } }) } @@ -81,16 +166,6 @@ }) } - function updatePodsScore (good_pods, bad_pods) { - logger.info('Updating %d good pods and %d bad pods scores.', good_pods.length, bad_pods.length) - - PodsDB.update({ _id: { $in: good_pods } }, { $inc: { score: constants.PODS_SCORE.BONUS } }, { multi: true }).exec() - PodsDB.update({ _id: { $in: bad_pods } }, { $inc: { score: constants.PODS_SCORE.MALUS } }, { multi: true }, function (err) { - if (err) throw err - removeBadPods() - }) - } - function removeBadPods () { PodsDB.find({ score: 0 }, { _id: 1, url: 1 }, function (err, pods) { if (err) throw err @@ -115,92 +190,24 @@ }) } - function makePoolRequest (type, requests, callback) { - if (!callback) callback = function () {} + function removePoolRequestsFromDB (ids) { + PoolRequestsDB.remove({ _id: { $in: ids } }, function (err) { + if (err) { + logger.error('Cannot remove requests from the pool requests database.', { error: err }) + return + } - PodsDB.find({}, { _id: 1, url: 1, publicKey: 1 }).exec(function (err, pods) { + logger.info('Pool requests flushed.') + }) + } + + function updatePodsScore (good_pods, bad_pods) { + logger.info('Updating %d good pods and %d bad pods scores.', good_pods.length, bad_pods.length) + + PodsDB.update({ _id: { $in: good_pods } }, { $inc: { score: constants.PODS_SCORE.BONUS } }, { multi: true }).exec() + PodsDB.update({ _id: { $in: bad_pods } }, { $inc: { score: constants.PODS_SCORE.MALUS } }, { multi: true }, function (err) { if (err) throw err - - var params = { - encrypt: true, - sign: true, - method: 'POST', - path: null, - data: requests - } - - if (type === 'add') { - params.path = '/api/' + constants.API_VERSION + '/remotevideos/add' - } else if (type === 'remove') { - params.path = '/api/' + constants.API_VERSION + '/remotevideos/remove' - } else { - throw new Error('Unkown pool request type.') - } - - var bad_pods = [] - var good_pods = [] - - utils.makeMultipleRetryRequest(params, pods, callbackEachPodFinished, callbackAllPodsFinished) - - function callbackEachPodFinished (err, response, body, url, pod, callback_each_pod_finished) { - if (err || (response.statusCode !== 200 && response.statusCode !== 204)) { - bad_pods.push(pod._id) - logger.error('Error sending secure request to %s pod.', url, { error: err || new Error('Status code not 20x') }) - } else { - good_pods.push(pod._id) - } - - return callback_each_pod_finished() - } - - function callbackAllPodsFinished (err) { - if (err) return callback(err) - - updatePodsScore(good_pods, bad_pods) - callback(null) - } + removeBadPods() }) } - - // ----------- Public ----------- - poolRequests.activate = function () { - logger.info('Pool requests activated.') - timer = setInterval(makePoolRequests, constants.INTERVAL) - } - - poolRequests.addToPoolRequests = function (id, type, request) { - logger.debug('Add request to the pool requests.', { id: id, type: type, request: request }) - - PoolRequestsDB.findOne({ id: id }, function (err, entity) { - if (err) logger.error(err) - - if (entity) { - if (entity.type === type) { - logger.error(new Error('Cannot insert two same requests.')) - return - } - - // Remove the request of the other type - PoolRequestsDB.remove({ id: id }, function (err) { - if (err) logger.error(err) - }) - } else { - PoolRequestsDB.create({ id: id, type: type, request: request }, function (err) { - if (err) logger.error(err) - }) - } - }) - } - - poolRequests.deactivate = function () { - logger.info('Pool requests deactivated.') - clearInterval(timer) - } - - poolRequests.forceSend = function () { - logger.info('Force pool requests sending.') - makePoolRequests() - } - - module.exports = poolRequests })() diff --git a/lib/webTorrentNode.js b/lib/webTorrentNode.js index 8827c68c5..69fa6b012 100644 --- a/lib/webTorrentNode.js +++ b/lib/webTorrentNode.js @@ -10,22 +10,21 @@ var host = config.get('webserver.host') var port = config.get('webserver.port') - var nodeKey = 'webtorrentnode' + port var processKey = 'webtorrent' + port - ipc.config.silent = true ipc.config.id = nodeKey - var webtorrentnode = {} + var webtorrentnode = { + add: add, + app: null, // Pid of the app + create: create, + remove: remove, + seed: seed, + silent: false // Useful for beautiful tests + } - // Useful for beautiful tests - webtorrentnode.silent = false - - // Useful to kill it - webtorrentnode.app = null - - webtorrentnode.create = function (options, callback) { + function create (options, callback) { if (typeof options === 'function') { callback = options options = {} @@ -75,7 +74,7 @@ ipc.server.start() } - webtorrentnode.seed = function (path, callback) { + function seed (path, callback) { var extension = pathUtils.extname(path) var basename = pathUtils.basename(path, extension) var data = { @@ -104,7 +103,7 @@ ipc.server.broadcast(processKey + '.seed', data) } - webtorrentnode.add = function (magnetUri, callback) { + function add (magnetUri, callback) { var data = { _id: magnetUri, args: { @@ -131,7 +130,7 @@ ipc.server.broadcast(processKey + '.add', data) } - webtorrentnode.remove = function (magnetUri, callback) { + function remove (magnetUri, callback) { var data = { _id: magnetUri, args: { @@ -156,5 +155,7 @@ ipc.server.broadcast(processKey + '.remove', data) } + // --------------------------------------------------------------------------- + module.exports = webtorrentnode })() diff --git a/lib/webtorrent.js b/lib/webtorrent.js index b72bc500d..41e60499f 100644 --- a/lib/webtorrent.js +++ b/lib/webtorrent.js @@ -1,7 +1,7 @@ ;(function () { 'use strict' - module.exports = function (args) { + function webtorrent (args) { var WebTorrent = require('webtorrent') var ipc = require('node-ipc') @@ -88,4 +88,8 @@ ipc.of[nodeKey].emit(processKey + '.exception', { exception: e }) }) } + + // --------------------------------------------------------------------------- + + module.exports = webtorrent })() diff --git a/middlewares/index.js b/middlewares/index.js index e727202ba..311dfb6d2 100644 --- a/middlewares/index.js +++ b/middlewares/index.js @@ -1,10 +1,12 @@ ;(function () { 'use strict' - var middleware = { - reqValidators: require('./reqValidators'), - misc: require('./misc') + var middlewares = { + misc: require('./misc'), + reqValidators: require('./reqValidators') } - module.exports = middleware + // --------------------------------------------------------------------------- + + module.exports = middlewares })() diff --git a/middlewares/misc.js b/middlewares/misc.js index f814acd9f..dbb604db3 100644 --- a/middlewares/misc.js +++ b/middlewares/misc.js @@ -1,16 +1,19 @@ ;(function () { 'use strict' - var ursa = require('ursa') var fs = require('fs') + var ursa = require('ursa') var logger = require('../helpers/logger') - var utils = require('../helpers/utils') var PodsDB = require('../initializers/database').PodsDB + var utils = require('../helpers/utils') - var misc = {} + var miscMiddleware = { + cache: cache, + decryptBody: decryptBody + } - misc.cache = function (cache) { + function cache (cache) { return function (req, res, next) { // If we want explicitly a cache // Or if we don't specify if we want a cache or no and we are in production @@ -24,7 +27,7 @@ } } - misc.decryptBody = function (req, res, next) { + function decryptBody (req, res, next) { PodsDB.findOne({ url: req.body.signature.url }, function (err, pod) { if (err) { logger.error('Cannot get signed url in decryptBody.', { error: err }) @@ -42,7 +45,7 @@ var signature_ok = crt.hashAndVerify('sha256', new Buffer(req.body.signature.url).toString('hex'), req.body.signature.signature, 'hex') if (signature_ok === true) { - var myKey = ursa.createPrivateKey(fs.readFileSync(utils.certDir + 'peertube.key.pem')) + var myKey = ursa.createPrivateKey(fs.readFileSync(utils.getCertDir() + 'peertube.key.pem')) var decryptedKey = myKey.decrypt(req.body.key, 'hex', 'utf8') req.body.data = JSON.parse(utils.symetricDecrypt(req.body.data, decryptedKey)) delete req.body.key @@ -55,5 +58,7 @@ }) } - module.exports = misc + // --------------------------------------------------------------------------- + + module.exports = miscMiddleware })() diff --git a/middlewares/reqValidators/index.js b/middlewares/reqValidators/index.js index 1ea611031..34d34013c 100644 --- a/middlewares/reqValidators/index.js +++ b/middlewares/reqValidators/index.js @@ -1,11 +1,13 @@ ;(function () { 'use strict' - var reqValidator = { + var reqValidators = { videos: require('./videos'), pods: require('./pods'), remote: require('./remote') } - module.exports = reqValidator + // --------------------------------------------------------------------------- + + module.exports = reqValidators })() diff --git a/middlewares/reqValidators/pods.js b/middlewares/reqValidators/pods.js index 0d023842d..6ccfd7361 100644 --- a/middlewares/reqValidators/pods.js +++ b/middlewares/reqValidators/pods.js @@ -4,9 +4,11 @@ var checkErrors = require('./utils').checkErrors var logger = require('../../helpers/logger') - var pods = {} + var reqValidatorsPod = { + podsAdd: podsAdd + } - pods.podsAdd = function (req, res, next) { + function podsAdd (req, res, next) { req.checkBody('data.url', 'Should have an url').notEmpty().isURL({ require_protocol: true }) req.checkBody('data.publicKey', 'Should have a public key').notEmpty() @@ -15,5 +17,7 @@ checkErrors(req, res, next) } - module.exports = pods + // --------------------------------------------------------------------------- + + module.exports = reqValidatorsPod })() diff --git a/middlewares/reqValidators/remote.js b/middlewares/reqValidators/remote.js index 4b161e292..9b61481ad 100644 --- a/middlewares/reqValidators/remote.js +++ b/middlewares/reqValidators/remote.js @@ -4,9 +4,31 @@ var checkErrors = require('./utils').checkErrors var logger = require('../../helpers/logger') - var remote = {} + var reqValidatorsRemote = { + remoteVideosAdd: remoteVideosAdd, + remoteVideosRemove: remoteVideosRemove, + secureRequest: secureRequest + } - remote.secureRequest = function (req, res, next) { + function remoteVideosAdd (req, res, next) { + req.checkBody('data').isArray() + req.checkBody('data').eachIsRemoteVideosAddValid() + + logger.debug('Checking remoteVideosAdd parameters', { parameters: req.body }) + + checkErrors(req, res, next) + } + + function remoteVideosRemove (req, res, next) { + req.checkBody('data').isArray() + req.checkBody('data').eachIsRemoteVideosRemoveValid() + + logger.debug('Checking remoteVideosRemove parameters', { parameters: req.body }) + + checkErrors(req, res, next) + } + + function secureRequest (req, res, next) { req.checkBody('signature.url', 'Should have a signature url').isURL() req.checkBody('signature.signature', 'Should have a signature').notEmpty() req.checkBody('key', 'Should have a key').notEmpty() @@ -17,23 +39,7 @@ checkErrors(req, res, next) } - remote.remoteVideosAdd = function (req, res, next) { - req.checkBody('data').isArray() - req.checkBody('data').eachIsRemoteVideosAddValid() + // --------------------------------------------------------------------------- - logger.debug('Checking remoteVideosAdd parameters', { parameters: req.body }) - - checkErrors(req, res, next) - } - - remote.remoteVideosRemove = function (req, res, next) { - req.checkBody('data').isArray() - req.checkBody('data').eachIsRemoteVideosRemoveValid() - - logger.debug('Checking remoteVideosRemove parameters', { parameters: req.body }) - - checkErrors(req, res, next) - } - - module.exports = remote + module.exports = reqValidatorsRemote })() diff --git a/middlewares/reqValidators/utils.js b/middlewares/reqValidators/utils.js index 5bc9f4f0b..c88f6df2e 100644 --- a/middlewares/reqValidators/utils.js +++ b/middlewares/reqValidators/utils.js @@ -2,11 +2,14 @@ 'use strict' var util = require('util') + var logger = require('../../helpers/logger') - var utils = {} + var reqValidatorsUtils = { + checkErrors: checkErrors + } - utils.checkErrors = function (req, res, next, status_code) { + function checkErrors (req, res, next, status_code) { if (status_code === undefined) status_code = 400 var errors = req.validationErrors() @@ -18,5 +21,7 @@ return next() } - module.exports = utils + // --------------------------------------------------------------------------- + + module.exports = reqValidatorsUtils })() diff --git a/middlewares/reqValidators/videos.js b/middlewares/reqValidators/videos.js index a34445f7a..3479c47c3 100644 --- a/middlewares/reqValidators/videos.js +++ b/middlewares/reqValidators/videos.js @@ -2,28 +2,17 @@ 'use strict' var checkErrors = require('./utils').checkErrors - var VideosDB = require('../../initializers/database').VideosDB var logger = require('../../helpers/logger') + var VideosDB = require('../../initializers/database').VideosDB - var videos = {} - - function findVideoById (id, callback) { - VideosDB.findById(id, { _id: 1, namePath: 1 }).limit(1).exec(function (err, video) { - if (err) throw err - - callback(video) - }) + var reqValidatorsVideos = { + videosAdd: videosAdd, + videosGet: videosGet, + videosRemove: videosRemove, + videosSearch: videosSearch } - videos.videosSearch = function (req, res, next) { - req.checkParams('name', 'Should have a name').notEmpty() - - logger.debug('Checking videosSearch parameters', { parameters: req.params }) - - checkErrors(req, res, next) - } - - videos.videosAdd = function (req, res, next) { + function videosAdd (req, res, next) { req.checkFiles('input_video[0].originalname', 'Should have an input video').notEmpty() req.checkFiles('input_video[0].mimetype', 'Should have a correct mime type').matches(/video\/(webm)|(mp4)|(ogg)/i) req.checkBody('name', 'Should have a name').isLength(1, 50) @@ -34,7 +23,7 @@ checkErrors(req, res, next) } - videos.videosGet = function (req, res, next) { + function videosGet (req, res, next) { req.checkParams('id', 'Should have a valid id').notEmpty().isMongoId() logger.debug('Checking videosGet parameters', { parameters: req.params }) @@ -48,7 +37,7 @@ }) } - videos.videosRemove = function (req, res, next) { + function videosRemove (req, res, next) { req.checkParams('id', 'Should have a valid id').notEmpty().isMongoId() logger.debug('Checking videosRemove parameters', { parameters: req.params }) @@ -63,5 +52,25 @@ }) } - module.exports = videos + function videosSearch (req, res, next) { + req.checkParams('name', 'Should have a name').notEmpty() + + logger.debug('Checking videosSearch parameters', { parameters: req.params }) + + checkErrors(req, res, next) + } + + // --------------------------------------------------------------------------- + + module.exports = reqValidatorsVideos + + // --------------------------------------------------------------------------- + + function findVideoById (id, callback) { + VideosDB.findById(id, { _id: 1, namePath: 1 }).limit(1).exec(function (err, video) { + if (err) throw err + + callback(video) + }) + } })() diff --git a/models/pods.js b/models/pods.js index c8d08b26f..ed2f0d8ee 100644 --- a/models/pods.js +++ b/models/pods.js @@ -12,39 +12,23 @@ var poolRequests = require('../lib/poolRequests') var utils = require('../helpers/utils') - var pods = {} - var http = config.get('webserver.https') ? 'https' : 'http' var host = config.get('webserver.host') var port = config.get('webserver.port') - // ----------- Private functions ----------- - - function getForeignPodsList (url, callback) { - var path = '/api/' + constants.API_VERSION + '/pods' - - request.get(url + path, function (err, response, body) { - if (err) throw err - callback(JSON.parse(body)) - }) + var pods = { + add: add, + addVideoToFriends: addVideoToFriends, + list: list, + hasFriends: hasFriends, + makeFriends: makeFriends, + quitFriends: quitFriends, + remove: remove, + removeVideoToFriends } - // ----------- Public functions ----------- - - pods.list = function (callback) { - PodsDB.find(function (err, pods_list) { - if (err) { - logger.error('Cannot get the list of the pods.', { error: err }) - return callback(err) - } - - return callback(null, pods_list) - }) - } - - // { url } // TODO: check if the pod is not already a friend - pods.add = function (data, callback) { + function add (data, callback) { var videos = require('./videos') logger.info('Adding pod: %s', data.url) @@ -62,7 +46,7 @@ videos.addRemotes(data.videos) - fs.readFile(utils.certDir + 'peertube.pub', 'utf8', function (err, cert) { + fs.readFile(utils.getCertDir() + 'peertube.pub', 'utf8', function (err, cert) { if (err) { logger.error('Cannot read cert file.', { error: err }) return callback(err) @@ -80,40 +64,38 @@ }) } - pods.remove = function (url, callback) { - var videos = require('./videos') - logger.info('Removing %s pod.', url) - - videos.removeAllRemotesOf(url, function (err) { - if (err) logger.error('Cannot remove all remote videos of %s.', url) - - PodsDB.remove({ url: url }, function (err) { - if (err) return callback(err) - - logger.info('%s pod removed.', url) - callback(null) - }) - }) - } - - pods.addVideoToFriends = function (video) { + function addVideoToFriends (video) { // To avoid duplicates var id = video.name + video.magnetUri poolRequests.addToPoolRequests(id, 'add', video) } - pods.removeVideoToFriends = function (video) { - // To avoid duplicates - var id = video.name + video.magnetUri - poolRequests.addToPoolRequests(id, 'remove', video) + function list (callback) { + PodsDB.find(function (err, pods_list) { + if (err) { + logger.error('Cannot get the list of the pods.', { error: err }) + return callback(err) + } + + return callback(null, pods_list) + }) } - pods.makeFriends = function (callback) { + function hasFriends (callback) { + PodsDB.count(function (err, count) { + if (err) return callback(err) + + var has_friends = (count !== 0) + callback(null, has_friends) + }) + } + + function makeFriends (callback) { var videos = require('./videos') var pods_score = {} logger.info('Make friends!') - fs.readFile(utils.certDir + 'peertube.pub', 'utf8', function (err, cert) { + fs.readFile(utils.getCertDir() + 'peertube.pub', 'utf8', function (err, cert) { if (err) { logger.error('Cannot read public cert.', { error: err }) return callback(err) @@ -188,7 +170,7 @@ function eachRequest (err, response, body, url, pod, callback_each_request) { // We add the pod if it responded correctly with its public certificate if (!err && response.statusCode === 200) { - pods.add({ url: pod.url, publicKey: body.cert, score: constants.FRIEND_BASE_SCORE }, function (err) { + add({ url: pod.url, publicKey: body.cert, score: constants.FRIEND_BASE_SCORE }, function (err) { if (err) logger.error('Error with adding %s pod.', pod.url, { error: err }) videos.addRemotes(body.videos, function (err) { @@ -221,7 +203,7 @@ } } - pods.quitFriends = function (callback) { + function quitFriends (callback) { // Stop pool requests poolRequests.deactivate() // Flush pool requests @@ -261,14 +243,40 @@ }) } - pods.hasFriends = function (callback) { - PodsDB.count(function (err, count) { - if (err) return callback(err) + function remove (url, callback) { + var videos = require('./videos') + logger.info('Removing %s pod.', url) - var has_friends = (count !== 0) - callback(null, has_friends) + videos.removeAllRemotesOf(url, function (err) { + if (err) logger.error('Cannot remove all remote videos of %s.', url) + + PodsDB.remove({ url: url }, function (err) { + if (err) return callback(err) + + logger.info('%s pod removed.', url) + callback(null) + }) }) } + function removeVideoToFriends (video) { + // To avoid duplicates + var id = video.name + video.magnetUri + poolRequests.addToPoolRequests(id, 'remove', video) + } + + // --------------------------------------------------------------------------- + module.exports = pods + + // --------------------------------------------------------------------------- + + function getForeignPodsList (url, callback) { + var path = '/api/' + constants.API_VERSION + '/pods' + + request.get(url + path, function (err, response, body) { + if (err) throw err + callback(JSON.parse(body)) + }) + } })() diff --git a/models/videos.js b/models/videos.js index 626c55819..5711c5657 100644 --- a/models/videos.js +++ b/models/videos.js @@ -11,51 +11,29 @@ var pods = require('./pods') var VideosDB = require('../initializers/database').VideosDB - var videos = {} - var http = config.get('webserver.https') === true ? 'https' : 'http' var host = config.get('webserver.host') var port = config.get('webserver.port') - // ----------- Private functions ----------- - function seedVideo (path, callback) { - logger.info('Seeding %s...', path) - - webtorrent.seed(path, function (torrent) { - logger.info('%s seeded (%s).', path, torrent.magnetURI) - - return callback(null, torrent) - }) + var videos = { + add: add, + addRemotes: addRemotes, + get: get, + list: list, + listOwned: listOwned, + remove: remove, + removeAllRemotes: removeAllRemotes, + removeAllRemotesOf: removeAllRemotesOf, + removeRemotes: removeRemotes, + search: search, + seedAll: seedAll, + uploadDir: uploadDir } // ----------- Public attributes ---------- - videos.uploadDir = __dirname + '/../' + config.get('storage.uploads') + var uploadDir = __dirname + '/../' + config.get('storage.uploads') - // ----------- Public functions ----------- - videos.list = function (callback) { - VideosDB.find(function (err, videos_list) { - if (err) { - logger.error('Cannot get list of the videos.', { error: err }) - return callback(err) - } - - return callback(null, videos_list) - }) - } - - videos.listOwned = function (callback) { - // If namePath is not null this is *our* video - VideosDB.find({ namePath: { $ne: null } }, function (err, videos_list) { - if (err) { - logger.error('Cannot get list of the videos.', { error: err }) - return callback(err) - } - - return callback(null, videos_list) - }) - } - - videos.add = function (data, callback) { + function add (data, callback) { var video_file = data.video var video_data = data.data @@ -89,7 +67,74 @@ }) } - videos.remove = function (id, callback) { + // TODO: avoid doublons + function addRemotes (videos, callback) { + if (callback === undefined) callback = function () {} + + var to_add = [] + + async.each(videos, function (video, callback_each) { + callback_each = dz(callback_each) + logger.debug('Add remote video from pod: %s', video.podUrl) + + var params = { + name: video.name, + namePath: null, + description: video.description, + magnetUri: video.magnetUri, + podUrl: video.podUrl + } + + to_add.push(params) + + callback_each() + }, function () { + VideosDB.create(to_add, function (err, videos) { + if (err) { + logger.error('Cannot insert this remote video.', { error: err }) + return callback(err) + } + + return callback(null, videos) + }) + }) + } + + function get (id, callback) { + VideosDB.findById(id, function (err, video) { + if (err) { + logger.error('Cannot get this video.', { error: err }) + return callback(err) + } + + return callback(null, video) + }) + } + + function list (callback) { + VideosDB.find(function (err, videos_list) { + if (err) { + logger.error('Cannot get list of the videos.', { error: err }) + return callback(err) + } + + return callback(null, videos_list) + }) + } + + function listOwned (callback) { + // If namePath is not null this is *our* video + VideosDB.find({ namePath: { $ne: null } }, function (err, videos_list) { + if (err) { + logger.error('Cannot get list of the videos.', { error: err }) + return callback(err) + } + + return callback(null, videos_list) + }) + } + + function remove (id, callback) { // Maybe the torrent is not seeded, but we catch the error to don't stop the removing process function removeTorrent (magnetUri, callback) { try { @@ -122,7 +167,7 @@ return callback(err) } - fs.unlink(videos.uploadDir + video.namePath, function (err) { + fs.unlink(uploadDir + video.namePath, function (err) { if (err) { logger.error('Cannot remove this video file.', { error: err }) return callback(err) @@ -141,8 +186,24 @@ }) } + function removeAllRemotes (callback) { + VideosDB.remove({ namePath: null }, function (err) { + if (err) return callback(err) + + callback(null) + }) + } + + function removeAllRemotesOf (fromUrl, callback) { + VideosDB.remove({ podUrl: fromUrl }, function (err) { + if (err) return callback(err) + + callback(null) + }) + } + // Use the magnet Uri because the _id field is not the same on different servers - videos.removeRemotes = function (fromUrl, magnetUris, callback) { + function removeRemotes (fromUrl, magnetUris, callback) { if (callback === undefined) callback = function () {} VideosDB.find({ magnetUri: { $in: magnetUris } }, function (err, videos) { @@ -176,68 +237,7 @@ }) } - videos.removeAllRemotes = function (callback) { - VideosDB.remove({ namePath: null }, function (err) { - if (err) return callback(err) - - callback(null) - }) - } - - videos.removeAllRemotesOf = function (fromUrl, callback) { - VideosDB.remove({ podUrl: fromUrl }, function (err) { - if (err) return callback(err) - - callback(null) - }) - } - - // { name, magnetUri, podUrl } - // TODO: avoid doublons - videos.addRemotes = function (videos, callback) { - if (callback === undefined) callback = function () {} - - var to_add = [] - - async.each(videos, function (video, callback_each) { - callback_each = dz(callback_each) - logger.debug('Add remote video from pod: %s', video.podUrl) - - var params = { - name: video.name, - namePath: null, - description: video.description, - magnetUri: video.magnetUri, - podUrl: video.podUrl - } - - to_add.push(params) - - callback_each() - }, function () { - VideosDB.create(to_add, function (err, videos) { - if (err) { - logger.error('Cannot insert this remote video.', { error: err }) - return callback(err) - } - - return callback(null, videos) - }) - }) - } - - videos.get = function (id, callback) { - VideosDB.findById(id, function (err, video) { - if (err) { - logger.error('Cannot get this video.', { error: err }) - return callback(err) - } - - return callback(null, video) - }) - } - - videos.search = function (name, callback) { + function search (name, callback) { VideosDB.find({ name: new RegExp(name) }, function (err, videos) { if (err) { logger.error('Cannot search the videos.', { error: err }) @@ -248,7 +248,7 @@ }) } - videos.seedAll = function (callback) { + function seedAll (callback) { VideosDB.find({ namePath: { $ne: null } }, function (err, videos_list) { if (err) { logger.error('Cannot get list of the videos to seed.', { error: err }) @@ -256,7 +256,7 @@ } async.each(videos_list, function (video, each_callback) { - seedVideo(videos.uploadDir + video.namePath, function (err) { + seedVideo(uploadDir + video.namePath, function (err) { if (err) { logger.error('Cannot seed this video.', { error: err }) return callback(err) @@ -268,5 +268,19 @@ }) } + // --------------------------------------------------------------------------- + module.exports = videos + + // --------------------------------------------------------------------------- + + function seedVideo (path, callback) { + logger.info('Seeding %s...', path) + + webtorrent.seed(path, function (torrent) { + logger.info('%s seeded (%s).', path, torrent.magnetURI) + + return callback(null, torrent) + }) + } })() diff --git a/tests/api/singlePod.js b/tests/api/singlePod.js index ce3ca80f2..7621d766c 100644 --- a/tests/api/singlePod.js +++ b/tests/api/singlePod.js @@ -3,8 +3,8 @@ var async = require('async') var chai = require('chai') - var fs = require('fs') var expect = chai.expect + var fs = require('fs') var webtorrent = require(__dirname + '/../../lib/webTorrentNode') webtorrent.silent = true diff --git a/tests/api/utils.js b/tests/api/utils.js index afb0abb33..a1996b4d7 100644 --- a/tests/api/utils.js +++ b/tests/api/utils.js @@ -6,7 +6,7 @@ var fork = child_process.fork var request = require('supertest') - module.exports = { + var testUtils = { flushTests: flushTests, getFriendsList: getFriendsList, getVideosList: getVideosList, @@ -179,4 +179,8 @@ .expect(201) .end(end) } + + // --------------------------------------------------------------------------- + + module.exports = testUtils })()