From cbe2f7c34822b1bd3b1f8c691f79f0c29cf21f07 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 10 May 2016 21:19:24 +0200 Subject: [PATCH] Refractoring and add thumbnails support (without tests) --- .gitignore | 1 + config/default.yaml | 1 + config/test-1.yaml | 1 + config/test-2.yaml | 1 + config/test-3.yaml | 1 + config/test-4.yaml | 1 + config/test-5.yaml | 1 + config/test-6.yaml | 1 + server.js | 4 + server/controllers/api/v1/pods.js | 27 +++-- server/controllers/api/v1/remoteVideos.js | 32 ++++-- server/controllers/api/v1/videos.js | 82 +++++++++----- server/helpers/utils.js | 13 ++- server/initializers/constants.js | 10 +- server/lib/friends.js | 39 ++++--- server/lib/requestsScheduler.js | 12 ++- server/lib/videos.js | 104 +++++++++++++++++- server/models/videos.js | 126 ++++++---------------- server/tests/api/multiplePods.js | 13 ++- 19 files changed, 310 insertions(+), 160 deletions(-) diff --git a/.gitignore b/.gitignore index 6c0165c41..9d9b1978b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ test6/ public/stylesheets/global.css public/stylesheets/vendor uploads +thumbnails diff --git a/config/default.yaml b/config/default.yaml index be161640c..87b72aa3b 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -16,6 +16,7 @@ storage: certs: 'certs/' uploads: 'uploads/' logs: 'logs/' + thumbnails: 'thumbnails/' network: friends: [] diff --git a/config/test-1.yaml b/config/test-1.yaml index 031e4893f..3afcb1b04 100644 --- a/config/test-1.yaml +++ b/config/test-1.yaml @@ -13,6 +13,7 @@ storage: certs: 'test1/certs/' uploads: 'test1/uploads/' logs: 'test1/logs/' + thumbnails: 'test1/thumbnails/' network: friends: diff --git a/config/test-2.yaml b/config/test-2.yaml index 8a2a80158..51cc186eb 100644 --- a/config/test-2.yaml +++ b/config/test-2.yaml @@ -13,6 +13,7 @@ storage: certs: 'test2/certs/' uploads: 'test2/uploads/' logs: 'test2/logs/' + thumbnails: 'test2/thumbnails/' network: friends: diff --git a/config/test-3.yaml b/config/test-3.yaml index 3e906d125..7ef01ba4d 100644 --- a/config/test-3.yaml +++ b/config/test-3.yaml @@ -13,6 +13,7 @@ storage: certs: 'test3/certs/' uploads: 'test3/uploads/' logs: 'test3/logs/' + thumbnails: 'test3/thumbnails/' network: friends: diff --git a/config/test-4.yaml b/config/test-4.yaml index 6db8a5d03..a4d3bb164 100644 --- a/config/test-4.yaml +++ b/config/test-4.yaml @@ -13,6 +13,7 @@ storage: certs: 'test4/certs/' uploads: 'test4/uploads/' logs: 'test4/logs/' + thumbnails: 'test4/thumbnails/' network: friends: diff --git a/config/test-5.yaml b/config/test-5.yaml index 7b3f18d35..0435c17fe 100644 --- a/config/test-5.yaml +++ b/config/test-5.yaml @@ -13,6 +13,7 @@ storage: certs: 'test5/certs/' uploads: 'test5/uploads/' logs: 'test5/logs/' + thumbnails: 'test5/thumbnails/' network: friends: diff --git a/config/test-6.yaml b/config/test-6.yaml index 0c7675cc2..b7dbd4bdd 100644 --- a/config/test-6.yaml +++ b/config/test-6.yaml @@ -13,6 +13,7 @@ storage: certs: 'test6/certs/' uploads: 'test6/uploads/' logs: 'test6/logs/' + thumbnails: 'test6/thumbnails/' network: friends: diff --git a/server.js b/server.js index 204cc146f..ef26ea773 100644 --- a/server.js +++ b/server.js @@ -75,6 +75,10 @@ app.use('/app/*', function (req, res, next) { res.sendStatus(404) }) +// Thumbnails path for express +const thumbnails_physical_path = path.join(__dirname, config.get('storage.thumbnails')) +app.use(constants.THUMBNAILS_STATIC_PATH, express.static(thumbnails_physical_path, { maxAge: 0 })) + // Client application app.use('/*', function (req, res, next) { res.sendFile(path.join(__dirname, 'client/index.html')) diff --git a/server/controllers/api/v1/pods.js b/server/controllers/api/v1/pods.js index dbe1a7372..d08b7860d 100644 --- a/server/controllers/api/v1/pods.js +++ b/server/controllers/api/v1/pods.js @@ -1,17 +1,16 @@ 'use strict' const express = require('express') -const fs = require('fs') const logger = require('../../../helpers/logger') const friends = require('../../../lib/friends') const middleware = require('../../../middlewares') const cacheMiddleware = middleware.cache -const peertubeCrypto = require('../../../helpers/peertubeCrypto') const Pods = require('../../../models/pods') const reqValidator = middleware.reqValidators.pods const secureMiddleware = middleware.secure const secureRequest = middleware.reqValidators.remote.secureRequest +const videos = require('../../../lib/videos') const Videos = require('../../../models/videos') const router = express.Router() @@ -34,9 +33,12 @@ function addPods (req, res, next) { Pods.add(informations, function (err) { if (err) return next(err) - Videos.addRemotes(informations.videos) + // Create the remote videos from the new pod + videos.createRemoteVideos(informations.videos, function (err) { + if (err) logger.error('Cannot create remote videos.', { error: err }) + }) - fs.readFile(peertubeCrypto.getCertDir() + 'peertube.pub', 'utf8', function (err, cert) { + friends.getMyCertificate(function (err, cert) { if (err) { logger.error('Cannot read cert file.') return next(err) @@ -75,11 +77,20 @@ function removePods (req, res, next) { Pods.remove(url, function (err) { if (err) return next(err) - Videos.removeAllRemotesOf(url, function (err) { - if (err) logger.error('Cannot remove all remote videos of %s.', url) - else logger.info('%s pod removed.', url) + Videos.listFromUrl(url, function (err, videos_list) { + if (err) { + logger.error('Cannot list videos from url.', { error: err }) + next(err) + } - res.type('json').status(204).end() + videos.removeRemoteVideos(videos_list, function (err) { + if (err) { + logger.error('Cannot remove remote videos.', { error: err }) + next(err) + } + + res.type('json').status(204).end() + }) }) }) } diff --git a/server/controllers/api/v1/remoteVideos.js b/server/controllers/api/v1/remoteVideos.js index 5e9e71fdd..8ff212b7f 100644 --- a/server/controllers/api/v1/remoteVideos.js +++ b/server/controllers/api/v1/remoteVideos.js @@ -7,7 +7,9 @@ const middleware = require('../../../middlewares') const secureMiddleware = middleware.secure const cacheMiddleware = middleware.cache const reqValidator = middleware.reqValidators.remote -const videos = require('../../../models/videos') +const logger = require('../../../helpers/logger') +const Videos = require('../../../models/videos') +const videos = require('../../../lib/videos') const router = express.Router() @@ -34,20 +36,34 @@ module.exports = router // --------------------------------------------------------------------------- function addRemoteVideos (req, res, next) { - videos.addRemotes(req.body.data, function (err, videos) { - if (err) return next(err) + const videos_to_create = req.body.data + videos.createRemoteVideos(videos_to_create, function (err, remote_videos) { + if (err) { + logger.error('Cannot create remote videos.', { error: err }) + return next(err) + } - res.json(videos) + res.type('json').status(201).end() }) } function removeRemoteVideo (req, res, next) { - const url = req.body.signature.url + const fromUrl = req.body.signature.url const magnetUris = map(req.body.data, 'magnetUri') - videos.removeRemotesOfByMagnetUris(url, magnetUris, function (err) { - if (err) return next(err) + Videos.listFromUrlAndMagnets(fromUrl, magnetUris, function (err, videos_list) { + if (err) { + logger.error('Cannot list videos from url and magnets.', { error: err }) + return next(err) + } - res.type('json').status(204).end() + videos.removeRemoteVideos(videos_list, function (err) { + if (err) { + logger.error('Cannot remove remote videos.', { error: err }) + return next(err) + } + + res.type('json').status(204).end() + }) }) } diff --git a/server/controllers/api/v1/videos.js b/server/controllers/api/v1/videos.js index 7fdc50e52..98f17ac6c 100644 --- a/server/controllers/api/v1/videos.js +++ b/server/controllers/api/v1/videos.js @@ -1,16 +1,19 @@ 'use strict' const config = require('config') -const crypto = require('crypto') const express = require('express') +const fs = require('fs') +const path = require('path') const multer = require('multer') +const constants = require('../../../initializers/constants') const logger = require('../../../helpers/logger') const friends = require('../../../lib/friends') const middleware = require('../../../middlewares') const oAuth2 = require('../../../middlewares/oauth2') const cacheMiddleware = middleware.cache const reqValidator = middleware.reqValidators.videos +const utils = require('../../../helpers/utils') const Videos = require('../../../models/videos') // model const videos = require('../../../lib/videos') const webtorrent = require('../../../lib/webtorrent') @@ -29,14 +32,15 @@ const storage = multer.diskStorage({ 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) { - const fieldname = err ? undefined : raw.toString('hex') + utils.generateRandomString(16, function (err, random_string) { + const fieldname = err ? undefined : random_string cb(null, fieldname + '.' + extension) }) } }) const reqFiles = multer({ storage: storage }).fields([{ name: 'videofile', maxCount: 1 }]) +const thumbnailsDir = path.join(__dirname, '..', '..', '..', '..', config.get('storage.thumbnails')) router.get('/', cacheMiddleware.cache(false), listVideos) router.post('/', oAuth2.authenticate, reqFiles, reqValidator.videosAdd, cacheMiddleware.cache(false), addVideo) @@ -63,31 +67,50 @@ function addVideo (req, res, next) { videos.getVideoDuration(video_file.path, function (err, duration) { if (err) { // TODO: unseed the video - logger.error('Cannot retrieve metadata of the file') + logger.error('Cannot retrieve metadata of the file.') return next(err) } - const video_data = { - name: video_infos.name, - namePath: video_file.filename, - description: video_infos.description, - magnetUri: torrent.magnetURI, - author: res.locals.oauth.token.user.username, - duration: duration - } - - Videos.add(video_data, function (err) { + videos.getVideoThumbnail(video_file.path, function (err, thumbnail_name) { if (err) { - // TODO unseed the video - logger.error('Cannot insert this video in the database.') + // TODO: unseed the video + logger.error('Cannot make a thumbnail of the video file.') return next(err) } - // Now we'll add the video's meta data to our friends - friends.addVideoToFriends(video_data) + const video_data = { + name: video_infos.name, + namePath: video_file.filename, + description: video_infos.description, + magnetUri: torrent.magnetURI, + author: res.locals.oauth.token.user.username, + duration: duration, + thumbnail: thumbnail_name + } - // TODO : include Location of the new video -> 201 - res.type('json').status(204).end() + Videos.add(video_data, function (err) { + if (err) { + // TODO unseed the video + logger.error('Cannot insert this video in the database.') + return next(err) + } + + fs.readFile(thumbnailsDir + thumbnail_name, function (err, data) { + if (err) { + // TODO: remove video? + logger.error('Cannot read the thumbnail of the video') + return next(err) + } + + // Set the image in base64 + video_data.thumbnail_base64 = new Buffer(data).toString('base64') + // Now we'll add the video's meta data to our friends + friends.addVideoToFriends(video_data) + + // TODO : include Location of the new video -> 201 + res.type('json').status(204).end() + }) + }) }) }) }) @@ -123,13 +146,17 @@ function removeVideo (req, res, next) { Videos.removeOwned(req.params.id, function (err) { if (err) return next(err) - const params = { - name: video.name, - magnetUri: video.magnetUri - } + videos.removeVideosDataFromDisk([ video ], function (err) { + if (err) logger.error('Cannot remove video data from disk.', { video: video }) + + const params = { + name: video.name, + magnetUri: video.magnetUri + } - friends.removeVideoToFriends(params) - res.type('json').status(204).end() + friends.removeVideoToFriends(params) + res.type('json').status(204).end() + }) }) }) }) @@ -154,7 +181,8 @@ function getFormatedVideo (video_obj) { isLocal: videos.getVideoState(video_obj).owned, magnetUri: video_obj.magnetUri, author: video_obj.author, - duration: video_obj.duration + duration: video_obj.duration, + thumbnail_path: constants.THUMBNAILS_STATIC_PATH + '/' + video_obj.thumbnail } return formated_video diff --git a/server/helpers/utils.js b/server/helpers/utils.js index 1f7839673..9d4d51c46 100644 --- a/server/helpers/utils.js +++ b/server/helpers/utils.js @@ -1,9 +1,20 @@ 'use strict' +const crypto = require('crypto') + const logger = require('./logger') const utils = { - cleanForExit: cleanForExit + cleanForExit: cleanForExit, + generateRandomString: generateRandomString +} + +function generateRandomString (size, callback) { + crypto.pseudoRandomBytes(size, function (err, raw) { + if (err) return callback(err) + + callback(null, raw.toString('hex')) + }) } function cleanForExit (webtorrent_process) { diff --git a/server/initializers/constants.js b/server/initializers/constants.js index dc08805b9..bb141456a 100644 --- a/server/initializers/constants.js +++ b/server/initializers/constants.js @@ -18,6 +18,12 @@ const PODS_SCORE = { // Number of retries we make for the make retry requests (to friends...) let REQUEST_RETRIES = 10 +// Videos thumbnail size +const THUMBNAILS_SIZE = '200x110' + +// Path for access to thumbnails with express router +const THUMBNAILS_STATIC_PATH = '/static/thumbnails' + // Special constants for a test instance if (isTestInstance() === true) { FRIEND_BASE_SCORE = 20 @@ -32,7 +38,9 @@ module.exports = { FRIEND_BASE_SCORE: FRIEND_BASE_SCORE, INTERVAL: INTERVAL, PODS_SCORE: PODS_SCORE, - REQUEST_RETRIES: REQUEST_RETRIES + REQUEST_RETRIES: REQUEST_RETRIES, + THUMBNAILS_SIZE: THUMBNAILS_SIZE, + THUMBNAILS_STATIC_PATH: THUMBNAILS_STATIC_PATH } // --------------------------------------------------------------------------- diff --git a/server/lib/friends.js b/server/lib/friends.js index 9a2c5c06e..3b8a52060 100644 --- a/server/lib/friends.js +++ b/server/lib/friends.js @@ -11,6 +11,7 @@ const peertubeCrypto = require('../helpers/peertubeCrypto') const Pods = require('../models/pods') const requestsScheduler = require('../lib/requestsScheduler') const requests = require('../helpers/requests') +const videos = require('../lib/videos') const Videos = require('../models/videos') const http = config.get('webserver.https') ? 'https' : 'http' @@ -20,6 +21,7 @@ const port = config.get('webserver.port') const pods = { addVideoToFriends: addVideoToFriends, hasFriends: hasFriends, + getMyCertificate: getMyCertificate, makeFriends: makeFriends, quitFriends: quitFriends, removeVideoToFriends: removeVideoToFriends @@ -42,11 +44,15 @@ function hasFriends (callback) { }) } +function getMyCertificate (callback) { + fs.readFile(peertubeCrypto.getCertDir() + 'peertube.pub', 'utf8', callback) +} + function makeFriends (callback) { const pods_score = {} logger.info('Make friends!') - fs.readFile(peertubeCrypto.getCertDir() + 'peertube.pub', 'utf8', function (err, cert) { + getMyCertificate(function (err, cert) { if (err) { logger.error('Cannot read public cert.') return callback(err) @@ -54,8 +60,8 @@ function makeFriends (callback) { const urls = config.get('network.friends') - async.each(urls, function (url, callback) { - computeForeignPodsList(url, pods_score, callback) + async.each(urls, function (url, callback_each) { + computeForeignPodsList(url, pods_score, callback_each) }, function (err) { if (err) return callback(err) @@ -96,11 +102,18 @@ function quitFriends (callback) { logger.info('Broke friends, so sad :(') - Videos.removeAllRemotes(function (err) { + Videos.listFromRemotes(function (err, videos_list) { if (err) return callback(err) - logger.info('Removed all remote videos.') - callback(null) + videos.removeRemoteVideos(videos_list, function (err) { + if (err) { + logger.error('Cannot remove remote videos.', { error: err }) + return callback(err) + } + + logger.info('Removed all remote videos.') + callback(null) + }) }) }) }) @@ -127,16 +140,14 @@ function computeForeignPodsList (url, pods_score, callback) { if (err) return callback(err) if (foreign_pods_list.length === 0) return callback() - async.each(foreign_pods_list, function (foreign_pod, callback_each) { + foreign_pods_list.forEach(function (foreign_pod) { const foreign_url = foreign_pod.url if (pods_score[foreign_url]) pods_score[foreign_url]++ else pods_score[foreign_url] = 1 - - callback_each() - }, function () { - callback() }) + + callback() }) } @@ -194,13 +205,15 @@ function makeRequestsToWinningPods (cert, pods_list, callback) { logger.error('Error with adding %s pod.', pod.url, { error: err }) return callback_each_request() } - - Videos.addRemotes(body.videos, function (err) { + console.log('hihi') + videos.createRemoteVideos(body.videos, function (err) { if (err) { logger.error('Error with adding videos of pod.', pod.url, { error: err }) return callback_each_request() } + console.log('kik') + logger.debug('Adding remote videos from %s.', pod.url, { videos: body.videos }) return callback_each_request() }) diff --git a/server/lib/requestsScheduler.js b/server/lib/requestsScheduler.js index 2c5474e51..4953f6a91 100644 --- a/server/lib/requestsScheduler.js +++ b/server/lib/requestsScheduler.js @@ -8,6 +8,7 @@ const logger = require('../helpers/logger') const Pods = require('../models/pods') const Requests = require('../models/requests') const requests = require('../helpers/requests') +const videos = require('../lib/videos') const Videos = require('../models/videos') let timer = null @@ -99,7 +100,7 @@ function makeRequest (type, requests_to_make, callback) { requests.makeMultipleRetryRequest(params, pods, callbackEachPodFinished, callbackAllPodsFinished) function callbackEachPodFinished (err, response, body, url, pod, callback_each_pod_finished) { - if (err || (response.statusCode !== 200 && response.statusCode !== 204)) { + if (err || (response.statusCode !== 200 && response.statusCode !== 201 && 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 { @@ -187,12 +188,13 @@ function removeBadPods () { const urls = map(pods, 'url') const ids = map(pods, '_id') - Videos.removeAllRemotesOf(urls, function (err, r) { + Videos.listFromUrls(urls, function (err, videos_list) { if (err) { - logger.error('Cannot remove videos from a pod that we removing.', { error: err }) + logger.error('Cannot list videos urls.', { error: err, urls: urls }) } else { - const videos_removed = r.result.n - logger.info('Removed %d videos.', videos_removed) + videos.removeRemoteVideos(videos_list, function (err) { + if (err) logger.error('Cannot remove remote videos.', { error: err }) + }) } Pods.removeAllByIds(ids, function (err, r) { diff --git a/server/lib/videos.js b/server/lib/videos.js index 43d6c6b99..b3497743a 100644 --- a/server/lib/videos.js +++ b/server/lib/videos.js @@ -3,21 +3,39 @@ const async = require('async') const config = require('config') const ffmpeg = require('fluent-ffmpeg') +const fs = require('fs') +const map = require('lodash/map') const pathUtils = require('path') -const webtorrent = require('../lib/webtorrent') +const constants = require('../initializers/constants') const logger = require('../helpers/logger') +const utils = require('../helpers/utils') const Videos = require('../models/videos') +const webtorrent = require('../lib/webtorrent') const uploadDir = pathUtils.join(__dirname, '..', '..', config.get('storage.uploads')) +const thumbnailsDir = pathUtils.join(__dirname, '..', '..', config.get('storage.thumbnails')) const videos = { + createRemoteVideos: createRemoteVideos, getVideoDuration: getVideoDuration, getVideoState: getVideoState, + getVideoThumbnail: getVideoThumbnail, + removeVideosDataFromDisk: removeVideosDataFromDisk, + removeRemoteVideos: removeRemoteVideos, seed: seed, seedAllExisting: seedAllExisting } +function createRemoteVideos (videos, callback) { + // Create the remote videos from the new pod + createRemoteVideoObjects(videos, function (err, remote_videos) { + if (err) return callback(err) + + Videos.addRemotes(remote_videos, callback) + }) +} + function getVideoDuration (video_path, callback) { ffmpeg.ffprobe(video_path, function (err, metadata) { if (err) return callback(err) @@ -36,6 +54,51 @@ function getVideoState (video) { return { exist: exist, owned: owned } } +function getVideoThumbnail (video_path, callback) { + const filename = pathUtils.basename(video_path) + '.jpg' + ffmpeg(video_path) + .on('error', callback) + .on('end', function () { + callback(null, filename) + }) + .thumbnail({ + count: 1, + folder: thumbnailsDir, + size: constants.THUMBNAILS_SIZE, + filename: filename + }) +} + +// Remove video datas from disk (video file, thumbnail...) +function removeVideosDataFromDisk (videos, callback) { + async.each(videos, function (video, callback_each) { + fs.unlink(thumbnailsDir + video.thumbnail, function (err) { + if (err) logger.error('Cannot remove the video thumbnail') + + if (getVideoState(video).owned === true) { + fs.unlink(uploadDir + video.namePath, function (err) { + if (err) { + logger.error('Cannot remove this video file.') + return callback_each(err) + } + + callback_each(null) + }) + } else { + callback_each(null) + } + }) + }, callback) +} + +function removeRemoteVideos (videos, callback) { + Videos.removeByIds(map(videos, '_id'), function (err) { + if (err) return callback(err) + + removeVideosDataFromDisk(videos, callback) + }) +} + function seed (path, callback) { logger.info('Seeding %s...', path) @@ -69,3 +132,42 @@ function seedAllExisting (callback) { // --------------------------------------------------------------------------- module.exports = videos + +// --------------------------------------------------------------------------- + +function createRemoteVideoObjects (videos, callback) { + const remote_videos = [] + + async.each(videos, function (video, callback_each) { + // Creating the thumbnail for this remote video + utils.generateRandomString(16, function (err, random_string) { + if (err) return callback_each(err) + + const thumbnail_name = random_string + '.jpg' + createThumbnailFromBase64(thumbnail_name, video.thumbnail_base64, function (err) { + if (err) return callback_each(err) + + const params = { + name: video.name, + description: video.description, + magnetUri: video.magnetUri, + podUrl: video.podUrl, + duration: video.duration, + thumbnail: thumbnail_name + } + remote_videos.push(params) + + callback_each(null) + }) + }) + }, + function (err) { + if (err) return callback(err) + + callback(null, remote_videos) + }) +} + +function createThumbnailFromBase64 (thumbnail_name, data, callback) { + fs.writeFile(thumbnailsDir + thumbnail_name, data, { encoding: 'base64' }, callback) +} diff --git a/server/models/videos.js b/server/models/videos.js index e02158be7..eedb6eb58 100644 --- a/server/models/videos.js +++ b/server/models/videos.js @@ -1,18 +1,13 @@ 'use strict' -const async = require('async') const config = require('config') -const dz = require('dezalgo') -const fs = require('fs') const mongoose = require('mongoose') -const path = require('path') const logger = require('../helpers/logger') const http = config.get('webserver.https') === true ? 'https' : 'http' const host = config.get('webserver.host') const port = config.get('webserver.port') -const uploadDir = path.join(__dirname, '..', '..', config.get('storage.uploads')) // --------------------------------------------------------------------------- @@ -23,7 +18,8 @@ const videosSchema = mongoose.Schema({ magnetUri: String, podUrl: String, author: String, - duration: Number + duration: Number, + thumbnail: String }) const VideosDB = mongoose.model('videos', videosSchema) @@ -34,11 +30,13 @@ const Videos = { addRemotes: addRemotes, get: get, list: list, + listFromUrl: listFromUrl, + listFromUrls: listFromUrls, + listFromUrlAndMagnets: listFromUrlAndMagnets, + listFromRemotes: listFromRemotes, listOwned: listOwned, removeOwned: removeOwned, - removeAllRemotes: removeAllRemotes, - removeAllRemotesOf: removeAllRemotesOf, - removeRemotesOfByMagnetUris: removeRemotesOfByMagnetUris, + removeByIds: removeByIds, search: search } @@ -58,38 +56,13 @@ function add (video, callback) { }) } -// TODO: avoid doublons function addRemotes (videos, callback) { - if (!callback) callback = function () {} - - const to_add = [] - - async.each(videos, function (video, callback_each) { - callback_each = dz(callback_each) - logger.debug('Add remote video from pod: %s', video.podUrl) - - const params = { - name: video.name, - namePath: null, - description: video.description, - magnetUri: video.magnetUri, - podUrl: video.podUrl, - duration: video.duration - } - - to_add.push(params) - - callback_each() - }, function () { - VideosDB.create(to_add, function (err, videos) { - if (err) { - logger.error('Cannot insert this remote video.') - return callback(err) - } - - return callback(null, videos) - }) + videos.forEach(function (video) { + // Ensure they are remote videos + video.namePath = null }) + + VideosDB.create(videos, callback) } function get (id, callback) { @@ -114,6 +87,22 @@ function list (callback) { }) } +function listFromUrl (fromUrl, callback) { + VideosDB.find({ podUrl: fromUrl }, callback) +} + +function listFromUrls (fromUrls, callback) { + VideosDB.find({ podUrl: { $in: fromUrls } }, callback) +} + +function listFromUrlAndMagnets (fromUrl, magnets, callback) { + VideosDB.find({ podUrl: fromUrl, magnetUri: { $in: magnets } }, callback) +} + +function listFromRemotes (callback) { + VideosDB.find({ namePath: null }, callback) +} + function listOwned (callback) { // If namePath is not null this is *our* video VideosDB.find({ namePath: { $ne: null } }, function (err, videos_list) { @@ -126,65 +115,14 @@ function listOwned (callback) { }) } +// Return the video in the callback function removeOwned (id, callback) { - VideosDB.findByIdAndRemove(id, function (err, video) { - if (err) { - logger.error('Cannot remove the torrent.') - return callback(err) - } - - fs.unlink(uploadDir + video.namePath, function (err) { - if (err) { - logger.error('Cannot remove this video file.') - return callback(err) - } - - callback(null) - }) - }) -} - -function removeAllRemotes (callback) { - VideosDB.remove({ namePath: null }, callback) -} - -function removeAllRemotesOf (fromUrl, callback) { - VideosDB.remove({ podUrl: fromUrl }, callback) + VideosDB.findByIdAndRemove(id, callback) } // Use the magnet Uri because the _id field is not the same on different servers -function removeRemotesOfByMagnetUris (fromUrl, magnetUris, callback) { - if (callback === undefined) callback = function () {} - - VideosDB.find({ magnetUri: { $in: magnetUris } }, function (err, videos) { - if (err || !videos) { - logger.error('Cannot find the torrent URI of these remote videos.') - return callback(err) - } - - const to_remove = [] - async.each(videos, function (video, callback_async) { - callback_async = dz(callback_async) - - if (video.podUrl !== fromUrl) { - logger.error('The pod %s has not the rights on the video of %s.', fromUrl, video.podUrl) - } else { - to_remove.push(video._id) - } - - callback_async() - }, function () { - VideosDB.remove({ _id: { $in: to_remove } }, function (err) { - if (err) { - logger.error('Cannot remove the remote videos.') - return callback(err) - } - - logger.info('Removed remote videos from %s.', fromUrl) - callback(null) - }) - }) - }) +function removeByIds (ids, callback) { + VideosDB.remove({ _id: { $in: ids } }, callback) } function search (name, callback) { diff --git a/server/tests/api/multiplePods.js b/server/tests/api/multiplePods.js index adc99f714..4a4532a0f 100644 --- a/server/tests/api/multiplePods.js +++ b/server/tests/api/multiplePods.js @@ -193,14 +193,23 @@ describe('Test multiple pods', function () { expect(videos).to.be.an('array') expect(videos.length).to.equal(4) - const video1 = videos[2] + // We not sure about the order of the two last uploads + let video1 = null + let video2 = null + if (videos[2].name === 'my super name for pod 3') { + video1 = videos[2] + video2 = videos[3] + } else { + video1 = videos[3] + video2 = videos[2] + } + expect(video1.name).to.equal('my super name for pod 3') expect(video1.description).to.equal('my super description for pod 3') expect(video1.podUrl).to.equal('http://localhost:9003') expect(video1.magnetUri).to.exist expect(video1.duration).to.equal(5) - const video2 = videos[3] expect(video2.name).to.equal('my super name for pod 3-2') expect(video2.description).to.equal('my super description for pod 3-2') expect(video2.podUrl).to.equal('http://localhost:9003') -- 2.41.0