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