-import { Observable } from 'rxjs'
-import { catchError, map, switchMap } from 'rxjs/operators'
+import { SortMeta } from 'primeng/api'
+import { from, Observable } from 'rxjs'
+import { catchError, concatMap, map, switchMap, toArray } from 'rxjs/operators'
import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http'
import { Injectable } from '@angular/core'
-import { ComponentPaginationLight, RestExtractor, RestService, ServerService, UserService } from '@app/core'
+import { ComponentPaginationLight, RestExtractor, RestPagination, RestService, ServerService, UserService } from '@app/core'
import { objectToFormData } from '@app/helpers'
+import { AdvancedInputFilter } from '@app/shared/shared-forms'
import {
BooleanBothQuery,
FeedFormat,
UserVideoRateType,
UserVideoRateUpdate,
Video as VideoServerModel,
+ VideoChannel as VideoChannelServerModel,
VideoConstant,
VideoDetails as VideoDetailsServerModel,
VideoFileMetadata,
- VideoFilter,
+ VideoInclude,
VideoPrivacy,
VideoSortField,
VideoUpdate
import { Video } from './video.model'
export type CommonVideoParams = {
- videoPagination: ComponentPaginationLight
- sort: VideoSortField
- filter?: VideoFilter
+ videoPagination?: ComponentPaginationLight
+ sort: VideoSortField | SortMeta
+ include?: VideoInclude
+ isLocal?: boolean
categoryOneOf?: number[]
languageOneOf?: string[]
isLive?: boolean
skipCount?: boolean
+
// FIXME: remove?
nsfwPolicy?: NSFWPolicyType
nsfw?: BooleanBothQuery
@Injectable()
export class VideoService {
- static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos/'
+ static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos'
static BASE_FEEDS_URL = environment.apiUrl + '/feeds/videos.'
static BASE_SUBSCRIPTION_FEEDS_URL = environment.apiUrl + '/feeds/subscriptions.'
) {}
getVideoViewUrl (uuid: string) {
- return VideoService.BASE_VIDEO_URL + uuid + '/views'
+ return `${VideoService.BASE_VIDEO_URL}/${uuid}/views`
}
getUserWatchingVideoUrl (uuid: string) {
- return VideoService.BASE_VIDEO_URL + uuid + '/watching'
+ return `${VideoService.BASE_VIDEO_URL}/${uuid}/watching`
}
getVideo (options: { videoId: string }): Observable<VideoDetails> {
return this.serverService.getServerLocale()
.pipe(
switchMap(translations => {
- return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + options.videoId)
+ return this.authHttp.get<VideoDetailsServerModel>(`${VideoService.BASE_VIDEO_URL}/${options.videoId}`)
.pipe(map(videoHash => ({ videoHash, translations })))
}),
map(({ videoHash, translations }) => new VideoDetails(videoHash, translations)),
const data = objectToFormData(body)
- return this.authHttp.put(VideoService.BASE_VIDEO_URL + video.id, data)
+ return this.authHttp.put(`${VideoService.BASE_VIDEO_URL}/${video.id}`, data)
.pipe(
map(this.restExtractor.extractDataBool),
catchError(err => this.restExtractor.handleError(err))
}
uploadVideo (video: FormData) {
- const req = new HttpRequest('POST', VideoService.BASE_VIDEO_URL + 'upload', video, { reportProgress: true })
+ const req = new HttpRequest('POST', `${VideoService.BASE_VIDEO_URL}/upload`, video, { reportProgress: true })
return this.authHttp
.request<{ video: { id: number, uuid: string } }>(req)
.pipe(catchError(err => this.restExtractor.handleError(err)))
}
- getMyVideos (videoPagination: ComponentPaginationLight, sort: VideoSortField, search?: string): Observable<ResultList<Video>> {
- const pagination = this.restService.componentPaginationToRestPagination(videoPagination)
+ getMyVideos (options: {
+ videoPagination: ComponentPaginationLight
+ sort: VideoSortField
+ userChannels?: VideoChannelServerModel[]
+ search?: string
+ }): Observable<ResultList<Video>> {
+ const { videoPagination, sort, userChannels = [], search } = options
+
+ const pagination = this.restService.componentToRestPagination(videoPagination)
let params = new HttpParams()
params = this.restService.addRestGetParams(params, pagination, sort)
isLive: {
prefix: 'isLive:',
isBoolean: true
+ },
+ channelId: {
+ prefix: 'channel:',
+ handler: (name: string) => {
+ const channel = userChannels.find(c => c.name === name)
+
+ if (channel) return channel.id
+
+ return undefined
+ }
}
})
)
}
+ getAdminVideos (
+ options: CommonVideoParams & { pagination: RestPagination, search?: string }
+ ): Observable<ResultList<Video>> {
+ const { pagination, search } = options
+
+ let params = new HttpParams()
+ params = this.buildCommonVideosParams({ params, ...options })
+
+ params = params.set('start', pagination.start.toString())
+ .set('count', pagination.count.toString())
+
+ params = this.buildAdminParamsFromSearch(search, params)
+
+ return this.authHttp
+ .get<ResultList<Video>>(VideoService.BASE_VIDEO_URL, { params })
+ .pipe(
+ switchMap(res => this.extractVideos(res)),
+ catchError(err => this.restExtractor.handleError(err))
+ )
+ }
+
getVideos (parameters: CommonVideoParams): Observable<ResultList<Video>> {
let params = new HttpParams()
params = this.buildCommonVideosParams({ params, ...parameters })
return feeds
}
- getVideoFeedUrls (sort: VideoSortField, filter?: VideoFilter, categoryOneOf?: number[]) {
+ getVideoFeedUrls (sort: VideoSortField, isLocal: boolean, categoryOneOf?: number[]) {
let params = this.restService.addRestGetParams(new HttpParams(), undefined, sort)
- if (filter) params = params.set('filter', filter)
+ if (isLocal) params = params.set('isLocal', isLocal)
if (categoryOneOf) {
for (const c of categoryOneOf) {
)
}
- removeVideo (id: number) {
- return this.authHttp
- .delete(VideoService.BASE_VIDEO_URL + id)
- .pipe(
- map(this.restExtractor.extractDataBool),
- catchError(err => this.restExtractor.handleError(err))
- )
+ removeVideo (idArg: number | number[]) {
+ const ids = Array.isArray(idArg) ? idArg : [ idArg ]
+
+ return from(ids)
+ .pipe(
+ concatMap(id => this.authHttp.delete(`${VideoService.BASE_VIDEO_URL}/${id}`)),
+ toArray(),
+ catchError(err => this.restExtractor.handleError(err))
+ )
}
loadCompleteDescription (descriptionPath: string) {
}
private setVideoRate (id: number, rateType: UserVideoRateType) {
- const url = VideoService.BASE_VIDEO_URL + id + '/rate'
+ const url = `${VideoService.BASE_VIDEO_URL}/${id}/rate`
const body: UserVideoRateUpdate = {
rating: rateType
}
}
private buildCommonVideosParams (options: CommonVideoParams & { params: HttpParams }) {
- const { params, videoPagination, sort, filter, categoryOneOf, languageOneOf, skipCount, nsfwPolicy, isLive, nsfw } = options
+ const {
+ params,
+ videoPagination,
+ sort,
+ isLocal,
+ include,
+ categoryOneOf,
+ languageOneOf,
+ skipCount,
+ nsfwPolicy,
+ isLive,
+ nsfw
+ } = options
+
+ const pagination = videoPagination
+ ? this.restService.componentToRestPagination(videoPagination)
+ : undefined
- const pagination = this.restService.componentPaginationToRestPagination(videoPagination)
let newParams = this.restService.addRestGetParams(params, pagination, sort)
- if (filter) newParams = newParams.set('filter', filter)
if (skipCount) newParams = newParams.set('skipCount', skipCount + '')
+ if (isLocal) newParams = newParams.set('isLocal', isLocal)
+ if (include) newParams = newParams.set('include', include)
if (isLive) newParams = newParams.set('isLive', isLive)
if (nsfw) newParams = newParams.set('nsfw', nsfw)
if (nsfwPolicy) newParams = newParams.set('nsfw', this.nsfwPolicyToParam(nsfwPolicy))
return newParams
}
+
+ buildAdminInputFilter (): AdvancedInputFilter[] {
+ return [
+ {
+ title: $localize`Videos scope`,
+ children: [
+ {
+ queryParams: { search: 'isLocal:false' },
+ label: $localize`Remote videos`
+ },
+ {
+ queryParams: { search: 'isLocal:true' },
+ label: $localize`Local videos`
+ }
+ ]
+ },
+
+ {
+ title: $localize`Include/Exclude`,
+ children: [
+ {
+ queryParams: { search: 'excludeMuted' },
+ label: $localize`Exclude muted accounts`
+ }
+ ]
+ }
+ ]
+ }
+
+ private buildAdminParamsFromSearch (search: string, params: HttpParams) {
+ let include = VideoInclude.BLACKLISTED |
+ VideoInclude.BLOCKED_OWNER |
+ VideoInclude.HIDDEN_PRIVACY |
+ VideoInclude.NOT_PUBLISHED_STATE |
+ VideoInclude.FILES
+
+ if (!search) return this.restService.addObjectParams(params, { include })
+
+ const filters = this.restService.parseQueryStringFilter(search, {
+ isLocal: {
+ prefix: 'isLocal:',
+ isBoolean: true
+ },
+ excludeMuted: {
+ prefix: 'excludeMuted',
+ handler: () => true
+ }
+ })
+
+ if (filters.excludeMuted) {
+ include &= ~VideoInclude.BLOCKED_OWNER
+
+ filters.excludeMuted = undefined
+ }
+
+ return this.restService.addObjectParams(params, { ...filters, include })
+ }
}