Server: add video language attribute
[oweals/peertube.git] / server / models / request-video-event.js
1 'use strict'
2
3 /*
4   Request Video events (likes, dislikes, views...)
5 */
6
7 const values = require('lodash/values')
8
9 const constants = require('../initializers/constants')
10 const customVideosValidators = require('../helpers/custom-validators').videos
11
12 // ---------------------------------------------------------------------------
13
14 module.exports = function (sequelize, DataTypes) {
15   const RequestVideoEvent = sequelize.define('RequestVideoEvent',
16     {
17       type: {
18         type: DataTypes.ENUM(values(constants.REQUEST_VIDEO_EVENT_TYPES)),
19         allowNull: false
20       },
21       count: {
22         type: DataTypes.INTEGER,
23         allowNull: false,
24         validate: {
25           countValid: function (value) {
26             const res = customVideosValidators.isVideoEventCountValid(value)
27             if (res === false) throw new Error('Video event count is not valid.')
28           }
29         }
30       }
31     },
32     {
33       updatedAt: false,
34       indexes: [
35         {
36           fields: [ 'videoId' ]
37         }
38       ],
39       classMethods: {
40         associate,
41
42         listWithLimitAndRandom,
43
44         countTotalRequests,
45         removeAll,
46         removeByRequestIdsAndPod
47       }
48     }
49   )
50
51   return RequestVideoEvent
52 }
53
54 // ------------------------------ STATICS ------------------------------
55
56 function associate (models) {
57   this.belongsTo(models.Video, {
58     foreignKey: {
59       name: 'videoId',
60       allowNull: false
61     },
62     onDelete: 'CASCADE'
63   })
64 }
65
66 function countTotalRequests (callback) {
67   const query = {}
68   return this.count(query).asCallback(callback)
69 }
70
71 function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
72   const self = this
73   const Pod = this.sequelize.models.Pod
74
75   // We make a join between videos and authors to find the podId of our video event requests
76   const podJoins = 'INNER JOIN "Videos" ON "Videos"."authorId" = "Authors"."id" ' +
77                    'INNER JOIN "RequestVideoEvents" ON "RequestVideoEvents"."videoId" = "Videos"."id"'
78
79   Pod.listRandomPodIdsWithRequest(limitPods, 'Authors', podJoins, function (err, podIds) {
80     if (err) return callback(err)
81
82     // We don't have friends that have requests
83     if (podIds.length === 0) return callback(null, [])
84
85     const query = {
86       order: [
87         [ 'id', 'ASC' ]
88       ],
89       include: [
90         {
91           model: self.sequelize.models.Video,
92           include: [
93             {
94               model: self.sequelize.models.Author,
95               include: [
96                 {
97                   model: self.sequelize.models.Pod,
98                   where: {
99                     id: {
100                       $in: podIds
101                     }
102                   }
103                 }
104               ]
105             }
106           ]
107         }
108       ]
109     }
110
111     self.findAll(query).asCallback(function (err, requests) {
112       if (err) return callback(err)
113
114       const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
115       return callback(err, requestsGrouped)
116     })
117   })
118 }
119
120 function removeByRequestIdsAndPod (ids, podId, callback) {
121   const query = {
122     where: {
123       id: {
124         $in: ids
125       }
126     },
127     include: [
128       {
129         model: this.sequelize.models.Video,
130         include: [
131           {
132             model: this.sequelize.models.Author,
133             where: {
134               podId
135             }
136           }
137         ]
138       }
139     ]
140   }
141
142   this.destroy(query).asCallback(callback)
143 }
144
145 function removeAll (callback) {
146   // Delete all requests
147   this.truncate({ cascade: true }).asCallback(callback)
148 }
149
150 // ---------------------------------------------------------------------------
151
152 function groupAndTruncateRequests (events, limitRequestsPerPod) {
153   const eventsGrouped = {}
154
155   events.forEach(function (event) {
156     const pod = event.Video.Author.Pod
157
158     if (!eventsGrouped[pod.id]) eventsGrouped[pod.id] = []
159
160     if (eventsGrouped[pod.id].length < limitRequestsPerPod) {
161       eventsGrouped[pod.id].push({
162         id: event.id,
163         type: event.type,
164         count: event.count,
165         video: event.Video,
166         pod
167       })
168     }
169   })
170
171   return eventsGrouped
172 }