]>
Commit | Line | Data |
---|---|---|
d9bf974f C |
1 | import { pick } from 'lodash' |
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' | |
18 | import { VideoAttributes } from './video-attributes' | |
19 | ||
1d43c3a6 C |
20 | /** |
21 | * | |
22 | * Build video models from SQL rows | |
23 | * | |
24 | */ | |
25 | ||
d9bf974f C |
26 | export 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 | } |