2 import { logger, loggerTagsFactory, LoggerTagsFn } from '@server/helpers/logger'
3 import { sequelizeTypescript } from '@server/initializers/database'
4 import { Hooks } from '@server/lib/plugins/hooks'
5 import { autoBlacklistVideoIfNeeded } from '@server/lib/video-blacklist'
6 import { VideoModel } from '@server/models/video/video'
7 import { MThumbnail, MVideoFullLight, MVideoThumbnail } from '@server/types/models'
8 import { VideoObject } from '@shared/models'
9 import { APVideoAbstractBuilder } from './abstract-builder'
10 import { getVideoAttributesFromObject } from './object-to-model-attributes'
12 export class APVideoCreator extends APVideoAbstractBuilder {
13 protected lTags: LoggerTagsFn
15 constructor (protected readonly videoObject: VideoObject) {
18 this.lTags = loggerTagsFactory('ap', 'video', 'create', this.videoObject.uuid, this.videoObject.id)
21 async create (waitThumbnail = false) {
22 logger.debug('Adding remote video %s.', this.videoObject.id, this.lTags())
24 const channelActor = await this.getOrCreateVideoChannelFromVideoObject()
25 const channel = channelActor.VideoChannel
27 const videoData = getVideoAttributesFromObject(channel, this.videoObject, this.videoObject.to)
28 const video = VideoModel.build({ ...videoData, likes: 0, dislikes: 0 }) as MVideoThumbnail
30 const promiseThumbnail = this.tryToGenerateThumbnail(video)
32 let thumbnailModel: MThumbnail
33 if (waitThumbnail === true) {
34 thumbnailModel = await promiseThumbnail
37 const { autoBlacklisted, videoCreated } = await sequelizeTypescript.transaction(async t => {
39 const videoCreated = await video.save({ transaction: t }) as MVideoFullLight
40 videoCreated.VideoChannel = channel
42 if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t)
44 await this.setPreview(videoCreated, t)
45 await this.setWebTorrentFiles(videoCreated, t)
46 await this.setStreamingPlaylists(videoCreated, t)
47 await this.setTags(videoCreated, t)
48 await this.setTrackers(videoCreated, t)
49 await this.insertOrReplaceCaptions(videoCreated, t)
50 await this.insertOrReplaceLive(videoCreated, t)
52 // We added a video in this channel, set it as updated
53 await channel.setAsUpdated(t)
55 const autoBlacklisted = await autoBlacklistVideoIfNeeded({
63 logger.info('Remote video with uuid %s inserted.', this.videoObject.uuid, this.lTags())
65 Hooks.runAction('action:activity-pub.remote-video.created', { video: videoCreated, videoAPObject: this.videoObject })
67 return { autoBlacklisted, videoCreated }
69 // FIXME: Use rollback hook when https://github.com/sequelize/sequelize/pull/13038 is released
70 if (thumbnailModel) await thumbnailModel.removeThumbnail()
76 if (waitThumbnail === false) {
77 // Error is already caught above
78 // eslint-disable-next-line @typescript-eslint/no-floating-promises
79 promiseThumbnail.then(thumbnailModel => {
80 if (!thumbnailModel) return
82 thumbnailModel = videoCreated.id
84 return thumbnailModel.save()
88 return { autoBlacklisted, videoCreated }