]>
Commit | Line | Data |
---|---|---|
72c7248b C |
1 | import * as Sequelize from 'sequelize' |
2 | ||
3 | import { isVideoChannelNameValid, isVideoChannelDescriptionValid } from '../../helpers' | |
4 | import { removeVideoChannelToFriends } from '../../lib' | |
5 | ||
6 | import { addMethodsToModel, getSort } from '../utils' | |
7 | import { | |
8 | VideoChannelInstance, | |
9 | VideoChannelAttributes, | |
10 | ||
11 | VideoChannelMethods | |
12 | } from './video-channel-interface' | |
13 | ||
14 | let VideoChannel: Sequelize.Model<VideoChannelInstance, VideoChannelAttributes> | |
15 | let toFormattedJSON: VideoChannelMethods.ToFormattedJSON | |
e4f97bab | 16 | let toActivityPubObject: VideoChannelMethods.ToActivityPubObject |
72c7248b | 17 | let isOwned: VideoChannelMethods.IsOwned |
e4f97bab | 18 | let countByAccount: VideoChannelMethods.CountByAccount |
72c7248b C |
19 | let listOwned: VideoChannelMethods.ListOwned |
20 | let listForApi: VideoChannelMethods.ListForApi | |
e4f97bab C |
21 | let listByAccount: VideoChannelMethods.ListByAccount |
22 | let loadByIdAndAccount: VideoChannelMethods.LoadByIdAndAccount | |
72c7248b | 23 | let loadByUUID: VideoChannelMethods.LoadByUUID |
e4f97bab C |
24 | let loadAndPopulateAccount: VideoChannelMethods.LoadAndPopulateAccount |
25 | let loadByUUIDAndPopulateAccount: VideoChannelMethods.LoadByUUIDAndPopulateAccount | |
72c7248b | 26 | let loadByHostAndUUID: VideoChannelMethods.LoadByHostAndUUID |
e4f97bab | 27 | let loadAndPopulateAccountAndVideos: VideoChannelMethods.LoadAndPopulateAccountAndVideos |
0d0e8dd0 C |
28 | let loadByUrl: VideoChannelMethods.LoadByUrl |
29 | let loadByUUIDOrUrl: VideoChannelMethods.LoadByUUIDOrUrl | |
72c7248b C |
30 | |
31 | export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) { | |
32 | VideoChannel = sequelize.define<VideoChannelInstance, VideoChannelAttributes>('VideoChannel', | |
33 | { | |
34 | uuid: { | |
35 | type: DataTypes.UUID, | |
36 | defaultValue: DataTypes.UUIDV4, | |
37 | allowNull: false, | |
38 | validate: { | |
39 | isUUID: 4 | |
40 | } | |
41 | }, | |
42 | name: { | |
43 | type: DataTypes.STRING, | |
44 | allowNull: false, | |
45 | validate: { | |
46 | nameValid: value => { | |
47 | const res = isVideoChannelNameValid(value) | |
48 | if (res === false) throw new Error('Video channel name is not valid.') | |
49 | } | |
50 | } | |
51 | }, | |
52 | description: { | |
53 | type: DataTypes.STRING, | |
54 | allowNull: true, | |
55 | validate: { | |
56 | descriptionValid: value => { | |
57 | const res = isVideoChannelDescriptionValid(value) | |
58 | if (res === false) throw new Error('Video channel description is not valid.') | |
59 | } | |
60 | } | |
61 | }, | |
62 | remote: { | |
63 | type: DataTypes.BOOLEAN, | |
64 | allowNull: false, | |
65 | defaultValue: false | |
e4f97bab C |
66 | }, |
67 | url: { | |
68 | type: DataTypes.STRING, | |
69 | allowNull: false, | |
70 | validate: { | |
71 | isUrl: true | |
72 | } | |
72c7248b C |
73 | } |
74 | }, | |
75 | { | |
76 | indexes: [ | |
77 | { | |
e4f97bab | 78 | fields: [ 'accountId' ] |
72c7248b C |
79 | } |
80 | ], | |
81 | hooks: { | |
82 | afterDestroy | |
83 | } | |
84 | } | |
85 | ) | |
86 | ||
87 | const classMethods = [ | |
88 | associate, | |
89 | ||
90 | listForApi, | |
e4f97bab | 91 | listByAccount, |
72c7248b | 92 | listOwned, |
e4f97bab C |
93 | loadByIdAndAccount, |
94 | loadAndPopulateAccount, | |
95 | loadByUUIDAndPopulateAccount, | |
72c7248b C |
96 | loadByUUID, |
97 | loadByHostAndUUID, | |
e4f97bab | 98 | loadAndPopulateAccountAndVideos, |
0d0e8dd0 C |
99 | countByAccount, |
100 | loadByUrl, | |
101 | loadByUUIDOrUrl | |
72c7248b C |
102 | ] |
103 | const instanceMethods = [ | |
104 | isOwned, | |
105 | toFormattedJSON, | |
0d0e8dd0 | 106 | toActivityPubObject |
72c7248b C |
107 | ] |
108 | addMethodsToModel(VideoChannel, classMethods, instanceMethods) | |
109 | ||
110 | return VideoChannel | |
111 | } | |
112 | ||
113 | // ------------------------------ METHODS ------------------------------ | |
114 | ||
115 | isOwned = function (this: VideoChannelInstance) { | |
116 | return this.remote === false | |
117 | } | |
118 | ||
119 | toFormattedJSON = function (this: VideoChannelInstance) { | |
120 | const json = { | |
121 | id: this.id, | |
122 | uuid: this.uuid, | |
123 | name: this.name, | |
124 | description: this.description, | |
125 | isLocal: this.isOwned(), | |
126 | createdAt: this.createdAt, | |
127 | updatedAt: this.updatedAt | |
128 | } | |
129 | ||
e4f97bab | 130 | if (this.Account !== undefined) { |
72c7248b | 131 | json['owner'] = { |
e4f97bab C |
132 | name: this.Account.name, |
133 | uuid: this.Account.uuid | |
72c7248b C |
134 | } |
135 | } | |
136 | ||
137 | if (Array.isArray(this.Videos)) { | |
138 | json['videos'] = this.Videos.map(v => v.toFormattedJSON()) | |
139 | } | |
140 | ||
141 | return json | |
142 | } | |
143 | ||
e4f97bab | 144 | toActivityPubObject = function (this: VideoChannelInstance) { |
72c7248b C |
145 | const json = { |
146 | uuid: this.uuid, | |
147 | name: this.name, | |
148 | description: this.description, | |
149 | createdAt: this.createdAt, | |
150 | updatedAt: this.updatedAt, | |
e4f97bab | 151 | ownerUUID: this.Account.uuid |
72c7248b C |
152 | } |
153 | ||
154 | return json | |
155 | } | |
156 | ||
157 | // ------------------------------ STATICS ------------------------------ | |
158 | ||
159 | function associate (models) { | |
e4f97bab | 160 | VideoChannel.belongsTo(models.Account, { |
72c7248b | 161 | foreignKey: { |
e4f97bab | 162 | name: 'accountId', |
72c7248b C |
163 | allowNull: false |
164 | }, | |
165 | onDelete: 'CASCADE' | |
166 | }) | |
167 | ||
168 | VideoChannel.hasMany(models.Video, { | |
169 | foreignKey: { | |
170 | name: 'channelId', | |
171 | allowNull: false | |
172 | }, | |
173 | onDelete: 'CASCADE' | |
174 | }) | |
175 | } | |
176 | ||
911238e3 | 177 | function afterDestroy (videoChannel: VideoChannelInstance) { |
72c7248b C |
178 | if (videoChannel.isOwned()) { |
179 | const removeVideoChannelToFriendsParams = { | |
180 | uuid: videoChannel.uuid | |
181 | } | |
182 | ||
911238e3 | 183 | return removeVideoChannelToFriends(removeVideoChannelToFriendsParams) |
72c7248b C |
184 | } |
185 | ||
186 | return undefined | |
187 | } | |
188 | ||
e4f97bab | 189 | countByAccount = function (accountId: number) { |
72c7248b C |
190 | const query = { |
191 | where: { | |
e4f97bab | 192 | accountId |
72c7248b C |
193 | } |
194 | } | |
195 | ||
196 | return VideoChannel.count(query) | |
197 | } | |
198 | ||
199 | listOwned = function () { | |
200 | const query = { | |
201 | where: { | |
202 | remote: false | |
203 | }, | |
e4f97bab | 204 | include: [ VideoChannel['sequelize'].models.Account ] |
72c7248b C |
205 | } |
206 | ||
207 | return VideoChannel.findAll(query) | |
208 | } | |
209 | ||
210 | listForApi = function (start: number, count: number, sort: string) { | |
211 | const query = { | |
212 | offset: start, | |
213 | limit: count, | |
214 | order: [ getSort(sort) ], | |
215 | include: [ | |
216 | { | |
e4f97bab | 217 | model: VideoChannel['sequelize'].models.Account, |
72c7248b C |
218 | required: true, |
219 | include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ] | |
220 | } | |
221 | ] | |
222 | } | |
223 | ||
224 | return VideoChannel.findAndCountAll(query).then(({ rows, count }) => { | |
225 | return { total: count, data: rows } | |
226 | }) | |
227 | } | |
228 | ||
e4f97bab | 229 | listByAccount = function (accountId: number) { |
72c7248b C |
230 | const query = { |
231 | order: [ getSort('createdAt') ], | |
232 | include: [ | |
233 | { | |
e4f97bab | 234 | model: VideoChannel['sequelize'].models.Account, |
72c7248b | 235 | where: { |
e4f97bab | 236 | id: accountId |
72c7248b C |
237 | }, |
238 | required: true, | |
239 | include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ] | |
240 | } | |
241 | ] | |
242 | } | |
243 | ||
244 | return VideoChannel.findAndCountAll(query).then(({ rows, count }) => { | |
245 | return { total: count, data: rows } | |
246 | }) | |
247 | } | |
248 | ||
249 | loadByUUID = function (uuid: string, t?: Sequelize.Transaction) { | |
250 | const query: Sequelize.FindOptions<VideoChannelAttributes> = { | |
251 | where: { | |
252 | uuid | |
253 | } | |
254 | } | |
255 | ||
256 | if (t !== undefined) query.transaction = t | |
257 | ||
258 | return VideoChannel.findOne(query) | |
259 | } | |
260 | ||
0d0e8dd0 C |
261 | loadByUrl = function (url: string, t?: Sequelize.Transaction) { |
262 | const query: Sequelize.FindOptions<VideoChannelAttributes> = { | |
263 | where: { | |
264 | url | |
265 | } | |
266 | } | |
267 | ||
268 | if (t !== undefined) query.transaction = t | |
269 | ||
270 | return VideoChannel.findOne(query) | |
271 | } | |
272 | ||
273 | loadByUUIDOrUrl = function (uuid: string, url: string, t?: Sequelize.Transaction) { | |
274 | const query: Sequelize.FindOptions<VideoChannelAttributes> = { | |
275 | where: { | |
276 | [Sequelize.Op.or]: [ | |
277 | { uuid }, | |
278 | { url } | |
279 | ] | |
280 | }, | |
281 | } | |
282 | ||
283 | if (t !== undefined) query.transaction = t | |
284 | ||
285 | return VideoChannel.findOne(query) | |
286 | } | |
287 | ||
72c7248b C |
288 | loadByHostAndUUID = function (fromHost: string, uuid: string, t?: Sequelize.Transaction) { |
289 | const query: Sequelize.FindOptions<VideoChannelAttributes> = { | |
290 | where: { | |
291 | uuid | |
292 | }, | |
293 | include: [ | |
294 | { | |
e4f97bab | 295 | model: VideoChannel['sequelize'].models.Account, |
72c7248b C |
296 | include: [ |
297 | { | |
298 | model: VideoChannel['sequelize'].models.Pod, | |
299 | required: true, | |
300 | where: { | |
301 | host: fromHost | |
302 | } | |
303 | } | |
304 | ] | |
305 | } | |
306 | ] | |
307 | } | |
308 | ||
309 | if (t !== undefined) query.transaction = t | |
310 | ||
311 | return VideoChannel.findOne(query) | |
312 | } | |
313 | ||
e4f97bab | 314 | loadByIdAndAccount = function (id: number, accountId: number) { |
72c7248b C |
315 | const options = { |
316 | where: { | |
317 | id, | |
e4f97bab | 318 | accountId |
72c7248b C |
319 | }, |
320 | include: [ | |
321 | { | |
e4f97bab | 322 | model: VideoChannel['sequelize'].models.Account, |
72c7248b C |
323 | include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ] |
324 | } | |
325 | ] | |
326 | } | |
327 | ||
328 | return VideoChannel.findOne(options) | |
329 | } | |
330 | ||
e4f97bab | 331 | loadAndPopulateAccount = function (id: number) { |
72c7248b C |
332 | const options = { |
333 | include: [ | |
334 | { | |
e4f97bab | 335 | model: VideoChannel['sequelize'].models.Account, |
72c7248b C |
336 | include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ] |
337 | } | |
338 | ] | |
339 | } | |
340 | ||
341 | return VideoChannel.findById(id, options) | |
342 | } | |
343 | ||
e4f97bab | 344 | loadByUUIDAndPopulateAccount = function (uuid: string) { |
72c7248b C |
345 | const options = { |
346 | where: { | |
347 | uuid | |
348 | }, | |
349 | include: [ | |
350 | { | |
e4f97bab | 351 | model: VideoChannel['sequelize'].models.Account, |
72c7248b C |
352 | include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ] |
353 | } | |
354 | ] | |
355 | } | |
356 | ||
357 | return VideoChannel.findOne(options) | |
358 | } | |
359 | ||
e4f97bab | 360 | loadAndPopulateAccountAndVideos = function (id: number) { |
72c7248b C |
361 | const options = { |
362 | include: [ | |
363 | { | |
e4f97bab | 364 | model: VideoChannel['sequelize'].models.Account, |
72c7248b C |
365 | include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ] |
366 | }, | |
367 | VideoChannel['sequelize'].models.Video | |
368 | ] | |
369 | } | |
370 | ||
371 | return VideoChannel.findById(id, options) | |
372 | } |