]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/controllers/api/remote/videos.js
Server: add licence video attribute
[github/Chocobozzz/PeerTube.git] / server / controllers / api / remote / videos.js
index 79b503d4d0692217bc022d7a7f8e37eb65d9eaf0..a3e1189c749b29e788587b241301483a765e8150 100644 (file)
@@ -11,6 +11,7 @@ const secureMiddleware = middlewares.secure
 const videosValidators = middlewares.validators.remote.videos
 const signatureValidators = middlewares.validators.remote.signature
 const logger = require('../../../helpers/logger')
+const friends = require('../../../lib/friends')
 const databaseUtils = require('../../../helpers/database-utils')
 
 const ENDPOINT_ACTIONS = constants.REQUEST_ENDPOINT_ACTIONS[constants.REQUEST_ENDPOINTS.VIDEOS]
@@ -38,6 +39,13 @@ router.post('/qadu',
   remoteVideosQadu
 )
 
+router.post('/events',
+  signatureValidators.signature,
+  secureMiddleware.checkSignature,
+  videosValidators.remoteEventsVideos,
+  remoteVideosEvents
+)
+
 // ---------------------------------------------------------------------------
 
 module.exports = router
@@ -84,6 +92,100 @@ function remoteVideosQadu (req, res, next) {
   return res.type('json').status(204).end()
 }
 
+function remoteVideosEvents (req, res, next) {
+  const requests = req.body.data
+  const fromPod = res.locals.secure.pod
+
+  eachSeries(requests, function (request, callbackEach) {
+    const eventData = request.data
+
+    processVideosEventsRetryWrapper(eventData, fromPod, callbackEach)
+  }, function (err) {
+    if (err) logger.error('Error managing remote videos.', { error: err })
+  })
+
+  return res.type('json').status(204).end()
+}
+
+function processVideosEventsRetryWrapper (eventData, fromPod, finalCallback) {
+  const options = {
+    arguments: [ eventData, fromPod ],
+    errorMessage: 'Cannot process videos events with many retries.'
+  }
+
+  databaseUtils.retryTransactionWrapper(processVideosEvents, options, finalCallback)
+}
+
+function processVideosEvents (eventData, fromPod, finalCallback) {
+  waterfall([
+    databaseUtils.startSerializableTransaction,
+
+    function findVideo (t, callback) {
+      fetchOwnedVideo(eventData.remoteId, function (err, videoInstance) {
+        return callback(err, t, videoInstance)
+      })
+    },
+
+    function updateVideoIntoDB (t, videoInstance, callback) {
+      const options = { transaction: t }
+
+      let columnToUpdate
+      let qaduType
+
+      switch (eventData.eventType) {
+        case constants.REQUEST_VIDEO_EVENT_TYPES.VIEWS:
+          columnToUpdate = 'views'
+          qaduType = constants.REQUEST_VIDEO_QADU_TYPES.VIEWS
+          break
+
+        case constants.REQUEST_VIDEO_EVENT_TYPES.LIKES:
+          columnToUpdate = 'likes'
+          qaduType = constants.REQUEST_VIDEO_QADU_TYPES.LIKES
+          break
+
+        case constants.REQUEST_VIDEO_EVENT_TYPES.DISLIKES:
+          columnToUpdate = 'dislikes'
+          qaduType = constants.REQUEST_VIDEO_QADU_TYPES.DISLIKES
+          break
+
+        default:
+          return callback(new Error('Unknown video event type.'))
+      }
+
+      const query = {}
+      query[columnToUpdate] = eventData.count
+
+      videoInstance.increment(query, options).asCallback(function (err) {
+        return callback(err, t, videoInstance, qaduType)
+      })
+    },
+
+    function sendQaduToFriends (t, videoInstance, qaduType, callback) {
+      const qadusParams = [
+        {
+          videoId: videoInstance.id,
+          type: qaduType
+        }
+      ]
+
+      friends.quickAndDirtyUpdatesVideoToFriends(qadusParams, t, function (err) {
+        return callback(err, t)
+      })
+    },
+
+    databaseUtils.commitTransaction
+
+  ], function (err, t) {
+    if (err) {
+      logger.debug('Cannot process a video event.', { error: err })
+      return databaseUtils.rollbackTransaction(err, t, finalCallback)
+    }
+
+    logger.info('Remote video event processed for video %s.', eventData.remoteId)
+    return finalCallback(null)
+  })
+}
+
 function quickAndDirtyUpdateVideoRetryWrapper (videoData, fromPod, finalCallback) {
   const options = {
     arguments: [ videoData, fromPod ],
@@ -94,11 +196,13 @@ function quickAndDirtyUpdateVideoRetryWrapper (videoData, fromPod, finalCallback
 }
 
 function quickAndDirtyUpdateVideo (videoData, fromPod, finalCallback) {
+  let videoName
+
   waterfall([
     databaseUtils.startSerializableTransaction,
 
     function findVideo (t, callback) {
-      fetchVideo(fromPod.host, videoData.remoteId, function (err, videoInstance) {
+      fetchRemoteVideo(fromPod.host, videoData.remoteId, function (err, videoInstance) {
         return callback(err, t, videoInstance)
       })
     },
@@ -106,6 +210,8 @@ function quickAndDirtyUpdateVideo (videoData, fromPod, finalCallback) {
     function updateVideoIntoDB (t, videoInstance, callback) {
       const options = { transaction: t }
 
+      videoName = videoInstance.name
+
       if (videoData.views) {
         videoInstance.set('views', videoData.views)
       }
@@ -131,7 +237,7 @@ function quickAndDirtyUpdateVideo (videoData, fromPod, finalCallback) {
       return databaseUtils.rollbackTransaction(err, t, finalCallback)
     }
 
-    logger.info('Remote video %s quick and dirty updated', videoData.name)
+    logger.info('Remote video %s quick and dirty updated', videoName)
     return finalCallback(null)
   })
 }
@@ -188,12 +294,17 @@ function addRemoteVideo (videoToCreateData, fromPod, finalCallback) {
         remoteId: videoToCreateData.remoteId,
         extname: videoToCreateData.extname,
         infoHash: videoToCreateData.infoHash,
+        category: videoToCreateData.category,
+        licence: videoToCreateData.licence,
         description: videoToCreateData.description,
         authorId: author.id,
         duration: videoToCreateData.duration,
         createdAt: videoToCreateData.createdAt,
         // FIXME: updatedAt does not seems to be considered by Sequelize
-        updatedAt: videoToCreateData.updatedAt
+        updatedAt: videoToCreateData.updatedAt,
+        views: videoToCreateData.views,
+        likes: videoToCreateData.likes,
+        dislikes: videoToCreateData.dislikes
       }
 
       const video = db.Video.build(videoData)
@@ -264,7 +375,7 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
     databaseUtils.startSerializableTransaction,
 
     function findVideo (t, callback) {
-      fetchVideo(fromPod.host, videoAttributesToUpdate.remoteId, function (err, videoInstance) {
+      fetchRemoteVideo(fromPod.host, videoAttributesToUpdate.remoteId, function (err, videoInstance) {
         return callback(err, t, videoInstance)
       })
     },
@@ -281,12 +392,17 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
       const options = { transaction: t }
 
       videoInstance.set('name', videoAttributesToUpdate.name)
+      videoInstance.set('category', videoAttributesToUpdate.category)
+      videoInstance.set('licence', videoAttributesToUpdate.licence)
       videoInstance.set('description', videoAttributesToUpdate.description)
       videoInstance.set('infoHash', videoAttributesToUpdate.infoHash)
       videoInstance.set('duration', videoAttributesToUpdate.duration)
       videoInstance.set('createdAt', videoAttributesToUpdate.createdAt)
       videoInstance.set('updatedAt', videoAttributesToUpdate.updatedAt)
       videoInstance.set('extname', videoAttributesToUpdate.extname)
+      videoInstance.set('views', videoAttributesToUpdate.views)
+      videoInstance.set('likes', videoAttributesToUpdate.likes)
+      videoInstance.set('dislikes', videoAttributesToUpdate.dislikes)
 
       videoInstance.save(options).asCallback(function (err) {
         return callback(err, t, videoInstance, tagInstances)
@@ -317,7 +433,7 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
 
 function removeRemoteVideo (videoToRemoveData, fromPod, callback) {
   // We need the instance because we have to remove some other stuffs (thumbnail etc)
-  fetchVideo(fromPod.host, videoToRemoveData.remoteId, function (err, video) {
+  fetchRemoteVideo(fromPod.host, videoToRemoveData.remoteId, function (err, video) {
     // Do not return the error, continue the process
     if (err) return callback(null)
 
@@ -334,7 +450,7 @@ function removeRemoteVideo (videoToRemoveData, fromPod, callback) {
 }
 
 function reportAbuseRemoteVideo (reportData, fromPod, callback) {
-  db.Video.load(reportData.videoRemoteId, function (err, video) {
+  fetchOwnedVideo(reportData.videoRemoteId, function (err, video) {
     if (err || !video) {
       if (!err) err = new Error('video not found')
 
@@ -362,7 +478,20 @@ function reportAbuseRemoteVideo (reportData, fromPod, callback) {
   })
 }
 
-function fetchVideo (podHost, remoteId, callback) {
+function fetchOwnedVideo (id, callback) {
+  db.Video.load(id, function (err, video) {
+    if (err || !video) {
+      if (!err) err = new Error('video not found')
+
+      logger.error('Cannot load owned video from id.', { error: err, id })
+      return callback(err)
+    }
+
+    return callback(null, video)
+  })
+}
+
+function fetchRemoteVideo (podHost, remoteId, callback) {
   db.Video.loadByHostAndRemoteId(podHost, remoteId, function (err, video) {
     if (err || !video) {
       if (!err) err = new Error('video not found')