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