import * as debug from 'debug' import { Observable, Subject } from 'rxjs' import { filter, first, map } from 'rxjs/operators' import { Injectable } from '@angular/core' import { buildBulkObservable } from '@app/helpers' import { ResultList } from '@shared/models/common' import { Video, VideoChannel } from '../shared-main' import { VideoPlaylist } from '../shared-video-playlist' import { SearchService } from './search.service' import { AdvancedSearch } from './advanced-search.model' const debugLogger = debug('peertube:search:FindInBulkService') type BulkObservables

= { notifier: Subject

result: Observable<{ params: P[], response: R }> } @Injectable() export class FindInBulkService { private advancedSearchForBulk: AdvancedSearch private getVideoInBulk: BulkObservables> private getChannelInBulk: BulkObservables> private getPlaylistInBulk: BulkObservables> constructor ( private searchService: SearchService ) { this.getVideoInBulk = this.buildBulkObservableObject(this.getVideosInBulk.bind(this)) this.getChannelInBulk = this.buildBulkObservableObject(this.getChannelsInBulk.bind(this)) this.getPlaylistInBulk = this.buildBulkObservableObject(this.getPlaylistsInBulk.bind(this)) this.advancedSearchForBulk = new AdvancedSearch({ searchTarget: 'local' }) } getVideo (uuid: string): Observable

(options: { observableObject: BulkObservables> param: P finder: (d: R) => boolean }) { const { observableObject, param, finder } = options return new Observable(obs => { observableObject.result .pipe( filter(result => result.params.includes(param)), first(), map(result => result.response.data), map(data => data.find(finder)) ) .subscribe({ next: result => { if (!result) { obs.error(new Error($localize`Element ${param} not found`)) return } obs.next(result) obs.complete() }, error: err => obs.error(err) }) observableObject.notifier.next(param) }) } private getVideosInBulk (uuids: string[]) { debugLogger('Fetching videos %s.', uuids.join(', ')) return this.searchService.searchVideos({ uuids, componentPagination: { itemsPerPage: uuids.length, currentPage: 1 }, advancedSearch: this.advancedSearchForBulk }) } private getChannelsInBulk (handles: string[]) { debugLogger('Fetching channels %s.', handles.join(', ')) return this.searchService.searchVideoChannels({ handles, componentPagination: { itemsPerPage: handles.length, currentPage: 1 }, advancedSearch: this.advancedSearchForBulk }) } private getPlaylistsInBulk (uuids: string[]) { debugLogger('Fetching playlists %s.', uuids.join(', ')) return this.searchService.searchVideoPlaylists({ uuids, componentPagination: { itemsPerPage: uuids.length, currentPage: 1 }, advancedSearch: this.advancedSearchForBulk }) } private buildBulkObservableObject

(bulkGet: (params: P[]) => Observable) { const notifier = new Subject

() return { notifier, result: buildBulkObservable({ time: 500, bulkGet, notifierObservable: notifier.asObservable() }) } } }