]>
git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/controllers/api/videos.js
3 const express
= require('express')
4 const fs
= require('fs')
5 const multer
= require('multer')
6 const path
= require('path')
7 const waterfall
= require('async/waterfall')
9 const constants
= require('../../initializers/constants')
10 const db
= require('../../initializers/database')
11 const logger
= require('../../helpers/logger')
12 const friends
= require('../../lib/friends')
13 const middlewares
= require('../../middlewares')
14 const admin
= middlewares
.admin
15 const oAuth
= middlewares
.oauth
16 const pagination
= middlewares
.pagination
17 const validators
= middlewares
.validators
18 const validatorsPagination
= validators
.pagination
19 const validatorsSort
= validators
.sort
20 const validatorsVideos
= validators
.videos
21 const search
= middlewares
.search
22 const sort
= middlewares
.sort
23 const utils
= require('../../helpers/utils')
25 const router
= express
.Router()
27 // multer configuration
28 const storage
= multer
.diskStorage({
29 destination: function (req
, file
, cb
) {
30 cb(null, constants
.CONFIG
.STORAGE
.VIDEOS_DIR
)
33 filename: function (req
, file
, cb
) {
35 if (file
.mimetype
=== 'video/webm') extension
= 'webm'
36 else if (file
.mimetype
=== 'video/mp4') extension
= 'mp4'
37 else if (file
.mimetype
=== 'video/ogg') extension
= 'ogv'
38 utils
.generateRandomString(16, function (err
, randomString
) {
39 const fieldname
= err
? undefined : randomString
40 cb(null, fieldname
+ '.' + extension
)
45 const reqFiles
= multer({ storage: storage
}).fields([{ name: 'videofile', maxCount: 1 }])
50 validatorsPagination
.pagination
,
51 validatorsSort
.videoAbusesSort
,
52 sort
.setVideoAbusesSort
,
53 pagination
.setPagination
,
56 router
.post('/:id/abuse',
58 validatorsVideos
.videoAbuseReport
,
63 validatorsPagination
.pagination
,
64 validatorsSort
.videosSort
,
66 pagination
.setPagination
,
72 validatorsVideos
.videosUpdate
,
78 validatorsVideos
.videosAdd
,
82 validatorsVideos
.videosGet
,
87 validatorsVideos
.videosRemove
,
90 router
.get('/search/:value',
91 validatorsVideos
.videosSearch
,
92 validatorsPagination
.pagination
,
93 validatorsSort
.videosSort
,
95 pagination
.setPagination
,
96 search
.setVideosSearch
,
100 // ---------------------------------------------------------------------------
102 module
.exports
= router
104 // ---------------------------------------------------------------------------
106 function addVideo (req
, res
, next
) {
107 const videoFile
= req
.files
.videofile
[0]
108 const videoInfos
= req
.body
112 function startTransaction (callback
) {
113 db
.sequelize
.transaction().asCallback(function (err
, t
) {
114 return callback(err
, t
)
118 function findOrCreateAuthor (t
, callback
) {
119 const user
= res
.locals
.oauth
.token
.User
121 const name
= user
.username
122 // null because it is OUR pod
124 const userId
= user
.id
126 db
.Author
.findOrCreateAuthor(name
, podId
, userId
, t
, function (err
, authorInstance
) {
127 return callback(err
, t
, authorInstance
)
131 function findOrCreateTags (t
, author
, callback
) {
132 const tags
= videoInfos
.tags
134 db
.Tag
.findOrCreateTags(tags
, t
, function (err
, tagInstances
) {
135 return callback(err
, t
, author
, tagInstances
)
139 function createVideoObject (t
, author
, tagInstances
, callback
) {
141 name: videoInfos
.name
,
143 extname: path
.extname(videoFile
.filename
),
144 description: videoInfos
.description
,
145 duration: videoFile
.duration
,
149 const video
= db
.Video
.build(videoData
)
151 return callback(null, t
, author
, tagInstances
, video
)
154 // Set the videoname the same as the id
155 function renameVideoFile (t
, author
, tagInstances
, video
, callback
) {
156 const videoDir
= constants
.CONFIG
.STORAGE
.VIDEOS_DIR
157 const source
= path
.join(videoDir
, videoFile
.filename
)
158 const destination
= path
.join(videoDir
, video
.getVideoFilename())
160 fs
.rename(source
, destination
, function (err
) {
161 return callback(err
, t
, author
, tagInstances
, video
)
165 function insertVideoIntoDB (t
, author
, tagInstances
, video
, callback
) {
166 const options
= { transaction: t
}
168 // Add tags association
169 video
.save(options
).asCallback(function (err
, videoCreated
) {
170 if (err
) return callback(err
)
172 // Do not forget to add Author informations to the created video
173 videoCreated
.Author
= author
175 return callback(err
, t
, tagInstances
, videoCreated
)
179 function associateTagsToVideo (t
, tagInstances
, video
, callback
) {
180 const options
= { transaction: t
}
182 video
.setTags(tagInstances
, options
).asCallback(function (err
) {
183 video
.Tags
= tagInstances
185 return callback(err
, t
, video
)
189 function sendToFriends (t
, video
, callback
) {
190 video
.toAddRemoteJSON(function (err
, remoteVideo
) {
191 if (err
) return callback(err
)
193 // Now we'll add the video's meta data to our friends
194 friends
.addVideoToFriends(remoteVideo
)
196 return callback(null, t
)
200 ], function andFinally (err
, t
) {
202 logger
.error('Cannot insert the video.')
204 // Abort transaction?
210 // Commit transaction
213 // TODO : include Location of the new video -> 201
214 return res
.type('json').status(204).end()
218 function updateVideo (req
, res
, next
) {
219 const videoInstance
= res
.locals
.video
220 const videoInfosToUpdate
= req
.body
224 function startTransaction (callback
) {
225 db
.sequelize
.transaction().asCallback(function (err
, t
) {
226 return callback(err
, t
)
230 function findOrCreateTags (t
, callback
) {
231 if (videoInfosToUpdate
.tags
) {
232 db
.Tag
.findOrCreateTags(videoInfosToUpdate
.tags
, t
, function (err
, tagInstances
) {
233 return callback(err
, t
, tagInstances
)
236 return callback(null, t
, null)
240 function updateVideoIntoDB (t
, tagInstances
, callback
) {
241 const options
= { transaction: t
}
243 if (videoInfosToUpdate
.name
) videoInstance
.set('name', videoInfosToUpdate
.name
)
244 if (videoInfosToUpdate
.description
) videoInstance
.set('description', videoInfosToUpdate
.description
)
246 // Add tags association
247 videoInstance
.save(options
).asCallback(function (err
) {
248 return callback(err
, t
, tagInstances
)
252 function associateTagsToVideo (t
, tagInstances
, callback
) {
254 const options
= { transaction: t
}
256 videoInstance
.setTags(tagInstances
, options
).asCallback(function (err
) {
257 videoInstance
.Tags
= tagInstances
259 return callback(err
, t
)
262 return callback(null, t
)
266 function sendToFriends (t
, callback
) {
267 const json
= videoInstance
.toUpdateRemoteJSON()
269 // Now we'll update the video's meta data to our friends
270 friends
.updateVideoToFriends(json
)
272 return callback(null, t
)
275 ], function andFinally (err
, t
) {
277 logger
.error('Cannot insert the video.')
279 // Abort transaction?
285 // Commit transaction
288 // TODO : include Location of the new video -> 201
289 return res
.type('json').status(204).end()
293 function getVideo (req
, res
, next
) {
294 const videoInstance
= res
.locals
.video
295 res
.json(videoInstance
.toFormatedJSON())
298 function listVideos (req
, res
, next
) {
299 db
.Video
.listForApi(req
.query
.start
, req
.query
.count
, req
.query
.sort
, function (err
, videosList
, videosTotal
) {
300 if (err
) return next(err
)
302 res
.json(utils
.getFormatedObjects(videosList
, videosTotal
))
306 function removeVideo (req
, res
, next
) {
307 const videoInstance
= res
.locals
.video
309 videoInstance
.destroy().asCallback(function (err
) {
311 logger
.error('Errors when removed the video.', { error: err
})
315 return res
.type('json').status(204).end()
319 function searchVideos (req
, res
, next
) {
320 db
.Video
.searchAndPopulateAuthorAndPodAndTags(
321 req
.params
.value
, req
.query
.field
, req
.query
.start
, req
.query
.count
, req
.query
.sort
,
322 function (err
, videosList
, videosTotal
) {
323 if (err
) return next(err
)
325 res
.json(utils
.getFormatedObjects(videosList
, videosTotal
))
330 function listVideoAbuses (req
, res
, next
) {
331 db
.VideoAbuse
.listForApi(req
.query
.start
, req
.query
.count
, req
.query
.sort
, function (err
, abusesList
, abusesTotal
) {
332 if (err
) return next(err
)
334 res
.json(utils
.getFormatedObjects(abusesList
, abusesTotal
))
338 function reportVideoAbuse (req
, res
, next
) {
339 const videoInstance
= res
.locals
.video
340 const reporterUsername
= res
.locals
.oauth
.token
.User
.username
344 reason: req
.body
.reason
,
345 videoId: videoInstance
.id
,
346 reporterPodId: null // This is our pod that reported this abuse
349 db
.VideoAbuse
.create(abuse
).asCallback(function (err
) {
350 if (err
) return next(err
)
352 // We send the information to the destination pod
353 if (videoInstance
.isOwned() === false) {
356 reportReason: abuse
.reason
,
357 videoRemoteId: videoInstance
.remoteId
360 friends
.reportAbuseVideoToFriend(reportData
, videoInstance
)
363 return res
.type('json').status(204).end()