]>
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) { | |
668f864f C |
111 | const id = row['VideoFiles.id'] |
112 | if (!id) continue | |
113 | ||
17bb4538 C |
114 | const videoModel = this.videosMemo[row.id] |
115 | this.addWebTorrentFile(row, videoModel) | |
668f864f | 116 | this.addRedundancy(row, 'VideoFiles.RedundancyVideos', this.videoFileMemo[id]) |
17bb4538 C |
117 | } |
118 | } | |
119 | ||
120 | private grabSeparateStreamingPlaylistFiles (rowsStreamingPlaylist?: SQLRow[]) { | |
121 | if (!rowsStreamingPlaylist) return | |
122 | ||
123 | for (const row of rowsStreamingPlaylist || []) { | |
668f864f C |
124 | const id = row['VideoStreamingPlaylists.id'] |
125 | if (!id) continue | |
126 | ||
17bb4538 C |
127 | const videoModel = this.videosMemo[row.id] |
128 | ||
129 | this.addStreamingPlaylist(row, videoModel) | |
130 | this.addStreamingPlaylistFile(row) | |
131 | this.addRedundancy( | |
132 | row, | |
133 | 'VideoStreamingPlaylists.RedundancyVideos', | |
668f864f | 134 | this.videoStreamingPlaylistMemo[id] |
17bb4538 C |
135 | ) |
136 | } | |
137 | } | |
138 | ||
71d4af1e | 139 | private buildVideoAndAccount (row: SQLRow) { |
d9bf974f C |
140 | if (this.videosMemo[row.id]) return |
141 | ||
17bb4538 | 142 | const videoModel = new VideoModel(this.grab(row, this.tables.getVideoAttributes(), ''), this.buildOpts) |
d9bf974f C |
143 | |
144 | videoModel.UserVideoHistories = [] | |
145 | videoModel.Thumbnails = [] | |
146 | videoModel.VideoFiles = [] | |
147 | videoModel.VideoStreamingPlaylists = [] | |
148 | videoModel.Tags = [] | |
149 | videoModel.Trackers = [] | |
150 | ||
71d4af1e C |
151 | this.buildAccount(row, videoModel) |
152 | ||
153 | this.videosMemo[row.id] = videoModel | |
154 | ||
d9bf974f C |
155 | // Keep rows order |
156 | this.videos.push(videoModel) | |
157 | } | |
158 | ||
71d4af1e C |
159 | private buildAccount (row: SQLRow, videoModel: VideoModel) { |
160 | const id = row['VideoChannel.Account.id'] | |
161 | if (!id) return | |
162 | ||
163 | const channelModel = new VideoChannelModel(this.grab(row, this.tables.getChannelAttributes(), 'VideoChannel'), this.buildOpts) | |
164 | channelModel.Actor = this.buildActor(row, 'VideoChannel') | |
165 | ||
166 | const accountModel = new AccountModel(this.grab(row, this.tables.getAccountAttributes(), 'VideoChannel.Account'), this.buildOpts) | |
167 | accountModel.Actor = this.buildActor(row, 'VideoChannel.Account') | |
168 | ||
169 | channelModel.Account = accountModel | |
170 | ||
171 | videoModel.VideoChannel = channelModel | |
172 | } | |
173 | ||
17bb4538 C |
174 | private buildActor (row: SQLRow, prefix: string) { |
175 | const actorPrefix = `${prefix}.Actor` | |
176 | const avatarPrefix = `${actorPrefix}.Avatar` | |
177 | const serverPrefix = `${actorPrefix}.Server` | |
178 | ||
179 | const avatarModel = row[`${avatarPrefix}.id`] !== null | |
180 | ? new ActorImageModel(this.grab(row, this.tables.getAvatarAttributes(), avatarPrefix), this.buildOpts) | |
d9bf974f C |
181 | : null |
182 | ||
17bb4538 C |
183 | const serverModel = row[`${serverPrefix}.id`] !== null |
184 | ? new ServerModel(this.grab(row, this.tables.getServerAttributes(), serverPrefix), this.buildOpts) | |
d9bf974f C |
185 | : null |
186 | ||
17bb4538 | 187 | const actorModel = new ActorModel(this.grab(row, this.tables.getActorAttributes(), actorPrefix), this.buildOpts) |
d9bf974f C |
188 | actorModel.Avatar = avatarModel |
189 | actorModel.Server = serverModel | |
190 | ||
191 | return actorModel | |
192 | } | |
193 | ||
17bb4538 C |
194 | private setUserHistory (row: SQLRow, videoModel: VideoModel) { |
195 | const id = row['userVideoHistory.id'] | |
196 | if (!id || this.historyDone.has(id)) return | |
d9bf974f | 197 | |
17bb4538 | 198 | const attributes = this.grab(row, this.tables.getUserHistoryAttributes(), 'userVideoHistory') |
d9bf974f C |
199 | const historyModel = new UserVideoHistoryModel(attributes, this.buildOpts) |
200 | videoModel.UserVideoHistories.push(historyModel) | |
201 | ||
17bb4538 | 202 | this.historyDone.add(id) |
d9bf974f C |
203 | } |
204 | ||
17bb4538 C |
205 | private addThumbnail (row: SQLRow, videoModel: VideoModel) { |
206 | const id = row['Thumbnails.id'] | |
207 | if (!id || this.thumbnailsDone.has(id)) return | |
d9bf974f | 208 | |
17bb4538 | 209 | const attributes = this.grab(row, this.tables.getThumbnailAttributes(), 'Thumbnails') |
d9bf974f C |
210 | const thumbnailModel = new ThumbnailModel(attributes, this.buildOpts) |
211 | videoModel.Thumbnails.push(thumbnailModel) | |
212 | ||
17bb4538 | 213 | this.thumbnailsDone.add(id) |
d9bf974f C |
214 | } |
215 | ||
17bb4538 C |
216 | private addWebTorrentFile (row: SQLRow, videoModel: VideoModel) { |
217 | const id = row['VideoFiles.id'] | |
218 | if (!id || this.videoFileMemo[id]) return | |
d9bf974f | 219 | |
17bb4538 | 220 | const attributes = this.grab(row, this.tables.getFileAttributes(), 'VideoFiles') |
d9bf974f C |
221 | const videoFileModel = new VideoFileModel(attributes, this.buildOpts) |
222 | videoModel.VideoFiles.push(videoFileModel) | |
223 | ||
17bb4538 | 224 | this.videoFileMemo[id] = videoFileModel |
d9bf974f C |
225 | } |
226 | ||
17bb4538 C |
227 | private addStreamingPlaylist (row: SQLRow, videoModel: VideoModel) { |
228 | const id = row['VideoStreamingPlaylists.id'] | |
229 | if (!id || this.videoStreamingPlaylistMemo[id]) return | |
d9bf974f | 230 | |
17bb4538 | 231 | const attributes = this.grab(row, this.tables.getStreamingPlaylistAttributes(), 'VideoStreamingPlaylists') |
d9bf974f C |
232 | const streamingPlaylist = new VideoStreamingPlaylistModel(attributes, this.buildOpts) |
233 | streamingPlaylist.VideoFiles = [] | |
234 | ||
235 | videoModel.VideoStreamingPlaylists.push(streamingPlaylist) | |
236 | ||
17bb4538 | 237 | this.videoStreamingPlaylistMemo[id] = streamingPlaylist |
d9bf974f C |
238 | } |
239 | ||
17bb4538 C |
240 | private addStreamingPlaylistFile (row: SQLRow) { |
241 | const id = row['VideoStreamingPlaylists.VideoFiles.id'] | |
242 | if (!id || this.videoFileMemo[id]) return | |
d9bf974f | 243 | |
17bb4538 | 244 | const streamingPlaylist = this.videoStreamingPlaylistMemo[row['VideoStreamingPlaylists.id']] |
d9bf974f | 245 | |
17bb4538 | 246 | const attributes = this.grab(row, this.tables.getFileAttributes(), 'VideoStreamingPlaylists.VideoFiles') |
d9bf974f C |
247 | const videoFileModel = new VideoFileModel(attributes, this.buildOpts) |
248 | streamingPlaylist.VideoFiles.push(videoFileModel) | |
249 | ||
17bb4538 | 250 | this.videoFileMemo[id] = videoFileModel |
d9bf974f C |
251 | } |
252 | ||
17bb4538 | 253 | private addRedundancy (row: SQLRow, prefix: string, to: VideoFileModel | VideoStreamingPlaylistModel) { |
d9bf974f C |
254 | if (!to.RedundancyVideos) to.RedundancyVideos = [] |
255 | ||
17bb4538 C |
256 | const redundancyPrefix = `${prefix}.RedundancyVideos` |
257 | const id = row[`${redundancyPrefix}.id`] | |
258 | ||
259 | if (!id || this.redundancyDone.has(id)) return | |
d9bf974f | 260 | |
17bb4538 | 261 | const attributes = this.grab(row, this.tables.getRedundancyAttributes(), redundancyPrefix) |
d9bf974f C |
262 | const redundancyModel = new VideoRedundancyModel(attributes, this.buildOpts) |
263 | to.RedundancyVideos.push(redundancyModel) | |
264 | ||
17bb4538 | 265 | this.redundancyDone.add(id) |
d9bf974f C |
266 | } |
267 | ||
17bb4538 C |
268 | private addTag (row: SQLRow, videoModel: VideoModel) { |
269 | if (!row['Tags.name']) return | |
d9bf974f | 270 | |
17bb4538 | 271 | const key = `${row['Tags.VideoTagModel.videoId']}-${row['Tags.VideoTagModel.tagId']}` |
d9bf974f C |
272 | if (this.tagsDone.has(key)) return |
273 | ||
17bb4538 | 274 | const attributes = this.grab(row, this.tables.getTagAttributes(), 'Tags') |
d9bf974f C |
275 | const tagModel = new TagModel(attributes, this.buildOpts) |
276 | videoModel.Tags.push(tagModel) | |
277 | ||
278 | this.tagsDone.add(key) | |
279 | } | |
280 | ||
17bb4538 C |
281 | private addTracker (row: SQLRow, videoModel: VideoModel) { |
282 | if (!row['Trackers.id']) return | |
d9bf974f | 283 | |
17bb4538 | 284 | const key = `${row['Trackers.VideoTrackerModel.videoId']}-${row['Trackers.VideoTrackerModel.trackerId']}` |
d9bf974f C |
285 | if (this.trackersDone.has(key)) return |
286 | ||
17bb4538 | 287 | const attributes = this.grab(row, this.tables.getTrackerAttributes(), 'Trackers') |
d9bf974f C |
288 | const trackerModel = new TrackerModel(attributes, this.buildOpts) |
289 | videoModel.Trackers.push(trackerModel) | |
290 | ||
291 | this.trackersDone.add(key) | |
292 | } | |
293 | ||
17bb4538 C |
294 | private setBlacklisted (row: SQLRow, videoModel: VideoModel) { |
295 | const id = row['VideoBlacklist.id'] | |
296 | if (!id || this.blacklistDone.has(id)) return | |
d9bf974f | 297 | |
17bb4538 | 298 | const attributes = this.grab(row, this.tables.getBlacklistedAttributes(), 'VideoBlacklist') |
d9bf974f C |
299 | videoModel.VideoBlacklist = new VideoBlacklistModel(attributes, this.buildOpts) |
300 | ||
17bb4538 | 301 | this.blacklistDone.add(id) |
d9bf974f C |
302 | } |
303 | ||
17bb4538 C |
304 | private setScheduleVideoUpdate (row: SQLRow, videoModel: VideoModel) { |
305 | const id = row['ScheduleVideoUpdate.id'] | |
306 | if (!id || this.scheduleVideoUpdateDone.has(id)) return | |
d9bf974f | 307 | |
17bb4538 | 308 | const attributes = this.grab(row, this.tables.getScheduleUpdateAttributes(), 'ScheduleVideoUpdate') |
d9bf974f C |
309 | videoModel.ScheduleVideoUpdate = new ScheduleVideoUpdateModel(attributes, this.buildOpts) |
310 | ||
17bb4538 | 311 | this.scheduleVideoUpdateDone.add(id) |
d9bf974f C |
312 | } |
313 | ||
17bb4538 C |
314 | private setLive (row: SQLRow, videoModel: VideoModel) { |
315 | const id = row['VideoLive.id'] | |
316 | if (!id || this.liveDone.has(id)) return | |
d9bf974f | 317 | |
17bb4538 | 318 | const attributes = this.grab(row, this.tables.getLiveAttributes(), 'VideoLive') |
d9bf974f C |
319 | videoModel.VideoLive = new VideoLiveModel(attributes, this.buildOpts) |
320 | ||
17bb4538 C |
321 | this.liveDone.add(id) |
322 | } | |
323 | ||
324 | private grab (row: SQLRow, attributes: string[], prefix: string) { | |
325 | const result: { [ id: string ]: string | number } = {} | |
326 | ||
327 | for (const a of attributes) { | |
328 | const key = prefix | |
329 | ? prefix + '.' + a | |
330 | : a | |
331 | ||
332 | result[a] = row[key] | |
333 | } | |
334 | ||
335 | return result | |
d9bf974f C |
336 | } |
337 | } |