]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/controllers/api/videos.js
Server: generate magnet uri on the fly
[github/Chocobozzz/PeerTube.git] / server / controllers / api / videos.js
CommitLineData
9f10b292
C
1'use strict'
2
f0f5567b 3const express = require('express')
558d7c23 4const fs = require('fs')
aaf61f38 5const mongoose = require('mongoose')
f0f5567b 6const multer = require('multer')
558d7c23 7const path = require('path')
1a42c9e2 8const waterfall = require('async/waterfall')
f0f5567b 9
f253b1c1
C
10const constants = require('../../initializers/constants')
11const logger = require('../../helpers/logger')
12const friends = require('../../lib/friends')
13const middlewares = require('../../middlewares')
69b0a27c 14const oAuth = middlewares.oauth
fbf1134e 15const pagination = middlewares.pagination
fc51fde0
C
16const validators = middlewares.validators
17const validatorsPagination = validators.pagination
18const validatorsSort = validators.sort
19const validatorsVideos = validators.videos
46246b5f 20const search = middlewares.search
a877d5ac 21const sort = middlewares.sort
f253b1c1 22const utils = require('../../helpers/utils')
f0f5567b
C
23
24const router = express.Router()
aaf61f38 25const Video = mongoose.model('Video')
9f10b292
C
26
27// multer configuration
f0f5567b 28const storage = multer.diskStorage({
9f10b292 29 destination: function (req, file, cb) {
b3d92510 30 cb(null, constants.CONFIG.STORAGE.VIDEOS_DIR)
9f10b292
C
31 },
32
33 filename: function (req, file, cb) {
f0f5567b 34 let extension = ''
9f10b292
C
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'
bc503c2a
C
38 utils.generateRandomString(16, function (err, randomString) {
39 const fieldname = err ? undefined : randomString
9f10b292
C
40 cb(null, fieldname + '.' + extension)
41 })
42 }
43})
44
8c9c1942 45const reqFiles = multer({ storage: storage }).fields([{ name: 'videofile', maxCount: 1 }])
8c308c2b 46
fbf1134e 47router.get('/',
fc51fde0
C
48 validatorsPagination.pagination,
49 validatorsSort.videosSort,
a877d5ac 50 sort.setVideosSort,
fbf1134e
C
51 pagination.setPagination,
52 listVideos
53)
54router.post('/',
69b0a27c 55 oAuth.authenticate,
fbf1134e 56 reqFiles,
fc51fde0 57 validatorsVideos.videosAdd,
fbf1134e
C
58 addVideo
59)
60router.get('/:id',
fc51fde0 61 validatorsVideos.videosGet,
68ce3ae0 62 getVideo
fbf1134e
C
63)
64router.delete('/:id',
69b0a27c 65 oAuth.authenticate,
fc51fde0 66 validatorsVideos.videosRemove,
fbf1134e
C
67 removeVideo
68)
46246b5f 69router.get('/search/:value',
fc51fde0
C
70 validatorsVideos.videosSearch,
71 validatorsPagination.pagination,
72 validatorsSort.videosSort,
a877d5ac 73 sort.setVideosSort,
fbf1134e 74 pagination.setPagination,
46246b5f 75 search.setVideosSearch,
fbf1134e
C
76 searchVideos
77)
8c308c2b 78
9f10b292 79// ---------------------------------------------------------------------------
c45f7f84 80
9f10b292 81module.exports = router
c45f7f84 82
9f10b292 83// ---------------------------------------------------------------------------
c45f7f84 84
9f10b292 85function addVideo (req, res, next) {
bc503c2a
C
86 const videoFile = req.files.videofile[0]
87 const videoInfos = req.body
9f10b292 88
1a42c9e2 89 waterfall([
558d7c23
C
90 function createVideoObject (callback) {
91 const id = mongoose.Types.ObjectId()
807df9e6 92
807df9e6 93 const videoData = {
558d7c23 94 _id: id,
807df9e6 95 name: videoInfos.name,
558d7c23
C
96 remoteId: null,
97 extname: path.extname(videoFile.filename),
807df9e6 98 description: videoInfos.description,
807df9e6 99 author: res.locals.oauth.token.user.username,
67100f1f 100 duration: videoFile.duration,
be587647 101 tags: videoInfos.tags
807df9e6
C
102 }
103
aaf61f38 104 const video = new Video(videoData)
558d7c23
C
105
106 return callback(null, video)
107 },
108
109 // Set the videoname the same as the MongoDB id
110 function renameVideoFile (video, callback) {
111 const videoDir = constants.CONFIG.STORAGE.VIDEOS_DIR
112 const source = path.join(videoDir, videoFile.filename)
f285faa0 113 const destination = path.join(videoDir, video.getVideoFilename())
558d7c23
C
114
115 fs.rename(source, destination, function (err) {
116 return callback(err, video)
117 })
118 },
119
120 function insertIntoDB (video, callback) {
f285faa0 121 video.save(function (err, video) {
aaf61f38
C
122 // Assert there are only one argument sent to the next function (video)
123 return callback(err, video)
3a8a8b51 124 })
807df9e6
C
125 },
126
aaf61f38
C
127 function sendToFriends (video, callback) {
128 video.toRemoteJSON(function (err, remoteVideo) {
129 if (err) return callback(err)
807df9e6 130
528a9efa
C
131 // Now we'll add the video's meta data to our friends
132 friends.addVideoToFriends(remoteVideo)
807df9e6 133
528a9efa
C
134 return callback(null)
135 })
807df9e6
C
136 }
137
be587647 138 ], function andFinally (err) {
807df9e6
C
139 if (err) {
140 logger.error('Cannot insert the video.')
141 return next(err)
142 }
143
144 // TODO : include Location of the new video -> 201
145 return res.type('json').status(204).end()
9f10b292
C
146 })
147}
8c308c2b 148
68ce3ae0 149function getVideo (req, res, next) {
aaf61f38 150 Video.load(req.params.id, function (err, video) {
9f10b292 151 if (err) return next(err)
8c308c2b 152
aaf61f38 153 if (!video) {
2df82d42 154 return res.type('json').status(204).end()
9f10b292 155 }
8c308c2b 156
aaf61f38 157 res.json(video.toFormatedJSON())
9f10b292
C
158 })
159}
8c308c2b 160
9f10b292 161function listVideos (req, res, next) {
0ff21c1c 162 Video.listForApi(req.query.start, req.query.count, req.query.sort, function (err, videosList, videosTotal) {
9f10b292 163 if (err) return next(err)
c45f7f84 164
aaf61f38 165 res.json(getFormatedVideos(videosList, videosTotal))
9f10b292
C
166 })
167}
c45f7f84 168
9f10b292 169function removeVideo (req, res, next) {
bc503c2a 170 const videoId = req.params.id
8c308c2b 171
1a42c9e2 172 waterfall([
807df9e6 173 function getVideo (callback) {
aaf61f38 174 Video.load(videoId, callback)
807df9e6
C
175 },
176
177 function removeFromDB (video, callback) {
aaf61f38 178 video.remove(function (err) {
807df9e6 179 if (err) return callback(err)
c173e565 180
807df9e6
C
181 return callback(null, video)
182 })
183 },
cbe2f7c3 184
807df9e6
C
185 function sendInformationToFriends (video, callback) {
186 const params = {
187 name: video.name,
558d7c23 188 remoteId: video._id
807df9e6
C
189 }
190
191 friends.removeVideoToFriends(params)
192
193 return callback(null)
194 }
be587647 195 ], function andFinally (err) {
807df9e6
C
196 if (err) {
197 logger.error('Errors when removed the video.', { error: err })
198 return next(err)
199 }
200
201 return res.type('json').status(204).end()
9f10b292
C
202 })
203}
8c308c2b 204
9f10b292 205function searchVideos (req, res, next) {
aaf61f38
C
206 Video.search(req.params.value, req.query.field, req.query.start, req.query.count, req.query.sort,
207 function (err, videosList, videosTotal) {
9f10b292 208 if (err) return next(err)
8c308c2b 209
aaf61f38 210 res.json(getFormatedVideos(videosList, videosTotal))
9f10b292
C
211 })
212}
c173e565 213
9f10b292 214// ---------------------------------------------------------------------------
c173e565 215
aaf61f38 216function getFormatedVideos (videos, videosTotal) {
bc503c2a 217 const formatedVideos = []
2df82d42 218
aaf61f38
C
219 videos.forEach(function (video) {
220 formatedVideos.push(video.toFormatedJSON())
2df82d42
C
221 })
222
68ce3ae0 223 return {
aaf61f38 224 total: videosTotal,
68ce3ae0
C
225 data: formatedVideos
226 }
2df82d42 227}