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