1 import * as Sequelize from 'sequelize'
18 } from 'sequelize-typescript'
19 import { IFindOptions } from 'sequelize-typescript/lib/interfaces/IFindOptions'
20 import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../../helpers/custom-validators/video-channels'
21 import { sendDeleteVideoChannel } from '../../lib/activitypub/send'
22 import { AccountModel } from '../account/account'
23 import { ActorModel } from '../activitypub/actor'
24 import { ServerModel } from '../server/server'
25 import { getSort, throwIfNotValid } from '../utils'
26 import { VideoModel } from './video'
27 import { VideoChannelShareModel } from './video-channel-share'
30 WITH_ACCOUNT = 'WITH_ACCOUNT',
31 WITH_VIDEOS = 'WITH_VIDEOS'
35 [ScopeNames.WITH_ACCOUNT]: {
38 model: () => AccountModel,
39 include: [ { model: () => ServerModel, required: false } ]
43 [ScopeNames.WITH_VIDEOS]: {
50 tableName: 'videoChannel',
53 fields: [ 'accountId' ]
57 export class VideoChannelModel extends Model<VideoChannelModel> {
60 @Default(DataType.UUIDV4)
62 @Column(DataType.UUID)
66 @Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelNameValid, 'name'))
71 @Is('VideoChannelDescription', value => throwIfNotValid(value, isVideoChannelDescriptionValid, 'description'))
85 @ForeignKey(() => ActorModel)
89 @BelongsTo(() => ActorModel, {
97 @ForeignKey(() => AccountModel)
101 @BelongsTo(() => AccountModel, {
107 Account: AccountModel
109 @HasMany(() => VideoModel, {
118 @HasMany(() => VideoChannelShareModel, {
125 VideoChannelShares: VideoChannelShareModel[]
128 static sendDeleteIfOwned (instance: VideoChannelModel) {
129 if (instance.isOwned()) {
130 return sendDeleteVideoChannel(instance, undefined)
136 static countByAccount (accountId: number) {
143 return VideoChannelModel.count(query)
146 static listForApi (start: number, count: number, sort: string) {
150 order: [ getSort(sort) ]
153 return VideoChannelModel.scope(ScopeNames.WITH_ACCOUNT).findAndCountAll(query)
154 .then(({ rows, count }) => {
155 return { total: count, data: rows }
159 static listByAccount (accountId: number) {
161 order: [ getSort('createdAt') ],
169 include: [ { model: ServerModel, required: false } ]
174 return VideoChannelModel.findAndCountAll(query)
175 .then(({ rows, count }) => {
176 return { total: count, data: rows }
180 static loadByUrl (url: string, t?: Sequelize.Transaction) {
181 const query: IFindOptions<VideoChannelModel> = {
193 if (t !== undefined) query.transaction = t
195 return VideoChannelModel.scope(ScopeNames.WITH_ACCOUNT).findOne(query)
198 static loadByUUIDOrUrl (uuid: string, url: string, t?: Sequelize.Transaction) {
199 const query: IFindOptions<VideoChannelModel> = {
201 [ Sequelize.Op.or ]: [
208 if (t !== undefined) query.transaction = t
210 return VideoChannelModel.findOne(query)
213 static loadByIdAndAccount (id: number, accountId: number) {
221 return VideoChannelModel.scope(ScopeNames.WITH_ACCOUNT).findOne(options)
224 static loadAndPopulateAccount (id: number) {
225 return VideoChannelModel.scope(ScopeNames.WITH_ACCOUNT).findById(id)
228 static loadByUUIDAndPopulateAccount (uuid: string) {
235 return VideoChannelModel.scope(ScopeNames.WITH_ACCOUNT).findOne(options)
238 static loadAndPopulateAccountAndVideos (id: number) {
245 return VideoChannelModel.scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_VIDEOS ]).findById(id, options)
249 return this.remote === false
257 description: this.description,
258 isLocal: this.isOwned(),
259 createdAt: this.createdAt,
260 updatedAt: this.updatedAt
263 if (this.Account !== undefined) {
265 name: this.Account.name,
266 uuid: this.Account.uuid
270 if (Array.isArray(this.Videos)) {
271 json[ 'videos' ] = this.Videos.map(v => v.toFormattedJSON())
277 toActivityPubObject () {
278 return this.Actor.toActivityPubObject(this.name, this.uuid, 'VideoChannel')