Use global uuid instead of remoteId for videos
This commit is contained in:
parent
e6d4b0ff24
commit
0a6658fdcb
|
@ -22,7 +22,7 @@ export class VideoAbuseService {
|
|||
return new RestDataSource(this.authHttp, VideoAbuseService.BASE_VIDEO_ABUSE_URL + 'abuse')
|
||||
}
|
||||
|
||||
reportVideo (id: string, reason: string) {
|
||||
reportVideo (id: number, reason: string) {
|
||||
const body = {
|
||||
reason
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ export class Video implements VideoServerModel {
|
|||
description: string
|
||||
duration: number
|
||||
durationLabel: string
|
||||
id: string
|
||||
id: number
|
||||
uuid: string
|
||||
isLocal: boolean
|
||||
magnetUri: string
|
||||
name: string
|
||||
|
@ -51,7 +52,8 @@ export class Video implements VideoServerModel {
|
|||
language: number
|
||||
description: string,
|
||||
duration: number
|
||||
id: string,
|
||||
id: number,
|
||||
uuid: string,
|
||||
isLocal: boolean,
|
||||
magnetUri: string,
|
||||
name: string,
|
||||
|
@ -75,6 +77,7 @@ export class Video implements VideoServerModel {
|
|||
this.duration = hash.duration
|
||||
this.durationLabel = Video.createDurationString(hash.duration)
|
||||
this.id = hash.id
|
||||
this.uuid = hash.uuid
|
||||
this.isLocal = hash.isLocal
|
||||
this.magnetUri = hash.magnetUri
|
||||
this.name = hash.name
|
||||
|
|
|
@ -52,8 +52,8 @@ export class VideoService {
|
|||
return this.loadVideoAttributeEnum('languages', this.videoLanguages)
|
||||
}
|
||||
|
||||
getVideo (id: string): Observable<Video> {
|
||||
return this.http.get(VideoService.BASE_VIDEO_URL + id)
|
||||
getVideo (uuid: string): Observable<Video> {
|
||||
return this.http.get(VideoService.BASE_VIDEO_URL + uuid)
|
||||
.map(this.restExtractor.extractDataGet)
|
||||
.map(videoHash => new Video(videoHash))
|
||||
.catch((res) => this.restExtractor.handleError(res))
|
||||
|
@ -89,7 +89,7 @@ export class VideoService {
|
|||
.catch((res) => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
removeVideo (id: string) {
|
||||
removeVideo (id: number) {
|
||||
return this.authHttp.delete(VideoService.BASE_VIDEO_URL + id)
|
||||
.map(this.restExtractor.extractDataBool)
|
||||
.catch((res) => this.restExtractor.handleError(res))
|
||||
|
@ -106,7 +106,7 @@ export class VideoService {
|
|||
.catch((res) => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
reportVideo (id: string, reason: string) {
|
||||
reportVideo (id: number, reason: string) {
|
||||
const url = VideoService.BASE_VIDEO_URL + id + '/abuse'
|
||||
const body: VideoAbuseCreate = {
|
||||
reason
|
||||
|
@ -117,15 +117,15 @@ export class VideoService {
|
|||
.catch((res) => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
setVideoLike (id: string) {
|
||||
setVideoLike (id: number) {
|
||||
return this.setVideoRate(id, 'like')
|
||||
}
|
||||
|
||||
setVideoDislike (id: string) {
|
||||
setVideoDislike (id: number) {
|
||||
return this.setVideoRate(id, 'dislike')
|
||||
}
|
||||
|
||||
getUserVideoRating (id: string): Observable<UserVideoRate> {
|
||||
getUserVideoRating (id: number): Observable<UserVideoRate> {
|
||||
const url = UserService.BASE_USERS_URL + '/me/videos/' + id + '/rating'
|
||||
|
||||
return this.authHttp.get(url)
|
||||
|
@ -133,13 +133,13 @@ export class VideoService {
|
|||
.catch((res) => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
blacklistVideo (id: string) {
|
||||
blacklistVideo (id: number) {
|
||||
return this.authHttp.post(VideoService.BASE_VIDEO_URL + id + '/blacklist', {})
|
||||
.map(this.restExtractor.extractDataBool)
|
||||
.catch((res) => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
private setVideoRate (id: string, rateType: VideoRateType) {
|
||||
private setVideoRate (id: number, rateType: VideoRateType) {
|
||||
const url = VideoService.BASE_VIDEO_URL + id + '/rate'
|
||||
const body: UserVideoRateUpdate = {
|
||||
rating: rateType
|
||||
|
|
|
@ -85,8 +85,8 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
|
|||
this.videoLicences = this.videoService.videoLicences
|
||||
this.videoLanguages = this.videoService.videoLanguages
|
||||
|
||||
const id = this.route.snapshot.params['id']
|
||||
this.videoService.getVideo(id)
|
||||
const uuid: string = this.route.snapshot.params['uuid']
|
||||
this.videoService.getVideo(uuid)
|
||||
.subscribe(
|
||||
video => {
|
||||
this.video = video
|
||||
|
@ -118,7 +118,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
|
|||
.subscribe(
|
||||
() => {
|
||||
this.notificationsService.success('Success', 'Video updated.')
|
||||
this.router.navigate([ '/videos/watch', this.video.id ])
|
||||
this.router.navigate([ '/videos/watch', this.video.uuid ])
|
||||
},
|
||||
|
||||
err => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="video-miniature">
|
||||
<a
|
||||
[routerLink]="['/videos/watch', video.id]" [attr.title]="video.description"
|
||||
[routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.description"
|
||||
class="video-miniature-thumbnail"
|
||||
>
|
||||
<img *ngIf="isVideoNSFWForThisUser() === false" [attr.src]="video.thumbnailUrl" alt="video thumbnail" />
|
||||
|
@ -16,7 +16,7 @@
|
|||
|
||||
<div class="video-miniature-informations">
|
||||
<span class="video-miniature-name">
|
||||
<a [routerLink]="['/videos/watch', video.id]" [attr.title]="getVideoName()" class="video-miniature-name">{{ getVideoName() }}</a>
|
||||
<a [routerLink]="['/videos/watch', video.uuid]" [attr.title]="getVideoName()" class="video-miniature-name">{{ getVideoName() }}</a>
|
||||
</span>
|
||||
|
||||
<div class="video-miniature-tags">
|
||||
|
|
|
@ -27,7 +27,7 @@ export class VideoShareComponent {
|
|||
|
||||
getVideoIframeCode () {
|
||||
return '<iframe width="560" height="315" ' +
|
||||
'src="' + window.location.origin + '/videos/embed/' + this.video.id + '" ' +
|
||||
'src="' + window.location.origin + '/videos/embed/' + this.video.uuid + '" ' +
|
||||
'frameborder="0" allowfullscreen>' +
|
||||
'</iframe>'
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
<ul *dropdownMenu class="dropdown-menu" id="more-menu" role="menu" aria-labelledby="single-button">
|
||||
<li *ngIf="canUserUpdateVideo()" role="menuitem">
|
||||
<a class="dropdown-item" title="Update this video" href="#" [routerLink]="[ '/videos/edit', video.id ]">
|
||||
<a class="dropdown-item" title="Update this video" href="#" [routerLink]="[ '/videos/edit', video.uuid ]">
|
||||
<span class="glyphicon glyphicon-pencil"></span> Update
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -58,8 +58,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
|
||||
ngOnInit () {
|
||||
this.paramsSub = this.route.params.subscribe(routeParams => {
|
||||
let id = routeParams['id']
|
||||
this.videoService.getVideo(id).subscribe(
|
||||
let uuid = routeParams['uuid']
|
||||
this.videoService.getVideo(uuid).subscribe(
|
||||
video => this.onVideoFetched(video),
|
||||
|
||||
error => {
|
||||
|
|
|
@ -33,7 +33,7 @@ const videosRoutes: Routes = [
|
|||
}
|
||||
},
|
||||
{
|
||||
path: 'edit/:id',
|
||||
path: 'edit/:uuid',
|
||||
component: VideoUpdateComponent,
|
||||
data: {
|
||||
meta: {
|
||||
|
@ -42,11 +42,11 @@ const videosRoutes: Routes = [
|
|||
}
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
redirectTo: 'watch/:id'
|
||||
path: ':uuid',
|
||||
redirectTo: 'watch/:uuid'
|
||||
},
|
||||
{
|
||||
path: 'watch/:id',
|
||||
path: 'watch/:uuid',
|
||||
component: VideoWatchComponent
|
||||
}
|
||||
]
|
||||
|
|
|
@ -133,7 +133,7 @@ function processVideosEventsRetryWrapper (eventData: RemoteVideoEventData, fromP
|
|||
function processVideosEvents (eventData: RemoteVideoEventData, fromPod: PodInstance) {
|
||||
|
||||
return db.sequelize.transaction(t => {
|
||||
return fetchOwnedVideo(eventData.remoteId)
|
||||
return fetchVideoByUUID(eventData.uuid)
|
||||
.then(videoInstance => {
|
||||
const options = { transaction: t }
|
||||
|
||||
|
@ -176,7 +176,7 @@ function processVideosEvents (eventData: RemoteVideoEventData, fromPod: PodInsta
|
|||
return quickAndDirtyUpdatesVideoToFriends(qadusParams, t)
|
||||
})
|
||||
})
|
||||
.then(() => logger.info('Remote video event processed for video %s.', eventData.remoteId))
|
||||
.then(() => logger.info('Remote video event processed for video %s.', eventData.uuid))
|
||||
.catch(err => {
|
||||
logger.debug('Cannot process a video event.', err)
|
||||
throw err
|
||||
|
@ -196,7 +196,7 @@ function quickAndDirtyUpdateVideo (videoData: RemoteQaduVideoData, fromPod: PodI
|
|||
let videoName
|
||||
|
||||
return db.sequelize.transaction(t => {
|
||||
return fetchRemoteVideo(fromPod.host, videoData.remoteId)
|
||||
return fetchVideoByHostAndUUID(fromPod.host, videoData.uuid)
|
||||
.then(videoInstance => {
|
||||
const options = { transaction: t }
|
||||
|
||||
|
@ -232,12 +232,12 @@ function addRemoteVideoRetryWrapper (videoToCreateData: RemoteVideoCreateData, f
|
|||
}
|
||||
|
||||
function addRemoteVideo (videoToCreateData: RemoteVideoCreateData, fromPod: PodInstance) {
|
||||
logger.debug('Adding remote video "%s".', videoToCreateData.remoteId)
|
||||
logger.debug('Adding remote video "%s".', videoToCreateData.uuid)
|
||||
|
||||
return db.sequelize.transaction(t => {
|
||||
return db.Video.loadByHostAndRemoteId(fromPod.host, videoToCreateData.remoteId)
|
||||
return db.Video.loadByUUID(videoToCreateData.uuid)
|
||||
.then(video => {
|
||||
if (video) throw new Error('RemoteId and host pair is not unique.')
|
||||
if (video) throw new Error('UUID already exists.')
|
||||
|
||||
return undefined
|
||||
})
|
||||
|
@ -257,7 +257,7 @@ function addRemoteVideo (videoToCreateData: RemoteVideoCreateData, fromPod: PodI
|
|||
.then(({ author, tagInstances }) => {
|
||||
const videoData = {
|
||||
name: videoToCreateData.name,
|
||||
remoteId: videoToCreateData.remoteId,
|
||||
uuid: videoToCreateData.uuid,
|
||||
extname: videoToCreateData.extname,
|
||||
infoHash: videoToCreateData.infoHash,
|
||||
category: videoToCreateData.category,
|
||||
|
@ -272,7 +272,8 @@ function addRemoteVideo (videoToCreateData: RemoteVideoCreateData, fromPod: PodI
|
|||
updatedAt: videoToCreateData.updatedAt,
|
||||
views: videoToCreateData.views,
|
||||
likes: videoToCreateData.likes,
|
||||
dislikes: videoToCreateData.dislikes
|
||||
dislikes: videoToCreateData.dislikes,
|
||||
remote: true
|
||||
}
|
||||
|
||||
const video = db.Video.build(videoData)
|
||||
|
@ -314,10 +315,10 @@ function updateRemoteVideoRetryWrapper (videoAttributesToUpdate: RemoteVideoUpda
|
|||
}
|
||||
|
||||
function updateRemoteVideo (videoAttributesToUpdate: RemoteVideoUpdateData, fromPod: PodInstance) {
|
||||
logger.debug('Updating remote video "%s".', videoAttributesToUpdate.remoteId)
|
||||
logger.debug('Updating remote video "%s".', videoAttributesToUpdate.uuid)
|
||||
|
||||
return db.sequelize.transaction(t => {
|
||||
return fetchRemoteVideo(fromPod.host, videoAttributesToUpdate.remoteId)
|
||||
return fetchVideoByHostAndUUID(fromPod.host, videoAttributesToUpdate.uuid)
|
||||
.then(videoInstance => {
|
||||
const tags = videoAttributesToUpdate.tags
|
||||
|
||||
|
@ -359,18 +360,18 @@ function updateRemoteVideo (videoAttributesToUpdate: RemoteVideoUpdateData, from
|
|||
|
||||
function removeRemoteVideo (videoToRemoveData: RemoteVideoRemoveData, fromPod: PodInstance) {
|
||||
// We need the instance because we have to remove some other stuffs (thumbnail etc)
|
||||
return fetchRemoteVideo(fromPod.host, videoToRemoveData.remoteId)
|
||||
return fetchVideoByHostAndUUID(fromPod.host, videoToRemoveData.uuid)
|
||||
.then(video => {
|
||||
logger.debug('Removing remote video %s.', video.remoteId)
|
||||
logger.debug('Removing remote video %s.', video.uuid)
|
||||
return video.destroy()
|
||||
})
|
||||
.catch(err => {
|
||||
logger.debug('Could not fetch remote video.', { host: fromPod.host, remoteId: videoToRemoveData.remoteId, error: err.stack })
|
||||
logger.debug('Could not fetch remote video.', { host: fromPod.host, uuid: videoToRemoveData.uuid, error: err.stack })
|
||||
})
|
||||
}
|
||||
|
||||
function reportAbuseRemoteVideo (reportData: RemoteVideoReportAbuseData, fromPod: PodInstance) {
|
||||
return fetchOwnedVideo(reportData.videoRemoteId)
|
||||
return fetchVideoByUUID(reportData.videoUUID)
|
||||
.then(video => {
|
||||
logger.debug('Reporting remote abuse for video %s.', video.id)
|
||||
|
||||
|
@ -386,8 +387,8 @@ function reportAbuseRemoteVideo (reportData: RemoteVideoReportAbuseData, fromPod
|
|||
.catch(err => logger.error('Cannot create remote abuse video.', err))
|
||||
}
|
||||
|
||||
function fetchOwnedVideo (id: string) {
|
||||
return db.Video.load(id)
|
||||
function fetchVideoByUUID (id: string) {
|
||||
return db.Video.loadByUUID(id)
|
||||
.then(video => {
|
||||
if (!video) throw new Error('Video not found')
|
||||
|
||||
|
@ -399,15 +400,15 @@ function fetchOwnedVideo (id: string) {
|
|||
})
|
||||
}
|
||||
|
||||
function fetchRemoteVideo (podHost: string, remoteId: string) {
|
||||
return db.Video.loadByHostAndRemoteId(podHost, remoteId)
|
||||
function fetchVideoByHostAndUUID (podHost: string, uuid: string) {
|
||||
return db.Video.loadByHostAndUUID(podHost, uuid)
|
||||
.then(video => {
|
||||
if (!video) throw new Error('Video not found')
|
||||
|
||||
return video
|
||||
})
|
||||
.catch(err => {
|
||||
logger.error('Cannot load video from host and remote id.', { error: err.stack, podHost, remoteId })
|
||||
logger.error('Cannot load video from host and uuid.', { error: err.stack, podHost, uuid })
|
||||
throw err
|
||||
})
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ function getUserInformation (req: express.Request, res: express.Response, next:
|
|||
}
|
||||
|
||||
function getUserVideoRating (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
const videoId = '' + req.params.videoId
|
||||
const videoId = +req.params.videoId
|
||||
const userId = +res.locals.oauth.token.User.id
|
||||
|
||||
db.UserVideoRate.load(userId, videoId, null)
|
||||
|
|
|
@ -62,7 +62,7 @@ function reportVideoAbuseRetryWrapper (req: express.Request, res: express.Respon
|
|||
}
|
||||
|
||||
function reportVideoAbuse (req: express.Request, res: express.Response) {
|
||||
const videoInstance = res.locals.video
|
||||
const videoInstance = res.locals.video as VideoInstance
|
||||
const reporterUsername = res.locals.oauth.token.User.username
|
||||
const body: VideoAbuseCreate = req.body
|
||||
|
||||
|
@ -81,7 +81,7 @@ function reportVideoAbuse (req: express.Request, res: express.Response) {
|
|||
const reportData = {
|
||||
reporterUsername,
|
||||
reportReason: abuse.reason,
|
||||
videoRemoteId: videoInstance.remoteId
|
||||
videoUUID: videoInstance.uuid
|
||||
}
|
||||
|
||||
return friends.reportAbuseVideoToFriend(reportData, videoInstance, t).then(() => videoInstance)
|
||||
|
|
|
@ -176,7 +176,7 @@ function addVideo (req: express.Request, res: express.Response, videoFile: Expre
|
|||
.then(({ author, tagInstances }) => {
|
||||
const videoData = {
|
||||
name: videoInfos.name,
|
||||
remoteId: null,
|
||||
remote: false,
|
||||
extname: path.extname(videoFile.filename),
|
||||
category: videoInfos.category,
|
||||
licence: videoInfos.licence,
|
||||
|
|
|
@ -69,7 +69,7 @@ function rateVideo (req: express.Request, res: express.Response) {
|
|||
|
||||
// There was a previous rate, update it
|
||||
if (previousRate) {
|
||||
// We will remove the previous rate, so we will need to remove it from the video attribute
|
||||
// We will remove the previous rate, so we will need to update the video count attribute
|
||||
if (previousRate.type === VIDEO_RATE_TYPES.LIKE) likesToIncrement--
|
||||
else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement--
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ function addOpenGraphTags (htmlStringPage: string, video: VideoInstance) {
|
|||
}
|
||||
|
||||
let tagsString = ''
|
||||
Object.keys(metaTags).forEach(function (tagName) {
|
||||
Object.keys(metaTags).forEach(tagName => {
|
||||
const tagValue = metaTags[tagName]
|
||||
|
||||
tagsString += '<meta property="' + tagName + '" content="' + tagValue + '" />'
|
||||
|
@ -89,13 +89,20 @@ function addOpenGraphTags (htmlStringPage: string, video: VideoInstance) {
|
|||
|
||||
function generateWatchHtmlPage (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
const videoId = '' + req.params.id
|
||||
let videoPromise: Promise<VideoInstance>
|
||||
|
||||
// Let Angular application handle errors
|
||||
if (!validator.isUUID(videoId, 4)) return res.sendFile(indexPath)
|
||||
if (validator.isUUID(videoId, 4)) {
|
||||
videoPromise = db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(videoId)
|
||||
} else if (validator.isInt(videoId)) {
|
||||
videoPromise = db.Video.loadAndPopulateAuthorAndPodAndTags(+videoId)
|
||||
} else {
|
||||
return res.sendFile(indexPath)
|
||||
}
|
||||
|
||||
Promise.all([
|
||||
readFileBufferPromise(indexPath),
|
||||
db.Video.loadAndPopulateAuthorAndPodAndTags(videoId)
|
||||
videoPromise
|
||||
])
|
||||
.then(([ file, video ]) => {
|
||||
file = file as Buffer
|
||||
|
|
|
@ -9,7 +9,7 @@ import { isArray } from '../misc'
|
|||
import {
|
||||
isVideoAuthorValid,
|
||||
isVideoThumbnailDataValid,
|
||||
isVideoRemoteIdValid,
|
||||
isVideoUUIDValid,
|
||||
isVideoAbuseReasonValid,
|
||||
isVideoAbuseReporterUsernameValid,
|
||||
isVideoViewsValid,
|
||||
|
@ -50,11 +50,11 @@ function isEachRemoteRequestVideosValid (requests: any[]) {
|
|||
) ||
|
||||
(
|
||||
isRequestTypeRemoveValid(request.type) &&
|
||||
isVideoRemoteIdValid(video.remoteId)
|
||||
isVideoUUIDValid(video.uuid)
|
||||
) ||
|
||||
(
|
||||
isRequestTypeReportAbuseValid(request.type) &&
|
||||
isVideoRemoteIdValid(request.data.videoRemoteId) &&
|
||||
isVideoUUIDValid(request.data.videoUUID) &&
|
||||
isVideoAbuseReasonValid(request.data.reportReason) &&
|
||||
isVideoAbuseReporterUsernameValid(request.data.reporterUsername)
|
||||
)
|
||||
|
@ -69,7 +69,7 @@ function isEachRemoteRequestVideosQaduValid (requests: any[]) {
|
|||
if (!video) return false
|
||||
|
||||
return (
|
||||
isVideoRemoteIdValid(video.remoteId) &&
|
||||
isVideoUUIDValid(video.uuid) &&
|
||||
(has(video, 'views') === false || isVideoViewsValid(video.views)) &&
|
||||
(has(video, 'likes') === false || isVideoLikesValid(video.likes)) &&
|
||||
(has(video, 'dislikes') === false || isVideoDislikesValid(video.dislikes))
|
||||
|
@ -85,7 +85,7 @@ function isEachRemoteRequestVideosEventsValid (requests: any[]) {
|
|||
if (!eventData) return false
|
||||
|
||||
return (
|
||||
isVideoRemoteIdValid(eventData.remoteId) &&
|
||||
isVideoUUIDValid(eventData.uuid) &&
|
||||
values(REQUEST_VIDEO_EVENT_TYPES).indexOf(eventData.eventType) !== -1 &&
|
||||
isVideoEventCountValid(eventData.count)
|
||||
)
|
||||
|
@ -124,7 +124,7 @@ function isCommonVideoAttributesValid (video: any) {
|
|||
isVideoInfoHashValid(video.infoHash) &&
|
||||
isVideoNameValid(video.name) &&
|
||||
isVideoTagsValid(video.tags) &&
|
||||
isVideoRemoteIdValid(video.remoteId) &&
|
||||
isVideoUUIDValid(video.uuid) &&
|
||||
isVideoExtnameValid(video.extname) &&
|
||||
isVideoViewsValid(video.views) &&
|
||||
isVideoLikesValid(video.likes) &&
|
||||
|
|
|
@ -17,6 +17,10 @@ const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
|
|||
const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
|
||||
const VIDEO_EVENTS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_EVENTS
|
||||
|
||||
function isVideoIdOrUUIDValid (value: string) {
|
||||
return validator.isInt(value) || isVideoUUIDValid(value)
|
||||
}
|
||||
|
||||
function isVideoAuthorValid (value: string) {
|
||||
return isUserUsernameValid(value)
|
||||
}
|
||||
|
@ -77,8 +81,8 @@ function isVideoThumbnailDataValid (value: string) {
|
|||
return exists(value) && validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL_DATA)
|
||||
}
|
||||
|
||||
function isVideoRemoteIdValid (value: string) {
|
||||
return exists(value) && validator.isUUID(value, 4)
|
||||
function isVideoUUIDValid (value: string) {
|
||||
return exists(value) && validator.isUUID('' + value, 4)
|
||||
}
|
||||
|
||||
function isVideoAbuseReasonValid (value: string) {
|
||||
|
@ -127,6 +131,7 @@ function isVideoFile (value: string, files: { [ fieldname: string ]: Express.Mul
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
isVideoIdOrUUIDValid,
|
||||
isVideoAuthorValid,
|
||||
isVideoDateValid,
|
||||
isVideoCategoryValid,
|
||||
|
@ -141,7 +146,7 @@ export {
|
|||
isVideoThumbnailValid,
|
||||
isVideoThumbnailDataValid,
|
||||
isVideoExtnameValid,
|
||||
isVideoRemoteIdValid,
|
||||
isVideoUUIDValid,
|
||||
isVideoAbuseReasonValid,
|
||||
isVideoAbuseReporterUsernameValid,
|
||||
isVideoFile,
|
||||
|
@ -155,6 +160,7 @@ export {
|
|||
declare global {
|
||||
namespace ExpressValidator {
|
||||
export interface Validator {
|
||||
isVideoIdOrUUIDValid,
|
||||
isVideoAuthorValid,
|
||||
isVideoDateValid,
|
||||
isVideoCategoryValid,
|
||||
|
@ -169,7 +175,7 @@ declare global {
|
|||
isVideoThumbnailValid,
|
||||
isVideoThumbnailDataValid,
|
||||
isVideoExtnameValid,
|
||||
isVideoRemoteIdValid,
|
||||
isVideoUUIDValid,
|
||||
isVideoAbuseReasonValid,
|
||||
isVideoAbuseReporterUsernameValid,
|
||||
isVideoFile,
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const LAST_MIGRATION_VERSION = 50
|
||||
const LAST_MIGRATION_VERSION = 55
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ function up (utils: {
|
|||
})
|
||||
}
|
||||
|
||||
function down (options, callback) {
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ function up (utils: {
|
|||
})
|
||||
}
|
||||
|
||||
function down (options, callback) {
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ function up (utils: {
|
|||
return q.addColumn('Videos', 'views', data)
|
||||
}
|
||||
|
||||
function down (options, callback) {
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ function up (utils: {
|
|||
return q.addColumn('Videos', 'likes', data)
|
||||
}
|
||||
|
||||
function down (options, callback) {
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ function up (utils: {
|
|||
return q.addColumn('Videos', 'dislikes', data)
|
||||
}
|
||||
|
||||
function down (options, callback) {
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ function up (utils: {
|
|||
})
|
||||
}
|
||||
|
||||
function down (options, callback) {
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ function up (utils: {
|
|||
})
|
||||
}
|
||||
|
||||
function down (options, callback) {
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ function up (utils: {
|
|||
})
|
||||
}
|
||||
|
||||
function down (options, callback) {
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ function up (utils: {
|
|||
return q.addColumn('Users', 'displayNSFW', data)
|
||||
}
|
||||
|
||||
function down (options, callback) {
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ function up (utils: {
|
|||
return q.addColumn('Videos', 'language', data)
|
||||
}
|
||||
|
||||
function down (options, callback) {
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
import * as Promise from 'bluebird'
|
||||
|
||||
function up (utils: {
|
||||
transaction: Sequelize.Transaction,
|
||||
queryInterface: Sequelize.QueryInterface,
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const q = utils.queryInterface
|
||||
|
||||
const dataUUID = {
|
||||
type: Sequelize.UUID,
|
||||
defaultValue: Sequelize.UUIDV4,
|
||||
allowNull: true
|
||||
}
|
||||
|
||||
return q.addColumn('Videos', 'uuid', dataUUID)
|
||||
.then(() => {
|
||||
const query = 'UPDATE "Videos" SET "uuid" = "id" WHERE "remoteId" IS NULL'
|
||||
return utils.sequelize.query(query)
|
||||
})
|
||||
.then(() => {
|
||||
const query = 'UPDATE "Videos" SET "uuid" = "remoteId" WHERE "remoteId" IS NOT NULL'
|
||||
return utils.sequelize.query(query)
|
||||
})
|
||||
.then(() => {
|
||||
dataUUID.defaultValue = null
|
||||
|
||||
return q.changeColumn('Videos', 'uuid', dataUUID)
|
||||
})
|
||||
.then(() => {
|
||||
return removeForeignKey(utils.sequelize, 'RequestVideoQadus')
|
||||
})
|
||||
.then(() => {
|
||||
return removeForeignKey(utils.sequelize, 'RequestVideoEvents')
|
||||
})
|
||||
.then(() => {
|
||||
return removeForeignKey(utils.sequelize, 'BlacklistedVideos')
|
||||
})
|
||||
.then(() => {
|
||||
return removeForeignKey(utils.sequelize, 'UserVideoRates')
|
||||
})
|
||||
.then(() => {
|
||||
return removeForeignKey(utils.sequelize, 'VideoAbuses')
|
||||
})
|
||||
.then(() => {
|
||||
return removeForeignKey(utils.sequelize, 'VideoTags')
|
||||
})
|
||||
.then(() => {
|
||||
const query = 'ALTER TABLE "Videos" DROP CONSTRAINT "Videos_pkey"'
|
||||
return utils.sequelize.query(query)
|
||||
})
|
||||
.then(() => {
|
||||
const query = 'ALTER TABLE "Videos" ADD COLUMN "id2" SERIAL PRIMARY KEY'
|
||||
return utils.sequelize.query(query)
|
||||
})
|
||||
.then(() => {
|
||||
return q.renameColumn('Videos', 'id', 'oldId')
|
||||
})
|
||||
.then(() => {
|
||||
return q.renameColumn('Videos', 'id2', 'id')
|
||||
})
|
||||
.then(() => {
|
||||
return changeForeignKey(q, utils.sequelize, 'RequestVideoQadus', false)
|
||||
})
|
||||
.then(() => {
|
||||
return changeForeignKey(q, utils.sequelize, 'RequestVideoEvents', false)
|
||||
})
|
||||
.then(() => {
|
||||
return changeForeignKey(q, utils.sequelize, 'BlacklistedVideos', false)
|
||||
})
|
||||
.then(() => {
|
||||
return changeForeignKey(q, utils.sequelize, 'UserVideoRates', false)
|
||||
})
|
||||
.then(() => {
|
||||
return changeForeignKey(q, utils.sequelize, 'VideoAbuses', false)
|
||||
})
|
||||
.then(() => {
|
||||
return changeForeignKey(q, utils.sequelize, 'VideoTags', true)
|
||||
})
|
||||
.then(() => {
|
||||
return q.removeColumn('Videos', 'oldId')
|
||||
})
|
||||
.then(() => {
|
||||
const dataRemote = {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false,
|
||||
allowNull: false
|
||||
}
|
||||
return q.addColumn('Videos', 'remote', dataRemote)
|
||||
})
|
||||
.then(() => {
|
||||
const query = 'UPDATE "Videos" SET "remote" = false WHERE "remoteId" IS NULL'
|
||||
return utils.sequelize.query(query)
|
||||
})
|
||||
.then(() => {
|
||||
const query = 'UPDATE "Videos" SET "remote" = true WHERE "remoteId" IS NOT NULL'
|
||||
return utils.sequelize.query(query)
|
||||
})
|
||||
.then(() => {
|
||||
return q.removeColumn('Videos', 'remoteId')
|
||||
})
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
function removeForeignKey (sequelize: Sequelize.Sequelize, tableName: string) {
|
||||
const query = 'ALTER TABLE "' + tableName + '" DROP CONSTRAINT "' + tableName + '_videoId_fkey' + '"'
|
||||
return sequelize.query(query)
|
||||
}
|
||||
|
||||
function changeForeignKey (q: Sequelize.QueryInterface, sequelize: Sequelize.Sequelize, tableName: string, allowNull: boolean) {
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true
|
||||
}
|
||||
|
||||
return q.addColumn(tableName, 'videoId2', data)
|
||||
.then(() => {
|
||||
const query = 'UPDATE "' + tableName + '" SET "videoId2" = ' +
|
||||
'(SELECT "id" FROM "Videos" WHERE "' + tableName + '"."videoId" = "Videos"."oldId")'
|
||||
return sequelize.query(query)
|
||||
})
|
||||
.then(() => {
|
||||
if (allowNull === false) {
|
||||
data.allowNull = false
|
||||
|
||||
return q.changeColumn(tableName, 'videoId2', data)
|
||||
}
|
||||
|
||||
return Promise.resolve()
|
||||
})
|
||||
.then(() => {
|
||||
return q.removeColumn(tableName, 'videoId')
|
||||
})
|
||||
.then(() => {
|
||||
return q.renameColumn(tableName, 'videoId2', 'videoId')
|
||||
})
|
||||
.then(() => {
|
||||
return q.addIndex(tableName, [ 'videoId' ])
|
||||
})
|
||||
.then(() => {
|
||||
const constraintName = tableName + '_videoId_fkey'
|
||||
const query = 'ALTER TABLE "' + tableName + '" ' +
|
||||
' ADD CONSTRAINT "' + constraintName + '"' +
|
||||
' FOREIGN KEY ("videoId") REFERENCES "Videos" ON DELETE CASCADE'
|
||||
|
||||
return sequelize.query(query)
|
||||
})
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
|
@ -96,10 +96,10 @@ function executeMigration (actualVersion: number, entity: { version: string, scr
|
|||
sequelize: db.sequelize
|
||||
}
|
||||
|
||||
migrationScript.up(options)
|
||||
return migrationScript.up(options)
|
||||
.then(() => {
|
||||
// Update the new migration version
|
||||
db.Application.updateMigrationVersion(versionScript, t)
|
||||
return db.Application.updateMigrationVersion(versionScript, t)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -43,8 +43,8 @@ import {
|
|||
Pod as FormatedPod
|
||||
} from '../../shared'
|
||||
|
||||
type QaduParam = { videoId: string, type: RequestVideoQaduType }
|
||||
type EventParam = { videoId: string, type: RequestVideoEventType }
|
||||
type QaduParam = { videoId: number, type: RequestVideoQaduType }
|
||||
type EventParam = { videoId: number, type: RequestVideoEventType }
|
||||
|
||||
const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ import { logger } from '../../../helpers'
|
|||
import { addVideoToFriends } from '../../../lib'
|
||||
import { VideoInstance } from '../../../models'
|
||||
|
||||
function process (data: { id: string }) {
|
||||
return db.Video.loadAndPopulateAuthorAndPodAndTags(data.id).then(video => {
|
||||
function process (data: { videoUUID: string }) {
|
||||
return db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(data.videoUUID).then(video => {
|
||||
return video.transcodeVideofile().then(() => video)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import { RequestVideoEventType, RemoteVideoEventRequest, RemoteVideoEventType }
|
|||
|
||||
export type RequestVideoEventSchedulerOptions = {
|
||||
type: RequestVideoEventType
|
||||
videoId: string
|
||||
videoId: number
|
||||
count?: number
|
||||
transaction?: Sequelize.Transaction
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ class RequestVideoEventScheduler extends AbstractRequestScheduler<RequestsVideoE
|
|||
*/
|
||||
const eventsPerVideoPerPod: {
|
||||
[ podId: string ]: {
|
||||
[ videoRemoteId: string ]: {
|
||||
[ videoUUID: string ]: {
|
||||
views?: number
|
||||
likes?: number
|
||||
dislikes?: number
|
||||
|
@ -74,10 +74,10 @@ class RequestVideoEventScheduler extends AbstractRequestScheduler<RequestsVideoE
|
|||
requestsToMakeGrouped[toPodId].ids.push(eventToProcess.id)
|
||||
|
||||
const eventsPerVideo = eventsPerVideoPerPod[toPodId]
|
||||
const remoteId = eventToProcess.video.remoteId
|
||||
if (!eventsPerVideo[remoteId]) eventsPerVideo[remoteId] = {}
|
||||
const uuid = eventToProcess.video.uuid
|
||||
if (!eventsPerVideo[uuid]) eventsPerVideo[uuid] = {}
|
||||
|
||||
const events = eventsPerVideo[remoteId]
|
||||
const events = eventsPerVideo[uuid]
|
||||
if (!events[eventToProcess.type]) events[eventToProcess.type] = 0
|
||||
|
||||
events[eventToProcess.type] += eventToProcess.count
|
||||
|
@ -88,13 +88,13 @@ class RequestVideoEventScheduler extends AbstractRequestScheduler<RequestsVideoE
|
|||
Object.keys(eventsPerVideoPerPod).forEach(toPodId => {
|
||||
const eventsForPod = eventsPerVideoPerPod[toPodId]
|
||||
|
||||
Object.keys(eventsForPod).forEach(remoteId => {
|
||||
const eventsForVideo = eventsForPod[remoteId]
|
||||
Object.keys(eventsForPod).forEach(uuid => {
|
||||
const eventsForVideo = eventsForPod[uuid]
|
||||
|
||||
Object.keys(eventsForVideo).forEach(eventType => {
|
||||
requestsToMakeGrouped[toPodId].datas.push({
|
||||
data: {
|
||||
remoteId,
|
||||
uuid,
|
||||
eventType: eventType as RemoteVideoEventType,
|
||||
count: +eventsForVideo[eventType]
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ interface RequestsObjectsCustom<U> extends RequestsObjects<U> {
|
|||
datas: U[]
|
||||
|
||||
videos: {
|
||||
[ id: string ]: {
|
||||
remoteId: string
|
||||
[ uuid: string ]: {
|
||||
uuid: string
|
||||
likes?: number
|
||||
dislikes?: number
|
||||
views?: number
|
||||
|
@ -33,7 +33,7 @@ interface RequestsObjectsCustom<U> extends RequestsObjects<U> {
|
|||
|
||||
export type RequestVideoQaduSchedulerOptions = {
|
||||
type: RequestVideoQaduType
|
||||
videoId: string
|
||||
videoId: number
|
||||
transaction?: Sequelize.Transaction
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ class RequestVideoQaduScheduler extends AbstractRequestScheduler<RequestsVideoQa
|
|||
|
||||
// Maybe another attribute was filled for this video
|
||||
let videoData = requestsToMakeGrouped[hashKey].videos[video.id]
|
||||
if (!videoData) videoData = { remoteId: null }
|
||||
if (!videoData) videoData = { uuid: null }
|
||||
|
||||
switch (request.type) {
|
||||
case REQUEST_VIDEO_QADU_TYPES.LIKES:
|
||||
|
@ -98,8 +98,8 @@ class RequestVideoQaduScheduler extends AbstractRequestScheduler<RequestsVideoQa
|
|||
return
|
||||
}
|
||||
|
||||
// Do not forget the remoteId so the remote pod can identify the video
|
||||
videoData.remoteId = video.id
|
||||
// Do not forget the uuid so the remote pod can identify the video
|
||||
videoData.uuid = video.uuid
|
||||
requestsToMakeGrouped[hashKey].ids.push(request.id)
|
||||
|
||||
// Maybe there are multiple quick and dirty update for the same video
|
||||
|
@ -110,8 +110,8 @@ class RequestVideoQaduScheduler extends AbstractRequestScheduler<RequestsVideoQa
|
|||
|
||||
// Now we deduped similar quick and dirty updates, we can build our requests datas
|
||||
Object.keys(requestsToMakeGrouped).forEach(hashKey => {
|
||||
Object.keys(requestsToMakeGrouped[hashKey].videos).forEach(videoId => {
|
||||
const videoData = requestsToMakeGrouped[hashKey].videos[videoId]
|
||||
Object.keys(requestsToMakeGrouped[hashKey].videos).forEach(videoUUID => {
|
||||
const videoData = requestsToMakeGrouped[hashKey].videos[videoUUID]
|
||||
|
||||
requestsToMakeGrouped[hashKey].datas.push({
|
||||
data: videoData
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import 'express-validator'
|
||||
import * as express from 'express'
|
||||
import * as Promise from 'bluebird'
|
||||
import * as validator from 'validator'
|
||||
|
||||
import { database as db } from '../../initializers/database'
|
||||
import { checkErrors } from './utils'
|
||||
import { logger } from '../../helpers'
|
||||
import { VideoInstance } from '../../models'
|
||||
|
||||
function usersAddValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
req.checkBody('username', 'Should have a valid username').isUserUsernameValid()
|
||||
|
@ -59,12 +62,20 @@ function usersUpdateValidator (req: express.Request, res: express.Response, next
|
|||
}
|
||||
|
||||
function usersVideoRatingValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
req.checkParams('videoId', 'Should have a valid video id').notEmpty().isUUID(4)
|
||||
req.checkParams('videoId', 'Should have a valid video id').notEmpty().isVideoIdOrUUIDValid()
|
||||
|
||||
logger.debug('Checking usersVideoRating parameters', { parameters: req.params })
|
||||
|
||||
checkErrors(req, res, function () {
|
||||
db.Video.load(req.params.videoId)
|
||||
let videoPromise: Promise<VideoInstance>
|
||||
|
||||
if (validator.isUUID(req.params.videoId)) {
|
||||
videoPromise = db.Video.loadByUUID(req.params.videoId)
|
||||
} else {
|
||||
videoPromise = db.Video.load(req.params.videoId)
|
||||
}
|
||||
|
||||
videoPromise
|
||||
.then(video => {
|
||||
if (!video) return res.status(404).send('Video not found')
|
||||
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import 'express-validator'
|
||||
import * as express from 'express'
|
||||
import * as Promise from 'bluebird'
|
||||
import * as validator from 'validator'
|
||||
|
||||
import { database as db } from '../../initializers/database'
|
||||
import { checkErrors } from './utils'
|
||||
import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers'
|
||||
import { logger, isVideoDurationValid } from '../../helpers'
|
||||
import { VideoInstance } from '../../models'
|
||||
|
||||
function videosAddValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
// FIXME: Don't write an error message, it seems there is a bug with express-validator
|
||||
|
@ -40,7 +43,7 @@ function videosAddValidator (req: express.Request, res: express.Response, next:
|
|||
}
|
||||
|
||||
function videosUpdateValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
|
||||
req.checkParams('id', 'Should have a valid id').notEmpty().isVideoIdOrUUIDValid()
|
||||
req.checkBody('name', 'Should have a valid name').optional().isVideoNameValid()
|
||||
req.checkBody('category', 'Should have a valid category').optional().isVideoCategoryValid()
|
||||
req.checkBody('licence', 'Should have a valid licence').optional().isVideoLicenceValid()
|
||||
|
@ -68,7 +71,7 @@ function videosUpdateValidator (req: express.Request, res: express.Response, nex
|
|||
}
|
||||
|
||||
function videosGetValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
|
||||
req.checkParams('id', 'Should have a valid id').notEmpty().isVideoIdOrUUIDValid()
|
||||
|
||||
logger.debug('Checking videosGet parameters', { parameters: req.params })
|
||||
|
||||
|
@ -78,7 +81,7 @@ function videosGetValidator (req: express.Request, res: express.Response, next:
|
|||
}
|
||||
|
||||
function videosRemoveValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
|
||||
req.checkParams('id', 'Should have a valid id').notEmpty().isVideoIdOrUUIDValid()
|
||||
|
||||
logger.debug('Checking videosRemove parameters', { parameters: req.params })
|
||||
|
||||
|
@ -105,7 +108,7 @@ function videosSearchValidator (req: express.Request, res: express.Response, nex
|
|||
}
|
||||
|
||||
function videoAbuseReportValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
|
||||
req.checkParams('id', 'Should have a valid id').notEmpty().isVideoIdOrUUIDValid()
|
||||
req.checkBody('reason', 'Should have a valid reason').isVideoAbuseReasonValid()
|
||||
|
||||
logger.debug('Checking videoAbuseReport parameters', { parameters: req.body })
|
||||
|
@ -116,7 +119,7 @@ function videoAbuseReportValidator (req: express.Request, res: express.Response,
|
|||
}
|
||||
|
||||
function videoRateValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
|
||||
req.checkParams('id', 'Should have a valid id').notEmpty().isVideoIdOrUUIDValid()
|
||||
req.checkBody('rating', 'Should have a valid rate type').isVideoRatingTypeValid()
|
||||
|
||||
logger.debug('Checking videoRate parameters', { parameters: req.body })
|
||||
|
@ -127,7 +130,7 @@ function videoRateValidator (req: express.Request, res: express.Response, next:
|
|||
}
|
||||
|
||||
function videosBlacklistValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
|
||||
req.checkParams('id', 'Should have a valid id').notEmpty().isVideoIdOrUUIDValid()
|
||||
|
||||
logger.debug('Checking videosBlacklist parameters', { parameters: req.params })
|
||||
|
||||
|
@ -157,7 +160,14 @@ export {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
function checkVideoExists (id: string, res: express.Response, callback: () => void) {
|
||||
db.Video.loadAndPopulateAuthorAndPodAndTags(id).then(video => {
|
||||
let promise: Promise<VideoInstance>
|
||||
if (validator.isInt(id)) {
|
||||
promise = db.Video.loadAndPopulateAuthorAndPodAndTags(+id)
|
||||
} else { // UUID
|
||||
promise = db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(id)
|
||||
}
|
||||
|
||||
promise.then(video => {
|
||||
if (!video) return res.status(404).send('Video not found')
|
||||
|
||||
res.locals.video = video
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as Promise from 'bluebird'
|
|||
import { VideoRateType } from '../../../shared/models/videos/video-rate.type'
|
||||
|
||||
export namespace UserVideoRateMethods {
|
||||
export type Load = (userId: number, videoId: string, transaction: Sequelize.Transaction) => Promise<UserVideoRateInstance>
|
||||
export type Load = (userId: number, videoId: number, transaction: Sequelize.Transaction) => Promise<UserVideoRateInstance>
|
||||
}
|
||||
|
||||
export interface UserVideoRateClass {
|
||||
|
|
|
@ -65,7 +65,7 @@ function associate (models) {
|
|||
})
|
||||
}
|
||||
|
||||
load = function (userId: number, videoId: string, transaction: Sequelize.Transaction) {
|
||||
load = function (userId: number, videoId: number, transaction: Sequelize.Transaction) {
|
||||
const options: Sequelize.FindOptions = {
|
||||
where: {
|
||||
userId,
|
||||
|
|
|
@ -47,7 +47,7 @@ function associate (models) {
|
|||
Tag.belongsToMany(models.Video, {
|
||||
foreignKey: 'tagId',
|
||||
through: models.VideoTag,
|
||||
onDelete: 'cascade'
|
||||
onDelete: 'CASCADE'
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ export interface VideoAbuseClass {
|
|||
export interface VideoAbuseAttributes {
|
||||
reporterUsername: string
|
||||
reason: string
|
||||
videoId: string
|
||||
videoId: number
|
||||
}
|
||||
|
||||
export interface VideoAbuseInstance extends VideoAbuseClass, VideoAbuseAttributes, Sequelize.Instance<VideoAbuseAttributes> {
|
||||
|
|
|
@ -96,7 +96,7 @@ function associate (models) {
|
|||
name: 'reporterPodId',
|
||||
allowNull: true
|
||||
},
|
||||
onDelete: 'cascade'
|
||||
onDelete: 'CASCADE'
|
||||
})
|
||||
|
||||
VideoAbuse.belongsTo(models.Video, {
|
||||
|
@ -104,7 +104,7 @@ function associate (models) {
|
|||
name: 'videoId',
|
||||
allowNull: false
|
||||
},
|
||||
onDelete: 'cascade'
|
||||
onDelete: 'CASCADE'
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ export namespace BlacklistedVideoMethods {
|
|||
|
||||
export type LoadById = (id: number) => Promise<BlacklistedVideoInstance>
|
||||
|
||||
export type LoadByVideoId = (id: string) => Promise<BlacklistedVideoInstance>
|
||||
export type LoadByVideoId = (id: number) => Promise<BlacklistedVideoInstance>
|
||||
}
|
||||
|
||||
export interface BlacklistedVideoClass {
|
||||
|
@ -30,7 +30,7 @@ export interface BlacklistedVideoClass {
|
|||
}
|
||||
|
||||
export interface BlacklistedVideoAttributes {
|
||||
videoId: string
|
||||
videoId: number
|
||||
}
|
||||
|
||||
export interface BlacklistedVideoInstance
|
||||
|
|
|
@ -60,8 +60,11 @@ toFormatedJSON = function (this: BlacklistedVideoInstance) {
|
|||
|
||||
function associate (models) {
|
||||
BlacklistedVideo.belongsTo(models.Video, {
|
||||
foreignKey: 'videoId',
|
||||
onDelete: 'cascade'
|
||||
foreignKey: {
|
||||
name: 'videoId',
|
||||
allowNull: false
|
||||
},
|
||||
onDelete: 'CASCADE'
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -92,7 +95,7 @@ loadById = function (id: number) {
|
|||
return BlacklistedVideo.findById(id)
|
||||
}
|
||||
|
||||
loadByVideoId = function (id: string) {
|
||||
loadByVideoId = function (id: number) {
|
||||
const query = {
|
||||
where: {
|
||||
videoId: id
|
||||
|
|
|
@ -9,6 +9,7 @@ import { Video as FormatedVideo } from '../../../shared/models/videos/video.mode
|
|||
import { ResultList } from '../../../shared/models/result-list.model'
|
||||
|
||||
export type FormatedAddRemoteVideo = {
|
||||
uuid: string
|
||||
name: string
|
||||
category: number
|
||||
licence: number
|
||||
|
@ -16,7 +17,6 @@ export type FormatedAddRemoteVideo = {
|
|||
nsfw: boolean
|
||||
description: string
|
||||
infoHash: string
|
||||
remoteId: string
|
||||
author: string
|
||||
duration: number
|
||||
thumbnailData: string
|
||||
|
@ -30,6 +30,7 @@ export type FormatedAddRemoteVideo = {
|
|||
}
|
||||
|
||||
export type FormatedUpdateRemoteVideo = {
|
||||
uuid: string
|
||||
name: string
|
||||
category: number
|
||||
licence: number
|
||||
|
@ -37,7 +38,6 @@ export type FormatedUpdateRemoteVideo = {
|
|||
nsfw: boolean
|
||||
description: string
|
||||
infoHash: string
|
||||
remoteId: string
|
||||
author: string
|
||||
duration: number
|
||||
tags: string[]
|
||||
|
@ -80,10 +80,12 @@ export namespace VideoMethods {
|
|||
sort: string
|
||||
) => Promise< ResultList<VideoInstance> >
|
||||
|
||||
export type Load = (id: string) => Promise<VideoInstance>
|
||||
export type LoadByHostAndRemoteId = (fromHost: string, remoteId: string) => Promise<VideoInstance>
|
||||
export type LoadAndPopulateAuthor = (id: string) => Promise<VideoInstance>
|
||||
export type LoadAndPopulateAuthorAndPodAndTags = (id: string) => Promise<VideoInstance>
|
||||
export type Load = (id: number) => Promise<VideoInstance>
|
||||
export type LoadByUUID = (uuid: string) => Promise<VideoInstance>
|
||||
export type LoadByHostAndUUID = (fromHost: string, uuid: string) => Promise<VideoInstance>
|
||||
export type LoadAndPopulateAuthor = (id: number) => Promise<VideoInstance>
|
||||
export type LoadAndPopulateAuthorAndPodAndTags = (id: number) => Promise<VideoInstance>
|
||||
export type LoadByUUIDAndPopulateAuthorAndPodAndTags = (uuid: string) => Promise<VideoInstance>
|
||||
}
|
||||
|
||||
export interface VideoClass {
|
||||
|
@ -102,19 +104,21 @@ export interface VideoClass {
|
|||
getDurationFromFile: VideoMethods.GetDurationFromFile
|
||||
list: VideoMethods.List
|
||||
listForApi: VideoMethods.ListForApi
|
||||
loadByHostAndRemoteId: VideoMethods.LoadByHostAndRemoteId
|
||||
loadByHostAndUUID: VideoMethods.LoadByHostAndUUID
|
||||
listOwnedAndPopulateAuthorAndTags: VideoMethods.ListOwnedAndPopulateAuthorAndTags
|
||||
listOwnedByAuthor: VideoMethods.ListOwnedByAuthor
|
||||
load: VideoMethods.Load
|
||||
loadByUUID: VideoMethods.LoadByUUID
|
||||
loadAndPopulateAuthor: VideoMethods.LoadAndPopulateAuthor
|
||||
loadAndPopulateAuthorAndPodAndTags: VideoMethods.LoadAndPopulateAuthorAndPodAndTags
|
||||
loadByUUIDAndPopulateAuthorAndPodAndTags: VideoMethods.LoadByUUIDAndPopulateAuthorAndPodAndTags
|
||||
searchAndPopulateAuthorAndPodAndTags: VideoMethods.SearchAndPopulateAuthorAndPodAndTags
|
||||
}
|
||||
|
||||
export interface VideoAttributes {
|
||||
uuid?: string
|
||||
name: string
|
||||
extname: string
|
||||
remoteId: string
|
||||
category: number
|
||||
licence: number
|
||||
language: number
|
||||
|
@ -125,13 +129,14 @@ export interface VideoAttributes {
|
|||
views?: number
|
||||
likes?: number
|
||||
dislikes?: number
|
||||
remote: boolean
|
||||
|
||||
Author?: AuthorInstance
|
||||
Tags?: TagInstance[]
|
||||
}
|
||||
|
||||
export interface VideoInstance extends VideoClass, VideoAttributes, Sequelize.Instance<VideoAttributes> {
|
||||
id: string
|
||||
id: number
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
|
||||
|
|
|
@ -62,21 +62,23 @@ let generateThumbnailFromData: VideoMethods.GenerateThumbnailFromData
|
|||
let getDurationFromFile: VideoMethods.GetDurationFromFile
|
||||
let list: VideoMethods.List
|
||||
let listForApi: VideoMethods.ListForApi
|
||||
let loadByHostAndRemoteId: VideoMethods.LoadByHostAndRemoteId
|
||||
let loadByHostAndUUID: VideoMethods.LoadByHostAndUUID
|
||||
let listOwnedAndPopulateAuthorAndTags: VideoMethods.ListOwnedAndPopulateAuthorAndTags
|
||||
let listOwnedByAuthor: VideoMethods.ListOwnedByAuthor
|
||||
let load: VideoMethods.Load
|
||||
let loadByUUID: VideoMethods.LoadByUUID
|
||||
let loadAndPopulateAuthor: VideoMethods.LoadAndPopulateAuthor
|
||||
let loadAndPopulateAuthorAndPodAndTags: VideoMethods.LoadAndPopulateAuthorAndPodAndTags
|
||||
let loadByUUIDAndPopulateAuthorAndPodAndTags: VideoMethods.LoadByUUIDAndPopulateAuthorAndPodAndTags
|
||||
let searchAndPopulateAuthorAndPodAndTags: VideoMethods.SearchAndPopulateAuthorAndPodAndTags
|
||||
|
||||
export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
|
||||
Video = sequelize.define<VideoInstance, VideoAttributes>('Video',
|
||||
{
|
||||
id: {
|
||||
uuid: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
allowNull: false,
|
||||
validate: {
|
||||
isUUID: 4
|
||||
}
|
||||
|
@ -95,13 +97,6 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
|||
type: DataTypes.ENUM(values(CONSTRAINTS_FIELDS.VIDEOS.EXTNAME)),
|
||||
allowNull: false
|
||||
},
|
||||
remoteId: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: true,
|
||||
validate: {
|
||||
isUUID: 4
|
||||
}
|
||||
},
|
||||
category: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
|
@ -199,6 +194,11 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
|||
min: 0,
|
||||
isInt: true
|
||||
}
|
||||
},
|
||||
remote: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -206,9 +206,6 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
|||
{
|
||||
fields: [ 'authorId' ]
|
||||
},
|
||||
{
|
||||
fields: [ 'remoteId' ]
|
||||
},
|
||||
{
|
||||
fields: [ 'name' ]
|
||||
},
|
||||
|
@ -226,6 +223,9 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
|||
},
|
||||
{
|
||||
fields: [ 'likes' ]
|
||||
},
|
||||
{
|
||||
fields: [ 'uuid' ]
|
||||
}
|
||||
],
|
||||
hooks: {
|
||||
|
@ -246,9 +246,11 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
|||
listOwnedAndPopulateAuthorAndTags,
|
||||
listOwnedByAuthor,
|
||||
load,
|
||||
loadByHostAndRemoteId,
|
||||
loadByUUID,
|
||||
loadByHostAndUUID,
|
||||
loadAndPopulateAuthor,
|
||||
loadAndPopulateAuthorAndPodAndTags,
|
||||
loadByUUIDAndPopulateAuthorAndPodAndTags,
|
||||
searchAndPopulateAuthorAndPodAndTags,
|
||||
removeFromBlacklist
|
||||
]
|
||||
|
@ -289,8 +291,9 @@ function beforeCreate (video: VideoInstance, options: { transaction: Sequelize.T
|
|||
)
|
||||
|
||||
if (CONFIG.TRANSCODING.ENABLED === true) {
|
||||
// Put uuid because we don't have id auto incremented for now
|
||||
const dataInput = {
|
||||
id: video.id
|
||||
videoUUID: video.uuid
|
||||
}
|
||||
|
||||
tasks.push(
|
||||
|
@ -313,7 +316,7 @@ function afterDestroy (video: VideoInstance) {
|
|||
|
||||
if (video.isOwned()) {
|
||||
const removeVideoToFriendsParams = {
|
||||
remoteId: video.id
|
||||
uuid: video.uuid
|
||||
}
|
||||
|
||||
tasks.push(
|
||||
|
@ -381,34 +384,27 @@ generateMagnetUri = function (this: VideoInstance) {
|
|||
}
|
||||
|
||||
getVideoFilename = function (this: VideoInstance) {
|
||||
if (this.isOwned()) return this.id + this.extname
|
||||
|
||||
return this.remoteId + this.extname
|
||||
return this.uuid + this.extname
|
||||
}
|
||||
|
||||
getThumbnailName = function (this: VideoInstance) {
|
||||
// We always have a copy of the thumbnail
|
||||
return this.id + '.jpg'
|
||||
const extension = '.jpg'
|
||||
return this.uuid + extension
|
||||
}
|
||||
|
||||
getPreviewName = function (this: VideoInstance) {
|
||||
const extension = '.jpg'
|
||||
|
||||
if (this.isOwned()) return this.id + extension
|
||||
|
||||
return this.remoteId + extension
|
||||
return this.uuid + extension
|
||||
}
|
||||
|
||||
getTorrentName = function (this: VideoInstance) {
|
||||
const extension = '.torrent'
|
||||
|
||||
if (this.isOwned()) return this.id + extension
|
||||
|
||||
return this.remoteId + extension
|
||||
return this.uuid + extension
|
||||
}
|
||||
|
||||
isOwned = function (this: VideoInstance) {
|
||||
return this.remoteId === null
|
||||
return this.remote === false
|
||||
}
|
||||
|
||||
toFormatedJSON = function (this: VideoInstance) {
|
||||
|
@ -435,6 +431,7 @@ toFormatedJSON = function (this: VideoInstance) {
|
|||
|
||||
const json = {
|
||||
id: this.id,
|
||||
uuid: this.uuid,
|
||||
name: this.name,
|
||||
category: this.category,
|
||||
categoryLabel,
|
||||
|
@ -467,6 +464,7 @@ toAddRemoteJSON = function (this: VideoInstance) {
|
|||
|
||||
return readFileBufferPromise(thumbnailPath).then(thumbnailData => {
|
||||
const remoteVideo = {
|
||||
uuid: this.uuid,
|
||||
name: this.name,
|
||||
category: this.category,
|
||||
licence: this.licence,
|
||||
|
@ -474,7 +472,6 @@ toAddRemoteJSON = function (this: VideoInstance) {
|
|||
nsfw: this.nsfw,
|
||||
description: this.description,
|
||||
infoHash: this.infoHash,
|
||||
remoteId: this.id,
|
||||
author: this.Author.name,
|
||||
duration: this.duration,
|
||||
thumbnailData: thumbnailData.toString('binary'),
|
||||
|
@ -493,6 +490,7 @@ toAddRemoteJSON = function (this: VideoInstance) {
|
|||
|
||||
toUpdateRemoteJSON = function (this: VideoInstance) {
|
||||
const json = {
|
||||
uuid: this.uuid,
|
||||
name: this.name,
|
||||
category: this.category,
|
||||
licence: this.licence,
|
||||
|
@ -500,7 +498,6 @@ toUpdateRemoteJSON = function (this: VideoInstance) {
|
|||
nsfw: this.nsfw,
|
||||
description: this.description,
|
||||
infoHash: this.infoHash,
|
||||
remoteId: this.id,
|
||||
author: this.Author.name,
|
||||
duration: this.duration,
|
||||
tags: map<TagInstance, string>(this.Tags, 'name'),
|
||||
|
@ -615,10 +612,10 @@ listForApi = function (start: number, count: number, sort: string) {
|
|||
})
|
||||
}
|
||||
|
||||
loadByHostAndRemoteId = function (fromHost: string, remoteId: string) {
|
||||
loadByHostAndUUID = function (fromHost: string, uuid: string) {
|
||||
const query = {
|
||||
where: {
|
||||
remoteId: remoteId
|
||||
uuid
|
||||
},
|
||||
include: [
|
||||
{
|
||||
|
@ -640,10 +637,9 @@ loadByHostAndRemoteId = function (fromHost: string, remoteId: string) {
|
|||
}
|
||||
|
||||
listOwnedAndPopulateAuthorAndTags = function () {
|
||||
// If remoteId is null this is *our* video
|
||||
const query = {
|
||||
where: {
|
||||
remoteId: null
|
||||
remote: false
|
||||
},
|
||||
include: [ Video['sequelize'].models.Author, Video['sequelize'].models.Tag ]
|
||||
}
|
||||
|
@ -654,7 +650,7 @@ listOwnedAndPopulateAuthorAndTags = function () {
|
|||
listOwnedByAuthor = function (author: string) {
|
||||
const query = {
|
||||
where: {
|
||||
remoteId: null
|
||||
remote: false
|
||||
},
|
||||
include: [
|
||||
{
|
||||
|
@ -669,11 +665,20 @@ listOwnedByAuthor = function (author: string) {
|
|||
return Video.findAll(query)
|
||||
}
|
||||
|
||||
load = function (id: string) {
|
||||
load = function (id: number) {
|
||||
return Video.findById(id)
|
||||
}
|
||||
|
||||
loadAndPopulateAuthor = function (id: string) {
|
||||
loadByUUID = function (uuid: string) {
|
||||
const query = {
|
||||
where: {
|
||||
uuid
|
||||
}
|
||||
}
|
||||
return Video.findOne(query)
|
||||
}
|
||||
|
||||
loadAndPopulateAuthor = function (id: number) {
|
||||
const options = {
|
||||
include: [ Video['sequelize'].models.Author ]
|
||||
}
|
||||
|
@ -681,7 +686,7 @@ loadAndPopulateAuthor = function (id: string) {
|
|||
return Video.findById(id, options)
|
||||
}
|
||||
|
||||
loadAndPopulateAuthorAndPodAndTags = function (id: string) {
|
||||
loadAndPopulateAuthorAndPodAndTags = function (id: number) {
|
||||
const options = {
|
||||
include: [
|
||||
{
|
||||
|
@ -695,6 +700,23 @@ loadAndPopulateAuthorAndPodAndTags = function (id: string) {
|
|||
return Video.findById(id, options)
|
||||
}
|
||||
|
||||
loadByUUIDAndPopulateAuthorAndPodAndTags = function (uuid: string) {
|
||||
const options = {
|
||||
where: {
|
||||
uuid
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: Video['sequelize'].models.Author,
|
||||
include: [ { model: Video['sequelize'].models.Pod, required: false } ]
|
||||
},
|
||||
Video['sequelize'].models.Tag
|
||||
]
|
||||
}
|
||||
|
||||
return Video.findOne(options)
|
||||
}
|
||||
|
||||
searchAndPopulateAuthorAndPodAndTags = function (value: string, field: string, start: number, count: number, sort: string) {
|
||||
const podInclude: Sequelize.IncludeOptions = {
|
||||
model: Video['sequelize'].models.Pod,
|
||||
|
|
|
@ -44,7 +44,7 @@ describe('Test remote videos API validators', function () {
|
|||
describe('When adding a video', function () {
|
||||
it('Should check when adding a video')
|
||||
|
||||
it('Should not add an existing remoteId and host pair')
|
||||
it('Should not add an existing uuid')
|
||||
})
|
||||
|
||||
describe('When removing a video', function () {
|
||||
|
|
|
@ -20,6 +20,7 @@ const videosUtils = require('../utils/videos')
|
|||
describe('Test multiple pods', function () {
|
||||
let servers = []
|
||||
const toRemove = []
|
||||
let videoUUID = ''
|
||||
|
||||
before(function (done) {
|
||||
this.timeout(120000)
|
||||
|
@ -746,6 +747,36 @@ describe('Test multiple pods', function () {
|
|||
expect(videos[0].name).not.to.equal(toRemove[1].name)
|
||||
expect(videos[1].name).not.to.equal(toRemove[1].name)
|
||||
|
||||
videoUUID = videos[0].uuid
|
||||
|
||||
callback()
|
||||
})
|
||||
}, done)
|
||||
})
|
||||
|
||||
it('Should get the same video by UUID on each pod', function (done) {
|
||||
let baseVideo = null
|
||||
each(servers, function (server, callback) {
|
||||
videosUtils.getVideo(server.url, videoUUID, function (err, res) {
|
||||
if (err) throw err
|
||||
|
||||
const video = res.body
|
||||
|
||||
if (baseVideo === null) {
|
||||
baseVideo = video
|
||||
return callback()
|
||||
}
|
||||
|
||||
expect(baseVideo.name).to.equal(video.name)
|
||||
expect(baseVideo.uuid).to.equal(video.uuid)
|
||||
expect(baseVideo.category).to.equal(video.category)
|
||||
expect(baseVideo.language).to.equal(video.language)
|
||||
expect(baseVideo.licence).to.equal(video.licence)
|
||||
expect(baseVideo.category).to.equal(video.category)
|
||||
expect(baseVideo.nsfw).to.equal(video.nsfw)
|
||||
expect(baseVideo.author).to.equal(video.author)
|
||||
expect(baseVideo.tags).to.deep.equal(video.tags)
|
||||
|
||||
callback()
|
||||
})
|
||||
}, done)
|
||||
|
|
|
@ -19,6 +19,7 @@ const videosUtils = require('../utils/videos')
|
|||
describe('Test a single pod', function () {
|
||||
let server = null
|
||||
let videoId = -1
|
||||
let videoUUID = ''
|
||||
let videosListBase = null
|
||||
|
||||
before(function (done) {
|
||||
|
@ -140,6 +141,7 @@ describe('Test a single pod', function () {
|
|||
expect(test).to.equal(true)
|
||||
|
||||
videoId = video.id
|
||||
videoUUID = video.uuid
|
||||
|
||||
webtorrent.add(video.magnetUri, function (torrent) {
|
||||
expect(torrent.files).to.exist
|
||||
|
@ -181,18 +183,33 @@ describe('Test a single pod', function () {
|
|||
if (err) throw err
|
||||
expect(test).to.equal(true)
|
||||
|
||||
// Wait the async views increment
|
||||
// Wait the async views increment
|
||||
setTimeout(done, 500)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('Should get the video by UUID', function (done) {
|
||||
// Yes, this could be long
|
||||
this.timeout(60000)
|
||||
|
||||
videosUtils.getVideo(server.url, videoUUID, function (err, res) {
|
||||
if (err) throw err
|
||||
|
||||
const video = res.body
|
||||
expect(video.name).to.equal('my super name')
|
||||
|
||||
// Wait the async views increment
|
||||
setTimeout(done, 500)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should have the views updated', function (done) {
|
||||
videosUtils.getVideo(server.url, videoId, function (err, res) {
|
||||
if (err) throw err
|
||||
|
||||
const video = res.body
|
||||
expect(video.views).to.equal(1)
|
||||
expect(video.views).to.equal(2)
|
||||
|
||||
done()
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export interface RemoteQaduVideoData {
|
||||
remoteId: string
|
||||
uuid: string
|
||||
views?: number
|
||||
likes?: number
|
||||
dislikes?: number
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { RemoteVideoRequest } from './remote-video-request.model'
|
||||
|
||||
export interface RemoteVideoCreateData {
|
||||
remoteId: string
|
||||
uuid: string
|
||||
author: string
|
||||
tags: string[]
|
||||
name: string
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
export type RemoteVideoEventType = 'views' | 'likes' | 'dislikes'
|
||||
|
||||
export interface RemoteVideoEventData {
|
||||
remoteId: string
|
||||
uuid: string
|
||||
eventType: RemoteVideoEventType
|
||||
count: number
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { RemoteVideoRequest } from './remote-video-request.model'
|
||||
|
||||
export interface RemoteVideoRemoveData {
|
||||
remoteId: string
|
||||
uuid: string
|
||||
}
|
||||
|
||||
export interface RemoteVideoRemoveRequest extends RemoteVideoRequest {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { RemoteVideoRequest } from './remote-video-request.model'
|
||||
|
||||
export interface RemoteVideoReportAbuseData {
|
||||
videoRemoteId: string
|
||||
videoUUID: string
|
||||
reporterUsername: string
|
||||
reportReason: string
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export interface RemoteVideoUpdateData {
|
||||
remoteId: string
|
||||
uuid: string
|
||||
tags: string[]
|
||||
name: string
|
||||
extname: string
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { UserVideoRateType } from './user-video-rate.type'
|
||||
|
||||
export interface UserVideoRate {
|
||||
videoId: string
|
||||
videoId: number
|
||||
rating: UserVideoRateType
|
||||
}
|
||||
|
|
|
@ -3,6 +3,6 @@ export interface VideoAbuse {
|
|||
reporterPodHost: string
|
||||
reason: string
|
||||
reporterUsername: string
|
||||
videoId: string
|
||||
videoId: number
|
||||
createdAt: Date
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export interface BlacklistedVideo {
|
||||
id: number
|
||||
videoId: string
|
||||
videoId: number
|
||||
createdAt: Date
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export interface Video {
|
||||
id: string
|
||||
id: number
|
||||
uuid: string
|
||||
author: string
|
||||
createdAt: Date
|
||||
categoryLabel: string
|
||||
|
|
Loading…
Reference in New Issue