]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/models/video/video-channel.ts
Make it compile at least
[github/Chocobozzz/PeerTube.git] / server / models / video / video-channel.ts
1 import * as Sequelize from 'sequelize'
2
3 import { isVideoChannelNameValid, isVideoChannelDescriptionValid } from '../../helpers'
4
5 import { addMethodsToModel, getSort } from '../utils'
6 import {
7 VideoChannelInstance,
8 VideoChannelAttributes,
9
10 VideoChannelMethods
11 } from './video-channel-interface'
12
13 let VideoChannel: Sequelize.Model<VideoChannelInstance, VideoChannelAttributes>
14 let toFormattedJSON: VideoChannelMethods.ToFormattedJSON
15 let toActivityPubObject: VideoChannelMethods.ToActivityPubObject
16 let isOwned: VideoChannelMethods.IsOwned
17 let countByAccount: VideoChannelMethods.CountByAccount
18 let listOwned: VideoChannelMethods.ListOwned
19 let listForApi: VideoChannelMethods.ListForApi
20 let listByAccount: VideoChannelMethods.ListByAccount
21 let loadByIdAndAccount: VideoChannelMethods.LoadByIdAndAccount
22 let loadByUUID: VideoChannelMethods.LoadByUUID
23 let loadAndPopulateAccount: VideoChannelMethods.LoadAndPopulateAccount
24 let loadByUUIDAndPopulateAccount: VideoChannelMethods.LoadByUUIDAndPopulateAccount
25 let loadByHostAndUUID: VideoChannelMethods.LoadByHostAndUUID
26 let loadAndPopulateAccountAndVideos: VideoChannelMethods.LoadAndPopulateAccountAndVideos
27 let loadByUrl: VideoChannelMethods.LoadByUrl
28 let loadByUUIDOrUrl: VideoChannelMethods.LoadByUUIDOrUrl
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 url: {
67 type: DataTypes.STRING,
68 allowNull: false,
69 validate: {
70 isUrl: true
71 }
72 }
73 },
74 {
75 indexes: [
76 {
77 fields: [ 'accountId' ]
78 }
79 ],
80 hooks: {
81 afterDestroy
82 }
83 }
84 )
85
86 const classMethods = [
87 associate,
88
89 listForApi,
90 listByAccount,
91 listOwned,
92 loadByIdAndAccount,
93 loadAndPopulateAccount,
94 loadByUUIDAndPopulateAccount,
95 loadByUUID,
96 loadByHostAndUUID,
97 loadAndPopulateAccountAndVideos,
98 countByAccount,
99 loadByUrl,
100 loadByUUIDOrUrl
101 ]
102 const instanceMethods = [
103 isOwned,
104 toFormattedJSON,
105 toActivityPubObject
106 ]
107 addMethodsToModel(VideoChannel, classMethods, instanceMethods)
108
109 return VideoChannel
110 }
111
112 // ------------------------------ METHODS ------------------------------
113
114 isOwned = function (this: VideoChannelInstance) {
115 return this.remote === false
116 }
117
118 toFormattedJSON = function (this: VideoChannelInstance) {
119 const json = {
120 id: this.id,
121 uuid: this.uuid,
122 name: this.name,
123 description: this.description,
124 isLocal: this.isOwned(),
125 createdAt: this.createdAt,
126 updatedAt: this.updatedAt
127 }
128
129 if (this.Account !== undefined) {
130 json['owner'] = {
131 name: this.Account.name,
132 uuid: this.Account.uuid
133 }
134 }
135
136 if (Array.isArray(this.Videos)) {
137 json['videos'] = this.Videos.map(v => v.toFormattedJSON())
138 }
139
140 return json
141 }
142
143 toActivityPubObject = function (this: VideoChannelInstance) {
144 const json = {
145 type: 'VideoChannel' as 'VideoChannel',
146 id: this.url,
147 uuid: this.uuid,
148 content: this.description,
149 name: this.name,
150 published: this.createdAt,
151 updated: this.updatedAt
152 }
153
154 return json
155 }
156
157 // ------------------------------ STATICS ------------------------------
158
159 function associate (models) {
160 VideoChannel.belongsTo(models.Account, {
161 foreignKey: {
162 name: 'accountId',
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
177 function afterDestroy (videoChannel: VideoChannelInstance) {
178 if (videoChannel.isOwned()) {
179 const removeVideoChannelToFriendsParams = {
180 uuid: videoChannel.uuid
181 }
182
183 // FIXME: send remove event to followers
184 }
185
186 return undefined
187 }
188
189 countByAccount = function (accountId: number) {
190 const query = {
191 where: {
192 accountId
193 }
194 }
195
196 return VideoChannel.count(query)
197 }
198
199 listOwned = function () {
200 const query = {
201 where: {
202 remote: false
203 },
204 include: [ VideoChannel['sequelize'].models.Account ]
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 {
217 model: VideoChannel['sequelize'].models.Account,
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
229 listByAccount = function (accountId: number) {
230 const query = {
231 order: [ getSort('createdAt') ],
232 include: [
233 {
234 model: VideoChannel['sequelize'].models.Account,
235 where: {
236 id: accountId
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
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
288 loadByHostAndUUID = function (fromHost: string, uuid: string, t?: Sequelize.Transaction) {
289 const query: Sequelize.FindOptions<VideoChannelAttributes> = {
290 where: {
291 uuid
292 },
293 include: [
294 {
295 model: VideoChannel['sequelize'].models.Account,
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
314 loadByIdAndAccount = function (id: number, accountId: number) {
315 const options = {
316 where: {
317 id,
318 accountId
319 },
320 include: [
321 {
322 model: VideoChannel['sequelize'].models.Account,
323 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
324 }
325 ]
326 }
327
328 return VideoChannel.findOne(options)
329 }
330
331 loadAndPopulateAccount = function (id: number) {
332 const options = {
333 include: [
334 {
335 model: VideoChannel['sequelize'].models.Account,
336 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
337 }
338 ]
339 }
340
341 return VideoChannel.findById(id, options)
342 }
343
344 loadByUUIDAndPopulateAccount = function (uuid: string) {
345 const options = {
346 where: {
347 uuid
348 },
349 include: [
350 {
351 model: VideoChannel['sequelize'].models.Account,
352 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ]
353 }
354 ]
355 }
356
357 return VideoChannel.findOne(options)
358 }
359
360 loadAndPopulateAccountAndVideos = function (id: number) {
361 const options = {
362 include: [
363 {
364 model: VideoChannel['sequelize'].models.Account,
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 }