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