1 import * as Sequelize from 'sequelize'
3 import { isVideoChannelNameValid, isVideoChannelDescriptionValid } from '../../helpers'
5 import { addMethodsToModel, getSort } from '../utils'
8 VideoChannelAttributes,
11 } from './video-channel-interface'
12 import { sendDeleteVideoChannel } from '../../lib/activitypub/send-request'
13 import { isVideoChannelUrlValid } from '../../helpers/custom-validators/video-channels'
14 import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
16 let VideoChannel: Sequelize.Model<VideoChannelInstance, VideoChannelAttributes>
17 let toFormattedJSON: VideoChannelMethods.ToFormattedJSON
18 let toActivityPubObject: VideoChannelMethods.ToActivityPubObject
19 let isOwned: VideoChannelMethods.IsOwned
20 let countByAccount: VideoChannelMethods.CountByAccount
21 let listOwned: VideoChannelMethods.ListOwned
22 let listForApi: VideoChannelMethods.ListForApi
23 let listByAccount: VideoChannelMethods.ListByAccount
24 let loadByIdAndAccount: VideoChannelMethods.LoadByIdAndAccount
25 let loadByUUID: VideoChannelMethods.LoadByUUID
26 let loadAndPopulateAccount: VideoChannelMethods.LoadAndPopulateAccount
27 let loadByUUIDAndPopulateAccount: VideoChannelMethods.LoadByUUIDAndPopulateAccount
28 let loadByHostAndUUID: VideoChannelMethods.LoadByHostAndUUID
29 let loadAndPopulateAccountAndVideos: VideoChannelMethods.LoadAndPopulateAccountAndVideos
30 let loadByUrl: VideoChannelMethods.LoadByUrl
31 let loadByUUIDOrUrl: VideoChannelMethods.LoadByUUIDOrUrl
33 export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
34 VideoChannel = sequelize.define<VideoChannelInstance, VideoChannelAttributes>('VideoChannel',
38 defaultValue: DataTypes.UUIDV4,
45 type: DataTypes.STRING,
49 const res = isVideoChannelNameValid(value)
50 if (res === false) throw new Error('Video channel name is not valid.')
55 type: DataTypes.STRING,
58 descriptionValid: value => {
59 const res = isVideoChannelDescriptionValid(value)
60 if (res === false) throw new Error('Video channel description is not valid.')
65 type: DataTypes.BOOLEAN,
70 type: DataTypes.STRING(CONSTRAINTS_FIELDS.VIDEO_CHANNELS.URL.max),
74 const res = isVideoChannelUrlValid(value)
75 if (res === false) throw new Error('Video channel URL is not valid.')
83 fields: [ 'accountId' ]
92 const classMethods = [
99 loadAndPopulateAccount,
100 loadByUUIDAndPopulateAccount,
103 loadAndPopulateAccountAndVideos,
108 const instanceMethods = [
113 addMethodsToModel(VideoChannel, classMethods, instanceMethods)
118 // ------------------------------ METHODS ------------------------------
120 isOwned = function (this: VideoChannelInstance) {
121 return this.remote === false
124 toFormattedJSON = function (this: VideoChannelInstance) {
129 description: this.description,
130 isLocal: this.isOwned(),
131 createdAt: this.createdAt,
132 updatedAt: this.updatedAt
135 if (this.Account !== undefined) {
137 name: this.Account.name,
138 uuid: this.Account.uuid
142 if (Array.isArray(this.Videos)) {
143 json['videos'] = this.Videos.map(v => v.toFormattedJSON())
149 toActivityPubObject = function (this: VideoChannelInstance) {
151 type: 'VideoChannel' as 'VideoChannel',
154 content: this.description,
156 published: this.createdAt,
157 updated: this.updatedAt
163 // ------------------------------ STATICS ------------------------------
165 function associate (models) {
166 VideoChannel.belongsTo(models.Account, {
174 VideoChannel.hasMany(models.Video, {
183 function afterDestroy (videoChannel: VideoChannelInstance) {
184 if (videoChannel.isOwned()) {
185 return sendDeleteVideoChannel(videoChannel, undefined)
191 countByAccount = function (accountId: number) {
198 return VideoChannel.count(query)
201 listOwned = function () {
206 include: [ VideoChannel['sequelize'].models.Account ]
209 return VideoChannel.findAll(query)
212 listForApi = function (start: number, count: number, sort: string) {
216 order: [ getSort(sort) ],
219 model: VideoChannel['sequelize'].models.Account,
221 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
226 return VideoChannel.findAndCountAll(query).then(({ rows, count }) => {
227 return { total: count, data: rows }
231 listByAccount = function (accountId: number) {
233 order: [ getSort('createdAt') ],
236 model: VideoChannel['sequelize'].models.Account,
241 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
246 return VideoChannel.findAndCountAll(query).then(({ rows, count }) => {
247 return { total: count, data: rows }
251 loadByUUID = function (uuid: string, t?: Sequelize.Transaction) {
252 const query: Sequelize.FindOptions<VideoChannelAttributes> = {
258 if (t !== undefined) query.transaction = t
260 return VideoChannel.findOne(query)
263 loadByUrl = function (url: string, t?: Sequelize.Transaction) {
264 const query: Sequelize.FindOptions<VideoChannelAttributes> = {
270 if (t !== undefined) query.transaction = t
272 return VideoChannel.findOne(query)
275 loadByUUIDOrUrl = function (uuid: string, url: string, t?: Sequelize.Transaction) {
276 const query: Sequelize.FindOptions<VideoChannelAttributes> = {
285 if (t !== undefined) query.transaction = t
287 return VideoChannel.findOne(query)
290 loadByHostAndUUID = function (fromHost: string, uuid: string, t?: Sequelize.Transaction) {
291 const query: Sequelize.FindOptions<VideoChannelAttributes> = {
297 model: VideoChannel['sequelize'].models.Account,
300 model: VideoChannel['sequelize'].models.Pod,
311 if (t !== undefined) query.transaction = t
313 return VideoChannel.findOne(query)
316 loadByIdAndAccount = function (id: number, accountId: number) {
324 model: VideoChannel['sequelize'].models.Account,
325 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
330 return VideoChannel.findOne(options)
333 loadAndPopulateAccount = function (id: number) {
337 model: VideoChannel['sequelize'].models.Account,
338 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
343 return VideoChannel.findById(id, options)
346 loadByUUIDAndPopulateAccount = function (uuid: string) {
353 model: VideoChannel['sequelize'].models.Account,
354 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
359 return VideoChannel.findOne(options)
362 loadAndPopulateAccountAndVideos = function (id: number) {
366 model: VideoChannel['sequelize'].models.Account,
367 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
369 VideoChannel['sequelize'].models.Video
373 return VideoChannel.findById(id, options)