]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/models/video/sql/video-model-get-query-builder.ts
Update changelog
[github/Chocobozzz/PeerTube.git] / server / models / video / sql / video-model-get-query-builder.ts
1 import { Sequelize, Transaction } from 'sequelize'
2 import { AbstractVideoQueryBuilder } from './shared/abstract-video-query-builder'
3 import { VideoFileQueryBuilder } from './shared/video-file-query-builder'
4 import { VideoModelBuilder } from './shared/video-model-builder'
5 import { VideoTableAttributes } from './shared/video-table-attributes'
6
7 /**
8 *
9 * Build a GET SQL query, fetch rows and create the video model
10 *
11 */
12
13 export type GetType =
14 'api' |
15 'full-light' |
16 'account-blacklist-files' |
17 'all-files' |
18 'thumbnails' |
19 'thumbnails-blacklist' |
20 'id' |
21 'blacklist-rights'
22
23 export type BuildVideoGetQueryOptions = {
24 id?: number | string
25 url?: string
26
27 type: GetType
28
29 userId?: number
30 transaction?: Transaction
31
32 logging?: boolean
33 }
34
35 export class VideoModelGetQueryBuilder {
36 videoQueryBuilder: VideosModelGetQuerySubBuilder
37 webtorrentFilesQueryBuilder: VideoFileQueryBuilder
38 streamingPlaylistFilesQueryBuilder: VideoFileQueryBuilder
39
40 private readonly videoModelBuilder: VideoModelBuilder
41
42 private static readonly videoFilesInclude = new Set<GetType>([ 'api', 'full-light', 'account-blacklist-files', 'all-files' ])
43
44 constructor (protected readonly sequelize: Sequelize) {
45 this.videoQueryBuilder = new VideosModelGetQuerySubBuilder(sequelize)
46 this.webtorrentFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
47 this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
48
49 this.videoModelBuilder = new VideoModelBuilder('get', new VideoTableAttributes('get'))
50 }
51
52 async queryVideo (options: BuildVideoGetQueryOptions) {
53 const [ videoRows, webtorrentFilesRows, streamingPlaylistFilesRows ] = await Promise.all([
54 this.videoQueryBuilder.queryVideos(options),
55
56 VideoModelGetQueryBuilder.videoFilesInclude.has(options.type)
57 ? this.webtorrentFilesQueryBuilder.queryWebTorrentVideos(options)
58 : Promise.resolve(undefined),
59
60 VideoModelGetQueryBuilder.videoFilesInclude.has(options.type)
61 ? this.streamingPlaylistFilesQueryBuilder.queryStreamingPlaylistVideos(options)
62 : Promise.resolve(undefined)
63 ])
64
65 const videos = this.videoModelBuilder.buildVideosFromRows({
66 rows: videoRows,
67 rowsWebTorrentFiles: webtorrentFilesRows,
68 rowsStreamingPlaylist: streamingPlaylistFilesRows
69 })
70
71 if (videos.length > 1) {
72 throw new Error('Video results is more than 1')
73 }
74
75 if (videos.length === 0) return null
76
77 return videos[0]
78 }
79 }
80
81 export class VideosModelGetQuerySubBuilder extends AbstractVideoQueryBuilder {
82 protected attributes: { [key: string]: string }
83
84 protected webtorrentFilesQuery: string
85 protected streamingPlaylistFilesQuery: string
86
87 private static readonly trackersInclude = new Set<GetType>([ 'api' ])
88 private static readonly liveInclude = new Set<GetType>([ 'api', 'full-light' ])
89 private static readonly scheduleUpdateInclude = new Set<GetType>([ 'api', 'full-light' ])
90 private static readonly tagsInclude = new Set<GetType>([ 'api', 'full-light' ])
91 private static readonly userHistoryInclude = new Set<GetType>([ 'api', 'full-light' ])
92 private static readonly accountInclude = new Set<GetType>([ 'api', 'full-light', 'account-blacklist-files' ])
93 private static readonly ownerUserInclude = new Set<GetType>([ 'blacklist-rights' ])
94
95 private static readonly blacklistedInclude = new Set<GetType>([
96 'api',
97 'full-light',
98 'account-blacklist-files',
99 'thumbnails-blacklist',
100 'blacklist-rights'
101 ])
102
103 private static readonly thumbnailsInclude = new Set<GetType>([
104 'api',
105 'full-light',
106 'account-blacklist-files',
107 'all-files',
108 'thumbnails',
109 'thumbnails-blacklist'
110 ])
111
112 constructor (protected readonly sequelize: Sequelize) {
113 super('get')
114 }
115
116 queryVideos (options: BuildVideoGetQueryOptions) {
117 this.buildMainGetQuery(options)
118
119 return this.runQuery(options)
120 }
121
122 private buildMainGetQuery (options: BuildVideoGetQueryOptions) {
123 this.attributes = {
124 '"video".*': ''
125 }
126
127 if (VideosModelGetQuerySubBuilder.thumbnailsInclude.has(options.type)) {
128 this.includeThumbnails()
129 }
130
131 if (VideosModelGetQuerySubBuilder.blacklistedInclude.has(options.type)) {
132 this.includeBlacklisted()
133 }
134
135 if (VideosModelGetQuerySubBuilder.accountInclude.has(options.type)) {
136 this.includeChannels()
137 this.includeAccounts()
138 }
139
140 if (VideosModelGetQuerySubBuilder.tagsInclude.has(options.type)) {
141 this.includeTags()
142 }
143
144 if (VideosModelGetQuerySubBuilder.scheduleUpdateInclude.has(options.type)) {
145 this.includeScheduleUpdate()
146 }
147
148 if (VideosModelGetQuerySubBuilder.liveInclude.has(options.type)) {
149 this.includeLive()
150 }
151
152 if (options.userId && VideosModelGetQuerySubBuilder.userHistoryInclude.has(options.type)) {
153 this.includeUserHistory(options.userId)
154 }
155
156 if (VideosModelGetQuerySubBuilder.ownerUserInclude.has(options.type)) {
157 this.includeOwnerUser()
158 }
159
160 if (VideosModelGetQuerySubBuilder.trackersInclude.has(options.type)) {
161 this.includeTrackers()
162 }
163
164 this.whereId(options)
165
166 this.query = this.buildQuery(options)
167 }
168
169 private buildQuery (options: BuildVideoGetQueryOptions) {
170 const order = VideosModelGetQuerySubBuilder.tagsInclude.has(options.type)
171 ? 'ORDER BY "Tags"."name" ASC'
172 : ''
173
174 const from = `SELECT * FROM "video" ${this.where} LIMIT 1`
175
176 return `${this.buildSelect()} FROM (${from}) AS "video" ${this.joins} ${order}`
177 }
178 }