feat: implement pagination for all endpoints

This commit is contained in:
luan.lrt4@gmail.com
2022-04-04 13:52:59 -03:00
parent 60130f4d0f
commit c5eea2b4ff

View File

@@ -14,7 +14,7 @@ const Constants = require('./Constants');
* @returns {Promise.<{ success: boolean; status_code: number; data: object; message?: string }>}
*/
async function engage(session, engagement_type, args = {}) {
if (!session.logged_in) throw new Error('You are not signed-in');
if (!session.logged_in) throw new Error('You are not signed in');
const data = { context: session.context };
switch (engagement_type) {
@@ -46,6 +46,7 @@ async function engage(session, engagement_type, args = {}) {
data.actions = [ action ];
break;
default:
throw new Utils.InnertubeError('Invalid action', action);
}
const response = await session.YTRequester.post(`/${engagement_type}`, JSON.stringify(data)).catch((error) => error);
@@ -61,18 +62,18 @@ async function engage(session, engagement_type, args = {}) {
* Accesses YouTube's various sections.
*
* @param {Innertube} session - A valid Innertube session.
* @param {string} action_type - Type of action.
* @param {string} action - Type of action.
* @param {object} args - Action argumenets.
* @returns {Promise.<{ success: boolean; status_code: number; data: object; message?: string }>}
*/
async function browse(session, action_type, args = {}) {
if (!session.logged_in && action_type != 'home_feed'
&& action_type !== 'lyrics' && action_type !== 'music_playlist'
&& action_type !== 'playlist')
throw new Error('You are not signed-in');
async function browse(session, action, args = {}) {
if (!session.logged_in && action != 'home_feed'
&& action !== 'lyrics' && action !== 'music_playlist'
&& action !== 'playlist')
throw new Error('You are not signed in');
const data = { context: session.context };
switch (action_type) {
switch (action) {
case 'account_notifications':
data.browseId = 'SPaccount_notifications';
break;
@@ -103,7 +104,11 @@ async function browse(session, action_type, args = {}) {
case 'playlist':
data.browseId = args.browse_id;
break;
case 'continuation':
data.continuation = args.ctoken;
break;
default:
throw new Utils.InnertubeError('Invalid action', action);
}
const requester = args.ytmusic && session.YTMRequester || session.YTRequester;
@@ -122,15 +127,15 @@ async function browse(session, action_type, args = {}) {
* Account settings endpoints.
*
* @param {Innertube} session - A valid Innertube session.
* @param {string} action_type - Type of action.
* @param {string} action - Type of action.
* @param {object} args - Action argumenets.
* @returns {Promise.<{ success: boolean; status_code: number; data: object; message?: string }>}
*/
async function account(session, action_type, args = {}) {
if (!session.logged_in) throw new Error('You are not signed-in');
async function account(session, action, args = {}) {
if (!session.logged_in) throw new Error('You are not signed in');
const data = {};
switch (action_type) {
switch (action) {
case 'account/account_menu':
data.context = session.context;
break;
@@ -140,9 +145,10 @@ async function account(session, action_type, args = {}) {
data.settingItemId = arts.setting_item_id;
break;
default:
throw new Utils.InnertubeError('Invalid action', action);
}
const response = await session.YTRequester.post(`/${action_type}`, JSON.stringify(data)).catch((error) => error);
const response = await session.YTRequester.post(`/${action}`, JSON.stringify(data)).catch((error) => error);
if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message };
return {
@@ -156,12 +162,12 @@ async function account(session, action_type, args = {}) {
* Accesses YouTube Music endpoints (/youtubei/v1/music/).
*
* @param {Innertube} session - A valid Innertube session.
* @param {string} action_type - Type of action.
* @param {string} action - Type of action.
* @param {object} args - Action arguments.
* @todo Implement more actions.
* @returns {Promise.<{ success: boolean; status_code: number; data: object; message?: string }>}
*/
async function music(session, action_type, args) {
async function music(session, action, args) {
const context = JSON.parse(JSON.stringify(session.context)); // deep copy the context obj so we don't accidentally change it
context.client.originalUrl = Constants.URLS.YT_MUSIC;
@@ -170,16 +176,16 @@ async function music(session, action_type, args) {
let data;
switch (action_type) {
switch (action) {
case 'get_search_suggestions':
data.context = context;
data.input = args.input || '';
break;
default:
break;
throw new Utils.InnertubeError('Invalid action', action);
}
const response = await session.YTMRequester.post(`/music/${action_type}`, JSON.stringify(data)).catch((error) => error);
const response = await session.YTMRequester.post(`/music/${action}`, JSON.stringify(data)).catch((error) => error);
if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message };
return {
@@ -198,13 +204,15 @@ async function music(session, action_type, args) {
* @returns {Promise.<{ success: boolean; status_code: number; data: object; message?: string }>}
*/
async function search(session, client, args = {}) {
if (!args.query) throw new Error('No query was provided');
const data = { context: session.context };
switch (client) {
case 'YOUTUBE':
data.params = Proto.encodeSearchFilter(args.options.period, args.options.duration, args.options.order);
data.query = args.query;
if (args.query) {
data.params = Proto.encodeSearchFilter(args.options.period, args.options.duration, args.options.order);
data.query = args.query;
} else {
data.continuation = args.ctoken;
}
break;
case 'YTMUSIC':
const context = JSON.parse(JSON.stringify(session.context)); // deep copy the context obj so we don't accidentally change it
@@ -217,7 +225,7 @@ async function search(session, client, args = {}) {
data.query = args.query;
break;
default:
break;
throw new Utils.InnertubeError('Invalid client', action);
}
const requester = client == 'YOUTUBE' && session.YTRequester || session.YTMRequester;
@@ -235,15 +243,15 @@ async function search(session, client, args = {}) {
* Interacts with YouTube's notification system.
*
* @param {Innertube} session - A valid Innertube session.
* @param {string} action_type - Type of action.
* @param {string} action - Type of action.
* @param {object} args - Action arguments.
* @returns {Promise.<{ success: boolean; status_code: number; data: object; message?: string }>}
*/
async function notifications(session, action_type, args = {}) {
if (!session.logged_in) throw new Error('You are not signed-in');
async function notifications(session, action, args = {}) {
if (!session.logged_in) throw new Error('You are not signed in');
const data = {};
switch (action_type) {
switch (action) {
case 'modify_channel_preference':
const pref_types = { PERSONALIZED: 1, ALL: 2, NONE: 3 };
data.context = session.context;
@@ -252,16 +260,18 @@ async function notifications(session, action_type, args = {}) {
case 'get_notification_menu':
data.context = session.context;
data.notificationsMenuRequestType = 'NOTIFICATIONS_MENU_REQUEST_TYPE_INBOX';
args.ctoken && (data.ctoken = args.ctoken);
break;
case 'get_unseen_count':
data.context = session.context;
break;
default:
throw new Utils.InnertubeError('Invalid action', action);
}
const response = await session.YTRequester.post(`/notification/${action_type}`, JSON.stringify(data)).catch((err) => err);
const response = await session.YTRequester.post(`/notification/${action}`, JSON.stringify(data)).catch((err) => err);
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 };
if (action === 'modify_channel_preference') return { success: true, status_code: response.status };
return {
success: true,
@@ -274,13 +284,13 @@ async function notifications(session, action_type, args = {}) {
* Interacts with YouTube's livechat system.
*
* @param {Innertube} session - A valid Innertube session.
* @param {string} action_type - Type of action.
* @param {string} action - Type of action.
* @param {object} args - Action arguments.
* @returns {Promise.<{ success: boolean; data: object; message?: string }>}
*/
async function livechat(session, action_type, args = {}) {
async function livechat(session, action, args = {}) {
const data = {};
switch (action_type) {
switch (action) {
case 'live_chat/get_live_chat':
data.context = session.context;
data.continuation = args.ctoken;
@@ -306,9 +316,10 @@ async function livechat(session, action_type, args = {}) {
args.continuation && (data.continuation = args.continuation);
break;
default:
throw new Utils.InnertubeError('Invalid action', action);
}
const response = await session.YTRequester.post(`/${action_type}`, JSON.stringify(data)).catch((err) => err);
const response = await session.YTRequester.post(`/${action}`, JSON.stringify(data)).catch((err) => err);
if (response instanceof Error) return { success: false, message: response.message };
return { success: true, data: response.data };