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