]>
Commit | Line | Data |
---|---|---|
9f10b292 C |
1 | 'use strict' |
2 | ||
f0f5567b | 3 | const config = require('config') |
f0f5567b | 4 | const express = require('express') |
cbe2f7c3 C |
5 | const fs = require('fs') |
6 | const path = require('path') | |
f0f5567b C |
7 | const multer = require('multer') |
8 | ||
cbe2f7c3 | 9 | const constants = require('../../../initializers/constants') |
f0f5567b C |
10 | const logger = require('../../../helpers/logger') |
11 | const friends = require('../../../lib/friends') | |
b3b92647 C |
12 | const middlewares = require('../../../middlewares') |
13 | const oAuth2 = middlewares.oauth2 | |
14 | const reqValidator = middlewares.reqValidators.videos | |
cbe2f7c3 | 15 | const utils = require('../../../helpers/utils') |
f0f5567b C |
16 | const Videos = require('../../../models/videos') // model |
17 | const videos = require('../../../lib/videos') | |
18 | const webtorrent = require('../../../lib/webtorrent') | |
19 | ||
20 | const router = express.Router() | |
21 | const uploads = config.get('storage.uploads') | |
9f10b292 C |
22 | |
23 | // multer configuration | |
f0f5567b | 24 | const storage = multer.diskStorage({ |
9f10b292 C |
25 | destination: function (req, file, cb) { |
26 | cb(null, uploads) | |
27 | }, | |
28 | ||
29 | filename: function (req, file, cb) { | |
f0f5567b | 30 | let extension = '' |
9f10b292 C |
31 | if (file.mimetype === 'video/webm') extension = 'webm' |
32 | else if (file.mimetype === 'video/mp4') extension = 'mp4' | |
33 | else if (file.mimetype === 'video/ogg') extension = 'ogv' | |
bc503c2a C |
34 | utils.generateRandomString(16, function (err, randomString) { |
35 | const fieldname = err ? undefined : randomString | |
9f10b292 C |
36 | cb(null, fieldname + '.' + extension) |
37 | }) | |
38 | } | |
39 | }) | |
40 | ||
8c9c1942 | 41 | const reqFiles = multer({ storage: storage }).fields([{ name: 'videofile', maxCount: 1 }]) |
cbe2f7c3 | 42 | const thumbnailsDir = path.join(__dirname, '..', '..', '..', '..', config.get('storage.thumbnails')) |
8c308c2b | 43 | |
5dda52c9 C |
44 | router.get('/', listVideos) |
45 | router.post('/', oAuth2.authenticate, reqFiles, reqValidator.videosAdd, addVideo) | |
46 | router.get('/:id', reqValidator.videosGet, getVideos) | |
47 | router.delete('/:id', oAuth2.authenticate, reqValidator.videosRemove, removeVideo) | |
48 | router.get('/search/:name', reqValidator.videosSearch, searchVideos) | |
8c308c2b | 49 | |
9f10b292 | 50 | // --------------------------------------------------------------------------- |
c45f7f84 | 51 | |
9f10b292 | 52 | module.exports = router |
c45f7f84 | 53 | |
9f10b292 | 54 | // --------------------------------------------------------------------------- |
c45f7f84 | 55 | |
9f10b292 | 56 | function addVideo (req, res, next) { |
bc503c2a C |
57 | const videoFile = req.files.videofile[0] |
58 | const videoInfos = req.body | |
9f10b292 | 59 | |
bc503c2a | 60 | videos.seed(videoFile.path, function (err, torrent) { |
9f10b292 C |
61 | if (err) { |
62 | logger.error('Cannot seed this video.') | |
63 | return next(err) | |
64 | } | |
8c308c2b | 65 | |
bc503c2a | 66 | videos.getVideoDuration(videoFile.path, function (err, duration) { |
c173e565 | 67 | if (err) { |
3a8a8b51 | 68 | // TODO: unseed the video |
cbe2f7c3 | 69 | logger.error('Cannot retrieve metadata of the file.') |
c173e565 C |
70 | return next(err) |
71 | } | |
72 | ||
bc503c2a | 73 | videos.getVideoThumbnail(videoFile.path, function (err, thumbnailName) { |
3a8a8b51 | 74 | if (err) { |
cbe2f7c3 C |
75 | // TODO: unseed the video |
76 | logger.error('Cannot make a thumbnail of the video file.') | |
3a8a8b51 C |
77 | return next(err) |
78 | } | |
79 | ||
bc503c2a C |
80 | const videoData = { |
81 | name: videoInfos.name, | |
82 | namePath: videoFile.filename, | |
83 | description: videoInfos.description, | |
cbe2f7c3 C |
84 | magnetUri: torrent.magnetURI, |
85 | author: res.locals.oauth.token.user.username, | |
86 | duration: duration, | |
bc503c2a | 87 | thumbnail: thumbnailName |
cbe2f7c3 | 88 | } |
3a8a8b51 | 89 | |
bc503c2a | 90 | Videos.add(videoData, function (err) { |
cbe2f7c3 C |
91 | if (err) { |
92 | // TODO unseed the video | |
93 | logger.error('Cannot insert this video in the database.') | |
94 | return next(err) | |
95 | } | |
96 | ||
bc503c2a | 97 | fs.readFile(thumbnailsDir + thumbnailName, function (err, data) { |
cbe2f7c3 C |
98 | if (err) { |
99 | // TODO: remove video? | |
100 | logger.error('Cannot read the thumbnail of the video') | |
101 | return next(err) | |
102 | } | |
103 | ||
104 | // Set the image in base64 | |
bc503c2a | 105 | videoData.thumbnailBase64 = new Buffer(data).toString('base64') |
cbe2f7c3 | 106 | // Now we'll add the video's meta data to our friends |
bc503c2a | 107 | friends.addVideoToFriends(videoData) |
cbe2f7c3 C |
108 | |
109 | // TODO : include Location of the new video -> 201 | |
110 | res.type('json').status(204).end() | |
111 | }) | |
112 | }) | |
3a8a8b51 | 113 | }) |
8c308c2b | 114 | }) |
9f10b292 C |
115 | }) |
116 | } | |
8c308c2b | 117 | |
9f10b292 | 118 | function getVideos (req, res, next) { |
bc503c2a | 119 | Videos.get(req.params.id, function (err, videoObj) { |
9f10b292 | 120 | if (err) return next(err) |
8c308c2b | 121 | |
bc503c2a | 122 | const state = videos.getVideoState(videoObj) |
2df82d42 C |
123 | if (state.exist === false) { |
124 | return res.type('json').status(204).end() | |
9f10b292 | 125 | } |
8c308c2b | 126 | |
bc503c2a | 127 | res.json(getFormatedVideo(videoObj)) |
9f10b292 C |
128 | }) |
129 | } | |
8c308c2b | 130 | |
9f10b292 | 131 | function listVideos (req, res, next) { |
bc503c2a | 132 | Videos.list(function (err, videosList) { |
9f10b292 | 133 | if (err) return next(err) |
c45f7f84 | 134 | |
bc503c2a | 135 | res.json(getFormatedVideos(videosList)) |
9f10b292 C |
136 | }) |
137 | } | |
c45f7f84 | 138 | |
9f10b292 | 139 | function removeVideo (req, res, next) { |
bc503c2a C |
140 | const videoId = req.params.id |
141 | Videos.get(videoId, function (err, video) { | |
9f10b292 | 142 | if (err) return next(err) |
8c308c2b | 143 | |
9f10b292 C |
144 | removeTorrent(video.magnetUri, function () { |
145 | Videos.removeOwned(req.params.id, function (err) { | |
146 | if (err) return next(err) | |
c173e565 | 147 | |
cbe2f7c3 C |
148 | videos.removeVideosDataFromDisk([ video ], function (err) { |
149 | if (err) logger.error('Cannot remove video data from disk.', { video: video }) | |
150 | ||
151 | const params = { | |
152 | name: video.name, | |
153 | magnetUri: video.magnetUri | |
154 | } | |
c173e565 | 155 | |
cbe2f7c3 C |
156 | friends.removeVideoToFriends(params) |
157 | res.type('json').status(204).end() | |
158 | }) | |
c173e565 | 159 | }) |
8c308c2b | 160 | }) |
9f10b292 C |
161 | }) |
162 | } | |
8c308c2b | 163 | |
9f10b292 | 164 | function searchVideos (req, res, next) { |
bc503c2a | 165 | Videos.search(req.params.name, function (err, videosList) { |
9f10b292 | 166 | if (err) return next(err) |
8c308c2b | 167 | |
bc503c2a | 168 | res.json(getFormatedVideos(videosList)) |
9f10b292 C |
169 | }) |
170 | } | |
c173e565 | 171 | |
9f10b292 | 172 | // --------------------------------------------------------------------------- |
c173e565 | 173 | |
bc503c2a C |
174 | function getFormatedVideo (videoObj) { |
175 | const formatedVideo = { | |
176 | id: videoObj._id, | |
177 | name: videoObj.name, | |
178 | description: videoObj.description, | |
179 | podUrl: videoObj.podUrl, | |
180 | isLocal: videos.getVideoState(videoObj).owned, | |
181 | magnetUri: videoObj.magnetUri, | |
182 | author: videoObj.author, | |
183 | duration: videoObj.duration, | |
184 | thumbnailPath: constants.THUMBNAILS_STATIC_PATH + '/' + videoObj.thumbnail | |
2df82d42 C |
185 | } |
186 | ||
bc503c2a | 187 | return formatedVideo |
2df82d42 C |
188 | } |
189 | ||
bc503c2a C |
190 | function getFormatedVideos (videosObj) { |
191 | const formatedVideos = [] | |
2df82d42 | 192 | |
bc503c2a C |
193 | videosObj.forEach(function (videoObj) { |
194 | formatedVideos.push(getFormatedVideo(videoObj)) | |
2df82d42 C |
195 | }) |
196 | ||
bc503c2a | 197 | return formatedVideos |
2df82d42 C |
198 | } |
199 | ||
9f10b292 C |
200 | // Maybe the torrent is not seeded, but we catch the error to don't stop the removing process |
201 | function removeTorrent (magnetUri, callback) { | |
202 | try { | |
203 | webtorrent.remove(magnetUri, callback) | |
204 | } catch (err) { | |
205 | logger.warn('Cannot remove the torrent from WebTorrent', { err: err }) | |
206 | return callback(null) | |
c173e565 | 207 | } |
9f10b292 | 208 | } |