From d324756edb836672f12284cd18e642a658b273d8 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 3 Nov 2021 11:32:41 +0100 Subject: Add ability to filter by file type --- .../video/sql/videos-id-list-query-builder.ts | 45 +++++++++++++++++----- server/models/video/video.ts | 44 +++++++++++++++------ 2 files changed, 68 insertions(+), 21 deletions(-) (limited to 'server/models') 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 5064afafe..4a882e790 100644 --- a/server/models/video/sql/videos-id-list-query-builder.ts +++ b/server/models/video/sql/videos-id-list-query-builder.ts @@ -44,6 +44,8 @@ export type BuildVideosListQueryOptions = { uuids?: string[] hasFiles?: boolean + hasHLSFiles?: boolean + hasWebtorrentFiles?: boolean accountId?: number videoChannelId?: number @@ -169,6 +171,14 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery { this.whereFileExists() } + if (exists(options.hasWebtorrentFiles)) { + this.whereWebTorrentFileExists(options.hasWebtorrentFiles) + } + + if (exists(options.hasHLSFiles)) { + this.whereHLSFileExists(options.hasHLSFiles) + } + if (options.tagsOneOf) { this.whereTagsOneOf(options.tagsOneOf) } @@ -371,16 +381,31 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery { } private whereFileExists () { - this.and.push( - '(' + - ' EXISTS (SELECT 1 FROM "videoFile" WHERE "videoFile"."videoId" = "video"."id") ' + - ' OR EXISTS (' + - ' SELECT 1 FROM "videoStreamingPlaylist" ' + - ' INNER JOIN "videoFile" ON "videoFile"."videoStreamingPlaylistId" = "videoStreamingPlaylist"."id" ' + - ' WHERE "videoStreamingPlaylist"."videoId" = "video"."id"' + - ' )' + - ')' - ) + this.and.push(`(${this.buildWebTorrentFileExistsQuery(true)} OR ${this.buildHLSFileExistsQuery(true)})`) + } + + private whereWebTorrentFileExists (exists: boolean) { + this.and.push(this.buildWebTorrentFileExistsQuery(exists)) + } + + private whereHLSFileExists (exists: boolean) { + this.and.push(this.buildHLSFileExistsQuery(exists)) + } + + private buildWebTorrentFileExistsQuery (exists: boolean) { + const prefix = exists ? '' : 'NOT ' + + return prefix + 'EXISTS (SELECT 1 FROM "videoFile" WHERE "videoFile"."videoId" = "video"."id")' + } + + private buildHLSFileExistsQuery (exists: boolean) { + const prefix = exists ? '' : 'NOT ' + + return prefix + 'EXISTS (' + + ' SELECT 1 FROM "videoStreamingPlaylist" ' + + ' INNER JOIN "videoFile" ON "videoFile"."videoStreamingPlaylistId" = "videoStreamingPlaylist"."id" ' + + ' WHERE "videoStreamingPlaylist"."videoId" = "video"."id"' + + ')' } private whereTagsOneOf (tagsOneOf: string[]) { diff --git a/server/models/video/video.ts b/server/models/video/video.ts index f9618c102..aef4fd20a 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -1030,6 +1030,8 @@ export class VideoModel extends Model>> { include?: VideoInclude hasFiles?: boolean // default false + hasWebtorrentFiles?: boolean + hasHLSFiles?: boolean categoryOneOf?: number[] licenceOneOf?: number[] @@ -1053,9 +1055,7 @@ export class VideoModel extends Model>> { search?: string }) { - 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') - } + VideoModel.throwIfPrivateIncludeWithoutUser(options.include, options.user) const trendingDays = options.sort.endsWith('trending') ? CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS @@ -1088,6 +1088,8 @@ export class VideoModel extends Model>> { 'videoPlaylistId', 'user', 'historyOfUser', + 'hasHLSFiles', + 'hasWebtorrentFiles', 'search' ]), @@ -1103,27 +1105,39 @@ export class VideoModel extends Model>> { start: number count: number sort: string - search?: string - host?: string - startDate?: string // ISO 8601 - endDate?: string // ISO 8601 - originallyPublishedStartDate?: string - originallyPublishedEndDate?: string + nsfw?: boolean isLive?: boolean isLocal?: boolean include?: VideoInclude + categoryOneOf?: number[] licenceOneOf?: number[] languageOneOf?: string[] tagsOneOf?: string[] tagsAllOf?: string[] + + displayOnlyForFollower: DisplayOnlyForFollowerOptions | null + + user?: MUserAccountId + + hasWebtorrentFiles?: boolean + hasHLSFiles?: boolean + + search?: string + + host?: string + startDate?: string // ISO 8601 + endDate?: string // ISO 8601 + originallyPublishedStartDate?: string + originallyPublishedEndDate?: string + durationMin?: number // seconds durationMax?: number // seconds - user?: MUserAccountId uuids?: string[] - displayOnlyForFollower: DisplayOnlyForFollowerOptions | null }) { + VideoModel.throwIfPrivateIncludeWithoutUser(options.include, options.user) + const serverActor = await getServerActor() const queryOptions = { @@ -1148,6 +1162,8 @@ export class VideoModel extends Model>> { 'originallyPublishedEndDate', 'durationMin', 'durationMax', + 'hasHLSFiles', + 'hasWebtorrentFiles', 'uuids', 'search', 'displayOnlyForFollower' @@ -1489,6 +1505,12 @@ export class VideoModel extends Model>> { } } + private static throwIfPrivateIncludeWithoutUser (include: VideoInclude, user: MUserAccountId) { + if (VideoModel.isPrivateInclude(include) && !user?.hasRight(UserRight.SEE_ALL_VIDEOS)) { + throw new Error('Try to filter all-local but no user has not the see all videos right') + } + } + private static isPrivateInclude (include: VideoInclude) { return include & VideoInclude.BLACKLISTED || include & VideoInclude.BLOCKED_OWNER || -- cgit v1.2.3