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