diff --git a/src/Innertube.ts b/src/Innertube.ts index b5c2cda8f..6d1907d82 100644 --- a/src/Innertube.ts +++ b/src/Innertube.ts @@ -85,32 +85,34 @@ export default class Innertube { const watch_endpoint = new NavigationEndpoint({ watchEndpoint: payload }); const watch_next_endpoint = new NavigationEndpoint({ watchNextEndpoint: payload }); + const session = this.#session; + const extra_payload: Record = { playbackContext: { contentPlaybackContext: { vis: 0, splay: false, lactMilliseconds: '-1', - signatureTimestamp: this.#session.player?.sts + signatureTimestamp: session.player?.sts } }, client }; - if (this.#session.po_token) { + if (session.po_token) { extra_payload.serviceIntegrityDimensions = { - poToken: this.#session.po_token + poToken: session.po_token }; } - const watch_response = watch_endpoint.call(this.#session.actions, extra_payload); - const watch_next_response = watch_next_endpoint.call(this.#session.actions); + const watch_response = watch_endpoint.call(session.actions, extra_payload); + const watch_next_response = watch_next_endpoint.call(session.actions); const response = await Promise.all([ watch_response, watch_next_response ]); const cpn = generateRandomString(16); - return new VideoInfo(response, this.actions, cpn); + return new VideoInfo(response, session.actions, cpn); } async getBasicInfo(video_id: string, client?: InnerTubeClient): Promise { @@ -118,29 +120,31 @@ export default class Innertube { const watch_endpoint = new NavigationEndpoint({ watchEndpoint: { videoId: video_id } }); + const session = this.#session; + const extra_payload: Record = { playbackContext: { contentPlaybackContext: { vis: 0, splay: false, lactMilliseconds: '-1', - signatureTimestamp: this.#session.player?.sts + signatureTimestamp: session.player?.sts } }, client }; - if (this.#session.po_token) { + if (session.po_token) { extra_payload.serviceIntegrityDimensions = { - poToken: this.#session.po_token + poToken: session.po_token }; } - const watch_response = await watch_endpoint.call(this.#session.actions, extra_payload); + const watch_response = await watch_endpoint.call(session.actions, extra_payload); const cpn = generateRandomString(16); - return new VideoInfo([ watch_response ], this.actions, cpn); + return new VideoInfo([ watch_response ], session.actions, cpn); } async getShortsVideoInfo(video_id: string, client?: InnerTubeClient): Promise { @@ -154,7 +158,9 @@ export default class Innertube { } }); - const reel_watch_response = reel_watch_endpoint.call(this.#session.actions, { client }); + const actions = this.#session.actions; + + const reel_watch_response = reel_watch_endpoint.call(actions, { client }); const writer = ReelSequence.encode({ shortId: video_id, @@ -167,13 +173,13 @@ export default class Innertube { const params = encodeURIComponent(u8ToBase64(writer.finish())); - const sequence_response = this.actions.execute('/reel/reel_watch_sequence', { sequenceParams: params }); + const sequence_response = actions.execute('/reel/reel_watch_sequence', { sequenceParams: params }); const response = await Promise.all([ reel_watch_response, sequence_response ]); const cpn = generateRandomString(16); - return new ShortFormVideoInfo([ response[0] ], this.actions, cpn, response[1]); + return new ShortFormVideoInfo([ response[0] ], actions, cpn, response[1]); } async search(query: string, filters: SearchFilters = {}): Promise { @@ -253,6 +259,8 @@ export default class Innertube { } async getSearchSuggestions(query: string, previous_query?: string): Promise { + const session = this.#session; + const url = new URL(`${Constants.URLS.YT_SUGGESTIONS}/complete/search`); url.searchParams.set('client', 'youtube'); url.searchParams.set('gs_ri', 'youtube'); @@ -260,16 +268,16 @@ export default class Innertube { url.searchParams.set('cp', '0'); url.searchParams.set('ds', 'yt'); url.searchParams.set('sugexp', Constants.CLIENTS.WEB.SUGG_EXP_ID); - url.searchParams.set('hl', this.#session.context.client.hl); - url.searchParams.set('gl', this.#session.context.client.gl); + url.searchParams.set('hl', session.context.client.hl); + url.searchParams.set('gl', session.context.client.gl); url.searchParams.set('q', query); if (previous_query) url.searchParams.set('pq', previous_query); - const response = await this.#session.http.fetch_function(url, { + const response = await session.http.fetch_function(url, { headers: { - 'Cookie': this.#session.cookie || '' + 'Cookie': session.cookie || '' } }); diff --git a/src/core/clients/Kids.ts b/src/core/clients/Kids.ts index a0fdad929..372e6949c 100644 --- a/src/core/clients/Kids.ts +++ b/src/core/clients/Kids.ts @@ -24,32 +24,34 @@ export default class Kids { const watch_endpoint = new NavigationEndpoint({ watchEndpoint: payload }); const watch_next_endpoint = new NavigationEndpoint({ watchNextEndpoint: payload }); + const session = this.#session; + const extra_payload: Record = { playbackContext: { contentPlaybackContext: { vis: 0, splay: false, lactMilliseconds: '-1', - signatureTimestamp: this.#session.player?.sts + signatureTimestamp: session.player?.sts } }, client: 'YTKIDS' }; - if (this.#session.po_token) { + if (session.po_token) { extra_payload.serviceIntegrityDimensions = { - poToken: this.#session.po_token + poToken: session.po_token }; } - const watch_response = watch_endpoint.call(this.#session.actions, extra_payload); + const watch_response = watch_endpoint.call(session.actions, extra_payload); - const watch_next_response = watch_next_endpoint.call(this.#session.actions, { client: 'YTKIDS' }); + const watch_next_response = watch_next_endpoint.call(session.actions, { client: 'YTKIDS' }); const response = await Promise.all([ watch_response, watch_next_response ]); const cpn = generateRandomString(16); - return new VideoInfo(response, this.#session.actions, cpn); + return new VideoInfo(response, session.actions, cpn); } async getChannel(channel_id: string): Promise { @@ -71,7 +73,9 @@ export default class Kids { * @returns A list of API responses. */ async blockChannel(channel_id: string): Promise { - if (!this.#session.logged_in) + const session = this.#session; + + if (!session.logged_in) throw new InnertubeError('You must be signed in to perform this operation.'); const kids_blocklist_picker_command = new NavigationEndpoint({ @@ -82,7 +86,7 @@ export default class Kids { } }); - const response = await kids_blocklist_picker_command.call(this.#session.actions, { client: 'YTKIDS' }); + const response = await kids_blocklist_picker_command.call(session.actions, { client: 'YTKIDS' }); const popup = response.data.command.confirmDialogEndpoint; const popup_fragment = { contents: popup.content, engagementPanels: [] }; const kid_picker = Parser.parseResponse(popup_fragment); @@ -96,7 +100,7 @@ export default class Kids { for (const kid of kids) { if (!kid.block_button?.is_toggled) { - kid.setActions(this.#session.actions); + kid.setActions(session.actions); // Block channel and add to the response list. responses.push(await kid.blockChannel()); } diff --git a/src/core/clients/Studio.ts b/src/core/clients/Studio.ts index e93f6dcb5..dcc53b52d 100644 --- a/src/core/clients/Studio.ts +++ b/src/core/clients/Studio.ts @@ -45,7 +45,9 @@ export default class Studio { * ``` */ async updateVideoMetadata(video_id: string, metadata: UpdateVideoMetadataOptions): Promise { - if (!this.#session.logged_in) + const session = this.#session; + + if (!session.logged_in) throw new InnertubeError('You must be signed in to perform this operation.'); const payload: MetadataUpdateRequest = { @@ -55,18 +57,18 @@ export default class Studio { clientName: parseInt(Constants.CLIENT_NAME_IDS.ANDROID), clientVersion: Constants.CLIENTS.ANDROID.VERSION, androidSdkVersion: Constants.CLIENTS.ANDROID.SDK_VERSION, - visitorData: this.#session.context.client.visitorData, + visitorData: session.context.client.visitorData, osVersion: '13', - acceptLanguage: this.#session.context.client.hl, - acceptRegion: this.#session.context.client.gl, + acceptLanguage: session.context.client.hl, + acceptRegion: session.context.client.gl, deviceMake: 'Google', deviceModel: 'sdk_gphone64_x86_64', screenHeightPoints: 840, screenWidthPoints: 432, configInfo: { - appInstallData: this.#session.context.client.configInfo?.appInstallData + appInstallData: session.context.client.configInfo?.appInstallData }, - timeZone: this.#session.context.client.timeZone, + timeZone: session.context.client.timeZone, chipset: 'qcom;taro' }, activePlayers: [] @@ -131,7 +133,7 @@ export default class Studio { const writer = MetadataUpdateRequest.encode(payload); - return await this.#session.actions.execute('/video_manager/metadata_update', { + return await session.actions.execute('/video_manager/metadata_update', { protobuf: true, serialized_data: writer.finish() }); diff --git a/src/utils/HTTPClient.ts b/src/utils/HTTPClient.ts index 0957b45ab..ef3887a82 100644 --- a/src/utils/HTTPClient.ts +++ b/src/utils/HTTPClient.ts @@ -33,7 +33,9 @@ export default class HTTPClient { input: URL | Request | string, init?: RequestInit & HTTPClientInit ): Promise { - const innertube_url = Constants.URLS.API.PRODUCTION_1 + this.#session.api_version; + const session = this.#session; + + const innertube_url = Constants.URLS.API.PRODUCTION_1 + session.api_version; const baseURL = init?.baseURL || innertube_url; const request_url = @@ -55,17 +57,17 @@ export default class HTTPClient { request_headers.set('Accept', '*/*'); request_headers.set('Accept-Language', '*'); - request_headers.set('X-Goog-Visitor-Id', this.#session.context.client.visitorData || ''); - request_headers.set('X-Youtube-Client-Version', this.#session.context.client.clientVersion || ''); + request_headers.set('X-Goog-Visitor-Id', session.context.client.visitorData || ''); + request_headers.set('X-Youtube-Client-Version', session.context.client.clientVersion || ''); - const client_name_id = Constants.CLIENT_NAME_IDS[this.#session.context.client.clientName as keyof typeof Constants.CLIENT_NAME_IDS]; + const client_name_id = Constants.CLIENT_NAME_IDS[session.context.client.clientName as keyof typeof Constants.CLIENT_NAME_IDS]; if (client_name_id) { request_headers.set('X-Youtube-Client-Name', client_name_id); } if (Platform.shim.server) { - request_headers.set('User-Agent', this.#session.user_agent || ''); + request_headers.set('User-Agent', session.user_agent || ''); request_headers.set('Origin', request_url.origin); } @@ -88,7 +90,7 @@ export default class HTTPClient { const n_body = { ...json, // Deep copy since we're going to be modifying it - context: JSON.parse(JSON.stringify(this.#session.context)) as Context + context: JSON.parse(JSON.stringify(session.context)) as Context }; this.#adjustContext(n_body.context, n_body.client); @@ -121,8 +123,8 @@ export default class HTTPClient { } // Authenticate (NOTE: YouTube Kids does not support regular bearer tokens) - if (this.#session.logged_in && is_innertube_req && !is_web_kids) { - const oauth = this.#session.oauth; + if (session.logged_in && is_innertube_req && !is_web_kids) { + const oauth = session.oauth; if (oauth.oauth2_tokens) { if (oauth.shouldRefreshToken()) { @@ -132,17 +134,19 @@ export default class HTTPClient { request_headers.set('Authorization', `Bearer ${oauth.oauth2_tokens.access_token}`); } - if (this.#cookie) { - const sapisid = getCookie(this.#cookie, 'SAPISID'); + const cookie = this.#cookie; + + if (cookie) { + const sapisid = getCookie(cookie, 'SAPISID'); if (sapisid) { request_headers.set('Authorization', await generateSidAuth(sapisid)); - request_headers.set('X-Goog-Authuser', this.#session.account_index.toString()); - if (this.#session.context.user.onBehalfOfUser) - request_headers.set('X-Goog-PageId', this.#session.context.user.onBehalfOfUser); + request_headers.set('X-Goog-Authuser', session.account_index.toString()); + if (session.context.user.onBehalfOfUser) + request_headers.set('X-Goog-PageId', session.context.user.onBehalfOfUser); } - request_headers.set('Cookie', this.#cookie); + request_headers.set('Cookie', cookie); } }