]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/controllers/api/remote.js
Client: upgrade angular dep'
[github/Chocobozzz/PeerTube.git] / server / controllers / api / remote.js
CommitLineData
528a9efa
C
1'use strict'
2
1a42c9e2
C
3const each = require('async/each')
4const eachSeries = require('async/eachSeries')
528a9efa 5const express = require('express')
feb4bdfd 6const waterfall = require('async/waterfall')
528a9efa 7
feb4bdfd 8const db = require('../../initializers/database')
f253b1c1 9const middlewares = require('../../middlewares')
528a9efa 10const secureMiddleware = middlewares.secure
fc51fde0 11const validators = middlewares.validators.remote
f253b1c1 12const logger = require('../../helpers/logger')
528a9efa
C
13
14const router = express.Router()
15
16router.post('/videos',
fc51fde0 17 validators.signature,
0eb78d53 18 secureMiddleware.checkSignature,
fc51fde0 19 validators.remoteVideos,
528a9efa
C
20 remoteVideos
21)
22
23// ---------------------------------------------------------------------------
24
25module.exports = router
26
27// ---------------------------------------------------------------------------
28
29function remoteVideos (req, res, next) {
30 const requests = req.body.data
49abbbbe 31 const fromHost = req.body.signature.host
528a9efa
C
32
33 // We need to process in the same order to keep consistency
34 // TODO: optimization
1a42c9e2 35 eachSeries(requests, function (request, callbackEach) {
aaf61f38 36 const videoData = request.data
528a9efa
C
37
38 if (request.type === 'add') {
437cf8b5 39 addRemoteVideo(videoData, fromHost, callbackEach)
528a9efa 40 } else if (request.type === 'remove') {
49abbbbe 41 removeRemoteVideo(videoData, fromHost, callbackEach)
6666aad4
C
42 } else {
43 logger.error('Unkown remote request type %s.', request.type)
528a9efa 44 }
aaf61f38
C
45 }, function (err) {
46 if (err) logger.error('Error managing remote videos.', { error: err })
528a9efa
C
47 })
48
49 // We don't need to keep the other pod waiting
50 return res.type('json').status(204).end()
51}
52
7920c273 53function addRemoteVideo (videoToCreateData, fromHost, finalCallback) {
a078c155 54 logger.debug('Adding remote video "%s".', videoToCreateData.name)
6666aad4 55
feb4bdfd
C
56 waterfall([
57
7920c273
C
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) {
feb4bdfd
C
65 const query = {
66 where: {
67 host: fromHost
68 },
69 defaults: {
70 host: fromHost
7920c273
C
71 },
72 transaction: t
feb4bdfd
C
73 }
74
75 db.Pod.findOrCreate(query).asCallback(function (err, result) {
76 // [ instance, wasCreated ]
7920c273 77 return callback(err, t, result[0])
feb4bdfd
C
78 })
79 },
80
7920c273 81 function findOrCreateAuthor (t, pod, callback) {
feb4bdfd
C
82 const username = videoToCreateData.author
83
84 const query = {
85 where: {
86 name: username,
4712081f
C
87 podId: pod.id,
88 userId: null
feb4bdfd
C
89 },
90 defaults: {
91 name: username,
4712081f
C
92 podId: pod.id,
93 userId: null
7920c273
C
94 },
95 transaction: t
feb4bdfd
C
96 }
97
98 db.Author.findOrCreate(query).asCallback(function (err, result) {
99 // [ instance, wasCreated ]
7920c273 100 return callback(err, t, result[0])
feb4bdfd
C
101 })
102 },
103
7920c273
C
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) {
feb4bdfd
C
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,
124648d7
C
140 duration: videoToCreateData.duration,
141 createdAt: videoToCreateData.createdAt
feb4bdfd
C
142 }
143
144 const video = db.Video.build(videoData)
145
7920c273 146 return callback(null, t, tagInstances, video)
feb4bdfd
C
147 },
148
7920c273 149 function generateThumbnail (t, tagInstances, video, callback) {
4d324488 150 db.Video.generateThumbnailFromData(video, videoToCreateData.thumbnailData, function (err) {
feb4bdfd 151 if (err) {
4d324488 152 logger.error('Cannot generate thumbnail from data.', { error: err })
feb4bdfd
C
153 return callback(err)
154 }
155
7920c273 156 return callback(err, t, tagInstances, video)
feb4bdfd
C
157 })
158 },
159
7920c273
C
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 })
c77fa067
C
176 }
177
7920c273
C
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 })
528a9efa
C
193}
194
49abbbbe 195function removeRemoteVideo (videoToRemoveData, fromHost, callback) {
feb4bdfd
C
196 // TODO: use bulkDestroy?
197
528a9efa 198 // We need the list because we have to remove some other stuffs (thumbnail etc)
feb4bdfd 199 db.Video.listByHostAndRemoteId(fromHost, videoToRemoveData.remoteId, function (err, videosList) {
528a9efa 200 if (err) {
feb4bdfd 201 logger.error('Cannot list videos from host and remote id.', { error: err.message })
aaf61f38 202 return callback(err)
528a9efa
C
203 }
204
6666aad4 205 if (videosList.length === 0) {
feb4bdfd 206 logger.error('No remote video was found for this pod.', { remoteId: videoToRemoveData.remoteId, podHost: fromHost })
6666aad4
C
207 }
208
1a42c9e2 209 each(videosList, function (video, callbackEach) {
feb4bdfd 210 logger.debug('Removing remote video %s.', video.remoteId)
6666aad4 211
feb4bdfd 212 video.destroy().asCallback(callbackEach)
aaf61f38 213 }, callback)
528a9efa
C
214 })
215}