215 lines
4.5 KiB
TypeScript
215 lines
4.5 KiB
TypeScript
import { FindAndCountOptions, Op, Transaction } from 'sequelize'
|
|
import {
|
|
AllowNull,
|
|
BelongsTo,
|
|
Column,
|
|
CreatedAt,
|
|
DataType,
|
|
Default,
|
|
ForeignKey,
|
|
Table,
|
|
UpdatedAt
|
|
} from 'sequelize-typescript'
|
|
import { MLiveVideo } from '@server/types/models/index.js'
|
|
import { UserModel } from '../user/user.js'
|
|
import { SequelizeModel } from '../shared/index.js'
|
|
|
|
export enum LiveVideoStatus {
|
|
SCHEDULED = 'scheduled',
|
|
CANCELLED = 'cancelled',
|
|
COMPLETED = 'completed'
|
|
}
|
|
|
|
@Table({
|
|
tableName: 'liveVideo',
|
|
indexes: [
|
|
{
|
|
fields: [ 'targetCamera' ]
|
|
},
|
|
{
|
|
fields: [ 'startTime' ]
|
|
},
|
|
{
|
|
fields: [ 'status' ]
|
|
}
|
|
]
|
|
})
|
|
export class LiveVideoModel extends SequelizeModel<LiveVideoModel> {
|
|
@AllowNull(false)
|
|
@Column
|
|
declare title: string
|
|
|
|
@AllowNull(true)
|
|
@Column
|
|
declare thumbnailFilename: string | null
|
|
|
|
@AllowNull(true)
|
|
@Column(DataType.BLOB)
|
|
declare thumbnailData: Buffer | null
|
|
|
|
@AllowNull(true)
|
|
@Column
|
|
declare thumbnailMimeType: string | null
|
|
|
|
@AllowNull(true)
|
|
@Column(DataType.BIGINT)
|
|
declare thumbnailSize: number | null
|
|
|
|
@AllowNull(true)
|
|
@Column
|
|
declare thumbnailEtag: string | null
|
|
|
|
@AllowNull(false)
|
|
@Column
|
|
declare videoOriginalName: string
|
|
|
|
@AllowNull(false)
|
|
@Column(DataType.TEXT)
|
|
declare videoStoragePath: string
|
|
|
|
@AllowNull(false)
|
|
@Column
|
|
declare videoMimeType: string
|
|
|
|
@AllowNull(false)
|
|
@Column(DataType.BIGINT)
|
|
declare videoSize: number
|
|
|
|
@AllowNull(false)
|
|
@Column
|
|
declare startTime: Date
|
|
|
|
@AllowNull(false)
|
|
@Column
|
|
declare endTime: Date
|
|
|
|
@AllowNull(false)
|
|
@Column
|
|
declare targetCamera: string
|
|
|
|
@AllowNull(false)
|
|
@Default(LiveVideoStatus.SCHEDULED)
|
|
@Column
|
|
declare status: LiveVideoStatus
|
|
|
|
@ForeignKey(() => UserModel)
|
|
@Column
|
|
declare createdByUserId: number
|
|
|
|
@BelongsTo(() => UserModel, {
|
|
foreignKey: {
|
|
allowNull: false
|
|
},
|
|
onDelete: 'restrict'
|
|
})
|
|
declare CreatedBy: Awaited<UserModel>
|
|
|
|
@CreatedAt
|
|
declare createdAt: Date
|
|
|
|
@UpdatedAt
|
|
declare updatedAt: Date
|
|
|
|
static listForApi (options: {
|
|
start?: number
|
|
count?: number
|
|
targetCamera?: string
|
|
status?: string
|
|
transaction?: Transaction
|
|
}) {
|
|
const query: FindAndCountOptions = {
|
|
offset: options.start,
|
|
limit: options.count,
|
|
order: [ [ 'startTime', 'DESC' ] ],
|
|
transaction: options.transaction
|
|
}
|
|
|
|
const where: Record<string, any> = {}
|
|
|
|
if (options.targetCamera) where.targetCamera = options.targetCamera
|
|
if (options.status) where.status = options.status
|
|
|
|
if (Object.keys(where).length !== 0) query.where = where
|
|
|
|
return LiveVideoModel.findAndCountAll<MLiveVideo>(query)
|
|
}
|
|
|
|
static loadById (id: number, transaction?: Transaction) {
|
|
return LiveVideoModel.findByPk<MLiveVideo>(id, { transaction })
|
|
}
|
|
|
|
static loadByThumbnailFilename (thumbnailFilename: string, transaction?: Transaction) {
|
|
return LiveVideoModel.findOne<MLiveVideo>({
|
|
where: {
|
|
thumbnailFilename
|
|
},
|
|
transaction
|
|
})
|
|
}
|
|
|
|
static listConflicts (options: {
|
|
targetCamera: string
|
|
startTime: Date
|
|
endTime: Date
|
|
excludeId?: number
|
|
transaction?: Transaction
|
|
}) {
|
|
const where: Record<string, any> = {
|
|
targetCamera: options.targetCamera,
|
|
status: {
|
|
[Op.not]: LiveVideoStatus.CANCELLED
|
|
}
|
|
}
|
|
|
|
if (options.excludeId) {
|
|
where.id = {
|
|
[Op.ne]: options.excludeId
|
|
}
|
|
}
|
|
|
|
return LiveVideoModel.findAll<MLiveVideo>({
|
|
where,
|
|
transaction: options.transaction
|
|
})
|
|
}
|
|
|
|
static listForStarting (options: {
|
|
startBefore: Date
|
|
endAfter: Date
|
|
transaction?: Transaction
|
|
}) {
|
|
return LiveVideoModel.findAll<MLiveVideo>({
|
|
where: {
|
|
status: LiveVideoStatus.SCHEDULED,
|
|
startTime: {
|
|
[Op.lte]: options.startBefore
|
|
},
|
|
endTime: {
|
|
[Op.gt]: options.endAfter
|
|
}
|
|
},
|
|
order: [ [ 'startTime', 'ASC' ] ],
|
|
transaction: options.transaction
|
|
})
|
|
}
|
|
|
|
toFormattedJSON (this: LiveVideoModel) {
|
|
return {
|
|
id: this.id,
|
|
title: this.title,
|
|
thumbnailFilename: this.thumbnailFilename,
|
|
videoOriginalName: this.videoOriginalName,
|
|
videoStoragePath: this.videoStoragePath,
|
|
videoMimeType: this.videoMimeType,
|
|
videoSize: this.videoSize,
|
|
startTime: this.startTime.toISOString(),
|
|
endTime: this.endTime.toISOString(),
|
|
targetCamera: this.targetCamera,
|
|
status: this.status,
|
|
createdByUserId: this.createdByUserId,
|
|
createdAt: this.createdAt.toISOString(),
|
|
updatedAt: this.updatedAt.toISOString()
|
|
}
|
|
}
|
|
}
|