]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/controllers/api/remote/videos.js
Server: move remote routes in their own directory
[github/Chocobozzz/PeerTube.git] / server / controllers / api / remote / videos.js
1 'use strict'
2
3 const eachSeries = require('async/eachSeries')
4 const express = require('express')
5 const waterfall = require('async/waterfall')
6
7 const db = require('../../../initializers/database')
8 const middlewares = require('../../../middlewares')
9 const secureMiddleware = middlewares.secure
10 const validators = middlewares.validators.remote
11 const logger = require('../../../helpers/logger')
12
13 const router = express.Router()
14
15 router.post('/',
16 validators.signature,
17 secureMiddleware.checkSignature,
18 validators.remoteVideos,
19 remoteVideos
20 )
21
22 // ---------------------------------------------------------------------------
23
24 module.exports = router
25
26 // ---------------------------------------------------------------------------
27
28 function remoteVideos (req, res, next) {
29 const requests = req.body.data
30 const fromPod = res.locals.secure.pod
31
32 // We need to process in the same order to keep consistency
33 // TODO: optimization
34 eachSeries(requests, function (request, callbackEach) {
35 const videoData = request.data
36
37 switch (request.type) {
38 case 'add':
39 addRemoteVideo(videoData, fromPod, callbackEach)
40 break
41
42 case 'update':
43 updateRemoteVideo(videoData, fromPod, callbackEach)
44 break
45
46 case 'remove':
47 removeRemoteVideo(videoData, fromPod, callbackEach)
48 break
49
50 default:
51 logger.error('Unkown remote request type %s.', request.type)
52 }
53 }, function (err) {
54 if (err) logger.error('Error managing remote videos.', { error: err })
55 })
56
57 // We don't need to keep the other pod waiting
58 return res.type('json').status(204).end()
59 }
60
61 function addRemoteVideo (videoToCreateData, fromPod, finalCallback) {
62 logger.debug('Adding remote video "%s".', videoToCreateData.name)
63
64 waterfall([
65
66 function startTransaction (callback) {
67 db.sequelize.transaction().asCallback(function (err, t) {
68 return callback(err, t)
69 })
70 },
71
72 function findOrCreateAuthor (t, callback) {
73 const name = videoToCreateData.author
74 const podId = fromPod.id
75 // This author is from another pod so we do not associate a user
76 const userId = null
77
78 db.Author.findOrCreateAuthor(name, podId, userId, t, function (err, authorInstance) {
79 return callback(err, t, authorInstance)
80 })
81 },
82
83 function findOrCreateTags (t, author, callback) {
84 const tags = videoToCreateData.tags
85
86 db.Tag.findOrCreateTags(tags, t, function (err, tagInstances) {
87 return callback(err, t, author, tagInstances)
88 })
89 },
90
91 function createVideoObject (t, author, tagInstances, callback) {
92 const videoData = {
93 name: videoToCreateData.name,
94 remoteId: videoToCreateData.remoteId,
95 extname: videoToCreateData.extname,
96 infoHash: videoToCreateData.infoHash,
97 description: videoToCreateData.description,
98 authorId: author.id,
99 duration: videoToCreateData.duration,
100 createdAt: videoToCreateData.createdAt,
101 updatedAt: videoToCreateData.updatedAt
102 }
103
104 const video = db.Video.build(videoData)
105
106 return callback(null, t, tagInstances, video)
107 },
108
109 function generateThumbnail (t, tagInstances, video, callback) {
110 db.Video.generateThumbnailFromData(video, videoToCreateData.thumbnailData, function (err) {
111 if (err) {
112 logger.error('Cannot generate thumbnail from data.', { error: err })
113 return callback(err)
114 }
115
116 return callback(err, t, tagInstances, video)
117 })
118 },
119
120 function insertVideoIntoDB (t, tagInstances, video, callback) {
121 const options = {
122 transaction: t
123 }
124
125 video.save(options).asCallback(function (err, videoCreated) {
126 return callback(err, t, tagInstances, videoCreated)
127 })
128 },
129
130 function associateTagsToVideo (t, tagInstances, video, callback) {
131 const options = { transaction: t }
132
133 video.setTags(tagInstances, options).asCallback(function (err) {
134 return callback(err, t)
135 })
136 }
137
138 ], function (err, t) {
139 if (err) {
140 logger.error('Cannot insert the remote video.')
141
142 // Abort transaction?
143 if (t) t.rollback()
144
145 return finalCallback(err)
146 }
147
148 // Commit transaction
149 t.commit()
150
151 return finalCallback()
152 })
153 }
154
155 function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
156 logger.debug('Updating remote video "%s".', videoAttributesToUpdate.name)
157
158 waterfall([
159
160 function startTransaction (callback) {
161 db.sequelize.transaction().asCallback(function (err, t) {
162 return callback(err, t)
163 })
164 },
165
166 function findVideo (t, callback) {
167 db.Video.loadByHostAndRemoteId(fromPod.host, videoAttributesToUpdate.remoteId, function (err, videoInstance) {
168 if (err || !videoInstance) {
169 logger.error('Cannot load video from host and remote id.', { error: err.message })
170 return callback(err)
171 }
172
173 return callback(null, t, videoInstance)
174 })
175 },
176
177 function findOrCreateTags (t, videoInstance, callback) {
178 const tags = videoAttributesToUpdate.tags
179
180 db.Tag.findOrCreateTags(tags, t, function (err, tagInstances) {
181 return callback(err, t, videoInstance, tagInstances)
182 })
183 },
184
185 function updateVideoIntoDB (t, videoInstance, tagInstances, callback) {
186 const options = { transaction: t }
187
188 videoInstance.set('name', videoAttributesToUpdate.name)
189 videoInstance.set('description', videoAttributesToUpdate.description)
190 videoInstance.set('infoHash', videoAttributesToUpdate.infoHash)
191 videoInstance.set('duration', videoAttributesToUpdate.duration)
192 videoInstance.set('createdAt', videoAttributesToUpdate.createdAt)
193 videoInstance.set('updatedAt', videoAttributesToUpdate.updatedAt)
194 videoInstance.set('extname', videoAttributesToUpdate.extname)
195
196 videoInstance.save(options).asCallback(function (err) {
197 return callback(err, t, videoInstance, tagInstances)
198 })
199 },
200
201 function associateTagsToVideo (t, videoInstance, tagInstances, callback) {
202 const options = { transaction: t }
203
204 videoInstance.setTags(tagInstances, options).asCallback(function (err) {
205 return callback(err, t)
206 })
207 }
208
209 ], function (err, t) {
210 if (err) {
211 logger.error('Cannot update the remote video.')
212
213 // Abort transaction?
214 if (t) t.rollback()
215
216 return finalCallback(err)
217 }
218
219 // Commit transaction
220 t.commit()
221
222 return finalCallback()
223 })
224 }
225
226 function removeRemoteVideo (videoToRemoveData, fromPod, callback) {
227 // We need the instance because we have to remove some other stuffs (thumbnail etc)
228 db.Video.loadByHostAndRemoteId(fromPod.host, videoToRemoveData.remoteId, function (err, video) {
229 if (err || !video) {
230 logger.error('Cannot load video from host and remote id.', { error: err.message })
231 return callback(err)
232 }
233
234 logger.debug('Removing remote video %s.', video.remoteId)
235 video.destroy().asCallback(callback)
236 })
237 }