Video model refractoring -> use mongoose api
This commit is contained in:
parent
07d9320387
commit
aaf61f3810
|
@ -31,7 +31,6 @@ const logger = require('./server/helpers/logger')
|
|||
const poolRequests = require('./server/lib/requestsScheduler')
|
||||
const routes = require('./server/controllers')
|
||||
const utils = require('./server/helpers/utils')
|
||||
const videos = require('./server/lib/videos')
|
||||
const webtorrent = require('./server/lib/webtorrent')
|
||||
|
||||
// Get configurations
|
||||
|
@ -138,11 +137,11 @@ installer.installApplication(function (err) {
|
|||
// Activate the pool requests
|
||||
poolRequests.activate()
|
||||
|
||||
videos.seedAllExisting(function () {
|
||||
// videos.seedAllExisting(function () {
|
||||
logger.info('Seeded all the videos')
|
||||
logger.info('Server listening on port %d', port)
|
||||
app.emit('ready')
|
||||
})
|
||||
// })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
const async = require('async')
|
||||
const express = require('express')
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const logger = require('../../../helpers/logger')
|
||||
const friends = require('../../../lib/friends')
|
||||
|
@ -10,10 +11,9 @@ const Pods = require('../../../models/pods')
|
|||
const oAuth2 = middlewares.oauth2
|
||||
const reqValidator = middlewares.reqValidators.pods
|
||||
const signatureValidator = middlewares.reqValidators.remote.signature
|
||||
const videos = require('../../../lib/videos')
|
||||
const Videos = require('../../../models/videos')
|
||||
|
||||
const router = express.Router()
|
||||
const Video = mongoose.model('Video')
|
||||
|
||||
router.get('/', listPodsUrl)
|
||||
router.post('/', reqValidator.podsAdd, addPods)
|
||||
|
@ -86,7 +86,7 @@ function removePods (req, res, next) {
|
|||
},
|
||||
|
||||
function (callback) {
|
||||
Videos.listFromUrl(url, function (err, videosList) {
|
||||
Video.listByUrls([ url ], function (err, videosList) {
|
||||
if (err) {
|
||||
logger.error('Cannot list videos from url.', { error: err })
|
||||
return callback(err)
|
||||
|
@ -97,14 +97,9 @@ function removePods (req, res, next) {
|
|||
},
|
||||
|
||||
function removeTheRemoteVideos (videosList, callback) {
|
||||
videos.removeRemoteVideos(videosList, function (err) {
|
||||
if (err) {
|
||||
logger.error('Cannot remove remote videos.', { error: err })
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
return callback(null)
|
||||
})
|
||||
async.each(videosList, function (video, callbackEach) {
|
||||
video.remove(callbackEach)
|
||||
}, callback)
|
||||
}
|
||||
], function (err) {
|
||||
if (err) return next(err)
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
const async = require('async')
|
||||
const express = require('express')
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const middlewares = require('../../../middlewares')
|
||||
const secureMiddleware = middlewares.secure
|
||||
const reqValidator = middlewares.reqValidators.remote
|
||||
const logger = require('../../../helpers/logger')
|
||||
const Videos = require('../../../models/videos')
|
||||
const videos = require('../../../lib/videos')
|
||||
|
||||
const router = express.Router()
|
||||
const Video = mongoose.model('Video')
|
||||
|
||||
router.post('/videos',
|
||||
reqValidator.signature,
|
||||
|
@ -33,48 +33,39 @@ function remoteVideos (req, res, next) {
|
|||
// We need to process in the same order to keep consistency
|
||||
// TODO: optimization
|
||||
async.eachSeries(requests, function (request, callbackEach) {
|
||||
const video = request.data
|
||||
const videoData = request.data
|
||||
|
||||
if (request.type === 'add') {
|
||||
addRemoteVideo(video, callbackEach)
|
||||
addRemoteVideo(videoData, callbackEach)
|
||||
} else if (request.type === 'remove') {
|
||||
removeRemoteVideo(video, fromUrl, callbackEach)
|
||||
removeRemoteVideo(videoData, fromUrl, callbackEach)
|
||||
}
|
||||
}, function (err) {
|
||||
if (err) logger.error('Error managing remote videos.', { error: err })
|
||||
})
|
||||
|
||||
// We don't need to keep the other pod waiting
|
||||
return res.type('json').status(204).end()
|
||||
}
|
||||
|
||||
function addRemoteVideo (videoToCreate, callback) {
|
||||
videos.createRemoteVideos([ videoToCreate ], function (err, remoteVideos) {
|
||||
if (err) {
|
||||
logger.error('Cannot create remote videos.', { error: err })
|
||||
// Don't break the process
|
||||
}
|
||||
function addRemoteVideo (videoToCreateData, callback) {
|
||||
// Mongoose pre hook will automatically create the thumbnail on disk
|
||||
videoToCreateData.thumbnail = videoToCreateData.thumbnailBase64
|
||||
|
||||
return callback()
|
||||
})
|
||||
const video = new Video(videoToCreateData)
|
||||
video.save(callback)
|
||||
}
|
||||
|
||||
function removeRemoteVideo (videoToRemove, fromUrl, callback) {
|
||||
const magnetUris = [ videoToRemove.magnetUri ]
|
||||
|
||||
function removeRemoteVideo (videoToRemoveData, fromUrl, callback) {
|
||||
// We need the list because we have to remove some other stuffs (thumbnail etc)
|
||||
Videos.listFromUrlAndMagnets(fromUrl, magnetUris, function (err, videosList) {
|
||||
Video.listByUrlAndMagnet(fromUrl, videoToRemoveData.magnetUri, function (err, videosList) {
|
||||
if (err) {
|
||||
logger.error('Cannot list videos from url and magnets.', { error: err })
|
||||
// Don't break the process
|
||||
return callback()
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
videos.removeRemoteVideos(videosList, function (err) {
|
||||
if (err) {
|
||||
logger.error('Cannot remove remote videos.', { error: err })
|
||||
// Don't break the process
|
||||
}
|
||||
|
||||
return callback()
|
||||
})
|
||||
async.each(videosList, function (video, callbackEach) {
|
||||
video.remove(callbackEach)
|
||||
}, callback)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
const async = require('async')
|
||||
const config = require('config')
|
||||
const express = require('express')
|
||||
const mongoose = require('mongoose')
|
||||
const multer = require('multer')
|
||||
|
||||
const constants = require('../../../initializers/constants')
|
||||
const logger = require('../../../helpers/logger')
|
||||
const friends = require('../../../lib/friends')
|
||||
const middlewares = require('../../../middlewares')
|
||||
|
@ -18,12 +18,10 @@ const reqValidatorVideos = reqValidator.videos
|
|||
const search = middlewares.search
|
||||
const sort = middlewares.sort
|
||||
const utils = require('../../../helpers/utils')
|
||||
const Videos = require('../../../models/videos') // model
|
||||
const videos = require('../../../lib/videos')
|
||||
const webtorrent = require('../../../lib/webtorrent')
|
||||
|
||||
const router = express.Router()
|
||||
const uploads = config.get('storage.uploads')
|
||||
const Video = mongoose.model('Video')
|
||||
|
||||
// multer configuration
|
||||
const storage = multer.diskStorage({
|
||||
|
@ -88,55 +86,27 @@ function addVideo (req, res, next) {
|
|||
const videoInfos = req.body
|
||||
|
||||
async.waterfall([
|
||||
function seedTheVideo (callback) {
|
||||
videos.seed(videoFile.path, callback)
|
||||
},
|
||||
|
||||
function createThumbnail (torrent, callback) {
|
||||
videos.createVideoThumbnail(videoFile.path, function (err, thumbnailName) {
|
||||
if (err) {
|
||||
// TODO: unseed the video
|
||||
logger.error('Cannot make a thumbnail of the video file.')
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
callback(null, torrent, thumbnailName)
|
||||
})
|
||||
},
|
||||
|
||||
function insertIntoDB (torrent, thumbnailName, callback) {
|
||||
function insertIntoDB (callback) {
|
||||
const videoData = {
|
||||
name: videoInfos.name,
|
||||
namePath: videoFile.filename,
|
||||
description: videoInfos.description,
|
||||
magnetUri: torrent.magnetURI,
|
||||
author: res.locals.oauth.token.user.username,
|
||||
duration: videoFile.duration,
|
||||
thumbnail: thumbnailName,
|
||||
tags: videoInfos.tags
|
||||
}
|
||||
|
||||
Videos.add(videoData, function (err, insertedVideo) {
|
||||
if (err) {
|
||||
// TODO unseed the video
|
||||
// TODO remove thumbnail
|
||||
logger.error('Cannot insert this video in the database.')
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
return callback(null, insertedVideo)
|
||||
const video = new Video(videoData)
|
||||
video.save(function (err, video) {
|
||||
// Assert there are only one argument sent to the next function (video)
|
||||
return callback(err, video)
|
||||
})
|
||||
},
|
||||
|
||||
function sendToFriends (insertedVideo, callback) {
|
||||
videos.convertVideoToRemote(insertedVideo, function (err, remoteVideo) {
|
||||
if (err) {
|
||||
// TODO unseed the video
|
||||
// TODO remove thumbnail
|
||||
// TODO delete from DB
|
||||
logger.error('Cannot convert video to remote.')
|
||||
return callback(err)
|
||||
}
|
||||
function sendToFriends (video, callback) {
|
||||
video.toRemoteJSON(function (err, remoteVideo) {
|
||||
if (err) return callback(err)
|
||||
|
||||
// Now we'll add the video's meta data to our friends
|
||||
friends.addVideoToFriends(remoteVideo)
|
||||
|
@ -147,6 +117,9 @@ function addVideo (req, res, next) {
|
|||
|
||||
], function andFinally (err) {
|
||||
if (err) {
|
||||
// TODO unseed the video
|
||||
// TODO remove thumbnail
|
||||
// TODO delete from DB
|
||||
logger.error('Cannot insert the video.')
|
||||
return next(err)
|
||||
}
|
||||
|
@ -157,23 +130,22 @@ function addVideo (req, res, next) {
|
|||
}
|
||||
|
||||
function getVideo (req, res, next) {
|
||||
Videos.get(req.params.id, function (err, videoObj) {
|
||||
Video.load(req.params.id, function (err, video) {
|
||||
if (err) return next(err)
|
||||
|
||||
const state = videos.getVideoState(videoObj)
|
||||
if (state.exist === false) {
|
||||
if (!video) {
|
||||
return res.type('json').status(204).end()
|
||||
}
|
||||
|
||||
res.json(getFormatedVideo(videoObj))
|
||||
res.json(video.toFormatedJSON())
|
||||
})
|
||||
}
|
||||
|
||||
function listVideos (req, res, next) {
|
||||
Videos.list(req.query.start, req.query.count, req.query.sort, function (err, videosList, totalVideos) {
|
||||
Video.list(req.query.start, req.query.count, req.query.sort, function (err, videosList, videosTotal) {
|
||||
if (err) return next(err)
|
||||
|
||||
res.json(getFormatedVideos(videosList, totalVideos))
|
||||
res.json(getFormatedVideos(videosList, videosTotal))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -182,31 +154,17 @@ function removeVideo (req, res, next) {
|
|||
|
||||
async.waterfall([
|
||||
function getVideo (callback) {
|
||||
Videos.get(videoId, callback)
|
||||
},
|
||||
|
||||
function removeVideoTorrent (video, callback) {
|
||||
removeTorrent(video.magnetUri, function () {
|
||||
return callback(null, video)
|
||||
})
|
||||
Video.load(videoId, callback)
|
||||
},
|
||||
|
||||
function removeFromDB (video, callback) {
|
||||
Videos.removeOwned(req.params.id, function (err) {
|
||||
video.remove(function (err) {
|
||||
if (err) return callback(err)
|
||||
|
||||
return callback(null, video)
|
||||
})
|
||||
},
|
||||
|
||||
function removeVideoData (video, callback) {
|
||||
videos.removeVideosDataFromDisk([ video ], function (err) {
|
||||
if (err) logger.error('Cannot remove video data from disk.', { video: video })
|
||||
|
||||
return callback(null, video)
|
||||
})
|
||||
},
|
||||
|
||||
function sendInformationToFriends (video, callback) {
|
||||
const params = {
|
||||
name: video.name,
|
||||
|
@ -228,53 +186,25 @@ function removeVideo (req, res, next) {
|
|||
}
|
||||
|
||||
function searchVideos (req, res, next) {
|
||||
Videos.search(req.params.value, req.query.field, req.query.start, req.query.count, req.query.sort,
|
||||
function (err, videosList, totalVideos) {
|
||||
Video.search(req.params.value, req.query.field, req.query.start, req.query.count, req.query.sort,
|
||||
function (err, videosList, videosTotal) {
|
||||
if (err) return next(err)
|
||||
|
||||
res.json(getFormatedVideos(videosList, totalVideos))
|
||||
res.json(getFormatedVideos(videosList, videosTotal))
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function getFormatedVideo (videoObj) {
|
||||
const formatedVideo = {
|
||||
id: videoObj._id,
|
||||
name: videoObj.name,
|
||||
description: videoObj.description,
|
||||
podUrl: videoObj.podUrl.replace(/^https?:\/\//, ''),
|
||||
isLocal: videos.getVideoState(videoObj).owned,
|
||||
magnetUri: videoObj.magnetUri,
|
||||
author: videoObj.author,
|
||||
duration: videoObj.duration,
|
||||
tags: videoObj.tags,
|
||||
thumbnailPath: constants.THUMBNAILS_STATIC_PATH + '/' + videoObj.thumbnail,
|
||||
createdDate: videoObj.createdDate
|
||||
}
|
||||
|
||||
return formatedVideo
|
||||
}
|
||||
|
||||
function getFormatedVideos (videosObj, totalVideos) {
|
||||
function getFormatedVideos (videos, videosTotal) {
|
||||
const formatedVideos = []
|
||||
|
||||
videosObj.forEach(function (videoObj) {
|
||||
formatedVideos.push(getFormatedVideo(videoObj))
|
||||
videos.forEach(function (video) {
|
||||
formatedVideos.push(video.toFormatedJSON())
|
||||
})
|
||||
|
||||
return {
|
||||
total: totalVideos,
|
||||
total: videosTotal,
|
||||
data: formatedVideos
|
||||
}
|
||||
}
|
||||
|
||||
// Maybe the torrent is not seeded, but we catch the error to don't stop the removing process
|
||||
function removeTorrent (magnetUri, callback) {
|
||||
try {
|
||||
webtorrent.remove(magnetUri, callback)
|
||||
} catch (err) {
|
||||
logger.warn('Cannot remove the torrent from WebTorrent', { err: err })
|
||||
return callback(null)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@ const customValidators = {
|
|||
isVideoNameValid: isVideoNameValid,
|
||||
isVideoPodUrlValid: isVideoPodUrlValid,
|
||||
isVideoTagsValid: isVideoTagsValid,
|
||||
isVideoThumbnailValid: isVideoThumbnailValid
|
||||
isVideoThumbnailValid: isVideoThumbnailValid,
|
||||
isVideoThumbnail64Valid: isVideoThumbnail64Valid
|
||||
}
|
||||
|
||||
function exists (value) {
|
||||
|
@ -37,7 +38,7 @@ function isEachRemoteVideosValid (requests) {
|
|||
isVideoNameValid(video.name) &&
|
||||
isVideoPodUrlValid(video.podUrl) &&
|
||||
isVideoTagsValid(video.tags) &&
|
||||
isVideoThumbnailValid(video.thumbnailBase64)
|
||||
isVideoThumbnail64Valid(video.thumbnailBase64)
|
||||
) ||
|
||||
(
|
||||
isRequestTypeRemoveValid(request.type) &&
|
||||
|
@ -97,8 +98,12 @@ function isVideoTagsValid (tags) {
|
|||
}
|
||||
|
||||
function isVideoThumbnailValid (value) {
|
||||
return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL)
|
||||
}
|
||||
|
||||
function isVideoThumbnail64Valid (value) {
|
||||
return validator.isBase64(value) &&
|
||||
validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL)
|
||||
validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL64)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -48,7 +48,8 @@ const VIDEOS_CONSTRAINTS_FIELDS = {
|
|||
AUTHOR: { min: 3, max: 20 }, // Length
|
||||
TAGS: { min: 1, max: 3 }, // Number of total tags
|
||||
TAG: { min: 2, max: 10 }, // Length
|
||||
THUMBNAIL: { min: 0, max: 20000 } // Bytes
|
||||
THUMBNAIL: { min: 2, max: 30 },
|
||||
THUMBNAIL64: { min: 0, max: 20000 } // Bytes
|
||||
}
|
||||
|
||||
// Special constants for a test instance
|
||||
|
|
|
@ -5,6 +5,9 @@ const mongoose = require('mongoose')
|
|||
|
||||
const logger = require('../helpers/logger')
|
||||
|
||||
// Bootstrap models
|
||||
require('../models/video')
|
||||
|
||||
const dbname = 'peertube' + config.get('database.suffix')
|
||||
const host = config.get('database.host')
|
||||
const port = config.get('database.port')
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
const async = require('async')
|
||||
const config = require('config')
|
||||
const fs = require('fs')
|
||||
const mongoose = require('mongoose')
|
||||
const request = require('request')
|
||||
|
||||
const constants = require('../initializers/constants')
|
||||
|
@ -11,12 +12,11 @@ const peertubeCrypto = require('../helpers/peertubeCrypto')
|
|||
const Pods = require('../models/pods')
|
||||
const requestsScheduler = require('../lib/requestsScheduler')
|
||||
const requests = require('../helpers/requests')
|
||||
const videos = require('../lib/videos')
|
||||
const Videos = require('../models/videos')
|
||||
|
||||
const http = config.get('webserver.https') ? 'https' : 'http'
|
||||
const host = config.get('webserver.host')
|
||||
const port = config.get('webserver.port')
|
||||
const Video = mongoose.model('Video')
|
||||
|
||||
const pods = {
|
||||
addVideoToFriends: addVideoToFriends,
|
||||
|
@ -117,18 +117,13 @@ function quitFriends (callback) {
|
|||
function listRemoteVideos (callbackAsync) {
|
||||
logger.info('Broke friends, so sad :(')
|
||||
|
||||
Videos.listFromRemotes(callbackAsync)
|
||||
Video.listRemotes(callbackAsync)
|
||||
},
|
||||
|
||||
function removeTheRemoteVideos (videosList, callbackAsync) {
|
||||
videos.removeRemoteVideos(videosList, function (err) {
|
||||
if (err) {
|
||||
logger.error('Cannot remove remote videos.', { error: err })
|
||||
return callbackAsync(err)
|
||||
}
|
||||
|
||||
return callbackAsync(null)
|
||||
})
|
||||
async.each(videosList, function (video, callbackEach) {
|
||||
video.remove(callbackEach)
|
||||
}, callbackAsync)
|
||||
}
|
||||
], function (err) {
|
||||
// Don't forget to re activate the scheduler, even if there was an error
|
||||
|
@ -146,14 +141,14 @@ function removeVideoToFriends (video) {
|
|||
}
|
||||
|
||||
function sendOwnedVideosToPod (podId) {
|
||||
Videos.listOwned(function (err, videosList) {
|
||||
Video.listOwned(function (err, videosList) {
|
||||
if (err) {
|
||||
logger.error('Cannot get the list of videos we own.')
|
||||
return
|
||||
}
|
||||
|
||||
videosList.forEach(function (video) {
|
||||
videos.convertVideoToRemote(video, function (err, remoteVideo) {
|
||||
video.toRemoteJSON(function (err, remoteVideo) {
|
||||
if (err) {
|
||||
logger.error('Cannot convert video to remote.', { error: err })
|
||||
// Don't break the process
|
||||
|
|
|
@ -2,14 +2,15 @@
|
|||
|
||||
const async = require('async')
|
||||
const map = require('lodash/map')
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const constants = require('../initializers/constants')
|
||||
const logger = require('../helpers/logger')
|
||||
const Pods = require('../models/pods')
|
||||
const Requests = require('../models/requests')
|
||||
const requests = require('../helpers/requests')
|
||||
const videos = require('../lib/videos')
|
||||
const Videos = require('../models/videos')
|
||||
|
||||
const Video = mongoose.model('Video')
|
||||
|
||||
let timer = null
|
||||
|
||||
|
@ -210,7 +211,7 @@ function removeBadPods () {
|
|||
const urls = map(pods, 'url')
|
||||
const ids = map(pods, '_id')
|
||||
|
||||
Videos.listFromUrls(urls, function (err, videosList) {
|
||||
Video.listByUrls(urls, function (err, videosList) {
|
||||
if (err) {
|
||||
logger.error('Cannot list videos urls.', { error: err, urls: urls })
|
||||
return callback(null, ids, [])
|
||||
|
@ -224,9 +225,14 @@ function removeBadPods () {
|
|||
// We don't have to remove pods, skip
|
||||
if (typeof podIds === 'function') return podIds(null)
|
||||
|
||||
// Remove the remote videos
|
||||
videos.removeRemoteVideos(videosList, function (err) {
|
||||
if (err) logger.error('Cannot remove remote videos.', { error: err })
|
||||
async.each(videosList, function (video, callbackEach) {
|
||||
video.remove(callbackEach)
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
// Don't stop the process
|
||||
logger.error('Error while removing videos of bad pods.', { error: err })
|
||||
return
|
||||
}
|
||||
|
||||
return callback(null, podIds)
|
||||
})
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
const async = require('async')
|
||||
const config = require('config')
|
||||
const ffmpeg = require('fluent-ffmpeg')
|
||||
const fs = require('fs')
|
||||
const map = require('lodash/map')
|
||||
const pathUtils = require('path')
|
||||
|
||||
const constants = require('../initializers/constants')
|
||||
const logger = require('../helpers/logger')
|
||||
const utils = require('../helpers/utils')
|
||||
const Videos = require('../models/videos')
|
||||
const webtorrent = require('../lib/webtorrent')
|
||||
|
||||
const uploadDir = pathUtils.join(__dirname, '..', '..', config.get('storage.uploads'))
|
||||
const thumbnailsDir = pathUtils.join(__dirname, '..', '..', config.get('storage.thumbnails'))
|
||||
|
||||
const videos = {
|
||||
convertVideoToRemote: convertVideoToRemote,
|
||||
createRemoteVideos: createRemoteVideos,
|
||||
getVideoDuration: getVideoDuration,
|
||||
getVideoState: getVideoState,
|
||||
createVideoThumbnail: createVideoThumbnail,
|
||||
removeVideosDataFromDisk: removeVideosDataFromDisk,
|
||||
removeRemoteVideos: removeRemoteVideos,
|
||||
seed: seed,
|
||||
seedAllExisting: seedAllExisting
|
||||
}
|
||||
|
||||
function convertVideoToRemote (video, callback) {
|
||||
fs.readFile(thumbnailsDir + video.thumbnail, function (err, thumbnailData) {
|
||||
if (err) {
|
||||
logger.error('Cannot read the thumbnail of the video')
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
const remoteVideo = {
|
||||
name: video.name,
|
||||
description: video.description,
|
||||
magnetUri: video.magnetUri,
|
||||
author: video.author,
|
||||
duration: video.duration,
|
||||
thumbnailBase64: new Buffer(thumbnailData).toString('base64'),
|
||||
tags: video.tags,
|
||||
createdDate: video.createdDate,
|
||||
podUrl: video.podUrl
|
||||
}
|
||||
|
||||
return callback(null, remoteVideo)
|
||||
})
|
||||
}
|
||||
|
||||
function createRemoteVideos (videos, callback) {
|
||||
// Create the remote videos from the new pod
|
||||
createRemoteVideoObjects(videos, function (err, remoteVideos) {
|
||||
if (err) return callback(err)
|
||||
|
||||
Videos.addRemotes(remoteVideos, callback)
|
||||
})
|
||||
}
|
||||
|
||||
function getVideoDuration (videoPath, callback) {
|
||||
ffmpeg.ffprobe(videoPath, function (err, metadata) {
|
||||
if (err) return callback(err)
|
||||
|
||||
return callback(null, Math.floor(metadata.format.duration))
|
||||
})
|
||||
}
|
||||
|
||||
function getVideoState (video) {
|
||||
const exist = (video !== null)
|
||||
let owned = false
|
||||
if (exist === true) {
|
||||
owned = (video.namePath !== null)
|
||||
}
|
||||
|
||||
return { exist: exist, owned: owned }
|
||||
}
|
||||
|
||||
function createVideoThumbnail (videoPath, callback) {
|
||||
const filename = pathUtils.basename(videoPath) + '.jpg'
|
||||
ffmpeg(videoPath)
|
||||
.on('error', callback)
|
||||
.on('end', function () {
|
||||
callback(null, filename)
|
||||
})
|
||||
.thumbnail({
|
||||
count: 1,
|
||||
folder: thumbnailsDir,
|
||||
size: constants.THUMBNAILS_SIZE,
|
||||
filename: filename
|
||||
})
|
||||
}
|
||||
|
||||
// Remove video datas from disk (video file, thumbnail...)
|
||||
function removeVideosDataFromDisk (videos, callback) {
|
||||
async.each(videos, function (video, callbackEach) {
|
||||
fs.unlink(thumbnailsDir + video.thumbnail, function (err) {
|
||||
if (err) logger.error('Cannot remove the video thumbnail')
|
||||
|
||||
if (getVideoState(video).owned === true) {
|
||||
fs.unlink(uploadDir + video.namePath, function (err) {
|
||||
if (err) {
|
||||
logger.error('Cannot remove this video file.')
|
||||
return callbackEach(err)
|
||||
}
|
||||
|
||||
callbackEach(null)
|
||||
})
|
||||
} else {
|
||||
callbackEach(null)
|
||||
}
|
||||
})
|
||||
}, callback)
|
||||
}
|
||||
|
||||
function removeRemoteVideos (videos, callback) {
|
||||
Videos.removeByIds(map(videos, '_id'), function (err) {
|
||||
if (err) return callback(err)
|
||||
|
||||
removeVideosDataFromDisk(videos, callback)
|
||||
})
|
||||
}
|
||||
|
||||
function seed (path, callback) {
|
||||
logger.info('Seeding %s...', path)
|
||||
|
||||
webtorrent.seed(path, function (torrent) {
|
||||
logger.info('%s seeded (%s).', path, torrent.magnetURI)
|
||||
|
||||
return callback(null, torrent)
|
||||
})
|
||||
}
|
||||
|
||||
function seedAllExisting (callback) {
|
||||
Videos.listOwned(function (err, videosList) {
|
||||
if (err) {
|
||||
logger.error('Cannot get list of the videos to seed.')
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
async.each(videosList, function (video, callbackEach) {
|
||||
seed(uploadDir + video.namePath, function (err) {
|
||||
if (err) {
|
||||
logger.error('Cannot seed this video.')
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
callbackEach(null)
|
||||
})
|
||||
}, callback)
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
module.exports = videos
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function createRemoteVideoObjects (videos, callback) {
|
||||
const remoteVideos = []
|
||||
|
||||
async.each(videos, function (video, callbackEach) {
|
||||
// Creating the thumbnail for this remote video
|
||||
utils.generateRandomString(16, function (err, randomString) {
|
||||
if (err) return callbackEach(err)
|
||||
|
||||
const thumbnailName = randomString + '.jpg'
|
||||
createThumbnailFromBase64(thumbnailName, video.thumbnailBase64, function (err) {
|
||||
if (err) return callbackEach(err)
|
||||
|
||||
const params = {
|
||||
name: video.name,
|
||||
description: video.description,
|
||||
magnetUri: video.magnetUri,
|
||||
podUrl: video.podUrl,
|
||||
duration: video.duration,
|
||||
thumbnail: thumbnailName,
|
||||
tags: video.tags,
|
||||
author: video.author
|
||||
}
|
||||
remoteVideos.push(params)
|
||||
|
||||
callbackEach(null)
|
||||
})
|
||||
})
|
||||
},
|
||||
function (err) {
|
||||
if (err) return callback(err)
|
||||
|
||||
callback(null, remoteVideos)
|
||||
})
|
||||
}
|
||||
|
||||
function createThumbnailFromBase64 (thumbnailName, data, callback) {
|
||||
fs.writeFile(thumbnailsDir + thumbnailName, data, { encoding: 'base64' }, callback)
|
||||
}
|
|
@ -22,7 +22,7 @@ function remoteVideos (req, res, next) {
|
|||
req.checkBody('data').isArray()
|
||||
req.checkBody('data').isEachRemoteVideosValid()
|
||||
|
||||
logger.debug('Checking remoteVideosAdd parameters', { parameters: req.body })
|
||||
logger.debug('Checking remoteVideos parameters', { parameters: req.body })
|
||||
|
||||
checkErrors(req, res, next)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
'use strict'
|
||||
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const checkErrors = require('./utils').checkErrors
|
||||
const constants = require('../../initializers/constants')
|
||||
const customValidators = require('../../helpers/customValidators')
|
||||
const logger = require('../../helpers/logger')
|
||||
const videos = require('../../lib/videos')
|
||||
const Videos = require('../../models/videos')
|
||||
|
||||
const Video = mongoose.model('Video')
|
||||
|
||||
const reqValidatorsVideos = {
|
||||
videosAdd: videosAdd,
|
||||
|
@ -26,7 +28,7 @@ function videosAdd (req, res, next) {
|
|||
checkErrors(req, res, function () {
|
||||
const videoFile = req.files.videofile[0]
|
||||
|
||||
videos.getVideoDuration(videoFile.path, function (err, duration) {
|
||||
Video.getDurationFromFile(videoFile.path, function (err, duration) {
|
||||
if (err) {
|
||||
return res.status(400).send('Cannot retrieve metadata of the file.')
|
||||
}
|
||||
|
@ -47,14 +49,13 @@ function videosGet (req, res, next) {
|
|||
logger.debug('Checking videosGet parameters', { parameters: req.params })
|
||||
|
||||
checkErrors(req, res, function () {
|
||||
Videos.get(req.params.id, function (err, video) {
|
||||
Video.load(req.params.id, function (err, video) {
|
||||
if (err) {
|
||||
logger.error('Error in videosGet request validator.', { error: err })
|
||||
return res.sendStatus(500)
|
||||
}
|
||||
|
||||
const state = videos.getVideoState(video)
|
||||
if (state.exist === false) return res.status(404).send('Video not found')
|
||||
if (!video) return res.status(404).send('Video not found')
|
||||
|
||||
next()
|
||||
})
|
||||
|
@ -67,15 +68,14 @@ function videosRemove (req, res, next) {
|
|||
logger.debug('Checking videosRemove parameters', { parameters: req.params })
|
||||
|
||||
checkErrors(req, res, function () {
|
||||
Videos.get(req.params.id, function (err, video) {
|
||||
Video.load(req.params.id, function (err, video) {
|
||||
if (err) {
|
||||
logger.error('Error in videosRemove request validator.', { error: err })
|
||||
return res.sendStatus(500)
|
||||
}
|
||||
|
||||
const state = videos.getVideoState(video)
|
||||
if (state.exist === false) return res.status(404).send('Video not found')
|
||||
else if (state.owned === false) return res.status(403).send('Cannot remove video of another pod')
|
||||
if (!video) return res.status(404).send('Video not found')
|
||||
else if (video.isOwned() === false) return res.status(403).send('Cannot remove video of another pod')
|
||||
|
||||
next()
|
||||
})
|
||||
|
|
|
@ -0,0 +1,314 @@
|
|||
'use strict'
|
||||
|
||||
const async = require('async')
|
||||
const config = require('config')
|
||||
const ffmpeg = require('fluent-ffmpeg')
|
||||
const fs = require('fs')
|
||||
const pathUtils = require('path')
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const constants = require('../initializers/constants')
|
||||
const customValidators = require('../helpers/customValidators')
|
||||
const logger = require('../helpers/logger')
|
||||
const utils = require('../helpers/utils')
|
||||
const webtorrent = require('../lib/webtorrent')
|
||||
|
||||
const http = config.get('webserver.https') === true ? 'https' : 'http'
|
||||
const host = config.get('webserver.host')
|
||||
const port = config.get('webserver.port')
|
||||
const uploadsDir = pathUtils.join(__dirname, '..', '..', config.get('storage.uploads'))
|
||||
const thumbnailsDir = pathUtils.join(__dirname, '..', '..', config.get('storage.thumbnails'))
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// TODO: add indexes on searchable columns
|
||||
const VideoSchema = mongoose.Schema({
|
||||
name: String,
|
||||
namePath: String,
|
||||
description: String,
|
||||
magnetUri: String,
|
||||
podUrl: String,
|
||||
author: String,
|
||||
duration: Number,
|
||||
thumbnail: String,
|
||||
tags: [ String ],
|
||||
createdDate: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
}
|
||||
})
|
||||
|
||||
VideoSchema.path('name').validate(customValidators.isVideoNameValid)
|
||||
VideoSchema.path('description').validate(customValidators.isVideoDescriptionValid)
|
||||
VideoSchema.path('magnetUri').validate(customValidators.isVideoMagnetUriValid)
|
||||
VideoSchema.path('podUrl').validate(customValidators.isVideoPodUrlValid)
|
||||
VideoSchema.path('author').validate(customValidators.isVideoAuthorValid)
|
||||
VideoSchema.path('duration').validate(customValidators.isVideoDurationValid)
|
||||
// The tumbnail can be the path or the data in base 64
|
||||
// The pre save hook will convert the base 64 data in a file on disk and replace the thumbnail key by the filename
|
||||
VideoSchema.path('thumbnail').validate(function (value) {
|
||||
return customValidators.isVideoThumbnailValid(value) || customValidators.isVideoThumbnail64Valid(value)
|
||||
})
|
||||
VideoSchema.path('tags').validate(customValidators.isVideoTagsValid)
|
||||
|
||||
VideoSchema.methods = {
|
||||
isOwned: isOwned,
|
||||
toFormatedJSON: toFormatedJSON,
|
||||
toRemoteJSON: toRemoteJSON
|
||||
}
|
||||
|
||||
VideoSchema.statics = {
|
||||
getDurationFromFile: getDurationFromFile,
|
||||
list: list,
|
||||
listByUrlAndMagnet: listByUrlAndMagnet,
|
||||
listByUrls: listByUrls,
|
||||
listOwned: listOwned,
|
||||
listRemotes: listRemotes,
|
||||
load: load,
|
||||
search: search,
|
||||
seedAllExisting: seedAllExisting
|
||||
}
|
||||
|
||||
VideoSchema.pre('remove', function (next) {
|
||||
const video = this
|
||||
const tasks = []
|
||||
|
||||
tasks.push(
|
||||
function (callback) {
|
||||
removeThumbnail(video, callback)
|
||||
}
|
||||
)
|
||||
|
||||
if (video.isOwned()) {
|
||||
tasks.push(
|
||||
function (callback) {
|
||||
removeFile(video, callback)
|
||||
},
|
||||
function (callback) {
|
||||
removeTorrent(video, callback)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
async.parallel(tasks, next)
|
||||
})
|
||||
|
||||
VideoSchema.pre('save', function (next) {
|
||||
const video = this
|
||||
const tasks = []
|
||||
|
||||
if (video.isOwned()) {
|
||||
const videoPath = pathUtils.join(uploadsDir, video.namePath)
|
||||
this.podUrl = http + '://' + host + ':' + port
|
||||
|
||||
tasks.push(
|
||||
function (callback) {
|
||||
seed(videoPath, callback)
|
||||
},
|
||||
function (callback) {
|
||||
createThumbnail(videoPath, callback)
|
||||
}
|
||||
)
|
||||
|
||||
async.parallel(tasks, function (err, results) {
|
||||
if (err) return next(err)
|
||||
|
||||
video.magnetUri = results[0].magnetURI
|
||||
video.thumbnail = results[1]
|
||||
|
||||
return next()
|
||||
})
|
||||
} else {
|
||||
generateThumbnailFromBase64(video.thumbnail, function (err, thumbnailName) {
|
||||
if (err) return next(err)
|
||||
|
||||
video.thumbnail = thumbnailName
|
||||
|
||||
return next()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
mongoose.model('Video', VideoSchema)
|
||||
|
||||
// ------------------------------ METHODS ------------------------------
|
||||
|
||||
function isOwned () {
|
||||
return this.namePath !== null
|
||||
}
|
||||
|
||||
function toFormatedJSON () {
|
||||
const json = {
|
||||
id: this._id,
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
podUrl: this.podUrl.replace(/^https?:\/\//, ''),
|
||||
isLocal: this.isOwned(),
|
||||
magnetUri: this.magnetUri,
|
||||
author: this.author,
|
||||
duration: this.duration,
|
||||
tags: this.tags,
|
||||
thumbnailPath: constants.THUMBNAILS_STATIC_PATH + '/' + this.thumbnail,
|
||||
createdDate: this.createdDate
|
||||
}
|
||||
|
||||
return json
|
||||
}
|
||||
|
||||
function toRemoteJSON (callback) {
|
||||
const self = this
|
||||
|
||||
// Convert thumbnail to base64
|
||||
fs.readFile(pathUtils.join(thumbnailsDir, this.thumbnail), function (err, thumbnailData) {
|
||||
if (err) {
|
||||
logger.error('Cannot read the thumbnail of the video')
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
const remoteVideo = {
|
||||
name: self.name,
|
||||
description: self.description,
|
||||
magnetUri: self.magnetUri,
|
||||
namePath: null,
|
||||
author: self.author,
|
||||
duration: self.duration,
|
||||
thumbnailBase64: new Buffer(thumbnailData).toString('base64'),
|
||||
tags: self.tags,
|
||||
createdDate: self.createdDate,
|
||||
podUrl: self.podUrl
|
||||
}
|
||||
|
||||
return callback(null, remoteVideo)
|
||||
})
|
||||
}
|
||||
|
||||
// ------------------------------ STATICS ------------------------------
|
||||
|
||||
function getDurationFromFile (videoPath, callback) {
|
||||
ffmpeg.ffprobe(videoPath, function (err, metadata) {
|
||||
if (err) return callback(err)
|
||||
|
||||
return callback(null, Math.floor(metadata.format.duration))
|
||||
})
|
||||
}
|
||||
|
||||
function list (start, count, sort, callback) {
|
||||
const query = {}
|
||||
return findWithCount.call(this, query, start, count, sort, callback)
|
||||
}
|
||||
|
||||
function listByUrlAndMagnet (fromUrl, magnetUri, callback) {
|
||||
this.find({ podUrl: fromUrl, magnetUri: magnetUri }, callback)
|
||||
}
|
||||
|
||||
function listByUrls (fromUrls, callback) {
|
||||
this.find({ podUrl: { $in: fromUrls } }, callback)
|
||||
}
|
||||
|
||||
function listOwned (callback) {
|
||||
// If namePath is not null this is *our* video
|
||||
this.find({ namePath: { $ne: null } }, callback)
|
||||
}
|
||||
|
||||
function listRemotes (callback) {
|
||||
this.find({ namePath: null }, callback)
|
||||
}
|
||||
|
||||
function load (id, callback) {
|
||||
this.findById(id, callback)
|
||||
}
|
||||
|
||||
function search (value, field, start, count, sort, callback) {
|
||||
const query = {}
|
||||
// Make an exact search with the magnet
|
||||
if (field === 'magnetUri' || field === 'tags') {
|
||||
query[field] = value
|
||||
} else {
|
||||
query[field] = new RegExp(value)
|
||||
}
|
||||
|
||||
findWithCount.call(this, query, start, count, sort, callback)
|
||||
}
|
||||
|
||||
// TODO
|
||||
function seedAllExisting () {
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function findWithCount (query, start, count, sort, callback) {
|
||||
const self = this
|
||||
|
||||
async.parallel([
|
||||
function (asyncCallback) {
|
||||
self.find(query).skip(start).limit(start + count).sort(sort).exec(asyncCallback)
|
||||
},
|
||||
function (asyncCallback) {
|
||||
self.count(query, asyncCallback)
|
||||
}
|
||||
], function (err, results) {
|
||||
if (err) return callback(err)
|
||||
|
||||
const videos = results[0]
|
||||
const totalVideos = results[1]
|
||||
return callback(null, videos, totalVideos)
|
||||
})
|
||||
}
|
||||
|
||||
function removeThumbnail (video, callback) {
|
||||
fs.unlink(thumbnailsDir + video.thumbnail, callback)
|
||||
}
|
||||
|
||||
function removeFile (video, callback) {
|
||||
fs.unlink(uploadsDir + video.namePath, callback)
|
||||
}
|
||||
|
||||
// Maybe the torrent is not seeded, but we catch the error to don't stop the removing process
|
||||
function removeTorrent (video, callback) {
|
||||
try {
|
||||
webtorrent.remove(video.magnetUri, callback)
|
||||
} catch (err) {
|
||||
logger.warn('Cannot remove the torrent from WebTorrent', { err: err })
|
||||
return callback(null)
|
||||
}
|
||||
}
|
||||
|
||||
function createThumbnail (videoPath, callback) {
|
||||
const filename = pathUtils.basename(videoPath) + '.jpg'
|
||||
ffmpeg(videoPath)
|
||||
.on('error', callback)
|
||||
.on('end', function () {
|
||||
callback(null, filename)
|
||||
})
|
||||
.thumbnail({
|
||||
count: 1,
|
||||
folder: thumbnailsDir,
|
||||
size: constants.THUMBNAILS_SIZE,
|
||||
filename: filename
|
||||
})
|
||||
}
|
||||
|
||||
function seed (path, callback) {
|
||||
logger.info('Seeding %s...', path)
|
||||
|
||||
webtorrent.seed(path, function (torrent) {
|
||||
logger.info('%s seeded (%s).', path, torrent.magnetURI)
|
||||
|
||||
return callback(null, torrent)
|
||||
})
|
||||
}
|
||||
|
||||
function generateThumbnailFromBase64 (data, callback) {
|
||||
// Creating the thumbnail for this remote video
|
||||
utils.generateRandomString(16, function (err, randomString) {
|
||||
if (err) return callback(err)
|
||||
|
||||
const thumbnailName = randomString + '.jpg'
|
||||
fs.writeFile(thumbnailsDir + thumbnailName, data, { encoding: 'base64' }, function (err) {
|
||||
if (err) return callback(err)
|
||||
|
||||
return callback(null, thumbnailName)
|
||||
})
|
||||
})
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
const async = require('async')
|
||||
const config = require('config')
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const logger = require('../helpers/logger')
|
||||
|
||||
const http = config.get('webserver.https') === true ? 'https' : 'http'
|
||||
const host = config.get('webserver.host')
|
||||
const port = config.get('webserver.port')
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// TODO: add indexes on searchable columns
|
||||
const videosSchema = mongoose.Schema({
|
||||
name: String,
|
||||
namePath: String,
|
||||
description: String,
|
||||
magnetUri: String,
|
||||
podUrl: String,
|
||||
author: String,
|
||||
duration: Number,
|
||||
thumbnail: String,
|
||||
tags: [ String ],
|
||||
createdDate: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
}
|
||||
})
|
||||
const VideosDB = mongoose.model('videos', videosSchema)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Videos = {
|
||||
add: add,
|
||||
addRemotes: addRemotes,
|
||||
get: get,
|
||||
list: list,
|
||||
listFromUrl: listFromUrl,
|
||||
listFromUrls: listFromUrls,
|
||||
listFromUrlAndMagnets: listFromUrlAndMagnets,
|
||||
listFromRemotes: listFromRemotes,
|
||||
listOwned: listOwned,
|
||||
removeOwned: removeOwned,
|
||||
removeByIds: removeByIds,
|
||||
search: search
|
||||
}
|
||||
|
||||
function add (video, callback) {
|
||||
logger.info('Adding %s video to database.', video.name)
|
||||
|
||||
const params = video
|
||||
params.podUrl = http + '://' + host + ':' + port
|
||||
|
||||
VideosDB.create(params, function (err, insertedVideo) {
|
||||
if (err) {
|
||||
logger.error('Cannot insert this video into database.')
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
callback(null, insertedVideo)
|
||||
})
|
||||
}
|
||||
|
||||
function addRemotes (videos, callback) {
|
||||
videos.forEach(function (video) {
|
||||
// Ensure they are remote videos
|
||||
video.namePath = null
|
||||
})
|
||||
|
||||
VideosDB.create(videos, callback)
|
||||
}
|
||||
|
||||
function get (id, callback) {
|
||||
VideosDB.findById(id, function (err, video) {
|
||||
if (err) {
|
||||
logger.error('Cannot get this video.')
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
return callback(null, video)
|
||||
})
|
||||
}
|
||||
|
||||
function list (start, count, sort, callback) {
|
||||
const query = {}
|
||||
return findWithCount(query, start, count, sort, callback)
|
||||
}
|
||||
|
||||
function listFromUrl (fromUrl, callback) {
|
||||
VideosDB.find({ podUrl: fromUrl }, callback)
|
||||
}
|
||||
|
||||
function listFromUrls (fromUrls, callback) {
|
||||
VideosDB.find({ podUrl: { $in: fromUrls } }, callback)
|
||||
}
|
||||
|
||||
function listFromUrlAndMagnets (fromUrl, magnets, callback) {
|
||||
VideosDB.find({ podUrl: fromUrl, magnetUri: { $in: magnets } }, callback)
|
||||
}
|
||||
|
||||
function listFromRemotes (callback) {
|
||||
VideosDB.find({ namePath: null }, callback)
|
||||
}
|
||||
|
||||
function listOwned (callback) {
|
||||
// If namePath is not null this is *our* video
|
||||
VideosDB.find({ namePath: { $ne: null } }, function (err, videosList) {
|
||||
if (err) {
|
||||
logger.error('Cannot get the list of owned videos.')
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
return callback(null, videosList)
|
||||
})
|
||||
}
|
||||
|
||||
// Return the video in the callback
|
||||
function removeOwned (id, callback) {
|
||||
VideosDB.findByIdAndRemove(id, callback)
|
||||
}
|
||||
|
||||
// Use the magnet Uri because the _id field is not the same on different servers
|
||||
function removeByIds (ids, callback) {
|
||||
VideosDB.remove({ _id: { $in: ids } }, callback)
|
||||
}
|
||||
|
||||
function search (value, field, start, count, sort, callback) {
|
||||
const query = {}
|
||||
// Make an exact search with the magnet
|
||||
if (field === 'magnetUri' || field === 'tags') {
|
||||
query[field] = value
|
||||
} else {
|
||||
query[field] = new RegExp(value)
|
||||
}
|
||||
|
||||
findWithCount(query, start, count, sort, callback)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
module.exports = Videos
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function findWithCount (query, start, count, sort, callback) {
|
||||
async.parallel([
|
||||
function (asyncCallback) {
|
||||
VideosDB.find(query).skip(start).limit(start + count).sort(sort).exec(asyncCallback)
|
||||
},
|
||||
function (asyncCallback) {
|
||||
VideosDB.count(query, asyncCallback)
|
||||
}
|
||||
], function (err, results) {
|
||||
if (err) return callback(err)
|
||||
|
||||
const videos = results[0]
|
||||
const totalVideos = results[1]
|
||||
return callback(null, videos, totalVideos)
|
||||
})
|
||||
}
|
|
@ -414,7 +414,7 @@ describe('Test multiple pods', function () {
|
|||
|
||||
// Keep the logs if the test failed
|
||||
if (this.ok) {
|
||||
utils.flushTests(done)
|
||||
// utils.flushTests(done)
|
||||
} else {
|
||||
done()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue