X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fmodels%2Fvideo%2Fvideo.ts;h=c006a91af0f1458978165cd40998776072455274;hb=29837f8885eb37fa300e4b80c90a6d03ab337084;hp=f3782fb434d7ba4f549f5c452c52c716433a9589;hpb=7c3a6636fdd9b905345996d825c249a18add8a2c;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/models/video/video.ts b/server/models/video/video.ts index f3782fb43..c006a91af 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -26,12 +26,13 @@ import { } from 'sequelize-typescript' import { setAsUpdated } from '@server/helpers/database-utils' import { buildNSFWFilter } from '@server/helpers/express-utils' +import { uuidToShort } from '@server/helpers/uuid' import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video' -import { LiveManager } from '@server/lib/live-manager' +import { LiveManager } from '@server/lib/live/live-manager' import { getHLSDirectory, getVideoFilePath } from '@server/lib/video-paths' import { getServerActor } from '@server/models/application/application' import { ModelCache } from '@server/models/model-cache' -import { AttributesOnly } from '@shared/core-utils' +import { AttributesOnly, buildVideoEmbedPath, buildVideoWatchPath } from '@shared/core-utils' import { VideoFile } from '@shared/models/videos/video-file.model' import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared' import { VideoObject } from '../../../shared/models/activitypub/objects' @@ -43,11 +44,8 @@ import { peertubeTruncate } from '../../helpers/core-utils' import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' import { isBooleanValid } from '../../helpers/custom-validators/misc' import { - isVideoCategoryValid, isVideoDescriptionValid, isVideoDurationValid, - isVideoLanguageValid, - isVideoLicenceValid, isVideoNameValid, isVideoPrivacyValid, isVideoStateValid, @@ -56,19 +54,7 @@ import { import { getVideoFileResolution } from '../../helpers/ffprobe-utils' import { logger } from '../../helpers/logger' import { CONFIG } from '../../initializers/config' -import { - ACTIVITY_PUB, - API_VERSION, - CONSTRAINTS_FIELDS, - LAZY_STATIC_PATHS, - STATIC_PATHS, - VIDEO_CATEGORIES, - VIDEO_LANGUAGES, - VIDEO_LICENCES, - VIDEO_PRIVACIES, - VIDEO_STATES, - WEBSERVER -} from '../../initializers/constants' +import { ACTIVITY_PUB, API_VERSION, CONSTRAINTS_FIELDS, LAZY_STATIC_PATHS, STATIC_PATHS, WEBSERVER } from '../../initializers/constants' import { sendDeleteVideo } from '../../lib/activitypub/send' import { MChannel, @@ -136,20 +122,16 @@ import { VideoTagModel } from './video-tag' import { VideoViewModel } from './video-view' export enum ScopeNames { - AVAILABLE_FOR_LIST_IDS = 'AVAILABLE_FOR_LIST_IDS', FOR_API = 'FOR_API', WITH_ACCOUNT_DETAILS = 'WITH_ACCOUNT_DETAILS', WITH_TAGS = 'WITH_TAGS', - WITH_TRACKERS = 'WITH_TRACKERS', WITH_WEBTORRENT_FILES = 'WITH_WEBTORRENT_FILES', WITH_SCHEDULED_UPDATE = 'WITH_SCHEDULED_UPDATE', WITH_BLACKLISTED = 'WITH_BLACKLISTED', - WITH_USER_HISTORY = 'WITH_USER_HISTORY', WITH_STREAMING_PLAYLISTS = 'WITH_STREAMING_PLAYLISTS', - WITH_USER_ID = 'WITH_USER_ID', WITH_IMMUTABLE_ATTRIBUTES = 'WITH_IMMUTABLE_ATTRIBUTES', - WITH_THUMBNAILS = 'WITH_THUMBNAILS', - WITH_LIVE = 'WITH_LIVE' + WITH_USER_HISTORY = 'WITH_USER_HISTORY', + WITH_THUMBNAILS = 'WITH_THUMBNAILS' } export type ForAPIOptions = { @@ -245,30 +227,6 @@ export type AvailableForListIDsOptions = { } ] }, - [ScopeNames.WITH_LIVE]: { - include: [ - { - model: VideoLiveModel.unscoped(), - required: false - } - ] - }, - [ScopeNames.WITH_USER_ID]: { - include: [ - { - attributes: [ 'accountId' ], - model: VideoChannelModel.unscoped(), - required: true, - include: [ - { - attributes: [ 'userId' ], - model: AccountModel.unscoped(), - required: true - } - ] - } - ] - }, [ScopeNames.WITH_ACCOUNT_DETAILS]: { include: [ { @@ -326,14 +284,6 @@ export type AvailableForListIDsOptions = { [ScopeNames.WITH_TAGS]: { include: [ TagModel ] }, - [ScopeNames.WITH_TRACKERS]: { - include: [ - { - attributes: [ 'id', 'url' ], - model: TrackerModel - } - ] - }, [ScopeNames.WITH_BLACKLISTED]: { include: [ { @@ -506,19 +456,16 @@ export class VideoModel extends Model>> { @AllowNull(true) @Default(null) - @Is('VideoCategory', value => throwIfNotValid(value, isVideoCategoryValid, 'category', true)) @Column category: number @AllowNull(true) @Default(null) - @Is('VideoLicence', value => throwIfNotValid(value, isVideoLicenceValid, 'licence', true)) @Column licence: number @AllowNull(true) @Default(null) - @Is('VideoLanguage', value => throwIfNotValid(value, isVideoLanguageValid, 'language', true)) @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.LANGUAGE.max)) language: string @@ -626,7 +573,7 @@ export class VideoModel extends Model>> { foreignKey: { allowNull: true }, - hooks: true + onDelete: 'cascade' }) VideoChannel: VideoChannelModel @@ -804,25 +751,24 @@ export class VideoModel extends Model>> { } @BeforeDestroy - static async removeFiles (instance: VideoModel) { + static async removeFiles (instance: VideoModel, options) { const tasks: Promise[] = [] logger.info('Removing files of video %s.', instance.url) if (instance.isOwned()) { if (!Array.isArray(instance.VideoFiles)) { - instance.VideoFiles = await instance.$get('VideoFiles') + instance.VideoFiles = await instance.$get('VideoFiles', { transaction: options.transaction }) } // Remove physical files and torrents instance.VideoFiles.forEach(file => { - tasks.push(instance.removeFile(file)) - tasks.push(file.removeTorrent()) + tasks.push(instance.removeFileAndTorrent(file)) }) // Remove playlists file if (!Array.isArray(instance.VideoStreamingPlaylists)) { - instance.VideoStreamingPlaylists = await instance.$get('VideoStreamingPlaylists') + instance.VideoStreamingPlaylists = await instance.$get('VideoStreamingPlaylists', { transaction: options.transaction }) } for (const p of instance.VideoStreamingPlaylists) { @@ -845,7 +791,7 @@ export class VideoModel extends Model>> { logger.info('Stopping live of video %s after video deletion.', instance.uuid) - return LiveManager.Instance.stopSessionOf(instance.id) + LiveManager.Instance.stopSessionOf(instance.id) } @BeforeDestroy @@ -858,7 +804,7 @@ export class VideoModel extends Model>> { const tasks: Promise[] = [] if (!Array.isArray(instance.VideoAbuses)) { - instance.VideoAbuses = await instance.$get('VideoAbuses') + instance.VideoAbuses = await instance.$get('VideoAbuses', { transaction: options.transaction }) if (instance.VideoAbuses.length === 0) return undefined } @@ -873,12 +819,7 @@ export class VideoModel extends Model>> { tasks.push(abuse.save({ transaction: options.transaction })) } - Promise.all(tasks) - .catch(err => { - logger.error('Some errors when saving details of video %s in its abuses before destroy hook.', instance.uuid, { err }) - }) - - return undefined + await Promise.all(tasks) } static listLocal (): Promise { @@ -1172,6 +1113,7 @@ export class VideoModel extends Model>> { static async searchAndPopulateAccountAndServer (options: { includeLocalVideos: boolean search?: string + host?: string start?: number count?: number sort?: string @@ -1210,6 +1152,7 @@ export class VideoModel extends Model>> { user: options.user, filter: options.filter, + host: options.host, start: options.start, count: options.count, @@ -1439,7 +1382,7 @@ export class VideoModel extends Model>> { const rawQuery = `UPDATE "video" SET "${field}" = ` + '(' + - 'SELECT COUNT(id) FROM "accountVideoRate" WHERE "accountVideoRate"."videoId" = "video"."id" AND type = :rateType' + + 'SELECT COUNT(id) FROM "accountVideoRate" WHERE "accountVideoRate"."videoId" = "video"."id" AND type = :rateType' + ') ' + 'WHERE "video"."id" = :videoId' @@ -1467,15 +1410,15 @@ export class VideoModel extends Model>> { .then(results => results.length === 1) } - static bulkUpdateSupportField (videoChannel: MChannel, t: Transaction) { + static bulkUpdateSupportField (ofChannel: MChannel, t: Transaction) { const options = { where: { - channelId: videoChannel.id + channelId: ofChannel.id }, transaction: t } - return VideoModel.update({ support: videoChannel.support }, options) + return VideoModel.update({ support: ofChannel.support }, options) } static getAllIdsFromChannel (videoChannel: MChannelId): Promise { @@ -1638,11 +1581,11 @@ export class VideoModel extends Model>> { } getWatchStaticPath () { - return '/w/' + this.uuid + return buildVideoWatchPath({ shortUUID: uuidToShort(this.uuid) }) } getEmbedStaticPath () { - return '/videos/embed/' + this.uuid + return buildVideoEmbedPath(this) } getMiniatureStaticPath () { @@ -1729,10 +1672,13 @@ export class VideoModel extends Model>> { .concat(toAdd) } - removeFile (videoFile: MVideoFile, isRedundancy = false) { + removeFileAndTorrent (videoFile: MVideoFile, isRedundancy = false) { const filePath = getVideoFilePath(this, videoFile, isRedundancy) - return remove(filePath) - .catch(err => logger.warn('Cannot delete file %s.', filePath, { err })) + + const promises: Promise[] = [ remove(filePath) ] + if (!isRedundancy) promises.push(videoFile.removeTorrent()) + + return Promise.all(promises) } async removeStreamingPlaylistFiles (streamingPlaylist: MStreamingPlaylist, isRedundancy = false) {