diff options
-rw-r--r-- | server/lib/activitypub/videos/shared/abstract-builder.ts | 25 | ||||
-rw-r--r-- | server/models/video/video-caption.ts | 19 |
2 files changed, 35 insertions, 9 deletions
diff --git a/server/lib/activitypub/videos/shared/abstract-builder.ts b/server/lib/activitypub/videos/shared/abstract-builder.ts index 22280fce1..e89c94bcd 100644 --- a/server/lib/activitypub/videos/shared/abstract-builder.ts +++ b/server/lib/activitypub/videos/shared/abstract-builder.ts | |||
@@ -75,11 +75,28 @@ export abstract class APVideoAbstractBuilder { | |||
75 | } | 75 | } |
76 | 76 | ||
77 | protected async insertOrReplaceCaptions (video: MVideoFullLight, t: Transaction) { | 77 | protected async insertOrReplaceCaptions (video: MVideoFullLight, t: Transaction) { |
78 | const videoCaptionsPromises = getCaptionAttributesFromObject(video, this.videoObject) | 78 | const existingCaptions = await VideoCaptionModel.listVideoCaptions(video.id, t) |
79 | .map(a => new VideoCaptionModel(a) as MVideoCaption) | ||
80 | .map(c => VideoCaptionModel.insertOrReplaceLanguage(c, t)) | ||
81 | 79 | ||
82 | await Promise.all(videoCaptionsPromises) | 80 | let captionsToCreate = getCaptionAttributesFromObject(video, this.videoObject) |
81 | .map(a => new VideoCaptionModel(a) as MVideoCaption) | ||
82 | |||
83 | for (const existingCaption of existingCaptions) { | ||
84 | // Only keep captions that do not already exist | ||
85 | const filtered = captionsToCreate.filter(c => !c.isEqual(existingCaption)) | ||
86 | |||
87 | // This caption already exists, we don't need to destroy and create it | ||
88 | if (filtered.length !== captionsToCreate.length) { | ||
89 | captionsToCreate = filtered | ||
90 | continue | ||
91 | } | ||
92 | |||
93 | // Destroy this caption that does not exist anymore | ||
94 | await existingCaption.destroy({ transaction: t }) | ||
95 | } | ||
96 | |||
97 | for (const captionToCreate of captionsToCreate) { | ||
98 | await captionToCreate.save({ transaction: t }) | ||
99 | } | ||
83 | } | 100 | } |
84 | 101 | ||
85 | protected async insertOrReplaceLive (video: MVideoFullLight, transaction: Transaction) { | 102 | protected async insertOrReplaceLive (video: MVideoFullLight, transaction: Transaction) { |
diff --git a/server/models/video/video-caption.ts b/server/models/video/video-caption.ts index d2c742b66..b4918e519 100644 --- a/server/models/video/video-caption.ts +++ b/server/models/video/video-caption.ts | |||
@@ -109,11 +109,12 @@ export class VideoCaptionModel extends Model<Partial<AttributesOnly<VideoCaption | |||
109 | return undefined | 109 | return undefined |
110 | } | 110 | } |
111 | 111 | ||
112 | static loadByVideoIdAndLanguage (videoId: string | number, language: string): Promise<MVideoCaptionVideo> { | 112 | static loadByVideoIdAndLanguage (videoId: string | number, language: string, transaction?: Transaction): Promise<MVideoCaptionVideo> { |
113 | const videoInclude = { | 113 | const videoInclude = { |
114 | model: VideoModel.unscoped(), | 114 | model: VideoModel.unscoped(), |
115 | attributes: [ 'id', 'remote', 'uuid' ], | 115 | attributes: [ 'id', 'remote', 'uuid' ], |
116 | where: buildWhereIdOrUUID(videoId) | 116 | where: buildWhereIdOrUUID(videoId), |
117 | transaction | ||
117 | } | 118 | } |
118 | 119 | ||
119 | const query = { | 120 | const query = { |
@@ -145,19 +146,21 @@ export class VideoCaptionModel extends Model<Partial<AttributesOnly<VideoCaption | |||
145 | } | 146 | } |
146 | 147 | ||
147 | static async insertOrReplaceLanguage (caption: MVideoCaption, transaction: Transaction) { | 148 | static async insertOrReplaceLanguage (caption: MVideoCaption, transaction: Transaction) { |
148 | const existing = await VideoCaptionModel.loadByVideoIdAndLanguage(caption.videoId, caption.language) | 149 | const existing = await VideoCaptionModel.loadByVideoIdAndLanguage(caption.videoId, caption.language, transaction) |
150 | |||
149 | // Delete existing file | 151 | // Delete existing file |
150 | if (existing) await existing.destroy({ transaction }) | 152 | if (existing) await existing.destroy({ transaction }) |
151 | 153 | ||
152 | return caption.save({ transaction }) | 154 | return caption.save({ transaction }) |
153 | } | 155 | } |
154 | 156 | ||
155 | static listVideoCaptions (videoId: number): Promise<MVideoCaptionVideo[]> { | 157 | static listVideoCaptions (videoId: number, transaction: Transaction): Promise<MVideoCaptionVideo[]> { |
156 | const query = { | 158 | const query = { |
157 | order: [ [ 'language', 'ASC' ] ] as OrderItem[], | 159 | order: [ [ 'language', 'ASC' ] ] as OrderItem[], |
158 | where: { | 160 | where: { |
159 | videoId | 161 | videoId |
160 | } | 162 | }, |
163 | transaction | ||
161 | } | 164 | } |
162 | 165 | ||
163 | return VideoCaptionModel.scope(ScopeNames.WITH_VIDEO_UUID_AND_REMOTE).findAll(query) | 166 | return VideoCaptionModel.scope(ScopeNames.WITH_VIDEO_UUID_AND_REMOTE).findAll(query) |
@@ -211,4 +214,10 @@ export class VideoCaptionModel extends Model<Partial<AttributesOnly<VideoCaption | |||
211 | 214 | ||
212 | return this.fileUrl | 215 | return this.fileUrl |
213 | } | 216 | } |
217 | |||
218 | isEqual (this: MVideoCaption, other: MVideoCaption) { | ||
219 | if (this.fileUrl) return this.fileUrl === other.fileUrl | ||
220 | |||
221 | return this.filename === other.filename | ||
222 | } | ||
214 | } | 223 | } |