From b2117f11b90110b09acda145b4ecda1c19b6fb15 Mon Sep 17 00:00:00 2001 From: LuanRT Date: Mon, 25 Oct 2021 18:02:28 -0300 Subject: [PATCH] chore: add comments and format code --- lib/Actions.js | 15 ++++++--------- lib/Constants.js | 18 ++++++------------ lib/NToken.js | 18 ++++++++---------- lib/OAuth.js | 6 +++--- lib/Player.js | 11 +++++++---- lib/SigDecipher.js | 6 +++--- 6 files changed, 33 insertions(+), 41 deletions(-) diff --git a/lib/Actions.js b/lib/Actions.js index 2e5a69f4..3ffe5983 100644 --- a/lib/Actions.js +++ b/lib/Actions.js @@ -1,9 +1,9 @@ 'use strict'; +const Uuid = require('uuid'); const Axios = require('axios'); const Utils = require('./Utils'); const Constants = require('./Constants'); -const Uuid = require('uuid'); async function engage(session, engagement_type, args = {}) { if (!session.logged_in) throw new Error('You are not logged in'); @@ -56,7 +56,7 @@ async function browse(session, action_type) { break; default: } - + const response = await Axios.post(`${Constants.urls.YT_BASE_URL}/youtubei/v1/browse${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.innertube_request_opts({ session })).catch((error) => error); if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message }; return { @@ -104,11 +104,11 @@ async function notifications(session, action_type, args = {}) { async function livechat(session, action_type, args = {}) { let data; switch (action_type) { - case 'live_chat/send_message': + case 'live_chat/send_message': data = { context: session.context, params: Utils.generateMessageParams(args.channel_id, args.video_id), - clientMessageId: `INntLiB${Uuid.v4()}`, + clientMessageId: `ytjs-${Uuid.v4()}`, richMessage: { textSegments: [{ text: args.text }] } @@ -127,7 +127,7 @@ async function livechat(session, action_type, args = {}) { break; default: } - + const response = await Axios.post(`${Constants.urls.YT_BASE_URL}/youtubei/v1/${action_type}${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.innertube_request_opts({ session, params: args.params })).catch((error) => error); if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message }; return { @@ -139,10 +139,7 @@ async function livechat(session, action_type, args = {}) { async function getContinuation(session, info = {}) { let data = { context: session.context }; - - if (info.continuation_token) { - data.continuation = info.continuation_token; - } + info.continuation_token && (data.continuation = info.continuation_token); if (info.video_id) { data.videoId = info.video_id; diff --git a/lib/Constants.js b/lib/Constants.js index 2d4ce37e..98c724a0 100644 --- a/lib/Constants.js +++ b/lib/Constants.js @@ -20,7 +20,6 @@ const oauth_reqopts = { 'origin': urls.YT_BASE_URL, 'user-agent': 'Mozilla/5.0 (ChromiumStylePlatform) Cobalt/Version', 'content-type': 'application/json', - 'x-requested-with': 'mark.via.gp', 'referer': `${urls.YT_BASE_URL}/tv`, 'accept-language': 'en-US' } @@ -41,7 +40,7 @@ const default_headers = (session) => { }; const innertube_request_opts = (info) => { - if (info.desktop === undefined) info.desktop = true; + info.desktop === undefined && (info.desktop = true); let req_opts = { params: info.params || {}, headers: { @@ -58,16 +57,14 @@ const innertube_request_opts = (info) => { 'origin': info.desktop ? urls.YT_BASE_URL : urls.YT_MOBILE_URL, } }; + + info.id && (req_opts.headers.referer = (info.desktop ? urls.YT_BASE_URL : urls.YT_MOBILE_URL) + '/watch?v=' + info.id); if (info.session.logged_in && info.desktop) { req_opts.headers.Cookie = info.session.cookie; req_opts.headers.authorization = info.session.cookie.length < 1 ? `Bearer ${info.session.access_token}` : info.session.auth_apisid; } - if (info.id) { - req_opts.headers.referer = (info.desktop ? urls.YT_BASE_URL : urls.YT_MOBILE_URL) + '/watch?v=' + info.id; - } - return req_opts; }; @@ -100,9 +97,7 @@ const stream_headers = (range) => { 'Referer': urls.YT_BASE_URL, 'DNT': '?1' }; - if (range) { - headers.Range = range; - } + range && (headers.Range = range); return headers; }; @@ -175,14 +170,13 @@ const formatVideoData = (data, context, desktop) => { return video_details; }; - const base64_alphabet = { normal: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'.split(''), reverse: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_'.split('') }; -const filters = (order) => { - // TODO: Refactor this with protobuf encoding +const filters = (order) => { + // It seems like all of these are just proto buffers, so I think it'll be easy to refactor switch (order) { case 'any,any,relevance': return 'EgIQAQ%3D%3D'; diff --git a/lib/NToken.js b/lib/NToken.js index 111bec0c..060466e2 100644 --- a/lib/NToken.js +++ b/lib/NToken.js @@ -7,14 +7,14 @@ class NToken { constructor(raw_code) { this.raw_code = raw_code; this.null_placeholder_regex = /c\[(.*?)\]=c/g; - this.transformation_args_regex = /c\[(.*?)\]\((.+?)\)/g; + this.transformations_calls_rege = /c\[(.*?)\]\((.+?)\)/g; } transform(n) { let n_token = n.split(''); let transformations = this.getTransformationData(this.raw_code); - // Identifies the necessary transformation functions and emulates them accordingly. + // Identifies the necessary transformation data and emulates them accordingly. transformations = transformations.map((el) => { if (el != null && typeof el != 'number') { const is_reverse_base64 = el.includes('case 65:'); @@ -48,8 +48,8 @@ class NToken { null_placeholder_positions.forEach((pos) => transformations[pos] = transformations); // Parses and emulates calls to functions of the transformations array. - let transformation_args = [...Utils.getStringBetweenStrings(this.raw_code.replace(/\n/g, ''), 'try{', '}catch').matchAll(this.transformation_args_regex)].map((params) => ({ index: params[1], params: params[2] })); - transformation_args.forEach((data) => { + let transformation_calls = [...Utils.getStringBetweenStrings(this.raw_code.replace(/\n/g, ''), 'try{', '}catch').matchAll(this.transformations_calls_rege)].map((params) => ({ index: params[1], params: params[2] })); + transformation_calls.forEach((data) => { const index = data.index; const param_index = data.params.split(',').map((param) => param.match(/c\[(.*?)\]/)[1]); transformations[index](transformations[param_index[0]], transformations[param_index[1]]); @@ -59,7 +59,7 @@ class NToken { } getTransformationData() { - let transformation_data = '[' + Utils.getStringBetweenStrings(this.raw_code, 'c=[', '];c') + ']'; + let transformation_data = `[${Utils.getStringBetweenStrings(this.raw_code, 'c=[', '];c')}]`; transformation_data = transformation_data .replace(/function\(d,e\)/g, '"function(d,e)') .replace(/function\(d\)/g, '"function(d)') @@ -74,11 +74,11 @@ class NToken { return JSON.parse(transformation_data); } - translateAB(arr, e, is_reverse_base64) { + translateAB(arr, index, is_reverse_base64) { let characters = is_reverse_base64 && Constants.base64_alphabet.reverse || Constants.base64_alphabet.normal; arr.forEach(function(char, index, loc) { this.push(loc[index] = characters[(characters.indexOf(char) - characters.indexOf(this[index]) + 64) % characters.length]); - }, e.split('')); + }, index.split('')); } unshiftPop(arr, index) { @@ -97,9 +97,7 @@ class NToken { spliceReverseUnshift(arr, index) { index = (index % arr.length + arr.length) % arr.length; - arr.splice(-index).reverse().forEach(function(f) { - arr.unshift(f); - }); + arr.splice(-index).reverse().forEach((f) => arr.unshift(f)); } spliceOnce(arr, index) { diff --git a/lib/OAuth.js b/lib/OAuth.js index a5e5fa29..5f92bf36 100644 --- a/lib/OAuth.js +++ b/lib/OAuth.js @@ -119,13 +119,13 @@ class OAuth extends EventEmitter { async getClientIdentity() { // The first request is made to get the auth script url, hard-coding it isn't viable as it changes overtime. const yttv_response = await Axios.get(`${Constants.urls.YT_BASE_URL}/tv`, Constants.oauth_reqopts).catch((error) => error); - if (yttv_response instanceof Error) throw new Error(`Could not get identify: ${yttv_response.message}`); + if (yttv_response instanceof Error) throw new Error(`Could not extract client identify: ${yttv_response.message}`); // Here we get the script and extract the necessary data to proceed with the auth flow. const url_body = this.auth_script_regex.exec(yttv_response.data)[1]; const script_url = `${Constants.urls.YT_BASE_URL}/${url_body}`; const response = await Axios.get(script_url, Constants.default_headers).catch((error) => error); - if (response instanceof Error) throw new Error(`Could not fetch data from auth script: ${response.message}`); + if (response instanceof Error) throw new Error(`Could not extract client identify: ${response.message}`); const identity_function = Utils.getStringBetweenStrings(response.data, '=function(){var a=window.environment', '(function()'); const client_identity = identity_function.match(this.identity_regex).groups; @@ -145,7 +145,7 @@ class OAuth extends EventEmitter { const response = await Axios.post(this.oauth_token_url, JSON.stringify(data), Constants.oauth_reqopts).catch((error) => error); if (response instanceof Error) return this.emit('refresh-token', { - error: 'Could not refresh token.', + error: 'Could not refresh access token.', status: 'FAILED' }); diff --git a/lib/Player.js b/lib/Player.js index 92c5283d..912d107d 100644 --- a/lib/Player.js +++ b/lib/Player.js @@ -19,10 +19,13 @@ class Player { this.getNEncoder(player_data); } else { const response = await Axios.get(`${Constants.urls.YT_BASE_URL}${this.session.player_url}`, { path: this.session.playerUrl, headers: { 'content-type': 'text/javascript', 'user-agent': Utils.getRandomUserAgent('desktop').userAgent } }).catch((error) => error); - if (response instanceof Error) throw new Error('Could not get player data: ' + response.message); + if (response instanceof Error) throw new Error('Could not download player script: ' + response.message); - fs.mkdirSync(this.tmp_cache_dir, { recursive: true }); - fs.writeFileSync(`${this.tmp_cache_dir}/${this.player_name}.js`, response.data); + try { + // Caches the current player so we don't have to download it all the time + fs.mkdirSync(this.tmp_cache_dir, { recursive: true }); + fs.writeFileSync(`${this.tmp_cache_dir}/${this.player_name}.js`, response.data); + } catch (err) {} this.getSigDecipherCode(response.data); this.getNEncoder(response.data); @@ -36,7 +39,7 @@ class Player { } getNEncoder(data) { - this.ntoken_sc = 'var b=a.split("")' + Utils.getStringBetweenStrings(data, 'b=a.split("")', '}return b.join("")}') + '} return b.join("");'; + this.ntoken_sc = `var b=a.split("")${Utils.getStringBetweenStrings(data, 'b=a.split("")', '}return b.join("")}')}} return b.join("");`; } } diff --git a/lib/SigDecipher.js b/lib/SigDecipher.js index 751a5a8d..7621a4dc 100644 --- a/lib/SigDecipher.js +++ b/lib/SigDecipher.js @@ -20,10 +20,10 @@ class SigDecipher { arr.splice(0, end); } - function swap(arr, position) { + function swap(arr, index) { let origArrI = arr[0]; - arr[0] = arr[position % arr.length]; - arr[position % arr.length] = origArrI; + arr[0] = arr[index % arr.length]; + arr[index % arr.length] = origArrI; } function reverse(arr) {