diff --git a/lib/Actions.js b/lib/Actions.js index 29108c8f..87ef565a 100644 --- a/lib/Actions.js +++ b/lib/Actions.js @@ -7,7 +7,8 @@ const Constants = require('./Constants'); async function engage(session, engagement_type, args = {}) { if (!session.logged_in) throw new Error('You are not logged in'); - let data = {}; + + let data; switch (engagement_type) { case 'like/like': case 'like/dislike': @@ -36,8 +37,11 @@ async function engage(session, engagement_type, args = {}) { default: } - const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/${engagement_type}${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.INNERTUBE_REQOPTS({ session, id: args.video_id, data })).catch((error) => error); + const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/${engagement_type}${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, + JSON.stringify(data), Constants.INNERTUBE_REQOPTS({ session, id: args.video_id, data })).catch((error) => error); + if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message }; + return { success: true, status_code: response.status @@ -46,8 +50,9 @@ async function engage(session, engagement_type, args = {}) { async function browse(session, action_type) { if (!session.logged_in) throw new Error('You are not logged in'); + let data; - switch (action_type) { + switch (action_type) { // TODO: Handle more actions case 'subscriptions_feed': data = { context: session.context, @@ -57,8 +62,29 @@ async function browse(session, action_type) { 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_REQOPTS({ session })).catch((error) => error); + 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_REQOPTS({ session })).catch((error) => error); + if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message }; + + return { + success: true, + status_code: response.status, + data: response.data + }; +} + +async function search(session, args = {}) { + if (!args.query) throw new Error('No query was provided'); + + const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/search${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, + JSON.stringify({ + context: session.context, + params: Utils.encodeFilter(args.options.period, args.options.duration, args.options.order), + query: args.query + }), Constants.INNERTUBE_REQOPTS({ session })).catch((error) => error); + if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message }; + return { success: true, status_code: response.status, @@ -68,7 +94,9 @@ async function browse(session, action_type) { async function notifications(session, action_type, args = {}) { if (!session.logged_in) throw new Error('You are not logged in'); + let data; + switch (action_type) { case 'modify_channel_preference': let pref_types = { PERSONALIZED: 1, ALL: 2, NONE: 3 }; @@ -91,9 +119,12 @@ async function notifications(session, action_type, args = {}) { default: } - 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); + 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 }; + return { success: true, status_code: response.status, @@ -128,8 +159,10 @@ async function livechat(session, action_type, args = {}) { 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_REQOPTS({ session, params: args.params })).catch((error) => error); + 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_REQOPTS({ session, params: args.params })).catch((error) => error); if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message }; + return { success: true, status_code: response.status, @@ -153,8 +186,10 @@ async function getContinuation(session, info = {}) { data.captionsRequested = false; } - const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/next${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.INNERTUBE_REQOPTS({ session })).catch((error) => error); + const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/next${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 }; + return { success: true, status_code: response.status, @@ -162,4 +197,4 @@ async function getContinuation(session, info = {}) { }; } -module.exports = { engage, browse, notifications, livechat, getContinuation }; \ No newline at end of file +module.exports = { engage, browse, search, notifications, livechat, getContinuation }; \ No newline at end of file diff --git a/lib/Innertube.js b/lib/Innertube.js index 2f8ba4db..cacc59aa 100644 --- a/lib/Innertube.js +++ b/lib/Innertube.js @@ -114,10 +114,8 @@ class Innertube extends EventEmitter { } async search(query, options = { period: 'any', order: 'relevance', duration: 'any' }) { - if (!query) throw new Error('No query was provided'); - - const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/search${this.logged_in && this.cookie.length < 1 ? '' : `?key=${this.key}`}`, JSON.stringify({ context: this.context, params: Utils.encodeFilter(options.period, options.duration, options.order), query }), Constants.INNERTUBE_REQOPTS({ session: this })).catch((error) => error); - if (response instanceof Error) throw new Error(`Could not search on YouTube: ${response.message}`); + 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 +156,7 @@ class Innertube extends EventEmitter { } async getDetails(id) { - if (!id) return { error: 'Missing video id' }; + if (!id) throw new Error('You must provide a video id'); const data = await this.requestVideoInfo(id, false); const video_data = Constants.formatVideoData(data, this, false); @@ -448,8 +446,11 @@ class Innertube extends EventEmitter { }); response.data.on('error', (err) => { - cancelled && stream.emit('error', { message: 'The download was cancelled.', type: 'DOWNLOAD_CANCELLED' }) || + if (cancelled) { + stream.emit('error', { message: 'The download was cancelled.', type: 'DOWNLOAD_CANCELLED' }); + } else { stream.emit('error', { message: err.message, type: 'DOWNLOAD_ABORTED' }); + } }); response.data.on('end', () => {