From 9978ebf08582fe299b35c0b0b3b123d32f2d8faa Mon Sep 17 00:00:00 2001 From: LuanRT Date: Sat, 17 Dec 2022 00:54:08 -0300 Subject: [PATCH] refactor(Parser): reduce reliance on localised strings (#258) --- src/core/Music.ts | 31 ++++---------- src/core/TabbedFeed.ts | 17 ++++++-- src/parser/classes/C4TabbedHeader.ts | 41 ++++++++++++------- .../classes/ChannelAboutFullMetadata.ts | 26 ++++++++++-- src/parser/classes/SectionList.ts | 2 +- src/parser/helpers.ts | 12 ++++++ src/parser/youtube/Channel.ts | 19 +++++---- src/parser/youtube/Search.ts | 2 +- src/parser/youtube/Settings.ts | 2 +- src/parser/youtube/TimeWatched.ts | 2 +- src/parser/ytmusic/Explore.ts | 4 +- src/parser/ytmusic/HomeFeed.ts | 2 +- src/parser/ytmusic/Library.ts | 2 +- src/parser/ytmusic/Playlist.ts | 16 +++----- src/parser/ytmusic/Recap.ts | 2 +- src/parser/ytmusic/Search.ts | 2 +- src/parser/ytmusic/TrackInfo.ts | 20 ++++----- 17 files changed, 117 insertions(+), 85 deletions(-) diff --git a/src/core/Music.ts b/src/core/Music.ts index 41e83bd5..5c3d69d6 100644 --- a/src/core/Music.ts +++ b/src/core/Music.ts @@ -11,9 +11,6 @@ import Playlist from '../parser/ytmusic/Playlist'; import Recap from '../parser/ytmusic/Recap'; import Tab from '../parser/classes/Tab'; -import Tabbed from '../parser/classes/Tabbed'; -import SingleColumnMusicWatchNextResults from '../parser/classes/SingleColumnMusicWatchNextResults'; -import WatchNextTabbedResults from '../parser/classes/WatchNextTabbedResults'; import SectionList from '../parser/classes/SectionList'; import Message from '../parser/classes/Message'; @@ -235,13 +232,9 @@ class Music { parse: true }); - const tabs = data.contents.item() - .as(SingleColumnMusicWatchNextResults).contents.item() - .as(Tabbed).contents.item() - .as(WatchNextTabbedResults) - .tabs.array().as(Tab); + const tabs = data.contents_memo.getType(Tab); - const tab = tabs.get({ title: 'Up next' }); + const tab = tabs?.[0]; if (!tab) throw new InnertubeError('Could not find target tab.'); @@ -287,20 +280,16 @@ class Music { parse: true }); - const tabs = data.contents.item() - .as(SingleColumnMusicWatchNextResults).contents.item() - .as(Tabbed).contents.item() - .as(WatchNextTabbedResults) - .tabs.array().as(Tab); + const tabs = data.contents_memo.getType(Tab); - const tab = tabs.get({ title: 'Related' }); + const tab = tabs?.matchCondition((tab) => tab.endpoint.payload.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType === 'MUSIC_PAGE_TYPE_TRACK_RELATED'); if (!tab) throw new InnertubeError('Could not find target tab.'); const page = await tab.endpoint.call(this.#actions, { client: 'YTMUSIC', parse: true }); - const shelves = page.contents.item().as(SectionList).contents.array().as(MusicCarouselShelf, MusicDescriptionShelf); + const shelves = page.contents.item().as(SectionList).contents.as(MusicCarouselShelf, MusicDescriptionShelf); return shelves; } @@ -318,13 +307,9 @@ class Music { parse: true }); - const tabs = data.contents.item() - .as(SingleColumnMusicWatchNextResults).contents.item() - .as(Tabbed).contents.item() - .as(WatchNextTabbedResults) - .tabs.array().as(Tab); + const tabs = data.contents_memo.getType(Tab); - const tab = tabs.get({ title: 'Lyrics' }); + const tab = tabs?.matchCondition((tab) => tab.endpoint.payload.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType === 'MUSIC_PAGE_TYPE_TRACK_LYRICS'); if (!tab) throw new InnertubeError('Could not find target tab.'); @@ -334,7 +319,7 @@ class Music { if (page.contents.item().key('type').string() === 'Message') throw new InnertubeError(page.contents.item().as(Message).text, video_id); - const section_list = page.contents.item().as(SectionList).contents.array(); + const section_list = page.contents.item().as(SectionList).contents; return section_list.firstOfType(MusicDescriptionShelf); } diff --git a/src/core/TabbedFeed.ts b/src/core/TabbedFeed.ts index 8c53d6ff..ceda6b24 100644 --- a/src/core/TabbedFeed.ts +++ b/src/core/TabbedFeed.ts @@ -17,7 +17,7 @@ class TabbedFeed extends Feed { return this.#tabs.map((tab) => tab.title.toString()); } - async getTab(title: string) { + async getTabByName(title: string) { const tab = this.#tabs.find((tab) => tab.title.toLowerCase() === title.toLowerCase()); if (!tab) @@ -28,8 +28,19 @@ class TabbedFeed extends Feed { const response = await tab.endpoint.call(this.#actions); - if (!response) - throw new InnertubeError('Failed to call endpoint'); + return new TabbedFeed(this.#actions, response.data, false); + } + + async getTabByURL(url: string) { + const tab = this.#tabs.find((tab) => tab.endpoint.metadata.url?.split('/').pop() === url); + + if (!tab) + throw new InnertubeError(`Tab "${url}" not found`); + + if (tab.selected) + return this; + + const response = await tab.endpoint.call(this.#actions); return new TabbedFeed(this.#actions, response.data, false); } diff --git a/src/parser/classes/C4TabbedHeader.ts b/src/parser/classes/C4TabbedHeader.ts index fa246ea1..899cb7dc 100644 --- a/src/parser/classes/C4TabbedHeader.ts +++ b/src/parser/classes/C4TabbedHeader.ts @@ -1,20 +1,28 @@ import Parser from '../index'; import Author from './misc/Author'; -import Thumbnail from './misc/Thumbnail'; import Text from './misc/Text'; +import Thumbnail from './misc/Thumbnail'; + +import type Button from './Button'; +import type ChannelHeaderLinks from './ChannelHeaderLinks'; +import type SubscribeButton from './SubscribeButton'; + import { YTNode } from '../helpers'; class C4TabbedHeader extends YTNode { static type = 'C4TabbedHeader'; - author; - banner; - tv_banner; - mobile_banner; - subscribers; - sponsor_button; - subscribe_button; - header_links; + author: Author; + banner: Thumbnail[]; + tv_banner: Thumbnail[]; + mobile_banner: Thumbnail[]; + subscribers: Text; + videos_count: Text; + sponsor_button: Button | null; + subscribe_button: SubscribeButton | null; + header_links: ChannelHeaderLinks | null; + channel_handle: Text; + channel_id: string; constructor(data: any) { super(); @@ -23,13 +31,16 @@ class C4TabbedHeader extends YTNode { navigationEndpoint: data.navigationEndpoint }, data.badges, data.avatar); - this.banner = data.banner ? Thumbnail.fromResponse(data.banner) : []; - this.tv_banner = data.tvBanner ? Thumbnail.fromResponse(data.tvBanner) : []; - this.mobile_banner = data.mobileBanner ? Thumbnail.fromResponse(data.mobileBanner) : []; + this.banner = Thumbnail.fromResponse(data.banner); + this.tv_banner = Thumbnail.fromResponse(data.tvBanner); + this.mobile_banner = Thumbnail.fromResponse(data.mobileBanner); this.subscribers = new Text(data.subscriberCountText); - this.sponsor_button = data.sponsorButton ? Parser.parseItem(data.sponsorButton) : undefined; - this.subscribe_button = data.subscribeButton ? Parser.parseItem(data.subscribeButton) : undefined; - this.header_links = data.headerLinks ? Parser.parse(data.headerLinks) : undefined; + this.videos_count = new Text(data.videosCountText); + this.sponsor_button = Parser.parseItem