diff options
author | Chocobozzz <me@florianbigard.com> | 2020-06-23 14:10:17 +0200 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2020-06-23 16:00:49 +0200 |
commit | 67ed6552b831df66713bac9e672738796128d33f (patch) | |
tree | 59c97d41e0b49d75a90aa3de987968ab9b1ff447 /client/src/app/shared/video/video.service.ts | |
parent | 0c4bacbff53bc732f5a2677d62a6ead7752e2405 (diff) | |
download | PeerTube-67ed6552b831df66713bac9e672738796128d33f.tar.gz PeerTube-67ed6552b831df66713bac9e672738796128d33f.tar.zst PeerTube-67ed6552b831df66713bac9e672738796128d33f.zip |
Reorganize client shared modules
Diffstat (limited to 'client/src/app/shared/video/video.service.ts')
-rw-r--r-- | client/src/app/shared/video/video.service.ts | 409 |
1 files changed, 0 insertions, 409 deletions
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts deleted file mode 100644 index d66a1f809..000000000 --- a/client/src/app/shared/video/video.service.ts +++ /dev/null | |||
@@ -1,409 +0,0 @@ | |||
1 | import { catchError, map, switchMap } from 'rxjs/operators' | ||
2 | import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http' | ||
3 | import { Injectable } from '@angular/core' | ||
4 | import { Observable } from 'rxjs' | ||
5 | import { Video as VideoServerModel, VideoDetails as VideoDetailsServerModel } from '../../../../../shared' | ||
6 | import { ResultList } from '../../../../../shared/models/result-list.model' | ||
7 | import { | ||
8 | UserVideoRate, | ||
9 | UserVideoRateType, | ||
10 | UserVideoRateUpdate, | ||
11 | VideoConstant, | ||
12 | VideoFilter, | ||
13 | VideoPrivacy, | ||
14 | VideoUpdate | ||
15 | } from '../../../../../shared/models/videos' | ||
16 | import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum' | ||
17 | import { environment } from '../../../environments/environment' | ||
18 | import { ComponentPaginationLight } from '../rest/component-pagination.model' | ||
19 | import { RestExtractor } from '../rest/rest-extractor.service' | ||
20 | import { RestService } from '../rest/rest.service' | ||
21 | import { UserService } from '../users/user.service' | ||
22 | import { VideoSortField } from './sort-field.type' | ||
23 | import { VideoDetails } from './video-details.model' | ||
24 | import { VideoEdit } from './video-edit.model' | ||
25 | import { Video } from './video.model' | ||
26 | import { objectToFormData } from '@app/shared/misc/utils' | ||
27 | import { Account } from '@app/shared/account/account.model' | ||
28 | import { AccountService } from '@app/shared/account/account.service' | ||
29 | import { VideoChannelService } from '@app/shared/video-channel/video-channel.service' | ||
30 | import { ServerService, AuthService } from '@app/core' | ||
31 | import { UserSubscriptionService } from '@app/shared/user-subscription/user-subscription.service' | ||
32 | import { VideoChannel } from '@app/shared/video-channel/video-channel.model' | ||
33 | import { I18n } from '@ngx-translate/i18n-polyfill' | ||
34 | import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type' | ||
35 | import { FfprobeData } from 'fluent-ffmpeg' | ||
36 | |||
37 | export interface VideosProvider { | ||
38 | getVideos (parameters: { | ||
39 | videoPagination: ComponentPaginationLight, | ||
40 | sort: VideoSortField, | ||
41 | filter?: VideoFilter, | ||
42 | categoryOneOf?: number[], | ||
43 | languageOneOf?: string[] | ||
44 | nsfwPolicy: NSFWPolicyType | ||
45 | }): Observable<ResultList<Video>> | ||
46 | } | ||
47 | |||
48 | @Injectable() | ||
49 | export class VideoService implements VideosProvider { | ||
50 | static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos/' | ||
51 | static BASE_FEEDS_URL = environment.apiUrl + '/feeds/videos.' | ||
52 | |||
53 | constructor ( | ||
54 | private authHttp: HttpClient, | ||
55 | private authService: AuthService, | ||
56 | private userService: UserService, | ||
57 | private restExtractor: RestExtractor, | ||
58 | private restService: RestService, | ||
59 | private serverService: ServerService, | ||
60 | private i18n: I18n | ||
61 | ) {} | ||
62 | |||
63 | getVideoViewUrl (uuid: string) { | ||
64 | return VideoService.BASE_VIDEO_URL + uuid + '/views' | ||
65 | } | ||
66 | |||
67 | getUserWatchingVideoUrl (uuid: string) { | ||
68 | return VideoService.BASE_VIDEO_URL + uuid + '/watching' | ||
69 | } | ||
70 | |||
71 | getVideo (options: { videoId: string }): Observable<VideoDetails> { | ||
72 | return this.serverService.getServerLocale() | ||
73 | .pipe( | ||
74 | switchMap(translations => { | ||
75 | return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + options.videoId) | ||
76 | .pipe(map(videoHash => ({ videoHash, translations }))) | ||
77 | }), | ||
78 | map(({ videoHash, translations }) => new VideoDetails(videoHash, translations)), | ||
79 | catchError(err => this.restExtractor.handleError(err)) | ||
80 | ) | ||
81 | } | ||
82 | |||
83 | updateVideo (video: VideoEdit) { | ||
84 | const language = video.language || null | ||
85 | const licence = video.licence || null | ||
86 | const category = video.category || null | ||
87 | const description = video.description || null | ||
88 | const support = video.support || null | ||
89 | const scheduleUpdate = video.scheduleUpdate || null | ||
90 | const originallyPublishedAt = video.originallyPublishedAt || null | ||
91 | |||
92 | const body: VideoUpdate = { | ||
93 | name: video.name, | ||
94 | category, | ||
95 | licence, | ||
96 | language, | ||
97 | support, | ||
98 | description, | ||
99 | channelId: video.channelId, | ||
100 | privacy: video.privacy, | ||
101 | tags: video.tags, | ||
102 | nsfw: video.nsfw, | ||
103 | waitTranscoding: video.waitTranscoding, | ||
104 | commentsEnabled: video.commentsEnabled, | ||
105 | downloadEnabled: video.downloadEnabled, | ||
106 | thumbnailfile: video.thumbnailfile, | ||
107 | previewfile: video.previewfile, | ||
108 | scheduleUpdate, | ||
109 | originallyPublishedAt | ||
110 | } | ||
111 | |||
112 | const data = objectToFormData(body) | ||
113 | |||
114 | return this.authHttp.put(VideoService.BASE_VIDEO_URL + video.id, data) | ||
115 | .pipe( | ||
116 | map(this.restExtractor.extractDataBool), | ||
117 | catchError(err => this.restExtractor.handleError(err)) | ||
118 | ) | ||
119 | } | ||
120 | |||
121 | uploadVideo (video: FormData) { | ||
122 | const req = new HttpRequest('POST', VideoService.BASE_VIDEO_URL + 'upload', video, { reportProgress: true }) | ||
123 | |||
124 | return this.authHttp | ||
125 | .request<{ video: { id: number, uuid: string } }>(req) | ||
126 | .pipe(catchError(err => this.restExtractor.handleError(err))) | ||
127 | } | ||
128 | |||
129 | getMyVideos (videoPagination: ComponentPaginationLight, sort: VideoSortField, search?: string): Observable<ResultList<Video>> { | ||
130 | const pagination = this.restService.componentPaginationToRestPagination(videoPagination) | ||
131 | |||
132 | let params = new HttpParams() | ||
133 | params = this.restService.addRestGetParams(params, pagination, sort) | ||
134 | params = this.restService.addObjectParams(params, { search }) | ||
135 | |||
136 | return this.authHttp | ||
137 | .get<ResultList<Video>>(UserService.BASE_USERS_URL + 'me/videos', { params }) | ||
138 | .pipe( | ||
139 | switchMap(res => this.extractVideos(res)), | ||
140 | catchError(err => this.restExtractor.handleError(err)) | ||
141 | ) | ||
142 | } | ||
143 | |||
144 | getAccountVideos ( | ||
145 | account: Account, | ||
146 | videoPagination: ComponentPaginationLight, | ||
147 | sort: VideoSortField | ||
148 | ): Observable<ResultList<Video>> { | ||
149 | const pagination = this.restService.componentPaginationToRestPagination(videoPagination) | ||
150 | |||
151 | let params = new HttpParams() | ||
152 | params = this.restService.addRestGetParams(params, pagination, sort) | ||
153 | |||
154 | return this.authHttp | ||
155 | .get<ResultList<Video>>(AccountService.BASE_ACCOUNT_URL + account.nameWithHost + '/videos', { params }) | ||
156 | .pipe( | ||
157 | switchMap(res => this.extractVideos(res)), | ||
158 | catchError(err => this.restExtractor.handleError(err)) | ||
159 | ) | ||
160 | } | ||
161 | |||
162 | getVideoChannelVideos ( | ||
163 | videoChannel: VideoChannel, | ||
164 | videoPagination: ComponentPaginationLight, | ||
165 | sort: VideoSortField, | ||
166 | nsfwPolicy?: NSFWPolicyType | ||
167 | ): Observable<ResultList<Video>> { | ||
168 | const pagination = this.restService.componentPaginationToRestPagination(videoPagination) | ||
169 | |||
170 | let params = new HttpParams() | ||
171 | params = this.restService.addRestGetParams(params, pagination, sort) | ||
172 | |||
173 | if (nsfwPolicy) { | ||
174 | params = params.set('nsfw', this.nsfwPolicyToParam(nsfwPolicy)) | ||
175 | } | ||
176 | |||
177 | return this.authHttp | ||
178 | .get<ResultList<Video>>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannel.nameWithHost + '/videos', { params }) | ||
179 | .pipe( | ||
180 | switchMap(res => this.extractVideos(res)), | ||
181 | catchError(err => this.restExtractor.handleError(err)) | ||
182 | ) | ||
183 | } | ||
184 | |||
185 | getUserSubscriptionVideos (parameters: { | ||
186 | videoPagination: ComponentPaginationLight, | ||
187 | sort: VideoSortField, | ||
188 | skipCount?: boolean | ||
189 | }): Observable<ResultList<Video>> { | ||
190 | const { videoPagination, sort, skipCount } = parameters | ||
191 | const pagination = this.restService.componentPaginationToRestPagination(videoPagination) | ||
192 | |||
193 | let params = new HttpParams() | ||
194 | params = this.restService.addRestGetParams(params, pagination, sort) | ||
195 | |||
196 | if (skipCount) params = params.set('skipCount', skipCount + '') | ||
197 | |||
198 | return this.authHttp | ||
199 | .get<ResultList<Video>>(UserSubscriptionService.BASE_USER_SUBSCRIPTIONS_URL + '/videos', { params }) | ||
200 | .pipe( | ||
201 | switchMap(res => this.extractVideos(res)), | ||
202 | catchError(err => this.restExtractor.handleError(err)) | ||
203 | ) | ||
204 | } | ||
205 | |||
206 | getVideos (parameters: { | ||
207 | videoPagination: ComponentPaginationLight, | ||
208 | sort: VideoSortField, | ||
209 | filter?: VideoFilter, | ||
210 | categoryOneOf?: number[], | ||
211 | languageOneOf?: string[], | ||
212 | skipCount?: boolean, | ||
213 | nsfwPolicy?: NSFWPolicyType | ||
214 | }): Observable<ResultList<Video>> { | ||
215 | const { videoPagination, sort, filter, categoryOneOf, languageOneOf, skipCount, nsfwPolicy } = parameters | ||
216 | |||
217 | const pagination = this.restService.componentPaginationToRestPagination(videoPagination) | ||
218 | |||
219 | let params = new HttpParams() | ||
220 | params = this.restService.addRestGetParams(params, pagination, sort) | ||
221 | |||
222 | if (filter) params = params.set('filter', filter) | ||
223 | if (skipCount) params = params.set('skipCount', skipCount + '') | ||
224 | |||
225 | if (nsfwPolicy) { | ||
226 | params = params.set('nsfw', this.nsfwPolicyToParam(nsfwPolicy)) | ||
227 | } | ||
228 | |||
229 | if (languageOneOf) { | ||
230 | for (const l of languageOneOf) { | ||
231 | params = params.append('languageOneOf[]', l) | ||
232 | } | ||
233 | } | ||
234 | |||
235 | if (categoryOneOf) { | ||
236 | for (const c of categoryOneOf) { | ||
237 | params = params.append('categoryOneOf[]', c + '') | ||
238 | } | ||
239 | } | ||
240 | |||
241 | return this.authHttp | ||
242 | .get<ResultList<Video>>(VideoService.BASE_VIDEO_URL, { params }) | ||
243 | .pipe( | ||
244 | switchMap(res => this.extractVideos(res)), | ||
245 | catchError(err => this.restExtractor.handleError(err)) | ||
246 | ) | ||
247 | } | ||
248 | |||
249 | buildBaseFeedUrls (params: HttpParams) { | ||
250 | const feeds = [ | ||
251 | { | ||
252 | format: FeedFormat.RSS, | ||
253 | label: 'rss 2.0', | ||
254 | url: VideoService.BASE_FEEDS_URL + FeedFormat.RSS.toLowerCase() | ||
255 | }, | ||
256 | { | ||
257 | format: FeedFormat.ATOM, | ||
258 | label: 'atom 1.0', | ||
259 | url: VideoService.BASE_FEEDS_URL + FeedFormat.ATOM.toLowerCase() | ||
260 | }, | ||
261 | { | ||
262 | format: FeedFormat.JSON, | ||
263 | label: 'json 1.0', | ||
264 | url: VideoService.BASE_FEEDS_URL + FeedFormat.JSON.toLowerCase() | ||
265 | } | ||
266 | ] | ||
267 | |||
268 | if (params && params.keys().length !== 0) { | ||
269 | for (const feed of feeds) { | ||
270 | feed.url += '?' + params.toString() | ||
271 | } | ||
272 | } | ||
273 | |||
274 | return feeds | ||
275 | } | ||
276 | |||
277 | getVideoFeedUrls (sort: VideoSortField, filter?: VideoFilter, categoryOneOf?: number[]) { | ||
278 | let params = this.restService.addRestGetParams(new HttpParams(), undefined, sort) | ||
279 | |||
280 | if (filter) params = params.set('filter', filter) | ||
281 | |||
282 | if (categoryOneOf) { | ||
283 | for (const c of categoryOneOf) { | ||
284 | params = params.append('categoryOneOf[]', c + '') | ||
285 | } | ||
286 | } | ||
287 | |||
288 | return this.buildBaseFeedUrls(params) | ||
289 | } | ||
290 | |||
291 | getAccountFeedUrls (accountId: number) { | ||
292 | let params = this.restService.addRestGetParams(new HttpParams()) | ||
293 | params = params.set('accountId', accountId.toString()) | ||
294 | |||
295 | return this.buildBaseFeedUrls(params) | ||
296 | } | ||
297 | |||
298 | getVideoChannelFeedUrls (videoChannelId: number) { | ||
299 | let params = this.restService.addRestGetParams(new HttpParams()) | ||
300 | params = params.set('videoChannelId', videoChannelId.toString()) | ||
301 | |||
302 | return this.buildBaseFeedUrls(params) | ||
303 | } | ||
304 | |||
305 | getVideoFileMetadata (metadataUrl: string) { | ||
306 | return this.authHttp | ||
307 | .get<FfprobeData>(metadataUrl) | ||
308 | .pipe( | ||
309 | catchError(err => this.restExtractor.handleError(err)) | ||
310 | ) | ||
311 | } | ||
312 | |||
313 | removeVideo (id: number) { | ||
314 | return this.authHttp | ||
315 | .delete(VideoService.BASE_VIDEO_URL + id) | ||
316 | .pipe( | ||
317 | map(this.restExtractor.extractDataBool), | ||
318 | catchError(err => this.restExtractor.handleError(err)) | ||
319 | ) | ||
320 | } | ||
321 | |||
322 | loadCompleteDescription (descriptionPath: string) { | ||
323 | return this.authHttp | ||
324 | .get<{ description: string }>(environment.apiUrl + descriptionPath) | ||
325 | .pipe( | ||
326 | map(res => res.description), | ||
327 | catchError(err => this.restExtractor.handleError(err)) | ||
328 | ) | ||
329 | } | ||
330 | |||
331 | setVideoLike (id: number) { | ||
332 | return this.setVideoRate(id, 'like') | ||
333 | } | ||
334 | |||
335 | setVideoDislike (id: number) { | ||
336 | return this.setVideoRate(id, 'dislike') | ||
337 | } | ||
338 | |||
339 | unsetVideoLike (id: number) { | ||
340 | return this.setVideoRate(id, 'none') | ||
341 | } | ||
342 | |||
343 | getUserVideoRating (id: number) { | ||
344 | const url = UserService.BASE_USERS_URL + 'me/videos/' + id + '/rating' | ||
345 | |||
346 | return this.authHttp.get<UserVideoRate>(url) | ||
347 | .pipe(catchError(err => this.restExtractor.handleError(err))) | ||
348 | } | ||
349 | |||
350 | extractVideos (result: ResultList<VideoServerModel>) { | ||
351 | return this.serverService.getServerLocale() | ||
352 | .pipe( | ||
353 | map(translations => { | ||
354 | const videosJson = result.data | ||
355 | const totalVideos = result.total | ||
356 | const videos: Video[] = [] | ||
357 | |||
358 | for (const videoJson of videosJson) { | ||
359 | videos.push(new Video(videoJson, translations)) | ||
360 | } | ||
361 | |||
362 | return { total: totalVideos, data: videos } | ||
363 | }) | ||
364 | ) | ||
365 | } | ||
366 | |||
367 | explainedPrivacyLabels (privacies: VideoConstant<VideoPrivacy>[]) { | ||
368 | const base = [ | ||
369 | { | ||
370 | id: VideoPrivacy.PRIVATE, | ||
371 | label: this.i18n('Only I can see this video') | ||
372 | }, | ||
373 | { | ||
374 | id: VideoPrivacy.UNLISTED, | ||
375 | label: this.i18n('Only people with the private link can see this video') | ||
376 | }, | ||
377 | { | ||
378 | id: VideoPrivacy.PUBLIC, | ||
379 | label: this.i18n('Anyone can see this video') | ||
380 | }, | ||
381 | { | ||
382 | id: VideoPrivacy.INTERNAL, | ||
383 | label: this.i18n('Only users of this instance can see this video') | ||
384 | } | ||
385 | ] | ||
386 | |||
387 | return base.filter(o => !!privacies.find(p => p.id === o.id)) | ||
388 | } | ||
389 | |||
390 | nsfwPolicyToParam (nsfwPolicy: NSFWPolicyType) { | ||
391 | return nsfwPolicy === 'do_not_list' | ||
392 | ? 'false' | ||
393 | : 'both' | ||
394 | } | ||
395 | |||
396 | private setVideoRate (id: number, rateType: UserVideoRateType) { | ||
397 | const url = VideoService.BASE_VIDEO_URL + id + '/rate' | ||
398 | const body: UserVideoRateUpdate = { | ||
399 | rating: rateType | ||
400 | } | ||
401 | |||
402 | return this.authHttp | ||
403 | .put(url, body) | ||
404 | .pipe( | ||
405 | map(this.restExtractor.extractDataBool), | ||
406 | catchError(err => this.restExtractor.handleError(err)) | ||
407 | ) | ||
408 | } | ||
409 | } | ||