]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/models/video/video.ts
Add ability to filter by file type
[github/Chocobozzz/PeerTube.git] / server / models / video / video.ts
index 26be34329e4969d02c91c379008a4d2903a518b5..aef4fd20a0ae0365f873bc1fb28be3dd10c27661 100644 (file)
@@ -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,9 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
     isLocal?: boolean
     include?: VideoInclude
 
-    withFiles: boolean
+    hasFiles?: boolean // default false
+    hasWebtorrentFiles?: boolean
+    hasHLSFiles?: boolean
 
     categoryOneOf?: number[]
     licenceOneOf?: number[]
@@ -1053,9 +1055,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
 
     search?: string
   }) {
-    if (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
@@ -1082,12 +1082,14 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
         'isLocal',
         'include',
         'displayOnlyForFollower',
-        'withFiles',
+        'hasFiles',
         'accountId',
         'videoChannelId',
         'videoPlaylistId',
         'user',
         'historyOfUser',
+        'hasHLSFiles',
+        'hasWebtorrentFiles',
         'search'
       ]),
 
@@ -1103,27 +1105,39 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
     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<Partial<AttributesOnly<VideoModel>>> {
         'originallyPublishedEndDate',
         'durationMin',
         'durationMax',
+        'hasHLSFiles',
+        'hasWebtorrentFiles',
         'uuids',
         'search',
         'displayOnlyForFollower'
@@ -1229,13 +1245,13 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
   }
 
   static load (id: number | string, transaction?: Transaction): Promise<MVideoThumbnail> {
-    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<MVideoThumbnailBlacklist> {
-    const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
+    const queryBuilder = new VideoModelGetQueryBuilder(VideoModel.sequelize)
 
     return queryBuilder.queryVideo({ id, transaction, type: 'thumbnails-blacklist' })
   }
@@ -1279,31 +1295,31 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
   }
 
   static loadOnlyId (id: number | string, transaction?: Transaction): Promise<MVideoId> {
-    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<MVideoWithAllFiles> {
-    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<MVideoThumbnail> {
-    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<MVideoAccountLightBlacklistAllFiles> {
-    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<MVideoFullLight> {
-    const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
+    const queryBuilder = new VideoModelGetQueryBuilder(VideoModel.sequelize)
 
     return queryBuilder.queryVideo({ id, transaction: t, type: 'full-light', userId })
   }
@@ -1314,7 +1330,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
     userId?: number
   }): Promise<MVideoDetails> {
     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 +1361,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
       displayOnlyForFollower: {
         actorId: serverActor.id,
         orLocalVideos: true
-      },
-      withFiles: false
+      }
     })
 
     return {
@@ -1490,6 +1505,19 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
     }
   }
 
+  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 ||
+           include & VideoInclude.HIDDEN_PRIVACY ||
+           include & VideoInclude.NOT_PUBLISHED_STATE
+  }
+
   isBlacklisted () {
     return !!this.VideoBlacklist
   }