1 import * as debug from 'debug'
2 import { Observable, Subject } from 'rxjs'
3 import { filter, first, map } from 'rxjs/operators'
4 import { Injectable } from '@angular/core'
5 import { buildBulkObservable } from '@app/helpers'
6 import { ResultList } from '@shared/models/common'
7 import { Video, VideoChannel } from '../shared-main'
8 import { VideoPlaylist } from '../shared-video-playlist'
9 import { SearchService } from './search.service'
10 import { AdvancedSearch } from './advanced-search.model'
12 const debugLogger = debug('peertube:search:FindInBulkService')
14 type BulkObservables <P extends number | string, R> = {
16 result: Observable<{ params: P[], response: R }>
20 export class FindInBulkService {
22 private advancedSearchForBulk: AdvancedSearch
24 private getVideoInBulk: BulkObservables<string, ResultList<Video>>
25 private getChannelInBulk: BulkObservables<string, ResultList<VideoChannel>>
26 private getPlaylistInBulk: BulkObservables<string, ResultList<VideoPlaylist>>
29 private searchService: SearchService
31 this.getVideoInBulk = this.buildBulkObservableObject(this.getVideosInBulk.bind(this))
32 this.getChannelInBulk = this.buildBulkObservableObject(this.getChannelsInBulk.bind(this))
33 this.getPlaylistInBulk = this.buildBulkObservableObject(this.getPlaylistsInBulk.bind(this))
35 this.advancedSearchForBulk = new AdvancedSearch({ searchTarget: 'local' })
38 getVideo (uuid: string): Observable<Video> {
39 debugLogger('Schedule video fetch for uuid %s.', uuid)
42 observableObject: this.getVideoInBulk,
43 finder: v => v.uuid === uuid,
48 getChannel (handle: string): Observable<VideoChannel> {
49 debugLogger('Schedule channel fetch for handle %s.', handle)
52 observableObject: this.getChannelInBulk,
53 finder: c => c.nameWithHost === handle || c.nameWithHostForced === handle,
58 getPlaylist (uuid: string): Observable<VideoPlaylist> {
59 debugLogger('Schedule playlist fetch for uuid %s.', uuid)
62 observableObject: this.getPlaylistInBulk,
63 finder: p => p.uuid === uuid,
68 private getData <P extends number | string, R> (options: {
69 observableObject: BulkObservables<P, ResultList<R>>
71 finder: (d: R) => boolean
73 const { observableObject, param, finder } = options
75 return new Observable<R>(obs => {
76 observableObject.result
78 filter(result => result.params.includes(param)),
80 map(result => result.response.data),
81 map(data => data.find(finder))
86 obs.error(new Error($localize`Element ${param} not found`))
94 error: err => obs.error(err)
97 observableObject.notifier.next(param)
101 private getVideosInBulk (uuids: string[]) {
102 debugLogger('Fetching videos %s.', uuids.join(', '))
104 return this.searchService.searchVideos({
106 componentPagination: { itemsPerPage: uuids.length, currentPage: 1 },
107 advancedSearch: this.advancedSearchForBulk
111 private getChannelsInBulk (handles: string[]) {
112 debugLogger('Fetching channels %s.', handles.join(', '))
114 return this.searchService.searchVideoChannels({
116 componentPagination: { itemsPerPage: handles.length, currentPage: 1 },
117 advancedSearch: this.advancedSearchForBulk
121 private getPlaylistsInBulk (uuids: string[]) {
122 debugLogger('Fetching playlists %s.', uuids.join(', '))
124 return this.searchService.searchVideoPlaylists({
126 componentPagination: { itemsPerPage: uuids.length, currentPage: 1 },
127 advancedSearch: this.advancedSearchForBulk
131 private buildBulkObservableObject <P extends number | string, R> (bulkGet: (params: P[]) => Observable<R>) {
132 const notifier = new Subject<P>()
137 result: buildBulkObservable({
140 notifierObservable: notifier.asObservable()