From 3c10840fa90fc88fc98e8169faf4745ff6c80893 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 29 Oct 2021 10:54:27 +0200 Subject: Add video file size info in admin videos list --- server/controllers/api/accounts.ts | 1 - server/controllers/api/overviews.ts | 1 - server/controllers/api/users/my-subscriptions.ts | 1 - server/controllers/api/video-channel.ts | 1 - server/controllers/api/videos/index.ts | 1 - server/controllers/bots.ts | 1 - server/controllers/feeds.ts | 10 ++++--- server/models/account/account.ts | 2 +- server/models/user/user-video-history.ts | 1 - .../models/video/formatter/video-format-utils.ts | 32 ++++++++++---------- .../video/sql/video-model-get-query-builder.ts | 6 ++-- .../video/sql/videos-id-list-query-builder.ts | 4 +-- .../video/sql/videos-model-list-query-builder.ts | 2 +- server/models/video/video.ts | 34 +++++++++++++--------- server/tests/api/videos/videos-common-filters.ts | 28 +++++++++++++++++- server/types/models/account/account.ts | 4 +-- server/types/models/server/server.ts | 2 +- server/types/models/video/video.ts | 4 ++- 18 files changed, 82 insertions(+), 53 deletions(-) (limited to 'server') diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts index 44edffe38..46d89bafa 100644 --- a/server/controllers/api/accounts.ts +++ b/server/controllers/api/accounts.ts @@ -189,7 +189,6 @@ async function listAccountVideos (req: express.Request, res: express.Response) { displayOnlyForFollower, nsfw: buildNSFWFilter(res, query.nsfw), - withFiles: false, accountId: account.id, user: res.locals.oauth ? res.locals.oauth.token.User : undefined, countVideos diff --git a/server/controllers/api/overviews.ts b/server/controllers/api/overviews.ts index 68626a508..34585e557 100644 --- a/server/controllers/api/overviews.ts +++ b/server/controllers/api/overviews.ts @@ -122,7 +122,6 @@ async function getVideos ( }, nsfw: buildNSFWFilter(res), user: res.locals.oauth ? res.locals.oauth.token.User : undefined, - withFiles: false, countVideos: false, ...where diff --git a/server/controllers/api/users/my-subscriptions.ts b/server/controllers/api/users/my-subscriptions.ts index d96378180..6799ca8c5 100644 --- a/server/controllers/api/users/my-subscriptions.ts +++ b/server/controllers/api/users/my-subscriptions.ts @@ -181,7 +181,6 @@ async function getUserSubscriptionVideos (req: express.Request, res: express.Res orLocalVideos: false }, nsfw: buildNSFWFilter(res, query.nsfw), - withFiles: false, user, countVideos }) diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts index f9c1a405d..d1a1e6473 100644 --- a/server/controllers/api/video-channel.ts +++ b/server/controllers/api/video-channel.ts @@ -347,7 +347,6 @@ async function listVideoChannelVideos (req: express.Request, res: express.Respon displayOnlyForFollower, nsfw: buildNSFWFilter(res, query.nsfw), - withFiles: false, videoChannelId: videoChannelInstance.id, user: res.locals.oauth ? res.locals.oauth.token.User : undefined, countVideos diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 821ed7ff3..821161c64 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts @@ -225,7 +225,6 @@ async function listVideos (req: express.Request, res: express.Response) { orLocalVideos: true }, nsfw: buildNSFWFilter(res, query.nsfw), - withFiles: false, user: res.locals.oauth ? res.locals.oauth.token.User : undefined, countVideos }, 'filter:api.videos.list.params') diff --git a/server/controllers/bots.ts b/server/controllers/bots.ts index 9f03de7e8..2a8d6863a 100644 --- a/server/controllers/bots.ts +++ b/server/controllers/bots.ts @@ -76,7 +76,6 @@ async function getSitemapLocalVideoUrls () { }, isLocal: true, nsfw: buildNSFWFilter(), - withFiles: false, countVideos: false }) diff --git a/server/controllers/feeds.ts b/server/controllers/feeds.ts index 1f6aebac3..29502a154 100644 --- a/server/controllers/feeds.ts +++ b/server/controllers/feeds.ts @@ -2,6 +2,7 @@ import express from 'express' import Feed from 'pfeed' import { getServerActor } from '@server/models/application/application' import { getCategoryLabel } from '@server/models/video/formatter/video-format-utils' +import { VideoInclude } from '@shared/models' import { buildNSFWFilter } from '../helpers/express-utils' import { CONFIG } from '../initializers/config' import { FEEDS, PREVIEWS_SIZE, ROUTE_CACHE_LIFETIME, WEBSERVER } from '../initializers/constants' @@ -171,8 +172,8 @@ async function generateVideoFeed (req: express.Request, res: express.Response) { }, nsfw, isLocal: req.query.isLocal, - include: req.query.include, - withFiles: true, + include: req.query.include | VideoInclude.FILES, + hasFiles: true, countVideos: false, ...options }) @@ -204,9 +205,10 @@ async function generateVideoFeedForSubscriptions (req: express.Request, res: exp nsfw, isLocal: req.query.isLocal, - include: req.query.include, - withFiles: true, + hasFiles: true, + include: req.query.include | VideoInclude.FILES, + countVideos: false, displayOnlyForFollower: { diff --git a/server/models/account/account.ts b/server/models/account/account.ts index 056ec6857..71a9b8ccb 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts @@ -99,7 +99,7 @@ export type SummaryOptions = { queryInclude.push({ attributes: [ 'id' ], model: AccountBlocklistModel.unscoped(), - as: 'BlockedAccounts', + as: 'BlockedBy', required: false, where: { accountId: { diff --git a/server/models/user/user-video-history.ts b/server/models/user/user-video-history.ts index d633cc9d5..1aefdf02b 100644 --- a/server/models/user/user-video-history.ts +++ b/server/models/user/user-video-history.ts @@ -70,7 +70,6 @@ export class UserVideoHistoryModel extends Model> const tags = video.Tags ? video.Tags.map(t => t.name) : [] - const streamingPlaylists = streamingPlaylistsModelToFormattedJSON(video, video.VideoStreamingPlaylists) - - const detailsJson = { + const detailsJSON = { support: video.support, descriptionPath: video.getDescriptionAPIPath(), channel: video.VideoChannel.toFormattedJSON(), @@ -179,20 +185,14 @@ function videoModelToFormattedDetailsJSON (video: MVideoFormattableDetails): Vid label: getStateLabel(video.state) }, - trackerUrls: video.getTrackerUrls(), - - files: [], - streamingPlaylists + trackerUrls: video.getTrackerUrls() } - // Format and sort video files - detailsJson.files = videoFilesModelToFormattedJSON(video, video.VideoFiles) - - return Object.assign(formattedJson, detailsJson) + return Object.assign(videoJSON, detailsJSON) } function streamingPlaylistsModelToFormattedJSON ( - video: MVideoFormattableDetails, + video: MVideoFormattable, playlists: MStreamingPlaylistRedundanciesOpt[] ): VideoStreamingPlaylist[] { if (isArray(playlists) === false) return [] @@ -223,7 +223,7 @@ function sortByResolutionDesc (fileA: MVideoFile, fileB: MVideoFile) { } function videoFilesModelToFormattedJSON ( - video: MVideoFormattableDetails, + video: MVideoFormattable, videoFiles: MVideoFileRedundanciesOpt[], includeMagnet = true ): VideoFile[] { diff --git a/server/models/video/sql/video-model-get-query-builder.ts b/server/models/video/sql/video-model-get-query-builder.ts index d18ddae67..2f34d5602 100644 --- a/server/models/video/sql/video-model-get-query-builder.ts +++ b/server/models/video/sql/video-model-get-query-builder.ts @@ -32,7 +32,7 @@ export type BuildVideoGetQueryOptions = { logging?: boolean } -export class VideosModelGetQueryBuilder { +export class VideoModelGetQueryBuilder { videoQueryBuilder: VideosModelGetQuerySubBuilder webtorrentFilesQueryBuilder: VideoFileQueryBuilder streamingPlaylistFilesQueryBuilder: VideoFileQueryBuilder @@ -53,11 +53,11 @@ export class VideosModelGetQueryBuilder { const [ videoRows, webtorrentFilesRows, streamingPlaylistFilesRows ] = await Promise.all([ this.videoQueryBuilder.queryVideos(options), - VideosModelGetQueryBuilder.videoFilesInclude.has(options.type) + VideoModelGetQueryBuilder.videoFilesInclude.has(options.type) ? this.webtorrentFilesQueryBuilder.queryWebTorrentVideos(options) : Promise.resolve(undefined), - VideosModelGetQueryBuilder.videoFilesInclude.has(options.type) + VideoModelGetQueryBuilder.videoFilesInclude.has(options.type) ? this.streamingPlaylistFilesQueryBuilder.queryStreamingPlaylistVideos(options) : Promise.resolve(undefined) ]) diff --git a/server/models/video/sql/videos-id-list-query-builder.ts b/server/models/video/sql/videos-id-list-query-builder.ts index 3eb547e75..4d6e0ea4b 100644 --- a/server/models/video/sql/videos-id-list-query-builder.ts +++ b/server/models/video/sql/videos-id-list-query-builder.ts @@ -43,7 +43,7 @@ export type BuildVideosListQueryOptions = { uuids?: string[] - withFiles?: boolean + hasFiles?: boolean accountId?: number videoChannelId?: number @@ -165,7 +165,7 @@ export class VideosIdListQueryBuilder extends AbstractVideosQueryBuilder { this.whereFollowerActorId(options.displayOnlyForFollower) } - if (options.withFiles === true) { + if (options.hasFiles === true) { this.whereFileExists() } diff --git a/server/models/video/sql/videos-model-list-query-builder.ts b/server/models/video/sql/videos-model-list-query-builder.ts index ef92bd2b0..cd721f055 100644 --- a/server/models/video/sql/videos-model-list-query-builder.ts +++ b/server/models/video/sql/videos-model-list-query-builder.ts @@ -52,7 +52,7 @@ export class VideosModelListQueryBuilder extends AbstractVideosModelQueryBuilder this.includeAccounts() this.includeThumbnails() - if (options.withFiles) { + if (options.include & VideoInclude.FILES) { this.includeWebtorrentFiles() this.includeStreamingPlaylistFiles() } diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 26be34329..f9618c102 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -105,7 +105,7 @@ import { videoModelToFormattedJSON } from './formatter/video-format-utils' import { ScheduleVideoUpdateModel } from './schedule-video-update' -import { VideosModelGetQueryBuilder } from './sql/video-model-get-query-builder' +import { VideoModelGetQueryBuilder } from './sql/video-model-get-query-builder' import { BuildVideosListQueryOptions, DisplayOnlyForFollowerOptions, VideosIdListQueryBuilder } from './sql/videos-id-list-query-builder' import { VideosModelListQueryBuilder } from './sql/videos-model-list-query-builder' import { TagModel } from './tag' @@ -1029,7 +1029,7 @@ export class VideoModel extends Model>> { isLocal?: boolean include?: VideoInclude - withFiles: boolean + hasFiles?: boolean // default false categoryOneOf?: number[] licenceOneOf?: number[] @@ -1053,7 +1053,7 @@ export class VideoModel extends Model>> { search?: string }) { - if (options.include && !options.user.hasRight(UserRight.SEE_ALL_VIDEOS)) { + if (VideoModel.isPrivateInclude(options.include) && !options.user.hasRight(UserRight.SEE_ALL_VIDEOS)) { throw new Error('Try to filter all-local but no user has not the see all videos right') } @@ -1082,7 +1082,7 @@ export class VideoModel extends Model>> { 'isLocal', 'include', 'displayOnlyForFollower', - 'withFiles', + 'hasFiles', 'accountId', 'videoChannelId', 'videoPlaylistId', @@ -1229,13 +1229,13 @@ export class VideoModel extends Model>> { } static load (id: number | string, transaction?: Transaction): Promise { - const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize) + const queryBuilder = new VideoModelGetQueryBuilder(VideoModel.sequelize) return queryBuilder.queryVideo({ id, transaction, type: 'thumbnails' }) } static loadWithBlacklist (id: number | string, transaction?: Transaction): Promise { - const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize) + const queryBuilder = new VideoModelGetQueryBuilder(VideoModel.sequelize) return queryBuilder.queryVideo({ id, transaction, type: 'thumbnails-blacklist' }) } @@ -1279,31 +1279,31 @@ export class VideoModel extends Model>> { } static loadOnlyId (id: number | string, transaction?: Transaction): Promise { - const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize) + const queryBuilder = new VideoModelGetQueryBuilder(VideoModel.sequelize) return queryBuilder.queryVideo({ id, transaction, type: 'id' }) } static loadWithFiles (id: number | string, transaction?: Transaction, logging?: boolean): Promise { - const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize) + const queryBuilder = new VideoModelGetQueryBuilder(VideoModel.sequelize) return queryBuilder.queryVideo({ id, transaction, type: 'all-files', logging }) } static loadByUrl (url: string, transaction?: Transaction): Promise { - const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize) + const queryBuilder = new VideoModelGetQueryBuilder(VideoModel.sequelize) return queryBuilder.queryVideo({ url, transaction, type: 'thumbnails' }) } static loadByUrlAndPopulateAccount (url: string, transaction?: Transaction): Promise { - const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize) + const queryBuilder = new VideoModelGetQueryBuilder(VideoModel.sequelize) return queryBuilder.queryVideo({ url, transaction, type: 'account-blacklist-files' }) } static loadAndPopulateAccountAndServerAndTags (id: number | string, t?: Transaction, userId?: number): Promise { - const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize) + const queryBuilder = new VideoModelGetQueryBuilder(VideoModel.sequelize) return queryBuilder.queryVideo({ id, transaction: t, type: 'full-light', userId }) } @@ -1314,7 +1314,7 @@ export class VideoModel extends Model>> { userId?: number }): Promise { const { id, transaction, userId } = parameters - const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize) + const queryBuilder = new VideoModelGetQueryBuilder(VideoModel.sequelize) return queryBuilder.queryVideo({ id, transaction, type: 'api', userId }) } @@ -1345,8 +1345,7 @@ export class VideoModel extends Model>> { displayOnlyForFollower: { actorId: serverActor.id, orLocalVideos: true - }, - withFiles: false + } }) return { @@ -1490,6 +1489,13 @@ export class VideoModel extends Model>> { } } + private static isPrivateInclude (include: VideoInclude) { + return include & VideoInclude.BLACKLISTED || + include & VideoInclude.BLOCKED_OWNER || + include & VideoInclude.HIDDEN_PRIVACY || + include & VideoInclude.NOT_PUBLISHED_STATE + } + isBlacklisted () { return !!this.VideoBlacklist } diff --git a/server/tests/api/videos/videos-common-filters.ts b/server/tests/api/videos/videos-common-filters.ts index eb2d2ab50..03c5c3b3f 100644 --- a/server/tests/api/videos/videos-common-filters.ts +++ b/server/tests/api/videos/videos-common-filters.ts @@ -13,7 +13,7 @@ import { setDefaultVideoChannel, waitJobs } from '@shared/extra-utils' -import { HttpStatusCode, UserRole, Video, VideoInclude, VideoPrivacy } from '@shared/models' +import { HttpStatusCode, UserRole, Video, VideoDetails, VideoInclude, VideoPrivacy } from '@shared/models' describe('Test videos filter', function () { let servers: PeerTubeServer[] @@ -365,6 +365,32 @@ describe('Test videos filter', function () { await servers[0].blocklist.removeFromServerBlocklist({ server: servers[1].host }) }) + it('Should include video files', async function () { + for (const path of paths) { + { + const videos = await listVideos({ server: servers[0], path }) + + for (const video of videos) { + const videoWithFiles = video as VideoDetails + + expect(videoWithFiles.files).to.not.exist + expect(videoWithFiles.streamingPlaylists).to.not.exist + } + } + + { + const videos = await listVideos({ server: servers[0], path, include: VideoInclude.FILES }) + + for (const video of videos) { + const videoWithFiles = video as VideoDetails + + expect(videoWithFiles.files).to.exist + expect(videoWithFiles.files).to.have.length.at.least(1) + } + } + } + }) + it('Should filter by tags and category', async function () { await servers[0].videos.upload({ attributes: { name: 'tag filter', tags: [ 'tag1', 'tag2' ] } }) await servers[0].videos.upload({ attributes: { name: 'tag filter with category', tags: [ 'tag3' ], category: 4 } }) diff --git a/server/types/models/account/account.ts b/server/types/models/account/account.ts index abe0de27b..71f6c79aa 100644 --- a/server/types/models/account/account.ts +++ b/server/types/models/account/account.ts @@ -23,7 +23,7 @@ type Use = PickWith export type MAccount = Omit + 'VideoComments' | 'BlockedBy'> // ############################################################################ @@ -84,7 +84,7 @@ export type MAccountSummary = export type MAccountSummaryBlocks = MAccountSummary & - Use<'BlockedByAccounts', MAccountBlocklistId[]> + Use<'BlockedBy', MAccountBlocklistId[]> export type MAccountAPI = MAccount & diff --git a/server/types/models/server/server.ts b/server/types/models/server/server.ts index f8b053e3b..876186fc0 100644 --- a/server/types/models/server/server.ts +++ b/server/types/models/server/server.ts @@ -15,7 +15,7 @@ export type MServerRedundancyAllowed = Pick export type MServerHostBlocks = MServerHost & - Use<'BlockedByAccounts', MAccountBlocklistId[]> + Use<'BlockedBy', MAccountBlocklistId[]> // ############################################################################ diff --git a/server/types/models/video/video.ts b/server/types/models/video/video.ts index 16ddaf740..9a6b27888 100644 --- a/server/types/models/video/video.ts +++ b/server/types/models/video/video.ts @@ -210,7 +210,9 @@ export type MVideoFormattable = PickWithOpt & Use<'VideoChannel', MChannelAccountSummaryFormattable> & PickWithOpt> & - PickWithOpt> + PickWithOpt> & + PickWithOpt & + PickWithOpt export type MVideoFormattableDetails = MVideoFormattable & -- cgit v1.2.3