import { Transaction } from 'sequelize/types'
-import { checkUrlsSameHost } from '@server/helpers/activitypub'
-import { deleteNonExistingModels } from '@server/helpers/database-utils'
+import { deleteAllModels, filterNonExistingModels } from '@server/helpers/database-utils'
import { logger, LoggerTagsFn } from '@server/helpers/logger'
-import { createPlaceholderThumbnail, createVideoMiniatureFromUrl } from '@server/lib/thumbnail'
+import { updatePlaceholderThumbnail, updateVideoMiniatureFromUrl } from '@server/lib/thumbnail'
import { setVideoTags } from '@server/lib/video'
import { VideoCaptionModel } from '@server/models/video/video-caption'
import { VideoFileModel } from '@server/models/video/video-file'
import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist'
import { MStreamingPlaylistFilesVideo, MThumbnail, MVideoCaption, MVideoFile, MVideoFullLight, MVideoThumbnail } from '@server/types/models'
import { ActivityTagObject, ThumbnailType, VideoObject, VideoStreamingPlaylistType } from '@shared/models'
-import { getOrCreateActorAndServerAndModel } from '../../actor'
+import { getOrCreateAPActor } from '../../actors'
+import { checkUrlsSameHost } from '../../url'
import {
getCaptionAttributesFromObject,
getFileAttributesFromUrl,
throw new Error(`Video channel url ${channel.id} does not have the same host than video object id ${this.videoObject.id}`)
}
- return getOrCreateActorAndServerAndModel(channel.id, 'all')
+ return getOrCreateAPActor(channel.id, 'all')
}
protected tryToGenerateThumbnail (video: MVideoThumbnail): Promise<MThumbnail> {
- return createVideoMiniatureFromUrl({
+ return updateVideoMiniatureFromUrl({
downloadUrl: getThumbnailFromIcons(this.videoObject).url,
video,
type: ThumbnailType.MINIATURE
}).catch(err => {
- logger.warn('Cannot generate thumbnail of %s.', this.videoObject.id, { err, ...this.lTags(video.uuid) })
+ logger.warn('Cannot generate thumbnail of %s.', this.videoObject.id, { err, ...this.lTags() })
return undefined
})
}
- protected async setPreview (video: MVideoFullLight, t: Transaction) {
+ protected async setPreview (video: MVideoFullLight, t?: Transaction) {
// Don't fetch the preview that could be big, create a placeholder instead
const previewIcon = getPreviewFromIcons(this.videoObject)
if (!previewIcon) return
- const previewModel = createPlaceholderThumbnail({
+ const previewModel = updatePlaceholderThumbnail({
fileUrl: previewIcon.url,
video,
type: ThumbnailType.PREVIEW,
}
protected async insertOrReplaceCaptions (video: MVideoFullLight, t: Transaction) {
- const videoCaptionsPromises = getCaptionAttributesFromObject(video, this.videoObject)
- .map(a => new VideoCaptionModel(a) as MVideoCaption)
- .map(c => VideoCaptionModel.insertOrReplaceLanguage(c, t))
+ const existingCaptions = await VideoCaptionModel.listVideoCaptions(video.id, t)
- await Promise.all(videoCaptionsPromises)
+ let captionsToCreate = getCaptionAttributesFromObject(video, this.videoObject)
+ .map(a => new VideoCaptionModel(a) as MVideoCaption)
+
+ for (const existingCaption of existingCaptions) {
+ // Only keep captions that do not already exist
+ const filtered = captionsToCreate.filter(c => !c.isEqual(existingCaption))
+
+ // This caption already exists, we don't need to destroy and create it
+ if (filtered.length !== captionsToCreate.length) {
+ captionsToCreate = filtered
+ continue
+ }
+
+ // Destroy this caption that does not exist anymore
+ await existingCaption.destroy({ transaction: t })
+ }
+
+ for (const captionToCreate of captionsToCreate) {
+ await captionToCreate.save({ transaction: t })
+ }
}
protected async insertOrReplaceLive (video: MVideoFullLight, transaction: Transaction) {
const newVideoFiles = videoFileAttributes.map(a => new VideoFileModel(a))
// Remove video files that do not exist anymore
- const destroyTasks = deleteNonExistingModels(video.VideoFiles || [], newVideoFiles, t)
- await Promise.all(destroyTasks)
+ await deleteAllModels(filterNonExistingModels(video.VideoFiles || [], newVideoFiles), t)
// Update or add other one
const upsertTasks = newVideoFiles.map(f => VideoFileModel.customUpsert(f, 'video', t))
}
protected async setStreamingPlaylists (video: MVideoFullLight, t: Transaction) {
- const streamingPlaylistAttributes = getStreamingPlaylistAttributesFromObject(video, this.videoObject, video.VideoFiles || [])
+ const streamingPlaylistAttributes = getStreamingPlaylistAttributesFromObject(video, this.videoObject)
const newStreamingPlaylists = streamingPlaylistAttributes.map(a => new VideoStreamingPlaylistModel(a))
// Remove video playlists that do not exist anymore
- const destroyTasks = deleteNonExistingModels(video.VideoStreamingPlaylists || [], newStreamingPlaylists, t)
- await Promise.all(destroyTasks)
+ await deleteAllModels(filterNonExistingModels(video.VideoStreamingPlaylists || [], newStreamingPlaylists), t)
video.VideoStreamingPlaylists = []
for (const playlistAttributes of streamingPlaylistAttributes) {
-
const streamingPlaylistModel = await this.insertOrReplaceStreamingPlaylist(playlistAttributes, t)
streamingPlaylistModel.Video = video
const newVideoFiles: MVideoFile[] = getFileAttributesFromUrl(playlistModel, tagObjects).map(a => new VideoFileModel(a))
- const destroyTasks = deleteNonExistingModels(oldStreamingPlaylistFiles, newVideoFiles, t)
- await Promise.all(destroyTasks)
+ await deleteAllModels(filterNonExistingModels(oldStreamingPlaylistFiles, newVideoFiles), t)
// Update or add other one
const upsertTasks = newVideoFiles.map(f => VideoFileModel.customUpsert(f, 'streaming-playlist', t))