-import { WhereOptions } from 'sequelize'
+import { IncludeOptions, Op, WhereOptions } from 'sequelize'
import {
AfterUpdate,
AllowNull,
import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos'
import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants'
import { UserModel } from '../user/user'
-import { getSort, throwIfNotValid } from '../utils'
+import { getSort, searchAttribute, throwIfNotValid } from '../shared'
import { ScopeNames as VideoModelScopeNames, VideoModel } from './video'
+import { VideoChannelSyncModel } from './video-channel-sync'
+
+const defaultVideoScope = () => {
+ return VideoModel.scope([
+ VideoModelScopeNames.WITH_ACCOUNT_DETAILS,
+ VideoModelScopeNames.WITH_TAGS,
+ VideoModelScopeNames.WITH_THUMBNAILS
+ ])
+}
@DefaultScope(() => ({
include: [
required: true
},
{
- model: VideoModel.scope([
- VideoModelScopeNames.WITH_ACCOUNT_DETAILS,
- VideoModelScopeNames.WITH_TAGS,
- VideoModelScopeNames.WITH_THUMBNAILS
- ]),
+ model: defaultVideoScope(),
+ required: false
+ },
+ {
+ model: VideoChannelSyncModel.unscoped(),
required: false
}
]
})
Video: VideoModel
+ @ForeignKey(() => VideoChannelSyncModel)
+ @Column
+ videoChannelSyncId: number
+
+ @BelongsTo(() => VideoChannelSyncModel, {
+ foreignKey: {
+ allowNull: true
+ },
+ onDelete: 'set null'
+ })
+ VideoChannelSync: VideoChannelSyncModel
+
@AfterUpdate
static deleteVideoIfFailed (instance: VideoImportModel, options) {
if (instance.state === VideoImportState.FAILED) {
count: number
sort: string
+ search?: string
targetUrl?: string
+ videoChannelSyncId?: number
}) {
- const { userId, start, count, sort, targetUrl } = options
+ const { userId, start, count, sort, targetUrl, videoChannelSyncId, search } = options
const where: WhereOptions = { userId }
+ const include: IncludeOptions[] = [
+ {
+ attributes: [ 'id' ],
+ model: UserModel.unscoped(), // FIXME: Without this, sequelize try to COUNT(DISTINCT(*)) which is an invalid SQL query
+ required: true
+ },
+ {
+ model: VideoChannelSyncModel.unscoped(),
+ required: false
+ }
+ ]
if (targetUrl) where['targetUrl'] = targetUrl
+ if (videoChannelSyncId) where['videoChannelSyncId'] = videoChannelSyncId
+
+ if (search) {
+ include.push({
+ model: defaultVideoScope(),
+ required: true,
+ where: searchAttribute(search, 'name')
+ })
+ } else {
+ include.push({
+ model: defaultVideoScope(),
+ required: false
+ })
+ }
const query = {
distinct: true,
- include: [
- {
- attributes: [ 'id' ],
- model: UserModel.unscoped(), // FIXME: Without this, sequelize try to COUNT(DISTINCT(*)) which is an invalid SQL query
- required: true
- }
- ],
+ include,
offset: start,
limit: count,
order: getSort(sort),
]).then(([ total, data ]) => ({ total, data }))
}
+ static async urlAlreadyImported (channelId: number, targetUrl: string): Promise<boolean> {
+ const element = await VideoImportModel.unscoped().findOne({
+ where: {
+ targetUrl,
+ state: {
+ [Op.in]: [ VideoImportState.PENDING, VideoImportState.PROCESSING, VideoImportState.SUCCESS ]
+ }
+ },
+ include: [
+ {
+ model: VideoModel,
+ required: true,
+ where: {
+ channelId
+ }
+ }
+ ]
+ })
+
+ return !!element
+ }
+
getTargetIdentifier () {
return this.targetUrl || this.magnetUri || this.torrentName
}
? Object.assign(this.Video.toFormattedJSON(videoFormatOptions), { tags: this.Video.Tags.map(t => t.name) })
: undefined
+ const videoChannelSync = this.VideoChannelSync
+ ? { id: this.VideoChannelSync.id, externalChannelUrl: this.VideoChannelSync.externalChannelUrl }
+ : undefined
+
return {
id: this.id,
error: this.error,
updatedAt: this.updatedAt.toISOString(),
createdAt: this.createdAt.toISOString(),
- video
+ video,
+ videoChannelSync
}
}