diff options
Diffstat (limited to 'server/models/video/sql/video/video-model-get-query-builder.ts')
-rw-r--r-- | server/models/video/sql/video/video-model-get-query-builder.ts | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/server/models/video/sql/video/video-model-get-query-builder.ts b/server/models/video/sql/video/video-model-get-query-builder.ts new file mode 100644 index 000000000..a65c96097 --- /dev/null +++ b/server/models/video/sql/video/video-model-get-query-builder.ts | |||
@@ -0,0 +1,178 @@ | |||
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 | } | ||