]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/models/video/sql/shared/video-model-builder.ts
Use raw SQL for video get request
[github/Chocobozzz/PeerTube.git] / server / models / video / sql / shared / video-model-builder.ts
1 import { pick } from 'lodash'
2 import { AccountModel } from '@server/models/account/account'
3 import { ActorModel } from '@server/models/actor/actor'
4 import { ActorImageModel } from '@server/models/actor/actor-image'
5 import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy'
6 import { ServerModel } from '@server/models/server/server'
7 import { TrackerModel } from '@server/models/server/tracker'
8 import { UserVideoHistoryModel } from '@server/models/user/user-video-history'
9 import { ScheduleVideoUpdateModel } from '../../schedule-video-update'
10 import { TagModel } from '../../tag'
11 import { ThumbnailModel } from '../../thumbnail'
12 import { VideoModel } from '../../video'
13 import { VideoBlacklistModel } from '../../video-blacklist'
14 import { VideoChannelModel } from '../../video-channel'
15 import { VideoFileModel } from '../../video-file'
16 import { VideoLiveModel } from '../../video-live'
17 import { VideoStreamingPlaylistModel } from '../../video-streaming-playlist'
18 import { VideoAttributes } from './video-attributes'
19
20 export class VideoModelBuilder {
21 private videosMemo: { [ id: number ]: VideoModel }
22 private videoStreamingPlaylistMemo: { [ id: number ]: VideoStreamingPlaylistModel }
23 private videoFileMemo: { [ id: number ]: VideoFileModel }
24
25 private thumbnailsDone: Set<number>
26 private historyDone: Set<number>
27 private blacklistDone: Set<number>
28 private liveDone: Set<number>
29 private redundancyDone: Set<number>
30 private scheduleVideoUpdateDone: Set<number>
31
32 private trackersDone: Set<string>
33 private tagsDone: Set<string>
34
35 private videos: VideoModel[]
36
37 private readonly buildOpts = { raw: true, isNewRecord: false }
38
39 constructor (
40 readonly mode: 'get' | 'list',
41 readonly videoAttributes: VideoAttributes
42 ) {
43
44 }
45
46 buildVideosFromRows (rows: any[]) {
47 this.reinit()
48
49 for (const row of rows) {
50 this.buildVideo(row)
51
52 const videoModel = this.videosMemo[row.id]
53
54 this.setUserHistory(row, videoModel)
55 this.addThumbnail(row, videoModel)
56 this.addWebTorrentFile(row, videoModel)
57
58 this.addStreamingPlaylist(row, videoModel)
59 this.addStreamingPlaylistFile(row)
60
61 if (this.mode === 'get') {
62 this.addTag(row, videoModel)
63 this.addTracker(row, videoModel)
64 this.setBlacklisted(row, videoModel)
65 this.setScheduleVideoUpdate(row, videoModel)
66 this.setLive(row, videoModel)
67
68 if (row.VideoFiles.id) {
69 this.addRedundancy(row.VideoFiles.RedundancyVideos, this.videoFileMemo[row.VideoFiles.id])
70 }
71
72 if (row.VideoStreamingPlaylists.id) {
73 this.addRedundancy(row.VideoStreamingPlaylists.RedundancyVideos, this.videoStreamingPlaylistMemo[row.VideoStreamingPlaylists.id])
74 }
75 }
76 }
77
78 return this.videos
79 }
80
81 private reinit () {
82 this.videosMemo = {}
83 this.videoStreamingPlaylistMemo = {}
84 this.videoFileMemo = {}
85
86 this.thumbnailsDone = new Set<number>()
87 this.historyDone = new Set<number>()
88 this.blacklistDone = new Set<number>()
89 this.liveDone = new Set<number>()
90 this.redundancyDone = new Set<number>()
91 this.scheduleVideoUpdateDone = new Set<number>()
92
93 this.trackersDone = new Set<string>()
94 this.tagsDone = new Set<string>()
95
96 this.videos = []
97 }
98
99 private buildVideo (row: any) {
100 if (this.videosMemo[row.id]) return
101
102 // Build Channel
103 const channel = row.VideoChannel
104 const channelModel = new VideoChannelModel(pick(channel, this.videoAttributes.getChannelAttributes()), this.buildOpts)
105 channelModel.Actor = this.buildActor(channel.Actor)
106
107 const account = row.VideoChannel.Account
108 const accountModel = new AccountModel(pick(account, this.videoAttributes.getAccountAttributes()), this.buildOpts)
109 accountModel.Actor = this.buildActor(account.Actor)
110
111 channelModel.Account = accountModel
112
113 const videoModel = new VideoModel(pick(row, this.videoAttributes.getVideoAttributes()), this.buildOpts)
114 videoModel.VideoChannel = channelModel
115
116 this.videosMemo[row.id] = videoModel
117
118 videoModel.UserVideoHistories = []
119 videoModel.Thumbnails = []
120 videoModel.VideoFiles = []
121 videoModel.VideoStreamingPlaylists = []
122 videoModel.Tags = []
123 videoModel.Trackers = []
124
125 // Keep rows order
126 this.videos.push(videoModel)
127 }
128
129 private buildActor (rowActor: any) {
130 const avatarModel = rowActor.Avatar.id !== null
131 ? new ActorImageModel(pick(rowActor.Avatar, this.videoAttributes.getAvatarAttributes()), this.buildOpts)
132 : null
133
134 const serverModel = rowActor.Server.id !== null
135 ? new ServerModel(pick(rowActor.Server, this.videoAttributes.getServerAttributes()), this.buildOpts)
136 : null
137
138 const actorModel = new ActorModel(pick(rowActor, this.videoAttributes.getActorAttributes()), this.buildOpts)
139 actorModel.Avatar = avatarModel
140 actorModel.Server = serverModel
141
142 return actorModel
143 }
144
145 private setUserHistory (row: any, videoModel: VideoModel) {
146 if (!row.userVideoHistory?.id || this.historyDone.has(row.userVideoHistory.id)) return
147
148 const attributes = pick(row.userVideoHistory, this.videoAttributes.getUserHistoryAttributes())
149 const historyModel = new UserVideoHistoryModel(attributes, this.buildOpts)
150 videoModel.UserVideoHistories.push(historyModel)
151
152 this.historyDone.add(row.userVideoHistory.id)
153 }
154
155 private addThumbnail (row: any, videoModel: VideoModel) {
156 if (!row.Thumbnails?.id || this.thumbnailsDone.has(row.Thumbnails.id)) return
157
158 const attributes = pick(row.Thumbnails, this.videoAttributes.getThumbnailAttributes())
159 const thumbnailModel = new ThumbnailModel(attributes, this.buildOpts)
160 videoModel.Thumbnails.push(thumbnailModel)
161
162 this.thumbnailsDone.add(row.Thumbnails.id)
163 }
164
165 private addWebTorrentFile (row: any, videoModel: VideoModel) {
166 if (!row.VideoFiles?.id || this.videoFileMemo[row.VideoFiles.id]) return
167
168 const attributes = pick(row.VideoFiles, this.videoAttributes.getFileAttributes())
169 const videoFileModel = new VideoFileModel(attributes, this.buildOpts)
170 videoModel.VideoFiles.push(videoFileModel)
171
172 this.videoFileMemo[row.VideoFiles.id] = videoFileModel
173 }
174
175 private addStreamingPlaylist (row: any, videoModel: VideoModel) {
176 if (!row.VideoStreamingPlaylists?.id || this.videoStreamingPlaylistMemo[row.VideoStreamingPlaylists.id]) return
177
178 const attributes = pick(row.VideoStreamingPlaylists, this.videoAttributes.getStreamingPlaylistAttributes())
179 const streamingPlaylist = new VideoStreamingPlaylistModel(attributes, this.buildOpts)
180 streamingPlaylist.VideoFiles = []
181
182 videoModel.VideoStreamingPlaylists.push(streamingPlaylist)
183
184 this.videoStreamingPlaylistMemo[streamingPlaylist.id] = streamingPlaylist
185 }
186
187 private addStreamingPlaylistFile (row: any) {
188 if (!row.VideoStreamingPlaylists?.VideoFiles?.id || this.videoFileMemo[row.VideoStreamingPlaylists.VideoFiles.id]) return
189
190 const streamingPlaylist = this.videoStreamingPlaylistMemo[row.VideoStreamingPlaylists.id]
191
192 const attributes = pick(row.VideoStreamingPlaylists.VideoFiles, this.videoAttributes.getFileAttributes())
193 const videoFileModel = new VideoFileModel(attributes, this.buildOpts)
194 streamingPlaylist.VideoFiles.push(videoFileModel)
195
196 this.videoFileMemo[row.VideoStreamingPlaylists.VideoFiles.id] = videoFileModel
197 }
198
199 private addRedundancy (redundancyRow: any, to: VideoFileModel | VideoStreamingPlaylistModel) {
200 if (!to.RedundancyVideos) to.RedundancyVideos = []
201
202 if (!redundancyRow?.id || this.redundancyDone.has(redundancyRow.id)) return
203
204 const attributes = pick(redundancyRow, this.videoAttributes.getRedundancyAttributes())
205 const redundancyModel = new VideoRedundancyModel(attributes, this.buildOpts)
206 to.RedundancyVideos.push(redundancyModel)
207
208 this.redundancyDone.add(redundancyRow.id)
209 }
210
211 private addTag (row: any, videoModel: VideoModel) {
212 if (!row.Tags?.name) return
213 const association = row.Tags.VideoTagModel
214
215 const key = `${association.videoId}-${association.tagId}`
216 if (this.tagsDone.has(key)) return
217
218 const attributes = pick(row.Tags, this.videoAttributes.getTagAttributes())
219 const tagModel = new TagModel(attributes, this.buildOpts)
220 videoModel.Tags.push(tagModel)
221
222 this.tagsDone.add(key)
223 }
224
225 private addTracker (row: any, videoModel: VideoModel) {
226 if (!row.Trackers?.id) return
227 const association = row.Trackers.VideoTrackerModel
228
229 const key = `${association.videoId}-${association.trackerId}`
230 if (this.trackersDone.has(key)) return
231
232 const attributes = pick(row.Trackers, this.videoAttributes.getTrackerAttributes())
233 const trackerModel = new TrackerModel(attributes, this.buildOpts)
234 videoModel.Trackers.push(trackerModel)
235
236 this.trackersDone.add(key)
237 }
238
239 private setBlacklisted (row: any, videoModel: VideoModel) {
240 if (!row.VideoBlacklist?.id) return
241 if (this.blacklistDone.has(row.VideoBlacklist.id)) return
242
243 const attributes = pick(row.VideoBlacklist, this.videoAttributes.getBlacklistedAttributes())
244 videoModel.VideoBlacklist = new VideoBlacklistModel(attributes, this.buildOpts)
245
246 this.blacklistDone.add(row.VideoBlacklist.id)
247 }
248
249 private setScheduleVideoUpdate (row: any, videoModel: VideoModel) {
250 if (!row.ScheduleVideoUpdate?.id) return
251 if (this.scheduleVideoUpdateDone.has(row.ScheduleVideoUpdate.id)) return
252
253 const attributes = pick(row.ScheduleVideoUpdate, this.videoAttributes.getScheduleUpdateAttributes())
254 videoModel.ScheduleVideoUpdate = new ScheduleVideoUpdateModel(attributes, this.buildOpts)
255
256 this.scheduleVideoUpdateDone.add(row.ScheduleVideoUpdate.id)
257 }
258
259 private setLive (row: any, videoModel: VideoModel) {
260 if (!row.VideoLive?.id) return
261 if (this.liveDone.has(row.VideoLive.id)) return
262
263 const attributes = pick(row.VideoLive, this.videoAttributes.getLiveAttributes())
264 videoModel.VideoLive = new VideoLiveModel(attributes, this.buildOpts)
265
266 this.liveDone.add(row.ScheduleVideoUpdate.id)
267 }
268 }