]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/models/video/video-channel.ts
Fix lint
[github/Chocobozzz/PeerTube.git] / server / models / video / video-channel.ts
CommitLineData
3fd3ab2d 1import {
f05a1c30 2 AllowNull, BeforeDestroy, BelongsTo, Column, CreatedAt, DefaultScope, ForeignKey, HasMany, Is, Model, Scopes, Table,
a10fc78b 3 UpdatedAt, Default, DataType
3fd3ab2d 4} from 'sequelize-typescript'
50d6de9c 5import { ActivityPubActor } from '../../../shared/models/activitypub'
2422c46b
C
6import { VideoChannel } from '../../../shared/models/videos'
7import {
8 isVideoChannelDescriptionValid, isVideoChannelNameValid,
9 isVideoChannelSupportValid
10} from '../../helpers/custom-validators/video-channels'
f05a1c30 11import { logger } from '../../helpers/logger'
50d6de9c 12import { sendDeleteActor } from '../../lib/activitypub/send'
3fd3ab2d 13import { AccountModel } from '../account/account'
fadf619a 14import { ActorModel } from '../activitypub/actor'
3fd3ab2d
C
15import { getSort, throwIfNotValid } from '../utils'
16import { VideoModel } from './video'
a10fc78b 17import { CONSTRAINTS_FIELDS } from '../../initializers'
3fd3ab2d 18
d48ff09d
C
19enum ScopeNames {
20 WITH_ACCOUNT = 'WITH_ACCOUNT',
50d6de9c 21 WITH_ACTOR = 'WITH_ACTOR',
d48ff09d
C
22 WITH_VIDEOS = 'WITH_VIDEOS'
23}
24
50d6de9c
C
25@DefaultScope({
26 include: [
27 {
28 model: () => ActorModel,
29 required: true
30 }
31 ]
32})
d48ff09d
C
33@Scopes({
34 [ScopeNames.WITH_ACCOUNT]: {
35 include: [
36 {
a4f99a76 37 model: () => AccountModel.unscoped(),
50d6de9c
C
38 required: true,
39 include: [
40 {
a4f99a76 41 model: () => ActorModel.unscoped(),
50d6de9c
C
42 required: true
43 }
44 ]
d48ff09d
C
45 }
46 ]
47 },
48 [ScopeNames.WITH_VIDEOS]: {
49 include: [
50 () => VideoModel
51 ]
50d6de9c
C
52 },
53 [ScopeNames.WITH_ACTOR]: {
54 include: [
55 () => ActorModel
56 ]
d48ff09d
C
57 }
58})
3fd3ab2d
C
59@Table({
60 tableName: 'videoChannel',
61 indexes: [
72c7248b 62 {
3fd3ab2d 63 fields: [ 'accountId' ]
72c7248b 64 }
72c7248b 65 ]
3fd3ab2d
C
66})
67export class VideoChannelModel extends Model<VideoChannelModel> {
72c7248b 68
3fd3ab2d
C
69 @AllowNull(false)
70 @Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelNameValid, 'name'))
71 @Column
72 name: string
72c7248b 73
3fd3ab2d 74 @AllowNull(true)
2422c46b 75 @Default(null)
3fd3ab2d 76 @Is('VideoChannelDescription', value => throwIfNotValid(value, isVideoChannelDescriptionValid, 'description'))
a10fc78b 77 @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_CHANNELS.DESCRIPTION.max))
3fd3ab2d 78 description: string
72c7248b 79
2422c46b
C
80 @AllowNull(true)
81 @Default(null)
82 @Is('VideoChannelSupport', value => throwIfNotValid(value, isVideoChannelSupportValid, 'support'))
a10fc78b 83 @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_CHANNELS.SUPPORT.max))
2422c46b
C
84 support: string
85
3fd3ab2d
C
86 @CreatedAt
87 createdAt: Date
72c7248b 88
3fd3ab2d
C
89 @UpdatedAt
90 updatedAt: Date
4e50b6a1 91
fadf619a
C
92 @ForeignKey(() => ActorModel)
93 @Column
94 actorId: number
95
96 @BelongsTo(() => ActorModel, {
97 foreignKey: {
98 allowNull: false
99 },
100 onDelete: 'cascade'
101 })
102 Actor: ActorModel
103
3fd3ab2d
C
104 @ForeignKey(() => AccountModel)
105 @Column
106 accountId: number
4e50b6a1 107
3fd3ab2d
C
108 @BelongsTo(() => AccountModel, {
109 foreignKey: {
110 allowNull: false
111 },
6b738c7a 112 hooks: true
3fd3ab2d
C
113 })
114 Account: AccountModel
72c7248b 115
3fd3ab2d 116 @HasMany(() => VideoModel, {
72c7248b 117 foreignKey: {
3fd3ab2d 118 name: 'channelId',
72c7248b
C
119 allowNull: false
120 },
f05a1c30
C
121 onDelete: 'CASCADE',
122 hooks: true
72c7248b 123 })
3fd3ab2d 124 Videos: VideoModel[]
72c7248b 125
f05a1c30
C
126 @BeforeDestroy
127 static async sendDeleteIfOwned (instance: VideoChannelModel, options) {
128 if (!instance.Actor) {
129 instance.Actor = await instance.$get('Actor', { transaction: options.transaction }) as ActorModel
130 }
131
50d6de9c 132 if (instance.Actor.isOwned()) {
f05a1c30
C
133 logger.debug('Sending delete of actor of video channel %s.', instance.Actor.url)
134
135 return sendDeleteActor(instance.Actor, options.transaction)
3fd3ab2d 136 }
72c7248b 137
3fd3ab2d
C
138 return undefined
139 }
72c7248b 140
3fd3ab2d
C
141 static countByAccount (accountId: number) {
142 const query = {
143 where: {
144 accountId
145 }
72c7248b 146 }
3fd3ab2d
C
147
148 return VideoChannelModel.count(query)
72c7248b
C
149 }
150
3fd3ab2d
C
151 static listForApi (start: number, count: number, sort: string) {
152 const query = {
153 offset: start,
154 limit: count,
3bb6c526 155 order: getSort(sort)
3fd3ab2d 156 }
72c7248b 157
50d6de9c
C
158 return VideoChannelModel
159 .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ])
160 .findAndCountAll(query)
3fd3ab2d
C
161 .then(({ rows, count }) => {
162 return { total: count, data: rows }
163 })
72c7248b
C
164 }
165
3fd3ab2d
C
166 static listByAccount (accountId: number) {
167 const query = {
3bb6c526 168 order: getSort('createdAt'),
3fd3ab2d
C
169 include: [
170 {
171 model: AccountModel,
172 where: {
173 id: accountId
174 },
50d6de9c 175 required: true
3fd3ab2d
C
176 }
177 ]
178 }
72c7248b 179
50d6de9c
C
180 return VideoChannelModel
181 .findAndCountAll(query)
3fd3ab2d
C
182 .then(({ rows, count }) => {
183 return { total: count, data: rows }
184 })
72c7248b
C
185 }
186
3fd3ab2d
C
187 static loadByIdAndAccount (id: number, accountId: number) {
188 const options = {
189 where: {
190 id,
191 accountId
d48ff09d 192 }
571389d4 193 }
3fd3ab2d 194
50d6de9c
C
195 return VideoChannelModel
196 .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ])
197 .findOne(options)
0d0e8dd0
C
198 }
199
3fd3ab2d 200 static loadAndPopulateAccount (id: number) {
50d6de9c
C
201 return VideoChannelModel
202 .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ])
203 .findById(id)
3fd3ab2d 204 }
0d0e8dd0 205
3fd3ab2d
C
206 static loadByUUIDAndPopulateAccount (uuid: string) {
207 const options = {
50d6de9c
C
208 include: [
209 {
210 model: ActorModel,
211 required: true,
212 where: {
213 uuid
214 }
215 }
216 ]
3fd3ab2d
C
217 }
218
50d6de9c
C
219 return VideoChannelModel
220 .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ])
221 .findOne(options)
72c7248b
C
222 }
223
3fd3ab2d
C
224 static loadAndPopulateAccountAndVideos (id: number) {
225 const options = {
226 include: [
3fd3ab2d
C
227 VideoModel
228 ]
229 }
72c7248b 230
50d6de9c
C
231 return VideoChannelModel
232 .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_VIDEOS ])
233 .findById(id, options)
72c7248b
C
234 }
235
2422c46b 236 toFormattedJSON (): VideoChannel {
50d6de9c 237 const actor = this.Actor.toFormattedJSON()
6b738c7a 238 const videoChannel = {
3fd3ab2d 239 id: this.id,
60650c77 240 displayName: this.name,
3fd3ab2d 241 description: this.description,
2422c46b 242 support: this.support,
50d6de9c 243 isLocal: this.Actor.isOwned(),
3fd3ab2d 244 createdAt: this.createdAt,
6b738c7a
C
245 updatedAt: this.updatedAt,
246 ownerAccount: undefined,
247 videos: undefined
248 }
249
a4f99a76 250 if (this.Account) videoChannel.ownerAccount = this.Account.toFormattedJSON()
72c7248b 251
6b738c7a 252 return Object.assign(actor, videoChannel)
72c7248b
C
253 }
254
50d6de9c
C
255 toActivityPubObject (): ActivityPubActor {
256 const obj = this.Actor.toActivityPubObject(this.name, 'VideoChannel')
257
258 return Object.assign(obj, {
259 summary: this.description,
2422c46b 260 support: this.support,
50d6de9c
C
261 attributedTo: [
262 {
263 type: 'Person' as 'Person',
264 id: this.Account.Actor.url
265 }
266 ]
267 })
72c7248b 268 }
72c7248b 269}