Add host to common video filters
This commit is contained in:
parent
e433a74bb6
commit
94a7879d7d
|
@ -210,6 +210,8 @@ export class CustomMarkupService {
|
|||
accountHandle: data.accountHandle || undefined,
|
||||
channelHandle: data.channelHandle || undefined,
|
||||
|
||||
host: data.host || undefined,
|
||||
|
||||
isLive: this.buildBoolean(data.isLive),
|
||||
|
||||
isLocal: this.buildBoolean(data.onlyLocal) ? true : undefined
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import { finalize, map } from 'rxjs/operators'
|
||||
import { NgFor, NgStyle } from '@angular/common'
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
|
||||
import { AuthService, Notifier } from '@app/core'
|
||||
import { Video } from '@app/shared/shared-main/video/video.model'
|
||||
import { CommonVideoParams, VideoService } from '@app/shared/shared-main/video/video.service'
|
||||
import { objectKeysTyped } from '@peertube/peertube-core-utils'
|
||||
import { ResultList, VideoSortField } from '@peertube/peertube-models'
|
||||
import { CustomMarkupComponent } from './shared'
|
||||
import { Observable } from 'rxjs'
|
||||
import { finalize, map } from 'rxjs/operators'
|
||||
import { MiniatureDisplayOptions, VideoMiniatureComponent } from '../../shared-video-miniature/video-miniature.component'
|
||||
import { NgStyle, NgFor } from '@angular/common'
|
||||
import { Video } from '@app/shared/shared-main/video/video.model'
|
||||
import { VideoService } from '@app/shared/shared-main/video/video.service'
|
||||
import { CustomMarkupComponent } from './shared'
|
||||
|
||||
/*
|
||||
* Markup component list videos depending on criteria
|
||||
|
@ -33,6 +33,7 @@ export class VideosListMarkupComponent implements CustomMarkupComponent, OnInit
|
|||
@Input() maxRows: number
|
||||
@Input() channelHandle: string
|
||||
@Input() accountHandle: string
|
||||
@Input() host: string
|
||||
|
||||
@Output() loaded = new EventEmitter<boolean>()
|
||||
|
||||
|
@ -90,26 +91,37 @@ export class VideosListMarkupComponent implements CustomMarkupComponent, OnInit
|
|||
}
|
||||
|
||||
getVideosObservable () {
|
||||
const options = {
|
||||
const options: CommonVideoParams = {
|
||||
videoPagination: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: this.count
|
||||
},
|
||||
categoryOneOf: this.categoryOneOf,
|
||||
languageOneOf: this.languageOneOf,
|
||||
host: this.host,
|
||||
isLocal: this.isLocal,
|
||||
isLive: this.isLive,
|
||||
sort: this.sort as VideoSortField,
|
||||
account: { nameWithHost: this.accountHandle },
|
||||
videoChannel: { nameWithHost: this.channelHandle },
|
||||
skipCount: true
|
||||
}
|
||||
|
||||
let obs: Observable<ResultList<Video>>
|
||||
|
||||
if (this.channelHandle) obs = this.videoService.getVideoChannelVideos(options)
|
||||
else if (this.accountHandle) obs = this.videoService.getAccountVideos(options)
|
||||
else obs = this.videoService.getVideos(options)
|
||||
if (this.channelHandle) {
|
||||
obs = this.videoService.getVideoChannelVideos({
|
||||
...options,
|
||||
|
||||
videoChannel: { nameWithHost: this.channelHandle }
|
||||
})
|
||||
} else if (this.accountHandle) {
|
||||
obs = this.videoService.getAccountVideos({
|
||||
...options,
|
||||
|
||||
account: { nameWithHost: this.accountHandle }
|
||||
})
|
||||
} else {
|
||||
obs = this.videoService.getVideos(options)
|
||||
}
|
||||
|
||||
return obs.pipe(map(({ data }) => data))
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ export type CommonVideoParams = {
|
|||
isLive?: boolean
|
||||
skipCount?: boolean
|
||||
nsfw?: BooleanBothQuery
|
||||
host?: string
|
||||
search?: string
|
||||
}
|
||||
|
||||
|
@ -548,6 +549,7 @@ export class VideoService {
|
|||
isLive,
|
||||
nsfw,
|
||||
search,
|
||||
host,
|
||||
|
||||
...otherOptions
|
||||
} = options
|
||||
|
@ -568,6 +570,7 @@ export class VideoService {
|
|||
if (categoryOneOf !== undefined) newParams = this.restService.addArrayParams(newParams, 'categoryOneOf', categoryOneOf)
|
||||
if (privacyOneOf !== undefined) newParams = this.restService.addArrayParams(newParams, 'privacyOneOf', privacyOneOf)
|
||||
if (search) newParams = newParams.set('search', search)
|
||||
if (host) newParams = newParams.set('host', host)
|
||||
|
||||
newParams = this.restService.addObjectParams(newParams, otherOptions)
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@ export type VideosListMarkupData = {
|
|||
channelHandle?: string
|
||||
accountHandle?: string
|
||||
|
||||
host?: string
|
||||
|
||||
isLive?: string // number
|
||||
|
||||
onlyLocal?: StringBoolean
|
||||
|
|
|
@ -34,6 +34,8 @@ export interface VideosCommonQuery {
|
|||
|
||||
excludeAlreadyWatched?: boolean
|
||||
|
||||
host?: string
|
||||
|
||||
// Only available with special user right
|
||||
autoTagOneOf?: string[]
|
||||
privacyOneOf?: VideoPrivacyType[]
|
||||
|
|
|
@ -615,13 +615,15 @@ export class VideosCommand extends AbstractCommand {
|
|||
'categoryOneOf',
|
||||
'licenceOneOf',
|
||||
'languageOneOf',
|
||||
'host',
|
||||
'privacyOneOf',
|
||||
'tagsOneOf',
|
||||
'tagsAllOf',
|
||||
'isLocal',
|
||||
'include',
|
||||
'skipCount',
|
||||
'autoTagOneOf'
|
||||
'autoTagOneOf',
|
||||
'search'
|
||||
])
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||
|
||||
import { expect } from 'chai'
|
||||
import { pick } from '@peertube/peertube-core-utils'
|
||||
import {
|
||||
HttpStatusCode,
|
||||
|
@ -11,7 +10,8 @@ import {
|
|||
VideoInclude,
|
||||
VideoIncludeType,
|
||||
VideoPrivacy,
|
||||
VideoPrivacyType
|
||||
VideoPrivacyType,
|
||||
VideosCommonQuery
|
||||
} from '@peertube/peertube-models'
|
||||
import {
|
||||
cleanupTests,
|
||||
|
@ -24,6 +24,7 @@ import {
|
|||
setDefaultVideoChannel,
|
||||
waitJobs
|
||||
} from '@peertube/peertube-server-commands'
|
||||
import { expect } from 'chai'
|
||||
|
||||
describe('Test videos filter', function () {
|
||||
let servers: PeerTubeServer[]
|
||||
|
@ -89,17 +90,11 @@ describe('Test videos filter', function () {
|
|||
async function listVideos (options: {
|
||||
server: PeerTubeServer
|
||||
path: string
|
||||
isLocal?: boolean
|
||||
hasWebVideoFiles?: boolean
|
||||
hasHLSFiles?: boolean
|
||||
include?: VideoIncludeType
|
||||
privacyOneOf?: VideoPrivacyType[]
|
||||
category?: number
|
||||
tagsAllOf?: string[]
|
||||
|
||||
token?: string
|
||||
expectedStatus?: HttpStatusCodeType
|
||||
excludeAlreadyWatched?: boolean
|
||||
}) {
|
||||
} & VideosCommonQuery) {
|
||||
const res = await makeGetRequest({
|
||||
url: options.server.url,
|
||||
path: options.path,
|
||||
|
@ -108,12 +103,15 @@ describe('Test videos filter', function () {
|
|||
...pick(options, [
|
||||
'isLocal',
|
||||
'include',
|
||||
'category',
|
||||
'tagsAllOf',
|
||||
'hasWebVideoFiles',
|
||||
'hasHLSFiles',
|
||||
'tagsAllOf',
|
||||
'categoryOneOf',
|
||||
'languageOneOf',
|
||||
'privacyOneOf',
|
||||
'excludeAlreadyWatched'
|
||||
'excludeAlreadyWatched',
|
||||
'host',
|
||||
'search'
|
||||
]),
|
||||
|
||||
sort: 'createdAt'
|
||||
|
@ -399,6 +397,51 @@ describe('Test videos filter', function () {
|
|||
}
|
||||
})
|
||||
|
||||
it('Should filter by language', async function () {
|
||||
await servers[0].videos.upload({ attributes: { name: 'english', language: 'en' } })
|
||||
await servers[0].videos.upload({ attributes: { name: 'french', language: 'fr' } })
|
||||
|
||||
for (const path of paths) {
|
||||
{
|
||||
const videos = await listVideos({ server: servers[0], path, languageOneOf: [ 'fr', 'en' ] })
|
||||
expect(videos).to.have.lengthOf(2)
|
||||
expect(videos.map(v => v.name)).to.have.members([ 'english', 'french' ])
|
||||
}
|
||||
|
||||
{
|
||||
const videos = await listVideos({ server: servers[0], path, languageOneOf: [ 'ca', 'es' ] })
|
||||
expect(videos).to.have.lengthOf(0)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
it('Should filter by host', async function () {
|
||||
await servers[0].videos.upload({ attributes: { name: 'filter host 1' } })
|
||||
await servers[1].videos.upload({ attributes: { name: 'filter host 2' } })
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
const getVideos = (videos: Video[]) => videos.filter(v => v.name.includes('filter host'))
|
||||
|
||||
{
|
||||
const { data } = await servers[0].videos.list({ search: 'filter host' })
|
||||
expect(getVideos(data)).to.have.lengthOf(2)
|
||||
}
|
||||
|
||||
{
|
||||
const { data } = await servers[0].videos.list({ search: 'filter host', host: servers[0].host })
|
||||
const videos = getVideos(data)
|
||||
|
||||
expect(videos).to.have.lengthOf(1)
|
||||
expect(videos.map(v => v.name)).to.have.members([ 'filter host 1' ])
|
||||
}
|
||||
|
||||
{
|
||||
const { data } = await servers[0].videos.list({ host: 'example.com' })
|
||||
expect(data).to.have.lengthOf(0)
|
||||
}
|
||||
})
|
||||
|
||||
it('Should filter by HLS or Web Video files', async function () {
|
||||
this.timeout(360000)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ function pickCommonVideoQuery (query: VideosCommonQueryAfterSanitize) {
|
|||
'categoryOneOf',
|
||||
'licenceOneOf',
|
||||
'languageOneOf',
|
||||
'host',
|
||||
'privacyOneOf',
|
||||
'tagsOneOf',
|
||||
'tagsAllOf',
|
||||
|
|
|
@ -10,10 +10,6 @@ const videosSearchValidator = [
|
|||
.optional()
|
||||
.not().isEmpty(),
|
||||
|
||||
query('host')
|
||||
.optional()
|
||||
.custom(isHostValid),
|
||||
|
||||
query('startDate')
|
||||
.optional()
|
||||
.custom(isDateValid).withMessage('Should have a start date that conforms to ISO 8601'),
|
||||
|
|
|
@ -56,6 +56,7 @@ import {
|
|||
} from '../shared/index.js'
|
||||
import { addDurationToVideoFileIfNeeded, commonVideoFileChecks, isVideoFileAccepted } from './shared/index.js'
|
||||
import { VideoLoadType } from '@server/lib/model-loaders/video.js'
|
||||
import { isHostValid } from '@server/helpers/custom-validators/servers.js'
|
||||
|
||||
export const videosAddLegacyValidator = getCommonVideoEditAttributes().concat([
|
||||
body('videofile')
|
||||
|
@ -491,6 +492,9 @@ export const commonVideosFiltersValidator = [
|
|||
.optional()
|
||||
.customSanitizer(arrayify)
|
||||
.custom(isStringArray).withMessage('Should have a valid autoTagOneOf array'),
|
||||
query('host')
|
||||
.optional()
|
||||
.custom(isHostValid),
|
||||
|
||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
if (areValidationErrors(req, res)) return
|
||||
|
|
|
@ -1141,6 +1141,8 @@ export class VideoModel extends SequelizeModel<VideoModel> {
|
|||
tagsAllOf?: string[]
|
||||
privacyOneOf?: VideoPrivacyType[]
|
||||
|
||||
host?: string
|
||||
|
||||
accountId?: number
|
||||
videoChannelId?: number
|
||||
|
||||
|
@ -1184,6 +1186,7 @@ export class VideoModel extends SequelizeModel<VideoModel> {
|
|||
'categoryOneOf',
|
||||
'licenceOneOf',
|
||||
'languageOneOf',
|
||||
'host',
|
||||
'autoTagOneOf',
|
||||
'tagsOneOf',
|
||||
'tagsAllOf',
|
||||
|
|
|
@ -794,6 +794,7 @@ paths:
|
|||
- $ref: '#/components/parameters/languageOneOf'
|
||||
- $ref: '#/components/parameters/autoTagOneOfVideo'
|
||||
- $ref: '#/components/parameters/nsfw'
|
||||
- $ref: '#/components/parameters/host'
|
||||
- $ref: '#/components/parameters/isLocal'
|
||||
- $ref: '#/components/parameters/include'
|
||||
- $ref: '#/components/parameters/privacyOneOf'
|
||||
|
@ -2256,6 +2257,7 @@ paths:
|
|||
- $ref: '#/components/parameters/tagsAllOf'
|
||||
- $ref: '#/components/parameters/licenceOneOf'
|
||||
- $ref: '#/components/parameters/languageOneOf'
|
||||
- $ref: '#/components/parameters/host'
|
||||
- $ref: '#/components/parameters/autoTagOneOfVideo'
|
||||
- $ref: '#/components/parameters/nsfw'
|
||||
- $ref: '#/components/parameters/isLocal'
|
||||
|
@ -2803,6 +2805,7 @@ paths:
|
|||
- $ref: '#/components/parameters/tagsAllOf'
|
||||
- $ref: '#/components/parameters/licenceOneOf'
|
||||
- $ref: '#/components/parameters/languageOneOf'
|
||||
- $ref: '#/components/parameters/host'
|
||||
- $ref: '#/components/parameters/autoTagOneOfVideo'
|
||||
- $ref: '#/components/parameters/nsfw'
|
||||
- $ref: '#/components/parameters/isLocal'
|
||||
|
@ -4497,6 +4500,7 @@ paths:
|
|||
- $ref: '#/components/parameters/tagsAllOf'
|
||||
- $ref: '#/components/parameters/licenceOneOf'
|
||||
- $ref: '#/components/parameters/languageOneOf'
|
||||
- $ref: '#/components/parameters/host'
|
||||
- $ref: '#/components/parameters/autoTagOneOfVideo'
|
||||
- $ref: '#/components/parameters/nsfw'
|
||||
- $ref: '#/components/parameters/isLocal'
|
||||
|
|
Loading…
Reference in New Issue