X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fmodels%2Fvideo%2Fsql%2Fvideo-model-get-query-builder.ts;h=a65c96097cae77741f21d7728f4677548eca8d41;hb=5cad2ca9db9b9d138f8a33058d10b94a9fd50c69;hp=0a3723e632aa4a68eb7f134803e3244634c761c3;hpb=d9bf974f5df787bbeaab5b04949ca91a2b3ca2a3;p=github%2FChocobozzz%2FPeerTube.git 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 0a3723e63..a65c96097 100644 --- a/server/models/video/sql/video-model-get-query-builder.ts +++ b/server/models/video/sql/video-model-get-query-builder.ts @@ -1,86 +1,178 @@ import { Sequelize, Transaction } from 'sequelize' -import validator from 'validator' -import { AbstractVideosModelQueryBuilder } from './shared/abstract-videos-model-query-builder' +import { AbstractVideoQueryBuilder } from './shared/abstract-video-query-builder' +import { VideoFileQueryBuilder } from './shared/video-file-query-builder' +import { VideoModelBuilder } from './shared/video-model-builder' +import { VideoTableAttributes } from './shared/video-table-attributes' + +/** + * + * Build a GET SQL query, fetch rows and create the video model + * + */ + +export type GetType = + 'api' | + 'full-light' | + 'account-blacklist-files' | + 'all-files' | + 'thumbnails' | + 'thumbnails-blacklist' | + 'id' | + 'blacklist-rights' export type BuildVideoGetQueryOptions = { - id: number | string - transaction?: Transaction + id?: number | string + url?: string + + type: GetType + userId?: number - forGetAPI?: boolean + transaction?: Transaction + + logging?: boolean } -export class VideosModelGetQueryBuilder extends AbstractVideosModelQueryBuilder { - protected attributes: { [key: string]: string } - protected joins: string[] = [] - protected where: string +export class VideoModelGetQueryBuilder { + videoQueryBuilder: VideosModelGetQuerySubBuilder + webtorrentFilesQueryBuilder: VideoFileQueryBuilder + streamingPlaylistFilesQueryBuilder: VideoFileQueryBuilder + + private readonly videoModelBuilder: VideoModelBuilder + + private static readonly videoFilesInclude = new Set([ 'api', 'full-light', 'account-blacklist-files', 'all-files' ]) constructor (protected readonly sequelize: Sequelize) { - super('get') + this.videoQueryBuilder = new VideosModelGetQuerySubBuilder(sequelize) + this.webtorrentFilesQueryBuilder = new VideoFileQueryBuilder(sequelize) + this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize) + + this.videoModelBuilder = new VideoModelBuilder('get', new VideoTableAttributes('get')) } - queryVideos (options: BuildVideoGetQueryOptions) { - this.buildGetQuery(options) + async queryVideo (options: BuildVideoGetQueryOptions) { + const [ videoRows, webtorrentFilesRows, streamingPlaylistFilesRows ] = await Promise.all([ + this.videoQueryBuilder.queryVideos(options), - return this.runQuery(options.transaction, true).then(rows => { - const videos = this.videoModelBuilder.buildVideosFromRows(rows) + VideoModelGetQueryBuilder.videoFilesInclude.has(options.type) + ? this.webtorrentFilesQueryBuilder.queryWebTorrentVideos(options) + : Promise.resolve(undefined), - if (videos.length > 1) { - throw new Error('Video results is more than ') - } + VideoModelGetQueryBuilder.videoFilesInclude.has(options.type) + ? this.streamingPlaylistFilesQueryBuilder.queryStreamingPlaylistVideos(options) + : Promise.resolve(undefined) + ]) - if (videos.length === 0) return null - return videos[0] + const videos = this.videoModelBuilder.buildVideosFromRows({ + rows: videoRows, + rowsWebTorrentFiles: webtorrentFilesRows, + rowsStreamingPlaylist: streamingPlaylistFilesRows }) + + if (videos.length > 1) { + throw new Error('Video results is more than 1') + } + + if (videos.length === 0) return null + + return videos[0] } +} + +export class VideosModelGetQuerySubBuilder extends AbstractVideoQueryBuilder { + protected attributes: { [key: string]: string } - private buildGetQuery (options: BuildVideoGetQueryOptions) { + protected webtorrentFilesQuery: string + protected streamingPlaylistFilesQuery: string + + private static readonly trackersInclude = new Set([ 'api' ]) + private static readonly liveInclude = new Set([ 'api', 'full-light' ]) + private static readonly scheduleUpdateInclude = new Set([ 'api', 'full-light' ]) + private static readonly tagsInclude = new Set([ 'api', 'full-light' ]) + private static readonly userHistoryInclude = new Set([ 'api', 'full-light' ]) + private static readonly accountInclude = new Set([ 'api', 'full-light', 'account-blacklist-files' ]) + private static readonly ownerUserInclude = new Set([ 'blacklist-rights' ]) + + private static readonly blacklistedInclude = new Set([ + 'api', + 'full-light', + 'account-blacklist-files', + 'thumbnails-blacklist', + 'blacklist-rights' + ]) + + private static readonly thumbnailsInclude = new Set([ + 'api', + 'full-light', + 'account-blacklist-files', + 'all-files', + 'thumbnails', + 'thumbnails-blacklist' + ]) + + constructor (protected readonly sequelize: Sequelize) { + super('get') + } + + queryVideos (options: BuildVideoGetQueryOptions) { + this.buildMainGetQuery(options) + + return this.runQuery(options) + } + + private buildMainGetQuery (options: BuildVideoGetQueryOptions) { this.attributes = { '"video".*': '' } - this.includeChannels() - this.includeAccounts() - - this.includeTags() + if (VideosModelGetQuerySubBuilder.thumbnailsInclude.has(options.type)) { + this.includeThumbnails() + } - this.includeThumbnails() + if (VideosModelGetQuerySubBuilder.blacklistedInclude.has(options.type)) { + this.includeBlacklisted() + } - this.includeFiles() + if (VideosModelGetQuerySubBuilder.accountInclude.has(options.type)) { + this.includeChannels() + this.includeAccounts() + } - this.includeBlacklisted() + if (VideosModelGetQuerySubBuilder.tagsInclude.has(options.type)) { + this.includeTags() + } - this.includeScheduleUpdate() + if (VideosModelGetQuerySubBuilder.scheduleUpdateInclude.has(options.type)) { + this.includeScheduleUpdate() + } - this.includeLive() + if (VideosModelGetQuerySubBuilder.liveInclude.has(options.type)) { + this.includeLive() + } - if (options.userId) { + if (options.userId && VideosModelGetQuerySubBuilder.userHistoryInclude.has(options.type)) { this.includeUserHistory(options.userId) } - if (options.forGetAPI === true) { - this.includeTrackers() - this.includeRedundancies() + if (VideosModelGetQuerySubBuilder.ownerUserInclude.has(options.type)) { + this.includeOwnerUser() } - this.whereId(options.id) + if (VideosModelGetQuerySubBuilder.trackersInclude.has(options.type)) { + this.includeTrackers() + } - const select = this.buildSelect() - const order = this.buildOrder() + this.whereId(options) - this.query = `${select} FROM "video" ${this.joins.join(' ')} ${this.where} ${order}` + this.query = this.buildQuery(options) } - private whereId (id: string | number) { - if (validator.isInt('' + id)) { - this.where = 'WHERE "video".id = :videoId' - } else { - this.where = 'WHERE uuid = :videoId' - } + private buildQuery (options: BuildVideoGetQueryOptions) { + const order = VideosModelGetQuerySubBuilder.tagsInclude.has(options.type) + ? 'ORDER BY "Tags"."name" ASC' + : '' - this.replacements.videoId = id - } + const from = `SELECT * FROM "video" ${this.where} LIMIT 1` - private buildOrder () { - return 'ORDER BY "Tags"."name" ASC' + return `${this.buildSelect()} FROM (${from}) AS "video" ${this.joins} ${order}` } }