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