aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-12-08 14:30:29 +0100
committerChocobozzz <chocobozzz@cpy.re>2020-12-09 11:41:22 +0100
commitb49f22d8f9a52ab75fd38db2d377249eb58fa678 (patch)
treea2825877d7b3b53454804a79c9d2a14c5d37385c /server
parent6c8c15f914cd375da1db5d0cd4d924a86c53d4c1 (diff)
downloadPeerTube-b49f22d8f9a52ab75fd38db2d377249eb58fa678.tar.gz
PeerTube-b49f22d8f9a52ab75fd38db2d377249eb58fa678.tar.zst
PeerTube-b49f22d8f9a52ab75fd38db2d377249eb58fa678.zip
Upgrade sequelize to v6
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/videos/import.ts5
-rw-r--r--server/helpers/actor.ts6
-rw-r--r--server/helpers/middlewares/accounts.ts7
-rw-r--r--server/helpers/video.ts25
-rw-r--r--server/initializers/migrations/0005-email-pod.ts1
-rw-r--r--server/initializers/migrations/0010-email-user.ts1
-rw-r--r--server/initializers/migrations/0015-video-views.ts1
-rw-r--r--server/initializers/migrations/0020-video-likes.ts1
-rw-r--r--server/initializers/migrations/0025-video-dislikes.ts1
-rw-r--r--server/initializers/migrations/0030-video-category.ts1
-rw-r--r--server/initializers/migrations/0035-video-licence.ts1
-rw-r--r--server/initializers/migrations/0040-video-nsfw.ts1
-rw-r--r--server/initializers/migrations/0045-user-display-nsfw.ts1
-rw-r--r--server/initializers/migrations/0050-video-language.ts1
-rw-r--r--server/initializers/migrations/0055-video-uuid.ts1
-rw-r--r--server/initializers/migrations/0060-video-file.ts1
-rw-r--r--server/initializers/migrations/0065-video-file-size.ts1
-rw-r--r--server/initializers/migrations/0070-user-video-quota.ts1
-rw-r--r--server/initializers/migrations/0130-user-autoplay-video.ts1
-rw-r--r--server/initializers/migrations/0150-avatar-cascade.ts3
-rw-r--r--server/initializers/migrations/0410-video-playlist-element.ts3
-rw-r--r--server/lib/activitypub/playlist.ts2
-rw-r--r--server/lib/activitypub/process/process-dislike.ts2
-rw-r--r--server/lib/activitypub/process/process-like.ts2
-rw-r--r--server/lib/activitypub/video-rates.ts15
-rw-r--r--server/lib/activitypub/videos.ts3
-rw-r--r--server/lib/client-html.ts31
-rw-r--r--server/lib/job-queue/handlers/activitypub-http-fetcher.ts21
-rw-r--r--server/lib/video-transcoding-profiles.ts1
-rw-r--r--server/middlewares/validators/users.ts25
-rw-r--r--server/models/abuse/abuse-message.ts6
-rw-r--r--server/models/abuse/abuse.ts7
-rw-r--r--server/models/abuse/video-abuse.ts2
-rw-r--r--server/models/abuse/video-comment-abuse.ts2
-rw-r--r--server/models/account/account-blocklist.ts9
-rw-r--r--server/models/account/account-video-rate.ts53
-rw-r--r--server/models/account/account.ts58
-rw-r--r--server/models/account/user-notification-setting.ts2
-rw-r--r--server/models/account/user-notification.ts2
-rw-r--r--server/models/account/user-video-history.ts2
-rw-r--r--server/models/account/user.ts35
-rw-r--r--server/models/activitypub/actor-follow.ts13
-rw-r--r--server/models/activitypub/actor.ts44
-rw-r--r--server/models/application/application.ts2
-rw-r--r--server/models/avatar/avatar.ts2
-rw-r--r--server/models/model-cache.ts2
-rw-r--r--server/models/oauth/oauth-client.ts2
-rw-r--r--server/models/oauth/oauth-token.ts17
-rw-r--r--server/models/redundancy/video-redundancy.ts45
-rw-r--r--server/models/server/plugin.ts9
-rw-r--r--server/models/server/server-blocklist.ts7
-rw-r--r--server/models/server/server.ts9
-rw-r--r--server/models/utils.ts3
-rw-r--r--server/models/video/schedule-video-update.ts2
-rw-r--r--server/models/video/tag.ts13
-rw-r--r--server/models/video/thumbnail.ts2
-rw-r--r--server/models/video/video-blacklist.ts17
-rw-r--r--server/models/video/video-caption.ts23
-rw-r--r--server/models/video/video-change-ownership.ts11
-rw-r--r--server/models/video/video-channel.ts78
-rw-r--r--server/models/video/video-comment.ts13
-rw-r--r--server/models/video/video-file.ts2
-rw-r--r--server/models/video/video-import.ts15
-rw-r--r--server/models/video/video-live.ts2
-rw-r--r--server/models/video/video-playlist-element.ts33
-rw-r--r--server/models/video/video-playlist.ts22
-rw-r--r--server/models/video/video-share.ts19
-rw-r--r--server/models/video/video-streaming-playlist.ts2
-rw-r--r--server/models/video/video-tag.ts2
-rw-r--r--server/models/video/video-view.ts2
-rw-r--r--server/models/video/video.ts85
-rw-r--r--server/tests/api/live/live.ts7
-rw-r--r--server/types/plugins/register-server-option.model.ts3
73 files changed, 405 insertions, 447 deletions
diff --git a/server/controllers/api/videos/import.ts b/server/controllers/api/videos/import.ts
index cd9ba046d..82e084c54 100644
--- a/server/controllers/api/videos/import.ts
+++ b/server/controllers/api/videos/import.ts
@@ -1,4 +1,3 @@
1import * as Bluebird from 'bluebird'
2import * as express from 'express' 1import * as express from 'express'
3import { move, readFile } from 'fs-extra' 2import { move, readFile } from 'fs-extra'
4import * as magnetUtil from 'magnet-uri' 3import * as magnetUtil from 'magnet-uri'
@@ -17,6 +16,7 @@ import {
17} from '@server/types/models' 16} from '@server/types/models'
18import { MVideoImport, MVideoImportFormattable } from '@server/types/models/video/video-import' 17import { MVideoImport, MVideoImportFormattable } from '@server/types/models/video/video-import'
19import { VideoImportCreate, VideoImportState, VideoPrivacy, VideoState } from '../../../../shared' 18import { VideoImportCreate, VideoImportState, VideoPrivacy, VideoState } from '../../../../shared'
19import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
20import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' 20import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type'
21import { auditLoggerFactory, getAuditIdFromRes, VideoImportAuditView } from '../../../helpers/audit-logger' 21import { auditLoggerFactory, getAuditIdFromRes, VideoImportAuditView } from '../../../helpers/audit-logger'
22import { moveAndProcessCaptionFile } from '../../../helpers/captions-utils' 22import { moveAndProcessCaptionFile } from '../../../helpers/captions-utils'
@@ -36,7 +36,6 @@ import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videoIm
36import { VideoModel } from '../../../models/video/video' 36import { VideoModel } from '../../../models/video/video'
37import { VideoCaptionModel } from '../../../models/video/video-caption' 37import { VideoCaptionModel } from '../../../models/video/video-caption'
38import { VideoImportModel } from '../../../models/video/video-import' 38import { VideoImportModel } from '../../../models/video/video-import'
39import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
40 39
41const auditLogger = auditLoggerFactory('video-imports') 40const auditLogger = auditLoggerFactory('video-imports')
42const videoImportsRouter = express.Router() 41const videoImportsRouter = express.Router()
@@ -314,7 +313,7 @@ function insertIntoDB (parameters: {
314 tags: string[] 313 tags: string[]
315 videoImportAttributes: Partial<MVideoImport> 314 videoImportAttributes: Partial<MVideoImport>
316 user: MUser 315 user: MUser
317}): Bluebird<MVideoImportFormattable> { 316}): Promise<MVideoImportFormattable> {
318 const { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes, user } = parameters 317 const { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes, user } = parameters
319 318
320 return sequelizeTypescript.transaction(async t => { 319 return sequelizeTypescript.transaction(async t => {
diff --git a/server/helpers/actor.ts b/server/helpers/actor.ts
index 015b4a39f..a60d3ed5d 100644
--- a/server/helpers/actor.ts
+++ b/server/helpers/actor.ts
@@ -1,10 +1,10 @@
1
1import { ActorModel } from '../models/activitypub/actor' 2import { ActorModel } from '../models/activitypub/actor'
2import * as Bluebird from 'bluebird' 3import { MActorAccountChannelId, MActorFull } from '../types/models'
3import { MActorFull, MActorAccountChannelId } from '../types/models'
4 4
5type ActorFetchByUrlType = 'all' | 'association-ids' 5type ActorFetchByUrlType = 'all' | 'association-ids'
6 6
7function fetchActorByUrl (url: string, fetchType: ActorFetchByUrlType): Bluebird<MActorFull | MActorAccountChannelId> { 7function fetchActorByUrl (url: string, fetchType: ActorFetchByUrlType): Promise<MActorFull | MActorAccountChannelId> {
8 if (fetchType === 'all') return ActorModel.loadByUrlAndPopulateAccountAndChannel(url) 8 if (fetchType === 'all') return ActorModel.loadByUrlAndPopulateAccountAndChannel(url)
9 9
10 if (fetchType === 'association-ids') return ActorModel.loadByUrl(url) 10 if (fetchType === 'association-ids') return ActorModel.loadByUrl(url)
diff --git a/server/helpers/middlewares/accounts.ts b/server/helpers/middlewares/accounts.ts
index 23470cac6..13ae6cdf4 100644
--- a/server/helpers/middlewares/accounts.ts
+++ b/server/helpers/middlewares/accounts.ts
@@ -1,9 +1,8 @@
1import { Response } from 'express' 1import { Response } from 'express'
2import { AccountModel } from '../../models/account/account'
3import * as Bluebird from 'bluebird'
4import { MAccountDefault } from '../../types/models'
5import { UserModel } from '@server/models/account/user' 2import { UserModel } from '@server/models/account/user'
6import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' 3import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
4import { AccountModel } from '../../models/account/account'
5import { MAccountDefault } from '../../types/models'
7 6
8function doesAccountIdExist (id: number | string, res: Response, sendNotFound = true) { 7function doesAccountIdExist (id: number | string, res: Response, sendNotFound = true) {
9 const promise = AccountModel.load(parseInt(id + '', 10)) 8 const promise = AccountModel.load(parseInt(id + '', 10))
@@ -23,7 +22,7 @@ function doesAccountNameWithHostExist (nameWithDomain: string, res: Response, se
23 return doesAccountExist(promise, res, sendNotFound) 22 return doesAccountExist(promise, res, sendNotFound)
24} 23}
25 24
26async function doesAccountExist (p: Bluebird<MAccountDefault>, res: Response, sendNotFound: boolean) { 25async function doesAccountExist (p: Promise<MAccountDefault>, res: Response, sendNotFound: boolean) {
27 const account = await p 26 const account = await p
28 27
29 if (!account) { 28 if (!account) {
diff --git a/server/helpers/video.ts b/server/helpers/video.ts
index 999137c6d..5d1cd7de1 100644
--- a/server/helpers/video.ts
+++ b/server/helpers/video.ts
@@ -1,4 +1,3 @@
1import * as Bluebird from 'bluebird'
2import { Response } from 'express' 1import { Response } from 'express'
3import { CONFIG } from '@server/initializers/config' 2import { CONFIG } from '@server/initializers/config'
4import { DEFAULT_AUDIO_RESOLUTION } from '@server/initializers/constants' 3import { DEFAULT_AUDIO_RESOLUTION } from '@server/initializers/constants'
@@ -20,21 +19,21 @@ import { VideoModel } from '../models/video/video'
20 19
21type VideoFetchType = 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none' | 'only-immutable-attributes' 20type VideoFetchType = 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none' | 'only-immutable-attributes'
22 21
23function fetchVideo (id: number | string, fetchType: 'all', userId?: number): Bluebird<MVideoFullLight> 22function fetchVideo (id: number | string, fetchType: 'all', userId?: number): Promise<MVideoFullLight>
24function fetchVideo (id: number | string, fetchType: 'only-immutable-attributes'): Bluebird<MVideoImmutable> 23function fetchVideo (id: number | string, fetchType: 'only-immutable-attributes'): Promise<MVideoImmutable>
25function fetchVideo (id: number | string, fetchType: 'only-video', userId?: number): Bluebird<MVideoThumbnail> 24function fetchVideo (id: number | string, fetchType: 'only-video', userId?: number): Promise<MVideoThumbnail>
26function fetchVideo (id: number | string, fetchType: 'only-video-with-rights', userId?: number): Bluebird<MVideoWithRights> 25function fetchVideo (id: number | string, fetchType: 'only-video-with-rights', userId?: number): Promise<MVideoWithRights>
27function fetchVideo (id: number | string, fetchType: 'id' | 'none', userId?: number): Bluebird<MVideoIdThumbnail> 26function fetchVideo (id: number | string, fetchType: 'id' | 'none', userId?: number): Promise<MVideoIdThumbnail>
28function fetchVideo ( 27function fetchVideo (
29 id: number | string, 28 id: number | string,
30 fetchType: VideoFetchType, 29 fetchType: VideoFetchType,
31 userId?: number 30 userId?: number
32): Bluebird<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail | MVideoImmutable> 31): Promise<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail | MVideoImmutable>
33function fetchVideo ( 32function fetchVideo (
34 id: number | string, 33 id: number | string,
35 fetchType: VideoFetchType, 34 fetchType: VideoFetchType,
36 userId?: number 35 userId?: number
37): Bluebird<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail | MVideoImmutable> { 36): Promise<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail | MVideoImmutable> {
38 if (fetchType === 'all') return VideoModel.loadAndPopulateAccountAndServerAndTags(id, undefined, userId) 37 if (fetchType === 'all') return VideoModel.loadAndPopulateAccountAndServerAndTags(id, undefined, userId)
39 38
40 if (fetchType === 'only-immutable-attributes') return VideoModel.loadImmutableAttributes(id) 39 if (fetchType === 'only-immutable-attributes') return VideoModel.loadImmutableAttributes(id)
@@ -48,17 +47,17 @@ function fetchVideo (
48 47
49type VideoFetchByUrlType = 'all' | 'only-video' | 'only-immutable-attributes' 48type VideoFetchByUrlType = 'all' | 'only-video' | 'only-immutable-attributes'
50 49
51function fetchVideoByUrl (url: string, fetchType: 'all'): Bluebird<MVideoAccountLightBlacklistAllFiles> 50function fetchVideoByUrl (url: string, fetchType: 'all'): Promise<MVideoAccountLightBlacklistAllFiles>
52function fetchVideoByUrl (url: string, fetchType: 'only-immutable-attributes'): Bluebird<MVideoImmutable> 51function fetchVideoByUrl (url: string, fetchType: 'only-immutable-attributes'): Promise<MVideoImmutable>
53function fetchVideoByUrl (url: string, fetchType: 'only-video'): Bluebird<MVideoThumbnail> 52function fetchVideoByUrl (url: string, fetchType: 'only-video'): Promise<MVideoThumbnail>
54function fetchVideoByUrl ( 53function fetchVideoByUrl (
55 url: string, 54 url: string,
56 fetchType: VideoFetchByUrlType 55 fetchType: VideoFetchByUrlType
57): Bluebird<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable> 56): Promise<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable>
58function fetchVideoByUrl ( 57function fetchVideoByUrl (
59 url: string, 58 url: string,
60 fetchType: VideoFetchByUrlType 59 fetchType: VideoFetchByUrlType
61): Bluebird<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable> { 60): Promise<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable> {
62 if (fetchType === 'all') return VideoModel.loadByUrlAndPopulateAccount(url) 61 if (fetchType === 'all') return VideoModel.loadByUrlAndPopulateAccount(url)
63 62
64 if (fetchType === 'only-immutable-attributes') return VideoModel.loadByUrlImmutableAttributes(url) 63 if (fetchType === 'only-immutable-attributes') return VideoModel.loadByUrlImmutableAttributes(url)
diff --git a/server/initializers/migrations/0005-email-pod.ts b/server/initializers/migrations/0005-email-pod.ts
index 417c33b1f..025bcdb59 100644
--- a/server/initializers/migrations/0005-email-pod.ts
+++ b/server/initializers/migrations/0005-email-pod.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3import { Migration } from '../../models/migrations' 2import { Migration } from '../../models/migrations'
4 3
5function up (utils: { 4function up (utils: {
diff --git a/server/initializers/migrations/0010-email-user.ts b/server/initializers/migrations/0010-email-user.ts
index f7d01f6d6..4193b7ff9 100644
--- a/server/initializers/migrations/0010-email-user.ts
+++ b/server/initializers/migrations/0010-email-user.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3import { Migration } from '../../models/migrations' 2import { Migration } from '../../models/migrations'
4 3
5function up (utils: { 4function up (utils: {
diff --git a/server/initializers/migrations/0015-video-views.ts b/server/initializers/migrations/0015-video-views.ts
index 47dd4069b..aa80ffbcc 100644
--- a/server/initializers/migrations/0015-video-views.ts
+++ b/server/initializers/migrations/0015-video-views.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3 2
4function up (utils: { 3function up (utils: {
5 transaction: Sequelize.Transaction 4 transaction: Sequelize.Transaction
diff --git a/server/initializers/migrations/0020-video-likes.ts b/server/initializers/migrations/0020-video-likes.ts
index 44333f3b0..aae815a8e 100644
--- a/server/initializers/migrations/0020-video-likes.ts
+++ b/server/initializers/migrations/0020-video-likes.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3 2
4function up (utils: { 3function up (utils: {
5 transaction: Sequelize.Transaction 4 transaction: Sequelize.Transaction
diff --git a/server/initializers/migrations/0025-video-dislikes.ts b/server/initializers/migrations/0025-video-dislikes.ts
index 2aa22e2d7..6eb6fb9dc 100644
--- a/server/initializers/migrations/0025-video-dislikes.ts
+++ b/server/initializers/migrations/0025-video-dislikes.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3 2
4function up (utils: { 3function up (utils: {
5 transaction: Sequelize.Transaction 4 transaction: Sequelize.Transaction
diff --git a/server/initializers/migrations/0030-video-category.ts b/server/initializers/migrations/0030-video-category.ts
index 00cd2d8cf..dd3922549 100644
--- a/server/initializers/migrations/0030-video-category.ts
+++ b/server/initializers/migrations/0030-video-category.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3import { Migration } from '../../models/migrations' 2import { Migration } from '../../models/migrations'
4 3
5function up (utils: { 4function up (utils: {
diff --git a/server/initializers/migrations/0035-video-licence.ts b/server/initializers/migrations/0035-video-licence.ts
index 61d666c5e..b4224d758 100644
--- a/server/initializers/migrations/0035-video-licence.ts
+++ b/server/initializers/migrations/0035-video-licence.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3import { Migration } from '../../models/migrations' 2import { Migration } from '../../models/migrations'
4 3
5function up (utils: { 4function up (utils: {
diff --git a/server/initializers/migrations/0040-video-nsfw.ts b/server/initializers/migrations/0040-video-nsfw.ts
index 44aec8a6c..d5aad3e53 100644
--- a/server/initializers/migrations/0040-video-nsfw.ts
+++ b/server/initializers/migrations/0040-video-nsfw.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3import { Migration } from '../../models/migrations' 2import { Migration } from '../../models/migrations'
4 3
5function up (utils: { 4function up (utils: {
diff --git a/server/initializers/migrations/0045-user-display-nsfw.ts b/server/initializers/migrations/0045-user-display-nsfw.ts
index 07795bd75..5226a25eb 100644
--- a/server/initializers/migrations/0045-user-display-nsfw.ts
+++ b/server/initializers/migrations/0045-user-display-nsfw.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3 2
4function up (utils: { 3function up (utils: {
5 transaction: Sequelize.Transaction 4 transaction: Sequelize.Transaction
diff --git a/server/initializers/migrations/0050-video-language.ts b/server/initializers/migrations/0050-video-language.ts
index 6f90abb44..0cd518272 100644
--- a/server/initializers/migrations/0050-video-language.ts
+++ b/server/initializers/migrations/0050-video-language.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3 2
4function up (utils: { 3function up (utils: {
5 transaction: Sequelize.Transaction 4 transaction: Sequelize.Transaction
diff --git a/server/initializers/migrations/0055-video-uuid.ts b/server/initializers/migrations/0055-video-uuid.ts
index 8a58aebb8..525a69ea5 100644
--- a/server/initializers/migrations/0055-video-uuid.ts
+++ b/server/initializers/migrations/0055-video-uuid.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3import { Migration } from '../../models/migrations' 2import { Migration } from '../../models/migrations'
4 3
5function up (utils: { 4function up (utils: {
diff --git a/server/initializers/migrations/0060-video-file.ts b/server/initializers/migrations/0060-video-file.ts
index 00647e60e..f07fa7780 100644
--- a/server/initializers/migrations/0060-video-file.ts
+++ b/server/initializers/migrations/0060-video-file.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3 2
4function up (utils: { 3function up (utils: {
5 transaction: Sequelize.Transaction 4 transaction: Sequelize.Transaction
diff --git a/server/initializers/migrations/0065-video-file-size.ts b/server/initializers/migrations/0065-video-file-size.ts
index 0bdc675c2..1aeb27f2d 100644
--- a/server/initializers/migrations/0065-video-file-size.ts
+++ b/server/initializers/migrations/0065-video-file-size.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3import { stat } from 'fs-extra' 2import { stat } from 'fs-extra'
4import { VideoModel } from '../../models/video/video' 3import { VideoModel } from '../../models/video/video'
5import { getVideoFilePath } from '@server/lib/video-paths' 4import { getVideoFilePath } from '@server/lib/video-paths'
diff --git a/server/initializers/migrations/0070-user-video-quota.ts b/server/initializers/migrations/0070-user-video-quota.ts
index 1d073f244..3fc4d2970 100644
--- a/server/initializers/migrations/0070-user-video-quota.ts
+++ b/server/initializers/migrations/0070-user-video-quota.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3import { Migration } from '../../models/migrations' 2import { Migration } from '../../models/migrations'
4 3
5function up (utils: { 4function up (utils: {
diff --git a/server/initializers/migrations/0130-user-autoplay-video.ts b/server/initializers/migrations/0130-user-autoplay-video.ts
index d57934588..8f2767266 100644
--- a/server/initializers/migrations/0130-user-autoplay-video.ts
+++ b/server/initializers/migrations/0130-user-autoplay-video.ts
@@ -1,5 +1,4 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3 2
4function up (utils: { 3function up (utils: {
5 transaction: Sequelize.Transaction 4 transaction: Sequelize.Transaction
diff --git a/server/initializers/migrations/0150-avatar-cascade.ts b/server/initializers/migrations/0150-avatar-cascade.ts
index fb3b25773..ecf3467a0 100644
--- a/server/initializers/migrations/0150-avatar-cascade.ts
+++ b/server/initializers/migrations/0150-avatar-cascade.ts
@@ -7,7 +7,8 @@ async function up (utils: {
7}): Promise<void> { 7}): Promise<void> {
8 await utils.queryInterface.removeConstraint('actor', 'actor_avatarId_fkey') 8 await utils.queryInterface.removeConstraint('actor', 'actor_avatarId_fkey')
9 9
10 await utils.queryInterface.addConstraint('actor', [ 'avatarId' ], { 10 await utils.queryInterface.addConstraint('actor', {
11 fields: [ 'avatarId' ],
11 type: 'foreign key', 12 type: 'foreign key',
12 references: { 13 references: {
13 table: 'avatar', 14 table: 'avatar',
diff --git a/server/initializers/migrations/0410-video-playlist-element.ts b/server/initializers/migrations/0410-video-playlist-element.ts
index 1b4692357..be61b932b 100644
--- a/server/initializers/migrations/0410-video-playlist-element.ts
+++ b/server/initializers/migrations/0410-video-playlist-element.ts
@@ -18,7 +18,8 @@ async function up (utils: {
18 18
19 await utils.queryInterface.removeConstraint('videoPlaylistElement', 'videoPlaylistElement_videoId_fkey') 19 await utils.queryInterface.removeConstraint('videoPlaylistElement', 'videoPlaylistElement_videoId_fkey')
20 20
21 await utils.queryInterface.addConstraint('videoPlaylistElement', [ 'videoId' ], { 21 await utils.queryInterface.addConstraint('videoPlaylistElement', {
22 fields: [ 'videoId' ],
22 type: 'foreign key', 23 type: 'foreign key',
23 references: { 24 references: {
24 table: 'video', 25 table: 'video',
diff --git a/server/lib/activitypub/playlist.ts b/server/lib/activitypub/playlist.ts
index 53298e968..8b54a001a 100644
--- a/server/lib/activitypub/playlist.ts
+++ b/server/lib/activitypub/playlist.ts
@@ -99,6 +99,8 @@ async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAc
99 return Promise.resolve() 99 return Promise.resolve()
100 }) 100 })
101 101
102 logger.info('toto', { playlist, id: playlist.id })
103
102 const refreshedPlaylist = await VideoPlaylistModel.loadWithAccountAndChannel(playlist.id, null) 104 const refreshedPlaylist = await VideoPlaylistModel.loadWithAccountAndChannel(playlist.id, null)
103 105
104 if (playlistObject.icon) { 106 if (playlistObject.icon) {
diff --git a/server/lib/activitypub/process/process-dislike.ts b/server/lib/activitypub/process/process-dislike.ts
index 635c8bfcc..089c7b881 100644
--- a/server/lib/activitypub/process/process-dislike.ts
+++ b/server/lib/activitypub/process/process-dislike.ts
@@ -33,7 +33,7 @@ async function processDislike (activity: ActivityCreate | ActivityDislike, byAct
33 const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: dislikeObject }) 33 const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: dislikeObject })
34 34
35 return sequelizeTypescript.transaction(async t => { 35 return sequelizeTypescript.transaction(async t => {
36 const existingRate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byAccount.id, video.id, activity.id) 36 const existingRate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byAccount.id, video.id, activity.id, t)
37 if (existingRate && existingRate.type === 'dislike') return 37 if (existingRate && existingRate.type === 'dislike') return
38 38
39 await video.increment('dislikes', { transaction: t }) 39 await video.increment('dislikes', { transaction: t })
diff --git a/server/lib/activitypub/process/process-like.ts b/server/lib/activitypub/process/process-like.ts
index 6acc097b1..8688b3b47 100644
--- a/server/lib/activitypub/process/process-like.ts
+++ b/server/lib/activitypub/process/process-like.ts
@@ -30,7 +30,7 @@ async function processLikeVideo (byActor: MActorSignature, activity: ActivityLik
30 const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoUrl }) 30 const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoUrl })
31 31
32 return sequelizeTypescript.transaction(async t => { 32 return sequelizeTypescript.transaction(async t => {
33 const existingRate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byAccount.id, video.id, activity.id) 33 const existingRate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byAccount.id, video.id, activity.id, t)
34 if (existingRate && existingRate.type === 'like') return 34 if (existingRate && existingRate.type === 'like') return
35 35
36 if (existingRate && existingRate.type === 'dislike') { 36 if (existingRate && existingRate.type === 'dislike') {
diff --git a/server/lib/activitypub/video-rates.ts b/server/lib/activitypub/video-rates.ts
index 581a2bca1..e246b1313 100644
--- a/server/lib/activitypub/video-rates.ts
+++ b/server/lib/activitypub/video-rates.ts
@@ -13,8 +13,6 @@ import { sendDislike } from './send/send-dislike'
13import { MAccountActor, MActorUrl, MVideo, MVideoAccountLight, MVideoId } from '../../types/models' 13import { MAccountActor, MActorUrl, MVideo, MVideoAccountLight, MVideoId } from '../../types/models'
14 14
15async function createRates (ratesUrl: string[], video: MVideo, rate: VideoRateType) { 15async function createRates (ratesUrl: string[], video: MVideo, rate: VideoRateType) {
16 let rateCounts = 0
17
18 await Bluebird.map(ratesUrl, async rateUrl => { 16 await Bluebird.map(ratesUrl, async rateUrl => {
19 try { 17 try {
20 // Fetch url 18 // Fetch url
@@ -43,21 +41,12 @@ async function createRates (ratesUrl: string[], video: MVideo, rate: VideoRateTy
43 url: body.id 41 url: body.id
44 } 42 }
45 43
46 const created = await AccountVideoRateModel.upsert(entry) 44 // Video "likes"/"dislikes" will be updated by the caller
47 45 await AccountVideoRateModel.upsert(entry)
48 if (created) rateCounts += 1
49 } catch (err) { 46 } catch (err) {
50 logger.warn('Cannot add rate %s.', rateUrl, { err }) 47 logger.warn('Cannot add rate %s.', rateUrl, { err })
51 } 48 }
52 }, { concurrency: CRAWL_REQUEST_CONCURRENCY }) 49 }, { concurrency: CRAWL_REQUEST_CONCURRENCY })
53
54 logger.info('Adding %d %s to video %s.', rateCounts, rate, video.uuid)
55
56 // This is "likes" and "dislikes"
57 if (rateCounts !== 0) {
58 const field = rate === 'like' ? 'likes' : 'dislikes'
59 await video.increment(field, { by: rateCounts })
60 }
61} 50}
62 51
63async function sendVideoRateChange ( 52async function sendVideoRateChange (
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts
index b15d5da1c..cb462e258 100644
--- a/server/lib/activitypub/videos.ts
+++ b/server/lib/activitypub/videos.ts
@@ -352,6 +352,9 @@ async function updateVideoFromAP (options: {
352 video.views = videoData.views 352 video.views = videoData.views
353 video.isLive = videoData.isLive 353 video.isLive = videoData.isLive
354 354
355 // Ensures we update the updated video attribute
356 video.changed('updatedAt', true)
357
355 const videoUpdated = await video.save(sequelizeOptions) as MVideoFullLight 358 const videoUpdated = await video.save(sequelizeOptions) as MVideoFullLight
356 359
357 if (thumbnailModel) await videoUpdated.addAndSaveThumbnail(thumbnailModel, t) 360 if (thumbnailModel) await videoUpdated.addAndSaveThumbnail(thumbnailModel, t)
diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts
index 32f5d29ab..43585c591 100644
--- a/server/lib/client-html.ts
+++ b/server/lib/client-html.ts
@@ -1,29 +1,28 @@
1import * as express from 'express' 1import * as express from 'express'
2import * as Bluebird from 'bluebird' 2import { readFile } from 'fs-extra'
3import { join } from 'path'
4import validator from 'validator'
3import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n' 5import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n'
6import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
7import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos'
8import { escapeHTML, isTestInstance, sha256 } from '../helpers/core-utils'
9import { logger } from '../helpers/logger'
10import { CONFIG } from '../initializers/config'
4import { 11import {
12 ACCEPT_HEADERS,
5 AVATARS_SIZE, 13 AVATARS_SIZE,
6 CUSTOM_HTML_TAG_COMMENTS, 14 CUSTOM_HTML_TAG_COMMENTS,
7 EMBED_SIZE, 15 EMBED_SIZE,
8 PLUGIN_GLOBAL_CSS_PATH,
9 WEBSERVER,
10 FILES_CONTENT_HASH, 16 FILES_CONTENT_HASH,
11 ACCEPT_HEADERS 17 PLUGIN_GLOBAL_CSS_PATH,
18 WEBSERVER
12} from '../initializers/constants' 19} from '../initializers/constants'
13import { join } from 'path'
14import { escapeHTML, isTestInstance, sha256 } from '../helpers/core-utils'
15import { VideoModel } from '../models/video/video'
16import { VideoPlaylistModel } from '../models/video/video-playlist'
17import validator from 'validator'
18import { VideoPrivacy, VideoPlaylistPrivacy } from '../../shared/models/videos'
19import { readFile } from 'fs-extra'
20import { getActivityStreamDuration } from '../models/video/video-format-utils'
21import { AccountModel } from '../models/account/account' 20import { AccountModel } from '../models/account/account'
21import { VideoModel } from '../models/video/video'
22import { VideoChannelModel } from '../models/video/video-channel' 22import { VideoChannelModel } from '../models/video/video-channel'
23import { CONFIG } from '../initializers/config' 23import { getActivityStreamDuration } from '../models/video/video-format-utils'
24import { logger } from '../helpers/logger' 24import { VideoPlaylistModel } from '../models/video/video-playlist'
25import { MAccountActor, MChannelActor } from '../types/models' 25import { MAccountActor, MChannelActor } from '../types/models'
26import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
27 26
28type Tags = { 27type Tags = {
29 ogType: string 28 ogType: string
@@ -218,7 +217,7 @@ class ClientHtml {
218 } 217 }
219 218
220 private static async getAccountOrChannelHTMLPage ( 219 private static async getAccountOrChannelHTMLPage (
221 loader: () => Bluebird<MAccountActor | MChannelActor>, 220 loader: () => Promise<MAccountActor | MChannelActor>,
222 req: express.Request, 221 req: express.Request,
223 res: express.Response 222 res: express.Response
224 ) { 223 ) {
diff --git a/server/lib/job-queue/handlers/activitypub-http-fetcher.ts b/server/lib/job-queue/handlers/activitypub-http-fetcher.ts
index a7c1a556c..e210ac3ef 100644
--- a/server/lib/job-queue/handlers/activitypub-http-fetcher.ts
+++ b/server/lib/job-queue/handlers/activitypub-http-fetcher.ts
@@ -1,19 +1,18 @@
1import * as Bull from 'bull' 1import * as Bull from 'bull'
2import * as Bluebird from 'bluebird' 2import { ActivitypubHttpFetcherPayload, FetchType } from '@shared/models'
3import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
4import { processActivities } from '../../activitypub/process'
5import { addVideoComments } from '../../activitypub/video-comments'
6import { crawlCollectionPage } from '../../activitypub/crawl'
7import { VideoModel } from '../../../models/video/video'
8import { addVideoShares } from '../../activitypub/share'
9import { createRates } from '../../activitypub/video-rates'
10import { createAccountPlaylists } from '../../activitypub/playlist'
11import { AccountModel } from '../../../models/account/account' 4import { AccountModel } from '../../../models/account/account'
12import { AccountVideoRateModel } from '../../../models/account/account-video-rate' 5import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
13import { VideoShareModel } from '../../../models/video/video-share' 6import { VideoModel } from '../../../models/video/video'
14import { VideoCommentModel } from '../../../models/video/video-comment' 7import { VideoCommentModel } from '../../../models/video/video-comment'
8import { VideoShareModel } from '../../../models/video/video-share'
15import { MAccountDefault, MVideoFullLight } from '../../../types/models' 9import { MAccountDefault, MVideoFullLight } from '../../../types/models'
16import { ActivitypubHttpFetcherPayload, FetchType } from '@shared/models' 10import { crawlCollectionPage } from '../../activitypub/crawl'
11import { createAccountPlaylists } from '../../activitypub/playlist'
12import { processActivities } from '../../activitypub/process'
13import { addVideoShares } from '../../activitypub/share'
14import { addVideoComments } from '../../activitypub/video-comments'
15import { createRates } from '../../activitypub/video-rates'
17 16
18async function processActivityPubHttpFetcher (job: Bull.Job) { 17async function processActivityPubHttpFetcher (job: Bull.Job) {
19 logger.info('Processing ActivityPub fetcher in job %d.', job.id) 18 logger.info('Processing ActivityPub fetcher in job %d.', job.id)
@@ -35,7 +34,7 @@ async function processActivityPubHttpFetcher (job: Bull.Job) {
35 'account-playlists': items => createAccountPlaylists(items, account) 34 'account-playlists': items => createAccountPlaylists(items, account)
36 } 35 }
37 36
38 const cleanerType: { [ id in FetchType ]?: (crawlStartDate: Date) => Bluebird<any> } = { 37 const cleanerType: { [ id in FetchType ]?: (crawlStartDate: Date) => Promise<any> } = {
39 'video-likes': crawlStartDate => AccountVideoRateModel.cleanOldRatesOf(video.id, 'like' as 'like', crawlStartDate), 38 'video-likes': crawlStartDate => AccountVideoRateModel.cleanOldRatesOf(video.id, 'like' as 'like', crawlStartDate),
40 'video-dislikes': crawlStartDate => AccountVideoRateModel.cleanOldRatesOf(video.id, 'dislike' as 'dislike', crawlStartDate), 39 'video-dislikes': crawlStartDate => AccountVideoRateModel.cleanOldRatesOf(video.id, 'dislike' as 'dislike', crawlStartDate),
41 'video-shares': crawlStartDate => VideoShareModel.cleanOldSharesOf(video.id, crawlStartDate), 40 'video-shares': crawlStartDate => VideoShareModel.cleanOldSharesOf(video.id, crawlStartDate),
diff --git a/server/lib/video-transcoding-profiles.ts b/server/lib/video-transcoding-profiles.ts
index 3bf83d6a8..338f4de4a 100644
--- a/server/lib/video-transcoding-profiles.ts
+++ b/server/lib/video-transcoding-profiles.ts
@@ -111,7 +111,6 @@ async function buildTargetBitrate (options: {
111 input: string 111 input: string
112 resolution: VideoResolution 112 resolution: VideoResolution
113 fps: number 113 fps: number
114
115}) { 114}) {
116 const { input, resolution, fps } = options 115 const { input, resolution, fps } = options
117 const probe = await ffprobePromise(input) 116 const probe = await ffprobePromise(input)
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index c93895f2f..6b6e6c2df 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -1,8 +1,14 @@
1import * as Bluebird from 'bluebird'
2import * as express from 'express' 1import * as express from 'express'
3import { body, param, query } from 'express-validator' 2import { body, param, query } from 'express-validator'
4import { omit } from 'lodash' 3import { omit } from 'lodash'
4import { Hooks } from '@server/lib/plugins/hooks'
5import { MUserDefault } from '@server/types/models'
6import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
7import { UserRole } from '../../../shared/models/users'
8import { UserRegister } from '../../../shared/models/users/user-register.model'
9import { isActorPreferredUsernameValid } from '../../helpers/custom-validators/activitypub/actor'
5import { isIdOrUUIDValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' 10import { isIdOrUUIDValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
11import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
6import { 12import {
7 isNoInstanceConfigWarningModal, 13 isNoInstanceConfigWarningModal,
8 isNoWelcomeModal, 14 isNoWelcomeModal,
@@ -22,22 +28,15 @@ import {
22 isUserVideoQuotaValid, 28 isUserVideoQuotaValid,
23 isUserVideosHistoryEnabledValid 29 isUserVideosHistoryEnabledValid
24} from '../../helpers/custom-validators/users' 30} from '../../helpers/custom-validators/users'
31import { isVideoChannelNameValid } from '../../helpers/custom-validators/video-channels'
25import { logger } from '../../helpers/logger' 32import { logger } from '../../helpers/logger'
33import { doesVideoExist } from '../../helpers/middlewares'
26import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/signup' 34import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/signup'
35import { isThemeRegistered } from '../../lib/plugins/theme-utils'
27import { Redis } from '../../lib/redis' 36import { Redis } from '../../lib/redis'
28import { UserModel } from '../../models/account/user' 37import { UserModel } from '../../models/account/user'
29import { areValidationErrors } from './utils'
30import { ActorModel } from '../../models/activitypub/actor' 38import { ActorModel } from '../../models/activitypub/actor'
31import { isActorPreferredUsernameValid } from '../../helpers/custom-validators/activitypub/actor' 39import { areValidationErrors } from './utils'
32import { isVideoChannelNameValid } from '../../helpers/custom-validators/video-channels'
33import { UserRegister } from '../../../shared/models/users/user-register.model'
34import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
35import { isThemeRegistered } from '../../lib/plugins/theme-utils'
36import { doesVideoExist } from '../../helpers/middlewares'
37import { UserRole } from '../../../shared/models/users'
38import { MUserDefault } from '@server/types/models'
39import { Hooks } from '@server/lib/plugins/hooks'
40import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
41 40
42const usersListValidator = [ 41const usersListValidator = [
43 query('blocked') 42 query('blocked')
@@ -529,7 +528,7 @@ async function checkUserNameOrEmailDoesNotAlreadyExist (username: string, email:
529 return true 528 return true
530} 529}
531 530
532async function checkUserExist (finder: () => Bluebird<MUserDefault>, res: express.Response, abortResponse = true) { 531async function checkUserExist (finder: () => Promise<MUserDefault>, res: express.Response, abortResponse = true) {
533 const user = await finder() 532 const user = await finder()
534 533
535 if (!user) { 534 if (!user) {
diff --git a/server/models/abuse/abuse-message.ts b/server/models/abuse/abuse-message.ts
index fce20f7a7..7e51b3e07 100644
--- a/server/models/abuse/abuse-message.ts
+++ b/server/models/abuse/abuse-message.ts
@@ -1,10 +1,10 @@
1import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { isAbuseMessageValid } from '@server/helpers/custom-validators/abuses' 2import { isAbuseMessageValid } from '@server/helpers/custom-validators/abuses'
3import { MAbuseMessage, MAbuseMessageFormattable } from '@server/types/models'
3import { AbuseMessage } from '@shared/models' 4import { AbuseMessage } from '@shared/models'
4import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account' 5import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account'
5import { throwIfNotValid, getSort } from '../utils' 6import { getSort, throwIfNotValid } from '../utils'
6import { AbuseModel } from './abuse' 7import { AbuseModel } from './abuse'
7import { MAbuseMessageFormattable, MAbuseMessage } from '@server/types/models'
8 8
9@Table({ 9@Table({
10 tableName: 'abuseMessage', 10 tableName: 'abuseMessage',
@@ -17,7 +17,7 @@ import { MAbuseMessageFormattable, MAbuseMessage } from '@server/types/models'
17 } 17 }
18 ] 18 ]
19}) 19})
20export class AbuseMessageModel extends Model<AbuseMessageModel> { 20export class AbuseMessageModel extends Model {
21 21
22 @AllowNull(false) 22 @AllowNull(false)
23 @Is('AbuseMessage', value => throwIfNotValid(value, isAbuseMessageValid, 'message')) 23 @Is('AbuseMessage', value => throwIfNotValid(value, isAbuseMessageValid, 'message'))
diff --git a/server/models/abuse/abuse.ts b/server/models/abuse/abuse.ts
index 290270fe2..de249d211 100644
--- a/server/models/abuse/abuse.ts
+++ b/server/models/abuse/abuse.ts
@@ -1,4 +1,3 @@
1import * as Bluebird from 'bluebird'
2import { invert } from 'lodash' 1import { invert } from 'lodash'
3import { literal, Op, QueryTypes } from 'sequelize' 2import { literal, Op, QueryTypes } from 'sequelize'
4import { 3import {
@@ -188,7 +187,7 @@ export enum ScopeNames {
188 } 187 }
189 ] 188 ]
190}) 189})
191export class AbuseModel extends Model<AbuseModel> { 190export class AbuseModel extends Model {
192 191
193 @AllowNull(false) 192 @AllowNull(false)
194 @Default(null) 193 @Default(null)
@@ -265,7 +264,7 @@ export class AbuseModel extends Model<AbuseModel> {
265 }) 264 })
266 VideoAbuse: VideoAbuseModel 265 VideoAbuse: VideoAbuseModel
267 266
268 static loadByIdWithReporter (id: number): Bluebird<MAbuseReporter> { 267 static loadByIdWithReporter (id: number): Promise<MAbuseReporter> {
269 const query = { 268 const query = {
270 where: { 269 where: {
271 id 270 id
@@ -281,7 +280,7 @@ export class AbuseModel extends Model<AbuseModel> {
281 return AbuseModel.findOne(query) 280 return AbuseModel.findOne(query)
282 } 281 }
283 282
284 static loadFull (id: number): Bluebird<MAbuseFull> { 283 static loadFull (id: number): Promise<MAbuseFull> {
285 const query = { 284 const query = {
286 where: { 285 where: {
287 id 286 id
diff --git a/server/models/abuse/video-abuse.ts b/server/models/abuse/video-abuse.ts
index d92bcf19f..90aa0695e 100644
--- a/server/models/abuse/video-abuse.ts
+++ b/server/models/abuse/video-abuse.ts
@@ -14,7 +14,7 @@ import { AbuseModel } from './abuse'
14 } 14 }
15 ] 15 ]
16}) 16})
17export class VideoAbuseModel extends Model<VideoAbuseModel> { 17export class VideoAbuseModel extends Model {
18 18
19 @CreatedAt 19 @CreatedAt
20 createdAt: Date 20 createdAt: Date
diff --git a/server/models/abuse/video-comment-abuse.ts b/server/models/abuse/video-comment-abuse.ts
index 8b34009b4..d3fce76a5 100644
--- a/server/models/abuse/video-comment-abuse.ts
+++ b/server/models/abuse/video-comment-abuse.ts
@@ -13,7 +13,7 @@ import { AbuseModel } from './abuse'
13 } 13 }
14 ] 14 ]
15}) 15})
16export class VideoCommentAbuseModel extends Model<VideoCommentAbuseModel> { 16export class VideoCommentAbuseModel extends Model {
17 17
18 @CreatedAt 18 @CreatedAt
19 createdAt: Date 19 createdAt: Date
diff --git a/server/models/account/account-blocklist.ts b/server/models/account/account-blocklist.ts
index 577b7dc19..fe9168ab8 100644
--- a/server/models/account/account-blocklist.ts
+++ b/server/models/account/account-blocklist.ts
@@ -1,4 +1,3 @@
1import * as Bluebird from 'bluebird'
2import { Op } from 'sequelize' 1import { Op } from 'sequelize'
3import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' 2import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
4import { MAccountBlocklist, MAccountBlocklistAccounts, MAccountBlocklistFormattable } from '@server/types/models' 3import { MAccountBlocklist, MAccountBlocklistAccounts, MAccountBlocklistFormattable } from '@server/types/models'
@@ -41,7 +40,7 @@ enum ScopeNames {
41 } 40 }
42 ] 41 ]
43}) 42})
44export class AccountBlocklistModel extends Model<AccountBlocklistModel> { 43export class AccountBlocklistModel extends Model {
45 44
46 @CreatedAt 45 @CreatedAt
47 createdAt: Date 46 createdAt: Date
@@ -102,7 +101,7 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
102 }) 101 })
103 } 102 }
104 103
105 static loadByAccountAndTarget (accountId: number, targetAccountId: number): Bluebird<MAccountBlocklist> { 104 static loadByAccountAndTarget (accountId: number, targetAccountId: number): Promise<MAccountBlocklist> {
106 const query = { 105 const query = {
107 where: { 106 where: {
108 accountId, 107 accountId,
@@ -151,9 +150,9 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
151 }) 150 })
152 } 151 }
153 152
154 static listHandlesBlockedBy (accountIds: number[]): Bluebird<string[]> { 153 static listHandlesBlockedBy (accountIds: number[]): Promise<string[]> {
155 const query = { 154 const query = {
156 attributes: [], 155 attributes: [ 'id' ],
157 where: { 156 where: {
158 accountId: { 157 accountId: {
159 [Op.in]: accountIds 158 [Op.in]: accountIds
diff --git a/server/models/account/account-video-rate.ts b/server/models/account/account-video-rate.ts
index 6955f45ee..d9c529491 100644
--- a/server/models/account/account-video-rate.ts
+++ b/server/models/account/account-video-rate.ts
@@ -1,22 +1,21 @@
1import { values } from 'lodash' 1import { values } from 'lodash'
2import { FindOptions, Op, Transaction } from 'sequelize' 2import { FindOptions, Op, QueryTypes, Transaction } from 'sequelize'
3import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 3import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
4import { VideoRateType } from '../../../shared/models/videos'
5import { CONSTRAINTS_FIELDS, VIDEO_RATE_TYPES } from '../../initializers/constants'
6import { VideoModel } from '../video/video'
7import { AccountModel } from './account'
8import { ActorModel } from '../activitypub/actor'
9import { buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils'
10import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
11import { AccountVideoRate } from '../../../shared'
12import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from '../video/video-channel'
13import * as Bluebird from 'bluebird'
14import { 4import {
15 MAccountVideoRate, 5 MAccountVideoRate,
16 MAccountVideoRateAccountUrl, 6 MAccountVideoRateAccountUrl,
17 MAccountVideoRateAccountVideo, 7 MAccountVideoRateAccountVideo,
18 MAccountVideoRateFormattable 8 MAccountVideoRateFormattable
19} from '@server/types/models/video/video-rate' 9} from '@server/types/models/video/video-rate'
10import { AccountVideoRate } from '../../../shared'
11import { VideoRateType } from '../../../shared/models/videos'
12import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
13import { CONSTRAINTS_FIELDS, VIDEO_RATE_TYPES } from '../../initializers/constants'
14import { ActorModel } from '../activitypub/actor'
15import { buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils'
16import { VideoModel } from '../video/video'
17import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from '../video/video-channel'
18import { AccountModel } from './account'
20 19
21/* 20/*
22 Account rates per video. 21 Account rates per video.
@@ -43,7 +42,7 @@ import {
43 } 42 }
44 ] 43 ]
45}) 44})
46export class AccountVideoRateModel extends Model<AccountVideoRateModel> { 45export class AccountVideoRateModel extends Model {
47 46
48 @AllowNull(false) 47 @AllowNull(false)
49 @Column(DataType.ENUM(...values(VIDEO_RATE_TYPES))) 48 @Column(DataType.ENUM(...values(VIDEO_RATE_TYPES)))
@@ -84,7 +83,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
84 }) 83 })
85 Account: AccountModel 84 Account: AccountModel
86 85
87 static load (accountId: number, videoId: number, transaction?: Transaction): Bluebird<MAccountVideoRate> { 86 static load (accountId: number, videoId: number, transaction?: Transaction): Promise<MAccountVideoRate> {
88 const options: FindOptions = { 87 const options: FindOptions = {
89 where: { 88 where: {
90 accountId, 89 accountId,
@@ -96,7 +95,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
96 return AccountVideoRateModel.findOne(options) 95 return AccountVideoRateModel.findOne(options)
97 } 96 }
98 97
99 static loadByAccountAndVideoOrUrl (accountId: number, videoId: number, url: string, t?: Transaction): Bluebird<MAccountVideoRate> { 98 static loadByAccountAndVideoOrUrl (accountId: number, videoId: number, url: string, t?: Transaction): Promise<MAccountVideoRate> {
100 const options: FindOptions = { 99 const options: FindOptions = {
101 where: { 100 where: {
102 [Op.or]: [ 101 [Op.or]: [
@@ -152,7 +151,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
152 accountName: string, 151 accountName: string,
153 videoId: number | string, 152 videoId: number | string,
154 t?: Transaction 153 t?: Transaction
155 ): Bluebird<MAccountVideoRateAccountVideo> { 154 ): Promise<MAccountVideoRateAccountVideo> {
156 const options: FindOptions = { 155 const options: FindOptions = {
157 where: { 156 where: {
158 videoId, 157 videoId,
@@ -240,17 +239,23 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
240 transaction: t 239 transaction: t
241 } 240 }
242 241
243 const deleted = await AccountVideoRateModel.destroy(query) 242 await AccountVideoRateModel.destroy(query)
244 243
245 const options = { 244 const field = type === 'like'
246 transaction: t, 245 ? 'likes'
247 where: { 246 : 'dislikes'
248 id: videoId 247
249 } 248 const rawQuery = `UPDATE "video" SET "${field}" = ` +
250 } 249 '(' +
250 'SELECT COUNT(id) FROM "accountVideoRate" WHERE "accountVideoRate"."videoId" = "video"."id" AND type = :rateType' +
251 ') ' +
252 'WHERE "video"."id" = :videoId'
251 253
252 if (type === 'like') await VideoModel.increment({ likes: -deleted }, options) 254 return AccountVideoRateModel.sequelize.query(rawQuery, {
253 else if (type === 'dislike') await VideoModel.increment({ dislikes: -deleted }, options) 255 transaction: t,
256 replacements: { videoId, rateType: type },
257 type: QueryTypes.UPDATE
258 })
254 }) 259 })
255 } 260 }
256 261
diff --git a/server/models/account/account.ts b/server/models/account/account.ts
index 8c244d432..c72f9c63d 100644
--- a/server/models/account/account.ts
+++ b/server/models/account/account.ts
@@ -1,5 +1,4 @@
1import * as Bluebird from 'bluebird' 1import { FindOptions, Includeable, IncludeOptions, Op, Transaction, WhereOptions } from 'sequelize'
2import { FindOptions, IncludeOptions, Op, Transaction, WhereOptions } from 'sequelize'
3import { 2import {
4 AllowNull, 3 AllowNull,
5 BeforeDestroy, 4 BeforeDestroy,
@@ -73,28 +72,29 @@ export type SummaryOptions = {
73 required: false 72 required: false
74 } 73 }
75 74
76 const query: FindOptions = { 75 const queryInclude: Includeable[] = [
77 attributes: [ 'id', 'name', 'actorId' ], 76 {
78 include: [ 77 attributes: [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ],
79 { 78 model: ActorModel.unscoped(),
80 attributes: [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ], 79 required: options.actorRequired ?? true,
81 model: ActorModel.unscoped(), 80 where: whereActor,
82 required: options.actorRequired ?? true, 81 include: [
83 where: whereActor, 82 serverInclude,
84 include: [
85 serverInclude,
86 83
87 { 84 {
88 model: AvatarModel.unscoped(), 85 model: AvatarModel.unscoped(),
89 required: false 86 required: false
90 } 87 }
91 ] 88 ]
92 } 89 }
93 ] 90 ]
91
92 const query: FindOptions = {
93 attributes: [ 'id', 'name', 'actorId' ]
94 } 94 }
95 95
96 if (options.withAccountBlockerIds) { 96 if (options.withAccountBlockerIds) {
97 query.include.push({ 97 queryInclude.push({
98 attributes: [ 'id' ], 98 attributes: [ 'id' ],
99 model: AccountBlocklistModel.unscoped(), 99 model: AccountBlocklistModel.unscoped(),
100 as: 'BlockedAccounts', 100 as: 'BlockedAccounts',
@@ -120,6 +120,8 @@ export type SummaryOptions = {
120 ] 120 ]
121 } 121 }
122 122
123 query.include = queryInclude
124
123 return query 125 return query
124 } 126 }
125})) 127}))
@@ -138,7 +140,7 @@ export type SummaryOptions = {
138 } 140 }
139 ] 141 ]
140}) 142})
141export class AccountModel extends Model<AccountModel> { 143export class AccountModel extends Model {
142 144
143 @AllowNull(false) 145 @AllowNull(false)
144 @Column 146 @Column
@@ -244,11 +246,11 @@ export class AccountModel extends Model<AccountModel> {
244 return undefined 246 return undefined
245 } 247 }
246 248
247 static load (id: number, transaction?: Transaction): Bluebird<MAccountDefault> { 249 static load (id: number, transaction?: Transaction): Promise<MAccountDefault> {
248 return AccountModel.findByPk(id, { transaction }) 250 return AccountModel.findByPk(id, { transaction })
249 } 251 }
250 252
251 static loadByNameWithHost (nameWithHost: string): Bluebird<MAccountDefault> { 253 static loadByNameWithHost (nameWithHost: string): Promise<MAccountDefault> {
252 const [ accountName, host ] = nameWithHost.split('@') 254 const [ accountName, host ] = nameWithHost.split('@')
253 255
254 if (!host || host === WEBSERVER.HOST) return AccountModel.loadLocalByName(accountName) 256 if (!host || host === WEBSERVER.HOST) return AccountModel.loadLocalByName(accountName)
@@ -256,7 +258,7 @@ export class AccountModel extends Model<AccountModel> {
256 return AccountModel.loadByNameAndHost(accountName, host) 258 return AccountModel.loadByNameAndHost(accountName, host)
257 } 259 }
258 260
259 static loadLocalByName (name: string): Bluebird<MAccountDefault> { 261 static loadLocalByName (name: string): Promise<MAccountDefault> {
260 const fun = () => { 262 const fun = () => {
261 const query = { 263 const query = {
262 where: { 264 where: {
@@ -296,7 +298,7 @@ export class AccountModel extends Model<AccountModel> {
296 }) 298 })
297 } 299 }
298 300
299 static loadByNameAndHost (name: string, host: string): Bluebird<MAccountDefault> { 301 static loadByNameAndHost (name: string, host: string): Promise<MAccountDefault> {
300 const query = { 302 const query = {
301 include: [ 303 include: [
302 { 304 {
@@ -321,7 +323,7 @@ export class AccountModel extends Model<AccountModel> {
321 return AccountModel.findOne(query) 323 return AccountModel.findOne(query)
322 } 324 }
323 325
324 static loadByUrl (url: string, transaction?: Transaction): Bluebird<MAccountDefault> { 326 static loadByUrl (url: string, transaction?: Transaction): Promise<MAccountDefault> {
325 const query = { 327 const query = {
326 include: [ 328 include: [
327 { 329 {
@@ -354,7 +356,7 @@ export class AccountModel extends Model<AccountModel> {
354 }) 356 })
355 } 357 }
356 358
357 static loadAccountIdFromVideo (videoId: number): Bluebird<MAccount> { 359 static loadAccountIdFromVideo (videoId: number): Promise<MAccount> {
358 const query = { 360 const query = {
359 include: [ 361 include: [
360 { 362 {
@@ -377,7 +379,7 @@ export class AccountModel extends Model<AccountModel> {
377 return AccountModel.findOne(query) 379 return AccountModel.findOne(query)
378 } 380 }
379 381
380 static listLocalsForSitemap (sort: string): Bluebird<MAccountActor[]> { 382 static listLocalsForSitemap (sort: string): Promise<MAccountActor[]> {
381 const query = { 383 const query = {
382 attributes: [ ], 384 attributes: [ ],
383 offset: 0, 385 offset: 0,
diff --git a/server/models/account/user-notification-setting.ts b/server/models/account/user-notification-setting.ts
index acc192d53..ebab8b6d2 100644
--- a/server/models/account/user-notification-setting.ts
+++ b/server/models/account/user-notification-setting.ts
@@ -28,7 +28,7 @@ import { UserModel } from './user'
28 } 28 }
29 ] 29 ]
30}) 30})
31export class UserNotificationSettingModel extends Model<UserNotificationSettingModel> { 31export class UserNotificationSettingModel extends Model {
32 32
33 @AllowNull(false) 33 @AllowNull(false)
34 @Default(null) 34 @Default(null)
diff --git a/server/models/account/user-notification.ts b/server/models/account/user-notification.ts
index 452574dc8..52b792a5b 100644
--- a/server/models/account/user-notification.ts
+++ b/server/models/account/user-notification.ts
@@ -254,7 +254,7 @@ function buildAccountInclude (required: boolean, withActor = false) {
254 } 254 }
255 ] as (ModelIndexesOptions & { where?: WhereOptions })[] 255 ] as (ModelIndexesOptions & { where?: WhereOptions })[]
256}) 256})
257export class UserNotificationModel extends Model<UserNotificationModel> { 257export class UserNotificationModel extends Model {
258 258
259 @AllowNull(false) 259 @AllowNull(false)
260 @Default(null) 260 @Default(null)
diff --git a/server/models/account/user-video-history.ts b/server/models/account/user-video-history.ts
index 76b469fbf..45171fc60 100644
--- a/server/models/account/user-video-history.ts
+++ b/server/models/account/user-video-history.ts
@@ -19,7 +19,7 @@ import { MUserAccountId, MUserId } from '@server/types/models'
19 } 19 }
20 ] 20 ]
21}) 21})
22export class UserVideoHistoryModel extends Model<UserVideoHistoryModel> { 22export class UserVideoHistoryModel extends Model {
23 @CreatedAt 23 @CreatedAt
24 createdAt: Date 24 createdAt: Date
25 25
diff --git a/server/models/account/user.ts b/server/models/account/user.ts
index 10117099b..8e437c3be 100644
--- a/server/models/account/user.ts
+++ b/server/models/account/user.ts
@@ -1,4 +1,3 @@
1import * as Bluebird from 'bluebird'
2import { values } from 'lodash' 1import { values } from 'lodash'
3import { col, FindOptions, fn, literal, Op, QueryTypes, where, WhereOptions } from 'sequelize' 2import { col, FindOptions, fn, literal, Op, QueryTypes, where, WhereOptions } from 'sequelize'
4import { 3import {
@@ -16,11 +15,11 @@ import {
16 HasOne, 15 HasOne,
17 Is, 16 Is,
18 IsEmail, 17 IsEmail,
18 IsUUID,
19 Model, 19 Model,
20 Scopes, 20 Scopes,
21 Table, 21 Table,
22 UpdatedAt, 22 UpdatedAt
23 IsUUID
24} from 'sequelize-typescript' 23} from 'sequelize-typescript'
25import { 24import {
26 MMyUserFormattable, 25 MMyUserFormattable,
@@ -220,7 +219,7 @@ enum ScopeNames {
220 } 219 }
221 ] 220 ]
222}) 221})
223export class UserModel extends Model<UserModel> { 222export class UserModel extends Model {
224 223
225 @AllowNull(true) 224 @AllowNull(true)
226 @Is('UserPassword', value => throwIfNotValid(value, isUserPasswordValid, 'user password', true)) 225 @Is('UserPassword', value => throwIfNotValid(value, isUserPasswordValid, 'user password', true))
@@ -483,7 +482,7 @@ export class UserModel extends Model<UserModel> {
483 }) 482 })
484 } 483 }
485 484
486 static listWithRight (right: UserRight): Bluebird<MUserDefault[]> { 485 static listWithRight (right: UserRight): Promise<MUserDefault[]> {
487 const roles = Object.keys(USER_ROLE_LABELS) 486 const roles = Object.keys(USER_ROLE_LABELS)
488 .map(k => parseInt(k, 10) as UserRole) 487 .map(k => parseInt(k, 10) as UserRole)
489 .filter(role => hasUserRight(role, right)) 488 .filter(role => hasUserRight(role, right))
@@ -499,7 +498,7 @@ export class UserModel extends Model<UserModel> {
499 return UserModel.findAll(query) 498 return UserModel.findAll(query)
500 } 499 }
501 500
502 static listUserSubscribersOf (actorId: number): Bluebird<MUserWithNotificationSetting[]> { 501 static listUserSubscribersOf (actorId: number): Promise<MUserWithNotificationSetting[]> {
503 const query = { 502 const query = {
504 include: [ 503 include: [
505 { 504 {
@@ -538,7 +537,7 @@ export class UserModel extends Model<UserModel> {
538 return UserModel.unscoped().findAll(query) 537 return UserModel.unscoped().findAll(query)
539 } 538 }
540 539
541 static listByUsernames (usernames: string[]): Bluebird<MUserDefault[]> { 540 static listByUsernames (usernames: string[]): Promise<MUserDefault[]> {
542 const query = { 541 const query = {
543 where: { 542 where: {
544 username: usernames 543 username: usernames
@@ -548,11 +547,11 @@ export class UserModel extends Model<UserModel> {
548 return UserModel.findAll(query) 547 return UserModel.findAll(query)
549 } 548 }
550 549
551 static loadById (id: number): Bluebird<MUser> { 550 static loadById (id: number): Promise<MUser> {
552 return UserModel.unscoped().findByPk(id) 551 return UserModel.unscoped().findByPk(id)
553 } 552 }
554 553
555 static loadByIdWithChannels (id: number, withStats = false): Bluebird<MUserDefault> { 554 static loadByIdWithChannels (id: number, withStats = false): Promise<MUserDefault> {
556 const scopes = [ 555 const scopes = [
557 ScopeNames.WITH_VIDEOCHANNELS 556 ScopeNames.WITH_VIDEOCHANNELS
558 ] 557 ]
@@ -562,7 +561,7 @@ export class UserModel extends Model<UserModel> {
562 return UserModel.scope(scopes).findByPk(id) 561 return UserModel.scope(scopes).findByPk(id)
563 } 562 }
564 563
565 static loadByUsername (username: string): Bluebird<MUserDefault> { 564 static loadByUsername (username: string): Promise<MUserDefault> {
566 const query = { 565 const query = {
567 where: { 566 where: {
568 username: { [Op.iLike]: username } 567 username: { [Op.iLike]: username }
@@ -572,7 +571,7 @@ export class UserModel extends Model<UserModel> {
572 return UserModel.findOne(query) 571 return UserModel.findOne(query)
573 } 572 }
574 573
575 static loadForMeAPI (username: string): Bluebird<MUserNotifSettingChannelDefault> { 574 static loadForMeAPI (username: string): Promise<MUserNotifSettingChannelDefault> {
576 const query = { 575 const query = {
577 where: { 576 where: {
578 username: { [Op.iLike]: username } 577 username: { [Op.iLike]: username }
@@ -582,7 +581,7 @@ export class UserModel extends Model<UserModel> {
582 return UserModel.scope(ScopeNames.FOR_ME_API).findOne(query) 581 return UserModel.scope(ScopeNames.FOR_ME_API).findOne(query)
583 } 582 }
584 583
585 static loadByEmail (email: string): Bluebird<MUserDefault> { 584 static loadByEmail (email: string): Promise<MUserDefault> {
586 const query = { 585 const query = {
587 where: { 586 where: {
588 email 587 email
@@ -592,7 +591,7 @@ export class UserModel extends Model<UserModel> {
592 return UserModel.findOne(query) 591 return UserModel.findOne(query)
593 } 592 }
594 593
595 static loadByUsernameOrEmail (username: string, email?: string): Bluebird<MUserDefault> { 594 static loadByUsernameOrEmail (username: string, email?: string): Promise<MUserDefault> {
596 if (!email) email = username 595 if (!email) email = username
597 596
598 const query = { 597 const query = {
@@ -608,7 +607,7 @@ export class UserModel extends Model<UserModel> {
608 return UserModel.findOne(query) 607 return UserModel.findOne(query)
609 } 608 }
610 609
611 static loadByVideoId (videoId: number): Bluebird<MUserDefault> { 610 static loadByVideoId (videoId: number): Promise<MUserDefault> {
612 const query = { 611 const query = {
613 include: [ 612 include: [
614 { 613 {
@@ -639,7 +638,7 @@ export class UserModel extends Model<UserModel> {
639 return UserModel.findOne(query) 638 return UserModel.findOne(query)
640 } 639 }
641 640
642 static loadByVideoImportId (videoImportId: number): Bluebird<MUserDefault> { 641 static loadByVideoImportId (videoImportId: number): Promise<MUserDefault> {
643 const query = { 642 const query = {
644 include: [ 643 include: [
645 { 644 {
@@ -656,7 +655,7 @@ export class UserModel extends Model<UserModel> {
656 return UserModel.findOne(query) 655 return UserModel.findOne(query)
657 } 656 }
658 657
659 static loadByChannelActorId (videoChannelActorId: number): Bluebird<MUserDefault> { 658 static loadByChannelActorId (videoChannelActorId: number): Promise<MUserDefault> {
660 const query = { 659 const query = {
661 include: [ 660 include: [
662 { 661 {
@@ -680,7 +679,7 @@ export class UserModel extends Model<UserModel> {
680 return UserModel.findOne(query) 679 return UserModel.findOne(query)
681 } 680 }
682 681
683 static loadByAccountActorId (accountActorId: number): Bluebird<MUserDefault> { 682 static loadByAccountActorId (accountActorId: number): Promise<MUserDefault> {
684 const query = { 683 const query = {
685 include: [ 684 include: [
686 { 685 {
@@ -697,7 +696,7 @@ export class UserModel extends Model<UserModel> {
697 return UserModel.findOne(query) 696 return UserModel.findOne(query)
698 } 697 }
699 698
700 static loadByLiveId (liveId: number): Bluebird<MUser> { 699 static loadByLiveId (liveId: number): Promise<MUser> {
701 const query = { 700 const query = {
702 include: [ 701 include: [
703 { 702 {
diff --git a/server/models/activitypub/actor-follow.ts b/server/models/activitypub/actor-follow.ts
index 58bc63d34..ce6a4e267 100644
--- a/server/models/activitypub/actor-follow.ts
+++ b/server/models/activitypub/actor-follow.ts
@@ -1,4 +1,3 @@
1import * as Bluebird from 'bluebird'
2import { difference, values } from 'lodash' 1import { difference, values } from 'lodash'
3import { IncludeOptions, Op, QueryTypes, Transaction, WhereOptions } from 'sequelize' 2import { IncludeOptions, Op, QueryTypes, Transaction, WhereOptions } from 'sequelize'
4import { 3import {
@@ -62,7 +61,7 @@ import { ActorModel, unusedActorAttributesForAPI } from './actor'
62 } 61 }
63 ] 62 ]
64}) 63})
65export class ActorFollowModel extends Model<ActorFollowModel> { 64export class ActorFollowModel extends Model {
66 65
67 @AllowNull(false) 66 @AllowNull(false)
68 @Column(DataType.ENUM(...values(FOLLOW_STATES))) 67 @Column(DataType.ENUM(...values(FOLLOW_STATES)))
@@ -176,7 +175,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
176 .then(results => results.length === 1) 175 .then(results => results.length === 1)
177 } 176 }
178 177
179 static loadByActorAndTarget (actorId: number, targetActorId: number, t?: Transaction): Bluebird<MActorFollowActorsDefault> { 178 static loadByActorAndTarget (actorId: number, targetActorId: number, t?: Transaction): Promise<MActorFollowActorsDefault> {
180 const query = { 179 const query = {
181 where: { 180 where: {
182 actorId, 181 actorId,
@@ -205,7 +204,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
205 targetName: string, 204 targetName: string,
206 targetHost: string, 205 targetHost: string,
207 t?: Transaction 206 t?: Transaction
208 ): Bluebird<MActorFollowActorsDefaultSubscription> { 207 ): Promise<MActorFollowActorsDefaultSubscription> {
209 const actorFollowingPartInclude: IncludeOptions = { 208 const actorFollowingPartInclude: IncludeOptions = {
210 model: ActorModel, 209 model: ActorModel,
211 required: true, 210 required: true,
@@ -258,7 +257,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
258 }) 257 })
259 } 258 }
260 259
261 static listSubscribedIn (actorId: number, targets: { name: string, host?: string }[]): Bluebird<MActorFollowFollowingHost[]> { 260 static listSubscribedIn (actorId: number, targets: { name: string, host?: string }[]): Promise<MActorFollowFollowingHost[]> {
262 const whereTab = targets 261 const whereTab = targets
263 .map(t => { 262 .map(t => {
264 if (t.host) { 263 if (t.host) {
@@ -287,7 +286,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
287 }) 286 })
288 287
289 const query = { 288 const query = {
290 attributes: [], 289 attributes: [ 'id' ],
291 where: { 290 where: {
292 [Op.and]: [ 291 [Op.and]: [
293 { 292 {
@@ -671,7 +670,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
671 670
672 selections.push('COUNT(*) AS "total"') 671 selections.push('COUNT(*) AS "total"')
673 672
674 const tasks: Bluebird<any>[] = [] 673 const tasks: Promise<any>[] = []
675 674
676 for (const selection of selections) { 675 for (const selection of selections) {
677 let query = 'SELECT ' + selection + ' FROM "actor" ' + 676 let query = 'SELECT ' + selection + ' FROM "actor" ' +
diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts
index a2fee0012..3b98e8841 100644
--- a/server/models/activitypub/actor.ts
+++ b/server/models/activitypub/actor.ts
@@ -1,5 +1,6 @@
1import { values } from 'lodash' 1import { values } from 'lodash'
2import { extname } from 'path' 2import { extname } from 'path'
3import { literal, Op, Transaction } from 'sequelize'
3import { 4import {
4 AllowNull, 5 AllowNull,
5 BelongsTo, 6 BelongsTo,
@@ -16,6 +17,7 @@ import {
16 Table, 17 Table,
17 UpdatedAt 18 UpdatedAt
18} from 'sequelize-typescript' 19} from 'sequelize-typescript'
20import { ModelCache } from '@server/models/model-cache'
19import { ActivityIconObject, ActivityPubActorType } from '../../../shared/models/activitypub' 21import { ActivityIconObject, ActivityPubActorType } from '../../../shared/models/activitypub'
20import { Avatar } from '../../../shared/models/avatars/avatar.model' 22import { Avatar } from '../../../shared/models/avatars/avatar.model'
21import { activityPubContextify } from '../../helpers/activitypub' 23import { activityPubContextify } from '../../helpers/activitypub'
@@ -28,13 +30,6 @@ import {
28} from '../../helpers/custom-validators/activitypub/actor' 30} from '../../helpers/custom-validators/activitypub/actor'
29import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 31import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
30import { ACTIVITY_PUB, ACTIVITY_PUB_ACTOR_TYPES, CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants' 32import { ACTIVITY_PUB, ACTIVITY_PUB_ACTOR_TYPES, CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants'
31import { AccountModel } from '../account/account'
32import { AvatarModel } from '../avatar/avatar'
33import { ServerModel } from '../server/server'
34import { isOutdated, throwIfNotValid } from '../utils'
35import { VideoChannelModel } from '../video/video-channel'
36import { ActorFollowModel } from './actor-follow'
37import { VideoModel } from '../video/video'
38import { 33import {
39 MActor, 34 MActor,
40 MActorAccountChannelId, 35 MActorAccountChannelId,
@@ -43,12 +38,17 @@ import {
43 MActorFull, 38 MActorFull,
44 MActorHost, 39 MActorHost,
45 MActorServer, 40 MActorServer,
46 MActorSummaryFormattable, MActorUrl, 41 MActorSummaryFormattable,
42 MActorUrl,
47 MActorWithInboxes 43 MActorWithInboxes
48} from '../../types/models' 44} from '../../types/models'
49import * as Bluebird from 'bluebird' 45import { AccountModel } from '../account/account'
50import { Op, Transaction, literal } from 'sequelize' 46import { AvatarModel } from '../avatar/avatar'
51import { ModelCache } from '@server/models/model-cache' 47import { ServerModel } from '../server/server'
48import { isOutdated, throwIfNotValid } from '../utils'
49import { VideoModel } from '../video/video'
50import { VideoChannelModel } from '../video/video-channel'
51import { ActorFollowModel } from './actor-follow'
52 52
53enum ScopeNames { 53enum ScopeNames {
54 FULL = 'FULL' 54 FULL = 'FULL'
@@ -146,7 +146,7 @@ export const unusedActorAttributesForAPI = [
146 } 146 }
147 ] 147 ]
148}) 148})
149export class ActorModel extends Model<ActorModel> { 149export class ActorModel extends Model {
150 150
151 @AllowNull(false) 151 @AllowNull(false)
152 @Column(DataType.ENUM(...values(ACTIVITY_PUB_ACTOR_TYPES))) 152 @Column(DataType.ENUM(...values(ACTIVITY_PUB_ACTOR_TYPES)))
@@ -276,15 +276,15 @@ export class ActorModel extends Model<ActorModel> {
276 }) 276 })
277 VideoChannel: VideoChannelModel 277 VideoChannel: VideoChannelModel
278 278
279 static load (id: number): Bluebird<MActor> { 279 static load (id: number): Promise<MActor> {
280 return ActorModel.unscoped().findByPk(id) 280 return ActorModel.unscoped().findByPk(id)
281 } 281 }
282 282
283 static loadFull (id: number): Bluebird<MActorFull> { 283 static loadFull (id: number): Promise<MActorFull> {
284 return ActorModel.scope(ScopeNames.FULL).findByPk(id) 284 return ActorModel.scope(ScopeNames.FULL).findByPk(id)
285 } 285 }
286 286
287 static loadFromAccountByVideoId (videoId: number, transaction: Transaction): Bluebird<MActor> { 287 static loadFromAccountByVideoId (videoId: number, transaction: Transaction): Promise<MActor> {
288 const query = { 288 const query = {
289 include: [ 289 include: [
290 { 290 {
@@ -328,7 +328,7 @@ export class ActorModel extends Model<ActorModel> {
328 .then(a => !!a) 328 .then(a => !!a)
329 } 329 }
330 330
331 static listByFollowersUrls (followersUrls: string[], transaction?: Transaction): Bluebird<MActorFull[]> { 331 static listByFollowersUrls (followersUrls: string[], transaction?: Transaction): Promise<MActorFull[]> {
332 const query = { 332 const query = {
333 where: { 333 where: {
334 followersUrl: { 334 followersUrl: {
@@ -341,7 +341,7 @@ export class ActorModel extends Model<ActorModel> {
341 return ActorModel.scope(ScopeNames.FULL).findAll(query) 341 return ActorModel.scope(ScopeNames.FULL).findAll(query)
342 } 342 }
343 343
344 static loadLocalByName (preferredUsername: string, transaction?: Transaction): Bluebird<MActorFull> { 344 static loadLocalByName (preferredUsername: string, transaction?: Transaction): Promise<MActorFull> {
345 const fun = () => { 345 const fun = () => {
346 const query = { 346 const query = {
347 where: { 347 where: {
@@ -364,7 +364,7 @@ export class ActorModel extends Model<ActorModel> {
364 }) 364 })
365 } 365 }
366 366
367 static loadLocalUrlByName (preferredUsername: string, transaction?: Transaction): Bluebird<MActorUrl> { 367 static loadLocalUrlByName (preferredUsername: string, transaction?: Transaction): Promise<MActorUrl> {
368 const fun = () => { 368 const fun = () => {
369 const query = { 369 const query = {
370 attributes: [ 'url' ], 370 attributes: [ 'url' ],
@@ -388,7 +388,7 @@ export class ActorModel extends Model<ActorModel> {
388 }) 388 })
389 } 389 }
390 390
391 static loadByNameAndHost (preferredUsername: string, host: string): Bluebird<MActorFull> { 391 static loadByNameAndHost (preferredUsername: string, host: string): Promise<MActorFull> {
392 const query = { 392 const query = {
393 where: { 393 where: {
394 preferredUsername 394 preferredUsername
@@ -407,7 +407,7 @@ export class ActorModel extends Model<ActorModel> {
407 return ActorModel.scope(ScopeNames.FULL).findOne(query) 407 return ActorModel.scope(ScopeNames.FULL).findOne(query)
408 } 408 }
409 409
410 static loadByUrl (url: string, transaction?: Transaction): Bluebird<MActorAccountChannelId> { 410 static loadByUrl (url: string, transaction?: Transaction): Promise<MActorAccountChannelId> {
411 const query = { 411 const query = {
412 where: { 412 where: {
413 url 413 url
@@ -430,7 +430,7 @@ export class ActorModel extends Model<ActorModel> {
430 return ActorModel.unscoped().findOne(query) 430 return ActorModel.unscoped().findOne(query)
431 } 431 }
432 432
433 static loadByUrlAndPopulateAccountAndChannel (url: string, transaction?: Transaction): Bluebird<MActorFull> { 433 static loadByUrlAndPopulateAccountAndChannel (url: string, transaction?: Transaction): Promise<MActorFull> {
434 const query = { 434 const query = {
435 where: { 435 where: {
436 url 436 url
@@ -461,7 +461,7 @@ export class ActorModel extends Model<ActorModel> {
461 }, { where, transaction }) 461 }, { where, transaction })
462 } 462 }
463 463
464 static loadAccountActorByVideoId (videoId: number): Bluebird<MActor> { 464 static loadAccountActorByVideoId (videoId: number): Promise<MActor> {
465 const query = { 465 const query = {
466 include: [ 466 include: [
467 { 467 {
diff --git a/server/models/application/application.ts b/server/models/application/application.ts
index 3bba2c70e..909569de1 100644
--- a/server/models/application/application.ts
+++ b/server/models/application/application.ts
@@ -24,7 +24,7 @@ export const getServerActor = memoizee(async function () {
24 tableName: 'application', 24 tableName: 'application',
25 timestamps: false 25 timestamps: false
26}) 26})
27export class ApplicationModel extends Model<ApplicationModel> { 27export class ApplicationModel extends Model {
28 28
29 @AllowNull(false) 29 @AllowNull(false)
30 @Default(0) 30 @Default(0)
diff --git a/server/models/avatar/avatar.ts b/server/models/avatar/avatar.ts
index d874dec99..0d246a144 100644
--- a/server/models/avatar/avatar.ts
+++ b/server/models/avatar/avatar.ts
@@ -18,7 +18,7 @@ import { MAvatarFormattable } from '@server/types/models'
18 } 18 }
19 ] 19 ]
20}) 20})
21export class AvatarModel extends Model<AvatarModel> { 21export class AvatarModel extends Model {
22 22
23 @AllowNull(false) 23 @AllowNull(false)
24 @Column 24 @Column
diff --git a/server/models/model-cache.ts b/server/models/model-cache.ts
index a87f99aa2..eafb5c13c 100644
--- a/server/models/model-cache.ts
+++ b/server/models/model-cache.ts
@@ -40,7 +40,7 @@ class ModelCache {
40 doCache<T extends Model> (options: { 40 doCache<T extends Model> (options: {
41 cacheType: ModelCacheType 41 cacheType: ModelCacheType
42 key: string 42 key: string
43 fun: () => Bluebird<T> 43 fun: () => Promise<T>
44 whitelist?: () => boolean 44 whitelist?: () => boolean
45 deleteKey?: DeleteKey 45 deleteKey?: DeleteKey
46 }) { 46 }) {
diff --git a/server/models/oauth/oauth-client.ts b/server/models/oauth/oauth-client.ts
index 42c59bb79..8dbc1c2f5 100644
--- a/server/models/oauth/oauth-client.ts
+++ b/server/models/oauth/oauth-client.ts
@@ -14,7 +14,7 @@ import { OAuthTokenModel } from './oauth-token'
14 } 14 }
15 ] 15 ]
16}) 16})
17export class OAuthClientModel extends Model<OAuthClientModel> { 17export class OAuthClientModel extends Model {
18 18
19 @AllowNull(false) 19 @AllowNull(false)
20 @Column 20 @Column
diff --git a/server/models/oauth/oauth-token.ts b/server/models/oauth/oauth-token.ts
index 7f2313dad..6bc6cf27c 100644
--- a/server/models/oauth/oauth-token.ts
+++ b/server/models/oauth/oauth-token.ts
@@ -1,3 +1,4 @@
1import { Transaction } from 'sequelize'
1import { 2import {
2 AfterDestroy, 3 AfterDestroy,
3 AfterUpdate, 4 AfterUpdate,
@@ -11,15 +12,13 @@ import {
11 Table, 12 Table,
12 UpdatedAt 13 UpdatedAt
13} from 'sequelize-typescript' 14} from 'sequelize-typescript'
15import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token'
14import { logger } from '../../helpers/logger' 16import { logger } from '../../helpers/logger'
15import { UserModel } from '../account/user' 17import { clearCacheByToken } from '../../lib/oauth-model'
16import { OAuthClientModel } from './oauth-client'
17import { Transaction } from 'sequelize'
18import { AccountModel } from '../account/account' 18import { AccountModel } from '../account/account'
19import { UserModel } from '../account/user'
19import { ActorModel } from '../activitypub/actor' 20import { ActorModel } from '../activitypub/actor'
20import { clearCacheByToken } from '../../lib/oauth-model' 21import { OAuthClientModel } from './oauth-client'
21import * as Bluebird from 'bluebird'
22import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token'
23 22
24export type OAuthTokenInfo = { 23export type OAuthTokenInfo = {
25 refreshToken: string 24 refreshToken: string
@@ -80,7 +79,7 @@ enum ScopeNames {
80 } 79 }
81 ] 80 ]
82}) 81})
83export class OAuthTokenModel extends Model<OAuthTokenModel> { 82export class OAuthTokenModel extends Model {
84 83
85 @AllowNull(false) 84 @AllowNull(false)
86 @Column 85 @Column
@@ -174,7 +173,7 @@ export class OAuthTokenModel extends Model<OAuthTokenModel> {
174 }) 173 })
175 } 174 }
176 175
177 static getByTokenAndPopulateUser (bearerToken: string): Bluebird<MOAuthTokenUser> { 176 static getByTokenAndPopulateUser (bearerToken: string): Promise<MOAuthTokenUser> {
178 const query = { 177 const query = {
179 where: { 178 where: {
180 accessToken: bearerToken 179 accessToken: bearerToken
@@ -190,7 +189,7 @@ export class OAuthTokenModel extends Model<OAuthTokenModel> {
190 }) 189 })
191 } 190 }
192 191
193 static getByRefreshTokenAndPopulateUser (refreshToken: string): Bluebird<MOAuthTokenUser> { 192 static getByRefreshTokenAndPopulateUser (refreshToken: string): Promise<MOAuthTokenUser> {
194 const query = { 193 const query = {
195 where: { 194 where: {
196 refreshToken 195 refreshToken
diff --git a/server/models/redundancy/video-redundancy.ts b/server/models/redundancy/video-redundancy.ts
index 1b967996c..fa96a1e39 100644
--- a/server/models/redundancy/video-redundancy.ts
+++ b/server/models/redundancy/video-redundancy.ts
@@ -1,3 +1,5 @@
1import { sample } from 'lodash'
2import { col, FindOptions, fn, literal, Op, Transaction, WhereOptions } from 'sequelize'
1import { 3import {
2 AllowNull, 4 AllowNull,
3 BeforeDestroy, 5 BeforeDestroy,
@@ -12,23 +14,7 @@ import {
12 Table, 14 Table,
13 UpdatedAt 15 UpdatedAt
14} from 'sequelize-typescript' 16} from 'sequelize-typescript'
15import { ActorModel } from '../activitypub/actor' 17import { getServerActor } from '@server/models/application/application'
16import { getSort, getVideoSort, parseAggregateResult, throwIfNotValid } from '../utils'
17import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc'
18import { CONSTRAINTS_FIELDS, MIMETYPES } from '../../initializers/constants'
19import { VideoFileModel } from '../video/video-file'
20import { VideoModel } from '../video/video'
21import { VideoRedundancyStrategy, VideoRedundancyStrategyWithManual } from '../../../shared/models/redundancy'
22import { logger } from '../../helpers/logger'
23import { CacheFileObject, VideoPrivacy } from '../../../shared'
24import { VideoChannelModel } from '../video/video-channel'
25import { ServerModel } from '../server/server'
26import { sample } from 'lodash'
27import { isTestInstance } from '../../helpers/core-utils'
28import * as Bluebird from 'bluebird'
29import { col, FindOptions, fn, literal, Op, Transaction, WhereOptions } from 'sequelize'
30import { VideoStreamingPlaylistModel } from '../video/video-streaming-playlist'
31import { CONFIG } from '../../initializers/config'
32import { MVideoForRedundancyAPI, MVideoRedundancy, MVideoRedundancyAP, MVideoRedundancyVideo } from '@server/types/models' 18import { MVideoForRedundancyAPI, MVideoRedundancy, MVideoRedundancyAP, MVideoRedundancyVideo } from '@server/types/models'
33import { VideoRedundanciesTarget } from '@shared/models/redundancy/video-redundancies-filters.model' 19import { VideoRedundanciesTarget } from '@shared/models/redundancy/video-redundancies-filters.model'
34import { 20import {
@@ -36,7 +22,20 @@ import {
36 StreamingPlaylistRedundancyInformation, 22 StreamingPlaylistRedundancyInformation,
37 VideoRedundancy 23 VideoRedundancy
38} from '@shared/models/redundancy/video-redundancy.model' 24} from '@shared/models/redundancy/video-redundancy.model'
39import { getServerActor } from '@server/models/application/application' 25import { CacheFileObject, VideoPrivacy } from '../../../shared'
26import { VideoRedundancyStrategy, VideoRedundancyStrategyWithManual } from '../../../shared/models/redundancy'
27import { isTestInstance } from '../../helpers/core-utils'
28import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc'
29import { logger } from '../../helpers/logger'
30import { CONFIG } from '../../initializers/config'
31import { CONSTRAINTS_FIELDS, MIMETYPES } from '../../initializers/constants'
32import { ActorModel } from '../activitypub/actor'
33import { ServerModel } from '../server/server'
34import { getSort, getVideoSort, parseAggregateResult, throwIfNotValid } from '../utils'
35import { VideoModel } from '../video/video'
36import { VideoChannelModel } from '../video/video-channel'
37import { VideoFileModel } from '../video/video-file'
38import { VideoStreamingPlaylistModel } from '../video/video-streaming-playlist'
40 39
41export enum ScopeNames { 40export enum ScopeNames {
42 WITH_VIDEO = 'WITH_VIDEO' 41 WITH_VIDEO = 'WITH_VIDEO'
@@ -84,7 +83,7 @@ export enum ScopeNames {
84 } 83 }
85 ] 84 ]
86}) 85})
87export class VideoRedundancyModel extends Model<VideoRedundancyModel> { 86export class VideoRedundancyModel extends Model {
88 87
89 @CreatedAt 88 @CreatedAt
90 createdAt: Date 89 createdAt: Date
@@ -199,7 +198,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
199 return VideoRedundancyModel.scope(ScopeNames.WITH_VIDEO).findOne(query) 198 return VideoRedundancyModel.scope(ScopeNames.WITH_VIDEO).findOne(query)
200 } 199 }
201 200
202 static loadByIdWithVideo (id: number, transaction?: Transaction): Bluebird<MVideoRedundancyVideo> { 201 static loadByIdWithVideo (id: number, transaction?: Transaction): Promise<MVideoRedundancyVideo> {
203 const query = { 202 const query = {
204 where: { id }, 203 where: { id },
205 transaction 204 transaction
@@ -208,7 +207,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
208 return VideoRedundancyModel.scope(ScopeNames.WITH_VIDEO).findOne(query) 207 return VideoRedundancyModel.scope(ScopeNames.WITH_VIDEO).findOne(query)
209 } 208 }
210 209
211 static loadByUrl (url: string, transaction?: Transaction): Bluebird<MVideoRedundancy> { 210 static loadByUrl (url: string, transaction?: Transaction): Promise<MVideoRedundancy> {
212 const query = { 211 const query = {
213 where: { 212 where: {
214 url 213 url
@@ -251,7 +250,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
251 .then(r => !!r) 250 .then(r => !!r)
252 } 251 }
253 252
254 static async getVideoSample (p: Bluebird<VideoModel[]>) { 253 static async getVideoSample (p: Promise<VideoModel[]>) {
255 const rows = await p 254 const rows = await p
256 if (rows.length === 0) return undefined 255 if (rows.length === 0) return undefined
257 256
@@ -696,7 +695,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
696 695
697 const notIn = literal( 696 const notIn = literal(
698 '(' + 697 '(' +
699 `SELECT "videoFileId" FROM "videoRedundancy" WHERE "actorId" = ${actor.id} AND "videoFileId" IS NOT NULL` + 698 `SELECT "videoFileId" FROM "videoRedundancy" WHERE "actorId" = ${actor.id} AND "videoFileId" IS NOT NULL` +
700 ')' 699 ')'
701 ) 700 )
702 701
diff --git a/server/models/server/plugin.ts b/server/models/server/plugin.ts
index 95fb386b5..82387af6a 100644
--- a/server/models/server/plugin.ts
+++ b/server/models/server/plugin.ts
@@ -1,4 +1,3 @@
1import * as Bluebird from 'bluebird'
2import { FindAndCountOptions, json, QueryTypes } from 'sequelize' 1import { FindAndCountOptions, json, QueryTypes } from 'sequelize'
3import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
4import { MPlugin, MPluginFormattable } from '@server/types/models' 3import { MPlugin, MPluginFormattable } from '@server/types/models'
@@ -29,7 +28,7 @@ import { getSort, throwIfNotValid } from '../utils'
29 } 28 }
30 ] 29 ]
31}) 30})
32export class PluginModel extends Model<PluginModel> { 31export class PluginModel extends Model {
33 32
34 @AllowNull(false) 33 @AllowNull(false)
35 @Is('PluginName', value => throwIfNotValid(value, isPluginNameValid, 'name')) 34 @Is('PluginName', value => throwIfNotValid(value, isPluginNameValid, 'name'))
@@ -87,7 +86,7 @@ export class PluginModel extends Model<PluginModel> {
87 @UpdatedAt 86 @UpdatedAt
88 updatedAt: Date 87 updatedAt: Date
89 88
90 static listEnabledPluginsAndThemes (): Bluebird<MPlugin[]> { 89 static listEnabledPluginsAndThemes (): Promise<MPlugin[]> {
91 const query = { 90 const query = {
92 where: { 91 where: {
93 enabled: true, 92 enabled: true,
@@ -98,7 +97,7 @@ export class PluginModel extends Model<PluginModel> {
98 return PluginModel.findAll(query) 97 return PluginModel.findAll(query)
99 } 98 }
100 99
101 static loadByNpmName (npmName: string): Bluebird<MPlugin> { 100 static loadByNpmName (npmName: string): Promise<MPlugin> {
102 const name = this.normalizePluginName(npmName) 101 const name = this.normalizePluginName(npmName)
103 const type = this.getTypeFromNpmName(npmName) 102 const type = this.getTypeFromNpmName(npmName)
104 103
@@ -252,7 +251,7 @@ export class PluginModel extends Model<PluginModel> {
252 }) 251 })
253 } 252 }
254 253
255 static listInstalled (): Bluebird<MPlugin[]> { 254 static listInstalled (): Promise<MPlugin[]> {
256 const query = { 255 const query = {
257 where: { 256 where: {
258 uninstalled: false 257 uninstalled: false
diff --git a/server/models/server/server-blocklist.ts b/server/models/server/server-blocklist.ts
index 68cd72ee7..4dc236537 100644
--- a/server/models/server/server-blocklist.ts
+++ b/server/models/server/server-blocklist.ts
@@ -1,4 +1,3 @@
1import * as Bluebird from 'bluebird'
2import { Op } from 'sequelize' 1import { Op } from 'sequelize'
3import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' 2import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
4import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/types/models' 3import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/types/models'
@@ -43,7 +42,7 @@ enum ScopeNames {
43 } 42 }
44 ] 43 ]
45}) 44})
46export class ServerBlocklistModel extends Model<ServerBlocklistModel> { 45export class ServerBlocklistModel extends Model {
47 46
48 @CreatedAt 47 @CreatedAt
49 createdAt: Date 48 createdAt: Date
@@ -101,7 +100,7 @@ export class ServerBlocklistModel extends Model<ServerBlocklistModel> {
101 }) 100 })
102 } 101 }
103 102
104 static loadByAccountAndHost (accountId: number, host: string): Bluebird<MServerBlocklist> { 103 static loadByAccountAndHost (accountId: number, host: string): Promise<MServerBlocklist> {
105 const query = { 104 const query = {
106 where: { 105 where: {
107 accountId 106 accountId
@@ -120,7 +119,7 @@ export class ServerBlocklistModel extends Model<ServerBlocklistModel> {
120 return ServerBlocklistModel.findOne(query) 119 return ServerBlocklistModel.findOne(query)
121 } 120 }
122 121
123 static listHostsBlockedBy (accountIds: number[]): Bluebird<string[]> { 122 static listHostsBlockedBy (accountIds: number[]): Promise<string[]> {
124 const query = { 123 const query = {
125 attributes: [ ], 124 attributes: [ ],
126 where: { 125 where: {
diff --git a/server/models/server/server.ts b/server/models/server/server.ts
index 771200797..0e58beeaf 100644
--- a/server/models/server/server.ts
+++ b/server/models/server/server.ts
@@ -1,10 +1,9 @@
1import { AllowNull, Column, CreatedAt, Default, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { AllowNull, Column, CreatedAt, Default, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { MServer, MServerFormattable } from '@server/types/models/server'
2import { isHostValid } from '../../helpers/custom-validators/servers' 3import { isHostValid } from '../../helpers/custom-validators/servers'
3import { ActorModel } from '../activitypub/actor' 4import { ActorModel } from '../activitypub/actor'
4import { throwIfNotValid } from '../utils' 5import { throwIfNotValid } from '../utils'
5import { ServerBlocklistModel } from './server-blocklist' 6import { ServerBlocklistModel } from './server-blocklist'
6import * as Bluebird from 'bluebird'
7import { MServer, MServerFormattable } from '@server/types/models/server'
8 7
9@Table({ 8@Table({
10 tableName: 'server', 9 tableName: 'server',
@@ -15,7 +14,7 @@ import { MServer, MServerFormattable } from '@server/types/models/server'
15 } 14 }
16 ] 15 ]
17}) 16})
18export class ServerModel extends Model<ServerModel> { 17export class ServerModel extends Model {
19 18
20 @AllowNull(false) 19 @AllowNull(false)
21 @Is('Host', value => throwIfNotValid(value, isHostValid, 'valid host')) 20 @Is('Host', value => throwIfNotValid(value, isHostValid, 'valid host'))
@@ -51,7 +50,7 @@ export class ServerModel extends Model<ServerModel> {
51 }) 50 })
52 BlockedByAccounts: ServerBlocklistModel[] 51 BlockedByAccounts: ServerBlocklistModel[]
53 52
54 static load (id: number): Bluebird<MServer> { 53 static load (id: number): Promise<MServer> {
55 const query = { 54 const query = {
56 where: { 55 where: {
57 id 56 id
@@ -61,7 +60,7 @@ export class ServerModel extends Model<ServerModel> {
61 return ServerModel.findOne(query) 60 return ServerModel.findOne(query)
62 } 61 }
63 62
64 static loadByHost (host: string): Bluebird<MServer> { 63 static loadByHost (host: string): Promise<MServer> {
65 const query = { 64 const query = {
66 where: { 65 where: {
67 host 66 host
diff --git a/server/models/utils.ts b/server/models/utils.ts
index a06d57831..143c1a23c 100644
--- a/server/models/utils.ts
+++ b/server/models/utils.ts
@@ -113,7 +113,8 @@ function throwIfNotValid (value: any, validator: (value: any) => boolean, fieldN
113function buildTrigramSearchIndex (indexName: string, attribute: string) { 113function buildTrigramSearchIndex (indexName: string, attribute: string) {
114 return { 114 return {
115 name: indexName, 115 name: indexName,
116 fields: [ Sequelize.literal('lower(immutable_unaccent(' + attribute + '))') as any ], 116 // FIXME: gin_trgm_ops is not taken into account in Sequelize 6, so adding it ourselves in the literal function
117 fields: [ Sequelize.literal('lower(immutable_unaccent(' + attribute + ')) gin_trgm_ops') as any ],
117 using: 'gin', 118 using: 'gin',
118 operator: 'gin_trgm_ops' 119 operator: 'gin_trgm_ops'
119 } 120 }
diff --git a/server/models/video/schedule-video-update.ts b/server/models/video/schedule-video-update.ts
index 1ce6bbfe5..22b08e91a 100644
--- a/server/models/video/schedule-video-update.ts
+++ b/server/models/video/schedule-video-update.ts
@@ -16,7 +16,7 @@ import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdateVideoAll } from '@
16 } 16 }
17 ] 17 ]
18}) 18})
19export class ScheduleVideoUpdateModel extends Model<ScheduleVideoUpdateModel> { 19export class ScheduleVideoUpdateModel extends Model {
20 20
21 @AllowNull(false) 21 @AllowNull(false)
22 @Default(null) 22 @Default(null)
diff --git a/server/models/video/tag.ts b/server/models/video/tag.ts
index adbc4fb7d..d04205703 100644
--- a/server/models/video/tag.ts
+++ b/server/models/video/tag.ts
@@ -1,12 +1,11 @@
1import * as Bluebird from 'bluebird' 1import { col, fn, QueryTypes, Transaction } from 'sequelize'
2import { fn, QueryTypes, Transaction, col } from 'sequelize'
3import { 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'
4import { VideoPrivacy, VideoState } from '../../../shared/models/videos'
4import { isVideoTagValid } from '../../helpers/custom-validators/videos' 5import { isVideoTagValid } from '../../helpers/custom-validators/videos'
5import { throwIfNotValid } from '../utils' 6import { throwIfNotValid } from '../utils'
6import { VideoModel } from './video' 7import { VideoModel } from './video'
7import { VideoTagModel } from './video-tag' 8import { VideoTagModel } from './video-tag'
8import { VideoPrivacy, VideoState } from '../../../shared/models/videos'
9import { MTag } from '@server/types/models'
10 9
11@Table({ 10@Table({
12 tableName: 'tag', 11 tableName: 'tag',
@@ -22,7 +21,7 @@ import { MTag } from '@server/types/models'
22 } 21 }
23 ] 22 ]
24}) 23})
25export class TagModel extends Model<TagModel> { 24export class TagModel extends Model {
26 25
27 @AllowNull(false) 26 @AllowNull(false)
28 @Is('VideoTag', value => throwIfNotValid(value, isVideoTagValid, 'tag')) 27 @Is('VideoTag', value => throwIfNotValid(value, isVideoTagValid, 'tag'))
@@ -45,7 +44,7 @@ export class TagModel extends Model<TagModel> {
45 static findOrCreateTags (tags: string[], transaction: Transaction): Promise<MTag[]> { 44 static findOrCreateTags (tags: string[], transaction: Transaction): Promise<MTag[]> {
46 if (tags === null) return Promise.resolve([]) 45 if (tags === null) return Promise.resolve([])
47 46
48 const tasks: Bluebird<MTag>[] = [] 47 const tasks: Promise<MTag>[] = []
49 tags.forEach(tag => { 48 tags.forEach(tag => {
50 const query = { 49 const query = {
51 where: { 50 where: {
@@ -66,7 +65,7 @@ export class TagModel extends Model<TagModel> {
66 } 65 }
67 66
68 // threshold corresponds to how many video the field should have to be returned 67 // threshold corresponds to how many video the field should have to be returned
69 static getRandomSamples (threshold: number, count: number): Bluebird<string[]> { 68 static getRandomSamples (threshold: number, count: number): Promise<string[]> {
70 const query = 'SELECT tag.name FROM tag ' + 69 const query = 'SELECT tag.name FROM tag ' +
71 'INNER JOIN "videoTag" ON "videoTag"."tagId" = tag.id ' + 70 'INNER JOIN "videoTag" ON "videoTag"."tagId" = tag.id ' +
72 'INNER JOIN video ON video.id = "videoTag"."videoId" ' + 71 'INNER JOIN video ON video.id = "videoTag"."videoId" ' +
diff --git a/server/models/video/thumbnail.ts b/server/models/video/thumbnail.ts
index 20c1e5858..6878a3155 100644
--- a/server/models/video/thumbnail.ts
+++ b/server/models/video/thumbnail.ts
@@ -34,7 +34,7 @@ import { buildRemoteVideoBaseUrl } from '@server/helpers/activitypub'
34 } 34 }
35 ] 35 ]
36}) 36})
37export class ThumbnailModel extends Model<ThumbnailModel> { 37export class ThumbnailModel extends Model {
38 38
39 @AllowNull(false) 39 @AllowNull(false)
40 @Column 40 @Column
diff --git a/server/models/video/video-blacklist.ts b/server/models/video/video-blacklist.ts
index 36d2a30fa..aa18896da 100644
--- a/server/models/video/video-blacklist.ts
+++ b/server/models/video/video-blacklist.ts
@@ -1,14 +1,13 @@
1import { FindOptions } from 'sequelize'
1import { 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'
2import { getBlacklistSort, SortType, throwIfNotValid, searchAttribute } from '../utils' 3import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models'
3import { VideoModel } from './video'
4import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
5import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist'
6import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos' 4import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos'
5import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist'
7import { CONSTRAINTS_FIELDS } from '../../initializers/constants' 6import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
8import { FindOptions } from 'sequelize' 7import { getBlacklistSort, searchAttribute, SortType, throwIfNotValid } from '../utils'
9import { ThumbnailModel } from './thumbnail' 8import { ThumbnailModel } from './thumbnail'
10import * as Bluebird from 'bluebird' 9import { VideoModel } from './video'
11import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models' 10import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
12 11
13@Table({ 12@Table({
14 tableName: 'videoBlacklist', 13 tableName: 'videoBlacklist',
@@ -19,7 +18,7 @@ import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/model
19 } 18 }
20 ] 19 ]
21}) 20})
22export class VideoBlacklistModel extends Model<VideoBlacklistModel> { 21export class VideoBlacklistModel extends Model {
23 22
24 @AllowNull(true) 23 @AllowNull(true)
25 @Is('VideoBlacklistReason', value => throwIfNotValid(value, isVideoBlacklistReasonValid, 'reason', true)) 24 @Is('VideoBlacklistReason', value => throwIfNotValid(value, isVideoBlacklistReasonValid, 'reason', true))
@@ -109,7 +108,7 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
109 }) 108 })
110 } 109 }
111 110
112 static loadByVideoId (id: number): Bluebird<MVideoBlacklist> { 111 static loadByVideoId (id: number): Promise<MVideoBlacklist> {
113 const query = { 112 const query = {
114 where: { 113 where: {
115 videoId: id 114 videoId: id
diff --git a/server/models/video/video-caption.ts b/server/models/video/video-caption.ts
index b68a6e99f..e8e883dd0 100644
--- a/server/models/video/video-caption.ts
+++ b/server/models/video/video-caption.ts
@@ -1,3 +1,5 @@
1import { remove } from 'fs-extra'
2import { join } from 'path'
1import { OrderItem, Transaction } from 'sequelize' 3import { OrderItem, Transaction } from 'sequelize'
2import { 4import {
3 AllowNull, 5 AllowNull,
@@ -13,18 +15,15 @@ import {
13 Table, 15 Table,
14 UpdatedAt 16 UpdatedAt
15} from 'sequelize-typescript' 17} from 'sequelize-typescript'
16import { buildWhereIdOrUUID, throwIfNotValid } from '../utils' 18import { buildRemoteVideoBaseUrl } from '@server/helpers/activitypub'
17import { VideoModel } from './video' 19import { MVideoAccountLight, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models'
18import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions'
19import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model' 20import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model'
20import { CONSTRAINTS_FIELDS, LAZY_STATIC_PATHS, VIDEO_LANGUAGES, WEBSERVER } from '../../initializers/constants' 21import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions'
21import { join } from 'path'
22import { logger } from '../../helpers/logger' 22import { logger } from '../../helpers/logger'
23import { remove } from 'fs-extra'
24import { CONFIG } from '../../initializers/config' 23import { CONFIG } from '../../initializers/config'
25import * as Bluebird from 'bluebird' 24import { CONSTRAINTS_FIELDS, LAZY_STATIC_PATHS, VIDEO_LANGUAGES, WEBSERVER } from '../../initializers/constants'
26import { MVideoAccountLight, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models' 25import { buildWhereIdOrUUID, throwIfNotValid } from '../utils'
27import { buildRemoteVideoBaseUrl } from '@server/helpers/activitypub' 26import { VideoModel } from './video'
28 27
29export enum ScopeNames { 28export enum ScopeNames {
30 WITH_VIDEO_UUID_AND_REMOTE = 'WITH_VIDEO_UUID_AND_REMOTE' 29 WITH_VIDEO_UUID_AND_REMOTE = 'WITH_VIDEO_UUID_AND_REMOTE'
@@ -54,7 +53,7 @@ export enum ScopeNames {
54 } 53 }
55 ] 54 ]
56}) 55})
57export class VideoCaptionModel extends Model<VideoCaptionModel> { 56export class VideoCaptionModel extends Model {
58 @CreatedAt 57 @CreatedAt
59 createdAt: Date 58 createdAt: Date
60 59
@@ -101,7 +100,7 @@ export class VideoCaptionModel extends Model<VideoCaptionModel> {
101 return undefined 100 return undefined
102 } 101 }
103 102
104 static loadByVideoIdAndLanguage (videoId: string | number, language: string): Bluebird<MVideoCaptionVideo> { 103 static loadByVideoIdAndLanguage (videoId: string | number, language: string): Promise<MVideoCaptionVideo> {
105 const videoInclude = { 104 const videoInclude = {
106 model: VideoModel.unscoped(), 105 model: VideoModel.unscoped(),
107 attributes: [ 'id', 'remote', 'uuid' ], 106 attributes: [ 'id', 'remote', 'uuid' ],
@@ -131,7 +130,7 @@ export class VideoCaptionModel extends Model<VideoCaptionModel> {
131 .then(([ caption ]) => caption) 130 .then(([ caption ]) => caption)
132 } 131 }
133 132
134 static listVideoCaptions (videoId: number): Bluebird<MVideoCaptionVideo[]> { 133 static listVideoCaptions (videoId: number): Promise<MVideoCaptionVideo[]> {
135 const query = { 134 const query = {
136 order: [ [ 'language', 'ASC' ] ] as OrderItem[], 135 order: [ [ 'language', 'ASC' ] ] as OrderItem[],
137 where: { 136 where: {
diff --git a/server/models/video/video-change-ownership.ts b/server/models/video/video-change-ownership.ts
index ac0ab7e8b..298e8bfe2 100644
--- a/server/models/video/video-change-ownership.ts
+++ b/server/models/video/video-change-ownership.ts
@@ -1,10 +1,9 @@
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 { AccountModel } from '../account/account' 2import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership'
3import { ScopeNames as VideoScopeNames, VideoModel } from './video'
4import { VideoChangeOwnership, VideoChangeOwnershipStatus } from '../../../shared/models/videos' 3import { VideoChangeOwnership, VideoChangeOwnershipStatus } from '../../../shared/models/videos'
4import { AccountModel } from '../account/account'
5import { getSort } from '../utils' 5import { getSort } from '../utils'
6import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership' 6import { ScopeNames as VideoScopeNames, VideoModel } from './video'
7import * as Bluebird from 'bluebird'
8 7
9enum ScopeNames { 8enum ScopeNames {
10 WITH_ACCOUNTS = 'WITH_ACCOUNTS', 9 WITH_ACCOUNTS = 'WITH_ACCOUNTS',
@@ -54,7 +53,7 @@ enum ScopeNames {
54 ] 53 ]
55 } 54 }
56})) 55}))
57export class VideoChangeOwnershipModel extends Model<VideoChangeOwnershipModel> { 56export class VideoChangeOwnershipModel extends Model {
58 @CreatedAt 57 @CreatedAt
59 createdAt: Date 58 createdAt: Date
60 59
@@ -119,7 +118,7 @@ export class VideoChangeOwnershipModel extends Model<VideoChangeOwnershipModel>
119 ]).then(([ count, rows ]) => ({ total: count, data: rows })) 118 ]).then(([ count, rows ]) => ({ total: count, data: rows }))
120 } 119 }
121 120
122 static load (id: number): Bluebird<MVideoChangeOwnershipFull> { 121 static load (id: number): Promise<MVideoChangeOwnershipFull> {
123 return VideoChangeOwnershipModel.scope([ ScopeNames.WITH_ACCOUNTS, ScopeNames.WITH_VIDEO ]) 122 return VideoChangeOwnershipModel.scope([ ScopeNames.WITH_ACCOUNTS, ScopeNames.WITH_VIDEO ])
124 .findByPk(id) 123 .findByPk(id)
125 } 124 }
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts
index 0c8aef18f..178878c55 100644
--- a/server/models/video/video-channel.ts
+++ b/server/models/video/video-channel.ts
@@ -1,5 +1,4 @@
1import * as Bluebird from 'bluebird' 1import { FindOptions, Includeable, literal, Op, ScopeOptions } from 'sequelize'
2import { FindOptions, literal, Op, ScopeOptions } from 'sequelize'
3import { 2import {
4 AllowNull, 3 AllowNull,
5 BeforeDestroy, 4 BeforeDestroy,
@@ -119,30 +118,31 @@ export type SummaryOptions = {
119 } 118 }
120 }, 119 },
121 [ScopeNames.SUMMARY]: (options: SummaryOptions = {}) => { 120 [ScopeNames.SUMMARY]: (options: SummaryOptions = {}) => {
121 const include: Includeable[] = [
122 {
123 attributes: [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ],
124 model: ActorModel.unscoped(),
125 required: options.actorRequired ?? true,
126 include: [
127 {
128 attributes: [ 'host' ],
129 model: ServerModel.unscoped(),
130 required: false
131 },
132 {
133 model: AvatarModel.unscoped(),
134 required: false
135 }
136 ]
137 }
138 ]
139
122 const base: FindOptions = { 140 const base: FindOptions = {
123 attributes: [ 'id', 'name', 'description', 'actorId' ], 141 attributes: [ 'id', 'name', 'description', 'actorId' ]
124 include: [
125 {
126 attributes: [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ],
127 model: ActorModel.unscoped(),
128 required: options.actorRequired ?? true,
129 include: [
130 {
131 attributes: [ 'host' ],
132 model: ServerModel.unscoped(),
133 required: false
134 },
135 {
136 model: AvatarModel.unscoped(),
137 required: false
138 }
139 ]
140 }
141 ]
142 } 142 }
143 143
144 if (options.withAccount === true) { 144 if (options.withAccount === true) {
145 base.include.push({ 145 include.push({
146 model: AccountModel.scope({ 146 model: AccountModel.scope({
147 method: [ AccountModelScopeNames.SUMMARY, { withAccountBlockerIds: options.withAccountBlockerIds } as AccountSummaryOptions ] 147 method: [ AccountModelScopeNames.SUMMARY, { withAccountBlockerIds: options.withAccountBlockerIds } as AccountSummaryOptions ]
148 }), 148 }),
@@ -150,6 +150,8 @@ export type SummaryOptions = {
150 }) 150 })
151 } 151 }
152 152
153 base.include = include
154
153 return base 155 return base
154 }, 156 },
155 [ScopeNames.WITH_ACCOUNT]: { 157 [ScopeNames.WITH_ACCOUNT]: {
@@ -221,7 +223,7 @@ export type SummaryOptions = {
221 } 223 }
222 ] 224 ]
223}) 225})
224export class VideoChannelModel extends Model<VideoChannelModel> { 226export class VideoChannelModel extends Model {
225 227
226 @AllowNull(false) 228 @AllowNull(false)
227 @Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelNameValid, 'name')) 229 @Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelNameValid, 'name'))
@@ -328,18 +330,17 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
328 order: getSort(parameters.sort) 330 order: getSort(parameters.sort)
329 } 331 }
330 332
331 const scopes = {
332 method: [ ScopeNames.FOR_API, { actorId } as AvailableForListOptions ]
333 }
334 return VideoChannelModel 333 return VideoChannelModel
335 .scope(scopes) 334 .scope({
335 method: [ ScopeNames.FOR_API, { actorId } as AvailableForListOptions ]
336 })
336 .findAndCountAll(query) 337 .findAndCountAll(query)
337 .then(({ rows, count }) => { 338 .then(({ rows, count }) => {
338 return { total: count, data: rows } 339 return { total: count, data: rows }
339 }) 340 })
340 } 341 }
341 342
342 static listLocalsForSitemap (sort: string): Bluebird<MChannelActor[]> { 343 static listLocalsForSitemap (sort: string): Promise<MChannelActor[]> {
343 const query = { 344 const query = {
344 attributes: [ ], 345 attributes: [ ],
345 offset: 0, 346 offset: 0,
@@ -391,11 +392,10 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
391 } 392 }
392 } 393 }
393 394
394 const scopes = {
395 method: [ ScopeNames.FOR_API, { actorId: options.actorId } as AvailableForListOptions ]
396 }
397 return VideoChannelModel 395 return VideoChannelModel
398 .scope(scopes) 396 .scope({
397 method: [ ScopeNames.FOR_API, { actorId: options.actorId } as AvailableForListOptions ]
398 })
399 .findAndCountAll(query) 399 .findAndCountAll(query)
400 .then(({ rows, count }) => { 400 .then(({ rows, count }) => {
401 return { total: count, data: rows } 401 return { total: count, data: rows }
@@ -457,13 +457,13 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
457 }) 457 })
458 } 458 }
459 459
460 static loadByIdAndPopulateAccount (id: number): Bluebird<MChannelAccountDefault> { 460 static loadByIdAndPopulateAccount (id: number): Promise<MChannelAccountDefault> {
461 return VideoChannelModel.unscoped() 461 return VideoChannelModel.unscoped()
462 .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) 462 .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ])
463 .findByPk(id) 463 .findByPk(id)
464 } 464 }
465 465
466 static loadByIdAndAccount (id: number, accountId: number): Bluebird<MChannelAccountDefault> { 466 static loadByIdAndAccount (id: number, accountId: number): Promise<MChannelAccountDefault> {
467 const query = { 467 const query = {
468 where: { 468 where: {
469 id, 469 id,
@@ -476,13 +476,13 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
476 .findOne(query) 476 .findOne(query)
477 } 477 }
478 478
479 static loadAndPopulateAccount (id: number): Bluebird<MChannelAccountDefault> { 479 static loadAndPopulateAccount (id: number): Promise<MChannelAccountDefault> {
480 return VideoChannelModel.unscoped() 480 return VideoChannelModel.unscoped()
481 .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) 481 .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ])
482 .findByPk(id) 482 .findByPk(id)
483 } 483 }
484 484
485 static loadByUrlAndPopulateAccount (url: string): Bluebird<MChannelAccountDefault> { 485 static loadByUrlAndPopulateAccount (url: string): Promise<MChannelAccountDefault> {
486 const query = { 486 const query = {
487 include: [ 487 include: [
488 { 488 {
@@ -508,7 +508,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
508 return VideoChannelModel.loadByNameAndHostAndPopulateAccount(name, host) 508 return VideoChannelModel.loadByNameAndHostAndPopulateAccount(name, host)
509 } 509 }
510 510
511 static loadLocalByNameAndPopulateAccount (name: string): Bluebird<MChannelAccountDefault> { 511 static loadLocalByNameAndPopulateAccount (name: string): Promise<MChannelAccountDefault> {
512 const query = { 512 const query = {
513 include: [ 513 include: [
514 { 514 {
@@ -527,7 +527,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
527 .findOne(query) 527 .findOne(query)
528 } 528 }
529 529
530 static loadByNameAndHostAndPopulateAccount (name: string, host: string): Bluebird<MChannelAccountDefault> { 530 static loadByNameAndHostAndPopulateAccount (name: string, host: string): Promise<MChannelAccountDefault> {
531 const query = { 531 const query = {
532 include: [ 532 include: [
533 { 533 {
@@ -552,7 +552,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
552 .findOne(query) 552 .findOne(query)
553 } 553 }
554 554
555 static loadAndPopulateAccountAndVideos (id: number): Bluebird<MChannelActorAccountDefaultVideos> { 555 static loadAndPopulateAccountAndVideos (id: number): Promise<MChannelActorAccountDefaultVideos> {
556 const options = { 556 const options = {
557 include: [ 557 include: [
558 VideoModel 558 VideoModel
diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts
index ed4a345eb..8d1c38826 100644
--- a/server/models/video/video-comment.ts
+++ b/server/models/video/video-comment.ts
@@ -1,4 +1,3 @@
1import * as Bluebird from 'bluebird'
2import { uniq } from 'lodash' 1import { uniq } from 'lodash'
3import { FindAndCountOptions, FindOptions, Op, Order, ScopeOptions, Sequelize, Transaction, WhereOptions } from 'sequelize' 2import { FindAndCountOptions, FindOptions, Op, Order, ScopeOptions, Sequelize, Transaction, WhereOptions } from 'sequelize'
4import { 3import {
@@ -174,7 +173,7 @@ export enum ScopeNames {
174 } 173 }
175 ] 174 ]
176}) 175})
177export class VideoCommentModel extends Model<VideoCommentModel> { 176export class VideoCommentModel extends Model {
178 @CreatedAt 177 @CreatedAt
179 createdAt: Date 178 createdAt: Date
180 179
@@ -255,7 +254,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
255 }) 254 })
256 CommentAbuses: VideoCommentAbuseModel[] 255 CommentAbuses: VideoCommentAbuseModel[]
257 256
258 static loadById (id: number, t?: Transaction): Bluebird<MComment> { 257 static loadById (id: number, t?: Transaction): Promise<MComment> {
259 const query: FindOptions = { 258 const query: FindOptions = {
260 where: { 259 where: {
261 id 260 id
@@ -267,7 +266,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
267 return VideoCommentModel.findOne(query) 266 return VideoCommentModel.findOne(query)
268 } 267 }
269 268
270 static loadByIdAndPopulateVideoAndAccountAndReply (id: number, t?: Transaction): Bluebird<MCommentOwnerVideoReply> { 269 static loadByIdAndPopulateVideoAndAccountAndReply (id: number, t?: Transaction): Promise<MCommentOwnerVideoReply> {
271 const query: FindOptions = { 270 const query: FindOptions = {
272 where: { 271 where: {
273 id 272 id
@@ -281,7 +280,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
281 .findOne(query) 280 .findOne(query)
282 } 281 }
283 282
284 static loadByUrlAndPopulateAccountAndVideo (url: string, t?: Transaction): Bluebird<MCommentOwnerVideo> { 283 static loadByUrlAndPopulateAccountAndVideo (url: string, t?: Transaction): Promise<MCommentOwnerVideo> {
285 const query: FindOptions = { 284 const query: FindOptions = {
286 where: { 285 where: {
287 url 286 url
@@ -293,7 +292,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
293 return VideoCommentModel.scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_VIDEO ]).findOne(query) 292 return VideoCommentModel.scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_VIDEO ]).findOne(query)
294 } 293 }
295 294
296 static loadByUrlAndPopulateReplyAndVideoUrlAndAccount (url: string, t?: Transaction): Bluebird<MCommentOwnerReplyVideoLight> { 295 static loadByUrlAndPopulateReplyAndVideoUrlAndAccount (url: string, t?: Transaction): Promise<MCommentOwnerReplyVideoLight> {
297 const query: FindOptions = { 296 const query: FindOptions = {
298 where: { 297 where: {
299 url 298 url
@@ -501,7 +500,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
501 }) 500 })
502 } 501 }
503 502
504 static listThreadParentComments (comment: MCommentId, t: Transaction, order: 'ASC' | 'DESC' = 'ASC'): Bluebird<MCommentOwner[]> { 503 static listThreadParentComments (comment: MCommentId, t: Transaction, order: 'ASC' | 'DESC' = 'ASC'): Promise<MCommentOwner[]> {
505 const query = { 504 const query = {
506 order: [ [ 'createdAt', order ] ] as Order, 505 order: [ [ 'createdAt', order ] ] as Order,
507 where: { 506 where: {
diff --git a/server/models/video/video-file.ts b/server/models/video/video-file.ts
index d48c9f5d4..48b337c68 100644
--- a/server/models/video/video-file.ts
+++ b/server/models/video/video-file.ts
@@ -101,7 +101,7 @@ export enum ScopeNames {
101 } 101 }
102 ] 102 ]
103}) 103})
104export class VideoFileModel extends Model<VideoFileModel> { 104export class VideoFileModel extends Model {
105 @CreatedAt 105 @CreatedAt
106 createdAt: Date 106 createdAt: Date
107 107
diff --git a/server/models/video/video-import.ts b/server/models/video/video-import.ts
index ea1e085af..f3ed651b2 100644
--- a/server/models/video/video-import.ts
+++ b/server/models/video/video-import.ts
@@ -13,15 +13,14 @@ import {
13 Table, 13 Table,
14 UpdatedAt 14 UpdatedAt
15} from 'sequelize-typescript' 15} from 'sequelize-typescript'
16import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants' 16import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import'
17import { getSort, throwIfNotValid } from '../utils'
18import { ScopeNames as VideoModelScopeNames, VideoModel } from './video'
19import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports'
20import { VideoImport, VideoImportState } from '../../../shared' 17import { VideoImport, VideoImportState } from '../../../shared'
18import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports'
21import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos' 19import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos'
20import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants'
22import { UserModel } from '../account/user' 21import { UserModel } from '../account/user'
23import * as Bluebird from 'bluebird' 22import { getSort, throwIfNotValid } from '../utils'
24import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import' 23import { ScopeNames as VideoModelScopeNames, VideoModel } from './video'
25 24
26@DefaultScope(() => ({ 25@DefaultScope(() => ({
27 include: [ 26 include: [
@@ -52,7 +51,7 @@ import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/mode
52 } 51 }
53 ] 52 ]
54}) 53})
55export class VideoImportModel extends Model<VideoImportModel> { 54export class VideoImportModel extends Model {
56 @CreatedAt 55 @CreatedAt
57 createdAt: Date 56 createdAt: Date
58 57
@@ -120,7 +119,7 @@ export class VideoImportModel extends Model<VideoImportModel> {
120 return undefined 119 return undefined
121 } 120 }
122 121
123 static loadAndPopulateVideo (id: number): Bluebird<MVideoImportDefault> { 122 static loadAndPopulateVideo (id: number): Promise<MVideoImportDefault> {
124 return VideoImportModel.findByPk(id) 123 return VideoImportModel.findByPk(id)
125 } 124 }
126 125
diff --git a/server/models/video/video-live.ts b/server/models/video/video-live.ts
index 875ba9b31..cb4a9b896 100644
--- a/server/models/video/video-live.ts
+++ b/server/models/video/video-live.ts
@@ -28,7 +28,7 @@ import { VideoBlacklistModel } from './video-blacklist'
28 } 28 }
29 ] 29 ]
30}) 30})
31export class VideoLiveModel extends Model<VideoLiveModel> { 31export class VideoLiveModel extends Model {
32 32
33 @AllowNull(true) 33 @AllowNull(true)
34 @Column(DataType.STRING) 34 @Column(DataType.STRING)
diff --git a/server/models/video/video-playlist-element.ts b/server/models/video/video-playlist-element.ts
index d357766e9..d2d7e2740 100644
--- a/server/models/video/video-playlist-element.ts
+++ b/server/models/video/video-playlist-element.ts
@@ -1,3 +1,4 @@
1import { AggregateOptions, Op, ScopeOptions, Sequelize, Transaction } from 'sequelize'
1import { 2import {
2 AllowNull, 3 AllowNull,
3 BelongsTo, 4 BelongsTo,
@@ -13,18 +14,8 @@ import {
13 Table, 14 Table,
14 UpdatedAt 15 UpdatedAt
15} from 'sequelize-typescript' 16} from 'sequelize-typescript'
16import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video'
17import { VideoPlaylistModel } from './video-playlist'
18import { getSort, throwIfNotValid } from '../utils'
19import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
20import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
21import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object'
22import validator from 'validator' 17import validator from 'validator'
23import { AggregateOptions, Op, ScopeOptions, Sequelize, Transaction } from 'sequelize' 18import { MUserAccountId } from '@server/types/models'
24import { VideoPlaylistElement, VideoPlaylistElementType } from '../../../shared/models/videos/playlist/video-playlist-element.model'
25import { AccountModel } from '../account/account'
26import { VideoPrivacy } from '../../../shared/models/videos'
27import * as Bluebird from 'bluebird'
28import { 19import {
29 MVideoPlaylistElement, 20 MVideoPlaylistElement,
30 MVideoPlaylistElementAP, 21 MVideoPlaylistElementAP,
@@ -32,7 +23,15 @@ import {
32 MVideoPlaylistElementVideoUrlPlaylistPrivacy, 23 MVideoPlaylistElementVideoUrlPlaylistPrivacy,
33 MVideoPlaylistVideoThumbnail 24 MVideoPlaylistVideoThumbnail
34} from '@server/types/models/video/video-playlist-element' 25} from '@server/types/models/video/video-playlist-element'
35import { MUserAccountId } from '@server/types/models' 26import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object'
27import { VideoPrivacy } from '../../../shared/models/videos'
28import { VideoPlaylistElement, VideoPlaylistElementType } from '../../../shared/models/videos/playlist/video-playlist-element.model'
29import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
30import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
31import { AccountModel } from '../account/account'
32import { getSort, throwIfNotValid } from '../utils'
33import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video'
34import { VideoPlaylistModel } from './video-playlist'
36 35
37@Table({ 36@Table({
38 tableName: 'videoPlaylistElement', 37 tableName: 'videoPlaylistElement',
@@ -49,7 +48,7 @@ import { MUserAccountId } from '@server/types/models'
49 } 48 }
50 ] 49 ]
51}) 50})
52export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel> { 51export class VideoPlaylistElementModel extends Model {
53 @CreatedAt 52 @CreatedAt
54 createdAt: Date 53 createdAt: Date
55 54
@@ -166,7 +165,7 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
166 ]).then(([ total, data ]) => ({ total, data })) 165 ]).then(([ total, data ]) => ({ total, data }))
167 } 166 }
168 167
169 static loadByPlaylistAndVideo (videoPlaylistId: number, videoId: number): Bluebird<MVideoPlaylistElement> { 168 static loadByPlaylistAndVideo (videoPlaylistId: number, videoId: number): Promise<MVideoPlaylistElement> {
170 const query = { 169 const query = {
171 where: { 170 where: {
172 videoPlaylistId, 171 videoPlaylistId,
@@ -177,14 +176,14 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
177 return VideoPlaylistElementModel.findOne(query) 176 return VideoPlaylistElementModel.findOne(query)
178 } 177 }
179 178
180 static loadById (playlistElementId: number | string): Bluebird<MVideoPlaylistElement> { 179 static loadById (playlistElementId: number | string): Promise<MVideoPlaylistElement> {
181 return VideoPlaylistElementModel.findByPk(playlistElementId) 180 return VideoPlaylistElementModel.findByPk(playlistElementId)
182 } 181 }
183 182
184 static loadByPlaylistAndElementIdForAP ( 183 static loadByPlaylistAndElementIdForAP (
185 playlistId: number | string, 184 playlistId: number | string,
186 playlistElementId: number 185 playlistElementId: number
187 ): Bluebird<MVideoPlaylistElementVideoUrlPlaylistPrivacy> { 186 ): Promise<MVideoPlaylistElementVideoUrlPlaylistPrivacy> {
188 const playlistWhere = validator.isUUID('' + playlistId) ? { uuid: playlistId } : { id: playlistId } 187 const playlistWhere = validator.isUUID('' + playlistId) ? { uuid: playlistId } : { id: playlistId }
189 188
190 const query = { 189 const query = {
@@ -226,7 +225,7 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
226 }) 225 })
227 } 226 }
228 227
229 static loadFirstElementWithVideoThumbnail (videoPlaylistId: number): Bluebird<MVideoPlaylistVideoThumbnail> { 228 static loadFirstElementWithVideoThumbnail (videoPlaylistId: number): Promise<MVideoPlaylistVideoThumbnail> {
230 const query = { 229 const query = {
231 order: getSort('position'), 230 order: getSort('position'),
232 where: { 231 where: {
diff --git a/server/models/video/video-playlist.ts b/server/models/video/video-playlist.ts
index 9f9e0b069..93ecf8cea 100644
--- a/server/models/video/video-playlist.ts
+++ b/server/models/video/video-playlist.ts
@@ -1,4 +1,3 @@
1import * as Bluebird from 'bluebird'
2import { join } from 'path' 1import { join } from 'path'
3import { FindOptions, literal, Op, ScopeOptions, Transaction, WhereOptions } from 'sequelize' 2import { FindOptions, literal, Op, ScopeOptions, Transaction, WhereOptions } from 'sequelize'
4import { 3import {
@@ -125,7 +124,6 @@ type AvailableForListOptions = {
125 ] 124 ]
126 }, 125 },
127 [ScopeNames.AVAILABLE_FOR_LIST]: (options: AvailableForListOptions) => { 126 [ScopeNames.AVAILABLE_FOR_LIST]: (options: AvailableForListOptions) => {
128
129 let whereActor: WhereOptions = {} 127 let whereActor: WhereOptions = {}
130 128
131 const whereAnd: WhereOptions[] = [] 129 const whereAnd: WhereOptions[] = []
@@ -182,15 +180,13 @@ type AvailableForListOptions = {
182 [Op.and]: whereAnd 180 [Op.and]: whereAnd
183 } 181 }
184 182
185 const accountScope = {
186 method: [ AccountScopeNames.SUMMARY, { whereActor } as SummaryOptions ]
187 }
188
189 return { 183 return {
190 where, 184 where,
191 include: [ 185 include: [
192 { 186 {
193 model: AccountModel.scope(accountScope), 187 model: AccountModel.scope({
188 method: [ AccountScopeNames.SUMMARY, { whereActor } as SummaryOptions ]
189 }),
194 required: true 190 required: true
195 }, 191 },
196 { 192 {
@@ -217,7 +213,7 @@ type AvailableForListOptions = {
217 } 213 }
218 ] 214 ]
219}) 215})
220export class VideoPlaylistModel extends Model<VideoPlaylistModel> { 216export class VideoPlaylistModel extends Model {
221 @CreatedAt 217 @CreatedAt
222 createdAt: Date 218 createdAt: Date
223 219
@@ -367,7 +363,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
367 }) 363 })
368 } 364 }
369 365
370 static listPlaylistIdsOf (accountId: number, videoIds: number[]): Bluebird<MVideoPlaylistIdWithElements[]> { 366 static listPlaylistIdsOf (accountId: number, videoIds: number[]): Promise<MVideoPlaylistIdWithElements[]> {
371 const query = { 367 const query = {
372 attributes: [ 'id' ], 368 attributes: [ 'id' ],
373 where: { 369 where: {
@@ -392,7 +388,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
392 388
393 static doesPlaylistExist (url: string) { 389 static doesPlaylistExist (url: string) {
394 const query = { 390 const query = {
395 attributes: [], 391 attributes: [ 'id' ],
396 where: { 392 where: {
397 url 393 url
398 } 394 }
@@ -403,7 +399,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
403 .then(e => !!e) 399 .then(e => !!e)
404 } 400 }
405 401
406 static loadWithAccountAndChannelSummary (id: number | string, transaction: Transaction): Bluebird<MVideoPlaylistFullSummary> { 402 static loadWithAccountAndChannelSummary (id: number | string, transaction: Transaction): Promise<MVideoPlaylistFullSummary> {
407 const where = buildWhereIdOrUUID(id) 403 const where = buildWhereIdOrUUID(id)
408 404
409 const query = { 405 const query = {
@@ -416,7 +412,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
416 .findOne(query) 412 .findOne(query)
417 } 413 }
418 414
419 static loadWithAccountAndChannel (id: number | string, transaction: Transaction): Bluebird<MVideoPlaylistFull> { 415 static loadWithAccountAndChannel (id: number | string, transaction: Transaction): Promise<MVideoPlaylistFull> {
420 const where = buildWhereIdOrUUID(id) 416 const where = buildWhereIdOrUUID(id)
421 417
422 const query = { 418 const query = {
@@ -429,7 +425,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
429 .findOne(query) 425 .findOne(query)
430 } 426 }
431 427
432 static loadByUrlAndPopulateAccount (url: string): Bluebird<MVideoPlaylistAccountThumbnail> { 428 static loadByUrlAndPopulateAccount (url: string): Promise<MVideoPlaylistAccountThumbnail> {
433 const query = { 429 const query = {
434 where: { 430 where: {
435 url 431 url
diff --git a/server/models/video/video-share.ts b/server/models/video/video-share.ts
index f9ee94589..b7f5f3fa3 100644
--- a/server/models/video/video-share.ts
+++ b/server/models/video/video-share.ts
@@ -1,13 +1,12 @@
1import * as Bluebird from 'bluebird' 1import { literal, Op, 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 { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 3import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
4import { CONSTRAINTS_FIELDS } from '../../initializers/constants' 4import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
5import { MActorDefault } from '../../types/models'
6import { MVideoShareActor, MVideoShareFull } from '../../types/models/video'
5import { ActorModel } from '../activitypub/actor' 7import { ActorModel } from '../activitypub/actor'
6import { buildLocalActorIdsIn, throwIfNotValid } from '../utils' 8import { buildLocalActorIdsIn, throwIfNotValid } from '../utils'
7import { VideoModel } from './video' 9import { VideoModel } from './video'
8import { literal, Op, Transaction } from 'sequelize'
9import { MVideoShareActor, MVideoShareFull } from '../../types/models/video'
10import { MActorDefault } from '../../types/models'
11 10
12enum ScopeNames { 11enum ScopeNames {
13 FULL = 'FULL', 12 FULL = 'FULL',
@@ -51,7 +50,7 @@ enum ScopeNames {
51 } 50 }
52 ] 51 ]
53}) 52})
54export class VideoShareModel extends Model<VideoShareModel> { 53export class VideoShareModel extends Model {
55 54
56 @AllowNull(false) 55 @AllowNull(false)
57 @Is('VideoShareUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) 56 @Is('VideoShareUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url'))
@@ -88,7 +87,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
88 }) 87 })
89 Video: VideoModel 88 Video: VideoModel
90 89
91 static load (actorId: number | string, videoId: number | string, t?: Transaction): Bluebird<MVideoShareActor> { 90 static load (actorId: number | string, videoId: number | string, t?: Transaction): Promise<MVideoShareActor> {
92 return VideoShareModel.scope(ScopeNames.WITH_ACTOR).findOne({ 91 return VideoShareModel.scope(ScopeNames.WITH_ACTOR).findOne({
93 where: { 92 where: {
94 actorId, 93 actorId,
@@ -98,7 +97,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
98 }) 97 })
99 } 98 }
100 99
101 static loadByUrl (url: string, t: Transaction): Bluebird<MVideoShareFull> { 100 static loadByUrl (url: string, t: Transaction): Promise<MVideoShareFull> {
102 return VideoShareModel.scope(ScopeNames.FULL).findOne({ 101 return VideoShareModel.scope(ScopeNames.FULL).findOne({
103 where: { 102 where: {
104 url 103 url
@@ -107,7 +106,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
107 }) 106 })
108 } 107 }
109 108
110 static loadActorsByShare (videoId: number, t: Transaction): Bluebird<MActorDefault[]> { 109 static loadActorsByShare (videoId: number, t: Transaction): Promise<MActorDefault[]> {
111 const query = { 110 const query = {
112 where: { 111 where: {
113 videoId 112 videoId
@@ -125,7 +124,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
125 .then((res: MVideoShareFull[]) => res.map(r => r.Actor)) 124 .then((res: MVideoShareFull[]) => res.map(r => r.Actor))
126 } 125 }
127 126
128 static loadActorsWhoSharedVideosOf (actorOwnerId: number, t: Transaction): Bluebird<MActorDefault[]> { 127 static loadActorsWhoSharedVideosOf (actorOwnerId: number, t: Transaction): Promise<MActorDefault[]> {
129 const safeOwnerId = parseInt(actorOwnerId + '', 10) 128 const safeOwnerId = parseInt(actorOwnerId + '', 10)
130 129
131 // /!\ On actor model 130 // /!\ On actor model
@@ -150,7 +149,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
150 return ActorModel.findAll(query) 149 return ActorModel.findAll(query)
151 } 150 }
152 151
153 static loadActorsByVideoChannel (videoChannelId: number, t: Transaction): Bluebird<MActorDefault[]> { 152 static loadActorsByVideoChannel (videoChannelId: number, t: Transaction): Promise<MActorDefault[]> {
154 const safeChannelId = parseInt(videoChannelId + '', 10) 153 const safeChannelId = parseInt(videoChannelId + '', 10)
155 154
156 // /!\ On actor model 155 // /!\ On actor model
diff --git a/server/models/video/video-streaming-playlist.ts b/server/models/video/video-streaming-playlist.ts
index 73bd89844..148768c21 100644
--- a/server/models/video/video-streaming-playlist.ts
+++ b/server/models/video/video-streaming-playlist.ts
@@ -40,7 +40,7 @@ import { logger } from '@server/helpers/logger'
40 } 40 }
41 ] 41 ]
42}) 42})
43export class VideoStreamingPlaylistModel extends Model<VideoStreamingPlaylistModel> { 43export class VideoStreamingPlaylistModel extends Model {
44 @CreatedAt 44 @CreatedAt
45 createdAt: Date 45 createdAt: Date
46 46
diff --git a/server/models/video/video-tag.ts b/server/models/video/video-tag.ts
index ca15e3426..5052b8c4d 100644
--- a/server/models/video/video-tag.ts
+++ b/server/models/video/video-tag.ts
@@ -13,7 +13,7 @@ import { VideoModel } from './video'
13 } 13 }
14 ] 14 ]
15}) 15})
16export class VideoTagModel extends Model<VideoTagModel> { 16export class VideoTagModel extends Model {
17 @CreatedAt 17 @CreatedAt
18 createdAt: Date 18 createdAt: Date
19 19
diff --git a/server/models/video/video-view.ts b/server/models/video/video-view.ts
index 40db5effd..992cf258a 100644
--- a/server/models/video/video-view.ts
+++ b/server/models/video/video-view.ts
@@ -14,7 +14,7 @@ import * as Sequelize from 'sequelize'
14 } 14 }
15 ] 15 ]
16}) 16})
17export class VideoViewModel extends Model<VideoViewModel> { 17export class VideoViewModel extends Model {
18 @CreatedAt 18 @CreatedAt
19 createdAt: Date 19 createdAt: Date
20 20
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index a43abbc09..d3fed338a 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -2,7 +2,7 @@ import * as Bluebird from 'bluebird'
2import { remove } from 'fs-extra' 2import { remove } from 'fs-extra'
3import { maxBy, minBy, pick } from 'lodash' 3import { maxBy, minBy, pick } from 'lodash'
4import { join } from 'path' 4import { join } from 'path'
5import { FindOptions, IncludeOptions, Op, QueryTypes, ScopeOptions, Sequelize, Transaction, WhereOptions } from 'sequelize' 5import { FindOptions, Includeable, IncludeOptions, Op, QueryTypes, ScopeOptions, Sequelize, Transaction, WhereOptions } from 'sequelize'
6import { 6import {
7 AllowNull, 7 AllowNull,
8 BeforeDestroy, 8 BeforeDestroy,
@@ -190,26 +190,26 @@ export type AvailableForListIDsOptions = {
190 attributes: [ 'id', 'url', 'uuid', 'remote' ] 190 attributes: [ 'id', 'url', 'uuid', 'remote' ]
191 }, 191 },
192 [ScopeNames.FOR_API]: (options: ForAPIOptions) => { 192 [ScopeNames.FOR_API]: (options: ForAPIOptions) => {
193 const query: FindOptions = { 193 const include: Includeable[] = [
194 include: [ 194 {
195 { 195 model: VideoChannelModel.scope({
196 model: VideoChannelModel.scope({ 196 method: [
197 method: [ 197 VideoChannelScopeNames.SUMMARY, {
198 VideoChannelScopeNames.SUMMARY, { 198 withAccount: true,
199 withAccount: true, 199 withAccountBlockerIds: options.withAccountBlockerIds
200 withAccountBlockerIds: options.withAccountBlockerIds 200 } as SummaryOptions
201 } as SummaryOptions 201 ]
202 ] 202 }),
203 }), 203 required: true
204 required: true 204 },
205 }, 205 {
206 { 206 attributes: [ 'type', 'filename' ],
207 attributes: [ 'type', 'filename' ], 207 model: ThumbnailModel,
208 model: ThumbnailModel, 208 required: false
209 required: false 209 }
210 } 210 ]
211 ] 211
212 } 212 const query: FindOptions = {}
213 213
214 if (options.ids) { 214 if (options.ids) {
215 query.where = { 215 query.where = {
@@ -220,14 +220,14 @@ export type AvailableForListIDsOptions = {
220 } 220 }
221 221
222 if (options.withFiles === true) { 222 if (options.withFiles === true) {
223 query.include.push({ 223 include.push({
224 model: VideoFileModel, 224 model: VideoFileModel,
225 required: true 225 required: true
226 }) 226 })
227 } 227 }
228 228
229 if (options.videoPlaylistId) { 229 if (options.videoPlaylistId) {
230 query.include.push({ 230 include.push({
231 model: VideoPlaylistElementModel.unscoped(), 231 model: VideoPlaylistElementModel.unscoped(),
232 required: true, 232 required: true,
233 where: { 233 where: {
@@ -236,6 +236,8 @@ export type AvailableForListIDsOptions = {
236 }) 236 })
237 } 237 }
238 238
239 query.include = include
240
239 return query 241 return query
240 }, 242 },
241 [ScopeNames.WITH_THUMBNAILS]: { 243 [ScopeNames.WITH_THUMBNAILS]: {
@@ -477,7 +479,7 @@ export type AvailableForListIDsOptions = {
477 } 479 }
478 ] 480 ]
479}) 481})
480export class VideoModel extends Model<VideoModel> { 482export class VideoModel extends Model {
481 483
482 @AllowNull(false) 484 @AllowNull(false)
483 @Default(DataType.UUIDV4) 485 @Default(DataType.UUIDV4)
@@ -860,7 +862,7 @@ export class VideoModel extends Model<VideoModel> {
860 return undefined 862 return undefined
861 } 863 }
862 864
863 static listLocal (): Bluebird<MVideoWithAllFiles[]> { 865 static listLocal (): Promise<MVideoWithAllFiles[]> {
864 const query = { 866 const query = {
865 where: { 867 where: {
866 remote: false 868 remote: false
@@ -988,7 +990,7 @@ export class VideoModel extends Model<VideoModel> {
988 }) 990 })
989 } 991 }
990 992
991 static listPublishedLiveIds () { 993 static async listPublishedLiveIds () {
992 const options = { 994 const options = {
993 attributes: [ 'id' ], 995 attributes: [ 'id' ],
994 where: { 996 where: {
@@ -997,8 +999,9 @@ export class VideoModel extends Model<VideoModel> {
997 } 999 }
998 } 1000 }
999 1001
1000 return VideoModel.findAll(options) 1002 const result = await VideoModel.findAll(options)
1001 .map(v => v.id) 1003
1004 return result.map(v => v.id)
1002 } 1005 }
1003 1006
1004 static listUserVideosForApi ( 1007 static listUserVideosForApi (
@@ -1214,7 +1217,7 @@ export class VideoModel extends Model<VideoModel> {
1214 return VideoModel.count(options) 1217 return VideoModel.count(options)
1215 } 1218 }
1216 1219
1217 static load (id: number | string, t?: Transaction): Bluebird<MVideoThumbnail> { 1220 static load (id: number | string, t?: Transaction): Promise<MVideoThumbnail> {
1218 const where = buildWhereIdOrUUID(id) 1221 const where = buildWhereIdOrUUID(id)
1219 const options = { 1222 const options = {
1220 where, 1223 where,
@@ -1224,7 +1227,7 @@ export class VideoModel extends Model<VideoModel> {
1224 return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options) 1227 return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
1225 } 1228 }
1226 1229
1227 static loadWithBlacklist (id: number | string, t?: Transaction): Bluebird<MVideoThumbnailBlacklist> { 1230 static loadWithBlacklist (id: number | string, t?: Transaction): Promise<MVideoThumbnailBlacklist> {
1228 const where = buildWhereIdOrUUID(id) 1231 const where = buildWhereIdOrUUID(id)
1229 const options = { 1232 const options = {
1230 where, 1233 where,
@@ -1237,7 +1240,7 @@ export class VideoModel extends Model<VideoModel> {
1237 ]).findOne(options) 1240 ]).findOne(options)
1238 } 1241 }
1239 1242
1240 static loadImmutableAttributes (id: number | string, t?: Transaction): Bluebird<MVideoImmutable> { 1243 static loadImmutableAttributes (id: number | string, t?: Transaction): Promise<MVideoImmutable> {
1241 const fun = () => { 1244 const fun = () => {
1242 const query = { 1245 const query = {
1243 where: buildWhereIdOrUUID(id), 1246 where: buildWhereIdOrUUID(id),
@@ -1255,7 +1258,7 @@ export class VideoModel extends Model<VideoModel> {
1255 }) 1258 })
1256 } 1259 }
1257 1260
1258 static loadWithRights (id: number | string, t?: Transaction): Bluebird<MVideoWithRights> { 1261 static loadWithRights (id: number | string, t?: Transaction): Promise<MVideoWithRights> {
1259 const where = buildWhereIdOrUUID(id) 1262 const where = buildWhereIdOrUUID(id)
1260 const options = { 1263 const options = {
1261 where, 1264 where,
@@ -1269,7 +1272,7 @@ export class VideoModel extends Model<VideoModel> {
1269 ]).findOne(options) 1272 ]).findOne(options)
1270 } 1273 }
1271 1274
1272 static loadOnlyId (id: number | string, t?: Transaction): Bluebird<MVideoIdThumbnail> { 1275 static loadOnlyId (id: number | string, t?: Transaction): Promise<MVideoIdThumbnail> {
1273 const where = buildWhereIdOrUUID(id) 1276 const where = buildWhereIdOrUUID(id)
1274 1277
1275 const options = { 1278 const options = {
@@ -1281,7 +1284,7 @@ export class VideoModel extends Model<VideoModel> {
1281 return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options) 1284 return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
1282 } 1285 }
1283 1286
1284 static loadWithFiles (id: number | string, t?: Transaction, logging?: boolean): Bluebird<MVideoWithAllFiles> { 1287 static loadWithFiles (id: number | string, t?: Transaction, logging?: boolean): Promise<MVideoWithAllFiles> {
1285 const where = buildWhereIdOrUUID(id) 1288 const where = buildWhereIdOrUUID(id)
1286 1289
1287 const query = { 1290 const query = {
@@ -1297,7 +1300,7 @@ export class VideoModel extends Model<VideoModel> {
1297 ]).findOne(query) 1300 ]).findOne(query)
1298 } 1301 }
1299 1302
1300 static loadByUUID (uuid: string): Bluebird<MVideoThumbnail> { 1303 static loadByUUID (uuid: string): Promise<MVideoThumbnail> {
1301 const options = { 1304 const options = {
1302 where: { 1305 where: {
1303 uuid 1306 uuid
@@ -1307,7 +1310,7 @@ export class VideoModel extends Model<VideoModel> {
1307 return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options) 1310 return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
1308 } 1311 }
1309 1312
1310 static loadByUrl (url: string, transaction?: Transaction): Bluebird<MVideoThumbnail> { 1313 static loadByUrl (url: string, transaction?: Transaction): Promise<MVideoThumbnail> {
1311 const query: FindOptions = { 1314 const query: FindOptions = {
1312 where: { 1315 where: {
1313 url 1316 url
@@ -1318,7 +1321,7 @@ export class VideoModel extends Model<VideoModel> {
1318 return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(query) 1321 return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(query)
1319 } 1322 }
1320 1323
1321 static loadByUrlImmutableAttributes (url: string, transaction?: Transaction): Bluebird<MVideoImmutable> { 1324 static loadByUrlImmutableAttributes (url: string, transaction?: Transaction): Promise<MVideoImmutable> {
1322 const fun = () => { 1325 const fun = () => {
1323 const query: FindOptions = { 1326 const query: FindOptions = {
1324 where: { 1327 where: {
@@ -1338,7 +1341,7 @@ export class VideoModel extends Model<VideoModel> {
1338 }) 1341 })
1339 } 1342 }
1340 1343
1341 static loadByUrlAndPopulateAccount (url: string, transaction?: Transaction): Bluebird<MVideoAccountLightBlacklistAllFiles> { 1344 static loadByUrlAndPopulateAccount (url: string, transaction?: Transaction): Promise<MVideoAccountLightBlacklistAllFiles> {
1342 const query: FindOptions = { 1345 const query: FindOptions = {
1343 where: { 1346 where: {
1344 url 1347 url
@@ -1355,7 +1358,7 @@ export class VideoModel extends Model<VideoModel> {
1355 ]).findOne(query) 1358 ]).findOne(query)
1356 } 1359 }
1357 1360
1358 static loadAndPopulateAccountAndServerAndTags (id: number | string, t?: Transaction, userId?: number): Bluebird<MVideoFullLight> { 1361 static loadAndPopulateAccountAndServerAndTags (id: number | string, t?: Transaction, userId?: number): Promise<MVideoFullLight> {
1359 const where = buildWhereIdOrUUID(id) 1362 const where = buildWhereIdOrUUID(id)
1360 1363
1361 const options = { 1364 const options = {
@@ -1388,7 +1391,7 @@ export class VideoModel extends Model<VideoModel> {
1388 id: number | string 1391 id: number | string
1389 t?: Transaction 1392 t?: Transaction
1390 userId?: number 1393 userId?: number
1391 }): Bluebird<MVideoDetails> { 1394 }): Promise<MVideoDetails> {
1392 const { id, t, userId } = parameters 1395 const { id, t, userId } = parameters
1393 const where = buildWhereIdOrUUID(id) 1396 const where = buildWhereIdOrUUID(id)
1394 1397
@@ -1487,7 +1490,7 @@ export class VideoModel extends Model<VideoModel> {
1487 return VideoModel.update({ support: videoChannel.support }, options) 1490 return VideoModel.update({ support: videoChannel.support }, options)
1488 } 1491 }
1489 1492
1490 static getAllIdsFromChannel (videoChannel: MChannelId): Bluebird<number[]> { 1493 static getAllIdsFromChannel (videoChannel: MChannelId): Promise<number[]> {
1491 const query = { 1494 const query = {
1492 attributes: [ 'id' ], 1495 attributes: [ 'id' ],
1493 where: { 1496 where: {
diff --git a/server/tests/api/live/live.ts b/server/tests/api/live/live.ts
index fdfc6105f..a74988aba 100644
--- a/server/tests/api/live/live.ts
+++ b/server/tests/api/live/live.ts
@@ -686,12 +686,7 @@ describe('Test live', function () {
686 it('Should save a live replay', async function () { 686 it('Should save a live replay', async function () {
687 this.timeout(60000) 687 this.timeout(60000)
688 688
689 await waitJobs(servers) 689 await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId)
690
691 const res = await getVideo(servers[0].url, liveVideoReplayId)
692 const video: VideoDetails = res.body
693
694 expect(video.state.id).to.equal(VideoState.PUBLISHED)
695 }) 690 })
696 }) 691 })
697 692
diff --git a/server/types/plugins/register-server-option.model.ts b/server/types/plugins/register-server-option.model.ts
index 74303d383..2e52d1efd 100644
--- a/server/types/plugins/register-server-option.model.ts
+++ b/server/types/plugins/register-server-option.model.ts
@@ -1,4 +1,3 @@
1import * as Bluebird from 'bluebird'
2import { Router } from 'express' 1import { Router } from 'express'
3import { Logger } from 'winston' 2import { Logger } from 'winston'
4import { ActorModel } from '@server/models/activitypub/actor' 3import { ActorModel } from '@server/models/activitypub/actor'
@@ -29,7 +28,7 @@ export type PeerTubeHelpers = {
29 } 28 }
30 29
31 videos: { 30 videos: {
32 loadByUrl: (url: string) => Bluebird<MVideoThumbnail> 31 loadByUrl: (url: string) => Promise<MVideoThumbnail>
33 32
34 removeVideo: (videoId: number) => Promise<void> 33 removeVideo: (videoId: number) => Promise<void>
35 } 34 }