]>
Commit | Line | Data |
---|---|---|
3da38d6e | 1 | import * as debug from 'debug' |
1378c0d3 | 2 | import { Observable, Subject } from 'rxjs' |
2cc276f9 | 3 | import { filter, first, map } from 'rxjs/operators' |
afb7d2d5 | 4 | import { Injectable } from '@angular/core' |
3da38d6e C |
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' | |
8d9c10bc | 10 | import { AdvancedSearch } from './advanced-search.model' |
3da38d6e C |
11 | |
12 | const logger = debug('peertube:search:FindInBulkService') | |
13 | ||
14 | type BulkObservables <P extends number | string, R> = { | |
15 | notifier: Subject<P> | |
2cc276f9 | 16 | result: Observable<{ params: P[], response: R }> |
3da38d6e C |
17 | } |
18 | ||
19 | @Injectable() | |
20 | export class FindInBulkService { | |
21 | ||
8d9c10bc C |
22 | private advancedSearchForBulk: AdvancedSearch |
23 | ||
3da38d6e C |
24 | private getVideoInBulk: BulkObservables<string, ResultList<Video>> |
25 | private getChannelInBulk: BulkObservables<string, ResultList<VideoChannel>> | |
26 | private getPlaylistInBulk: BulkObservables<string, ResultList<VideoPlaylist>> | |
27 | ||
28 | constructor ( | |
afb7d2d5 | 29 | private searchService: SearchService |
3da38d6e C |
30 | ) { |
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)) | |
8d9c10bc C |
34 | |
35 | this.advancedSearchForBulk = new AdvancedSearch({ searchTarget: 'local' }) | |
3da38d6e C |
36 | } |
37 | ||
38 | getVideo (uuid: string): Observable<Video> { | |
39 | logger('Schedule video fetch for uuid %s.', uuid) | |
40 | ||
41 | return this.getData({ | |
42 | observableObject: this.getVideoInBulk, | |
43 | finder: v => v.uuid === uuid, | |
44 | param: uuid | |
45 | }) | |
46 | } | |
47 | ||
48 | getChannel (handle: string): Observable<VideoChannel> { | |
49 | logger('Schedule channel fetch for handle %s.', handle) | |
50 | ||
51 | return this.getData({ | |
52 | observableObject: this.getChannelInBulk, | |
53 | finder: c => c.nameWithHost === handle || c.nameWithHostForced === handle, | |
54 | param: handle | |
55 | }) | |
56 | } | |
57 | ||
58 | getPlaylist (uuid: string): Observable<VideoPlaylist> { | |
59 | logger('Schedule playlist fetch for uuid %s.', uuid) | |
60 | ||
61 | return this.getData({ | |
62 | observableObject: this.getPlaylistInBulk, | |
63 | finder: p => p.uuid === uuid, | |
64 | param: uuid | |
65 | }) | |
66 | } | |
67 | ||
68 | private getData <P extends number | string, R> (options: { | |
69 | observableObject: BulkObservables<P, ResultList<R>> | |
70 | param: P | |
71 | finder: (d: R) => boolean | |
72 | }) { | |
73 | const { observableObject, param, finder } = options | |
74 | ||
75 | return new Observable<R>(obs => { | |
76 | observableObject.result | |
77 | .pipe( | |
2cc276f9 | 78 | filter(result => result.params.includes(param)), |
ff4de383 | 79 | first(), |
2cc276f9 | 80 | map(result => result.response.data), |
3da38d6e C |
81 | map(data => data.find(finder)) |
82 | ) | |
83 | .subscribe(result => { | |
ff4de383 C |
84 | if (!result) { |
85 | obs.error(new Error($localize`Element ${param} not found`)) | |
86 | } else { | |
87 | obs.next(result) | |
88 | obs.complete() | |
89 | } | |
3da38d6e C |
90 | }) |
91 | ||
92 | observableObject.notifier.next(param) | |
93 | }) | |
94 | } | |
95 | ||
96 | private getVideosInBulk (uuids: string[]) { | |
97 | logger('Fetching videos %s.', uuids.join(', ')) | |
98 | ||
8d9c10bc C |
99 | return this.searchService.searchVideos({ |
100 | uuids, | |
101 | componentPagination: { itemsPerPage: uuids.length, currentPage: 1 }, | |
102 | advancedSearch: this.advancedSearchForBulk | |
103 | }) | |
3da38d6e C |
104 | } |
105 | ||
106 | private getChannelsInBulk (handles: string[]) { | |
107 | logger('Fetching channels %s.', handles.join(', ')) | |
108 | ||
8d9c10bc C |
109 | return this.searchService.searchVideoChannels({ |
110 | handles, | |
111 | componentPagination: { itemsPerPage: handles.length, currentPage: 1 }, | |
112 | advancedSearch: this.advancedSearchForBulk | |
113 | }) | |
3da38d6e C |
114 | } |
115 | ||
116 | private getPlaylistsInBulk (uuids: string[]) { | |
117 | logger('Fetching playlists %s.', uuids.join(', ')) | |
118 | ||
8d9c10bc C |
119 | return this.searchService.searchVideoPlaylists({ |
120 | uuids, | |
121 | componentPagination: { itemsPerPage: uuids.length, currentPage: 1 }, | |
122 | advancedSearch: this.advancedSearchForBulk | |
123 | }) | |
3da38d6e C |
124 | } |
125 | ||
2cc276f9 C |
126 | private buildBulkObservableObject <P extends number | string, R> (bulkGet: (params: P[]) => Observable<R>) { |
127 | const notifier = new Subject<P>() | |
3da38d6e C |
128 | |
129 | return { | |
130 | notifier, | |
131 | ||
132 | result: buildBulkObservable({ | |
133 | time: 500, | |
134 | bulkGet, | |
3da38d6e C |
135 | notifierObservable: notifier.asObservable() |
136 | }) | |
137 | } | |
138 | } | |
139 | } |