]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/models/video/video-channel.ts
46c2db63fa56399e0f7ed7c3992f0876253d8fdc
[github/Chocobozzz/PeerTube.git] / server / models / video / video-channel.ts
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) {
182 if (videoChannel.isOwned()) {
183 const removeVideoChannelToFriendsParams = {
184 uuid: videoChannel.uuid
185 }
186
187 return removeVideoChannelToFriends(removeVideoChannelToFriendsParams)
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 }