Browse Source

Upgrade sequelize to v6

Chocobozzz 3 years ago
parent
commit
b49f22d8f9
75 changed files with 431 additions and 493 deletions
  1. 2 2
      package.json
  2. 2 3
      server/controllers/api/videos/import.ts
  3. 3 3
      server/helpers/actor.ts
  4. 3 4
      server/helpers/middlewares/accounts.ts
  5. 12 13
      server/helpers/video.ts
  6. 0 1
      server/initializers/migrations/0005-email-pod.ts
  7. 0 1
      server/initializers/migrations/0010-email-user.ts
  8. 0 1
      server/initializers/migrations/0015-video-views.ts
  9. 0 1
      server/initializers/migrations/0020-video-likes.ts
  10. 0 1
      server/initializers/migrations/0025-video-dislikes.ts
  11. 0 1
      server/initializers/migrations/0030-video-category.ts
  12. 0 1
      server/initializers/migrations/0035-video-licence.ts
  13. 0 1
      server/initializers/migrations/0040-video-nsfw.ts
  14. 0 1
      server/initializers/migrations/0045-user-display-nsfw.ts
  15. 0 1
      server/initializers/migrations/0050-video-language.ts
  16. 0 1
      server/initializers/migrations/0055-video-uuid.ts
  17. 0 1
      server/initializers/migrations/0060-video-file.ts
  18. 0 1
      server/initializers/migrations/0065-video-file-size.ts
  19. 0 1
      server/initializers/migrations/0070-user-video-quota.ts
  20. 0 1
      server/initializers/migrations/0130-user-autoplay-video.ts
  21. 2 1
      server/initializers/migrations/0150-avatar-cascade.ts
  22. 2 1
      server/initializers/migrations/0410-video-playlist-element.ts
  23. 2 0
      server/lib/activitypub/playlist.ts
  24. 1 1
      server/lib/activitypub/process/process-dislike.ts
  25. 1 1
      server/lib/activitypub/process/process-like.ts
  26. 2 13
      server/lib/activitypub/video-rates.ts
  27. 3 0
      server/lib/activitypub/videos.ts
  28. 15 16
      server/lib/client-html.ts
  29. 10 11
      server/lib/job-queue/handlers/activitypub-http-fetcher.ts
  30. 0 1
      server/lib/video-transcoding-profiles.ts
  31. 12 13
      server/middlewares/validators/users.ts
  32. 3 3
      server/models/abuse/abuse-message.ts
  33. 3 4
      server/models/abuse/abuse.ts
  34. 1 1
      server/models/abuse/video-abuse.ts
  35. 1 1
      server/models/abuse/video-comment-abuse.ts
  36. 4 5
      server/models/account/account-blocklist.ts
  37. 29 24
      server/models/account/account-video-rate.ts
  38. 30 28
      server/models/account/account.ts
  39. 1 1
      server/models/account/user-notification-setting.ts
  40. 1 1
      server/models/account/user-notification.ts
  41. 1 1
      server/models/account/user-video-history.ts
  42. 17 18
      server/models/account/user.ts
  43. 6 7
      server/models/activitypub/actor-follow.ts
  44. 22 22
      server/models/activitypub/actor.ts
  45. 1 1
      server/models/application/application.ts
  46. 1 1
      server/models/avatar/avatar.ts
  47. 1 1
      server/models/model-cache.ts
  48. 1 1
      server/models/oauth/oauth-client.ts
  49. 8 9
      server/models/oauth/oauth-token.ts
  50. 22 23
      server/models/redundancy/video-redundancy.ts
  51. 4 5
      server/models/server/plugin.ts
  52. 3 4
      server/models/server/server-blocklist.ts
  53. 4 5
      server/models/server/server.ts
  54. 2 1
      server/models/utils.ts
  55. 1 1
      server/models/video/schedule-video-update.ts
  56. 6 7
      server/models/video/tag.ts
  57. 1 1
      server/models/video/thumbnail.ts
  58. 8 9
      server/models/video/video-blacklist.ts
  59. 11 12
      server/models/video/video-caption.ts
  60. 5 6
      server/models/video/video-change-ownership.ts
  61. 39 39
      server/models/video/video-channel.ts
  62. 6 7
      server/models/video/video-comment.ts
  63. 1 1
      server/models/video/video-file.ts
  64. 7 8
      server/models/video/video-import.ts
  65. 1 1
      server/models/video/video-live.ts
  66. 16 17
      server/models/video/video-playlist-element.ts
  67. 9 13
      server/models/video/video-playlist.ts
  68. 9 10
      server/models/video/video-share.ts
  69. 1 1
      server/models/video/video-streaming-playlist.ts
  70. 1 1
      server/models/video/video-tag.ts
  71. 1 1
      server/models/video/video-view.ts
  72. 44 41
      server/models/video/video.ts
  73. 1 6
      server/tests/api/live/live.ts
  74. 1 2
      server/types/plugins/register-server-option.model.ts
  75. 24 44
      yarn.lock

+ 2 - 2
package.json

@@ -142,8 +142,8 @@
     "request": "^2.81.0",
     "sanitize-html": "2.x",
     "scripty": "^2.0.0",
-    "sequelize": "5.21.13",
-    "sequelize-typescript": "^1.0.0-beta.4",
+    "sequelize": "6.3.5",
+    "sequelize-typescript": "^2.0.0-beta.1",
     "sitemap": "^6.1.0",
     "socket.io": "^3.0.2",
     "srt-to-vtt": "^1.1.2",

+ 2 - 3
server/controllers/api/videos/import.ts

@@ -1,4 +1,3 @@
-import * as Bluebird from 'bluebird'
 import * as express from 'express'
 import { move, readFile } from 'fs-extra'
 import * as magnetUtil from 'magnet-uri'
@@ -17,6 +16,7 @@ import {
 } from '@server/types/models'
 import { MVideoImport, MVideoImportFormattable } from '@server/types/models/video/video-import'
 import { VideoImportCreate, VideoImportState, VideoPrivacy, VideoState } from '../../../../shared'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type'
 import { auditLoggerFactory, getAuditIdFromRes, VideoImportAuditView } from '../../../helpers/audit-logger'
 import { moveAndProcessCaptionFile } from '../../../helpers/captions-utils'
@@ -36,7 +36,6 @@ import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videoIm
 import { VideoModel } from '../../../models/video/video'
 import { VideoCaptionModel } from '../../../models/video/video-caption'
 import { VideoImportModel } from '../../../models/video/video-import'
-import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const auditLogger = auditLoggerFactory('video-imports')
 const videoImportsRouter = express.Router()
@@ -314,7 +313,7 @@ function insertIntoDB (parameters: {
   tags: string[]
   videoImportAttributes: Partial<MVideoImport>
   user: MUser
-}): Bluebird<MVideoImportFormattable> {
+}): Promise<MVideoImportFormattable> {
   const { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes, user } = parameters
 
   return sequelizeTypescript.transaction(async t => {

+ 3 - 3
server/helpers/actor.ts

@@ -1,10 +1,10 @@
+
 import { ActorModel } from '../models/activitypub/actor'
-import * as Bluebird from 'bluebird'
-import { MActorFull, MActorAccountChannelId } from '../types/models'
+import { MActorAccountChannelId, MActorFull } from '../types/models'
 
 type ActorFetchByUrlType = 'all' | 'association-ids'
 
-function fetchActorByUrl (url: string, fetchType: ActorFetchByUrlType): Bluebird<MActorFull | MActorAccountChannelId> {
+function fetchActorByUrl (url: string, fetchType: ActorFetchByUrlType): Promise<MActorFull | MActorAccountChannelId> {
   if (fetchType === 'all') return ActorModel.loadByUrlAndPopulateAccountAndChannel(url)
 
   if (fetchType === 'association-ids') return ActorModel.loadByUrl(url)

+ 3 - 4
server/helpers/middlewares/accounts.ts

@@ -1,9 +1,8 @@
 import { Response } from 'express'
-import { AccountModel } from '../../models/account/account'
-import * as Bluebird from 'bluebird'
-import { MAccountDefault } from '../../types/models'
 import { UserModel } from '@server/models/account/user'
 import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { AccountModel } from '../../models/account/account'
+import { MAccountDefault } from '../../types/models'
 
 function doesAccountIdExist (id: number | string, res: Response, sendNotFound = true) {
   const promise = AccountModel.load(parseInt(id + '', 10))
@@ -23,7 +22,7 @@ function doesAccountNameWithHostExist (nameWithDomain: string, res: Response, se
   return doesAccountExist(promise, res, sendNotFound)
 }
 
-async function doesAccountExist (p: Bluebird<MAccountDefault>, res: Response, sendNotFound: boolean) {
+async function doesAccountExist (p: Promise<MAccountDefault>, res: Response, sendNotFound: boolean) {
   const account = await p
 
   if (!account) {

+ 12 - 13
server/helpers/video.ts

@@ -1,4 +1,3 @@
-import * as Bluebird from 'bluebird'
 import { Response } from 'express'
 import { CONFIG } from '@server/initializers/config'
 import { DEFAULT_AUDIO_RESOLUTION } from '@server/initializers/constants'
@@ -20,21 +19,21 @@ import { VideoModel } from '../models/video/video'
 
 type VideoFetchType = 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none' | 'only-immutable-attributes'
 
-function fetchVideo (id: number | string, fetchType: 'all', userId?: number): Bluebird<MVideoFullLight>
-function fetchVideo (id: number | string, fetchType: 'only-immutable-attributes'): Bluebird<MVideoImmutable>
-function fetchVideo (id: number | string, fetchType: 'only-video', userId?: number): Bluebird<MVideoThumbnail>
-function fetchVideo (id: number | string, fetchType: 'only-video-with-rights', userId?: number): Bluebird<MVideoWithRights>
-function fetchVideo (id: number | string, fetchType: 'id' | 'none', userId?: number): Bluebird<MVideoIdThumbnail>
+function fetchVideo (id: number | string, fetchType: 'all', userId?: number): Promise<MVideoFullLight>
+function fetchVideo (id: number | string, fetchType: 'only-immutable-attributes'): Promise<MVideoImmutable>
+function fetchVideo (id: number | string, fetchType: 'only-video', userId?: number): Promise<MVideoThumbnail>
+function fetchVideo (id: number | string, fetchType: 'only-video-with-rights', userId?: number): Promise<MVideoWithRights>
+function fetchVideo (id: number | string, fetchType: 'id' | 'none', userId?: number): Promise<MVideoIdThumbnail>
 function fetchVideo (
   id: number | string,
   fetchType: VideoFetchType,
   userId?: number
-): Bluebird<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail | MVideoImmutable>
+): Promise<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail | MVideoImmutable>
 function fetchVideo (
   id: number | string,
   fetchType: VideoFetchType,
   userId?: number
-): Bluebird<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail | MVideoImmutable> {
+): Promise<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail | MVideoImmutable> {
   if (fetchType === 'all') return VideoModel.loadAndPopulateAccountAndServerAndTags(id, undefined, userId)
 
   if (fetchType === 'only-immutable-attributes') return VideoModel.loadImmutableAttributes(id)
@@ -48,17 +47,17 @@ function fetchVideo (
 
 type VideoFetchByUrlType = 'all' | 'only-video' | 'only-immutable-attributes'
 
-function fetchVideoByUrl (url: string, fetchType: 'all'): Bluebird<MVideoAccountLightBlacklistAllFiles>
-function fetchVideoByUrl (url: string, fetchType: 'only-immutable-attributes'): Bluebird<MVideoImmutable>
-function fetchVideoByUrl (url: string, fetchType: 'only-video'): Bluebird<MVideoThumbnail>
+function fetchVideoByUrl (url: string, fetchType: 'all'): Promise<MVideoAccountLightBlacklistAllFiles>
+function fetchVideoByUrl (url: string, fetchType: 'only-immutable-attributes'): Promise<MVideoImmutable>
+function fetchVideoByUrl (url: string, fetchType: 'only-video'): Promise<MVideoThumbnail>
 function fetchVideoByUrl (
   url: string,
   fetchType: VideoFetchByUrlType
-): Bluebird<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable>
+): Promise<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable>
 function fetchVideoByUrl (
   url: string,
   fetchType: VideoFetchByUrlType
-): Bluebird<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable> {
+): Promise<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable> {
   if (fetchType === 'all') return VideoModel.loadByUrlAndPopulateAccount(url)
 
   if (fetchType === 'only-immutable-attributes') return VideoModel.loadByUrlImmutableAttributes(url)

+ 0 - 1
server/initializers/migrations/0005-email-pod.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 import { Migration } from '../../models/migrations'
 
 function up (utils: {

+ 0 - 1
server/initializers/migrations/0010-email-user.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 import { Migration } from '../../models/migrations'
 
 function up (utils: {

+ 0 - 1
server/initializers/migrations/0015-video-views.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 
 function up (utils: {
   transaction: Sequelize.Transaction

+ 0 - 1
server/initializers/migrations/0020-video-likes.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 
 function up (utils: {
   transaction: Sequelize.Transaction

+ 0 - 1
server/initializers/migrations/0025-video-dislikes.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 
 function up (utils: {
   transaction: Sequelize.Transaction

+ 0 - 1
server/initializers/migrations/0030-video-category.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 import { Migration } from '../../models/migrations'
 
 function up (utils: {

+ 0 - 1
server/initializers/migrations/0035-video-licence.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 import { Migration } from '../../models/migrations'
 
 function up (utils: {

+ 0 - 1
server/initializers/migrations/0040-video-nsfw.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 import { Migration } from '../../models/migrations'
 
 function up (utils: {

+ 0 - 1
server/initializers/migrations/0045-user-display-nsfw.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 
 function up (utils: {
   transaction: Sequelize.Transaction

+ 0 - 1
server/initializers/migrations/0050-video-language.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 
 function up (utils: {
   transaction: Sequelize.Transaction

+ 0 - 1
server/initializers/migrations/0055-video-uuid.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 import { Migration } from '../../models/migrations'
 
 function up (utils: {

+ 0 - 1
server/initializers/migrations/0060-video-file.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 
 function up (utils: {
   transaction: Sequelize.Transaction

+ 0 - 1
server/initializers/migrations/0065-video-file-size.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 import { stat } from 'fs-extra'
 import { VideoModel } from '../../models/video/video'
 import { getVideoFilePath } from '@server/lib/video-paths'

+ 0 - 1
server/initializers/migrations/0070-user-video-quota.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 import { Migration } from '../../models/migrations'
 
 function up (utils: {

+ 0 - 1
server/initializers/migrations/0130-user-autoplay-video.ts

@@ -1,5 +1,4 @@
 import * as Sequelize from 'sequelize'
-import * as Promise from 'bluebird'
 
 function up (utils: {
   transaction: Sequelize.Transaction

+ 2 - 1
server/initializers/migrations/0150-avatar-cascade.ts

@@ -7,7 +7,8 @@ async function up (utils: {
 }): Promise<void> {
   await utils.queryInterface.removeConstraint('actor', 'actor_avatarId_fkey')
 
-  await utils.queryInterface.addConstraint('actor', [ 'avatarId' ], {
+  await utils.queryInterface.addConstraint('actor', {
+    fields: [ 'avatarId' ],
     type: 'foreign key',
     references: {
       table: 'avatar',

+ 2 - 1
server/initializers/migrations/0410-video-playlist-element.ts

@@ -18,7 +18,8 @@ async function up (utils: {
 
   await utils.queryInterface.removeConstraint('videoPlaylistElement', 'videoPlaylistElement_videoId_fkey')
 
-  await utils.queryInterface.addConstraint('videoPlaylistElement', [ 'videoId' ], {
+  await utils.queryInterface.addConstraint('videoPlaylistElement', {
+    fields: [ 'videoId' ],
     type: 'foreign key',
     references: {
       table: 'video',

+ 2 - 0
server/lib/activitypub/playlist.ts

@@ -99,6 +99,8 @@ async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAc
     return Promise.resolve()
   })
 
+  logger.info('toto', { playlist, id: playlist.id })
+
   const refreshedPlaylist = await VideoPlaylistModel.loadWithAccountAndChannel(playlist.id, null)
 
   if (playlistObject.icon) {

+ 1 - 1
server/lib/activitypub/process/process-dislike.ts

@@ -33,7 +33,7 @@ async function processDislike (activity: ActivityCreate | ActivityDislike, byAct
   const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: dislikeObject })
 
   return sequelizeTypescript.transaction(async t => {
-    const existingRate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byAccount.id, video.id, activity.id)
+    const existingRate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byAccount.id, video.id, activity.id, t)
     if (existingRate && existingRate.type === 'dislike') return
 
     await video.increment('dislikes', { transaction: t })

+ 1 - 1
server/lib/activitypub/process/process-like.ts

@@ -30,7 +30,7 @@ async function processLikeVideo (byActor: MActorSignature, activity: ActivityLik
   const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoUrl })
 
   return sequelizeTypescript.transaction(async t => {
-    const existingRate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byAccount.id, video.id, activity.id)
+    const existingRate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byAccount.id, video.id, activity.id, t)
     if (existingRate && existingRate.type === 'like') return
 
     if (existingRate && existingRate.type === 'dislike') {

+ 2 - 13
server/lib/activitypub/video-rates.ts

@@ -13,8 +13,6 @@ import { sendDislike } from './send/send-dislike'
 import { MAccountActor, MActorUrl, MVideo, MVideoAccountLight, MVideoId } from '../../types/models'
 
 async function createRates (ratesUrl: string[], video: MVideo, rate: VideoRateType) {
-  let rateCounts = 0
-
   await Bluebird.map(ratesUrl, async rateUrl => {
     try {
       // Fetch url
@@ -43,21 +41,12 @@ async function createRates (ratesUrl: string[], video: MVideo, rate: VideoRateTy
         url: body.id
       }
 
-      const created = await AccountVideoRateModel.upsert(entry)
-
-      if (created) rateCounts += 1
+      // Video "likes"/"dislikes" will be updated by the caller
+      await AccountVideoRateModel.upsert(entry)
     } catch (err) {
       logger.warn('Cannot add rate %s.', rateUrl, { err })
     }
   }, { concurrency: CRAWL_REQUEST_CONCURRENCY })
-
-  logger.info('Adding %d %s to video %s.', rateCounts, rate, video.uuid)
-
-  // This is "likes" and "dislikes"
-  if (rateCounts !== 0) {
-    const field = rate === 'like' ? 'likes' : 'dislikes'
-    await video.increment(field, { by: rateCounts })
-  }
 }
 
 async function sendVideoRateChange (

+ 3 - 0
server/lib/activitypub/videos.ts

@@ -352,6 +352,9 @@ async function updateVideoFromAP (options: {
       video.views = videoData.views
       video.isLive = videoData.isLive
 
+      // Ensures we update the updated video attribute
+      video.changed('updatedAt', true)
+
       const videoUpdated = await video.save(sequelizeOptions) as MVideoFullLight
 
       if (thumbnailModel) await videoUpdated.addAndSaveThumbnail(thumbnailModel, t)

+ 15 - 16
server/lib/client-html.ts

@@ -1,29 +1,28 @@
 import * as express from 'express'
-import * as Bluebird from 'bluebird'
+import { readFile } from 'fs-extra'
+import { join } from 'path'
+import validator from 'validator'
 import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n'
+import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
+import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos'
+import { escapeHTML, isTestInstance, sha256 } from '../helpers/core-utils'
+import { logger } from '../helpers/logger'
+import { CONFIG } from '../initializers/config'
 import {
+  ACCEPT_HEADERS,
   AVATARS_SIZE,
   CUSTOM_HTML_TAG_COMMENTS,
   EMBED_SIZE,
-  PLUGIN_GLOBAL_CSS_PATH,
-  WEBSERVER,
   FILES_CONTENT_HASH,
-  ACCEPT_HEADERS
+  PLUGIN_GLOBAL_CSS_PATH,
+  WEBSERVER
 } from '../initializers/constants'
-import { join } from 'path'
-import { escapeHTML, isTestInstance, sha256 } from '../helpers/core-utils'
-import { VideoModel } from '../models/video/video'
-import { VideoPlaylistModel } from '../models/video/video-playlist'
-import validator from 'validator'
-import { VideoPrivacy, VideoPlaylistPrivacy } from '../../shared/models/videos'
-import { readFile } from 'fs-extra'
-import { getActivityStreamDuration } from '../models/video/video-format-utils'
 import { AccountModel } from '../models/account/account'
+import { VideoModel } from '../models/video/video'
 import { VideoChannelModel } from '../models/video/video-channel'
-import { CONFIG } from '../initializers/config'
-import { logger } from '../helpers/logger'
+import { getActivityStreamDuration } from '../models/video/video-format-utils'
+import { VideoPlaylistModel } from '../models/video/video-playlist'
 import { MAccountActor, MChannelActor } from '../types/models'
-import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
 
 type Tags = {
   ogType: string
@@ -218,7 +217,7 @@ class ClientHtml {
   }
 
   private static async getAccountOrChannelHTMLPage (
-    loader: () => Bluebird<MAccountActor | MChannelActor>,
+    loader: () => Promise<MAccountActor | MChannelActor>,
     req: express.Request,
     res: express.Response
   ) {

+ 10 - 11
server/lib/job-queue/handlers/activitypub-http-fetcher.ts

@@ -1,19 +1,18 @@
 import * as Bull from 'bull'
-import * as Bluebird from 'bluebird'
+import { ActivitypubHttpFetcherPayload, FetchType } from '@shared/models'
 import { logger } from '../../../helpers/logger'
-import { processActivities } from '../../activitypub/process'
-import { addVideoComments } from '../../activitypub/video-comments'
-import { crawlCollectionPage } from '../../activitypub/crawl'
-import { VideoModel } from '../../../models/video/video'
-import { addVideoShares } from '../../activitypub/share'
-import { createRates } from '../../activitypub/video-rates'
-import { createAccountPlaylists } from '../../activitypub/playlist'
 import { AccountModel } from '../../../models/account/account'
 import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
-import { VideoShareModel } from '../../../models/video/video-share'
+import { VideoModel } from '../../../models/video/video'
 import { VideoCommentModel } from '../../../models/video/video-comment'
+import { VideoShareModel } from '../../../models/video/video-share'
 import { MAccountDefault, MVideoFullLight } from '../../../types/models'
-import { ActivitypubHttpFetcherPayload, FetchType } from '@shared/models'
+import { crawlCollectionPage } from '../../activitypub/crawl'
+import { createAccountPlaylists } from '../../activitypub/playlist'
+import { processActivities } from '../../activitypub/process'
+import { addVideoShares } from '../../activitypub/share'
+import { addVideoComments } from '../../activitypub/video-comments'
+import { createRates } from '../../activitypub/video-rates'
 
 async function processActivityPubHttpFetcher (job: Bull.Job) {
   logger.info('Processing ActivityPub fetcher in job %d.', job.id)
@@ -35,7 +34,7 @@ async function processActivityPubHttpFetcher (job: Bull.Job) {
     'account-playlists': items => createAccountPlaylists(items, account)
   }
 
-  const cleanerType: { [ id in FetchType ]?: (crawlStartDate: Date) => Bluebird<any> } = {
+  const cleanerType: { [ id in FetchType ]?: (crawlStartDate: Date) => Promise<any> } = {
     'video-likes': crawlStartDate => AccountVideoRateModel.cleanOldRatesOf(video.id, 'like' as 'like', crawlStartDate),
     'video-dislikes': crawlStartDate => AccountVideoRateModel.cleanOldRatesOf(video.id, 'dislike' as 'dislike', crawlStartDate),
     'video-shares': crawlStartDate => VideoShareModel.cleanOldSharesOf(video.id, crawlStartDate),

+ 0 - 1
server/lib/video-transcoding-profiles.ts

@@ -111,7 +111,6 @@ async function buildTargetBitrate (options: {
   input: string
   resolution: VideoResolution
   fps: number
-
 }) {
   const { input, resolution, fps } = options
   const probe = await ffprobePromise(input)

+ 12 - 13
server/middlewares/validators/users.ts

@@ -1,8 +1,14 @@
-import * as Bluebird from 'bluebird'
 import * as express from 'express'
 import { body, param, query } from 'express-validator'
 import { omit } from 'lodash'
+import { Hooks } from '@server/lib/plugins/hooks'
+import { MUserDefault } from '@server/types/models'
+import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { UserRole } from '../../../shared/models/users'
+import { UserRegister } from '../../../shared/models/users/user-register.model'
+import { isActorPreferredUsernameValid } from '../../helpers/custom-validators/activitypub/actor'
 import { isIdOrUUIDValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
+import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
 import {
   isNoInstanceConfigWarningModal,
   isNoWelcomeModal,
@@ -22,22 +28,15 @@ import {
   isUserVideoQuotaValid,
   isUserVideosHistoryEnabledValid
 } from '../../helpers/custom-validators/users'
+import { isVideoChannelNameValid } from '../../helpers/custom-validators/video-channels'
 import { logger } from '../../helpers/logger'
+import { doesVideoExist } from '../../helpers/middlewares'
 import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/signup'
+import { isThemeRegistered } from '../../lib/plugins/theme-utils'
 import { Redis } from '../../lib/redis'
 import { UserModel } from '../../models/account/user'
-import { areValidationErrors } from './utils'
 import { ActorModel } from '../../models/activitypub/actor'
-import { isActorPreferredUsernameValid } from '../../helpers/custom-validators/activitypub/actor'
-import { isVideoChannelNameValid } from '../../helpers/custom-validators/video-channels'
-import { UserRegister } from '../../../shared/models/users/user-register.model'
-import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
-import { isThemeRegistered } from '../../lib/plugins/theme-utils'
-import { doesVideoExist } from '../../helpers/middlewares'
-import { UserRole } from '../../../shared/models/users'
-import { MUserDefault } from '@server/types/models'
-import { Hooks } from '@server/lib/plugins/hooks'
-import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
+import { areValidationErrors } from './utils'
 
 const usersListValidator = [
   query('blocked')
@@ -529,7 +528,7 @@ async function checkUserNameOrEmailDoesNotAlreadyExist (username: string, email:
   return true
 }
 
-async function checkUserExist (finder: () => Bluebird<MUserDefault>, res: express.Response, abortResponse = true) {
+async function checkUserExist (finder: () => Promise<MUserDefault>, res: express.Response, abortResponse = true) {
   const user = await finder()
 
   if (!user) {

+ 3 - 3
server/models/abuse/abuse-message.ts

@@ -1,10 +1,10 @@
 import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
 import { isAbuseMessageValid } from '@server/helpers/custom-validators/abuses'
+import { MAbuseMessage, MAbuseMessageFormattable } from '@server/types/models'
 import { AbuseMessage } from '@shared/models'
 import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account'
-import { throwIfNotValid, getSort } from '../utils'
+import { getSort, throwIfNotValid } from '../utils'
 import { AbuseModel } from './abuse'
-import { MAbuseMessageFormattable, MAbuseMessage } from '@server/types/models'
 
 @Table({
   tableName: 'abuseMessage',
@@ -17,7 +17,7 @@ import { MAbuseMessageFormattable, MAbuseMessage } from '@server/types/models'
     }
   ]
 })
-export class AbuseMessageModel extends Model<AbuseMessageModel> {
+export class AbuseMessageModel extends Model {
 
   @AllowNull(false)
   @Is('AbuseMessage', value => throwIfNotValid(value, isAbuseMessageValid, 'message'))

+ 3 - 4
server/models/abuse/abuse.ts

@@ -1,4 +1,3 @@
-import * as Bluebird from 'bluebird'
 import { invert } from 'lodash'
 import { literal, Op, QueryTypes } from 'sequelize'
 import {
@@ -188,7 +187,7 @@ export enum ScopeNames {
     }
   ]
 })
-export class AbuseModel extends Model<AbuseModel> {
+export class AbuseModel extends Model {
 
   @AllowNull(false)
   @Default(null)
@@ -265,7 +264,7 @@ export class AbuseModel extends Model<AbuseModel> {
   })
   VideoAbuse: VideoAbuseModel
 
-  static loadByIdWithReporter (id: number): Bluebird<MAbuseReporter> {
+  static loadByIdWithReporter (id: number): Promise<MAbuseReporter> {
     const query = {
       where: {
         id
@@ -281,7 +280,7 @@ export class AbuseModel extends Model<AbuseModel> {
     return AbuseModel.findOne(query)
   }
 
-  static loadFull (id: number): Bluebird<MAbuseFull> {
+  static loadFull (id: number): Promise<MAbuseFull> {
     const query = {
       where: {
         id

+ 1 - 1
server/models/abuse/video-abuse.ts

@@ -14,7 +14,7 @@ import { AbuseModel } from './abuse'
     }
   ]
 })
-export class VideoAbuseModel extends Model<VideoAbuseModel> {
+export class VideoAbuseModel extends Model {
 
   @CreatedAt
   createdAt: Date

+ 1 - 1
server/models/abuse/video-comment-abuse.ts

@@ -13,7 +13,7 @@ import { AbuseModel } from './abuse'
     }
   ]
 })
-export class VideoCommentAbuseModel extends Model<VideoCommentAbuseModel> {
+export class VideoCommentAbuseModel extends Model {
 
   @CreatedAt
   createdAt: Date

+ 4 - 5
server/models/account/account-blocklist.ts

@@ -1,4 +1,3 @@
-import * as Bluebird from 'bluebird'
 import { Op } from 'sequelize'
 import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
 import { MAccountBlocklist, MAccountBlocklistAccounts, MAccountBlocklistFormattable } from '@server/types/models'
@@ -41,7 +40,7 @@ enum ScopeNames {
     }
   ]
 })
-export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
+export class AccountBlocklistModel extends Model {
 
   @CreatedAt
   createdAt: Date
@@ -102,7 +101,7 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
                                 })
   }
 
-  static loadByAccountAndTarget (accountId: number, targetAccountId: number): Bluebird<MAccountBlocklist> {
+  static loadByAccountAndTarget (accountId: number, targetAccountId: number): Promise<MAccountBlocklist> {
     const query = {
       where: {
         accountId,
@@ -151,9 +150,9 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
       })
   }
 
-  static listHandlesBlockedBy (accountIds: number[]): Bluebird<string[]> {
+  static listHandlesBlockedBy (accountIds: number[]): Promise<string[]> {
     const query = {
-      attributes: [],
+      attributes: [ 'id' ],
       where: {
         accountId: {
           [Op.in]: accountIds

+ 29 - 24
server/models/account/account-video-rate.ts

@@ -1,22 +1,21 @@
 import { values } from 'lodash'
-import { FindOptions, Op, Transaction } from 'sequelize'
+import { FindOptions, Op, QueryTypes, Transaction } from 'sequelize'
 import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
-import { VideoRateType } from '../../../shared/models/videos'
-import { CONSTRAINTS_FIELDS, VIDEO_RATE_TYPES } from '../../initializers/constants'
-import { VideoModel } from '../video/video'
-import { AccountModel } from './account'
-import { ActorModel } from '../activitypub/actor'
-import { buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils'
-import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
-import { AccountVideoRate } from '../../../shared'
-import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from '../video/video-channel'
-import * as Bluebird from 'bluebird'
 import {
   MAccountVideoRate,
   MAccountVideoRateAccountUrl,
   MAccountVideoRateAccountVideo,
   MAccountVideoRateFormattable
 } from '@server/types/models/video/video-rate'
+import { AccountVideoRate } from '../../../shared'
+import { VideoRateType } from '../../../shared/models/videos'
+import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
+import { CONSTRAINTS_FIELDS, VIDEO_RATE_TYPES } from '../../initializers/constants'
+import { ActorModel } from '../activitypub/actor'
+import { buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils'
+import { VideoModel } from '../video/video'
+import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from '../video/video-channel'
+import { AccountModel } from './account'
 
 /*
   Account rates per video.
@@ -43,7 +42,7 @@ import {
     }
   ]
 })
-export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
+export class AccountVideoRateModel extends Model {
 
   @AllowNull(false)
   @Column(DataType.ENUM(...values(VIDEO_RATE_TYPES)))
@@ -84,7 +83,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
   })
   Account: AccountModel
 
-  static load (accountId: number, videoId: number, transaction?: Transaction): Bluebird<MAccountVideoRate> {
+  static load (accountId: number, videoId: number, transaction?: Transaction): Promise<MAccountVideoRate> {
     const options: FindOptions = {
       where: {
         accountId,
@@ -96,7 +95,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
     return AccountVideoRateModel.findOne(options)
   }
 
-  static loadByAccountAndVideoOrUrl (accountId: number, videoId: number, url: string, t?: Transaction): Bluebird<MAccountVideoRate> {
+  static loadByAccountAndVideoOrUrl (accountId: number, videoId: number, url: string, t?: Transaction): Promise<MAccountVideoRate> {
     const options: FindOptions = {
       where: {
         [Op.or]: [
@@ -152,7 +151,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
     accountName: string,
     videoId: number | string,
     t?: Transaction
-  ): Bluebird<MAccountVideoRateAccountVideo> {
+  ): Promise<MAccountVideoRateAccountVideo> {
     const options: FindOptions = {
       where: {
         videoId,
@@ -240,17 +239,23 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
         transaction: t
       }
 
-      const deleted = await AccountVideoRateModel.destroy(query)
+      await AccountVideoRateModel.destroy(query)
 
-      const options = {
-        transaction: t,
-        where: {
-          id: videoId
-        }
-      }
+      const field = type === 'like'
+        ? 'likes'
+        : 'dislikes'
+
+      const rawQuery = `UPDATE "video" SET "${field}" = ` +
+        '(' +
+          'SELECT COUNT(id) FROM "accountVideoRate" WHERE "accountVideoRate"."videoId" = "video"."id" AND type = :rateType' +
+        ') ' +
+        'WHERE "video"."id" = :videoId'
 
-      if (type === 'like') await VideoModel.increment({ likes: -deleted }, options)
-      else if (type === 'dislike') await VideoModel.increment({ dislikes: -deleted }, options)
+      return AccountVideoRateModel.sequelize.query(rawQuery, {
+        transaction: t,
+        replacements: { videoId, rateType: type },
+        type: QueryTypes.UPDATE
+      })
     })
   }
 

+ 30 - 28
server/models/account/account.ts

@@ -1,5 +1,4 @@
-import * as Bluebird from 'bluebird'
-import { FindOptions, IncludeOptions, Op, Transaction, WhereOptions } from 'sequelize'
+import { FindOptions, Includeable, IncludeOptions, Op, Transaction, WhereOptions } from 'sequelize'
 import {
   AllowNull,
   BeforeDestroy,
@@ -73,28 +72,29 @@ export type SummaryOptions = {
       required: false
     }
 
-    const query: FindOptions = {
-      attributes: [ 'id', 'name', 'actorId' ],
-      include: [
-        {
-          attributes: [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ],
-          model: ActorModel.unscoped(),
-          required: options.actorRequired ?? true,
-          where: whereActor,
-          include: [
-            serverInclude,
+    const queryInclude: Includeable[] = [
+      {
+        attributes: [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ],
+        model: ActorModel.unscoped(),
+        required: options.actorRequired ?? true,
+        where: whereActor,
+        include: [
+          serverInclude,
 
-            {
-              model: AvatarModel.unscoped(),
-              required: false
-            }
-          ]
-        }
-      ]
+          {
+            model: AvatarModel.unscoped(),
+            required: false
+          }
+        ]
+      }
+    ]
+
+    const query: FindOptions = {
+      attributes: [ 'id', 'name', 'actorId' ]
     }
 
     if (options.withAccountBlockerIds) {
-      query.include.push({
+      queryInclude.push({
         attributes: [ 'id' ],
         model: AccountBlocklistModel.unscoped(),
         as: 'BlockedAccounts',
@@ -120,6 +120,8 @@ export type SummaryOptions = {
       ]
     }
 
+    query.include = queryInclude
+
     return query
   }
 }))
@@ -138,7 +140,7 @@ export type SummaryOptions = {
     }
   ]
 })
-export class AccountModel extends Model<AccountModel> {
+export class AccountModel extends Model {
 
   @AllowNull(false)
   @Column
@@ -244,11 +246,11 @@ export class AccountModel extends Model<AccountModel> {
     return undefined
   }
 
-  static load (id: number, transaction?: Transaction): Bluebird<MAccountDefault> {
+  static load (id: number, transaction?: Transaction): Promise<MAccountDefault> {
     return AccountModel.findByPk(id, { transaction })
   }
 
-  static loadByNameWithHost (nameWithHost: string): Bluebird<MAccountDefault> {
+  static loadByNameWithHost (nameWithHost: string): Promise<MAccountDefault> {
     const [ accountName, host ] = nameWithHost.split('@')
 
     if (!host || host === WEBSERVER.HOST) return AccountModel.loadLocalByName(accountName)
@@ -256,7 +258,7 @@ export class AccountModel extends Model<AccountModel> {
     return AccountModel.loadByNameAndHost(accountName, host)
   }
 
-  static loadLocalByName (name: string): Bluebird<MAccountDefault> {
+  static loadLocalByName (name: string): Promise<MAccountDefault> {
     const fun = () => {
       const query = {
         where: {
@@ -296,7 +298,7 @@ export class AccountModel extends Model<AccountModel> {
     })
   }
 
-  static loadByNameAndHost (name: string, host: string): Bluebird<MAccountDefault> {
+  static loadByNameAndHost (name: string, host: string): Promise<MAccountDefault> {
     const query = {
       include: [
         {
@@ -321,7 +323,7 @@ export class AccountModel extends Model<AccountModel> {
     return AccountModel.findOne(query)
   }
 
-  static loadByUrl (url: string, transaction?: Transaction): Bluebird<MAccountDefault> {
+  static loadByUrl (url: string, transaction?: Transaction): Promise<MAccountDefault> {
     const query = {
       include: [
         {
@@ -354,7 +356,7 @@ export class AccountModel extends Model<AccountModel> {
       })
   }
 
-  static loadAccountIdFromVideo (videoId: number): Bluebird<MAccount> {
+  static loadAccountIdFromVideo (videoId: number): Promise<MAccount> {
     const query = {
       include: [
         {
@@ -377,7 +379,7 @@ export class AccountModel extends Model<AccountModel> {
     return AccountModel.findOne(query)
   }
 
-  static listLocalsForSitemap (sort: string): Bluebird<MAccountActor[]> {
+  static listLocalsForSitemap (sort: string): Promise<MAccountActor[]> {
     const query = {
       attributes: [ ],
       offset: 0,

+ 1 - 1
server/models/account/user-notification-setting.ts

@@ -28,7 +28,7 @@ import { UserModel } from './user'
     }
   ]
 })
-export class UserNotificationSettingModel extends Model<UserNotificationSettingModel> {
+export class UserNotificationSettingModel extends Model {
 
   @AllowNull(false)
   @Default(null)

+ 1 - 1
server/models/account/user-notification.ts

@@ -254,7 +254,7 @@ function buildAccountInclude (required: boolean, withActor = false) {
     }
   ] as (ModelIndexesOptions & { where?: WhereOptions })[]
 })
-export class UserNotificationModel extends Model<UserNotificationModel> {
+export class UserNotificationModel extends Model {
 
   @AllowNull(false)
   @Default(null)

+ 1 - 1
server/models/account/user-video-history.ts

@@ -19,7 +19,7 @@ import { MUserAccountId, MUserId } from '@server/types/models'
     }
   ]
 })
-export class UserVideoHistoryModel extends Model<UserVideoHistoryModel> {
+export class UserVideoHistoryModel extends Model {
   @CreatedAt
   createdAt: Date
 

+ 17 - 18
server/models/account/user.ts

@@ -1,4 +1,3 @@
-import * as Bluebird from 'bluebird'
 import { values } from 'lodash'
 import { col, FindOptions, fn, literal, Op, QueryTypes, where, WhereOptions } from 'sequelize'
 import {
@@ -16,11 +15,11 @@ import {
   HasOne,
   Is,
   IsEmail,
+  IsUUID,
   Model,
   Scopes,
   Table,
-  UpdatedAt,
-  IsUUID
+  UpdatedAt
 } from 'sequelize-typescript'
 import {
   MMyUserFormattable,
@@ -220,7 +219,7 @@ enum ScopeNames {
     }
   ]
 })
-export class UserModel extends Model<UserModel> {
+export class UserModel extends Model {
 
   @AllowNull(true)
   @Is('UserPassword', value => throwIfNotValid(value, isUserPasswordValid, 'user password', true))
@@ -483,7 +482,7 @@ export class UserModel extends Model<UserModel> {
                     })
   }
 
-  static listWithRight (right: UserRight): Bluebird<MUserDefault[]> {
+  static listWithRight (right: UserRight): Promise<MUserDefault[]> {
     const roles = Object.keys(USER_ROLE_LABELS)
                         .map(k => parseInt(k, 10) as UserRole)
                         .filter(role => hasUserRight(role, right))
@@ -499,7 +498,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findAll(query)
   }
 
-  static listUserSubscribersOf (actorId: number): Bluebird<MUserWithNotificationSetting[]> {
+  static listUserSubscribersOf (actorId: number): Promise<MUserWithNotificationSetting[]> {
     const query = {
       include: [
         {
@@ -538,7 +537,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.unscoped().findAll(query)
   }
 
-  static listByUsernames (usernames: string[]): Bluebird<MUserDefault[]> {
+  static listByUsernames (usernames: string[]): Promise<MUserDefault[]> {
     const query = {
       where: {
         username: usernames
@@ -548,11 +547,11 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findAll(query)
   }
 
-  static loadById (id: number): Bluebird<MUser> {
+  static loadById (id: number): Promise<MUser> {
     return UserModel.unscoped().findByPk(id)
   }
 
-  static loadByIdWithChannels (id: number, withStats = false): Bluebird<MUserDefault> {
+  static loadByIdWithChannels (id: number, withStats = false): Promise<MUserDefault> {
     const scopes = [
       ScopeNames.WITH_VIDEOCHANNELS
     ]
@@ -562,7 +561,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.scope(scopes).findByPk(id)
   }
 
-  static loadByUsername (username: string): Bluebird<MUserDefault> {
+  static loadByUsername (username: string): Promise<MUserDefault> {
     const query = {
       where: {
         username: { [Op.iLike]: username }
@@ -572,7 +571,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadForMeAPI (username: string): Bluebird<MUserNotifSettingChannelDefault> {
+  static loadForMeAPI (username: string): Promise<MUserNotifSettingChannelDefault> {
     const query = {
       where: {
         username: { [Op.iLike]: username }
@@ -582,7 +581,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.scope(ScopeNames.FOR_ME_API).findOne(query)
   }
 
-  static loadByEmail (email: string): Bluebird<MUserDefault> {
+  static loadByEmail (email: string): Promise<MUserDefault> {
     const query = {
       where: {
         email
@@ -592,7 +591,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadByUsernameOrEmail (username: string, email?: string): Bluebird<MUserDefault> {
+  static loadByUsernameOrEmail (username: string, email?: string): Promise<MUserDefault> {
     if (!email) email = username
 
     const query = {
@@ -608,7 +607,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadByVideoId (videoId: number): Bluebird<MUserDefault> {
+  static loadByVideoId (videoId: number): Promise<MUserDefault> {
     const query = {
       include: [
         {
@@ -639,7 +638,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadByVideoImportId (videoImportId: number): Bluebird<MUserDefault> {
+  static loadByVideoImportId (videoImportId: number): Promise<MUserDefault> {
     const query = {
       include: [
         {
@@ -656,7 +655,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadByChannelActorId (videoChannelActorId: number): Bluebird<MUserDefault> {
+  static loadByChannelActorId (videoChannelActorId: number): Promise<MUserDefault> {
     const query = {
       include: [
         {
@@ -680,7 +679,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadByAccountActorId (accountActorId: number): Bluebird<MUserDefault> {
+  static loadByAccountActorId (accountActorId: number): Promise<MUserDefault> {
     const query = {
       include: [
         {
@@ -697,7 +696,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadByLiveId (liveId: number): Bluebird<MUser> {
+  static loadByLiveId (liveId: number): Promise<MUser> {
     const query = {
       include: [
         {

+ 6 - 7
server/models/activitypub/actor-follow.ts

@@ -1,4 +1,3 @@
-import * as Bluebird from 'bluebird'
 import { difference, values } from 'lodash'
 import { IncludeOptions, Op, QueryTypes, Transaction, WhereOptions } from 'sequelize'
 import {
@@ -62,7 +61,7 @@ import { ActorModel, unusedActorAttributesForAPI } from './actor'
     }
   ]
 })
-export class ActorFollowModel extends Model<ActorFollowModel> {
+export class ActorFollowModel extends Model {
 
   @AllowNull(false)
   @Column(DataType.ENUM(...values(FOLLOW_STATES)))
@@ -176,7 +175,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
                      .then(results => results.length === 1)
   }
 
-  static loadByActorAndTarget (actorId: number, targetActorId: number, t?: Transaction): Bluebird<MActorFollowActorsDefault> {
+  static loadByActorAndTarget (actorId: number, targetActorId: number, t?: Transaction): Promise<MActorFollowActorsDefault> {
     const query = {
       where: {
         actorId,
@@ -205,7 +204,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
     targetName: string,
     targetHost: string,
     t?: Transaction
-  ): Bluebird<MActorFollowActorsDefaultSubscription> {
+  ): Promise<MActorFollowActorsDefaultSubscription> {
     const actorFollowingPartInclude: IncludeOptions = {
       model: ActorModel,
       required: true,
@@ -258,7 +257,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
       })
   }
 
-  static listSubscribedIn (actorId: number, targets: { name: string, host?: string }[]): Bluebird<MActorFollowFollowingHost[]> {
+  static listSubscribedIn (actorId: number, targets: { name: string, host?: string }[]): Promise<MActorFollowFollowingHost[]> {
     const whereTab = targets
       .map(t => {
         if (t.host) {
@@ -287,7 +286,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
       })
 
     const query = {
-      attributes: [],
+      attributes: [ 'id' ],
       where: {
         [Op.and]: [
           {
@@ -671,7 +670,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
 
     selections.push('COUNT(*) AS "total"')
 
-    const tasks: Bluebird<any>[] = []
+    const tasks: Promise<any>[] = []
 
     for (const selection of selections) {
       let query = 'SELECT ' + selection + ' FROM "actor" ' +

+ 22 - 22
server/models/activitypub/actor.ts

@@ -1,5 +1,6 @@
 import { values } from 'lodash'
 import { extname } from 'path'
+import { literal, Op, Transaction } from 'sequelize'
 import {
   AllowNull,
   BelongsTo,
@@ -16,6 +17,7 @@ import {
   Table,
   UpdatedAt
 } from 'sequelize-typescript'
+import { ModelCache } from '@server/models/model-cache'
 import { ActivityIconObject, ActivityPubActorType } from '../../../shared/models/activitypub'
 import { Avatar } from '../../../shared/models/avatars/avatar.model'
 import { activityPubContextify } from '../../helpers/activitypub'
@@ -28,13 +30,6 @@ import {
 } from '../../helpers/custom-validators/activitypub/actor'
 import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
 import { ACTIVITY_PUB, ACTIVITY_PUB_ACTOR_TYPES, CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants'
-import { AccountModel } from '../account/account'
-import { AvatarModel } from '../avatar/avatar'
-import { ServerModel } from '../server/server'
-import { isOutdated, throwIfNotValid } from '../utils'
-import { VideoChannelModel } from '../video/video-channel'
-import { ActorFollowModel } from './actor-follow'
-import { VideoModel } from '../video/video'
 import {
   MActor,
   MActorAccountChannelId,
@@ -43,12 +38,17 @@ import {
   MActorFull,
   MActorHost,
   MActorServer,
-  MActorSummaryFormattable, MActorUrl,
+  MActorSummaryFormattable,
+  MActorUrl,
   MActorWithInboxes
 } from '../../types/models'
-import * as Bluebird from 'bluebird'
-import { Op, Transaction, literal } from 'sequelize'
-import { ModelCache } from '@server/models/model-cache'
+import { AccountModel } from '../account/account'
+import { AvatarModel } from '../avatar/avatar'
+import { ServerModel } from '../server/server'
+import { isOutdated, throwIfNotValid } from '../utils'
+import { VideoModel } from '../video/video'
+import { VideoChannelModel } from '../video/video-channel'
+import { ActorFollowModel } from './actor-follow'
 
 enum ScopeNames {
   FULL = 'FULL'
@@ -146,7 +146,7 @@ export const unusedActorAttributesForAPI = [
     }
   ]
 })
-export class ActorModel extends Model<ActorModel> {
+export class ActorModel extends Model {
 
   @AllowNull(false)
   @Column(DataType.ENUM(...values(ACTIVITY_PUB_ACTOR_TYPES)))
@@ -276,15 +276,15 @@ export class ActorModel extends Model<ActorModel> {
   })
   VideoChannel: VideoChannelModel
 
-  static load (id: number): Bluebird<MActor> {
+  static load (id: number): Promise<MActor> {
     return ActorModel.unscoped().findByPk(id)
   }
 
-  static loadFull (id: number): Bluebird<MActorFull> {
+  static loadFull (id: number): Promise<MActorFull> {
     return ActorModel.scope(ScopeNames.FULL).findByPk(id)
   }
 
-  static loadFromAccountByVideoId (videoId: number, transaction: Transaction): Bluebird<MActor> {
+  static loadFromAccountByVideoId (videoId: number, transaction: Transaction): Promise<MActor> {
     const query = {
       include: [
         {
@@ -328,7 +328,7 @@ export class ActorModel extends Model<ActorModel> {
       .then(a => !!a)
   }
 
-  static listByFollowersUrls (followersUrls: string[], transaction?: Transaction): Bluebird<MActorFull[]> {
+  static listByFollowersUrls (followersUrls: string[], transaction?: Transaction): Promise<MActorFull[]> {
     const query = {
       where: {
         followersUrl: {
@@ -341,7 +341,7 @@ export class ActorModel extends Model<ActorModel> {
     return ActorModel.scope(ScopeNames.FULL).findAll(query)
   }
 
-  static loadLocalByName (preferredUsername: string, transaction?: Transaction): Bluebird<MActorFull> {
+  static loadLocalByName (preferredUsername: string, transaction?: Transaction): Promise<MActorFull> {
     const fun = () => {
       const query = {
         where: {
@@ -364,7 +364,7 @@ export class ActorModel extends Model<ActorModel> {
     })
   }
 
-  static loadLocalUrlByName (preferredUsername: string, transaction?: Transaction): Bluebird<MActorUrl> {
+  static loadLocalUrlByName (preferredUsername: string, transaction?: Transaction): Promise<MActorUrl> {
     const fun = () => {
       const query = {
         attributes: [ 'url' ],
@@ -388,7 +388,7 @@ export class ActorModel extends Model<ActorModel> {
     })
   }
 
-  static loadByNameAndHost (preferredUsername: string, host: string): Bluebird<MActorFull> {
+  static loadByNameAndHost (preferredUsername: string, host: string): Promise<MActorFull> {
     const query = {
       where: {
         preferredUsername
@@ -407,7 +407,7 @@ export class ActorModel extends Model<ActorModel> {
     return ActorModel.scope(ScopeNames.FULL).findOne(query)
   }
 
-  static loadByUrl (url: string, transaction?: Transaction): Bluebird<MActorAccountChannelId> {
+  static loadByUrl (url: string, transaction?: Transaction): Promise<MActorAccountChannelId> {
     const query = {
       where: {
         url
@@ -430,7 +430,7 @@ export class ActorModel extends Model<ActorModel> {
     return ActorModel.unscoped().findOne(query)
   }
 
-  static loadByUrlAndPopulateAccountAndChannel (url: string, transaction?: Transaction): Bluebird<MActorFull> {
+  static loadByUrlAndPopulateAccountAndChannel (url: string, transaction?: Transaction): Promise<MActorFull> {
     const query = {
       where: {
         url
@@ -461,7 +461,7 @@ export class ActorModel extends Model<ActorModel> {
     }, { where, transaction })
   }
 
-  static loadAccountActorByVideoId (videoId: number): Bluebird<MActor> {
+  static loadAccountActorByVideoId (videoId: number): Promise<MActor> {
     const query = {
       include: [
         {

+ 1 - 1
server/models/application/application.ts

@@ -24,7 +24,7 @@ export const getServerActor = memoizee(async function () {
   tableName: 'application',
   timestamps: false
 })
-export class ApplicationModel extends Model<ApplicationModel> {
+export class ApplicationModel extends Model {
 
   @AllowNull(false)
   @Default(0)

+ 1 - 1
server/models/avatar/avatar.ts

@@ -18,7 +18,7 @@ import { MAvatarFormattable } from '@server/types/models'
     }
   ]
 })
-export class AvatarModel extends Model<AvatarModel> {
+export class AvatarModel extends Model {
 
   @AllowNull(false)
   @Column

+ 1 - 1
server/models/model-cache.ts

@@ -40,7 +40,7 @@ class ModelCache {
   doCache<T extends Model> (options: {
     cacheType: ModelCacheType
     key: string
-    fun: () => Bluebird<T>
+    fun: () => Promise<T>
     whitelist?: () => boolean
     deleteKey?: DeleteKey
   }) {

+ 1 - 1
server/models/oauth/oauth-client.ts

@@ -14,7 +14,7 @@ import { OAuthTokenModel } from './oauth-token'
     }
   ]
 })
-export class OAuthClientModel extends Model<OAuthClientModel> {
+export class OAuthClientModel extends Model {
 
   @AllowNull(false)
   @Column

+ 8 - 9
server/models/oauth/oauth-token.ts

@@ -1,3 +1,4 @@
+import { Transaction } from 'sequelize'
 import {
   AfterDestroy,
   AfterUpdate,
@@ -11,15 +12,13 @@ import {
   Table,
   UpdatedAt
 } from 'sequelize-typescript'
+import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token'
 import { logger } from '../../helpers/logger'
-import { UserModel } from '../account/user'
-import { OAuthClientModel } from './oauth-client'
-import { Transaction } from 'sequelize'
+import { clearCacheByToken } from '../../lib/oauth-model'
 import { AccountModel } from '../account/account'
+import { UserModel } from '../account/user'
 import { ActorModel } from '../activitypub/actor'
-import { clearCacheByToken } from '../../lib/oauth-model'
-import * as Bluebird from 'bluebird'
-import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token'
+import { OAuthClientModel } from './oauth-client'
 
 export type OAuthTokenInfo = {
   refreshToken: string
@@ -80,7 +79,7 @@ enum ScopeNames {
     }
   ]
 })
-export class OAuthTokenModel extends Model<OAuthTokenModel> {
+export class OAuthTokenModel extends Model {
 
   @AllowNull(false)
   @Column
@@ -174,7 +173,7 @@ export class OAuthTokenModel extends Model<OAuthTokenModel> {
                           })
   }
 
-  static getByTokenAndPopulateUser (bearerToken: string): Bluebird<MOAuthTokenUser> {
+  static getByTokenAndPopulateUser (bearerToken: string): Promise<MOAuthTokenUser> {
     const query = {
       where: {
         accessToken: bearerToken
@@ -190,7 +189,7 @@ export class OAuthTokenModel extends Model<OAuthTokenModel> {
                           })
   }
 
-  static getByRefreshTokenAndPopulateUser (refreshToken: string): Bluebird<MOAuthTokenUser> {
+  static getByRefreshTokenAndPopulateUser (refreshToken: string): Promise<MOAuthTokenUser> {
     const query = {
       where: {
         refreshToken

+ 22 - 23
server/models/redundancy/video-redundancy.ts

@@ -1,3 +1,5 @@
+import { sample } from 'lodash'
+import { col, FindOptions, fn, literal, Op, Transaction, WhereOptions } from 'sequelize'
 import {
   AllowNull,
   BeforeDestroy,
@@ -12,23 +14,7 @@ import {
   Table,
   UpdatedAt
 } from 'sequelize-typescript'
-import { ActorModel } from '../activitypub/actor'
-import { getSort, getVideoSort, parseAggregateResult, throwIfNotValid } from '../utils'
-import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc'
-import { CONSTRAINTS_FIELDS, MIMETYPES } from '../../initializers/constants'
-import { VideoFileModel } from '../video/video-file'
-import { VideoModel } from '../video/video'
-import { VideoRedundancyStrategy, VideoRedundancyStrategyWithManual } from '../../../shared/models/redundancy'
-import { logger } from '../../helpers/logger'
-import { CacheFileObject, VideoPrivacy } from '../../../shared'
-import { VideoChannelModel } from '../video/video-channel'
-import { ServerModel } from '../server/server'
-import { sample } from 'lodash'
-import { isTestInstance } from '../../helpers/core-utils'
-import * as Bluebird from 'bluebird'
-import { col, FindOptions, fn, literal, Op, Transaction, WhereOptions } from 'sequelize'
-import { VideoStreamingPlaylistModel } from '../video/video-streaming-playlist'
-import { CONFIG } from '../../initializers/config'
+import { getServerActor } from '@server/models/application/application'
 import { MVideoForRedundancyAPI, MVideoRedundancy, MVideoRedundancyAP, MVideoRedundancyVideo } from '@server/types/models'
 import { VideoRedundanciesTarget } from '@shared/models/redundancy/video-redundancies-filters.model'
 import {
@@ -36,7 +22,20 @@ import {
   StreamingPlaylistRedundancyInformation,
   VideoRedundancy
 } from '@shared/models/redundancy/video-redundancy.model'
-import { getServerActor } from '@server/models/application/application'
+import { CacheFileObject, VideoPrivacy } from '../../../shared'
+import { VideoRedundancyStrategy, VideoRedundancyStrategyWithManual } from '../../../shared/models/redundancy'
+import { isTestInstance } from '../../helpers/core-utils'
+import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc'
+import { logger } from '../../helpers/logger'
+import { CONFIG } from '../../initializers/config'
+import { CONSTRAINTS_FIELDS, MIMETYPES } from '../../initializers/constants'
+import { ActorModel } from '../activitypub/actor'
+import { ServerModel } from '../server/server'
+import { getSort, getVideoSort, parseAggregateResult, throwIfNotValid } from '../utils'
+import { VideoModel } from '../video/video'
+import { VideoChannelModel } from '../video/video-channel'
+import { VideoFileModel } from '../video/video-file'
+import { VideoStreamingPlaylistModel } from '../video/video-streaming-playlist'
 
 export enum ScopeNames {
   WITH_VIDEO = 'WITH_VIDEO'
@@ -84,7 +83,7 @@ export enum ScopeNames {
     }
   ]
 })
-export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
+export class VideoRedundancyModel extends Model {
 
   @CreatedAt
   createdAt: Date
@@ -199,7 +198,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
     return VideoRedundancyModel.scope(ScopeNames.WITH_VIDEO).findOne(query)
   }
 
-  static loadByIdWithVideo (id: number, transaction?: Transaction): Bluebird<MVideoRedundancyVideo> {
+  static loadByIdWithVideo (id: number, transaction?: Transaction): Promise<MVideoRedundancyVideo> {
     const query = {
       where: { id },
       transaction
@@ -208,7 +207,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
     return VideoRedundancyModel.scope(ScopeNames.WITH_VIDEO).findOne(query)
   }
 
-  static loadByUrl (url: string, transaction?: Transaction): Bluebird<MVideoRedundancy> {
+  static loadByUrl (url: string, transaction?: Transaction): Promise<MVideoRedundancy> {
     const query = {
       where: {
         url
@@ -251,7 +250,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
                                .then(r => !!r)
   }
 
-  static async getVideoSample (p: Bluebird<VideoModel[]>) {
+  static async getVideoSample (p: Promise<VideoModel[]>) {
     const rows = await p
     if (rows.length === 0) return undefined
 
@@ -696,7 +695,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
 
     const notIn = literal(
       '(' +
-      `SELECT "videoFileId" FROM "videoRedundancy" WHERE "actorId" = ${actor.id} AND "videoFileId" IS NOT NULL` +
+        `SELECT "videoFileId" FROM "videoRedundancy" WHERE "actorId" = ${actor.id} AND "videoFileId" IS NOT NULL` +
       ')'
     )
 

+ 4 - 5
server/models/server/plugin.ts

@@ -1,4 +1,3 @@
-import * as Bluebird from 'bluebird'
 import { FindAndCountOptions, json, QueryTypes } from 'sequelize'
 import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
 import { MPlugin, MPluginFormattable } from '@server/types/models'
@@ -29,7 +28,7 @@ import { getSort, throwIfNotValid } from '../utils'
     }
   ]
 })
-export class PluginModel extends Model<PluginModel> {
+export class PluginModel extends Model {
 
   @AllowNull(false)
   @Is('PluginName', value => throwIfNotValid(value, isPluginNameValid, 'name'))
@@ -87,7 +86,7 @@ export class PluginModel extends Model<PluginModel> {
   @UpdatedAt
   updatedAt: Date
 
-  static listEnabledPluginsAndThemes (): Bluebird<MPlugin[]> {
+  static listEnabledPluginsAndThemes (): Promise<MPlugin[]> {
     const query = {
       where: {
         enabled: true,
@@ -98,7 +97,7 @@ export class PluginModel extends Model<PluginModel> {
     return PluginModel.findAll(query)
   }
 
-  static loadByNpmName (npmName: string): Bluebird<MPlugin> {
+  static loadByNpmName (npmName: string): Promise<MPlugin> {
     const name = this.normalizePluginName(npmName)
     const type = this.getTypeFromNpmName(npmName)
 
@@ -252,7 +251,7 @@ export class PluginModel extends Model<PluginModel> {
       })
   }
 
-  static listInstalled (): Bluebird<MPlugin[]> {
+  static listInstalled (): Promise<MPlugin[]> {
     const query = {
       where: {
         uninstalled: false

+ 3 - 4
server/models/server/server-blocklist.ts

@@ -1,4 +1,3 @@
-import * as Bluebird from 'bluebird'
 import { Op } from 'sequelize'
 import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
 import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/types/models'
@@ -43,7 +42,7 @@ enum ScopeNames {
     }
   ]
 })
-export class ServerBlocklistModel extends Model<ServerBlocklistModel> {
+export class ServerBlocklistModel extends Model {
 
   @CreatedAt
   createdAt: Date
@@ -101,7 +100,7 @@ export class ServerBlocklistModel extends Model<ServerBlocklistModel> {
                                 })
   }
 
-  static loadByAccountAndHost (accountId: number, host: string): Bluebird<MServerBlocklist> {
+  static loadByAccountAndHost (accountId: number, host: string): Promise<MServerBlocklist> {
     const query = {
       where: {
         accountId
@@ -120,7 +119,7 @@ export class ServerBlocklistModel extends Model<ServerBlocklistModel> {
     return ServerBlocklistModel.findOne(query)
   }
 
-  static listHostsBlockedBy (accountIds: number[]): Bluebird<string[]> {
+  static listHostsBlockedBy (accountIds: number[]): Promise<string[]> {
     const query = {
       attributes: [ ],
       where: {

+ 4 - 5
server/models/server/server.ts

@@ -1,10 +1,9 @@
 import { AllowNull, Column, CreatedAt, Default, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
+import { MServer, MServerFormattable } from '@server/types/models/server'
 import { isHostValid } from '../../helpers/custom-validators/servers'
 import { ActorModel } from '../activitypub/actor'
 import { throwIfNotValid } from '../utils'
 import { ServerBlocklistModel } from './server-blocklist'
-import * as Bluebird from 'bluebird'
-import { MServer, MServerFormattable } from '@server/types/models/server'
 
 @Table({
   tableName: 'server',
@@ -15,7 +14,7 @@ import { MServer, MServerFormattable } from '@server/types/models/server'
     }
   ]
 })
-export class ServerModel extends Model<ServerModel> {
+export class ServerModel extends Model {
 
   @AllowNull(false)
   @Is('Host', value => throwIfNotValid(value, isHostValid, 'valid host'))
@@ -51,7 +50,7 @@ export class ServerModel extends Model<ServerModel> {
   })
   BlockedByAccounts: ServerBlocklistModel[]
 
-  static load (id: number): Bluebird<MServer> {
+  static load (id: number): Promise<MServer> {
     const query = {
       where: {
         id
@@ -61,7 +60,7 @@ export class ServerModel extends Model<ServerModel> {
     return ServerModel.findOne(query)
   }
 
-  static loadByHost (host: string): Bluebird<MServer> {
+  static loadByHost (host: string): Promise<MServer> {
     const query = {
       where: {
         host

+ 2 - 1
server/models/utils.ts

@@ -113,7 +113,8 @@ function throwIfNotValid (value: any, validator: (value: any) => boolean, fieldN
 function buildTrigramSearchIndex (indexName: string, attribute: string) {
   return {
     name: indexName,
-    fields: [ Sequelize.literal('lower(immutable_unaccent(' + attribute + '))') as any ],
+    // FIXME: gin_trgm_ops is not taken into account in Sequelize 6, so adding it ourselves in the literal function
+    fields: [ Sequelize.literal('lower(immutable_unaccent(' + attribute + ')) gin_trgm_ops') as any ],
     using: 'gin',
     operator: 'gin_trgm_ops'
   }

+ 1 - 1
server/models/video/schedule-video-update.ts

@@ -16,7 +16,7 @@ import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdateVideoAll } from '@
     }
   ]
 })
-export class ScheduleVideoUpdateModel extends Model<ScheduleVideoUpdateModel> {
+export class ScheduleVideoUpdateModel extends Model {
 
   @AllowNull(false)
   @Default(null)

+ 6 - 7
server/models/video/tag.ts

@@ -1,12 +1,11 @@
-import * as Bluebird from 'bluebird'
-import { fn, QueryTypes, Transaction, col } from 'sequelize'
+import { col, fn, QueryTypes, Transaction } from 'sequelize'
 import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
+import { MTag } from '@server/types/models'
+import { VideoPrivacy, VideoState } from '../../../shared/models/videos'
 import { isVideoTagValid } from '../../helpers/custom-validators/videos'
 import { throwIfNotValid } from '../utils'
 import { VideoModel } from './video'
 import { VideoTagModel } from './video-tag'
-import { VideoPrivacy, VideoState } from '../../../shared/models/videos'
-import { MTag } from '@server/types/models'
 
 @Table({
   tableName: 'tag',
@@ -22,7 +21,7 @@ import { MTag } from '@server/types/models'
     }
   ]
 })
-export class TagModel extends Model<TagModel> {
+export class TagModel extends Model {
 
   @AllowNull(false)
   @Is('VideoTag', value => throwIfNotValid(value, isVideoTagValid, 'tag'))
@@ -45,7 +44,7 @@ export class TagModel extends Model<TagModel> {
   static findOrCreateTags (tags: string[], transaction: Transaction): Promise<MTag[]> {
     if (tags === null) return Promise.resolve([])
 
-    const tasks: Bluebird<MTag>[] = []
+    const tasks: Promise<MTag>[] = []
     tags.forEach(tag => {
       const query = {
         where: {
@@ -66,7 +65,7 @@ export class TagModel extends Model<TagModel> {
   }
 
   // threshold corresponds to how many video the field should have to be returned
-  static getRandomSamples (threshold: number, count: number): Bluebird<string[]> {
+  static getRandomSamples (threshold: number, count: number): Promise<string[]> {
     const query = 'SELECT tag.name FROM tag ' +
       'INNER JOIN "videoTag" ON "videoTag"."tagId" = tag.id ' +
       'INNER JOIN video ON video.id = "videoTag"."videoId" ' +

+ 1 - 1
server/models/video/thumbnail.ts

@@ -34,7 +34,7 @@ import { buildRemoteVideoBaseUrl } from '@server/helpers/activitypub'
     }
   ]
 })
-export class ThumbnailModel extends Model<ThumbnailModel> {
+export class ThumbnailModel extends Model {
 
   @AllowNull(false)
   @Column

+ 8 - 9
server/models/video/video-blacklist.ts

@@ -1,14 +1,13 @@
+import { FindOptions } from 'sequelize'
 import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
-import { getBlacklistSort, SortType, throwIfNotValid, searchAttribute } from '../utils'
-import { VideoModel } from './video'
-import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
-import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist'
+import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models'
 import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos'
+import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist'
 import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
-import { FindOptions } from 'sequelize'
+import { getBlacklistSort, searchAttribute, SortType, throwIfNotValid } from '../utils'
 import { ThumbnailModel } from './thumbnail'
-import * as Bluebird from 'bluebird'
-import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models'
+import { VideoModel } from './video'
+import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
 
 @Table({
   tableName: 'videoBlacklist',
@@ -19,7 +18,7 @@ import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/model
     }
   ]
 })
-export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
+export class VideoBlacklistModel extends Model {
 
   @AllowNull(true)
   @Is('VideoBlacklistReason', value => throwIfNotValid(value, isVideoBlacklistReasonValid, 'reason', true))
@@ -109,7 +108,7 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
     })
   }
 
-  static loadByVideoId (id: number): Bluebird<MVideoBlacklist> {
+  static loadByVideoId (id: number): Promise<MVideoBlacklist> {
     const query = {
       where: {
         videoId: id

+ 11 - 12
server/models/video/video-caption.ts

@@ -1,3 +1,5 @@
+import { remove } from 'fs-extra'
+import { join } from 'path'
 import { OrderItem, Transaction } from 'sequelize'
 import {
   AllowNull,
@@ -13,18 +15,15 @@ import {
   Table,
   UpdatedAt
 } from 'sequelize-typescript'
-import { buildWhereIdOrUUID, throwIfNotValid } from '../utils'
-import { VideoModel } from './video'
-import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions'
+import { buildRemoteVideoBaseUrl } from '@server/helpers/activitypub'
+import { MVideoAccountLight, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models'
 import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model'
-import { CONSTRAINTS_FIELDS, LAZY_STATIC_PATHS, VIDEO_LANGUAGES, WEBSERVER } from '../../initializers/constants'
-import { join } from 'path'
+import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions'
 import { logger } from '../../helpers/logger'
-import { remove } from 'fs-extra'
 import { CONFIG } from '../../initializers/config'
-import * as Bluebird from 'bluebird'
-import { MVideoAccountLight, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models'
-import { buildRemoteVideoBaseUrl } from '@server/helpers/activitypub'
+import { CONSTRAINTS_FIELDS, LAZY_STATIC_PATHS, VIDEO_LANGUAGES, WEBSERVER } from '../../initializers/constants'
+import { buildWhereIdOrUUID, throwIfNotValid } from '../utils'
+import { VideoModel } from './video'
 
 export enum ScopeNames {
   WITH_VIDEO_UUID_AND_REMOTE = 'WITH_VIDEO_UUID_AND_REMOTE'
@@ -54,7 +53,7 @@ export enum ScopeNames {
     }
   ]
 })
-export class VideoCaptionModel extends Model<VideoCaptionModel> {
+export class VideoCaptionModel extends Model {
   @CreatedAt
   createdAt: Date
 
@@ -101,7 +100,7 @@ export class VideoCaptionModel extends Model<VideoCaptionModel> {
     return undefined
   }
 
-  static loadByVideoIdAndLanguage (videoId: string | number, language: string): Bluebird<MVideoCaptionVideo> {
+  static loadByVideoIdAndLanguage (videoId: string | number, language: string): Promise<MVideoCaptionVideo> {
     const videoInclude = {
       model: VideoModel.unscoped(),
       attributes: [ 'id', 'remote', 'uuid' ],
@@ -131,7 +130,7 @@ export class VideoCaptionModel extends Model<VideoCaptionModel> {
       .then(([ caption ]) => caption)
   }
 
-  static listVideoCaptions (videoId: number): Bluebird<MVideoCaptionVideo[]> {
+  static listVideoCaptions (videoId: number): Promise<MVideoCaptionVideo[]> {
     const query = {
       order: [ [ 'language', 'ASC' ] ] as OrderItem[],
       where: {

+ 5 - 6
server/models/video/video-change-ownership.ts

@@ -1,10 +1,9 @@
 import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
-import { AccountModel } from '../account/account'
-import { ScopeNames as VideoScopeNames, VideoModel } from './video'
+import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership'
 import { VideoChangeOwnership, VideoChangeOwnershipStatus } from '../../../shared/models/videos'
+import { AccountModel } from '../account/account'
 import { getSort } from '../utils'
-import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership'
-import * as Bluebird from 'bluebird'
+import { ScopeNames as VideoScopeNames, VideoModel } from './video'
 
 enum ScopeNames {
   WITH_ACCOUNTS = 'WITH_ACCOUNTS',
@@ -54,7 +53,7 @@ enum ScopeNames {
     ]
   }
 }))
-export class VideoChangeOwnershipModel extends Model<VideoChangeOwnershipModel> {
+export class VideoChangeOwnershipModel extends Model {
   @CreatedAt
   createdAt: Date
 
@@ -119,7 +118,7 @@ export class VideoChangeOwnershipModel extends Model<VideoChangeOwnershipModel>
     ]).then(([ count, rows ]) => ({ total: count, data: rows }))
   }
 
-  static load (id: number): Bluebird<MVideoChangeOwnershipFull> {
+  static load (id: number): Promise<MVideoChangeOwnershipFull> {
     return VideoChangeOwnershipModel.scope([ ScopeNames.WITH_ACCOUNTS, ScopeNames.WITH_VIDEO ])
                                     .findByPk(id)
   }

+ 39 - 39
server/models/video/video-channel.ts

@@ -1,5 +1,4 @@
-import * as Bluebird from 'bluebird'
-import { FindOptions, literal, Op, ScopeOptions } from 'sequelize'
+import { FindOptions, Includeable, literal, Op, ScopeOptions } from 'sequelize'
 import {
   AllowNull,
   BeforeDestroy,
@@ -119,30 +118,31 @@ export type SummaryOptions = {
     }
   },
   [ScopeNames.SUMMARY]: (options: SummaryOptions = {}) => {
+    const include: Includeable[] = [
+      {
+        attributes: [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ],
+        model: ActorModel.unscoped(),
+        required: options.actorRequired ?? true,
+        include: [
+          {
+            attributes: [ 'host' ],
+            model: ServerModel.unscoped(),
+            required: false
+          },
+          {
+            model: AvatarModel.unscoped(),
+            required: false
+          }
+        ]
+      }
+    ]
+
     const base: FindOptions = {
-      attributes: [ 'id', 'name', 'description', 'actorId' ],
-      include: [
-        {
-          attributes: [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ],
-          model: ActorModel.unscoped(),
-          required: options.actorRequired ?? true,
-          include: [
-            {
-              attributes: [ 'host' ],
-              model: ServerModel.unscoped(),
-              required: false
-            },
-            {
-              model: AvatarModel.unscoped(),
-              required: false
-            }
-          ]
-        }
-      ]
+      attributes: [ 'id', 'name', 'description', 'actorId' ]
     }
 
     if (options.withAccount === true) {
-      base.include.push({
+      include.push({
         model: AccountModel.scope({
           method: [ AccountModelScopeNames.SUMMARY, { withAccountBlockerIds: options.withAccountBlockerIds } as AccountSummaryOptions ]
         }),
@@ -150,6 +150,8 @@ export type SummaryOptions = {
       })
     }
 
+    base.include = include
+
     return base
   },
   [ScopeNames.WITH_ACCOUNT]: {
@@ -221,7 +223,7 @@ export type SummaryOptions = {
     }
   ]
 })
-export class VideoChannelModel extends Model<VideoChannelModel> {
+export class VideoChannelModel extends Model {
 
   @AllowNull(false)
   @Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelNameValid, 'name'))
@@ -328,18 +330,17 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
       order: getSort(parameters.sort)
     }
 
-    const scopes = {
-      method: [ ScopeNames.FOR_API, { actorId } as AvailableForListOptions ]
-    }
     return VideoChannelModel
-      .scope(scopes)
+      .scope({
+        method: [ ScopeNames.FOR_API, { actorId } as AvailableForListOptions ]
+      })
       .findAndCountAll(query)
       .then(({ rows, count }) => {
         return { total: count, data: rows }
       })
   }
 
-  static listLocalsForSitemap (sort: string): Bluebird<MChannelActor[]> {
+  static listLocalsForSitemap (sort: string): Promise<MChannelActor[]> {
     const query = {
       attributes: [ ],
       offset: 0,
@@ -391,11 +392,10 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
       }
     }
 
-    const scopes = {
-      method: [ ScopeNames.FOR_API, { actorId: options.actorId } as AvailableForListOptions ]
-    }
     return VideoChannelModel
-      .scope(scopes)
+      .scope({
+        method: [ ScopeNames.FOR_API, { actorId: options.actorId } as AvailableForListOptions ]
+      })
       .findAndCountAll(query)
       .then(({ rows, count }) => {
         return { total: count, data: rows }
@@ -457,13 +457,13 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
       })
   }
 
-  static loadByIdAndPopulateAccount (id: number): Bluebird<MChannelAccountDefault> {
+  static loadByIdAndPopulateAccount (id: number): Promise<MChannelAccountDefault> {
     return VideoChannelModel.unscoped()
       .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ])
       .findByPk(id)
   }
 
-  static loadByIdAndAccount (id: number, accountId: number): Bluebird<MChannelAccountDefault> {
+  static loadByIdAndAccount (id: number, accountId: number): Promise<MChannelAccountDefault> {
     const query = {
       where: {
         id,
@@ -476,13 +476,13 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
       .findOne(query)
   }
 
-  static loadAndPopulateAccount (id: number): Bluebird<MChannelAccountDefault> {
+  static loadAndPopulateAccount (id: number): Promise<MChannelAccountDefault> {
     return VideoChannelModel.unscoped()
       .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ])
       .findByPk(id)
   }
 
-  static loadByUrlAndPopulateAccount (url: string): Bluebird<MChannelAccountDefault> {
+  static loadByUrlAndPopulateAccount (url: string): Promise<MChannelAccountDefault> {
     const query = {
       include: [
         {
@@ -508,7 +508,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
     return VideoChannelModel.loadByNameAndHostAndPopulateAccount(name, host)
   }
 
-  static loadLocalByNameAndPopulateAccount (name: string): Bluebird<MChannelAccountDefault> {
+  static loadLocalByNameAndPopulateAccount (name: string): Promise<MChannelAccountDefault> {
     const query = {
       include: [
         {
@@ -527,7 +527,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
       .findOne(query)
   }
 
-  static loadByNameAndHostAndPopulateAccount (name: string, host: string): Bluebird<MChannelAccountDefault> {
+  static loadByNameAndHostAndPopulateAccount (name: string, host: string): Promise<MChannelAccountDefault> {
     const query = {
       include: [
         {
@@ -552,7 +552,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
       .findOne(query)
   }
 
-  static loadAndPopulateAccountAndVideos (id: number): Bluebird<MChannelActorAccountDefaultVideos> {
+  static loadAndPopulateAccountAndVideos (id: number): Promise<MChannelActorAccountDefaultVideos> {
     const options = {
       include: [
         VideoModel

+ 6 - 7
server/models/video/video-comment.ts

@@ -1,4 +1,3 @@
-import * as Bluebird from 'bluebird'
 import { uniq } from 'lodash'
 import { FindAndCountOptions, FindOptions, Op, Order, ScopeOptions, Sequelize, Transaction, WhereOptions } from 'sequelize'
 import {
@@ -174,7 +173,7 @@ export enum ScopeNames {
     }
   ]
 })
-export class VideoCommentModel extends Model<VideoCommentModel> {
+export class VideoCommentModel extends Model {
   @CreatedAt
   createdAt: Date
 
@@ -255,7 +254,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
   })
   CommentAbuses: VideoCommentAbuseModel[]
 
-  static loadById (id: number, t?: Transaction): Bluebird<MComment> {
+  static loadById (id: number, t?: Transaction): Promise<MComment> {
     const query: FindOptions = {
       where: {
         id
@@ -267,7 +266,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
     return VideoCommentModel.findOne(query)
   }
 
-  static loadByIdAndPopulateVideoAndAccountAndReply (id: number, t?: Transaction): Bluebird<MCommentOwnerVideoReply> {
+  static loadByIdAndPopulateVideoAndAccountAndReply (id: number, t?: Transaction): Promise<MCommentOwnerVideoReply> {
     const query: FindOptions = {
       where: {
         id
@@ -281,7 +280,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
       .findOne(query)
   }
 
-  static loadByUrlAndPopulateAccountAndVideo (url: string, t?: Transaction): Bluebird<MCommentOwnerVideo> {
+  static loadByUrlAndPopulateAccountAndVideo (url: string, t?: Transaction): Promise<MCommentOwnerVideo> {
     const query: FindOptions = {
       where: {
         url
@@ -293,7 +292,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
     return VideoCommentModel.scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_VIDEO ]).findOne(query)
   }
 
-  static loadByUrlAndPopulateReplyAndVideoUrlAndAccount (url: string, t?: Transaction): Bluebird<MCommentOwnerReplyVideoLight> {
+  static loadByUrlAndPopulateReplyAndVideoUrlAndAccount (url: string, t?: Transaction): Promise<MCommentOwnerReplyVideoLight> {
     const query: FindOptions = {
       where: {
         url
@@ -501,7 +500,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
       })
   }
 
-  static listThreadParentComments (comment: MCommentId, t: Transaction, order: 'ASC' | 'DESC' = 'ASC'): Bluebird<MCommentOwner[]> {
+  static listThreadParentComments (comment: MCommentId, t: Transaction, order: 'ASC' | 'DESC' = 'ASC'): Promise<MCommentOwner[]> {
     const query = {
       order: [ [ 'createdAt', order ] ] as Order,
       where: {

+ 1 - 1
server/models/video/video-file.ts

@@ -101,7 +101,7 @@ export enum ScopeNames {
     }
   ]
 })
-export class VideoFileModel extends Model<VideoFileModel> {
+export class VideoFileModel extends Model {
   @CreatedAt
   createdAt: Date
 

+ 7 - 8
server/models/video/video-import.ts

@@ -13,15 +13,14 @@ import {
   Table,
   UpdatedAt
 } from 'sequelize-typescript'
-import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants'
-import { getSort, throwIfNotValid } from '../utils'
-import { ScopeNames as VideoModelScopeNames, VideoModel } from './video'
-import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports'
+import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import'
 import { VideoImport, VideoImportState } from '../../../shared'
+import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports'
 import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos'
+import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants'
 import { UserModel } from '../account/user'
-import * as Bluebird from 'bluebird'
-import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import'
+import { getSort, throwIfNotValid } from '../utils'
+import { ScopeNames as VideoModelScopeNames, VideoModel } from './video'
 
 @DefaultScope(() => ({
   include: [
@@ -52,7 +51,7 @@ import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/mode
     }
   ]
 })
-export class VideoImportModel extends Model<VideoImportModel> {
+export class VideoImportModel extends Model {
   @CreatedAt
   createdAt: Date
 
@@ -120,7 +119,7 @@ export class VideoImportModel extends Model<VideoImportModel> {
     return undefined
   }
 
-  static loadAndPopulateVideo (id: number): Bluebird<MVideoImportDefault> {
+  static loadAndPopulateVideo (id: number): Promise<MVideoImportDefault> {
     return VideoImportModel.findByPk(id)
   }
 

+ 1 - 1
server/models/video/video-live.ts

@@ -28,7 +28,7 @@ import { VideoBlacklistModel } from './video-blacklist'
     }
   ]
 })
-export class VideoLiveModel extends Model<VideoLiveModel> {
+export class VideoLiveModel extends Model {
 
   @AllowNull(true)
   @Column(DataType.STRING)

+ 16 - 17
server/models/video/video-playlist-element.ts

@@ -1,3 +1,4 @@
+import { AggregateOptions, Op, ScopeOptions, Sequelize, Transaction } from 'sequelize'
 import {
   AllowNull,
   BelongsTo,
@@ -13,18 +14,8 @@ import {
   Table,
   UpdatedAt
 } from 'sequelize-typescript'
-import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video'
-import { VideoPlaylistModel } from './video-playlist'
-import { getSort, throwIfNotValid } from '../utils'
-import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
-import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
-import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object'
 import validator from 'validator'
-import { AggregateOptions, Op, ScopeOptions, Sequelize, Transaction } from 'sequelize'
-import { VideoPlaylistElement, VideoPlaylistElementType } from '../../../shared/models/videos/playlist/video-playlist-element.model'
-import { AccountModel } from '../account/account'
-import { VideoPrivacy } from '../../../shared/models/videos'
-import * as Bluebird from 'bluebird'
+import { MUserAccountId } from '@server/types/models'
 import {
   MVideoPlaylistElement,
   MVideoPlaylistElementAP,
@@ -32,7 +23,15 @@ import {
   MVideoPlaylistElementVideoUrlPlaylistPrivacy,
   MVideoPlaylistVideoThumbnail
 } from '@server/types/models/video/video-playlist-element'
-import { MUserAccountId } from '@server/types/models'
+import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object'
+import { VideoPrivacy } from '../../../shared/models/videos'
+import { VideoPlaylistElement, VideoPlaylistElementType } from '../../../shared/models/videos/playlist/video-playlist-element.model'
+import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
+import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
+import { AccountModel } from '../account/account'
+import { getSort, throwIfNotValid } from '../utils'
+import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video'
+import { VideoPlaylistModel } from './video-playlist'
 
 @Table({
   tableName: 'videoPlaylistElement',
@@ -49,7 +48,7 @@ import { MUserAccountId } from '@server/types/models'
     }
   ]
 })
-export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel> {
+export class VideoPlaylistElementModel extends Model {
   @CreatedAt
   createdAt: Date
 
@@ -166,7 +165,7 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
     ]).then(([ total, data ]) => ({ total, data }))
   }
 
-  static loadByPlaylistAndVideo (videoPlaylistId: number, videoId: number): Bluebird<MVideoPlaylistElement> {
+  static loadByPlaylistAndVideo (videoPlaylistId: number, videoId: number): Promise<MVideoPlaylistElement> {
     const query = {
       where: {
         videoPlaylistId,
@@ -177,14 +176,14 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
     return VideoPlaylistElementModel.findOne(query)
   }
 
-  static loadById (playlistElementId: number | string): Bluebird<MVideoPlaylistElement> {
+  static loadById (playlistElementId: number | string): Promise<MVideoPlaylistElement> {
     return VideoPlaylistElementModel.findByPk(playlistElementId)
   }
 
   static loadByPlaylistAndElementIdForAP (
     playlistId: number | string,
     playlistElementId: number
-  ): Bluebird<MVideoPlaylistElementVideoUrlPlaylistPrivacy> {
+  ): Promise<MVideoPlaylistElementVideoUrlPlaylistPrivacy> {
     const playlistWhere = validator.isUUID('' + playlistId) ? { uuid: playlistId } : { id: playlistId }
 
     const query = {
@@ -226,7 +225,7 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
       })
   }
 
-  static loadFirstElementWithVideoThumbnail (videoPlaylistId: number): Bluebird<MVideoPlaylistVideoThumbnail> {
+  static loadFirstElementWithVideoThumbnail (videoPlaylistId: number): Promise<MVideoPlaylistVideoThumbnail> {
     const query = {
       order: getSort('position'),
       where: {

+ 9 - 13
server/models/video/video-playlist.ts

@@ -1,4 +1,3 @@
-import * as Bluebird from 'bluebird'
 import { join } from 'path'
 import { FindOptions, literal, Op, ScopeOptions, Transaction, WhereOptions } from 'sequelize'
 import {
@@ -125,7 +124,6 @@ type AvailableForListOptions = {
     ]
   },
   [ScopeNames.AVAILABLE_FOR_LIST]: (options: AvailableForListOptions) => {
-
     let whereActor: WhereOptions = {}
 
     const whereAnd: WhereOptions[] = []
@@ -182,15 +180,13 @@ type AvailableForListOptions = {
       [Op.and]: whereAnd
     }
 
-    const accountScope = {
-      method: [ AccountScopeNames.SUMMARY, { whereActor } as SummaryOptions ]
-    }
-
     return {
       where,
       include: [
         {
-          model: AccountModel.scope(accountScope),
+          model: AccountModel.scope({
+            method: [ AccountScopeNames.SUMMARY, { whereActor } as SummaryOptions ]
+          }),
           required: true
         },
         {
@@ -217,7 +213,7 @@ type AvailableForListOptions = {
     }
   ]
 })
-export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
+export class VideoPlaylistModel extends Model {
   @CreatedAt
   createdAt: Date
 
@@ -367,7 +363,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
                              })
   }
 
-  static listPlaylistIdsOf (accountId: number, videoIds: number[]): Bluebird<MVideoPlaylistIdWithElements[]> {
+  static listPlaylistIdsOf (accountId: number, videoIds: number[]): Promise<MVideoPlaylistIdWithElements[]> {
     const query = {
       attributes: [ 'id' ],
       where: {
@@ -392,7 +388,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
 
   static doesPlaylistExist (url: string) {
     const query = {
-      attributes: [],
+      attributes: [ 'id' ],
       where: {
         url
       }
@@ -403,7 +399,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
       .then(e => !!e)
   }
 
-  static loadWithAccountAndChannelSummary (id: number | string, transaction: Transaction): Bluebird<MVideoPlaylistFullSummary> {
+  static loadWithAccountAndChannelSummary (id: number | string, transaction: Transaction): Promise<MVideoPlaylistFullSummary> {
     const where = buildWhereIdOrUUID(id)
 
     const query = {
@@ -416,7 +412,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
       .findOne(query)
   }
 
-  static loadWithAccountAndChannel (id: number | string, transaction: Transaction): Bluebird<MVideoPlaylistFull> {
+  static loadWithAccountAndChannel (id: number | string, transaction: Transaction): Promise<MVideoPlaylistFull> {
     const where = buildWhereIdOrUUID(id)
 
     const query = {
@@ -429,7 +425,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
       .findOne(query)
   }
 
-  static loadByUrlAndPopulateAccount (url: string): Bluebird<MVideoPlaylistAccountThumbnail> {
+  static loadByUrlAndPopulateAccount (url: string): Promise<MVideoPlaylistAccountThumbnail> {
     const query = {
       where: {
         url

+ 9 - 10
server/models/video/video-share.ts

@@ -1,13 +1,12 @@
-import * as Bluebird from 'bluebird'
+import { literal, Op, Transaction } from 'sequelize'
 import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
 import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
 import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
+import { MActorDefault } from '../../types/models'
+import { MVideoShareActor, MVideoShareFull } from '../../types/models/video'
 import { ActorModel } from '../activitypub/actor'
 import { buildLocalActorIdsIn, throwIfNotValid } from '../utils'
 import { VideoModel } from './video'
-import { literal, Op, Transaction } from 'sequelize'
-import { MVideoShareActor, MVideoShareFull } from '../../types/models/video'
-import { MActorDefault } from '../../types/models'
 
 enum ScopeNames {
   FULL = 'FULL',
@@ -51,7 +50,7 @@ enum ScopeNames {
     }
   ]
 })
-export class VideoShareModel extends Model<VideoShareModel> {
+export class VideoShareModel extends Model {
 
   @AllowNull(false)
   @Is('VideoShareUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url'))
@@ -88,7 +87,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
   })
   Video: VideoModel
 
-  static load (actorId: number | string, videoId: number | string, t?: Transaction): Bluebird<MVideoShareActor> {
+  static load (actorId: number | string, videoId: number | string, t?: Transaction): Promise<MVideoShareActor> {
     return VideoShareModel.scope(ScopeNames.WITH_ACTOR).findOne({
       where: {
         actorId,
@@ -98,7 +97,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
     })
   }
 
-  static loadByUrl (url: string, t: Transaction): Bluebird<MVideoShareFull> {
+  static loadByUrl (url: string, t: Transaction): Promise<MVideoShareFull> {
     return VideoShareModel.scope(ScopeNames.FULL).findOne({
       where: {
         url
@@ -107,7 +106,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
     })
   }
 
-  static loadActorsByShare (videoId: number, t: Transaction): Bluebird<MActorDefault[]> {
+  static loadActorsByShare (videoId: number, t: Transaction): Promise<MActorDefault[]> {
     const query = {
       where: {
         videoId
@@ -125,7 +124,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
                           .then((res: MVideoShareFull[]) => res.map(r => r.Actor))
   }
 
-  static loadActorsWhoSharedVideosOf (actorOwnerId: number, t: Transaction): Bluebird<MActorDefault[]> {
+  static loadActorsWhoSharedVideosOf (actorOwnerId: number, t: Transaction): Promise<MActorDefault[]> {
     const safeOwnerId = parseInt(actorOwnerId + '', 10)
 
     // /!\ On actor model
@@ -150,7 +149,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
     return ActorModel.findAll(query)
   }
 
-  static loadActorsByVideoChannel (videoChannelId: number, t: Transaction): Bluebird<MActorDefault[]> {
+  static loadActorsByVideoChannel (videoChannelId: number, t: Transaction): Promise<MActorDefault[]> {
     const safeChannelId = parseInt(videoChannelId + '', 10)
 
     // /!\ On actor model

+ 1 - 1
server/models/video/video-streaming-playlist.ts

@@ -40,7 +40,7 @@ import { logger } from '@server/helpers/logger'
     }
   ]
 })
-export class VideoStreamingPlaylistModel extends Model<VideoStreamingPlaylistModel> {
+export class VideoStreamingPlaylistModel extends Model {
   @CreatedAt
   createdAt: Date
 

+ 1 - 1
server/models/video/video-tag.ts

@@ -13,7 +13,7 @@ import { VideoModel } from './video'
     }
   ]
 })
-export class VideoTagModel extends Model<VideoTagModel> {
+export class VideoTagModel extends Model {
   @CreatedAt
   createdAt: Date
 

+ 1 - 1
server/models/video/video-view.ts

@@ -14,7 +14,7 @@ import * as Sequelize from 'sequelize'
     }
   ]
 })
-export class VideoViewModel extends Model<VideoViewModel> {
+export class VideoViewModel extends Model {
   @CreatedAt
   createdAt: Date
 

+ 44 - 41
server/models/video/video.ts

@@ -2,7 +2,7 @@ import * as Bluebird from 'bluebird'
 import { remove } from 'fs-extra'
 import { maxBy, minBy, pick } from 'lodash'
 import { join } from 'path'
-import { FindOptions, IncludeOptions, Op, QueryTypes, ScopeOptions, Sequelize, Transaction, WhereOptions } from 'sequelize'
+import { FindOptions, Includeable, IncludeOptions, Op, QueryTypes, ScopeOptions, Sequelize, Transaction, WhereOptions } from 'sequelize'
 import {
   AllowNull,
   BeforeDestroy,
@@ -190,26 +190,26 @@ export type AvailableForListIDsOptions = {
     attributes: [ 'id', 'url', 'uuid', 'remote' ]
   },
   [ScopeNames.FOR_API]: (options: ForAPIOptions) => {
-    const query: FindOptions = {
-      include: [
-        {
-          model: VideoChannelModel.scope({
-            method: [
-              VideoChannelScopeNames.SUMMARY, {
-                withAccount: true,
-                withAccountBlockerIds: options.withAccountBlockerIds
-              } as SummaryOptions
-            ]
-          }),
-          required: true
-        },
-        {
-          attributes: [ 'type', 'filename' ],
-          model: ThumbnailModel,
-          required: false
-        }
-      ]
-    }
+    const include: Includeable[] = [
+      {
+        model: VideoChannelModel.scope({
+          method: [
+            VideoChannelScopeNames.SUMMARY, {
+              withAccount: true,
+              withAccountBlockerIds: options.withAccountBlockerIds
+            } as SummaryOptions
+          ]
+        }),
+        required: true
+      },
+      {
+        attributes: [ 'type', 'filename' ],
+        model: ThumbnailModel,
+        required: false
+      }
+    ]
+
+    const query: FindOptions = {}
 
     if (options.ids) {
       query.where = {
@@ -220,14 +220,14 @@ export type AvailableForListIDsOptions = {
     }
 
     if (options.withFiles === true) {
-      query.include.push({
+      include.push({
         model: VideoFileModel,
         required: true
       })
     }
 
     if (options.videoPlaylistId) {
-      query.include.push({
+      include.push({
         model: VideoPlaylistElementModel.unscoped(),
         required: true,
         where: {
@@ -236,6 +236,8 @@ export type AvailableForListIDsOptions = {
       })
     }
 
+    query.include = include
+
     return query
   },
   [ScopeNames.WITH_THUMBNAILS]: {
@@ -477,7 +479,7 @@ export type AvailableForListIDsOptions = {
     }
   ]
 })
-export class VideoModel extends Model<VideoModel> {
+export class VideoModel extends Model {
 
   @AllowNull(false)
   @Default(DataType.UUIDV4)
@@ -860,7 +862,7 @@ export class VideoModel extends Model<VideoModel> {
     return undefined
   }
 
-  static listLocal (): Bluebird<MVideoWithAllFiles[]> {
+  static listLocal (): Promise<MVideoWithAllFiles[]> {
     const query = {
       where: {
         remote: false
@@ -988,7 +990,7 @@ export class VideoModel extends Model<VideoModel> {
     })
   }
 
-  static listPublishedLiveIds () {
+  static async listPublishedLiveIds () {
     const options = {
       attributes: [ 'id' ],
       where: {
@@ -997,8 +999,9 @@ export class VideoModel extends Model<VideoModel> {
       }
     }
 
-    return VideoModel.findAll(options)
-      .map(v => v.id)
+    const result = await VideoModel.findAll(options)
+
+    return result.map(v => v.id)
   }
 
   static listUserVideosForApi (
@@ -1214,7 +1217,7 @@ export class VideoModel extends Model<VideoModel> {
     return VideoModel.count(options)
   }
 
-  static load (id: number | string, t?: Transaction): Bluebird<MVideoThumbnail> {
+  static load (id: number | string, t?: Transaction): Promise<MVideoThumbnail> {
     const where = buildWhereIdOrUUID(id)
     const options = {
       where,
@@ -1224,7 +1227,7 @@ export class VideoModel extends Model<VideoModel> {
     return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
   }
 
-  static loadWithBlacklist (id: number | string, t?: Transaction): Bluebird<MVideoThumbnailBlacklist> {
+  static loadWithBlacklist (id: number | string, t?: Transaction): Promise<MVideoThumbnailBlacklist> {
     const where = buildWhereIdOrUUID(id)
     const options = {
       where,
@@ -1237,7 +1240,7 @@ export class VideoModel extends Model<VideoModel> {
     ]).findOne(options)
   }
 
-  static loadImmutableAttributes (id: number | string, t?: Transaction): Bluebird<MVideoImmutable> {
+  static loadImmutableAttributes (id: number | string, t?: Transaction): Promise<MVideoImmutable> {
     const fun = () => {
       const query = {
         where: buildWhereIdOrUUID(id),
@@ -1255,7 +1258,7 @@ export class VideoModel extends Model<VideoModel> {
     })
   }
 
-  static loadWithRights (id: number | string, t?: Transaction): Bluebird<MVideoWithRights> {
+  static loadWithRights (id: number | string, t?: Transaction): Promise<MVideoWithRights> {
     const where = buildWhereIdOrUUID(id)
     const options = {
       where,
@@ -1269,7 +1272,7 @@ export class VideoModel extends Model<VideoModel> {
     ]).findOne(options)
   }
 
-  static loadOnlyId (id: number | string, t?: Transaction): Bluebird<MVideoIdThumbnail> {
+  static loadOnlyId (id: number | string, t?: Transaction): Promise<MVideoIdThumbnail> {
     const where = buildWhereIdOrUUID(id)
 
     const options = {
@@ -1281,7 +1284,7 @@ export class VideoModel extends Model<VideoModel> {
     return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
   }
 
-  static loadWithFiles (id: number | string, t?: Transaction, logging?: boolean): Bluebird<MVideoWithAllFiles> {
+  static loadWithFiles (id: number | string, t?: Transaction, logging?: boolean): Promise<MVideoWithAllFiles> {
     const where = buildWhereIdOrUUID(id)
 
     const query = {
@@ -1297,7 +1300,7 @@ export class VideoModel extends Model<VideoModel> {
     ]).findOne(query)
   }
 
-  static loadByUUID (uuid: string): Bluebird<MVideoThumbnail> {
+  static loadByUUID (uuid: string): Promise<MVideoThumbnail> {
     const options = {
       where: {
         uuid
@@ -1307,7 +1310,7 @@ export class VideoModel extends Model<VideoModel> {
     return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
   }
 
-  static loadByUrl (url: string, transaction?: Transaction): Bluebird<MVideoThumbnail> {
+  static loadByUrl (url: string, transaction?: Transaction): Promise<MVideoThumbnail> {
     const query: FindOptions = {
       where: {
         url
@@ -1318,7 +1321,7 @@ export class VideoModel extends Model<VideoModel> {
     return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(query)
   }
 
-  static loadByUrlImmutableAttributes (url: string, transaction?: Transaction): Bluebird<MVideoImmutable> {
+  static loadByUrlImmutableAttributes (url: string, transaction?: Transaction): Promise<MVideoImmutable> {
     const fun = () => {
       const query: FindOptions = {
         where: {
@@ -1338,7 +1341,7 @@ export class VideoModel extends Model<VideoModel> {
     })
   }
 
-  static loadByUrlAndPopulateAccount (url: string, transaction?: Transaction): Bluebird<MVideoAccountLightBlacklistAllFiles> {
+  static loadByUrlAndPopulateAccount (url: string, transaction?: Transaction): Promise<MVideoAccountLightBlacklistAllFiles> {
     const query: FindOptions = {
       where: {
         url
@@ -1355,7 +1358,7 @@ export class VideoModel extends Model<VideoModel> {
     ]).findOne(query)
   }
 
-  static loadAndPopulateAccountAndServerAndTags (id: number | string, t?: Transaction, userId?: number): Bluebird<MVideoFullLight> {
+  static loadAndPopulateAccountAndServerAndTags (id: number | string, t?: Transaction, userId?: number): Promise<MVideoFullLight> {
     const where = buildWhereIdOrUUID(id)
 
     const options = {
@@ -1388,7 +1391,7 @@ export class VideoModel extends Model<VideoModel> {
     id: number | string
     t?: Transaction
     userId?: number
-  }): Bluebird<MVideoDetails> {
+  }): Promise<MVideoDetails> {
     const { id, t, userId } = parameters
     const where = buildWhereIdOrUUID(id)
 
@@ -1487,7 +1490,7 @@ export class VideoModel extends Model<VideoModel> {
     return VideoModel.update({ support: videoChannel.support }, options)
   }
 
-  static getAllIdsFromChannel (videoChannel: MChannelId): Bluebird<number[]> {
+  static getAllIdsFromChannel (videoChannel: MChannelId): Promise<number[]> {
     const query = {
       attributes: [ 'id' ],
       where: {

+ 1 - 6
server/tests/api/live/live.ts

@@ -686,12 +686,7 @@ describe('Test live', function () {
     it('Should save a live replay', async function () {
       this.timeout(60000)
 
-      await waitJobs(servers)
-
-      const res = await getVideo(servers[0].url, liveVideoReplayId)
-      const video: VideoDetails = res.body
-
-      expect(video.state.id).to.equal(VideoState.PUBLISHED)
+      await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId)
     })
   })
 

+ 1 - 2
server/types/plugins/register-server-option.model.ts

@@ -1,4 +1,3 @@
-import * as Bluebird from 'bluebird'
 import { Router } from 'express'
 import { Logger } from 'winston'
 import { ActorModel } from '@server/models/activitypub/actor'
@@ -29,7 +28,7 @@ export type PeerTubeHelpers = {
   }
 
   videos: {
-    loadByUrl: (url: string) => Bluebird<MVideoThumbnail>
+    loadByUrl: (url: string) => Promise<MVideoThumbnail>
 
     removeVideo: (videoId: number) => Promise<void>
   }

+ 24 - 44
yarn.lock

@@ -1985,14 +1985,6 @@ clone@^1.0.2:
   resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
   integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
 
-cls-bluebird@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/cls-bluebird/-/cls-bluebird-2.1.0.tgz#37ef1e080a8ffb55c2f4164f536f1919e7968aee"
-  integrity sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=
-  dependencies:
-    is-bluebird "^1.0.2"
-    shimmer "^1.1.0"
-
 cluster-key-slot@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d"
@@ -4135,11 +4127,6 @@ is-binary-path@~2.1.0:
   dependencies:
     binary-extensions "^2.0.0"
 
-is-bluebird@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/is-bluebird/-/is-bluebird-1.0.2.tgz#096439060f4aa411abee19143a84d6a55346d6e2"
-  integrity sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI=
-
 is-buffer@^1.1.5, is-buffer@~1.1.6:
   version "1.1.6"
   resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
@@ -5136,14 +5123,14 @@ mocha@^8.0.1:
     yargs-parser "13.1.2"
     yargs-unparser "2.0.0"
 
-moment-timezone@^0.5.21, moment-timezone@^0.5.31:
+moment-timezone@^0.5.31:
   version "0.5.32"
   resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.32.tgz#db7677cc3cc680fd30303ebd90b0da1ca0dfecc2"
   integrity sha512-Z8QNyuQHQAmWucp8Knmgei8YNo28aLjJq6Ma+jy1ZSpSk5nyfRT8xgUbSQvD2+2UajISfenndwvFuH3NGS+nvA==
   dependencies:
     moment ">= 2.9.0"
 
-"moment@>= 2.9.0", moment@^2.24.0:
+"moment@>= 2.9.0", moment@^2.26.0:
   version "2.29.1"
   resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
   integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
@@ -6926,38 +6913,36 @@ send@0.17.1:
     range-parser "~1.2.1"
     statuses "~1.5.0"
 
-sequelize-pool@^2.3.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-2.3.0.tgz#64f1fe8744228172c474f530604b6133be64993d"
-  integrity sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA==
+sequelize-pool@^6.0.0:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-6.1.0.tgz#caaa0c1e324d3c2c3a399fed2c7998970925d668"
+  integrity sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==
 
-sequelize-typescript@^1.0.0-beta.4:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/sequelize-typescript/-/sequelize-typescript-1.1.0.tgz#d5c2945e7fbfe55a934917b27d84589858d79123"
-  integrity sha512-FAPEQPeAhIaFQNLAcf9Q2IWcqWhNcvn5OZZ7BzGB0CJMtImIsGg4E/EAb7huMmPaPwDArxJUWGqk1KurphTNRA==
+sequelize-typescript@^2.0.0-beta.1:
+  version "2.0.0-beta.1"
+  resolved "https://registry.yarnpkg.com/sequelize-typescript/-/sequelize-typescript-2.0.0-beta.1.tgz#08c52c35e7fb4f940b9919cbc77752776bcc800a"
+  integrity sha512-GHlNfh8vPIJKzXtk4A8MTndK3Uu87HO75fFFX4PM+35P/SW3fFCiw/KeHeQ6DjLz7zeI+fop2HFWVeuZarnJwQ==
   dependencies:
     glob "7.1.2"
 
-sequelize@5.21.13:
-  version "5.21.13"
-  resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-5.21.13.tgz#c8c2f6a2d44d0a234c101155447d494d8d216c7b"
-  integrity sha512-wpwSpxzvADmgPkcOGeer5yFdAVsYeA7NLEw4evSXw03OlGL41J4S8hVz2/nilSWlJSwumlDGC9QbdwAmkWGqJg==
+sequelize@6.3.5:
+  version "6.3.5"
+  resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-6.3.5.tgz#80e3db7ac8b76d98c45ca93334197eb6e2335158"
+  integrity sha512-MiwiPkYSA8NWttRKAXdU9h0TxP6HAc1fl7qZmMO/VQqQOND83G4nZLXd0kWILtAoT9cxtZgFqeb/MPYgEeXwsw==
   dependencies:
-    bluebird "^3.5.0"
-    cls-bluebird "^2.1.0"
     debug "^4.1.1"
     dottie "^2.0.0"
     inflection "1.12.0"
     lodash "^4.17.15"
-    moment "^2.24.0"
-    moment-timezone "^0.5.21"
+    moment "^2.26.0"
+    moment-timezone "^0.5.31"
     retry-as-promised "^3.2.0"
-    semver "^6.3.0"
-    sequelize-pool "^2.3.0"
+    semver "^7.3.2"
+    sequelize-pool "^6.0.0"
     toposort-class "^1.0.1"
-    uuid "^3.3.3"
+    uuid "^8.1.0"
     validator "^10.11.0"
-    wkx "^0.4.8"
+    wkx "^0.5.0"
 
 serialize-javascript@5.0.1:
   version "5.0.1"
@@ -6998,11 +6983,6 @@ shebang-regex@^3.0.0:
   resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
   integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
 
-shimmer@^1.1.0:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337"
-  integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==
-
 signal-exit@^3.0.0, signal-exit@^3.0.2:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
@@ -8351,10 +8331,10 @@ with@^7.0.0:
     assert-never "^1.2.1"
     babel-walk "3.0.0-canary-5"
 
-wkx@^0.4.8:
-  version "0.4.8"
-  resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.4.8.tgz#a092cf088d112683fdc7182fd31493b2c5820003"
-  integrity sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==
+wkx@^0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.5.0.tgz#c6c37019acf40e517cc6b94657a25a3d4aa33e8c"
+  integrity sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==
   dependencies:
     "@types/node" "*"