From e8ca24891990d3f63b2451f37e8701dea2c0b99d Mon Sep 17 00:00:00 2001 From: LuanRT Date: Fri, 7 Jan 2022 18:50:00 -0300 Subject: [PATCH] feat: add home feed support --- lib/Actions.js | 14 ++++++++------ lib/Innertube.js | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/lib/Actions.js b/lib/Actions.js index 46cd5c2d..6d84ccfb 100644 --- a/lib/Actions.js +++ b/lib/Actions.js @@ -68,6 +68,12 @@ async function browse(session, action_type) { let data; switch (action_type) { // TODO: Handle more actions + case 'home_feed': + data = { + context: session.context, + browseId: 'FEwhat_to_watch' + }; + break; case 'subscriptions_feed': data = { context: session.context, @@ -235,13 +241,9 @@ async function livechat(session, action_type, args = {}) { 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 }; + if (response instanceof Error) return { success: false, message: response.message }; - return { - success: true, - status_code: response.status, - data: response.data - }; + return { success: true, data: response.data }; } diff --git a/lib/Innertube.js b/lib/Innertube.js index 32496de1..38f4c77d 100644 --- a/lib/Innertube.js +++ b/lib/Innertube.js @@ -203,13 +203,43 @@ class Innertube { return comments_section; } + /** + * Returns YouTube's home feed. + * @returns {Promise} home feed. + */ + async getHomeFeed() { + const response = await Actions.browse(this, 'home_feed'); + if (!response.success) throw new Error('Could not get home feed'); + + const contents = response.data.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.richGridRenderer.contents; + + return contents.map((item) => { + const content = item.richItemRenderer && item.richItemRenderer.content.videoRenderer && + item.richItemRenderer.content || undefined; + + if (content) return { + id: content.videoRenderer.videoId, + title: content.videoRenderer.title.runs.map((run) => run.text).join(' '), + channel: content.videoRenderer.shortBylineText && content.videoRenderer.shortBylineText.runs[0].text || 'N/A', + metadata: { + view_count: content.videoRenderer.viewCountText && content.videoRenderer.viewCountText.simpleText || 'N/A', + thumbnail: content.videoRenderer.thumbnail && content.videoRenderer.thumbnail.thumbnails.slice(-1)[0] || [], + moving_thumbnail: content.videoRenderer.richThumbnail && content.videoRenderer.richThumbnail.movingThumbnailRenderer.movingThumbnailDetails.thumbnails[0] || [], + published: content.videoRenderer.publishedTimeText && content.videoRenderer.publishedTimeText.simpleText || 'N/A', + badges: content.videoRenderer.badges && content.videoRenderer.badges.map((badge) => badge.metadataBadgeRenderer.label) || 'N/A', + owner_badges: content.videoRenderer.ownerBadges && content.videoRenderer.ownerBadges.map((badge) => badge.metadataBadgeRenderer.tooltip) || 'N/A' + } + } + }).filter((video) => video); + } + /** * Returns your subscription feed. * @returns {Promise} subs feed. */ async getSubscriptionsFeed() { const response = await Actions.browse(this, 'subscriptions_feed'); - if (!response.success) throw new Error('Could not fetch subscriptions feed'); + if (!response.success) throw new Error('Could not get subscriptions feed'); const contents = response.data.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.sectionListRenderer.contents; const subscriptions_feed = {}; @@ -219,18 +249,18 @@ class Innertube { const section_contents = section.itemSectionRenderer.contents[0]; const section_items = section_contents.shelfRenderer.content.gridRenderer.items; - + const key = section_contents.shelfRenderer.title.runs[0].text; subscriptions_feed[key.toLowerCase().replace(/ +/g, '_')] = []; section_items.forEach((item) => { const content = { - title: item.gridVideoRenderer.title.runs.map((run) => run.text).join(' '), id: item.gridVideoRenderer.videoId, + title: item.gridVideoRenderer.title.runs.map((run) => run.text).join(' '), channel: item.gridVideoRenderer.shortBylineText && item.gridVideoRenderer.shortBylineText.runs[0].text || 'N/A', metadata: { view_count: item.gridVideoRenderer.viewCountText && item.gridVideoRenderer.viewCountText.simpleText || 'N/A', - thumbnail: item.gridVideoRenderer.thumbnail && item.gridVideoRenderer.thumbnail.thumbnails || [], + thumbnail: item.gridVideoRenderer.thumbnail && item.gridVideoRenderer.thumbnail.thumbnails.slice(-1)[0] || [], published: item.gridVideoRenderer.publishedTimeText && item.gridVideoRenderer.publishedTimeText.simpleText || 'N/A', badges: item.gridVideoRenderer.badges && item.gridVideoRenderer.badges.map((badge) => badge.metadataBadgeRenderer.label) || 'N/A', owner_badges: item.gridVideoRenderer.ownerBadges && item.gridVideoRenderer.ownerBadges.map((badge) => badge.metadataBadgeRenderer.tooltip) || 'N/A'