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