Table,
UpdatedAt
} from 'sequelize-typescript'
-import { buildRemoteVideoBaseUrl } from '@server/helpers/activitypub'
-import { MVideoAccountLight, MVideoCaption, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models'
+import { MVideo, MVideoCaption, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models'
+import { buildUUID } from '@shared/extra-utils'
+import { AttributesOnly } from '@shared/typescript-utils'
import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model'
import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions'
import { logger } from '../../helpers/logger'
import { CONSTRAINTS_FIELDS, LAZY_STATIC_PATHS, VIDEO_LANGUAGES, WEBSERVER } from '../../initializers/constants'
import { buildWhereIdOrUUID, throwIfNotValid } from '../utils'
import { VideoModel } from './video'
-import { v4 as uuidv4 } from 'uuid'
export enum ScopeNames {
WITH_VIDEO_UUID_AND_REMOTE = 'WITH_VIDEO_UUID_AND_REMOTE'
}
]
})
-export class VideoCaptionModel extends Model {
+export class VideoCaptionModel extends Model<Partial<AttributesOnly<VideoCaptionModel>>> {
@CreatedAt
createdAt: Date
Video: VideoModel
@BeforeDestroy
- static async removeFiles (instance: VideoCaptionModel) {
+ static async removeFiles (instance: VideoCaptionModel, options) {
if (!instance.Video) {
- instance.Video = await instance.$get('Video')
+ instance.Video = await instance.$get('Video', { transaction: options.transaction })
}
if (instance.isOwned()) {
return undefined
}
- static loadByVideoIdAndLanguage (videoId: string | number, language: string): Promise<MVideoCaptionVideo> {
+ static loadByVideoIdAndLanguage (videoId: string | number, language: string, transaction?: Transaction): Promise<MVideoCaptionVideo> {
const videoInclude = {
model: VideoModel.unscoped(),
attributes: [ 'id', 'remote', 'uuid' ],
},
include: [
videoInclude
- ]
+ ],
+ transaction
}
return VideoCaptionModel.findOne(query)
}
static async insertOrReplaceLanguage (caption: MVideoCaption, transaction: Transaction) {
- const existing = await VideoCaptionModel.loadByVideoIdAndLanguage(caption.videoId, caption.language)
+ const existing = await VideoCaptionModel.loadByVideoIdAndLanguage(caption.videoId, caption.language, transaction)
+
// Delete existing file
if (existing) await existing.destroy({ transaction })
return caption.save({ transaction })
}
- static listVideoCaptions (videoId: number): Promise<MVideoCaptionVideo[]> {
+ static listVideoCaptions (videoId: number, transaction?: Transaction): Promise<MVideoCaptionVideo[]> {
const query = {
order: [ [ 'language', 'ASC' ] ] as OrderItem[],
where: {
videoId
- }
+ },
+ transaction
}
return VideoCaptionModel.scope(ScopeNames.WITH_VIDEO_UUID_AND_REMOTE).findAll(query)
}
static generateCaptionName (language: string) {
- return `${uuidv4()}-${language}.vtt`
+ return `${buildUUID()}-${language}.vtt`
}
isOwned () {
return remove(CONFIG.STORAGE.CAPTIONS_DIR + this.filename)
}
- getFileUrl (video: MVideoAccountLight) {
+ getFileUrl (video: MVideo) {
if (!this.Video) this.Video = video as VideoModel
if (video.isOwned()) return WEBSERVER.URL + this.getCaptionStaticPath()
- if (this.fileUrl) return this.fileUrl
- // Fallback if we don't have a file URL
- return buildRemoteVideoBaseUrl(video, this.getCaptionStaticPath())
+ return this.fileUrl
+ }
+
+ isEqual (this: MVideoCaption, other: MVideoCaption) {
+ if (this.fileUrl) return this.fileUrl === other.fileUrl
+
+ return this.filename === other.filename
}
}