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