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