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