1 import { Op } from 'sequelize'
15 } from 'sequelize-typescript'
16 import { isUrlValid } from '@server/helpers/custom-validators/activitypub/misc'
17 import { isVideoChannelSyncStateValid } from '@server/helpers/custom-validators/video-channel-syncs'
18 import { CONSTRAINTS_FIELDS, VIDEO_CHANNEL_SYNC_STATE } from '@server/initializers/constants'
19 import { MChannelSync, MChannelSyncChannel, MChannelSyncFormattable } from '@server/types/models'
20 import { VideoChannelSync, VideoChannelSyncState } from '@shared/models'
21 import { AttributesOnly } from '@shared/typescript-utils'
22 import { AccountModel } from '../account/account'
23 import { UserModel } from '../user/user'
24 import { getChannelSyncSort, throwIfNotValid } from '../shared'
25 import { VideoChannelModel } from './video-channel'
27 @DefaultScope(() => ({
30 model: VideoChannelModel, // Default scope includes avatar and server
36 tableName: 'videoChannelSync',
39 fields: [ 'videoChannelId' ]
43 export class VideoChannelSyncModel extends Model<Partial<AttributesOnly<VideoChannelSyncModel>>> {
47 @Is('VideoChannelExternalChannelUrl', value => throwIfNotValid(value, isUrlValid, 'externalChannelUrl', true))
48 @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_CHANNEL_SYNCS.EXTERNAL_CHANNEL_URL.max))
49 externalChannelUrl: string
57 @ForeignKey(() => VideoChannelModel)
59 videoChannelId: number
61 @BelongsTo(() => VideoChannelModel, {
67 VideoChannel: VideoChannelModel
70 @Default(VideoChannelSyncState.WAITING_FIRST_RUN)
71 @Is('VideoChannelSyncState', value => throwIfNotValid(value, isVideoChannelSyncStateValid, 'state'))
73 state: VideoChannelSyncState
76 @Column(DataType.DATE)
79 static listByAccountForAPI (options: {
85 const getQuery = (forCount: boolean) => {
86 const videoChannelModel = forCount
87 ? VideoChannelModel.unscoped()
91 offset: options.start,
93 order: getChannelSyncSort(options.sort),
96 model: videoChannelModel,
99 accountId: options.accountId
107 VideoChannelSyncModel.unscoped().count(getQuery(true)),
108 VideoChannelSyncModel.unscoped().findAll(getQuery(false))
109 ]).then(([ total, data ]) => ({ total, data }))
112 static countByAccount (accountId: number) {
116 model: VideoChannelModel.unscoped(),
125 return VideoChannelSyncModel.unscoped().count(query)
128 static loadWithChannel (id: number): Promise<MChannelSyncChannel> {
129 return VideoChannelSyncModel.findByPk(id)
132 static async listSyncs (): Promise<MChannelSync[]> {
136 model: VideoChannelModel.unscoped(),
140 model: AccountModel.unscoped(),
144 model: UserModel.unscoped(),
160 return VideoChannelSyncModel.unscoped().findAll(query)
163 toFormattedJSON (this: MChannelSyncFormattable): VideoChannelSync {
168 label: VIDEO_CHANNEL_SYNC_STATE[this.state]
170 externalChannelUrl: this.externalChannelUrl,
171 createdAt: this.createdAt.toISOString(),
172 channel: this.VideoChannel.toFormattedSummaryJSON(),
173 lastSyncAt: this.lastSyncAt?.toISOString()