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 { ServerModel } from '@server/models/server/server'
6 import { UserVideoHistoryModel } from '@server/models/user/user-video-history'
7 import { ThumbnailModel } from '../thumbnail'
8 import { VideoModel } from '../video'
9 import { VideoChannelModel } from '../video-channel'
10 import { VideoFileModel } from '../video-file'
11 import { VideoStreamingPlaylistModel } from '../video-streaming-playlist'
13 function buildVideosFromRows (rows: any[]) {
14 const videosMemo: { [ id: number ]: VideoModel } = {}
15 const videoStreamingPlaylistMemo: { [ id: number ]: VideoStreamingPlaylistModel } = {}
17 const thumbnailsDone = new Set<number>()
18 const historyDone = new Set<number>()
19 const videoFilesDone = new Set<number>()
21 const videos: VideoModel[] = []
23 const avatarKeys = [ 'id', 'filename', 'fileUrl', 'onDisk', 'createdAt', 'updatedAt' ]
24 const actorKeys = [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ]
25 const serverKeys = [ 'id', 'host' ]
26 const videoFileKeys = [
40 'videoStreamingPlaylistId'
42 const videoStreamingPlaylistKeys = [ 'id', 'type', 'playlistUrl' ]
66 'originallyPublishedAt',
71 const buildOpts = { raw: true }
73 function buildActor (rowActor: any) {
74 const avatarModel = rowActor.Avatar.id !== null
75 ? new ActorImageModel(pick(rowActor.Avatar, avatarKeys), buildOpts)
78 const serverModel = rowActor.Server.id !== null
79 ? new ServerModel(pick(rowActor.Server, serverKeys), buildOpts)
82 const actorModel = new ActorModel(pick(rowActor, actorKeys), buildOpts)
83 actorModel.Avatar = avatarModel
84 actorModel.Server = serverModel
89 for (const row of rows) {
90 if (!videosMemo[row.id]) {
92 const channel = row.VideoChannel
93 const channelModel = new VideoChannelModel(pick(channel, [ 'id', 'name', 'description', 'actorId' ]), buildOpts)
94 channelModel.Actor = buildActor(channel.Actor)
96 const account = row.VideoChannel.Account
97 const accountModel = new AccountModel(pick(account, [ 'id', 'name' ]), buildOpts)
98 accountModel.Actor = buildActor(account.Actor)
100 channelModel.Account = accountModel
102 const videoModel = new VideoModel(pick(row, videoKeys), buildOpts)
103 videoModel.VideoChannel = channelModel
105 videoModel.UserVideoHistories = []
106 videoModel.Thumbnails = []
107 videoModel.VideoFiles = []
108 videoModel.VideoStreamingPlaylists = []
110 videosMemo[row.id] = videoModel
111 // Don't take object value to have a sorted array
112 videos.push(videoModel)
115 const videoModel = videosMemo[row.id]
117 if (row.userVideoHistory?.id && !historyDone.has(row.userVideoHistory.id)) {
118 const historyModel = new UserVideoHistoryModel(pick(row.userVideoHistory, [ 'id', 'currentTime' ]), buildOpts)
119 videoModel.UserVideoHistories.push(historyModel)
121 historyDone.add(row.userVideoHistory.id)
124 if (row.Thumbnails?.id && !thumbnailsDone.has(row.Thumbnails.id)) {
125 const thumbnailModel = new ThumbnailModel(pick(row.Thumbnails, [ 'id', 'type', 'filename' ]), buildOpts)
126 videoModel.Thumbnails.push(thumbnailModel)
128 thumbnailsDone.add(row.Thumbnails.id)
131 if (row.VideoFiles?.id && !videoFilesDone.has(row.VideoFiles.id)) {
132 const videoFileModel = new VideoFileModel(pick(row.VideoFiles, videoFileKeys), buildOpts)
133 videoModel.VideoFiles.push(videoFileModel)
135 videoFilesDone.add(row.VideoFiles.id)
138 if (row.VideoStreamingPlaylists?.id && !videoStreamingPlaylistMemo[row.VideoStreamingPlaylists.id]) {
139 const streamingPlaylist = new VideoStreamingPlaylistModel(pick(row.VideoStreamingPlaylists, videoStreamingPlaylistKeys), buildOpts)
140 streamingPlaylist.VideoFiles = []
142 videoModel.VideoStreamingPlaylists.push(streamingPlaylist)
144 videoStreamingPlaylistMemo[streamingPlaylist.id] = streamingPlaylist
147 if (row.VideoStreamingPlaylists?.VideoFiles?.id && !videoFilesDone.has(row.VideoStreamingPlaylists.VideoFiles.id)) {
148 const streamingPlaylist = videoStreamingPlaylistMemo[row.VideoStreamingPlaylists.id]
150 const videoFileModel = new VideoFileModel(pick(row.VideoStreamingPlaylists.VideoFiles, videoFileKeys), buildOpts)
151 streamingPlaylist.VideoFiles.push(videoFileModel)
153 videoFilesDone.add(row.VideoStreamingPlaylists.VideoFiles.id)