diff options
Diffstat (limited to 'client/src/standalone')
-rw-r--r-- | client/src/standalone/videos/embed.html | 17 | ||||
-rw-r--r-- | client/src/standalone/videos/embed.scss | 43 | ||||
-rw-r--r-- | client/src/standalone/videos/embed.ts | 44 | ||||
-rw-r--r-- | client/src/standalone/videos/shared/auth-http.ts | 10 | ||||
-rw-r--r-- | client/src/standalone/videos/shared/player-html.ts | 52 | ||||
-rw-r--r-- | client/src/standalone/videos/shared/player-manager-options.ts | 12 | ||||
-rw-r--r-- | client/src/standalone/videos/shared/video-fetcher.ts | 24 |
7 files changed, 178 insertions, 24 deletions
diff --git a/client/src/standalone/videos/embed.html b/client/src/standalone/videos/embed.html index 32bf5f655..a74bb4cee 100644 --- a/client/src/standalone/videos/embed.html +++ b/client/src/standalone/videos/embed.html | |||
@@ -41,6 +41,23 @@ | |||
41 | <div id="error-content"></div> | 41 | <div id="error-content"></div> |
42 | </div> | 42 | </div> |
43 | 43 | ||
44 | <div id="video-password-block"> | ||
45 | <!-- eslint-disable-next-line @angular-eslint/template/elements-content --> | ||
46 | <h1 id="video-password-title"></h1> | ||
47 | |||
48 | <div id="video-password-content"></div> | ||
49 | |||
50 | <form id="video-password-form"> | ||
51 | <input type="password" id="video-password-input" name="video-password" required> | ||
52 | <button type="submit" id="video-password-submit"> </button> | ||
53 | </form> | ||
54 | |||
55 | <div id="video-password-error"></div> | ||
56 | <svg xmlns="http://www.w3.org/2000/svg" width="4rem" height="4rem" viewBox="0 0 24 24"> | ||
57 | <g fill="none" stroke="#c4c4c4" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></g> | ||
58 | </svg> | ||
59 | </div> | ||
60 | |||
44 | <div id="video-wrapper"></div> | 61 | <div id="video-wrapper"></div> |
45 | 62 | ||
46 | <div id="placeholder-preview"></div> | 63 | <div id="placeholder-preview"></div> |
diff --git a/client/src/standalone/videos/embed.scss b/client/src/standalone/videos/embed.scss index 3631ea7e6..d15887478 100644 --- a/client/src/standalone/videos/embed.scss +++ b/client/src/standalone/videos/embed.scss | |||
@@ -24,7 +24,7 @@ html, | |||
24 | body { | 24 | body { |
25 | height: 100%; | 25 | height: 100%; |
26 | margin: 0; | 26 | margin: 0; |
27 | background-color: #000; | 27 | background-color: #0f0f10; |
28 | } | 28 | } |
29 | 29 | ||
30 | #video-wrapper { | 30 | #video-wrapper { |
@@ -42,8 +42,10 @@ body { | |||
42 | } | 42 | } |
43 | } | 43 | } |
44 | 44 | ||
45 | #error-block { | 45 | #error-block, |
46 | #video-password-block { | ||
46 | display: none; | 47 | display: none; |
48 | user-select: none; | ||
47 | 49 | ||
48 | flex-direction: column; | 50 | flex-direction: column; |
49 | align-content: center; | 51 | align-content: center; |
@@ -86,6 +88,43 @@ body { | |||
86 | text-align: center; | 88 | text-align: center; |
87 | } | 89 | } |
88 | 90 | ||
91 | #video-password-content { | ||
92 | @include margin(1rem, 0, 2rem); | ||
93 | } | ||
94 | |||
95 | #video-password-input, | ||
96 | #video-password-submit { | ||
97 | line-height: 23px; | ||
98 | padding: 1rem; | ||
99 | margin: 1rem 0.5rem; | ||
100 | border: 0; | ||
101 | font-weight: 600; | ||
102 | border-radius: 3px!important; | ||
103 | font-size: 18px; | ||
104 | display: inline-block; | ||
105 | } | ||
106 | |||
107 | #video-password-submit { | ||
108 | color: #fff; | ||
109 | background-color: #f2690d; | ||
110 | cursor: pointer; | ||
111 | } | ||
112 | |||
113 | #video-password-submit:hover { | ||
114 | background-color: #f47825; | ||
115 | } | ||
116 | #video-password-error { | ||
117 | margin-top: 10px; | ||
118 | margin-bottom: 10px; | ||
119 | height: 2rem; | ||
120 | font-weight: bolder; | ||
121 | } | ||
122 | |||
123 | #video-password-block svg { | ||
124 | margin-left: auto; | ||
125 | margin-right: auto; | ||
126 | } | ||
127 | |||
89 | @media screen and (max-width: 300px) { | 128 | @media screen and (max-width: 300px) { |
90 | #error-block { | 129 | #error-block { |
91 | font-size: 36px; | 130 | font-size: 36px; |
diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts index cc4274b99..cffda2cc7 100644 --- a/client/src/standalone/videos/embed.ts +++ b/client/src/standalone/videos/embed.ts | |||
@@ -3,10 +3,18 @@ import '../../assets/player/shared/dock/peertube-dock-component' | |||
3 | import '../../assets/player/shared/dock/peertube-dock-plugin' | 3 | import '../../assets/player/shared/dock/peertube-dock-plugin' |
4 | import videojs from 'video.js' | 4 | import videojs from 'video.js' |
5 | import { peertubeTranslate } from '../../../../shared/core-utils/i18n' | 5 | import { peertubeTranslate } from '../../../../shared/core-utils/i18n' |
6 | import { HTMLServerConfig, ResultList, VideoDetails, VideoPlaylist, VideoPlaylistElement, VideoState } from '../../../../shared/models' | 6 | import { |
7 | HTMLServerConfig, | ||
8 | ResultList, | ||
9 | ServerErrorCode, | ||
10 | VideoDetails, | ||
11 | VideoPlaylist, | ||
12 | VideoPlaylistElement, | ||
13 | VideoState | ||
14 | } from '../../../../shared/models' | ||
7 | import { PeertubePlayerManager } from '../../assets/player' | 15 | import { PeertubePlayerManager } from '../../assets/player' |
8 | import { TranslationsManager } from '../../assets/player/translations-manager' | 16 | import { TranslationsManager } from '../../assets/player/translations-manager' |
9 | import { getParamString, logger, videoRequiresAuth } from '../../root-helpers' | 17 | import { getParamString, logger, videoRequiresFileToken } from '../../root-helpers' |
10 | import { PeerTubeEmbedApi } from './embed-api' | 18 | import { PeerTubeEmbedApi } from './embed-api' |
11 | import { | 19 | import { |
12 | AuthHTTP, | 20 | AuthHTTP, |
@@ -19,6 +27,7 @@ import { | |||
19 | VideoFetcher | 27 | VideoFetcher |
20 | } from './shared' | 28 | } from './shared' |
21 | import { PlayerHTML } from './shared/player-html' | 29 | import { PlayerHTML } from './shared/player-html' |
30 | import { PeerTubeServerError } from 'src/types' | ||
22 | 31 | ||
23 | export class PeerTubeEmbed { | 32 | export class PeerTubeEmbed { |
24 | player: videojs.Player | 33 | player: videojs.Player |
@@ -38,6 +47,8 @@ export class PeerTubeEmbed { | |||
38 | private readonly liveManager: LiveManager | 47 | private readonly liveManager: LiveManager |
39 | 48 | ||
40 | private playlistTracker: PlaylistTracker | 49 | private playlistTracker: PlaylistTracker |
50 | private videoPassword: string | ||
51 | private requiresPassword: boolean | ||
41 | 52 | ||
42 | constructor (videoWrapperId: string) { | 53 | constructor (videoWrapperId: string) { |
43 | logger.registerServerSending(window.location.origin) | 54 | logger.registerServerSending(window.location.origin) |
@@ -50,6 +61,7 @@ export class PeerTubeEmbed { | |||
50 | this.playerHTML = new PlayerHTML(videoWrapperId) | 61 | this.playerHTML = new PlayerHTML(videoWrapperId) |
51 | this.playerManagerOptions = new PlayerManagerOptions(this.playerHTML, this.videoFetcher, this.peertubePlugin) | 62 | this.playerManagerOptions = new PlayerManagerOptions(this.playerHTML, this.videoFetcher, this.peertubePlugin) |
52 | this.liveManager = new LiveManager(this.playerHTML) | 63 | this.liveManager = new LiveManager(this.playerHTML) |
64 | this.requiresPassword = false | ||
53 | 65 | ||
54 | try { | 66 | try { |
55 | this.config = JSON.parse((window as any)['PeerTubeServerConfig']) | 67 | this.config = JSON.parse((window as any)['PeerTubeServerConfig']) |
@@ -176,11 +188,13 @@ export class PeerTubeEmbed { | |||
176 | const { uuid, autoplayFromPreviousVideo, forceAutoplay } = options | 188 | const { uuid, autoplayFromPreviousVideo, forceAutoplay } = options |
177 | 189 | ||
178 | try { | 190 | try { |
179 | const { videoResponse, captionsPromise } = await this.videoFetcher.loadVideo(uuid) | 191 | const { videoResponse, captionsPromise } = await this.videoFetcher.loadVideo({ videoId: uuid, videoPassword: this.videoPassword }) |
180 | 192 | ||
181 | return this.buildVideoPlayer({ videoResponse, captionsPromise, autoplayFromPreviousVideo, forceAutoplay }) | 193 | return this.buildVideoPlayer({ videoResponse, captionsPromise, autoplayFromPreviousVideo, forceAutoplay }) |
182 | } catch (err) { | 194 | } catch (err) { |
183 | this.playerHTML.displayError(err.message, await this.translationsPromise) | 195 | |
196 | if (await this.handlePasswordError(err)) this.loadVideoAndBuildPlayer({ ...options }) | ||
197 | else this.playerHTML.displayError(err.message, await this.translationsPromise) | ||
184 | } | 198 | } |
185 | } | 199 | } |
186 | 200 | ||
@@ -205,8 +219,8 @@ export class PeerTubeEmbed { | |||
205 | ? await this.videoFetcher.loadLive(videoInfo) | 219 | ? await this.videoFetcher.loadLive(videoInfo) |
206 | : undefined | 220 | : undefined |
207 | 221 | ||
208 | const videoFileToken = videoRequiresAuth(videoInfo) | 222 | const videoFileToken = videoRequiresFileToken(videoInfo) |
209 | ? await this.videoFetcher.loadVideoToken(videoInfo) | 223 | ? await this.videoFetcher.loadVideoToken(videoInfo, this.videoPassword) |
210 | : undefined | 224 | : undefined |
211 | 225 | ||
212 | return { live, video: videoInfo, videoFileToken } | 226 | return { live, video: videoInfo, videoFileToken } |
@@ -232,6 +246,8 @@ export class PeerTubeEmbed { | |||
232 | 246 | ||
233 | authorizationHeader: () => this.http.getHeaderTokenValue(), | 247 | authorizationHeader: () => this.http.getHeaderTokenValue(), |
234 | videoFileToken: () => videoFileToken, | 248 | videoFileToken: () => videoFileToken, |
249 | videoPassword: () => this.videoPassword, | ||
250 | requiresPassword: this.requiresPassword, | ||
235 | 251 | ||
236 | onVideoUpdate: (uuid: string) => this.loadVideoAndBuildPlayer({ uuid, autoplayFromPreviousVideo: true, forceAutoplay: false }), | 252 | onVideoUpdate: (uuid: string) => this.loadVideoAndBuildPlayer({ uuid, autoplayFromPreviousVideo: true, forceAutoplay: false }), |
237 | 253 | ||
@@ -263,6 +279,7 @@ export class PeerTubeEmbed { | |||
263 | this.initializeApi() | 279 | this.initializeApi() |
264 | 280 | ||
265 | this.playerHTML.removePlaceholder() | 281 | this.playerHTML.removePlaceholder() |
282 | if (this.videoPassword) this.playerHTML.removeVideoPasswordBlock() | ||
266 | 283 | ||
267 | if (this.isPlaylistEmbed()) { | 284 | if (this.isPlaylistEmbed()) { |
268 | await this.buildPlayerPlaylistUpnext() | 285 | await this.buildPlayerPlaylistUpnext() |
@@ -401,6 +418,21 @@ export class PeerTubeEmbed { | |||
401 | (this.player.el() as HTMLElement).style.pointerEvents = 'none' | 418 | (this.player.el() as HTMLElement).style.pointerEvents = 'none' |
402 | } | 419 | } |
403 | 420 | ||
421 | private async handlePasswordError (err: PeerTubeServerError) { | ||
422 | let incorrectPassword: boolean = null | ||
423 | if (err.serverCode === ServerErrorCode.VIDEO_REQUIRES_PASSWORD) incorrectPassword = false | ||
424 | else if (err.serverCode === ServerErrorCode.INCORRECT_VIDEO_PASSWORD) incorrectPassword = true | ||
425 | |||
426 | if (incorrectPassword === null) return false | ||
427 | |||
428 | this.requiresPassword = true | ||
429 | this.videoPassword = await this.playerHTML.askVideoPassword({ | ||
430 | incorrectPassword, | ||
431 | translations: await this.translationsPromise | ||
432 | }) | ||
433 | return true | ||
434 | } | ||
435 | |||
404 | } | 436 | } |
405 | 437 | ||
406 | PeerTubeEmbed.main() | 438 | PeerTubeEmbed.main() |
diff --git a/client/src/standalone/videos/shared/auth-http.ts b/client/src/standalone/videos/shared/auth-http.ts index 95e3b029e..c1e9f7750 100644 --- a/client/src/standalone/videos/shared/auth-http.ts +++ b/client/src/standalone/videos/shared/auth-http.ts | |||
@@ -18,10 +18,12 @@ export class AuthHTTP { | |||
18 | if (this.userOAuthTokens) this.setHeadersFromTokens() | 18 | if (this.userOAuthTokens) this.setHeadersFromTokens() |
19 | } | 19 | } |
20 | 20 | ||
21 | fetch (url: string, { optionalAuth, method }: { optionalAuth: boolean, method?: string }) { | 21 | fetch (url: string, { optionalAuth, method }: { optionalAuth: boolean, method?: string }, videoPassword?: string) { |
22 | const refreshFetchOptions = optionalAuth | 22 | let refreshFetchOptions: { headers?: Headers } = {} |
23 | ? { headers: this.headers } | 23 | |
24 | : {} | 24 | if (videoPassword) this.headers.set('x-peertube-video-password', videoPassword) |
25 | |||
26 | if (videoPassword || optionalAuth) refreshFetchOptions = { headers: this.headers } | ||
25 | 27 | ||
26 | return this.refreshFetch(url.toString(), { ...refreshFetchOptions, method }) | 28 | return this.refreshFetch(url.toString(), { ...refreshFetchOptions, method }) |
27 | } | 29 | } |
diff --git a/client/src/standalone/videos/shared/player-html.ts b/client/src/standalone/videos/shared/player-html.ts index d93678c10..a0846d9d7 100644 --- a/client/src/standalone/videos/shared/player-html.ts +++ b/client/src/standalone/videos/shared/player-html.ts | |||
@@ -55,6 +55,58 @@ export class PlayerHTML { | |||
55 | this.wrapperElement.style.display = 'none' | 55 | this.wrapperElement.style.display = 'none' |
56 | } | 56 | } |
57 | 57 | ||
58 | async askVideoPassword (options: { incorrectPassword: boolean, translations: Translations }): Promise<string> { | ||
59 | const { incorrectPassword, translations } = options | ||
60 | return new Promise((resolve) => { | ||
61 | |||
62 | this.removePlaceholder() | ||
63 | this.wrapperElement.style.display = 'none' | ||
64 | |||
65 | const translatedTitle = peertubeTranslate('This video is password protected', translations) | ||
66 | const translatedMessage = peertubeTranslate('You need a password to watch this video.', translations) | ||
67 | |||
68 | document.title = translatedTitle | ||
69 | |||
70 | const videoPasswordBlock = document.getElementById('video-password-block') | ||
71 | videoPasswordBlock.style.display = 'flex' | ||
72 | |||
73 | const videoPasswordTitle = document.getElementById('video-password-title') | ||
74 | videoPasswordTitle.innerHTML = translatedTitle | ||
75 | |||
76 | const videoPasswordMessage = document.getElementById('video-password-content') | ||
77 | videoPasswordMessage.innerHTML = translatedMessage | ||
78 | |||
79 | if (incorrectPassword) { | ||
80 | const videoPasswordError = document.getElementById('video-password-error') | ||
81 | videoPasswordError.innerHTML = peertubeTranslate('Incorrect password, please enter a correct password', translations) | ||
82 | videoPasswordError.style.transform = 'scale(1.2)' | ||
83 | |||
84 | setTimeout(() => { | ||
85 | videoPasswordError.style.transform = 'scale(1)' | ||
86 | }, 500) | ||
87 | } | ||
88 | |||
89 | const videoPasswordSubmitButton = document.getElementById('video-password-submit') | ||
90 | videoPasswordSubmitButton.innerHTML = peertubeTranslate('Watch Video', translations) | ||
91 | |||
92 | const videoPasswordInput = document.getElementById('video-password-input') as HTMLInputElement | ||
93 | videoPasswordInput.placeholder = peertubeTranslate('Password', translations) | ||
94 | |||
95 | const videoPasswordForm = document.getElementById('video-password-form') | ||
96 | videoPasswordForm.addEventListener('submit', (event) => { | ||
97 | event.preventDefault() | ||
98 | const videoPassword = videoPasswordInput.value | ||
99 | resolve(videoPassword) | ||
100 | }) | ||
101 | }) | ||
102 | } | ||
103 | |||
104 | removeVideoPasswordBlock () { | ||
105 | const videoPasswordBlock = document.getElementById('video-password-block') | ||
106 | videoPasswordBlock.style.display = 'none' | ||
107 | this.wrapperElement.style.display = 'block' | ||
108 | } | ||
109 | |||
58 | buildPlaceholder (video: VideoDetails) { | 110 | buildPlaceholder (video: VideoDetails) { |
59 | const placeholder = this.getPlaceholderElement() | 111 | const placeholder = this.getPlaceholderElement() |
60 | 112 | ||
diff --git a/client/src/standalone/videos/shared/player-manager-options.ts b/client/src/standalone/videos/shared/player-manager-options.ts index 43ae22a3b..587516410 100644 --- a/client/src/standalone/videos/shared/player-manager-options.ts +++ b/client/src/standalone/videos/shared/player-manager-options.ts | |||
@@ -18,7 +18,7 @@ import { | |||
18 | logger, | 18 | logger, |
19 | peertubeLocalStorage, | 19 | peertubeLocalStorage, |
20 | UserLocalStorageKeys, | 20 | UserLocalStorageKeys, |
21 | videoRequiresAuth | 21 | videoRequiresUserAuth |
22 | } from '../../../root-helpers' | 22 | } from '../../../root-helpers' |
23 | import { PeerTubePlugin } from './peertube-plugin' | 23 | import { PeerTubePlugin } from './peertube-plugin' |
24 | import { PlayerHTML } from './player-html' | 24 | import { PlayerHTML } from './player-html' |
@@ -162,6 +162,9 @@ export class PlayerManagerOptions { | |||
162 | authorizationHeader: () => string | 162 | authorizationHeader: () => string |
163 | videoFileToken: () => string | 163 | videoFileToken: () => string |
164 | 164 | ||
165 | videoPassword: () => string | ||
166 | requiresPassword: boolean | ||
167 | |||
165 | serverConfig: HTMLServerConfig | 168 | serverConfig: HTMLServerConfig |
166 | 169 | ||
167 | autoplayFromPreviousVideo: boolean | 170 | autoplayFromPreviousVideo: boolean |
@@ -178,6 +181,8 @@ export class PlayerManagerOptions { | |||
178 | captionsResponse, | 181 | captionsResponse, |
179 | autoplayFromPreviousVideo, | 182 | autoplayFromPreviousVideo, |
180 | videoFileToken, | 183 | videoFileToken, |
184 | videoPassword, | ||
185 | requiresPassword, | ||
181 | translations, | 186 | translations, |
182 | forceAutoplay, | 187 | forceAutoplay, |
183 | playlistTracker, | 188 | playlistTracker, |
@@ -242,10 +247,13 @@ export class PlayerManagerOptions { | |||
242 | embedUrl: window.location.origin + video.embedPath, | 247 | embedUrl: window.location.origin + video.embedPath, |
243 | embedTitle: video.name, | 248 | embedTitle: video.name, |
244 | 249 | ||
245 | requiresAuth: videoRequiresAuth(video), | 250 | requiresUserAuth: videoRequiresUserAuth(video), |
246 | authorizationHeader, | 251 | authorizationHeader, |
247 | videoFileToken, | 252 | videoFileToken, |
248 | 253 | ||
254 | requiresPassword, | ||
255 | videoPassword, | ||
256 | |||
249 | errorNotifier: () => { | 257 | errorNotifier: () => { |
250 | // Empty, we don't have a notifier in the embed | 258 | // Empty, we don't have a notifier in the embed |
251 | }, | 259 | }, |
diff --git a/client/src/standalone/videos/shared/video-fetcher.ts b/client/src/standalone/videos/shared/video-fetcher.ts index cf6d12831..76ba0a3ed 100644 --- a/client/src/standalone/videos/shared/video-fetcher.ts +++ b/client/src/standalone/videos/shared/video-fetcher.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | import { PeerTubeServerError } from '../../../types' | ||
1 | import { HttpStatusCode, LiveVideo, VideoDetails, VideoToken } from '../../../../../shared/models' | 2 | import { HttpStatusCode, LiveVideo, VideoDetails, VideoToken } from '../../../../../shared/models' |
2 | import { logger } from '../../../root-helpers' | 3 | import { logger } from '../../../root-helpers' |
3 | import { AuthHTTP } from './auth-http' | 4 | import { AuthHTTP } from './auth-http' |
@@ -8,8 +9,8 @@ export class VideoFetcher { | |||
8 | 9 | ||
9 | } | 10 | } |
10 | 11 | ||
11 | async loadVideo (videoId: string) { | 12 | async loadVideo ({ videoId, videoPassword }: { videoId: string, videoPassword?: string }) { |
12 | const videoPromise = this.loadVideoInfo(videoId) | 13 | const videoPromise = this.loadVideoInfo({ videoId, videoPassword }) |
13 | 14 | ||
14 | let videoResponse: Response | 15 | let videoResponse: Response |
15 | let isResponseOk: boolean | 16 | let isResponseOk: boolean |
@@ -27,11 +28,14 @@ export class VideoFetcher { | |||
27 | if (videoResponse?.status === HttpStatusCode.NOT_FOUND_404) { | 28 | if (videoResponse?.status === HttpStatusCode.NOT_FOUND_404) { |
28 | throw new Error('This video does not exist.') | 29 | throw new Error('This video does not exist.') |
29 | } | 30 | } |
30 | 31 | if (videoResponse?.status === HttpStatusCode.FORBIDDEN_403) { | |
32 | const res = await videoResponse.json() | ||
33 | throw new PeerTubeServerError(res.message, res.code) | ||
34 | } | ||
31 | throw new Error('We cannot fetch the video. Please try again later.') | 35 | throw new Error('We cannot fetch the video. Please try again later.') |
32 | } | 36 | } |
33 | 37 | ||
34 | const captionsPromise = this.loadVideoCaptions(videoId) | 38 | const captionsPromise = this.loadVideoCaptions({ videoId, videoPassword }) |
35 | 39 | ||
36 | return { captionsPromise, videoResponse } | 40 | return { captionsPromise, videoResponse } |
37 | } | 41 | } |
@@ -41,8 +45,8 @@ export class VideoFetcher { | |||
41 | .then(res => res.json() as Promise<LiveVideo>) | 45 | .then(res => res.json() as Promise<LiveVideo>) |
42 | } | 46 | } |
43 | 47 | ||
44 | loadVideoToken (video: VideoDetails) { | 48 | loadVideoToken (video: VideoDetails, videoPassword?: string) { |
45 | return this.http.fetch(this.getVideoTokenUrl(video.uuid), { optionalAuth: true, method: 'POST' }) | 49 | return this.http.fetch(this.getVideoTokenUrl(video.uuid), { optionalAuth: true, method: 'POST' }, videoPassword) |
46 | .then(res => res.json() as Promise<VideoToken>) | 50 | .then(res => res.json() as Promise<VideoToken>) |
47 | .then(token => token.files.token) | 51 | .then(token => token.files.token) |
48 | } | 52 | } |
@@ -51,12 +55,12 @@ export class VideoFetcher { | |||
51 | return this.getVideoUrl(videoUUID) + '/views' | 55 | return this.getVideoUrl(videoUUID) + '/views' |
52 | } | 56 | } |
53 | 57 | ||
54 | private loadVideoInfo (videoId: string): Promise<Response> { | 58 | private loadVideoInfo ({ videoId, videoPassword }: { videoId: string, videoPassword?: string }): Promise<Response> { |
55 | return this.http.fetch(this.getVideoUrl(videoId), { optionalAuth: true }) | 59 | return this.http.fetch(this.getVideoUrl(videoId), { optionalAuth: true }, videoPassword) |
56 | } | 60 | } |
57 | 61 | ||
58 | private loadVideoCaptions (videoId: string): Promise<Response> { | 62 | private loadVideoCaptions ({ videoId, videoPassword }: { videoId: string, videoPassword?: string }): Promise<Response> { |
59 | return this.http.fetch(this.getVideoUrl(videoId) + '/captions', { optionalAuth: true }) | 63 | return this.http.fetch(this.getVideoUrl(videoId) + '/captions', { optionalAuth: true }, videoPassword) |
60 | } | 64 | } |
61 | 65 | ||
62 | private getVideoUrl (id: string) { | 66 | private getVideoUrl (id: string) { |