aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/video
diff options
context:
space:
mode:
Diffstat (limited to 'server/models/video')
-rw-r--r--server/models/video/schedule-video-update.ts9
-rw-r--r--server/models/video/tag.ts3
-rw-r--r--server/models/video/thumbnail.ts3
-rw-r--r--server/models/video/video-blacklist.ts3
-rw-r--r--server/models/video/video-caption.ts3
-rw-r--r--server/models/video/video-change-ownership.ts3
-rw-r--r--server/models/video/video-channel.ts9
-rw-r--r--server/models/video/video-comment.ts7
-rw-r--r--server/models/video/video-file.ts3
-rw-r--r--server/models/video/video-import.ts7
-rw-r--r--server/models/video/video-live.ts3
-rw-r--r--server/models/video/video-playlist-element.ts6
-rw-r--r--server/models/video/video-playlist.ts7
-rw-r--r--server/models/video/video-query-builder.ts22
-rw-r--r--server/models/video/video-share.ts5
-rw-r--r--server/models/video/video-streaming-playlist.ts3
-rw-r--r--server/models/video/video-tag.ts3
-rw-r--r--server/models/video/video-view.ts5
-rw-r--r--server/models/video/video.ts25
19 files changed, 74 insertions, 55 deletions
diff --git a/server/models/video/schedule-video-update.ts b/server/models/video/schedule-video-update.ts
index 22b08e91a..b0952c431 100644
--- a/server/models/video/schedule-video-update.ts
+++ b/server/models/video/schedule-video-update.ts
@@ -1,8 +1,9 @@
1import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { ScopeNames as VideoScopeNames, VideoModel } from './video'
3import { VideoPrivacy } from '../../../shared/models/videos'
4import { Op, Transaction } from 'sequelize' 1import { Op, Transaction } from 'sequelize'
2import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
5import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdateVideoAll } from '@server/types/models' 3import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdateVideoAll } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils'
5import { VideoPrivacy } from '../../../shared/models/videos'
6import { ScopeNames as VideoScopeNames, VideoModel } from './video'
6 7
7@Table({ 8@Table({
8 tableName: 'scheduleVideoUpdate', 9 tableName: 'scheduleVideoUpdate',
@@ -16,7 +17,7 @@ import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdateVideoAll } from '@
16 } 17 }
17 ] 18 ]
18}) 19})
19export class ScheduleVideoUpdateModel extends Model { 20export class ScheduleVideoUpdateModel extends Model<Partial<AttributesOnly<ScheduleVideoUpdateModel>>> {
20 21
21 @AllowNull(false) 22 @AllowNull(false)
22 @Default(null) 23 @Default(null)
diff --git a/server/models/video/tag.ts b/server/models/video/tag.ts
index d04205703..c1eebe27f 100644
--- a/server/models/video/tag.ts
+++ b/server/models/video/tag.ts
@@ -1,6 +1,7 @@
1import { col, fn, QueryTypes, Transaction } from 'sequelize' 1import { col, fn, QueryTypes, Transaction } from 'sequelize'
2import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
3import { MTag } from '@server/types/models' 3import { MTag } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils'
4import { VideoPrivacy, VideoState } from '../../../shared/models/videos' 5import { VideoPrivacy, VideoState } from '../../../shared/models/videos'
5import { isVideoTagValid } from '../../helpers/custom-validators/videos' 6import { isVideoTagValid } from '../../helpers/custom-validators/videos'
6import { throwIfNotValid } from '../utils' 7import { throwIfNotValid } from '../utils'
@@ -21,7 +22,7 @@ import { VideoTagModel } from './video-tag'
21 } 22 }
22 ] 23 ]
23}) 24})
24export class TagModel extends Model { 25export class TagModel extends Model<Partial<AttributesOnly<TagModel>>> {
25 26
26 @AllowNull(false) 27 @AllowNull(false)
27 @Is('VideoTag', value => throwIfNotValid(value, isVideoTagValid, 'tag')) 28 @Is('VideoTag', value => throwIfNotValid(value, isVideoTagValid, 'tag'))
diff --git a/server/models/video/thumbnail.ts b/server/models/video/thumbnail.ts
index f1187c8d6..3388478d9 100644
--- a/server/models/video/thumbnail.ts
+++ b/server/models/video/thumbnail.ts
@@ -17,6 +17,7 @@ import {
17} from 'sequelize-typescript' 17} from 'sequelize-typescript'
18import { afterCommitIfTransaction } from '@server/helpers/database-utils' 18import { afterCommitIfTransaction } from '@server/helpers/database-utils'
19import { MThumbnail, MThumbnailVideo, MVideo } from '@server/types/models' 19import { MThumbnail, MThumbnailVideo, MVideo } from '@server/types/models'
20import { AttributesOnly } from '@shared/core-utils'
20import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' 21import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
21import { logger } from '../../helpers/logger' 22import { logger } from '../../helpers/logger'
22import { CONFIG } from '../../initializers/config' 23import { CONFIG } from '../../initializers/config'
@@ -40,7 +41,7 @@ import { VideoPlaylistModel } from './video-playlist'
40 } 41 }
41 ] 42 ]
42}) 43})
43export class ThumbnailModel extends Model { 44export class ThumbnailModel extends Model<Partial<AttributesOnly<ThumbnailModel>>> {
44 45
45 @AllowNull(false) 46 @AllowNull(false)
46 @Column 47 @Column
diff --git a/server/models/video/video-blacklist.ts b/server/models/video/video-blacklist.ts
index aa18896da..98f4ec9c5 100644
--- a/server/models/video/video-blacklist.ts
+++ b/server/models/video/video-blacklist.ts
@@ -1,6 +1,7 @@
1import { FindOptions } from 'sequelize' 1import { FindOptions } from 'sequelize'
2import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
3import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models' 3import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils'
4import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos' 5import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos'
5import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist' 6import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist'
6import { CONSTRAINTS_FIELDS } from '../../initializers/constants' 7import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
@@ -18,7 +19,7 @@ import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel
18 } 19 }
19 ] 20 ]
20}) 21})
21export class VideoBlacklistModel extends Model { 22export class VideoBlacklistModel extends Model<Partial<AttributesOnly<VideoBlacklistModel>>> {
22 23
23 @AllowNull(true) 24 @AllowNull(true)
24 @Is('VideoBlacklistReason', value => throwIfNotValid(value, isVideoBlacklistReasonValid, 'reason', true)) 25 @Is('VideoBlacklistReason', value => throwIfNotValid(value, isVideoBlacklistReasonValid, 'reason', true))
diff --git a/server/models/video/video-caption.ts b/server/models/video/video-caption.ts
index bfdec73e9..d2c742b66 100644
--- a/server/models/video/video-caption.ts
+++ b/server/models/video/video-caption.ts
@@ -17,6 +17,7 @@ import {
17} from 'sequelize-typescript' 17} from 'sequelize-typescript'
18import { v4 as uuidv4 } from 'uuid' 18import { v4 as uuidv4 } from 'uuid'
19import { MVideo, MVideoCaption, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models' 19import { MVideo, MVideoCaption, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models'
20import { AttributesOnly } from '@shared/core-utils'
20import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model' 21import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model'
21import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions' 22import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions'
22import { logger } from '../../helpers/logger' 23import { logger } from '../../helpers/logger'
@@ -57,7 +58,7 @@ export enum ScopeNames {
57 } 58 }
58 ] 59 ]
59}) 60})
60export class VideoCaptionModel extends Model { 61export class VideoCaptionModel extends Model<Partial<AttributesOnly<VideoCaptionModel>>> {
61 @CreatedAt 62 @CreatedAt
62 createdAt: Date 63 createdAt: Date
63 64
diff --git a/server/models/video/video-change-ownership.ts b/server/models/video/video-change-ownership.ts
index 298e8bfe2..7d20a954d 100644
--- a/server/models/video/video-change-ownership.ts
+++ b/server/models/video/video-change-ownership.ts
@@ -1,5 +1,6 @@
1import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' 1import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
2import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership' 2import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership'
3import { AttributesOnly } from '@shared/core-utils'
3import { VideoChangeOwnership, VideoChangeOwnershipStatus } from '../../../shared/models/videos' 4import { VideoChangeOwnership, VideoChangeOwnershipStatus } from '../../../shared/models/videos'
4import { AccountModel } from '../account/account' 5import { AccountModel } from '../account/account'
5import { getSort } from '../utils' 6import { getSort } from '../utils'
@@ -53,7 +54,7 @@ enum ScopeNames {
53 ] 54 ]
54 } 55 }
55})) 56}))
56export class VideoChangeOwnershipModel extends Model { 57export class VideoChangeOwnershipModel extends Model<Partial<AttributesOnly<VideoChangeOwnershipModel>>> {
57 @CreatedAt 58 @CreatedAt
58 createdAt: Date 59 createdAt: Date
59 60
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts
index 081b21f2d..8c4357009 100644
--- a/server/models/video/video-channel.ts
+++ b/server/models/video/video-channel.ts
@@ -19,6 +19,7 @@ import {
19} from 'sequelize-typescript' 19} from 'sequelize-typescript'
20import { setAsUpdated } from '@server/helpers/database-utils' 20import { setAsUpdated } from '@server/helpers/database-utils'
21import { MAccountActor } from '@server/types/models' 21import { MAccountActor } from '@server/types/models'
22import { AttributesOnly } from '@shared/core-utils'
22import { ActivityPubActor } from '../../../shared/models/activitypub' 23import { ActivityPubActor } from '../../../shared/models/activitypub'
23import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos' 24import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos'
24import { 25import {
@@ -36,9 +37,9 @@ import {
36 MChannelSummaryFormattable 37 MChannelSummaryFormattable
37} from '../../types/models/video' 38} from '../../types/models/video'
38import { AccountModel, ScopeNames as AccountModelScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account' 39import { AccountModel, ScopeNames as AccountModelScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account'
39import { ActorImageModel } from '../account/actor-image' 40import { ActorModel, unusedActorAttributesForAPI } from '../actor/actor'
40import { ActorModel, unusedActorAttributesForAPI } from '../activitypub/actor' 41import { ActorFollowModel } from '../actor/actor-follow'
41import { ActorFollowModel } from '../activitypub/actor-follow' 42import { ActorImageModel } from '../actor/actor-image'
42import { ServerModel } from '../server/server' 43import { ServerModel } from '../server/server'
43import { buildServerIdsFollowedBy, buildTrigramSearchIndex, createSimilarityAttribute, getSort, throwIfNotValid } from '../utils' 44import { buildServerIdsFollowedBy, buildTrigramSearchIndex, createSimilarityAttribute, getSort, throwIfNotValid } from '../utils'
44import { VideoModel } from './video' 45import { VideoModel } from './video'
@@ -246,7 +247,7 @@ export type SummaryOptions = {
246 } 247 }
247 ] 248 ]
248}) 249})
249export class VideoChannelModel extends Model { 250export class VideoChannelModel extends Model<Partial<AttributesOnly<VideoChannelModel>>> {
250 251
251 @AllowNull(false) 252 @AllowNull(false)
252 @Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelNameValid, 'name')) 253 @Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelNameValid, 'name'))
diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts
index 151c2bc81..bdf5d86bc 100644
--- a/server/models/video/video-comment.ts
+++ b/server/models/video/video-comment.ts
@@ -16,10 +16,11 @@ import {
16} from 'sequelize-typescript' 16} from 'sequelize-typescript'
17import { getServerActor } from '@server/models/application/application' 17import { getServerActor } from '@server/models/application/application'
18import { MAccount, MAccountId, MUserAccountId } from '@server/types/models' 18import { MAccount, MAccountId, MUserAccountId } from '@server/types/models'
19import { AttributesOnly } from '@shared/core-utils'
19import { VideoPrivacy } from '@shared/models' 20import { VideoPrivacy } from '@shared/models'
20import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects' 21import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects'
21import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object' 22import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object'
22import { VideoComment, VideoCommentAdmin } from '../../../shared/models/videos/video-comment.model' 23import { VideoComment, VideoCommentAdmin } from '../../../shared/models/videos/comment/video-comment.model'
23import { actorNameAlphabet } from '../../helpers/custom-validators/activitypub/actor' 24import { actorNameAlphabet } from '../../helpers/custom-validators/activitypub/actor'
24import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 25import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
25import { regexpCapture } from '../../helpers/regexp' 26import { regexpCapture } from '../../helpers/regexp'
@@ -39,7 +40,7 @@ import {
39} from '../../types/models/video' 40} from '../../types/models/video'
40import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse' 41import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse'
41import { AccountModel } from '../account/account' 42import { AccountModel } from '../account/account'
42import { ActorModel, unusedActorAttributesForAPI } from '../activitypub/actor' 43import { ActorModel, unusedActorAttributesForAPI } from '../actor/actor'
43import { 44import {
44 buildBlockedAccountSQL, 45 buildBlockedAccountSQL,
45 buildBlockedAccountSQLOptimized, 46 buildBlockedAccountSQLOptimized,
@@ -173,7 +174,7 @@ export enum ScopeNames {
173 } 174 }
174 ] 175 ]
175}) 176})
176export class VideoCommentModel extends Model { 177export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoCommentModel>>> {
177 @CreatedAt 178 @CreatedAt
178 createdAt: Date 179 createdAt: Date
179 180
diff --git a/server/models/video/video-file.ts b/server/models/video/video-file.ts
index 0b5946149..22cf63804 100644
--- a/server/models/video/video-file.ts
+++ b/server/models/video/video-file.ts
@@ -25,6 +25,7 @@ import { logger } from '@server/helpers/logger'
25import { extractVideo } from '@server/helpers/video' 25import { extractVideo } from '@server/helpers/video'
26import { getTorrentFilePath } from '@server/lib/video-paths' 26import { getTorrentFilePath } from '@server/lib/video-paths'
27import { MStreamingPlaylistVideo, MVideo, MVideoWithHost } from '@server/types/models' 27import { MStreamingPlaylistVideo, MVideo, MVideoWithHost } from '@server/types/models'
28import { AttributesOnly } from '@shared/core-utils'
28import { 29import {
29 isVideoFileExtnameValid, 30 isVideoFileExtnameValid,
30 isVideoFileInfoHashValid, 31 isVideoFileInfoHashValid,
@@ -149,7 +150,7 @@ export enum ScopeNames {
149 } 150 }
150 ] 151 ]
151}) 152})
152export class VideoFileModel extends Model { 153export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>>> {
153 @CreatedAt 154 @CreatedAt
154 createdAt: Date 155 createdAt: Date
155 156
diff --git a/server/models/video/video-import.ts b/server/models/video/video-import.ts
index 8324166cc..5c73fb07c 100644
--- a/server/models/video/video-import.ts
+++ b/server/models/video/video-import.ts
@@ -13,15 +13,16 @@ import {
13 Table, 13 Table,
14 UpdatedAt 14 UpdatedAt
15} from 'sequelize-typescript' 15} from 'sequelize-typescript'
16import { afterCommitIfTransaction } from '@server/helpers/database-utils'
16import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import' 17import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import'
18import { AttributesOnly } from '@shared/core-utils'
17import { VideoImport, VideoImportState } from '../../../shared' 19import { VideoImport, VideoImportState } from '../../../shared'
18import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports' 20import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports'
19import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos' 21import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos'
20import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants' 22import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants'
21import { UserModel } from '../account/user' 23import { UserModel } from '../user/user'
22import { getSort, throwIfNotValid } from '../utils' 24import { getSort, throwIfNotValid } from '../utils'
23import { ScopeNames as VideoModelScopeNames, VideoModel } from './video' 25import { ScopeNames as VideoModelScopeNames, VideoModel } from './video'
24import { afterCommitIfTransaction } from '@server/helpers/database-utils'
25 26
26@DefaultScope(() => ({ 27@DefaultScope(() => ({
27 include: [ 28 include: [
@@ -52,7 +53,7 @@ import { afterCommitIfTransaction } from '@server/helpers/database-utils'
52 } 53 }
53 ] 54 ]
54}) 55})
55export class VideoImportModel extends Model { 56export class VideoImportModel extends Model<Partial<AttributesOnly<VideoImportModel>>> {
56 @CreatedAt 57 @CreatedAt
57 createdAt: Date 58 createdAt: Date
58 59
diff --git a/server/models/video/video-live.ts b/server/models/video/video-live.ts
index cb4a9b896..014491d50 100644
--- a/server/models/video/video-live.ts
+++ b/server/models/video/video-live.ts
@@ -1,6 +1,7 @@
1import { AllowNull, BelongsTo, Column, CreatedAt, DataType, DefaultScope, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { AllowNull, BelongsTo, Column, CreatedAt, DataType, DefaultScope, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { WEBSERVER } from '@server/initializers/constants' 2import { WEBSERVER } from '@server/initializers/constants'
3import { MVideoLive, MVideoLiveVideo } from '@server/types/models' 3import { MVideoLive, MVideoLiveVideo } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils'
4import { LiveVideo, VideoState } from '@shared/models' 5import { LiveVideo, VideoState } from '@shared/models'
5import { VideoModel } from './video' 6import { VideoModel } from './video'
6import { VideoBlacklistModel } from './video-blacklist' 7import { VideoBlacklistModel } from './video-blacklist'
@@ -28,7 +29,7 @@ import { VideoBlacklistModel } from './video-blacklist'
28 } 29 }
29 ] 30 ]
30}) 31})
31export class VideoLiveModel extends Model { 32export class VideoLiveModel extends Model<Partial<AttributesOnly<VideoLiveModel>>> {
32 33
33 @AllowNull(true) 34 @AllowNull(true)
34 @Column(DataType.STRING) 35 @Column(DataType.STRING)
diff --git a/server/models/video/video-playlist-element.ts b/server/models/video/video-playlist-element.ts
index d2d7e2740..e6906cb19 100644
--- a/server/models/video/video-playlist-element.ts
+++ b/server/models/video/video-playlist-element.ts
@@ -32,6 +32,7 @@ import { AccountModel } from '../account/account'
32import { getSort, throwIfNotValid } from '../utils' 32import { getSort, throwIfNotValid } from '../utils'
33import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video' 33import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video'
34import { VideoPlaylistModel } from './video-playlist' 34import { VideoPlaylistModel } from './video-playlist'
35import { AttributesOnly } from '@shared/core-utils'
35 36
36@Table({ 37@Table({
37 tableName: 'videoPlaylistElement', 38 tableName: 'videoPlaylistElement',
@@ -48,7 +49,7 @@ import { VideoPlaylistModel } from './video-playlist'
48 } 49 }
49 ] 50 ]
50}) 51})
51export class VideoPlaylistElementModel extends Model { 52export class VideoPlaylistElementModel extends Model<Partial<AttributesOnly<VideoPlaylistElementModel>>> {
52 @CreatedAt 53 @CreatedAt
53 createdAt: Date 54 createdAt: Date
54 55
@@ -274,7 +275,8 @@ export class VideoPlaylistElementModel extends Model {
274 validate: false // We use a literal to update the position 275 validate: false // We use a literal to update the position
275 } 276 }
276 277
277 return VideoPlaylistElementModel.update({ position: Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`) }, query) 278 const positionQuery = Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`)
279 return VideoPlaylistElementModel.update({ position: positionQuery as any }, query)
278 } 280 }
279 281
280 static increasePositionOf ( 282 static increasePositionOf (
diff --git a/server/models/video/video-playlist.ts b/server/models/video/video-playlist.ts
index efe5be36d..98cea1b64 100644
--- a/server/models/video/video-playlist.ts
+++ b/server/models/video/video-playlist.ts
@@ -19,6 +19,7 @@ import {
19} from 'sequelize-typescript' 19} from 'sequelize-typescript'
20import { v4 as uuidv4 } from 'uuid' 20import { v4 as uuidv4 } from 'uuid'
21import { MAccountId, MChannelId } from '@server/types/models' 21import { MAccountId, MChannelId } from '@server/types/models'
22import { AttributesOnly } from '@shared/core-utils'
22import { ActivityIconObject } from '../../../shared/models/activitypub/objects' 23import { ActivityIconObject } from '../../../shared/models/activitypub/objects'
23import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object' 24import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object'
24import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' 25import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model'
@@ -50,11 +51,11 @@ import {
50 MVideoPlaylistIdWithElements 51 MVideoPlaylistIdWithElements
51} from '../../types/models/video/video-playlist' 52} from '../../types/models/video/video-playlist'
52import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions } from '../account/account' 53import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions } from '../account/account'
54import { ActorModel } from '../actor/actor'
53import { buildServerIdsFollowedBy, buildWhereIdOrUUID, getPlaylistSort, isOutdated, throwIfNotValid } from '../utils' 55import { buildServerIdsFollowedBy, buildWhereIdOrUUID, getPlaylistSort, isOutdated, throwIfNotValid } from '../utils'
54import { ThumbnailModel } from './thumbnail' 56import { ThumbnailModel } from './thumbnail'
55import { ScopeNames as VideoChannelScopeNames, VideoChannelModel } from './video-channel' 57import { ScopeNames as VideoChannelScopeNames, VideoChannelModel } from './video-channel'
56import { VideoPlaylistElementModel } from './video-playlist-element' 58import { VideoPlaylistElementModel } from './video-playlist-element'
57import { ActorModel } from '../activitypub/actor'
58 59
59enum ScopeNames { 60enum ScopeNames {
60 AVAILABLE_FOR_LIST = 'AVAILABLE_FOR_LIST', 61 AVAILABLE_FOR_LIST = 'AVAILABLE_FOR_LIST',
@@ -221,7 +222,7 @@ type AvailableForListOptions = {
221 } 222 }
222 ] 223 ]
223}) 224})
224export class VideoPlaylistModel extends Model { 225export class VideoPlaylistModel extends Model<Partial<AttributesOnly<VideoPlaylistModel>>> {
225 @CreatedAt 226 @CreatedAt
226 createdAt: Date 227 createdAt: Date
227 228
@@ -495,7 +496,7 @@ export class VideoPlaylistModel extends Model {
495 } 496 }
496 497
497 getWatchUrl () { 498 getWatchUrl () {
498 return WEBSERVER.URL + '/videos/watch/playlist/' + this.uuid 499 return WEBSERVER.URL + '/w/p/' + this.uuid
499 } 500 }
500 501
501 getEmbedStaticPath () { 502 getEmbedStaticPath () {
diff --git a/server/models/video/video-query-builder.ts b/server/models/video/video-query-builder.ts
index 155afe64b..2aa5e65c8 100644
--- a/server/models/video/video-query-builder.ts
+++ b/server/models/video/video-query-builder.ts
@@ -1,9 +1,9 @@
1import { VideoFilter, VideoPrivacy, VideoState } from '@shared/models' 1import { Sequelize } from 'sequelize/types'
2import { buildDirectionAndField, createSafeIn } from '@server/models/utils'
3import { Model } from 'sequelize-typescript'
4import { MUserAccountId, MUserId } from '@server/types/models'
5import validator from 'validator' 2import validator from 'validator'
6import { exists } from '@server/helpers/custom-validators/misc' 3import { exists } from '@server/helpers/custom-validators/misc'
4import { buildDirectionAndField, createSafeIn } from '@server/models/utils'
5import { MUserAccountId, MUserId } from '@server/types/models'
6import { VideoFilter, VideoPrivacy, VideoState } from '@shared/models'
7 7
8export type BuildVideosQueryOptions = { 8export type BuildVideosQueryOptions = {
9 attributes?: string[] 9 attributes?: string[]
@@ -55,7 +55,7 @@ export type BuildVideosQueryOptions = {
55 having?: string 55 having?: string
56} 56}
57 57
58function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) { 58function buildListQuery (sequelize: Sequelize, options: BuildVideosQueryOptions) {
59 const and: string[] = [] 59 const and: string[] = []
60 const joins: string[] = [] 60 const joins: string[] = []
61 const replacements: any = {} 61 const replacements: any = {}
@@ -77,7 +77,7 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions)
77 const blockerIds = [ options.serverAccountId ] 77 const blockerIds = [ options.serverAccountId ]
78 if (options.user) blockerIds.push(options.user.Account.id) 78 if (options.user) blockerIds.push(options.user.Account.id)
79 79
80 const inClause = createSafeIn(model, blockerIds) 80 const inClause = createSafeIn(sequelize, blockerIds)
81 81
82 and.push( 82 and.push(
83 'NOT EXISTS (' + 83 'NOT EXISTS (' +
@@ -179,7 +179,7 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions)
179 'EXISTS (' + 179 'EXISTS (' +
180 ' SELECT 1 FROM "videoTag" ' + 180 ' SELECT 1 FROM "videoTag" ' +
181 ' INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + 181 ' INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' +
182 ' WHERE lower("tag"."name") IN (' + createSafeIn(model, tagsOneOfLower) + ') ' + 182 ' WHERE lower("tag"."name") IN (' + createSafeIn(sequelize, tagsOneOfLower) + ') ' +
183 ' AND "video"."id" = "videoTag"."videoId"' + 183 ' AND "video"."id" = "videoTag"."videoId"' +
184 ')' 184 ')'
185 ) 185 )
@@ -192,7 +192,7 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions)
192 'EXISTS (' + 192 'EXISTS (' +
193 ' SELECT 1 FROM "videoTag" ' + 193 ' SELECT 1 FROM "videoTag" ' +
194 ' INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + 194 ' INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' +
195 ' WHERE lower("tag"."name") IN (' + createSafeIn(model, tagsAllOfLower) + ') ' + 195 ' WHERE lower("tag"."name") IN (' + createSafeIn(sequelize, tagsAllOfLower) + ') ' +
196 ' AND "video"."id" = "videoTag"."videoId" ' + 196 ' AND "video"."id" = "videoTag"."videoId" ' +
197 ' GROUP BY "videoTag"."videoId" HAVING COUNT(*) = ' + tagsAllOfLower.length + 197 ' GROUP BY "videoTag"."videoId" HAVING COUNT(*) = ' + tagsAllOfLower.length +
198 ')' 198 ')'
@@ -232,7 +232,7 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions)
232 languagesQueryParts.push( 232 languagesQueryParts.push(
233 'EXISTS (' + 233 'EXISTS (' +
234 ' SELECT 1 FROM "videoCaption" WHERE "videoCaption"."language" ' + 234 ' SELECT 1 FROM "videoCaption" WHERE "videoCaption"."language" ' +
235 ' IN (' + createSafeIn(model, languages) + ') AND ' + 235 ' IN (' + createSafeIn(sequelize, languages) + ') AND ' +
236 ' "videoCaption"."videoId" = "video"."id"' + 236 ' "videoCaption"."videoId" = "video"."id"' +
237 ')' 237 ')'
238 ) 238 )
@@ -345,8 +345,8 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions)
345 } 345 }
346 346
347 if (options.search) { 347 if (options.search) {
348 const escapedSearch = model.sequelize.escape(options.search) 348 const escapedSearch = sequelize.escape(options.search)
349 const escapedLikeSearch = model.sequelize.escape('%' + options.search + '%') 349 const escapedLikeSearch = sequelize.escape('%' + options.search + '%')
350 350
351 cte.push( 351 cte.push(
352 '"trigramSearch" AS (' + 352 '"trigramSearch" AS (' +
diff --git a/server/models/video/video-share.ts b/server/models/video/video-share.ts
index 5059c1fa6..505c305e2 100644
--- a/server/models/video/video-share.ts
+++ b/server/models/video/video-share.ts
@@ -1,10 +1,11 @@
1import { literal, Op, QueryTypes, Transaction } from 'sequelize' 1import { literal, Op, QueryTypes, Transaction } from 'sequelize'
2import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
3import { AttributesOnly } from '@shared/core-utils'
3import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 4import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
4import { CONSTRAINTS_FIELDS } from '../../initializers/constants' 5import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
5import { MActorDefault } from '../../types/models' 6import { MActorDefault } from '../../types/models'
6import { MVideoShareActor, MVideoShareFull } from '../../types/models/video' 7import { MVideoShareActor, MVideoShareFull } from '../../types/models/video'
7import { ActorModel } from '../activitypub/actor' 8import { ActorModel } from '../actor/actor'
8import { buildLocalActorIdsIn, throwIfNotValid } from '../utils' 9import { buildLocalActorIdsIn, throwIfNotValid } from '../utils'
9import { VideoModel } from './video' 10import { VideoModel } from './video'
10 11
@@ -50,7 +51,7 @@ enum ScopeNames {
50 } 51 }
51 ] 52 ]
52}) 53})
53export class VideoShareModel extends Model { 54export class VideoShareModel extends Model<Partial<AttributesOnly<VideoShareModel>>> {
54 55
55 @AllowNull(false) 56 @AllowNull(false)
56 @Is('VideoShareUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) 57 @Is('VideoShareUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url'))
diff --git a/server/models/video/video-streaming-playlist.ts b/server/models/video/video-streaming-playlist.ts
index c9375b433..d627e8c9d 100644
--- a/server/models/video/video-streaming-playlist.ts
+++ b/server/models/video/video-streaming-playlist.ts
@@ -13,6 +13,7 @@ import { CONSTRAINTS_FIELDS, MEMOIZE_LENGTH, MEMOIZE_TTL, P2P_MEDIA_LOADER_PEER_
13import { VideoRedundancyModel } from '../redundancy/video-redundancy' 13import { VideoRedundancyModel } from '../redundancy/video-redundancy'
14import { throwIfNotValid } from '../utils' 14import { throwIfNotValid } from '../utils'
15import { VideoModel } from './video' 15import { VideoModel } from './video'
16import { AttributesOnly } from '@shared/core-utils'
16 17
17@Table({ 18@Table({
18 tableName: 'videoStreamingPlaylist', 19 tableName: 'videoStreamingPlaylist',
@@ -30,7 +31,7 @@ import { VideoModel } from './video'
30 } 31 }
31 ] 32 ]
32}) 33})
33export class VideoStreamingPlaylistModel extends Model { 34export class VideoStreamingPlaylistModel extends Model<Partial<AttributesOnly<VideoStreamingPlaylistModel>>> {
34 @CreatedAt 35 @CreatedAt
35 createdAt: Date 36 createdAt: Date
36 37
diff --git a/server/models/video/video-tag.ts b/server/models/video/video-tag.ts
index 5052b8c4d..1285d375b 100644
--- a/server/models/video/video-tag.ts
+++ b/server/models/video/video-tag.ts
@@ -1,4 +1,5 @@
1import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { AttributesOnly } from '@shared/core-utils'
2import { TagModel } from './tag' 3import { TagModel } from './tag'
3import { VideoModel } from './video' 4import { VideoModel } from './video'
4 5
@@ -13,7 +14,7 @@ import { VideoModel } from './video'
13 } 14 }
14 ] 15 ]
15}) 16})
16export class VideoTagModel extends Model { 17export class VideoTagModel extends Model<Partial<AttributesOnly<VideoTagModel>>> {
17 @CreatedAt 18 @CreatedAt
18 createdAt: Date 19 createdAt: Date
19 20
diff --git a/server/models/video/video-view.ts b/server/models/video/video-view.ts
index 992cf258a..dfc6296ce 100644
--- a/server/models/video/video-view.ts
+++ b/server/models/video/video-view.ts
@@ -1,6 +1,7 @@
1import * as Sequelize from 'sequelize'
1import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Table } from 'sequelize-typescript' 2import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Table } from 'sequelize-typescript'
3import { AttributesOnly } from '@shared/core-utils'
2import { VideoModel } from './video' 4import { VideoModel } from './video'
3import * as Sequelize from 'sequelize'
4 5
5@Table({ 6@Table({
6 tableName: 'videoView', 7 tableName: 'videoView',
@@ -14,7 +15,7 @@ import * as Sequelize from 'sequelize'
14 } 15 }
15 ] 16 ]
16}) 17})
17export class VideoViewModel extends Model { 18export class VideoViewModel extends Model<Partial<AttributesOnly<VideoViewModel>>> {
18 @CreatedAt 19 @CreatedAt
19 createdAt: Date 20 createdAt: Date
20 21
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 18afba1ba..8f561116b 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -31,6 +31,7 @@ import { LiveManager } from '@server/lib/live-manager'
31import { getHLSDirectory, getVideoFilePath } from '@server/lib/video-paths' 31import { getHLSDirectory, getVideoFilePath } from '@server/lib/video-paths'
32import { getServerActor } from '@server/models/application/application' 32import { getServerActor } from '@server/models/application/application'
33import { ModelCache } from '@server/models/model-cache' 33import { ModelCache } from '@server/models/model-cache'
34import { AttributesOnly } from '@shared/core-utils'
34import { VideoFile } from '@shared/models/videos/video-file.model' 35import { VideoFile } from '@shared/models/videos/video-file.model'
35import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared' 36import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared'
36import { VideoObject } from '../../../shared/models/activitypub/objects' 37import { VideoObject } from '../../../shared/models/activitypub/objects'
@@ -100,14 +101,14 @@ import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../types/models
100import { VideoAbuseModel } from '../abuse/video-abuse' 101import { VideoAbuseModel } from '../abuse/video-abuse'
101import { AccountModel } from '../account/account' 102import { AccountModel } from '../account/account'
102import { AccountVideoRateModel } from '../account/account-video-rate' 103import { AccountVideoRateModel } from '../account/account-video-rate'
103import { ActorImageModel } from '../account/actor-image' 104import { ActorModel } from '../actor/actor'
104import { UserModel } from '../account/user' 105import { ActorImageModel } from '../actor/actor-image'
105import { UserVideoHistoryModel } from '../account/user-video-history'
106import { ActorModel } from '../activitypub/actor'
107import { VideoRedundancyModel } from '../redundancy/video-redundancy' 106import { VideoRedundancyModel } from '../redundancy/video-redundancy'
108import { ServerModel } from '../server/server' 107import { ServerModel } from '../server/server'
109import { TrackerModel } from '../server/tracker' 108import { TrackerModel } from '../server/tracker'
110import { VideoTrackerModel } from '../server/video-tracker' 109import { VideoTrackerModel } from '../server/video-tracker'
110import { UserModel } from '../user/user'
111import { UserVideoHistoryModel } from '../user/user-video-history'
111import { buildTrigramSearchIndex, buildWhereIdOrUUID, getVideoSort, isOutdated, throwIfNotValid } from '../utils' 112import { buildTrigramSearchIndex, buildWhereIdOrUUID, getVideoSort, isOutdated, throwIfNotValid } from '../utils'
112import { ScheduleVideoUpdateModel } from './schedule-video-update' 113import { ScheduleVideoUpdateModel } from './schedule-video-update'
113import { TagModel } from './tag' 114import { TagModel } from './tag'
@@ -489,7 +490,7 @@ export type AvailableForListIDsOptions = {
489 } 490 }
490 ] 491 ]
491}) 492})
492export class VideoModel extends Model { 493export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
493 494
494 @AllowNull(false) 495 @AllowNull(false)
495 @Default(DataType.UUIDV4) 496 @Default(DataType.UUIDV4)
@@ -1003,9 +1004,9 @@ export class VideoModel extends Model {
1003 }) 1004 })
1004 } 1005 }
1005 1006
1006 static async listPublishedLiveIds () { 1007 static async listPublishedLiveUUIDs () {
1007 const options = { 1008 const options = {
1008 attributes: [ 'id' ], 1009 attributes: [ 'uuid' ],
1009 where: { 1010 where: {
1010 isLive: true, 1011 isLive: true,
1011 remote: false, 1012 remote: false,
@@ -1015,7 +1016,7 @@ export class VideoModel extends Model {
1015 1016
1016 const result = await VideoModel.findAll(options) 1017 const result = await VideoModel.findAll(options)
1017 1018
1018 return result.map(v => v.id) 1019 return result.map(v => v.uuid)
1019 } 1020 }
1020 1021
1021 static listUserVideosForApi (options: { 1022 static listUserVideosForApi (options: {
@@ -1618,7 +1619,7 @@ export class VideoModel extends Model {
1618 includeLocalVideos: true 1619 includeLocalVideos: true
1619 } 1620 }
1620 1621
1621 const { query, replacements } = buildListQuery(VideoModel, queryOptions) 1622 const { query, replacements } = buildListQuery(VideoModel.sequelize, queryOptions)
1622 1623
1623 return this.sequelize.query<any>(query, { replacements, type: QueryTypes.SELECT }) 1624 return this.sequelize.query<any>(query, { replacements, type: QueryTypes.SELECT })
1624 .then(rows => rows.map(r => r[field])) 1625 .then(rows => rows.map(r => r[field]))
@@ -1646,7 +1647,7 @@ export class VideoModel extends Model {
1646 if (countVideos !== true) return Promise.resolve(undefined) 1647 if (countVideos !== true) return Promise.resolve(undefined)
1647 1648
1648 const countOptions = Object.assign({}, options, { isCount: true }) 1649 const countOptions = Object.assign({}, options, { isCount: true })
1649 const { query: queryCount, replacements: replacementsCount } = buildListQuery(VideoModel, countOptions) 1650 const { query: queryCount, replacements: replacementsCount } = buildListQuery(VideoModel.sequelize, countOptions)
1650 1651
1651 return VideoModel.sequelize.query<any>(queryCount, { replacements: replacementsCount, type: QueryTypes.SELECT }) 1652 return VideoModel.sequelize.query<any>(queryCount, { replacements: replacementsCount, type: QueryTypes.SELECT })
1652 .then(rows => rows.length !== 0 ? rows[0].total : 0) 1653 .then(rows => rows.length !== 0 ? rows[0].total : 0)
@@ -1655,7 +1656,7 @@ export class VideoModel extends Model {
1655 function getModels () { 1656 function getModels () {
1656 if (options.count === 0) return Promise.resolve([]) 1657 if (options.count === 0) return Promise.resolve([])
1657 1658
1658 const { query, replacements, order } = buildListQuery(VideoModel, options) 1659 const { query, replacements, order } = buildListQuery(VideoModel.sequelize, options)
1659 const queryModels = wrapForAPIResults(query, replacements, options, order) 1660 const queryModels = wrapForAPIResults(query, replacements, options, order)
1660 1661
1661 return VideoModel.sequelize.query<any>(queryModels, { replacements, type: QueryTypes.SELECT, nest: true }) 1662 return VideoModel.sequelize.query<any>(queryModels, { replacements, type: QueryTypes.SELECT, nest: true })
@@ -1919,7 +1920,7 @@ export class VideoModel extends Model {
1919 } 1920 }
1920 1921
1921 getWatchStaticPath () { 1922 getWatchStaticPath () {
1922 return '/videos/watch/' + this.uuid 1923 return '/w/' + this.uuid
1923 } 1924 }
1924 1925
1925 getEmbedStaticPath () { 1926 getEmbedStaticPath () {