diff --git a/client/src/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts index bf12876c7..7beea5910 100644 --- a/client/src/app/shared/users/user.model.ts +++ b/client/src/app/shared/users/user.model.ts @@ -1,5 +1,23 @@ -import { User as UserServerModel, UserRole } from '../../../../../shared' +import { + User as UserServerModel, + UserRole, + VideoChannel +} from '../../../../../shared' +export type UserConstructorHash = { + id: number, + username: string, + email: string, + role: UserRole, + videoQuota?: number, + displayNSFW?: boolean, + createdAt?: Date, + author?: { + id: number + uuid: string + }, + videoChannels?: VideoChannel[] +} export class User implements UserServerModel { id: number username: string @@ -7,21 +25,23 @@ export class User implements UserServerModel { role: UserRole displayNSFW: boolean videoQuota: number + author: { + id: number + uuid: string + } + videoChannels: VideoChannel[] createdAt: Date - constructor (hash: { - id: number, - username: string, - email: string, - role: UserRole, - videoQuota?: number, - displayNSFW?: boolean, - createdAt?: Date - }) { + constructor (hash: UserConstructorHash) { this.id = hash.id this.username = hash.username this.email = hash.email this.role = hash.role + this.author = hash.author + + if (hash.videoChannels !== undefined) { + this.videoChannels = hash.videoChannels + } if (hash.videoQuota !== undefined) { this.videoQuota = hash.videoQuota diff --git a/client/src/app/videos/+video-edit/video-update.component.ts b/client/src/app/videos/+video-edit/video-update.component.ts index 6d45265e7..70cb334fd 100644 --- a/client/src/app/videos/+video-edit/video-update.component.ts +++ b/client/src/app/videos/+video-edit/video-update.component.ts @@ -14,7 +14,7 @@ import { VIDEO_DESCRIPTION, VIDEO_TAGS } from '../../shared' -import { Video, VideoService } from '../shared' +import { VideoEdit, VideoService } from '../shared' @Component({ selector: 'my-videos-update', @@ -27,7 +27,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { videoCategories = [] videoLicences = [] videoLanguages = [] - video: Video + video: VideoEdit tagValidators = VIDEO_TAGS.VALIDATORS tagValidatorsMessages = VIDEO_TAGS.MESSAGES diff --git a/client/src/app/videos/+video-watch/video-download.component.ts b/client/src/app/videos/+video-watch/video-download.component.ts index 22149aa6b..c32f8d586 100644 --- a/client/src/app/videos/+video-watch/video-download.component.ts +++ b/client/src/app/videos/+video-watch/video-download.component.ts @@ -2,7 +2,7 @@ import { Component, Input, ViewChild } from '@angular/core' import { ModalDirective } from 'ngx-bootstrap/modal' -import { Video } from '../shared' +import { VideoDetails } from '../shared' @Component({ selector: 'my-video-download', @@ -10,7 +10,7 @@ import { Video } from '../shared' styles: [ '.resolution-block { margin-top: 20px; }' ] }) export class VideoDownloadComponent { - @Input() video: Video = null + @Input() video: VideoDetails = null @ViewChild('modal') modal: ModalDirective diff --git a/client/src/app/videos/+video-watch/video-report.component.ts b/client/src/app/videos/+video-watch/video-report.component.ts index d9c83a640..fc9b5a9d4 100644 --- a/client/src/app/videos/+video-watch/video-report.component.ts +++ b/client/src/app/videos/+video-watch/video-report.component.ts @@ -5,14 +5,14 @@ import { ModalDirective } from 'ngx-bootstrap/modal' import { NotificationsService } from 'angular2-notifications' import { FormReactive, VideoAbuseService, VIDEO_ABUSE_REASON } from '../../shared' -import { Video, VideoService } from '../shared' +import { VideoDetails, VideoService } from '../shared' @Component({ selector: 'my-video-report', templateUrl: './video-report.component.html' }) export class VideoReportComponent extends FormReactive implements OnInit { - @Input() video: Video = null + @Input() video: VideoDetails = null @ViewChild('modal') modal: ModalDirective diff --git a/client/src/app/videos/+video-watch/video-share.component.ts b/client/src/app/videos/+video-watch/video-share.component.ts index 414ed28c6..aeef65ecf 100644 --- a/client/src/app/videos/+video-watch/video-share.component.ts +++ b/client/src/app/videos/+video-watch/video-share.component.ts @@ -2,14 +2,14 @@ import { Component, Input, ViewChild } from '@angular/core' import { ModalDirective } from 'ngx-bootstrap/modal' -import { Video } from '../shared' +import { VideoDetails } from '../shared' @Component({ selector: 'my-video-share', templateUrl: './video-share.component.html' }) export class VideoShareComponent { - @Input() video: Video = null + @Input() video: VideoDetails = null @ViewChild('modal') modal: ModalDirective diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index f45ffd82f..529e2e84f 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts @@ -13,7 +13,7 @@ import { AuthService, ConfirmService } from '../../core' import { VideoDownloadComponent } from './video-download.component' import { VideoShareComponent } from './video-share.component' import { VideoReportComponent } from './video-report.component' -import { Video, VideoService } from '../shared' +import { VideoDetails, VideoService } from '../shared' import { VideoBlacklistService } from '../../shared' import { UserVideoRateType, VideoRateType } from '../../../../../shared' @@ -35,7 +35,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { playerElement: HTMLMediaElement uploadSpeed: number userRating: UserVideoRateType = null - video: Video = null + video: VideoDetails = null videoPlayerLoaded = false videoNotFound = false @@ -211,7 +211,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { ) } - private onVideoFetched (video: Video) { + private onVideoFetched (video: VideoDetails) { this.video = video let observable diff --git a/client/src/app/videos/shared/index.ts b/client/src/app/videos/shared/index.ts index 8168e3bfd..dcaa4e090 100644 --- a/client/src/app/videos/shared/index.ts +++ b/client/src/app/videos/shared/index.ts @@ -1,4 +1,6 @@ export * from './sort-field.type' export * from './video.model' +export * from './video-details.model' +export * from './video-edit.model' export * from './video.service' export * from './video-pagination.model' diff --git a/client/src/app/videos/shared/video-details.model.ts b/client/src/app/videos/shared/video-details.model.ts new file mode 100644 index 000000000..e99a5ce2e --- /dev/null +++ b/client/src/app/videos/shared/video-details.model.ts @@ -0,0 +1,75 @@ +import { Video } from './video.model' +import { + VideoDetails as VideoDetailsServerModel, + VideoFile, + VideoChannel, + VideoResolution +} from '../../../../../shared' + +export class VideoDetails extends Video implements VideoDetailsServerModel { + author: string + by: string + createdAt: Date + updatedAt: Date + categoryLabel: string + category: number + licenceLabel: string + licence: number + languageLabel: string + language: number + description: string + duration: number + durationLabel: string + id: number + uuid: string + isLocal: boolean + name: string + podHost: string + tags: string[] + thumbnailPath: string + thumbnailUrl: string + previewPath: string + previewUrl: string + embedPath: string + embedUrl: string + views: number + likes: number + dislikes: number + nsfw: boolean + files: VideoFile[] + channel: VideoChannel + + constructor (hash: VideoDetailsServerModel) { + super(hash) + + this.files = hash.files + this.channel = hash.channel + } + + getAppropriateMagnetUri (actualDownloadSpeed = 0) { + if (this.files === undefined || this.files.length === 0) return '' + if (this.files.length === 1) return this.files[0].magnetUri + + // Find first video that is good for our download speed (remember they are sorted) + let betterResolutionFile = this.files.find(f => actualDownloadSpeed > (f.size / this.duration)) + + // If the download speed is too bad, return the lowest resolution we have + if (betterResolutionFile === undefined) { + betterResolutionFile = this.files.find(f => f.resolution === VideoResolution.H_240P) + } + + return betterResolutionFile.magnetUri + } + + isRemovableBy (user) { + return user && this.isLocal === true && (this.author === user.username || user.isAdmin() === true) + } + + isBlackistableBy (user) { + return user && user.isAdmin() === true && this.isLocal === false + } + + isUpdatableBy (user) { + return user && this.isLocal === true && user.username === this.author + } +} diff --git a/client/src/app/videos/shared/video-edit.model.ts b/client/src/app/videos/shared/video-edit.model.ts new file mode 100644 index 000000000..f30d8feba --- /dev/null +++ b/client/src/app/videos/shared/video-edit.model.ts @@ -0,0 +1,31 @@ +export class VideoEdit { + category: number + licence: number + language: number + description: string + name: string + tags: string[] + nsfw: boolean + channel: number + uuid?: string + id?: number + + patch (values: Object) { + Object.keys(values).forEach((key) => { + this[key] = values[key] + }) + } + + toJSON () { + return { + category: this.category, + licence: this.licence, + language: this.language, + description: this.description, + name: this.name, + tags: this.tags, + nsfw: this.nsfw, + channel: this.channel + } + } +} diff --git a/client/src/app/videos/shared/video.model.ts b/client/src/app/videos/shared/video.model.ts index 6e8dfaa6f..7f2871032 100644 --- a/client/src/app/videos/shared/video.model.ts +++ b/client/src/app/videos/shared/video.model.ts @@ -1,6 +1,5 @@ -import { Video as VideoServerModel, VideoFile } from '../../../../../shared' +import { Video as VideoServerModel } from '../../../../../shared' import { User } from '../../shared' -import { VideoResolution } from '../../../../../shared/models/videos/video-resolution.enum' export class Video implements VideoServerModel { author: string @@ -32,7 +31,6 @@ export class Video implements VideoServerModel { likes: number dislikes: number nsfw: boolean - files: VideoFile[] private static createByString (author: string, podHost: string) { return author + '@' + podHost @@ -47,32 +45,7 @@ export class Video implements VideoServerModel { return minutesPadding + minutes.toString() + ':' + secondsPadding + seconds.toString() } - constructor (hash: { - author: string, - createdAt: Date | string, - categoryLabel: string, - category: number, - licenceLabel: string, - licence: number, - languageLabel: string - language: number - description: string, - duration: number - id: number, - uuid: string, - isLocal: boolean, - name: string, - podHost: string, - tags: string[], - thumbnailPath: string, - previewPath: string, - embedPath: string, - views: number, - likes: number, - dislikes: number, - nsfw: boolean, - files: VideoFile[] - }) { + constructor (hash: VideoServerModel) { let absoluteAPIUrl = API_URL if (!absoluteAPIUrl) { // The API is on the same domain @@ -106,69 +79,12 @@ export class Video implements VideoServerModel { this.likes = hash.likes this.dislikes = hash.dislikes this.nsfw = hash.nsfw - this.files = hash.files this.by = Video.createByString(hash.author, hash.podHost) } - isRemovableBy (user) { - return user && this.isLocal === true && (this.author === user.username || user.isAdmin() === true) - } - - isBlackistableBy (user) { - return user && user.isAdmin() === true && this.isLocal === false - } - - isUpdatableBy (user) { - return user && this.isLocal === true && user.username === this.author - } - isVideoNSFWForUser (user: User) { // If the video is NSFW and the user is not logged in, or the user does not want to display NSFW videos... return (this.nsfw && (!user || user.displayNSFW === false)) } - - getAppropriateMagnetUri (actualDownloadSpeed = 0) { - if (this.files === undefined || this.files.length === 0) return '' - if (this.files.length === 1) return this.files[0].magnetUri - - // Find first video that is good for our download speed (remember they are sorted) - let betterResolutionFile = this.files.find(f => actualDownloadSpeed > (f.size / this.duration)) - - // If the download speed is too bad, return the lowest resolution we have - if (betterResolutionFile === undefined) { - betterResolutionFile = this.files.find(f => f.resolution === VideoResolution.H_240P) - } - - return betterResolutionFile.magnetUri - } - - patch (values: Object) { - Object.keys(values).forEach((key) => { - this[key] = values[key] - }) - } - - toJSON () { - return { - author: this.author, - createdAt: this.createdAt, - category: this.category, - licence: this.licence, - language: this.language, - description: this.description, - duration: this.duration, - id: this.id, - isLocal: this.isLocal, - name: this.name, - podHost: this.podHost, - tags: this.tags, - thumbnailPath: this.thumbnailPath, - views: this.views, - likes: this.likes, - dislikes: this.dislikes, - nsfw: this.nsfw, - files: this.files - } - } } diff --git a/client/src/app/videos/shared/video.service.ts b/client/src/app/videos/shared/video.service.ts index fc552f2b5..06fb3313e 100644 --- a/client/src/app/videos/shared/video.service.ts +++ b/client/src/app/videos/shared/video.service.ts @@ -12,6 +12,8 @@ import { UserService } from '../../shared' import { Video } from './video.model' +import { VideoDetails } from './video-details.model' +import { VideoEdit } from './video-edit.model' import { VideoPagination } from './video-pagination.model' import { UserVideoRate, @@ -20,6 +22,7 @@ import { VideoAbuseCreate, UserVideoRateUpdate, Video as VideoServerModel, + VideoDetails as VideoDetailsServerModel, ResultList } from '../../../../../shared' @@ -34,12 +37,12 @@ export class VideoService { ) {} getVideo (uuid: string) { - return this.authHttp.get(VideoService.BASE_VIDEO_URL + uuid) - .map(videoHash => new Video(videoHash)) + return this.authHttp.get(VideoService.BASE_VIDEO_URL + uuid) + .map(videoHash => new VideoDetails(videoHash)) .catch((res) => this.restExtractor.handleError(res)) } - updateVideo (video: Video) { + updateVideo (video: VideoEdit) { const language = video.language ? video.language : null const body: VideoUpdate = { diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts index f2f339bcc..f696df968 100644 --- a/client/src/standalone/videos/embed.ts +++ b/client/src/standalone/videos/embed.ts @@ -3,9 +3,9 @@ import './embed.scss' import videojs from 'video.js' import '../../assets/player/peertube-videojs-plugin' import 'videojs-dock/dist/videojs-dock.es.js' -import { Video } from '../../../../shared' +import { VideoDetails } from '../../../../shared' -function loadVideoInfo (videoId: string, callback: (err: Error, res?: Video) => void) { +function loadVideoInfo (videoId: string, callback: (err: Error, res?: VideoDetails) => void) { const xhttp = new XMLHttpRequest() xhttp.onreadystatechange = function () { if (this.readyState === 4 && this.status === 200) { diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts index 8b81a61e1..0ebbf48a8 100644 --- a/server/helpers/utils.ts +++ b/server/helpers/utils.ts @@ -1,6 +1,5 @@ import * as express from 'express' import * as Sequelize from 'sequelize' -import * as Promise from 'bluebird' import { pseudoRandomBytesPromise } from './core-utils' import { CONFIG, database as db } from '../initializers'