From 5d165ebb61d876e7696d9b46d07256920df5f63d Mon Sep 17 00:00:00 2001 From: LuanRT Date: Sat, 18 Dec 2021 00:16:47 -0300 Subject: [PATCH] refactor: move all internal actions to Actions.js for better maintainability --- lib/Actions.js | 14 ++++++++++++-- lib/Innertube.js | 34 +++++++++++++--------------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/lib/Actions.js b/lib/Actions.js index 87ef565a..3a64c009 100644 --- a/lib/Actions.js +++ b/lib/Actions.js @@ -121,7 +121,6 @@ async function notifications(session, action_type, args = {}) { const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/notification/${action_type}${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.INNERTUBE_REQOPTS({ session })).catch((error) => error); - if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message }; if (action_type === 'modify_channel_preference') return { success: true, status_code: response.status }; @@ -170,6 +169,17 @@ async function livechat(session, action_type, args = {}) { }; } +async function getVideoInfo(session, args = {}) { + let response; + + !args.is_desktop && (response = await Axios.get(`${Constants.URLS.YT_WATCH_PAGE}?v=${args.id}&t=8s&pbj=1`, Constants.INNERTUBE_REQOPTS({ session, id: args.id, desktop: false })).catch((error) => error)) || + (response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/player${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, + JSON.stringify(Constants.VIDEO_INFO_REQBODY(args.id, session.sts, session.context)), Constants.INNERTUBE_REQOPTS({ session, id: args.id, desktop: true })).catch((error) => error)); + if (response instanceof Error) throw new Error(`Could not get video info: ${response.message}`); + + return response.data; +} + async function getContinuation(session, info = {}) { let data = { context: session.context }; info.continuation_token && (data.continuation = info.continuation_token); @@ -197,4 +207,4 @@ async function getContinuation(session, info = {}) { }; } -module.exports = { engage, browse, search, notifications, livechat, getContinuation }; \ No newline at end of file +module.exports = { engage, browse, search, notifications, livechat, getVideoInfo, getContinuation }; \ No newline at end of file diff --git a/lib/Innertube.js b/lib/Innertube.js index cacc59aa..746d240c 100644 --- a/lib/Innertube.js +++ b/lib/Innertube.js @@ -75,16 +75,16 @@ class Innertube extends EventEmitter { this.access_token = data.access_token; this.refresh_token = credentials.refresh_token; this.logged_in = true; - + const expiration_date = new Date(new Date().getTime() + data.expires * 1000); - + this.emit('update-credentials', { access_token: data.access_token, refresh_token: credentials.refresh_token, expires: expiration_date, status: data.status }); - + resolve(); }); } @@ -94,16 +94,16 @@ class Innertube extends EventEmitter { this.access_token = data.access_token; this.refresh_token = data.refresh_token; this.logged_in = true; - + const expiration_date = new Date(new Date().getTime() + data.expires * 1000); - + this.emit('auth', { access_token: data.access_token, refresh_token: data.refresh_token, expires: expiration_date, status: data.status }); - + resolve(); } else { this.emit('auth', data); @@ -116,7 +116,7 @@ class Innertube extends EventEmitter { async search(query, options = { period: 'any', order: 'relevance', duration: 'any' }) { const response = await Actions.search(this, { query, options }); if (!response.success) throw new Error(`Could not search on YouTube: ${response.message}`); - + let content = response.data.contents.twoColumnSearchResultsRenderer.primaryContents.sectionListRenderer.contents[0].itemSectionRenderer.contents; let search_response = {}; @@ -158,7 +158,7 @@ class Innertube extends EventEmitter { async getDetails(id) { if (!id) throw new Error('You must provide a video id'); - const data = await this.requestVideoInfo(id, false); + const data = await Actions.getVideoInfo(this, { id, is_desktop: false }); const video_data = Constants.formatVideoData(data, this, false); if (video_data.metadata.is_live_content) { @@ -295,14 +295,6 @@ class Innertube extends EventEmitter { return response.data.unseenCount; } - async requestVideoInfo(id, desktop) { - let response; - !desktop && (response = await Axios.get(`${Constants.URLS.YT_WATCH_PAGE}?v=${id}&t=8s&pbj=1`, Constants.INNERTUBE_REQOPTS({ session: this, id, desktop: false })).catch((error) => error)) || - (response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/player${this.logged_in && this.cookie.length < 1 ? '' : `?key=${this.key}`}`, JSON.stringify(Constants.VIDEO_INFO_REQBODY(id, this.sts, this.context)), Constants.INNERTUBE_REQOPTS({ session: this, id, desktop: true })).catch((error) => error)); - if (response instanceof Error) throw new Error('Could not retrieve watch page info: ' + response.message); - return response.data; - } - download(id, options = {}) { if (!id) throw new Error('Missing video id'); @@ -314,7 +306,7 @@ class Innertube extends EventEmitter { let cancelled = false; const stream = new Stream.PassThrough(); - this.requestVideoInfo(id, true).then(async (video_data) => { + Actions.getVideoInfo(this, { id, is_desktop: true }).then(async (video_data) => { let formats = []; if (video_data.playabilityStatus.status === 'LOGIN_REQUIRED') return stream.emit('error', { message: 'You must login to download age-restricted videos.', error_type: 'LOGIN_REQUIRED', playability_status: video_data.playabilityStatus.status }); @@ -399,7 +391,7 @@ class Innertube extends EventEmitter { } let downloaded_size = 0; - + response.data.on('data', (chunk) => { downloaded_size += chunk.length; const size = (response.headers['content-length'] / 1024 / 1024).toFixed(2); @@ -408,14 +400,14 @@ class Innertube extends EventEmitter { }); response.data.on('error', (err) => { - cancelled && stream.emit('error', { message: 'The download was cancelled.', type: 'DOWNLOAD_CANCELLED' }) || - stream.emit('error', { message: err.message, type: 'DOWNLOAD_ABORTED' }); + cancelled && stream.emit('error', { message: 'The download was cancelled.', type: 'DOWNLOAD_CANCELLED' }) + || stream.emit('error', { message: err.message, type: 'DOWNLOAD_ABORTED' }); }); response.data.pipe(stream, { end: true }); } else { const chunk_size = 1048576 * 10; // 10MB - + let chunk_start = (options.range && options.range.start || 0); let chunk_end = (options.range && options.range.end || chunk_size); let downloaded_size = 0;