]>
Commit | Line | Data |
---|---|---|
17bb4538 | 1 | |
d9bf974f C |
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' | |
17bb4538 C |
18 | import { VideoTables } from './video-tables' |
19 | ||
20 | type SQLRow = { [id: string]: string | number } | |
d9bf974f | 21 | |
1d43c3a6 C |
22 | /** |
23 | * | |
24 | * Build video models from SQL rows | |
25 | * | |
26 | */ | |
27 | ||
d9bf974f C |
28 | export class VideoModelBuilder { |
29 | private videosMemo: { [ id: number ]: VideoModel } | |
30 | private videoStreamingPlaylistMemo: { [ id: number ]: VideoStreamingPlaylistModel } | |
31 | private videoFileMemo: { [ id: number ]: VideoFileModel } | |
32 | ||
17bb4538 C |
33 | private thumbnailsDone: Set<any> |
34 | private historyDone: Set<any> | |
35 | private blacklistDone: Set<any> | |
36 | private liveDone: Set<any> | |
37 | private redundancyDone: Set<any> | |
38 | private scheduleVideoUpdateDone: Set<any> | |
d9bf974f C |
39 | |
40 | private trackersDone: Set<string> | |
41 | private tagsDone: Set<string> | |
42 | ||
43 | private videos: VideoModel[] | |
44 | ||
45 | private readonly buildOpts = { raw: true, isNewRecord: false } | |
46 | ||
47 | constructor ( | |
48 | readonly mode: 'get' | 'list', | |
17bb4538 | 49 | readonly tables: VideoTables |
d9bf974f C |
50 | ) { |
51 | ||
52 | } | |
53 | ||
17bb4538 | 54 | buildVideosFromRows (rows: SQLRow[], rowsWebTorrentFiles?: SQLRow[], rowsStreamingPlaylist?: SQLRow[]) { |
d9bf974f C |
55 | this.reinit() |
56 | ||
57 | for (const row of rows) { | |
71d4af1e | 58 | this.buildVideoAndAccount(row) |
d9bf974f C |
59 | |
60 | const videoModel = this.videosMemo[row.id] | |
61 | ||
62 | this.setUserHistory(row, videoModel) | |
63 | this.addThumbnail(row, videoModel) | |
d9bf974f | 64 | |
17bb4538 | 65 | if (!rowsWebTorrentFiles) { |
1d43c3a6 C |
66 | this.addWebTorrentFile(row, videoModel) |
67 | } | |
68 | ||
69 | if (!rowsStreamingPlaylist) { | |
70 | this.addStreamingPlaylist(row, videoModel) | |
71 | this.addStreamingPlaylistFile(row) | |
72 | } | |
d9bf974f C |
73 | |
74 | if (this.mode === 'get') { | |
75 | this.addTag(row, videoModel) | |
76 | this.addTracker(row, videoModel) | |
77 | this.setBlacklisted(row, videoModel) | |
78 | this.setScheduleVideoUpdate(row, videoModel) | |
79 | this.setLive(row, videoModel) | |
d9bf974f C |
80 | } |
81 | } | |
82 | ||
17bb4538 C |
83 | this.grabSeparateWebTorrentFiles(rowsWebTorrentFiles) |
84 | this.grabSeparateStreamingPlaylistFiles(rowsStreamingPlaylist) | |
1d43c3a6 | 85 | |
d9bf974f C |
86 | return this.videos |
87 | } | |
88 | ||
89 | private reinit () { | |
90 | this.videosMemo = {} | |
91 | this.videoStreamingPlaylistMemo = {} | |
92 | this.videoFileMemo = {} | |
93 | ||
94 | this.thumbnailsDone = new Set<number>() | |
95 | this.historyDone = new Set<number>() | |
96 | this.blacklistDone = new Set<number>() | |
97 | this.liveDone = new Set<number>() | |
98 | this.redundancyDone = new Set<number>() | |
99 | this.scheduleVideoUpdateDone = new Set<number>() | |
100 | ||
101 | this.trackersDone = new Set<string>() | |
102 | this.tagsDone = new Set<string>() | |
103 | ||
104 | this.videos = [] | |
105 | } | |
106 | ||
17bb4538 C |
107 | private grabSeparateWebTorrentFiles (rowsWebTorrentFiles?: SQLRow[]) { |
108 | if (!rowsWebTorrentFiles) return | |
109 | ||
110 | for (const row of rowsWebTorrentFiles) { | |
111 | const videoModel = this.videosMemo[row.id] | |
112 | this.addWebTorrentFile(row, videoModel) | |
113 | this.addRedundancy(row, 'VideoFiles.RedundancyVideos', this.videoFileMemo[row['VideoFiles.id']]) | |
114 | } | |
115 | } | |
116 | ||
117 | private grabSeparateStreamingPlaylistFiles (rowsStreamingPlaylist?: SQLRow[]) { | |
118 | if (!rowsStreamingPlaylist) return | |
119 | ||
120 | for (const row of rowsStreamingPlaylist || []) { | |
121 | const videoModel = this.videosMemo[row.id] | |
122 | ||
123 | this.addStreamingPlaylist(row, videoModel) | |
124 | this.addStreamingPlaylistFile(row) | |
125 | this.addRedundancy( | |
126 | row, | |
127 | 'VideoStreamingPlaylists.RedundancyVideos', | |
128 | this.videoStreamingPlaylistMemo[row['VideoStreamingPlaylists.id']] | |
129 | ) | |
130 | } | |
131 | } | |
132 | ||
71d4af1e | 133 | private buildVideoAndAccount (row: SQLRow) { |
d9bf974f C |
134 | if (this.videosMemo[row.id]) return |
135 | ||
17bb4538 | 136 | const videoModel = new VideoModel(this.grab(row, this.tables.getVideoAttributes(), ''), this.buildOpts) |
d9bf974f C |
137 | |
138 | videoModel.UserVideoHistories = [] | |
139 | videoModel.Thumbnails = [] | |
140 | videoModel.VideoFiles = [] | |
141 | videoModel.VideoStreamingPlaylists = [] | |
142 | videoModel.Tags = [] | |
143 | videoModel.Trackers = [] | |
144 | ||
71d4af1e C |
145 | this.buildAccount(row, videoModel) |
146 | ||
147 | this.videosMemo[row.id] = videoModel | |
148 | ||
d9bf974f C |
149 | // Keep rows order |
150 | this.videos.push(videoModel) | |
151 | } | |
152 | ||
71d4af1e C |
153 | private buildAccount (row: SQLRow, videoModel: VideoModel) { |
154 | const id = row['VideoChannel.Account.id'] | |
155 | if (!id) return | |
156 | ||
157 | const channelModel = new VideoChannelModel(this.grab(row, this.tables.getChannelAttributes(), 'VideoChannel'), this.buildOpts) | |
158 | channelModel.Actor = this.buildActor(row, 'VideoChannel') | |
159 | ||
160 | const accountModel = new AccountModel(this.grab(row, this.tables.getAccountAttributes(), 'VideoChannel.Account'), this.buildOpts) | |
161 | accountModel.Actor = this.buildActor(row, 'VideoChannel.Account') | |
162 | ||
163 | channelModel.Account = accountModel | |
164 | ||
165 | videoModel.VideoChannel = channelModel | |
166 | } | |
167 | ||
17bb4538 C |
168 | private buildActor (row: SQLRow, prefix: string) { |
169 | const actorPrefix = `${prefix}.Actor` | |
170 | const avatarPrefix = `${actorPrefix}.Avatar` | |
171 | const serverPrefix = `${actorPrefix}.Server` | |
172 | ||
173 | const avatarModel = row[`${avatarPrefix}.id`] !== null | |
174 | ? new ActorImageModel(this.grab(row, this.tables.getAvatarAttributes(), avatarPrefix), this.buildOpts) | |
d9bf974f C |
175 | : null |
176 | ||
17bb4538 C |
177 | const serverModel = row[`${serverPrefix}.id`] !== null |
178 | ? new ServerModel(this.grab(row, this.tables.getServerAttributes(), serverPrefix), this.buildOpts) | |
d9bf974f C |
179 | : null |
180 | ||
17bb4538 | 181 | const actorModel = new ActorModel(this.grab(row, this.tables.getActorAttributes(), actorPrefix), this.buildOpts) |
d9bf974f C |
182 | actorModel.Avatar = avatarModel |
183 | actorModel.Server = serverModel | |
184 | ||
185 | return actorModel | |
186 | } | |
187 | ||
17bb4538 C |
188 | private setUserHistory (row: SQLRow, videoModel: VideoModel) { |
189 | const id = row['userVideoHistory.id'] | |
190 | if (!id || this.historyDone.has(id)) return | |
d9bf974f | 191 | |
17bb4538 | 192 | const attributes = this.grab(row, this.tables.getUserHistoryAttributes(), 'userVideoHistory') |
d9bf974f C |
193 | const historyModel = new UserVideoHistoryModel(attributes, this.buildOpts) |
194 | videoModel.UserVideoHistories.push(historyModel) | |
195 | ||
17bb4538 | 196 | this.historyDone.add(id) |
d9bf974f C |
197 | } |
198 | ||
17bb4538 C |
199 | private addThumbnail (row: SQLRow, videoModel: VideoModel) { |
200 | const id = row['Thumbnails.id'] | |
201 | if (!id || this.thumbnailsDone.has(id)) return | |
d9bf974f | 202 | |
17bb4538 | 203 | const attributes = this.grab(row, this.tables.getThumbnailAttributes(), 'Thumbnails') |
d9bf974f C |
204 | const thumbnailModel = new ThumbnailModel(attributes, this.buildOpts) |
205 | videoModel.Thumbnails.push(thumbnailModel) | |
206 | ||
17bb4538 | 207 | this.thumbnailsDone.add(id) |
d9bf974f C |
208 | } |
209 | ||
17bb4538 C |
210 | private addWebTorrentFile (row: SQLRow, videoModel: VideoModel) { |
211 | const id = row['VideoFiles.id'] | |
212 | if (!id || this.videoFileMemo[id]) return | |
d9bf974f | 213 | |
17bb4538 | 214 | const attributes = this.grab(row, this.tables.getFileAttributes(), 'VideoFiles') |
d9bf974f C |
215 | const videoFileModel = new VideoFileModel(attributes, this.buildOpts) |
216 | videoModel.VideoFiles.push(videoFileModel) | |
217 | ||
17bb4538 | 218 | this.videoFileMemo[id] = videoFileModel |
d9bf974f C |
219 | } |
220 | ||
17bb4538 C |
221 | private addStreamingPlaylist (row: SQLRow, videoModel: VideoModel) { |
222 | const id = row['VideoStreamingPlaylists.id'] | |
223 | if (!id || this.videoStreamingPlaylistMemo[id]) return | |
d9bf974f | 224 | |
17bb4538 | 225 | const attributes = this.grab(row, this.tables.getStreamingPlaylistAttributes(), 'VideoStreamingPlaylists') |
d9bf974f C |
226 | const streamingPlaylist = new VideoStreamingPlaylistModel(attributes, this.buildOpts) |
227 | streamingPlaylist.VideoFiles = [] | |
228 | ||
229 | videoModel.VideoStreamingPlaylists.push(streamingPlaylist) | |
230 | ||
17bb4538 | 231 | this.videoStreamingPlaylistMemo[id] = streamingPlaylist |
d9bf974f C |
232 | } |
233 | ||
17bb4538 C |
234 | private addStreamingPlaylistFile (row: SQLRow) { |
235 | const id = row['VideoStreamingPlaylists.VideoFiles.id'] | |
236 | if (!id || this.videoFileMemo[id]) return | |
d9bf974f | 237 | |
17bb4538 | 238 | const streamingPlaylist = this.videoStreamingPlaylistMemo[row['VideoStreamingPlaylists.id']] |
d9bf974f | 239 | |
17bb4538 | 240 | const attributes = this.grab(row, this.tables.getFileAttributes(), 'VideoStreamingPlaylists.VideoFiles') |
d9bf974f C |
241 | const videoFileModel = new VideoFileModel(attributes, this.buildOpts) |
242 | streamingPlaylist.VideoFiles.push(videoFileModel) | |
243 | ||
17bb4538 | 244 | this.videoFileMemo[id] = videoFileModel |
d9bf974f C |
245 | } |
246 | ||
17bb4538 | 247 | private addRedundancy (row: SQLRow, prefix: string, to: VideoFileModel | VideoStreamingPlaylistModel) { |
d9bf974f C |
248 | if (!to.RedundancyVideos) to.RedundancyVideos = [] |
249 | ||
17bb4538 C |
250 | const redundancyPrefix = `${prefix}.RedundancyVideos` |
251 | const id = row[`${redundancyPrefix}.id`] | |
252 | ||
253 | if (!id || this.redundancyDone.has(id)) return | |
d9bf974f | 254 | |
17bb4538 | 255 | const attributes = this.grab(row, this.tables.getRedundancyAttributes(), redundancyPrefix) |
d9bf974f C |
256 | const redundancyModel = new VideoRedundancyModel(attributes, this.buildOpts) |
257 | to.RedundancyVideos.push(redundancyModel) | |
258 | ||
17bb4538 | 259 | this.redundancyDone.add(id) |
d9bf974f C |
260 | } |
261 | ||
17bb4538 C |
262 | private addTag (row: SQLRow, videoModel: VideoModel) { |
263 | if (!row['Tags.name']) return | |
d9bf974f | 264 | |
17bb4538 | 265 | const key = `${row['Tags.VideoTagModel.videoId']}-${row['Tags.VideoTagModel.tagId']}` |
d9bf974f C |
266 | if (this.tagsDone.has(key)) return |
267 | ||
17bb4538 | 268 | const attributes = this.grab(row, this.tables.getTagAttributes(), 'Tags') |
d9bf974f C |
269 | const tagModel = new TagModel(attributes, this.buildOpts) |
270 | videoModel.Tags.push(tagModel) | |
271 | ||
272 | this.tagsDone.add(key) | |
273 | } | |
274 | ||
17bb4538 C |
275 | private addTracker (row: SQLRow, videoModel: VideoModel) { |
276 | if (!row['Trackers.id']) return | |
d9bf974f | 277 | |
17bb4538 | 278 | const key = `${row['Trackers.VideoTrackerModel.videoId']}-${row['Trackers.VideoTrackerModel.trackerId']}` |
d9bf974f C |
279 | if (this.trackersDone.has(key)) return |
280 | ||
17bb4538 | 281 | const attributes = this.grab(row, this.tables.getTrackerAttributes(), 'Trackers') |
d9bf974f C |
282 | const trackerModel = new TrackerModel(attributes, this.buildOpts) |
283 | videoModel.Trackers.push(trackerModel) | |
284 | ||
285 | this.trackersDone.add(key) | |
286 | } | |
287 | ||
17bb4538 C |
288 | private setBlacklisted (row: SQLRow, videoModel: VideoModel) { |
289 | const id = row['VideoBlacklist.id'] | |
290 | if (!id || this.blacklistDone.has(id)) return | |
d9bf974f | 291 | |
17bb4538 | 292 | const attributes = this.grab(row, this.tables.getBlacklistedAttributes(), 'VideoBlacklist') |
d9bf974f C |
293 | videoModel.VideoBlacklist = new VideoBlacklistModel(attributes, this.buildOpts) |
294 | ||
17bb4538 | 295 | this.blacklistDone.add(id) |
d9bf974f C |
296 | } |
297 | ||
17bb4538 C |
298 | private setScheduleVideoUpdate (row: SQLRow, videoModel: VideoModel) { |
299 | const id = row['ScheduleVideoUpdate.id'] | |
300 | if (!id || this.scheduleVideoUpdateDone.has(id)) return | |
d9bf974f | 301 | |
17bb4538 | 302 | const attributes = this.grab(row, this.tables.getScheduleUpdateAttributes(), 'ScheduleVideoUpdate') |
d9bf974f C |
303 | videoModel.ScheduleVideoUpdate = new ScheduleVideoUpdateModel(attributes, this.buildOpts) |
304 | ||
17bb4538 | 305 | this.scheduleVideoUpdateDone.add(id) |
d9bf974f C |
306 | } |
307 | ||
17bb4538 C |
308 | private setLive (row: SQLRow, videoModel: VideoModel) { |
309 | const id = row['VideoLive.id'] | |
310 | if (!id || this.liveDone.has(id)) return | |
d9bf974f | 311 | |
17bb4538 | 312 | const attributes = this.grab(row, this.tables.getLiveAttributes(), 'VideoLive') |
d9bf974f C |
313 | videoModel.VideoLive = new VideoLiveModel(attributes, this.buildOpts) |
314 | ||
17bb4538 C |
315 | this.liveDone.add(id) |
316 | } | |
317 | ||
318 | private grab (row: SQLRow, attributes: string[], prefix: string) { | |
319 | const result: { [ id: string ]: string | number } = {} | |
320 | ||
321 | for (const a of attributes) { | |
322 | const key = prefix | |
323 | ? prefix + '.' + a | |
324 | : a | |
325 | ||
326 | result[a] = row[key] | |
327 | } | |
328 | ||
329 | return result | |
d9bf974f C |
330 | } |
331 | } |