]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Use raw SQL for most of video queries
authorChocobozzz <me@florianbigard.com>
Fri, 11 Jun 2021 12:09:33 +0000 (14:09 +0200)
committerChocobozzz <me@florianbigard.com>
Fri, 11 Jun 2021 12:09:52 +0000 (14:09 +0200)
16 files changed:
scripts/create-import-video-file-job.ts
scripts/prune-storage.ts
server/controllers/activitypub/client.ts
server/helpers/video.ts
server/lib/model-loaders/video.ts
server/middlewares/validators/shared/videos.ts
server/middlewares/validators/videos/videos.ts
server/models/video/sql/shared/abstract-videos-model-query-builder.ts
server/models/video/sql/shared/abstract-videos-query-builder.ts
server/models/video/sql/shared/video-file-query-builder.ts
server/models/video/sql/shared/video-model-builder.ts
server/models/video/sql/shared/video-tables.ts
server/models/video/sql/video-model-get-query-builder.ts
server/models/video/sql/videos-model-list-query-builder.ts
server/models/video/video.ts
server/typings/express/index.d.ts

index 5d38af066b037dde6a4e2c532bb7e9ec01c9a954..094544e0550328d0a267dc8e353a84f44399ebd2 100644 (file)
@@ -36,7 +36,7 @@ async function run () {
     return
   }
 
-  const video = await VideoModel.loadByUUID(options.video)
+  const video = await VideoModel.load(options.video)
   if (!video) throw new Error('Video not found.')
   if (video.isOwned() === false) throw new Error('Cannot import files of a non owned video.')
 
@@ -45,7 +45,7 @@ async function run () {
     filePath: resolve(options.import)
   }
 
-  await JobQueue.Instance.init()
+  JobQueue.Instance.init()
   await JobQueue.Instance.createJobWithPromise({ type: 'video-file-import', payload: dataInput })
   console.log('Import job for video %s created.', video.uuid)
 }
index 0f2d1320e18a5ef13aca67cbc5be6ce932c64ead..58d24816e345e5e60c966c97999add985c31d63a 100755 (executable)
@@ -89,7 +89,7 @@ async function pruneDirectory (directory: string, existFun: ExistFun) {
 function doesVideoExist (keepOnlyOwned: boolean) {
   return async (file: string) => {
     const uuid = getUUIDFromFilename(file)
-    const video = await VideoModel.loadByUUID(uuid)
+    const video = await VideoModel.load(uuid)
 
     return video && (keepOnlyOwned === false || video.isOwned())
   }
index 1982e171deae04b7a60a8c0b38fa396cf2d1bc14..444a8abaa7e4055eb692066f1184e4f19729c35f 100644 (file)
@@ -78,12 +78,12 @@ activityPubClientRouter.get('/accounts?/:name/dislikes/:videoId',
 activityPubClientRouter.get('/videos/watch/:id',
   executeIfActivityPub,
   asyncMiddleware(cacheRoute()(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS)),
-  asyncMiddleware(videosCustomGetValidator('only-video-with-rights')),
+  asyncMiddleware(videosCustomGetValidator('all')),
   asyncMiddleware(videoController)
 )
 activityPubClientRouter.get('/videos/watch/:id/activity',
   executeIfActivityPub,
-  asyncMiddleware(videosCustomGetValidator('only-video-with-rights')),
+  asyncMiddleware(videosCustomGetValidator('all')),
   asyncMiddleware(videoController)
 )
 activityPubClientRouter.get('/videos/watch/:id/announces',
@@ -222,8 +222,7 @@ function getAccountVideoRateFactory (rateType: VideoRateType) {
 }
 
 async function videoController (req: express.Request, res: express.Response) {
-  // We need more attributes
-  const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(res.locals.onlyVideoWithRights.id)
+  const video = res.locals.videoAll
 
   if (redirectIfNotOwned(video.url, res)) return
 
index c2e15a705582001a076c5b10318dc3da478b7c44..f5f645d3eac1997614c177f00c5a64c215f38ef0 100644 (file)
@@ -4,7 +4,7 @@ import { isStreamingPlaylist, MStreamingPlaylistVideo, MVideo } from '@server/ty
 import { VideoPrivacy, VideoState } from '@shared/models'
 
 function getVideoWithAttributes (res: Response) {
-  return res.locals.videoAPI || res.locals.videoAll || res.locals.onlyVideo || res.locals.onlyVideoWithRights
+  return res.locals.videoAPI || res.locals.videoAll || res.locals.onlyVideo
 }
 
 function extractVideo (videoOrPlaylist: MVideo | MStreamingPlaylistVideo) {
index 07b373ed39e0dccdf6632924fd9f282d499b6ca7..e2bf96f6218e05b5ef65847d3e9454b4304b25d7 100644 (file)
@@ -3,31 +3,30 @@ import {
   MVideoAccountLightBlacklistAllFiles,
   MVideoFormattableDetails,
   MVideoFullLight,
-  MVideoIdThumbnail,
+  MVideoId,
   MVideoImmutable,
   MVideoThumbnail,
   MVideoWithRights
 } from '@server/types/models'
 import { Hooks } from '../plugins/hooks'
 
-type VideoLoadType = 'for-api' | 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none' | 'only-immutable-attributes'
+type VideoLoadType = 'for-api' | 'all' | 'only-video' | 'id' | 'none' | 'only-immutable-attributes'
 
 function loadVideo (id: number | string, fetchType: 'for-api', userId?: number): Promise<MVideoFormattableDetails>
 function loadVideo (id: number | string, fetchType: 'all', userId?: number): Promise<MVideoFullLight>
 function loadVideo (id: number | string, fetchType: 'only-immutable-attributes'): Promise<MVideoImmutable>
 function loadVideo (id: number | string, fetchType: 'only-video', userId?: number): Promise<MVideoThumbnail>
-function loadVideo (id: number | string, fetchType: 'only-video-with-rights', userId?: number): Promise<MVideoWithRights>
-function loadVideo (id: number | string, fetchType: 'id' | 'none', userId?: number): Promise<MVideoIdThumbnail>
+function loadVideo (id: number | string, fetchType: 'id' | 'none', userId?: number): Promise<MVideoId>
 function loadVideo (
   id: number | string,
   fetchType: VideoLoadType,
   userId?: number
-): Promise<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail | MVideoImmutable>
+): Promise<MVideoFullLight | MVideoThumbnail | MVideoId | MVideoImmutable>
 function loadVideo (
   id: number | string,
   fetchType: VideoLoadType,
   userId?: number
-): Promise<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail | MVideoImmutable> {
+): Promise<MVideoFullLight | MVideoThumbnail | MVideoId | MVideoImmutable> {
 
   if (fetchType === 'for-api') {
     return Hooks.wrapPromiseFun(
@@ -41,8 +40,6 @@ function loadVideo (
 
   if (fetchType === 'only-immutable-attributes') return VideoModel.loadImmutableAttributes(id)
 
-  if (fetchType === 'only-video-with-rights') return VideoModel.loadWithRights(id)
-
   if (fetchType === 'only-video') return VideoModel.load(id)
 
   if (fetchType === 'id' || fetchType === 'none') return VideoModel.loadOnlyId(id)
index 1a22d651381c37f65358670510c6ad4254aa6b46..6131379ce4683ed7f44fbf5591c313e91a56c0fe 100644 (file)
@@ -8,7 +8,7 @@ import {
   MVideoAccountLight,
   MVideoFormattableDetails,
   MVideoFullLight,
-  MVideoIdThumbnail,
+  MVideoId,
   MVideoImmutable,
   MVideoThumbnail,
   MVideoWithRights
@@ -43,16 +43,12 @@ async function doesVideoExist (id: number | string, res: Response, fetchType: Vi
       break
 
     case 'id':
-      res.locals.videoId = video as MVideoIdThumbnail
+      res.locals.videoId = video as MVideoId
       break
 
     case 'only-video':
       res.locals.onlyVideo = video as MVideoThumbnail
       break
-
-    case 'only-video-with-rights':
-      res.locals.onlyVideoWithRights = video as MVideoWithRights
-      break
   }
 
   return true
index a707fd08690ebebc26f78543ff2c84a45e24ece0..2bed5f18123b09ff9e5ce1a4538d1ab2b7902ee5 100644 (file)
@@ -4,7 +4,7 @@ import { getResumableUploadPath } from '@server/helpers/upload'
 import { isAbleToUploadVideo } from '@server/lib/user'
 import { getServerActor } from '@server/models/application/application'
 import { ExpressPromiseHandler } from '@server/types/express'
-import { MUserAccountId, MVideoWithRights } from '@server/types/models'
+import { MUserAccountId, MVideoFullLight } from '@server/types/models'
 import { ServerErrorCode, UserRight, VideoChangeOwnershipStatus, VideoPrivacy } from '../../../../shared'
 import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 import { VideoChangeOwnershipAccept } from '../../../../shared/models/videos/change-ownership/video-change-ownership-accept.model'
@@ -258,7 +258,7 @@ async function checkVideoFollowConstraints (req: express.Request, res: express.R
 }
 
 const videosCustomGetValidator = (
-  fetchType: 'for-api' | 'all' | 'only-video' | 'only-video-with-rights' | 'only-immutable-attributes',
+  fetchType: 'for-api' | 'all' | 'only-video' | 'only-immutable-attributes',
   authenticateInQuery = false
 ) => {
   return [
@@ -273,7 +273,7 @@ const videosCustomGetValidator = (
       // Controllers does not need to check video rights
       if (fetchType === 'only-immutable-attributes') return next()
 
-      const video = getVideoWithAttributes(res) as MVideoWithRights
+      const video = getVideoWithAttributes(res) as MVideoFullLight
 
       // Video private or blacklisted
       if (video.requiresAuth()) {
index 65df8d9149213e145bb4c1092751c0de7d723f2f..d959cb5d074d29088de0aad6ebee62b3349bf0e4 100644 (file)
@@ -80,6 +80,18 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder
     }
   }
 
+  protected includeOwnerUser () {
+    this.addJoin('INNER JOIN "videoChannel" AS "VideoChannel" ON "video"."channelId" = "VideoChannel"."id"')
+    this.addJoin('INNER JOIN "account" AS "VideoChannel->Account" ON "VideoChannel"."accountId" = "VideoChannel->Account"."id"')
+
+    this.attributes = {
+      ...this.attributes,
+
+      ...this.buildAttributesObject('VideoChannel', this.tables.getChannelAttributes()),
+      ...this.buildAttributesObject('VideoChannel->Account', this.tables.getUserAccountAttributes())
+    }
+  }
+
   protected includeThumbnails () {
     this.addJoin('LEFT OUTER JOIN "thumbnail" AS "Thumbnails" ON "video"."id" = "Thumbnails"."videoId"')
 
@@ -269,14 +281,20 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder
     return result
   }
 
-  protected whereId (id: string | number) {
-    if (validator.isInt('' + id)) {
+  protected whereId (options: { id?: string | number, url?: string }) {
+    if (options.url) {
+      this.where = 'WHERE "video"."url" = :videoUrl'
+      this.replacements.videoUrl = options.url
+      return
+    }
+
+    if (validator.isInt('' + options.id)) {
       this.where = 'WHERE "video".id = :videoId'
     } else {
       this.where = 'WHERE uuid = :videoId'
     }
 
-    this.replacements.videoId = id
+    this.replacements.videoId = options.id
   }
 
   protected addJoin (join: string) {
index 7e67fa34fab6b966750cedefc698ff9e7dd2a1a5..10699317ad72eca53e781bd496463b84b06943d9 100644 (file)
@@ -13,16 +13,17 @@ export class AbstractVideosQueryBuilder {
   protected query: string
   protected replacements: any = {}
 
-  protected runQuery (transaction?: Transaction) {
+  protected runQuery (options: { transaction?: Transaction, logging?: boolean } = {}) {
     logger.debug('Running videos query.', { query: this.query, replacements: this.replacements })
 
-    const options = {
-      transaction,
+    const queryOptions = {
+      transaction: options.transaction,
+      logging: options.logging,
       replacements: this.replacements,
       type: QueryTypes.SELECT as QueryTypes.SELECT,
       next: false
     }
 
-    return this.sequelize.query<any>(this.query, options)
+    return this.sequelize.query<any>(this.query, queryOptions)
   }
 }
index 7d822f8fabf96199f7eaa883d9a8b871290eeffa..a62fa64f842c63733d61c520c31c26802ad38dce 100644 (file)
@@ -18,13 +18,13 @@ export class VideoFileQueryBuilder extends AbstractVideosModelQueryBuilder {
   queryWebTorrentVideos (options: BuildVideoGetQueryOptions) {
     this.buildWebtorrentFilesQuery(options)
 
-    return this.runQuery(options.transaction)
+    return this.runQuery(options)
   }
 
   queryStreamingPlaylistVideos (options: BuildVideoGetQueryOptions) {
     this.buildVideoStreamingPlaylistFilesQuery(options)
 
-    return this.runQuery(options.transaction)
+    return this.runQuery(options)
   }
 
   private buildWebtorrentFilesQuery (options: BuildVideoGetQueryOptions) {
@@ -34,11 +34,11 @@ export class VideoFileQueryBuilder extends AbstractVideosModelQueryBuilder {
 
     this.includeWebtorrentFiles(true)
 
-    if (options.forGetAPI === true) {
+    if (this.shouldIncludeRedundancies(options)) {
       this.includeWebTorrentRedundancies()
     }
 
-    this.whereId(options.id)
+    this.whereId(options)
 
     this.query = this.buildQuery()
   }
@@ -50,11 +50,11 @@ export class VideoFileQueryBuilder extends AbstractVideosModelQueryBuilder {
 
     this.includeStreamingPlaylistFiles(true)
 
-    if (options.forGetAPI === true) {
+    if (this.shouldIncludeRedundancies(options)) {
       this.includeStreamingPlaylistRedundancies()
     }
 
-    this.whereId(options.id)
+    this.whereId(options)
 
     this.query = this.buildQuery()
   }
@@ -62,4 +62,8 @@ export class VideoFileQueryBuilder extends AbstractVideosModelQueryBuilder {
   private buildQuery () {
     return `${this.buildSelect()} FROM "video" ${this.joins} ${this.where}`
   }
+
+  private shouldIncludeRedundancies (options: BuildVideoGetQueryOptions) {
+    return options.type === 'api'
+  }
 }
index 2a60dab04d914cdf99a569adb06778a76ff95a8f..467a9378a14dd21a3bdb18569b899e0dfe2c95d8 100644 (file)
@@ -1,5 +1,4 @@
 
-import { logger } from '@server/helpers/logger'
 import { AccountModel } from '@server/models/account/account'
 import { ActorModel } from '@server/models/actor/actor'
 import { ActorImageModel } from '@server/models/actor/actor-image'
@@ -56,7 +55,7 @@ export class VideoModelBuilder {
     this.reinit()
 
     for (const row of rows) {
-      this.buildVideo(row)
+      this.buildVideoAndAccount(row)
 
       const videoModel = this.videosMemo[row.id]
 
@@ -131,22 +130,10 @@ export class VideoModelBuilder {
     }
   }
 
-  private buildVideo (row: SQLRow) {
+  private buildVideoAndAccount (row: SQLRow) {
     if (this.videosMemo[row.id]) return
 
-    // Build Channel
-    const channelModel = new VideoChannelModel(this.grab(row, this.tables.getChannelAttributes(), 'VideoChannel'), this.buildOpts)
-    channelModel.Actor = this.buildActor(row, 'VideoChannel')
-
-    const accountModel = new AccountModel(this.grab(row, this.tables.getAccountAttributes(), 'VideoChannel.Account'), this.buildOpts)
-    accountModel.Actor = this.buildActor(row, 'VideoChannel.Account')
-
-    channelModel.Account = accountModel
-
     const videoModel = new VideoModel(this.grab(row, this.tables.getVideoAttributes(), ''), this.buildOpts)
-    videoModel.VideoChannel = channelModel
-
-    this.videosMemo[row.id] = videoModel
 
     videoModel.UserVideoHistories = []
     videoModel.Thumbnails = []
@@ -155,10 +142,29 @@ export class VideoModelBuilder {
     videoModel.Tags = []
     videoModel.Trackers = []
 
+    this.buildAccount(row, videoModel)
+
+    this.videosMemo[row.id] = videoModel
+
     // Keep rows order
     this.videos.push(videoModel)
   }
 
+  private buildAccount (row: SQLRow, videoModel: VideoModel) {
+    const id = row['VideoChannel.Account.id']
+    if (!id) return
+
+    const channelModel = new VideoChannelModel(this.grab(row, this.tables.getChannelAttributes(), 'VideoChannel'), this.buildOpts)
+    channelModel.Actor = this.buildActor(row, 'VideoChannel')
+
+    const accountModel = new AccountModel(this.grab(row, this.tables.getAccountAttributes(), 'VideoChannel.Account'), this.buildOpts)
+    accountModel.Actor = this.buildActor(row, 'VideoChannel.Account')
+
+    channelModel.Account = accountModel
+
+    videoModel.VideoChannel = channelModel
+  }
+
   private buildActor (row: SQLRow, prefix: string) {
     const actorPrefix = `${prefix}.Actor`
     const avatarPrefix = `${actorPrefix}.Avatar`
index fddf1210c9c8b5ea09757e62178b873a3d8d7588..52929fa5ea611ddf28db31efea1f6ddf03f102d3 100644 (file)
@@ -10,6 +10,10 @@ export class VideoTables {
 
   }
 
+  getChannelAttributesForUser () {
+    return [ 'id', 'accountId' ]
+  }
+
   getChannelAttributes () {
     let attributeKeys = [
       'id',
@@ -29,6 +33,10 @@ export class VideoTables {
     return attributeKeys
   }
 
+  getUserAccountAttributes () {
+    return [ 'id', 'userId' ]
+  }
+
   getAccountAttributes () {
     let attributeKeys = [ 'id', 'name', 'actorId' ]
 
index 4aab9ff1d8a578b1da7a379dbe6facc3882d625c..f56fdd4743aba5beb56ff406645143c9d7201ccf 100644 (file)
@@ -11,10 +11,15 @@ import { VideoTables } from './shared/video-tables'
  */
 
 export type BuildVideoGetQueryOptions = {
-  id: number | string
-  transaction?: Transaction
+  id?: number | string
+  url?: string
+
+  type: 'api' | 'full-light' | 'account-blacklist-files' | 'all-files' | 'thumbnails' | 'thumbnails-blacklist' | 'id' | 'blacklist-rights'
+
   userId?: number
-  forGetAPI?: boolean
+  transaction?: Transaction
+
+  logging?: boolean
 }
 
 export class VideosModelGetQueryBuilder {
@@ -32,11 +37,17 @@ export class VideosModelGetQueryBuilder {
     this.videoModelBuilder = new VideoModelBuilder('get', new VideoTables('get'))
   }
 
-  async queryVideos (options: BuildVideoGetQueryOptions) {
+  async queryVideo (options: BuildVideoGetQueryOptions) {
     const [ videoRows, webtorrentFilesRows, streamingPlaylistFilesRows ] = await Promise.all([
       this.videoQueryBuilder.queryVideos(options),
-      this.webtorrentFilesQueryBuilder.queryWebTorrentVideos(options),
-      this.streamingPlaylistFilesQueryBuilder.queryStreamingPlaylistVideos(options)
+
+      this.shouldQueryVideoFiles(options)
+        ? this.webtorrentFilesQueryBuilder.queryWebTorrentVideos(options)
+        : Promise.resolve(undefined),
+
+      this.shouldQueryVideoFiles(options)
+        ? this.streamingPlaylistFilesQueryBuilder.queryStreamingPlaylistVideos(options)
+        : Promise.resolve(undefined)
     ])
 
     const videos = this.videoModelBuilder.buildVideosFromRows(videoRows, webtorrentFilesRows, streamingPlaylistFilesRows)
@@ -48,6 +59,10 @@ export class VideosModelGetQueryBuilder {
     if (videos.length === 0) return null
     return videos[0]
   }
+
+  private shouldQueryVideoFiles (options: BuildVideoGetQueryOptions) {
+    return [ 'api', 'full-light', 'account-blacklist-files', 'all-files' ].includes(options.type)
+  }
 }
 
 export class VideosModelGetQuerySubBuilder extends AbstractVideosModelQueryBuilder {
@@ -63,7 +78,7 @@ export class VideosModelGetQuerySubBuilder extends AbstractVideosModelQueryBuild
   queryVideos (options: BuildVideoGetQueryOptions) {
     this.buildMainGetQuery(options)
 
-    return this.runQuery(options.transaction)
+    return this.runQuery(options)
   }
 
   private buildMainGetQuery (options: BuildVideoGetQueryOptions) {
@@ -71,36 +86,91 @@ export class VideosModelGetQuerySubBuilder extends AbstractVideosModelQueryBuild
       '"video".*': ''
     }
 
-    this.includeChannels()
-    this.includeAccounts()
+    if (this.shouldIncludeThumbnails(options)) {
+      this.includeThumbnails()
+    }
 
-    this.includeTags()
+    if (this.shouldIncludeBlacklisted(options)) {
+      this.includeBlacklisted()
+    }
 
-    this.includeThumbnails()
+    if (this.shouldIncludeAccount(options)) {
+      this.includeChannels()
+      this.includeAccounts()
+    }
 
-    this.includeBlacklisted()
+    if (this.shouldIncludeTags(options)) {
+      this.includeTags()
+    }
 
-    this.includeScheduleUpdate()
+    if (this.shouldIncludeScheduleUpdate(options)) {
+      this.includeScheduleUpdate()
+    }
 
-    this.includeLive()
+    if (this.shouldIncludeLive(options)) {
+      this.includeLive()
+    }
 
-    if (options.userId) {
+    if (options.userId && this.shouldIncludeUserHistory(options)) {
       this.includeUserHistory(options.userId)
     }
 
-    if (options.forGetAPI === true) {
+    if (this.shouldIncludeOwnerUser(options)) {
+      this.includeOwnerUser()
+    }
+
+    if (this.shouldIncludeTrackers(options)) {
       this.includeTrackers()
     }
 
-    this.whereId(options.id)
+    this.whereId(options)
 
-    this.query = this.buildQuery()
+    this.query = this.buildQuery(options)
   }
 
-  private buildQuery () {
-    const order = 'ORDER BY "Tags"."name" ASC'
+  private buildQuery (options: BuildVideoGetQueryOptions) {
+    const order = this.shouldIncludeTags(options)
+      ? 'ORDER BY "Tags"."name" ASC'
+      : ''
+
     const from = `SELECT * FROM "video" ${this.where} LIMIT 1`
 
     return `${this.buildSelect()} FROM (${from}) AS "video" ${this.joins} ${order}`
   }
+
+  private shouldIncludeTrackers (options: BuildVideoGetQueryOptions) {
+    return options.type === 'api'
+  }
+
+  private shouldIncludeLive (options: BuildVideoGetQueryOptions) {
+    return [ 'api', 'full-light' ].includes(options.type)
+  }
+
+  private shouldIncludeScheduleUpdate (options: BuildVideoGetQueryOptions) {
+    return [ 'api', 'full-light' ].includes(options.type)
+  }
+
+  private shouldIncludeTags (options: BuildVideoGetQueryOptions) {
+    return [ 'api', 'full-light' ].includes(options.type)
+  }
+
+  private shouldIncludeUserHistory (options: BuildVideoGetQueryOptions) {
+    return [ 'api', 'full-light' ].includes(options.type)
+  }
+
+  private shouldIncludeAccount (options: BuildVideoGetQueryOptions) {
+    return [ 'api', 'full-light', 'account-blacklist-files' ].includes(options.type)
+  }
+
+  private shouldIncludeBlacklisted (options: BuildVideoGetQueryOptions) {
+    return [ 'api', 'full-light', 'account-blacklist-files', 'thumbnails-blacklist', 'blacklist-rights' ].includes(options.type)
+  }
+
+  private shouldIncludeOwnerUser (options: BuildVideoGetQueryOptions) {
+    return options.type === 'blacklist-rights'
+  }
+
+  private shouldIncludeThumbnails (options: BuildVideoGetQueryOptions) {
+    return [ 'api', 'full-light', 'account-blacklist-files', 'thumbnails', 'thumbnails-blacklist' ].includes(options.type)
+  }
 }
index d3a9a9466e92d0c6673db25c11cf67d56ba01ec2..43040fc5e6da1be861c5acad4a7dd275f3575983 100644 (file)
@@ -27,7 +27,8 @@ export class VideosModelListQueryBuilder extends AbstractVideosModelQueryBuilder
     this.buildInnerQuery(options)
     this.buildListQueryFromIdsQuery(options)
 
-    return this.runQuery(undefined).then(rows => this.videoModelBuilder.buildVideosFromRows(rows))
+    return this.runQuery()
+      .then(rows => this.videoModelBuilder.buildVideosFromRows(rows))
   }
 
   private buildInnerQuery (options: BuildVideosListQueryOptions) {
index 00fbb18f69249b5f82f193f3049c2b622c41ddd8..2d8b7b653a6c1f8437b9d31d0a0884d99f6d08b1 100644 (file)
@@ -88,13 +88,12 @@ import {
   MVideoFormattableDetails,
   MVideoForUser,
   MVideoFullLight,
-  MVideoIdThumbnail,
+  MVideoId,
   MVideoImmutable,
   MVideoThumbnail,
   MVideoThumbnailBlacklist,
   MVideoWithAllFiles,
-  MVideoWithFile,
-  MVideoWithRights
+  MVideoWithFile
 } from '../../types/models'
 import { MThumbnail } from '../../types/models/video/thumbnail'
 import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../types/models/video/video-file'
@@ -1301,27 +1300,16 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
     return VideoModel.count(options)
   }
 
-  static load (id: number | string, t?: Transaction): Promise<MVideoThumbnail> {
-    const where = buildWhereIdOrUUID(id)
-    const options = {
-      where,
-      transaction: t
-    }
+  static load (id: number | string, transaction?: Transaction): Promise<MVideoThumbnail> {
+    const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
 
-    return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
+    return queryBuilder.queryVideo({ id, transaction, type: 'thumbnails' })
   }
 
-  static loadWithBlacklist (id: number | string, t?: Transaction): Promise<MVideoThumbnailBlacklist> {
-    const where = buildWhereIdOrUUID(id)
-    const options = {
-      where,
-      transaction: t
-    }
+  static loadWithBlacklist (id: number | string, transaction?: Transaction): Promise<MVideoThumbnailBlacklist> {
+    const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
 
-    return VideoModel.scope([
-      ScopeNames.WITH_THUMBNAILS,
-      ScopeNames.WITH_BLACKLISTED
-    ]).findOne(options)
+    return queryBuilder.queryVideo({ id, transaction, type: 'thumbnails-blacklist' })
   }
 
   static loadImmutableAttributes (id: number | string, t?: Transaction): Promise<MVideoImmutable> {
@@ -1342,68 +1330,6 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
     })
   }
 
-  static loadWithRights (id: number | string, t?: Transaction): Promise<MVideoWithRights> {
-    const where = buildWhereIdOrUUID(id)
-    const options = {
-      where,
-      transaction: t
-    }
-
-    return VideoModel.scope([
-      ScopeNames.WITH_BLACKLISTED,
-      ScopeNames.WITH_USER_ID
-    ]).findOne(options)
-  }
-
-  static loadOnlyId (id: number | string, t?: Transaction): Promise<MVideoIdThumbnail> {
-    const where = buildWhereIdOrUUID(id)
-
-    const options = {
-      attributes: [ 'id' ],
-      where,
-      transaction: t
-    }
-
-    return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
-  }
-
-  static loadWithFiles (id: number | string, t?: Transaction, logging?: boolean): Promise<MVideoWithAllFiles> {
-    const where = buildWhereIdOrUUID(id)
-
-    const query = {
-      where,
-      transaction: t,
-      logging
-    }
-
-    return VideoModel.scope([
-      ScopeNames.WITH_WEBTORRENT_FILES,
-      ScopeNames.WITH_STREAMING_PLAYLISTS,
-      ScopeNames.WITH_THUMBNAILS
-    ]).findOne(query)
-  }
-
-  static loadByUUID (uuid: string): Promise<MVideoThumbnail> {
-    const options = {
-      where: {
-        uuid
-      }
-    }
-
-    return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
-  }
-
-  static loadByUrl (url: string, transaction?: Transaction): Promise<MVideoThumbnail> {
-    const query: FindOptions = {
-      where: {
-        url
-      },
-      transaction
-    }
-
-    return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(query)
-  }
-
   static loadByUrlImmutableAttributes (url: string, transaction?: Transaction): Promise<MVideoImmutable> {
     const fun = () => {
       const query: FindOptions = {
@@ -1424,50 +1350,34 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
     })
   }
 
-  static loadByUrlAndPopulateAccount (url: string, transaction?: Transaction): Promise<MVideoAccountLightBlacklistAllFiles> {
-    const query: FindOptions = {
-      where: {
-        url
-      },
-      transaction
-    }
+  static loadOnlyId (id: number | string, transaction?: Transaction): Promise<MVideoId> {
+    const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
 
-    return VideoModel.scope([
-      ScopeNames.WITH_ACCOUNT_DETAILS,
-      ScopeNames.WITH_WEBTORRENT_FILES,
-      ScopeNames.WITH_STREAMING_PLAYLISTS,
-      ScopeNames.WITH_THUMBNAILS,
-      ScopeNames.WITH_BLACKLISTED
-    ]).findOne(query)
+    return queryBuilder.queryVideo({ id, transaction, type: 'id' })
   }
 
-  static loadAndPopulateAccountAndServerAndTags (id: number | string, t?: Transaction, userId?: number): Promise<MVideoFullLight> {
-    const where = buildWhereIdOrUUID(id)
+  static loadWithFiles (id: number | string, transaction?: Transaction, logging?: boolean): Promise<MVideoWithAllFiles> {
+    const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
 
-    const options = {
-      order: [ [ 'Tags', 'name', 'ASC' ] ] as any,
-      where,
-      transaction: t
-    }
+    return queryBuilder.queryVideo({ id, transaction, type: 'all-files', logging })
+  }
 
-    const scopes: (string | ScopeOptions)[] = [
-      ScopeNames.WITH_TAGS,
-      ScopeNames.WITH_BLACKLISTED,
-      ScopeNames.WITH_ACCOUNT_DETAILS,
-      ScopeNames.WITH_SCHEDULED_UPDATE,
-      ScopeNames.WITH_WEBTORRENT_FILES,
-      ScopeNames.WITH_STREAMING_PLAYLISTS,
-      ScopeNames.WITH_THUMBNAILS,
-      ScopeNames.WITH_LIVE
-    ]
+  static loadByUrl (url: string, transaction?: Transaction): Promise<MVideoThumbnail> {
+    const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
 
-    if (userId) {
-      scopes.push({ method: [ ScopeNames.WITH_USER_HISTORY, userId ] })
-    }
+    return queryBuilder.queryVideo({ url, transaction, type: 'thumbnails' })
+  }
+
+  static loadByUrlAndPopulateAccount (url: string, transaction?: Transaction): Promise<MVideoAccountLightBlacklistAllFiles> {
+    const queryBuilder = new VideosModelGetQueryBuilder(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)
 
-    return VideoModel
-      .scope(scopes)
-      .findOne(options)
+    return queryBuilder.queryVideo({ id, transaction: t, type: 'full-light', userId })
   }
 
   static loadForGetAPI (parameters: {
@@ -1478,7 +1388,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
     const { id, transaction, userId } = parameters
     const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
 
-    return queryBuilder.queryVideos({ id, transaction, forGetAPI: true, userId })
+    return queryBuilder.queryVideo({ id, transaction, type: 'api', userId })
   }
 
   static async getStats () {
index 00ff689438597b11d225a8ae3d1195ce537b0c34..de673f4fcc3cfcceb166a458b313b8c2951acdd1 100644 (file)
@@ -11,6 +11,7 @@ import {
   MVideoChangeOwnershipFull,
   MVideoFile,
   MVideoFormattableDetails,
+  MVideoId,
   MVideoImmutable,
   MVideoLive,
   MVideoPlaylistFull,
@@ -106,8 +107,7 @@ declare module 'express' {
       videoAll?: MVideoFullLight
       onlyImmutableVideo?: MVideoImmutable
       onlyVideo?: MVideoThumbnail
-      onlyVideoWithRights?: MVideoWithRights
-      videoId?: MVideoIdThumbnail
+      videoId?: MVideoId
 
       videoLive?: MVideoLive