]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/models/video/sql/videos-id-list-query-builder.ts
Don't stuck state when move transcoding job failed
[github/Chocobozzz/PeerTube.git] / server / models / video / sql / videos-id-list-query-builder.ts
index 3eb547e75c85303688128833592652910d0edc80..76aafb88333cbe5d72d0a0c26db06bf88e2621b1 100644 (file)
@@ -5,7 +5,7 @@ import { WEBSERVER } from '@server/initializers/constants'
 import { buildDirectionAndField, createSafeIn } from '@server/models/utils'
 import { MUserAccountId, MUserId } from '@server/types/models'
 import { VideoInclude, VideoPrivacy, VideoState } from '@shared/models'
-import { AbstractVideosQueryBuilder } from './shared/abstract-videos-query-builder'
+import { AbstractRunQuery } from './shared/abstract-run-query'
 
 /**
  *
@@ -40,10 +40,13 @@ export type BuildVideosListQueryOptions = {
   languageOneOf?: string[]
   tagsOneOf?: string[]
   tagsAllOf?: string[]
+  privacyOneOf?: VideoPrivacy[]
 
   uuids?: string[]
 
-  withFiles?: boolean
+  hasFiles?: boolean
+  hasHLSFiles?: boolean
+  hasWebtorrentFiles?: boolean
 
   accountId?: number
   videoChannelId?: number
@@ -72,7 +75,7 @@ export type BuildVideosListQueryOptions = {
   having?: string
 }
 
-export class VideosIdListQueryBuilder extends AbstractVideosQueryBuilder {
+export class VideosIdListQueryBuilder extends AbstractRunQuery {
   protected replacements: any = {}
 
   private attributes: string[]
@@ -105,7 +108,7 @@ export class VideosIdListQueryBuilder extends AbstractVideosQueryBuilder {
     return this.runQuery().then(rows => rows.length !== 0 ? rows[0].total : 0)
   }
 
-  getIdsListQueryAndSort (options: BuildVideosListQueryOptions) {
+  getQuery (options: BuildVideosListQueryOptions) {
     this.buildIdsListQuery(options)
 
     return { query: this.query, sort: this.sort, replacements: this.replacements }
@@ -136,11 +139,6 @@ export class VideosIdListQueryBuilder extends AbstractVideosQueryBuilder {
       this.whereStateAvailable()
     }
 
-    // Only list videos with the appropriate priavcy
-    if (!(options.include & VideoInclude.HIDDEN_PRIVACY)) {
-      this.wherePrivacyAvailable(options.user)
-    }
-
     if (options.videoPlaylistId) {
       this.joinPlaylist(options.videoPlaylistId)
     }
@@ -165,10 +163,18 @@ export class VideosIdListQueryBuilder extends AbstractVideosQueryBuilder {
       this.whereFollowerActorId(options.displayOnlyForFollower)
     }
 
-    if (options.withFiles === true) {
+    if (options.hasFiles === true) {
       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)
     }
@@ -177,6 +183,13 @@ export class VideosIdListQueryBuilder extends AbstractVideosQueryBuilder {
       this.whereTagsAllOf(options.tagsAllOf)
     }
 
+    if (options.privacyOneOf) {
+      this.wherePrivacyOneOf(options.privacyOneOf)
+    } else {
+      // Only list videos with the appropriate priavcy
+      this.wherePrivacyAvailable(options.user)
+    }
+
     if (options.uuids) {
       this.whereUUIDs(options.uuids)
     }
@@ -354,9 +367,10 @@ export class VideosIdListQueryBuilder extends AbstractVideosQueryBuilder {
     '    WHERE "videoShare"."videoId" = "video"."id"' +
     '  )' +
     '  OR' +
-    '  EXISTS (' + // Videos published by accounts we follow
+    '  EXISTS (' + // Videos published by channels or accounts we follow
     '    SELECT 1 from "actorFollow" ' +
-    '    WHERE "actorFollow"."targetActorId" = "account"."actorId" AND "actorFollow"."actorId" = :followerActorId ' +
+    '    WHERE ("actorFollow"."targetActorId" = "account"."actorId" OR "actorFollow"."targetActorId" = "videoChannel"."actorId") ' +
+    '    AND "actorFollow"."actorId" = :followerActorId ' +
     '    AND "actorFollow"."state" = \'accepted\'' +
     '  )'
 
@@ -371,16 +385,31 @@ export class VideosIdListQueryBuilder extends AbstractVideosQueryBuilder {
   }
 
   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[]) {
@@ -410,6 +439,11 @@ export class VideosIdListQueryBuilder extends AbstractVideosQueryBuilder {
     )
   }
 
+  private wherePrivacyOneOf (privacyOneOf: VideoPrivacy[]) {
+    this.and.push('"video"."privacy" IN (:privacyOneOf)')
+    this.replacements.privacyOneOf = privacyOneOf
+  }
+
   private whereUUIDs (uuids: string[]) {
     this.and.push('"video"."uuid" IN (' + createSafeIn(this.sequelize, uuids) + ')')
   }