aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/video
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-06-11 14:09:33 +0200
committerChocobozzz <me@florianbigard.com>2021-06-11 14:09:52 +0200
commit71d4af1efc810f853e1a0d986bf758c201692594 (patch)
tree2066053638baefb6430772c2e0a0aa1774019a51 /server/models/video
parent3c79c2ce86eaf9e151ab6c2c9d1f646968a16744 (diff)
downloadPeerTube-71d4af1efc810f853e1a0d986bf758c201692594.tar.gz
PeerTube-71d4af1efc810f853e1a0d986bf758c201692594.tar.zst
PeerTube-71d4af1efc810f853e1a0d986bf758c201692594.zip
Use raw SQL for most of video queries
Diffstat (limited to 'server/models/video')
-rw-r--r--server/models/video/sql/shared/abstract-videos-model-query-builder.ts24
-rw-r--r--server/models/video/sql/shared/abstract-videos-query-builder.ts9
-rw-r--r--server/models/video/sql/shared/video-file-query-builder.ts16
-rw-r--r--server/models/video/sql/shared/video-model-builder.ts36
-rw-r--r--server/models/video/sql/shared/video-tables.ts8
-rw-r--r--server/models/video/sql/video-model-get-query-builder.ts110
-rw-r--r--server/models/video/sql/videos-model-list-query-builder.ts3
-rw-r--r--server/models/video/video.ts150
8 files changed, 187 insertions, 169 deletions
diff --git a/server/models/video/sql/shared/abstract-videos-model-query-builder.ts b/server/models/video/sql/shared/abstract-videos-model-query-builder.ts
index 65df8d914..d959cb5d0 100644
--- a/server/models/video/sql/shared/abstract-videos-model-query-builder.ts
+++ b/server/models/video/sql/shared/abstract-videos-model-query-builder.ts
@@ -80,6 +80,18 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder
80 } 80 }
81 } 81 }
82 82
83 protected includeOwnerUser () {
84 this.addJoin('INNER JOIN "videoChannel" AS "VideoChannel" ON "video"."channelId" = "VideoChannel"."id"')
85 this.addJoin('INNER JOIN "account" AS "VideoChannel->Account" ON "VideoChannel"."accountId" = "VideoChannel->Account"."id"')
86
87 this.attributes = {
88 ...this.attributes,
89
90 ...this.buildAttributesObject('VideoChannel', this.tables.getChannelAttributes()),
91 ...this.buildAttributesObject('VideoChannel->Account', this.tables.getUserAccountAttributes())
92 }
93 }
94
83 protected includeThumbnails () { 95 protected includeThumbnails () {
84 this.addJoin('LEFT OUTER JOIN "thumbnail" AS "Thumbnails" ON "video"."id" = "Thumbnails"."videoId"') 96 this.addJoin('LEFT OUTER JOIN "thumbnail" AS "Thumbnails" ON "video"."id" = "Thumbnails"."videoId"')
85 97
@@ -269,14 +281,20 @@ export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder
269 return result 281 return result
270 } 282 }
271 283
272 protected whereId (id: string | number) { 284 protected whereId (options: { id?: string | number, url?: string }) {
273 if (validator.isInt('' + id)) { 285 if (options.url) {
286 this.where = 'WHERE "video"."url" = :videoUrl'
287 this.replacements.videoUrl = options.url
288 return
289 }
290
291 if (validator.isInt('' + options.id)) {
274 this.where = 'WHERE "video".id = :videoId' 292 this.where = 'WHERE "video".id = :videoId'
275 } else { 293 } else {
276 this.where = 'WHERE uuid = :videoId' 294 this.where = 'WHERE uuid = :videoId'
277 } 295 }
278 296
279 this.replacements.videoId = id 297 this.replacements.videoId = options.id
280 } 298 }
281 299
282 protected addJoin (join: string) { 300 protected addJoin (join: string) {
diff --git a/server/models/video/sql/shared/abstract-videos-query-builder.ts b/server/models/video/sql/shared/abstract-videos-query-builder.ts
index 7e67fa34f..10699317a 100644
--- a/server/models/video/sql/shared/abstract-videos-query-builder.ts
+++ b/server/models/video/sql/shared/abstract-videos-query-builder.ts
@@ -13,16 +13,17 @@ export class AbstractVideosQueryBuilder {
13 protected query: string 13 protected query: string
14 protected replacements: any = {} 14 protected replacements: any = {}
15 15
16 protected runQuery (transaction?: Transaction) { 16 protected runQuery (options: { transaction?: Transaction, logging?: boolean } = {}) {
17 logger.debug('Running videos query.', { query: this.query, replacements: this.replacements }) 17 logger.debug('Running videos query.', { query: this.query, replacements: this.replacements })
18 18
19 const options = { 19 const queryOptions = {
20 transaction, 20 transaction: options.transaction,
21 logging: options.logging,
21 replacements: this.replacements, 22 replacements: this.replacements,
22 type: QueryTypes.SELECT as QueryTypes.SELECT, 23 type: QueryTypes.SELECT as QueryTypes.SELECT,
23 next: false 24 next: false
24 } 25 }
25 26
26 return this.sequelize.query<any>(this.query, options) 27 return this.sequelize.query<any>(this.query, queryOptions)
27 } 28 }
28} 29}
diff --git a/server/models/video/sql/shared/video-file-query-builder.ts b/server/models/video/sql/shared/video-file-query-builder.ts
index 7d822f8fa..a62fa64f8 100644
--- a/server/models/video/sql/shared/video-file-query-builder.ts
+++ b/server/models/video/sql/shared/video-file-query-builder.ts
@@ -18,13 +18,13 @@ export class VideoFileQueryBuilder extends AbstractVideosModelQueryBuilder {
18 queryWebTorrentVideos (options: BuildVideoGetQueryOptions) { 18 queryWebTorrentVideos (options: BuildVideoGetQueryOptions) {
19 this.buildWebtorrentFilesQuery(options) 19 this.buildWebtorrentFilesQuery(options)
20 20
21 return this.runQuery(options.transaction) 21 return this.runQuery(options)
22 } 22 }
23 23
24 queryStreamingPlaylistVideos (options: BuildVideoGetQueryOptions) { 24 queryStreamingPlaylistVideos (options: BuildVideoGetQueryOptions) {
25 this.buildVideoStreamingPlaylistFilesQuery(options) 25 this.buildVideoStreamingPlaylistFilesQuery(options)
26 26
27 return this.runQuery(options.transaction) 27 return this.runQuery(options)
28 } 28 }
29 29
30 private buildWebtorrentFilesQuery (options: BuildVideoGetQueryOptions) { 30 private buildWebtorrentFilesQuery (options: BuildVideoGetQueryOptions) {
@@ -34,11 +34,11 @@ export class VideoFileQueryBuilder extends AbstractVideosModelQueryBuilder {
34 34
35 this.includeWebtorrentFiles(true) 35 this.includeWebtorrentFiles(true)
36 36
37 if (options.forGetAPI === true) { 37 if (this.shouldIncludeRedundancies(options)) {
38 this.includeWebTorrentRedundancies() 38 this.includeWebTorrentRedundancies()
39 } 39 }
40 40
41 this.whereId(options.id) 41 this.whereId(options)
42 42
43 this.query = this.buildQuery() 43 this.query = this.buildQuery()
44 } 44 }
@@ -50,11 +50,11 @@ export class VideoFileQueryBuilder extends AbstractVideosModelQueryBuilder {
50 50
51 this.includeStreamingPlaylistFiles(true) 51 this.includeStreamingPlaylistFiles(true)
52 52
53 if (options.forGetAPI === true) { 53 if (this.shouldIncludeRedundancies(options)) {
54 this.includeStreamingPlaylistRedundancies() 54 this.includeStreamingPlaylistRedundancies()
55 } 55 }
56 56
57 this.whereId(options.id) 57 this.whereId(options)
58 58
59 this.query = this.buildQuery() 59 this.query = this.buildQuery()
60 } 60 }
@@ -62,4 +62,8 @@ export class VideoFileQueryBuilder extends AbstractVideosModelQueryBuilder {
62 private buildQuery () { 62 private buildQuery () {
63 return `${this.buildSelect()} FROM "video" ${this.joins} ${this.where}` 63 return `${this.buildSelect()} FROM "video" ${this.joins} ${this.where}`
64 } 64 }
65
66 private shouldIncludeRedundancies (options: BuildVideoGetQueryOptions) {
67 return options.type === 'api'
68 }
65} 69}
diff --git a/server/models/video/sql/shared/video-model-builder.ts b/server/models/video/sql/shared/video-model-builder.ts
index 2a60dab04..467a9378a 100644
--- a/server/models/video/sql/shared/video-model-builder.ts
+++ b/server/models/video/sql/shared/video-model-builder.ts
@@ -1,5 +1,4 @@
1 1
2import { logger } from '@server/helpers/logger'
3import { AccountModel } from '@server/models/account/account' 2import { AccountModel } from '@server/models/account/account'
4import { ActorModel } from '@server/models/actor/actor' 3import { ActorModel } from '@server/models/actor/actor'
5import { ActorImageModel } from '@server/models/actor/actor-image' 4import { ActorImageModel } from '@server/models/actor/actor-image'
@@ -56,7 +55,7 @@ export class VideoModelBuilder {
56 this.reinit() 55 this.reinit()
57 56
58 for (const row of rows) { 57 for (const row of rows) {
59 this.buildVideo(row) 58 this.buildVideoAndAccount(row)
60 59
61 const videoModel = this.videosMemo[row.id] 60 const videoModel = this.videosMemo[row.id]
62 61
@@ -131,22 +130,10 @@ export class VideoModelBuilder {
131 } 130 }
132 } 131 }
133 132
134 private buildVideo (row: SQLRow) { 133 private buildVideoAndAccount (row: SQLRow) {
135 if (this.videosMemo[row.id]) return 134 if (this.videosMemo[row.id]) return
136 135
137 // Build Channel
138 const channelModel = new VideoChannelModel(this.grab(row, this.tables.getChannelAttributes(), 'VideoChannel'), this.buildOpts)
139 channelModel.Actor = this.buildActor(row, 'VideoChannel')
140
141 const accountModel = new AccountModel(this.grab(row, this.tables.getAccountAttributes(), 'VideoChannel.Account'), this.buildOpts)
142 accountModel.Actor = this.buildActor(row, 'VideoChannel.Account')
143
144 channelModel.Account = accountModel
145
146 const videoModel = new VideoModel(this.grab(row, this.tables.getVideoAttributes(), ''), this.buildOpts) 136 const videoModel = new VideoModel(this.grab(row, this.tables.getVideoAttributes(), ''), this.buildOpts)
147 videoModel.VideoChannel = channelModel
148
149 this.videosMemo[row.id] = videoModel
150 137
151 videoModel.UserVideoHistories = [] 138 videoModel.UserVideoHistories = []
152 videoModel.Thumbnails = [] 139 videoModel.Thumbnails = []
@@ -155,10 +142,29 @@ export class VideoModelBuilder {
155 videoModel.Tags = [] 142 videoModel.Tags = []
156 videoModel.Trackers = [] 143 videoModel.Trackers = []
157 144
145 this.buildAccount(row, videoModel)
146
147 this.videosMemo[row.id] = videoModel
148
158 // Keep rows order 149 // Keep rows order
159 this.videos.push(videoModel) 150 this.videos.push(videoModel)
160 } 151 }
161 152
153 private buildAccount (row: SQLRow, videoModel: VideoModel) {
154 const id = row['VideoChannel.Account.id']
155 if (!id) return
156
157 const channelModel = new VideoChannelModel(this.grab(row, this.tables.getChannelAttributes(), 'VideoChannel'), this.buildOpts)
158 channelModel.Actor = this.buildActor(row, 'VideoChannel')
159
160 const accountModel = new AccountModel(this.grab(row, this.tables.getAccountAttributes(), 'VideoChannel.Account'), this.buildOpts)
161 accountModel.Actor = this.buildActor(row, 'VideoChannel.Account')
162
163 channelModel.Account = accountModel
164
165 videoModel.VideoChannel = channelModel
166 }
167
162 private buildActor (row: SQLRow, prefix: string) { 168 private buildActor (row: SQLRow, prefix: string) {
163 const actorPrefix = `${prefix}.Actor` 169 const actorPrefix = `${prefix}.Actor`
164 const avatarPrefix = `${actorPrefix}.Avatar` 170 const avatarPrefix = `${actorPrefix}.Avatar`
diff --git a/server/models/video/sql/shared/video-tables.ts b/server/models/video/sql/shared/video-tables.ts
index fddf1210c..52929fa5e 100644
--- a/server/models/video/sql/shared/video-tables.ts
+++ b/server/models/video/sql/shared/video-tables.ts
@@ -10,6 +10,10 @@ export class VideoTables {
10 10
11 } 11 }
12 12
13 getChannelAttributesForUser () {
14 return [ 'id', 'accountId' ]
15 }
16
13 getChannelAttributes () { 17 getChannelAttributes () {
14 let attributeKeys = [ 18 let attributeKeys = [
15 'id', 19 'id',
@@ -29,6 +33,10 @@ export class VideoTables {
29 return attributeKeys 33 return attributeKeys
30 } 34 }
31 35
36 getUserAccountAttributes () {
37 return [ 'id', 'userId' ]
38 }
39
32 getAccountAttributes () { 40 getAccountAttributes () {
33 let attributeKeys = [ 'id', 'name', 'actorId' ] 41 let attributeKeys = [ 'id', 'name', 'actorId' ]
34 42
diff --git a/server/models/video/sql/video-model-get-query-builder.ts b/server/models/video/sql/video-model-get-query-builder.ts
index 4aab9ff1d..f56fdd474 100644
--- a/server/models/video/sql/video-model-get-query-builder.ts
+++ b/server/models/video/sql/video-model-get-query-builder.ts
@@ -11,10 +11,15 @@ import { VideoTables } from './shared/video-tables'
11 */ 11 */
12 12
13export type BuildVideoGetQueryOptions = { 13export type BuildVideoGetQueryOptions = {
14 id: number | string 14 id?: number | string
15 transaction?: Transaction 15 url?: string
16
17 type: 'api' | 'full-light' | 'account-blacklist-files' | 'all-files' | 'thumbnails' | 'thumbnails-blacklist' | 'id' | 'blacklist-rights'
18
16 userId?: number 19 userId?: number
17 forGetAPI?: boolean 20 transaction?: Transaction
21
22 logging?: boolean
18} 23}
19 24
20export class VideosModelGetQueryBuilder { 25export class VideosModelGetQueryBuilder {
@@ -32,11 +37,17 @@ export class VideosModelGetQueryBuilder {
32 this.videoModelBuilder = new VideoModelBuilder('get', new VideoTables('get')) 37 this.videoModelBuilder = new VideoModelBuilder('get', new VideoTables('get'))
33 } 38 }
34 39
35 async queryVideos (options: BuildVideoGetQueryOptions) { 40 async queryVideo (options: BuildVideoGetQueryOptions) {
36 const [ videoRows, webtorrentFilesRows, streamingPlaylistFilesRows ] = await Promise.all([ 41 const [ videoRows, webtorrentFilesRows, streamingPlaylistFilesRows ] = await Promise.all([
37 this.videoQueryBuilder.queryVideos(options), 42 this.videoQueryBuilder.queryVideos(options),
38 this.webtorrentFilesQueryBuilder.queryWebTorrentVideos(options), 43
39 this.streamingPlaylistFilesQueryBuilder.queryStreamingPlaylistVideos(options) 44 this.shouldQueryVideoFiles(options)
45 ? this.webtorrentFilesQueryBuilder.queryWebTorrentVideos(options)
46 : Promise.resolve(undefined),
47
48 this.shouldQueryVideoFiles(options)
49 ? this.streamingPlaylistFilesQueryBuilder.queryStreamingPlaylistVideos(options)
50 : Promise.resolve(undefined)
40 ]) 51 ])
41 52
42 const videos = this.videoModelBuilder.buildVideosFromRows(videoRows, webtorrentFilesRows, streamingPlaylistFilesRows) 53 const videos = this.videoModelBuilder.buildVideosFromRows(videoRows, webtorrentFilesRows, streamingPlaylistFilesRows)
@@ -48,6 +59,10 @@ export class VideosModelGetQueryBuilder {
48 if (videos.length === 0) return null 59 if (videos.length === 0) return null
49 return videos[0] 60 return videos[0]
50 } 61 }
62
63 private shouldQueryVideoFiles (options: BuildVideoGetQueryOptions) {
64 return [ 'api', 'full-light', 'account-blacklist-files', 'all-files' ].includes(options.type)
65 }
51} 66}
52 67
53export class VideosModelGetQuerySubBuilder extends AbstractVideosModelQueryBuilder { 68export class VideosModelGetQuerySubBuilder extends AbstractVideosModelQueryBuilder {
@@ -63,7 +78,7 @@ export class VideosModelGetQuerySubBuilder extends AbstractVideosModelQueryBuild
63 queryVideos (options: BuildVideoGetQueryOptions) { 78 queryVideos (options: BuildVideoGetQueryOptions) {
64 this.buildMainGetQuery(options) 79 this.buildMainGetQuery(options)
65 80
66 return this.runQuery(options.transaction) 81 return this.runQuery(options)
67 } 82 }
68 83
69 private buildMainGetQuery (options: BuildVideoGetQueryOptions) { 84 private buildMainGetQuery (options: BuildVideoGetQueryOptions) {
@@ -71,36 +86,91 @@ export class VideosModelGetQuerySubBuilder extends AbstractVideosModelQueryBuild
71 '"video".*': '' 86 '"video".*': ''
72 } 87 }
73 88
74 this.includeChannels() 89 if (this.shouldIncludeThumbnails(options)) {
75 this.includeAccounts() 90 this.includeThumbnails()
91 }
76 92
77 this.includeTags() 93 if (this.shouldIncludeBlacklisted(options)) {
94 this.includeBlacklisted()
95 }
78 96
79 this.includeThumbnails() 97 if (this.shouldIncludeAccount(options)) {
98 this.includeChannels()
99 this.includeAccounts()
100 }
80 101
81 this.includeBlacklisted() 102 if (this.shouldIncludeTags(options)) {
103 this.includeTags()
104 }
82 105
83 this.includeScheduleUpdate() 106 if (this.shouldIncludeScheduleUpdate(options)) {
107 this.includeScheduleUpdate()
108 }
84 109
85 this.includeLive() 110 if (this.shouldIncludeLive(options)) {
111 this.includeLive()
112 }
86 113
87 if (options.userId) { 114 if (options.userId && this.shouldIncludeUserHistory(options)) {
88 this.includeUserHistory(options.userId) 115 this.includeUserHistory(options.userId)
89 } 116 }
90 117
91 if (options.forGetAPI === true) { 118 if (this.shouldIncludeOwnerUser(options)) {
119 this.includeOwnerUser()
120 }
121
122 if (this.shouldIncludeTrackers(options)) {
92 this.includeTrackers() 123 this.includeTrackers()
93 } 124 }
94 125
95 this.whereId(options.id) 126 this.whereId(options)
96 127
97 this.query = this.buildQuery() 128 this.query = this.buildQuery(options)
98 } 129 }
99 130
100 private buildQuery () { 131 private buildQuery (options: BuildVideoGetQueryOptions) {
101 const order = 'ORDER BY "Tags"."name" ASC' 132 const order = this.shouldIncludeTags(options)
133 ? 'ORDER BY "Tags"."name" ASC'
134 : ''
135
102 const from = `SELECT * FROM "video" ${this.where} LIMIT 1` 136 const from = `SELECT * FROM "video" ${this.where} LIMIT 1`
103 137
104 return `${this.buildSelect()} FROM (${from}) AS "video" ${this.joins} ${order}` 138 return `${this.buildSelect()} FROM (${from}) AS "video" ${this.joins} ${order}`
105 } 139 }
140
141 private shouldIncludeTrackers (options: BuildVideoGetQueryOptions) {
142 return options.type === 'api'
143 }
144
145 private shouldIncludeLive (options: BuildVideoGetQueryOptions) {
146 return [ 'api', 'full-light' ].includes(options.type)
147 }
148
149 private shouldIncludeScheduleUpdate (options: BuildVideoGetQueryOptions) {
150 return [ 'api', 'full-light' ].includes(options.type)
151 }
152
153 private shouldIncludeTags (options: BuildVideoGetQueryOptions) {
154 return [ 'api', 'full-light' ].includes(options.type)
155 }
156
157 private shouldIncludeUserHistory (options: BuildVideoGetQueryOptions) {
158 return [ 'api', 'full-light' ].includes(options.type)
159 }
160
161 private shouldIncludeAccount (options: BuildVideoGetQueryOptions) {
162 return [ 'api', 'full-light', 'account-blacklist-files' ].includes(options.type)
163 }
164
165 private shouldIncludeBlacklisted (options: BuildVideoGetQueryOptions) {
166 return [ 'api', 'full-light', 'account-blacklist-files', 'thumbnails-blacklist', 'blacklist-rights' ].includes(options.type)
167 }
168
169 private shouldIncludeOwnerUser (options: BuildVideoGetQueryOptions) {
170 return options.type === 'blacklist-rights'
171 }
172
173 private shouldIncludeThumbnails (options: BuildVideoGetQueryOptions) {
174 return [ 'api', 'full-light', 'account-blacklist-files', 'thumbnails', 'thumbnails-blacklist' ].includes(options.type)
175 }
106} 176}
diff --git a/server/models/video/sql/videos-model-list-query-builder.ts b/server/models/video/sql/videos-model-list-query-builder.ts
index d3a9a9466..43040fc5e 100644
--- a/server/models/video/sql/videos-model-list-query-builder.ts
+++ b/server/models/video/sql/videos-model-list-query-builder.ts
@@ -27,7 +27,8 @@ export class VideosModelListQueryBuilder extends AbstractVideosModelQueryBuilder
27 this.buildInnerQuery(options) 27 this.buildInnerQuery(options)
28 this.buildListQueryFromIdsQuery(options) 28 this.buildListQueryFromIdsQuery(options)
29 29
30 return this.runQuery(undefined).then(rows => this.videoModelBuilder.buildVideosFromRows(rows)) 30 return this.runQuery()
31 .then(rows => this.videoModelBuilder.buildVideosFromRows(rows))
31 } 32 }
32 33
33 private buildInnerQuery (options: BuildVideosListQueryOptions) { 34 private buildInnerQuery (options: BuildVideosListQueryOptions) {
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 00fbb18f6..2d8b7b653 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -88,13 +88,12 @@ import {
88 MVideoFormattableDetails, 88 MVideoFormattableDetails,
89 MVideoForUser, 89 MVideoForUser,
90 MVideoFullLight, 90 MVideoFullLight,
91 MVideoIdThumbnail, 91 MVideoId,
92 MVideoImmutable, 92 MVideoImmutable,
93 MVideoThumbnail, 93 MVideoThumbnail,
94 MVideoThumbnailBlacklist, 94 MVideoThumbnailBlacklist,
95 MVideoWithAllFiles, 95 MVideoWithAllFiles,
96 MVideoWithFile, 96 MVideoWithFile
97 MVideoWithRights
98} from '../../types/models' 97} from '../../types/models'
99import { MThumbnail } from '../../types/models/video/thumbnail' 98import { MThumbnail } from '../../types/models/video/thumbnail'
100import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../types/models/video/video-file' 99import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../types/models/video/video-file'
@@ -1301,27 +1300,16 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1301 return VideoModel.count(options) 1300 return VideoModel.count(options)
1302 } 1301 }
1303 1302
1304 static load (id: number | string, t?: Transaction): Promise<MVideoThumbnail> { 1303 static load (id: number | string, transaction?: Transaction): Promise<MVideoThumbnail> {
1305 const where = buildWhereIdOrUUID(id) 1304 const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
1306 const options = {
1307 where,
1308 transaction: t
1309 }
1310 1305
1311 return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options) 1306 return queryBuilder.queryVideo({ id, transaction, type: 'thumbnails' })
1312 } 1307 }
1313 1308
1314 static loadWithBlacklist (id: number | string, t?: Transaction): Promise<MVideoThumbnailBlacklist> { 1309 static loadWithBlacklist (id: number | string, transaction?: Transaction): Promise<MVideoThumbnailBlacklist> {
1315 const where = buildWhereIdOrUUID(id) 1310 const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
1316 const options = {
1317 where,
1318 transaction: t
1319 }
1320 1311
1321 return VideoModel.scope([ 1312 return queryBuilder.queryVideo({ id, transaction, type: 'thumbnails-blacklist' })
1322 ScopeNames.WITH_THUMBNAILS,
1323 ScopeNames.WITH_BLACKLISTED
1324 ]).findOne(options)
1325 } 1313 }
1326 1314
1327 static loadImmutableAttributes (id: number | string, t?: Transaction): Promise<MVideoImmutable> { 1315 static loadImmutableAttributes (id: number | string, t?: Transaction): Promise<MVideoImmutable> {
@@ -1342,68 +1330,6 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1342 }) 1330 })
1343 } 1331 }
1344 1332
1345 static loadWithRights (id: number | string, t?: Transaction): Promise<MVideoWithRights> {
1346 const where = buildWhereIdOrUUID(id)
1347 const options = {
1348 where,
1349 transaction: t
1350 }
1351
1352 return VideoModel.scope([
1353 ScopeNames.WITH_BLACKLISTED,
1354 ScopeNames.WITH_USER_ID
1355 ]).findOne(options)
1356 }
1357
1358 static loadOnlyId (id: number | string, t?: Transaction): Promise<MVideoIdThumbnail> {
1359 const where = buildWhereIdOrUUID(id)
1360
1361 const options = {
1362 attributes: [ 'id' ],
1363 where,
1364 transaction: t
1365 }
1366
1367 return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
1368 }
1369
1370 static loadWithFiles (id: number | string, t?: Transaction, logging?: boolean): Promise<MVideoWithAllFiles> {
1371 const where = buildWhereIdOrUUID(id)
1372
1373 const query = {
1374 where,
1375 transaction: t,
1376 logging
1377 }
1378
1379 return VideoModel.scope([
1380 ScopeNames.WITH_WEBTORRENT_FILES,
1381 ScopeNames.WITH_STREAMING_PLAYLISTS,
1382 ScopeNames.WITH_THUMBNAILS
1383 ]).findOne(query)
1384 }
1385
1386 static loadByUUID (uuid: string): Promise<MVideoThumbnail> {
1387 const options = {
1388 where: {
1389 uuid
1390 }
1391 }
1392
1393 return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
1394 }
1395
1396 static loadByUrl (url: string, transaction?: Transaction): Promise<MVideoThumbnail> {
1397 const query: FindOptions = {
1398 where: {
1399 url
1400 },
1401 transaction
1402 }
1403
1404 return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(query)
1405 }
1406
1407 static loadByUrlImmutableAttributes (url: string, transaction?: Transaction): Promise<MVideoImmutable> { 1333 static loadByUrlImmutableAttributes (url: string, transaction?: Transaction): Promise<MVideoImmutable> {
1408 const fun = () => { 1334 const fun = () => {
1409 const query: FindOptions = { 1335 const query: FindOptions = {
@@ -1424,50 +1350,34 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1424 }) 1350 })
1425 } 1351 }
1426 1352
1427 static loadByUrlAndPopulateAccount (url: string, transaction?: Transaction): Promise<MVideoAccountLightBlacklistAllFiles> { 1353 static loadOnlyId (id: number | string, transaction?: Transaction): Promise<MVideoId> {
1428 const query: FindOptions = { 1354 const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
1429 where: {
1430 url
1431 },
1432 transaction
1433 }
1434 1355
1435 return VideoModel.scope([ 1356 return queryBuilder.queryVideo({ id, transaction, type: 'id' })
1436 ScopeNames.WITH_ACCOUNT_DETAILS,
1437 ScopeNames.WITH_WEBTORRENT_FILES,
1438 ScopeNames.WITH_STREAMING_PLAYLISTS,
1439 ScopeNames.WITH_THUMBNAILS,
1440 ScopeNames.WITH_BLACKLISTED
1441 ]).findOne(query)
1442 } 1357 }
1443 1358
1444 static loadAndPopulateAccountAndServerAndTags (id: number | string, t?: Transaction, userId?: number): Promise<MVideoFullLight> { 1359 static loadWithFiles (id: number | string, transaction?: Transaction, logging?: boolean): Promise<MVideoWithAllFiles> {
1445 const where = buildWhereIdOrUUID(id) 1360 const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
1446 1361
1447 const options = { 1362 return queryBuilder.queryVideo({ id, transaction, type: 'all-files', logging })
1448 order: [ [ 'Tags', 'name', 'ASC' ] ] as any, 1363 }
1449 where,
1450 transaction: t
1451 }
1452 1364
1453 const scopes: (string | ScopeOptions)[] = [ 1365 static loadByUrl (url: string, transaction?: Transaction): Promise<MVideoThumbnail> {
1454 ScopeNames.WITH_TAGS, 1366 const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
1455 ScopeNames.WITH_BLACKLISTED,
1456 ScopeNames.WITH_ACCOUNT_DETAILS,
1457 ScopeNames.WITH_SCHEDULED_UPDATE,
1458 ScopeNames.WITH_WEBTORRENT_FILES,
1459 ScopeNames.WITH_STREAMING_PLAYLISTS,
1460 ScopeNames.WITH_THUMBNAILS,
1461 ScopeNames.WITH_LIVE
1462 ]
1463 1367
1464 if (userId) { 1368 return queryBuilder.queryVideo({ url, transaction, type: 'thumbnails' })
1465 scopes.push({ method: [ ScopeNames.WITH_USER_HISTORY, userId ] }) 1369 }
1466 } 1370
1371 static loadByUrlAndPopulateAccount (url: string, transaction?: Transaction): Promise<MVideoAccountLightBlacklistAllFiles> {
1372 const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
1373
1374 return queryBuilder.queryVideo({ url, transaction, type: 'account-blacklist-files' })
1375 }
1376
1377 static loadAndPopulateAccountAndServerAndTags (id: number | string, t?: Transaction, userId?: number): Promise<MVideoFullLight> {
1378 const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
1467 1379
1468 return VideoModel 1380 return queryBuilder.queryVideo({ id, transaction: t, type: 'full-light', userId })
1469 .scope(scopes)
1470 .findOne(options)
1471 } 1381 }
1472 1382
1473 static loadForGetAPI (parameters: { 1383 static loadForGetAPI (parameters: {
@@ -1478,7 +1388,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1478 const { id, transaction, userId } = parameters 1388 const { id, transaction, userId } = parameters
1479 const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize) 1389 const queryBuilder = new VideosModelGetQueryBuilder(VideoModel.sequelize)
1480 1390
1481 return queryBuilder.queryVideos({ id, transaction, forGetAPI: true, userId }) 1391 return queryBuilder.queryVideo({ id, transaction, type: 'api', userId })
1482 } 1392 }
1483 1393
1484 static async getStats () { 1394 static async getStats () {