]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/models/video/video.ts
Merge branch 'release/3.2.0' into develop
[github/Chocobozzz/PeerTube.git] / server / models / video / video.ts
index b10c6e38e660764ea91113d4103bcd7207c9d856..8f561116be70622f49eb898c1e6af7968d16dfd9 100644 (file)
@@ -24,12 +24,14 @@ import {
   Table,
   UpdatedAt
 } from 'sequelize-typescript'
+import { setAsUpdated } from '@server/helpers/database-utils'
 import { buildNSFWFilter } from '@server/helpers/express-utils'
 import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video'
 import { LiveManager } from '@server/lib/live-manager'
 import { getHLSDirectory, getVideoFilePath } from '@server/lib/video-paths'
 import { getServerActor } from '@server/models/application/application'
 import { ModelCache } from '@server/models/model-cache'
+import { AttributesOnly } from '@shared/core-utils'
 import { VideoFile } from '@shared/models/videos/video-file.model'
 import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared'
 import { VideoObject } from '../../../shared/models/activitypub/objects'
@@ -99,14 +101,14 @@ import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../types/models
 import { VideoAbuseModel } from '../abuse/video-abuse'
 import { AccountModel } from '../account/account'
 import { AccountVideoRateModel } from '../account/account-video-rate'
-import { ActorImageModel } from '../account/actor-image'
-import { UserModel } from '../account/user'
-import { UserVideoHistoryModel } from '../account/user-video-history'
-import { ActorModel } from '../activitypub/actor'
+import { ActorModel } from '../actor/actor'
+import { ActorImageModel } from '../actor/actor-image'
 import { VideoRedundancyModel } from '../redundancy/video-redundancy'
 import { ServerModel } from '../server/server'
 import { TrackerModel } from '../server/tracker'
 import { VideoTrackerModel } from '../server/video-tracker'
+import { UserModel } from '../user/user'
+import { UserVideoHistoryModel } from '../user/user-video-history'
 import { buildTrigramSearchIndex, buildWhereIdOrUUID, getVideoSort, isOutdated, throwIfNotValid } from '../utils'
 import { ScheduleVideoUpdateModel } from './schedule-video-update'
 import { TagModel } from './tag'
@@ -488,7 +490,7 @@ export type AvailableForListIDsOptions = {
     }
   ]
 })
-export class VideoModel extends Model {
+export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
 
   @AllowNull(false)
   @Default(DataType.UUIDV4)
@@ -917,7 +919,7 @@ export class VideoModel extends Model {
       },
       include: [
         {
-          attributes: [ 'language', 'fileUrl' ],
+          attributes: [ 'filename', 'language', 'fileUrl' ],
           model: VideoCaptionModel.unscoped(),
           required: false
         },
@@ -1002,18 +1004,19 @@ export class VideoModel extends Model {
     })
   }
 
-  static async listPublishedLiveIds () {
+  static async listPublishedLiveUUIDs () {
     const options = {
-      attributes: [ 'id' ],
+      attributes: [ 'uuid' ],
       where: {
         isLive: true,
+        remote: false,
         state: VideoState.PUBLISHED
       }
     }
 
     const result = await VideoModel.findAll(options)
 
-    return result.map(v => v.id)
+    return result.map(v => v.uuid)
   }
 
   static listUserVideosForApi (options: {
@@ -1021,14 +1024,28 @@ export class VideoModel extends Model {
     start: number
     count: number
     sort: string
+    isLive?: boolean
     search?: string
   }) {
-    const { accountId, start, count, sort, search } = options
+    const { accountId, start, count, sort, search, isLive } = options
 
     function buildBaseQuery (): FindOptions {
-      let baseQuery = {
+      const where: WhereOptions = {}
+
+      if (search) {
+        where.name = {
+          [Op.iLike]: '%' + search + '%'
+        }
+      }
+
+      if (isLive) {
+        where.isLive = isLive
+      }
+
+      const baseQuery = {
         offset: start,
         limit: count,
+        where,
         order: getVideoSort(sort),
         include: [
           {
@@ -1047,16 +1064,6 @@ export class VideoModel extends Model {
         ]
       }
 
-      if (search) {
-        baseQuery = Object.assign(baseQuery, {
-          where: {
-            name: {
-              [Op.iLike]: '%' + search + '%'
-            }
-          }
-        })
-      }
-
       return baseQuery
     }
 
@@ -1084,23 +1091,34 @@ export class VideoModel extends Model {
     start: number
     count: number
     sort: string
+
     nsfw: boolean
+    filter?: VideoFilter
+    isLive?: boolean
+
     includeLocalVideos: boolean
     withFiles: boolean
+
     categoryOneOf?: number[]
     licenceOneOf?: number[]
     languageOneOf?: string[]
     tagsOneOf?: string[]
     tagsAllOf?: string[]
-    filter?: VideoFilter
+
     accountId?: number
     videoChannelId?: number
+
     followerActorId?: number
+
     videoPlaylistId?: number
+
     trendingDays?: number
+
     user?: MUserAccountId
     historyOfUser?: MUserId
+
     countVideos?: boolean
+
     search?: string
   }) {
     if ((options.filter === 'all-local' || options.filter === 'all') && !options.user.hasRight(UserRight.SEE_ALL_VIDEOS)) {
@@ -1128,6 +1146,7 @@ export class VideoModel extends Model {
       followerActorId,
       serverAccountId: serverActor.Account.id,
       nsfw: options.nsfw,
+      isLive: options.isLive,
       categoryOneOf: options.categoryOneOf,
       licenceOneOf: options.licenceOneOf,
       languageOneOf: options.languageOneOf,
@@ -1160,6 +1179,7 @@ export class VideoModel extends Model {
     originallyPublishedStartDate?: string
     originallyPublishedEndDate?: string
     nsfw?: boolean
+    isLive?: boolean
     categoryOneOf?: number[]
     licenceOneOf?: number[]
     languageOneOf?: string[]
@@ -1171,23 +1191,32 @@ export class VideoModel extends Model {
     filter?: VideoFilter
   }) {
     const serverActor = await getServerActor()
+
     const queryOptions = {
       followerActorId: serverActor.id,
       serverAccountId: serverActor.Account.id,
+
       includeLocalVideos: options.includeLocalVideos,
       nsfw: options.nsfw,
+      isLive: options.isLive,
+
       categoryOneOf: options.categoryOneOf,
       licenceOneOf: options.licenceOneOf,
       languageOneOf: options.languageOneOf,
+
       tagsOneOf: options.tagsOneOf,
       tagsAllOf: options.tagsAllOf,
+
       user: options.user,
       filter: options.filter,
+
       start: options.start,
       count: options.count,
       sort: options.sort,
+
       startDate: options.startDate,
       endDate: options.endDate,
+
       originallyPublishedStartDate: options.originallyPublishedStartDate,
       originallyPublishedEndDate: options.originallyPublishedEndDate,
 
@@ -1590,7 +1619,7 @@ export class VideoModel extends Model {
       includeLocalVideos: true
     }
 
-    const { query, replacements } = buildListQuery(VideoModel, queryOptions)
+    const { query, replacements } = buildListQuery(VideoModel.sequelize, queryOptions)
 
     return this.sequelize.query<any>(query, { replacements, type: QueryTypes.SELECT })
         .then(rows => rows.map(r => r[field]))
@@ -1618,7 +1647,7 @@ export class VideoModel extends Model {
       if (countVideos !== true) return Promise.resolve(undefined)
 
       const countOptions = Object.assign({}, options, { isCount: true })
-      const { query: queryCount, replacements: replacementsCount } = buildListQuery(VideoModel, countOptions)
+      const { query: queryCount, replacements: replacementsCount } = buildListQuery(VideoModel.sequelize, countOptions)
 
       return VideoModel.sequelize.query<any>(queryCount, { replacements: replacementsCount, type: QueryTypes.SELECT })
           .then(rows => rows.length !== 0 ? rows[0].total : 0)
@@ -1627,7 +1656,7 @@ export class VideoModel extends Model {
     function getModels () {
       if (options.count === 0) return Promise.resolve([])
 
-      const { query, replacements, order } = buildListQuery(VideoModel, options)
+      const { query, replacements, order } = buildListQuery(VideoModel.sequelize, options)
       const queryModels = wrapForAPIResults(query, replacements, options, order)
 
       return VideoModel.sequelize.query<any>(queryModels, { replacements, type: QueryTypes.SELECT, nest: true })
@@ -1891,7 +1920,7 @@ export class VideoModel extends Model {
   }
 
   getWatchStaticPath () {
-    return '/videos/watch/' + this.uuid
+    return '/w/' + this.uuid
   }
 
   getEmbedStaticPath () {
@@ -2027,9 +2056,7 @@ export class VideoModel extends Model {
   }
 
   setAsRefreshed () {
-    this.changed('updatedAt', true)
-
-    return this.save()
+    return setAsUpdated('video', this.id)
   }
 
   requiresAuth () {