Refractoring and add thumbnails support (without tests)
authorChocobozzz <florian.bigard@gmail.com>
Tue, 10 May 2016 19:19:24 +0000 (21:19 +0200)
committerChocobozzz <florian.bigard@gmail.com>
Tue, 10 May 2016 19:19:24 +0000 (21:19 +0200)
19 files changed:
.gitignore
config/default.yaml
config/test-1.yaml
config/test-2.yaml
config/test-3.yaml
config/test-4.yaml
config/test-5.yaml
config/test-6.yaml
server.js
server/controllers/api/v1/pods.js
server/controllers/api/v1/remoteVideos.js
server/controllers/api/v1/videos.js
server/helpers/utils.js
server/initializers/constants.js
server/lib/friends.js
server/lib/requestsScheduler.js
server/lib/videos.js
server/models/videos.js
server/tests/api/multiplePods.js

index 6c0165c4157cd06d995e751ec7618a49220437ec..9d9b1978b223334627d32747dd0ebf3d629b8abc 100644 (file)
@@ -11,3 +11,4 @@ test6/
 public/stylesheets/global.css
 public/stylesheets/vendor
 uploads
+thumbnails
index be161640ca4c2a6af450b6008ee83be4b95a9774..87b72aa3b40ad015d593482b84aa45a0773f25e0 100644 (file)
@@ -16,6 +16,7 @@ storage:
   certs: 'certs/'
   uploads: 'uploads/'
   logs: 'logs/'
+  thumbnails: 'thumbnails/'
 
 network:
   friends: []
index 031e4893fcfb6d451bc8bdcd8593558f947a3b7b..3afcb1b043904d45cb754d4dff1ebef72ed27baa 100644 (file)
@@ -13,6 +13,7 @@ storage:
   certs: 'test1/certs/'
   uploads: 'test1/uploads/'
   logs: 'test1/logs/'
+  thumbnails: 'test1/thumbnails/'
 
 network:
   friends:
index 8a2a80158f593b4eb7c9743100d278968869607a..51cc186eb422f1d7b525eb218ad34e1ce2cbc450 100644 (file)
@@ -13,6 +13,7 @@ storage:
   certs: 'test2/certs/'
   uploads: 'test2/uploads/'
   logs: 'test2/logs/'
+  thumbnails: 'test2/thumbnails/'
 
 network:
   friends:
index 3e906d1250cf699a70861d702c7c90dc5a53ca87..7ef01ba4da759d5b2f80ca3829284c64627e4ac2 100644 (file)
@@ -13,6 +13,7 @@ storage:
   certs: 'test3/certs/'
   uploads: 'test3/uploads/'
   logs: 'test3/logs/'
+  thumbnails: 'test3/thumbnails/'
 
 network:
   friends:
index 6db8a5d033bbb9191fdce9c4b60ced989b8b2054..a4d3bb164f5ca946220918df3cea8cf2f9613e64 100644 (file)
@@ -13,6 +13,7 @@ storage:
   certs: 'test4/certs/'
   uploads: 'test4/uploads/'
   logs: 'test4/logs/'
+  thumbnails: 'test4/thumbnails/'
 
 network:
   friends:
index 7b3f18d35883f51cf88c61ad1736d85803130093..0435c17fee64af11a13300c85b92abdee9ff2ac4 100644 (file)
@@ -13,6 +13,7 @@ storage:
   certs: 'test5/certs/'
   uploads: 'test5/uploads/'
   logs: 'test5/logs/'
+  thumbnails: 'test5/thumbnails/'
 
 network:
   friends:
index 0c7675cc212a8b806f89ceb2c3646c1438488d75..b7dbd4bdd1cef9d51a32ce576f11a5d2960f52f6 100644 (file)
@@ -13,6 +13,7 @@ storage:
   certs: 'test6/certs/'
   uploads: 'test6/uploads/'
   logs: 'test6/logs/'
+  thumbnails: 'test6/thumbnails/'
 
 network:
   friends:
index 204cc146f3a1222ea7d2089fba13a64eb3005842..ef26ea773d391483a3ad514381a22e8b103ba89f 100644 (file)
--- 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'))
index dbe1a737253b25c8cba52e13337adfae7557b53f..d08b7860d74b0d90bc502769dc556e4cc9e4abee 100644 (file)
@@ -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()
+      })
     })
   })
 }
index 5e9e71fdd4386fd48dd7137c81b078169c07494e..8ff212b7f06b2a258bb3c2255a2de2ee6189699e 100644 (file)
@@ -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()
+    })
   })
 }
index 7fdc50e5239d742ecd33d086237bc54afc8c018e..98f17ac6c7e07cc8d2135770c0b8d3f5a0ef8331 100644 (file)
@@ -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
index 1f7839673a1795e94fb738193310bbfe4930abf9..9d4d51c46197dc6e35a8bce2bff7de3c75d968e2 100644 (file)
@@ -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) {
index dc08805b929f4c0fc8880d512c406c012463fe08..bb141456aba2919d75e11dbd5a0dbdeb2d908833 100644 (file)
@@ -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
 }
 
 // ---------------------------------------------------------------------------
index 9a2c5c06e6687c7f4a2ebb4e73223ff5b2d0529a..3b8a52060f5aac9b1994597ad038b294cd9bb917 100644 (file)
@@ -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()
             })
index 2c5474e51204ace54c6d376dfd303d7a2c9501b1..4953f6a91388441832c1783428ec7f665abe207b 100644 (file)
@@ -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) {
index 43d6c6b9992d6a46a8796787f53295a654fbdca7..b3497743abcaba741db6cee8e137c88fc93c120b 100644 (file)
@@ -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)
+}
index e02158be78a3d3c3b50b1522c2cc06d5e11cde81..eedb6eb587b493c5dd075d9e160d953e26830cd8 100644 (file)
@@ -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) {
index adc99f7145a4860822933f72e76b1153680483bb..4a4532a0fc4cd04739bb0be738f4306da16d0df9 100644 (file)
@@ -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')