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