refactor: improve Search parser (#247)

* refactor: improve Search parser

* chore: lint
This commit is contained in:
LuanRT
2022-11-29 03:50:17 -03:00
committed by GitHub
parent 6caa679df6
commit 516eeeff45
11 changed files with 53 additions and 75 deletions

View File

@@ -1,5 +1,7 @@
import Parser from '../index';
import { YTNode } from '../helpers';
import SearchRefinementCard from './SearchRefinementCard';
import Button from './Button';
class HorizontalCardList extends YTNode {
static type = 'HorizontalCardList';
@@ -11,10 +13,10 @@ class HorizontalCardList extends YTNode {
constructor(data: any) {
super();
this.cards = Parser.parse(data.cards);
this.header = Parser.parse(data.header);
this.previous_button = Parser.parse(data.previousButton);
this.next_button = Parser.parse(data.nextButton);
this.cards = Parser.parseArray<SearchRefinementCard>(data.cards, SearchRefinementCard);
this.header = Parser.parseItem(data.header);
this.previous_button = Parser.parseItem<Button>(data.previousButton, Button);
this.next_button = Parser.parseItem<Button>(data.nextButton, Button);
}
}

View File

@@ -1,7 +1,7 @@
import Text from './misc/Text';
import { YTNode } from '../helpers';
class RichListHeader extends YTNode {
export default class RichListHeader extends YTNode {
static type = 'RichListHeader';
title: Text;
@@ -16,6 +16,4 @@ class RichListHeader extends YTNode {
this.title_style = data?.titleStyle?.style;
this.icon_type = data?.icon?.iconType;
}
}
export default RichListHeader;
}

View File

@@ -20,14 +20,14 @@ class Shelf extends YTNode {
this.endpoint = new NavigationEndpoint(data.endpoint);
}
this.content = Parser.parse(data.content) || null;
this.content = Parser.parseItem(data.content) || null;
if (data.icon?.iconType) {
this.icon_type = data.icon?.iconType;
}
if (data.menu) {
this.menu = Parser.parse(data.menu);
this.menu = Parser.parseItem(data.menu);
}
}
}

View File

@@ -1,20 +1,23 @@
import Parser from '../index';
import Text from './misc/Text';
import { YTNode } from '../helpers';
class UniversalWatchCard extends YTNode {
export default class UniversalWatchCard extends YTNode {
static type = 'UniversalWatchCard';
header;
call_to_action;
sections;
collapsed_label?: Text;
constructor(data: any) {
super();
// TODO: use parseItem / parseArray for these
this.header = Parser.parse(data.header);
this.call_to_action = Parser.parse(data.callToAction);
this.sections = Parser.parse(data.sections);
}
}
this.header = Parser.parseItem(data.header);
this.call_to_action = Parser.parseItem(data.callToAction);
this.sections = Parser.parseArray(data.sections);
export default UniversalWatchCard;
if (data.collapsedLabel) {
this.collapsed_label = new Text(data.collapsedLabel);
}
}
}

View File

@@ -3,7 +3,7 @@ import Text from './misc/Text';
import NavigationEndpoint from './NavigationEndpoint';
import { YTNode } from '../helpers';
class VerticalWatchCardList extends YTNode {
export default class VerticalWatchCardList extends YTNode {
static type = 'VerticalWatchCardList';
items;
@@ -13,11 +13,9 @@ class VerticalWatchCardList extends YTNode {
constructor(data: any) {
super();
this.items = Parser.parse(data.items);
this.items = Parser.parseArray(data.items);
this.contents = this.items; // XXX: alias for consistency
this.view_all_text = new Text(data.viewAllText);
this.view_all_endpoint = new NavigationEndpoint(data.viewAllEndpoint);
}
}
export default VerticalWatchCardList;
}

View File

@@ -1,13 +1,14 @@
import Parser from '../index';
import Parser from '..';
import Text from './misc/Text';
import Author from './misc/Author';
import Menu from './menus/Menu';
import Thumbnail from './misc/Thumbnail';
import NavigationEndpoint from './NavigationEndpoint';
import { timeToSeconds } from '../../utils/Utils';
import { YTNode } from '../helpers';
class Video extends YTNode {
export default class Video extends YTNode {
static type = 'Video';
id: string;
@@ -55,7 +56,7 @@ class Video extends YTNode {
this.thumbnails = Thumbnail.fromResponse(data.thumbnail);
this.thumbnail_overlays = Parser.parseArray(data.thumbnailOverlays);
this.rich_thumbnail = data.richThumbnail ? Parser.parse(data.richThumbnail) : null;
this.rich_thumbnail = data.richThumbnail ? Parser.parseItem(data.richThumbnail) : null;
this.author = new Author(data.ownerText, data.ownerBadges, data.channelThumbnailSupportedRenderers?.channelThumbnailWithLinkRenderer?.thumbnail);
this.endpoint = new NavigationEndpoint(data.navigationEndpoint);
this.published = new Text(data.publishedTimeText);
@@ -102,6 +103,4 @@ class Video extends YTNode {
get best_thumbnail(): Thumbnail | undefined{
return this.thumbnails[0];
}
}
export default Video;
}

View File

@@ -2,7 +2,7 @@ import Parser from '../index';
import NavigationEndpoint from './NavigationEndpoint';
import { YTNode } from '../helpers';
class WatchCardHeroVideo extends YTNode {
export default class WatchCardHeroVideo extends YTNode {
static type = 'WatchCardHeroVideo';
endpoint: NavigationEndpoint;
@@ -13,10 +13,8 @@ class WatchCardHeroVideo extends YTNode {
constructor(data: any) {
super();
this.endpoint = new NavigationEndpoint(data.navigationEndpoint);
this.call_to_action_button = Parser.parse(data.callToActionButton);
this.hero_image = Parser.parse(data.heroImage);
this.label = data.lengthText.accessibility.accessibilityData.label;
this.call_to_action_button = Parser.parseItem(data.callToActionButton);
this.hero_image = Parser.parseItem(data.heroImage);
this.label = data.lengthText?.accessibility.accessibilityData.label || '';
}
}
export default WatchCardHeroVideo;
}

View File

@@ -3,7 +3,7 @@ import NavigationEndpoint from './NavigationEndpoint';
import Text from './misc/Text';
import { YTNode } from '../helpers';
class WatchCardRichHeader extends YTNode {
export default class WatchCardRichHeader extends YTNode {
static type = 'WatchCardRichHeader';
title: Text;
@@ -21,6 +21,4 @@ class WatchCardRichHeader extends YTNode {
this.author.name = this.title.toString();
this.style = data.style;
}
}
export default WatchCardRichHeader;
}

View File

@@ -1,15 +1,13 @@
import Parser from '../index';
import { YTNode } from '../helpers';
class WatchCardSectionSequence extends YTNode {
export default class WatchCardSectionSequence extends YTNode {
static type = 'WatchCardSectionSequence';
lists;
constructor(data: any) {
super();
this.lists = Parser.parse(data.lists);
this.lists = Parser.parseArray(data.lists);
}
}
export default WatchCardSectionSequence;
}

View File

@@ -39,10 +39,10 @@ class Library {
}
async #getAll(shelf: Shelf): Promise<Playlist | History | Feed> {
if (!shelf.menu?.item().as(Menu).hasKey('top_level_buttons'))
if (!shelf.menu?.as(Menu).hasKey('top_level_buttons'))
throw new InnertubeError(`The ${shelf.title.text} shelf doesn't have more items`);
const button = shelf.menu.item().as(Menu).top_level_buttons.get({ text: 'See all' });
const button = shelf.menu.as(Menu).top_level_buttons.get({ text: 'See all' });
if (!button)
throw new InnertubeError('Did not find target button.');

View File

@@ -1,19 +1,15 @@
import Actions from '../../core/Actions';
import { observe, ObservedArray, YTNode } from '../helpers';
import { ObservedArray, YTNode } from '../helpers';
import { InnertubeError } from '../../utils/Utils';
import Feed from '../../core/Feed';
import SectionList from '../classes/SectionList';
import ItemSection from '../classes/ItemSection';
import HorizontalCardList from '../classes/HorizontalCardList';
import RichListHeader from '../classes/RichListHeader';
import SearchRefinementCard from '../classes/SearchRefinementCard';
import TwoColumnSearchResults from '../classes/TwoColumnSearchResults';
import UniversalWatchCard from '../classes/UniversalWatchCard';
import WatchCardHeroVideo from '../classes/WatchCardHeroVideo';
import WatchCardSectionSequence from '../classes/WatchCardSectionSequence';
class Search extends Feed {
export default class Search extends Feed {
results: ObservedArray<YTNode> | null | undefined;
refinements;
estimated_results;
@@ -24,30 +20,16 @@ class Search extends Feed {
super(actions, data, already_parsed);
const contents =
this.page.contents?.item().as(TwoColumnSearchResults).primary_contents?.item().as(SectionList).contents.array() ||
this.page.contents_memo.getType(SectionList)?.[0]?.contents?.array() ||
this.page.on_response_received_commands?.[0].contents;
const secondary_contents_maybe = this.page.contents?.item().key('secondary_contents');
const secondary_contents = secondary_contents_maybe?.isParsed() ? secondary_contents_maybe.parsed().item().key('contents').parsed().array() : undefined;
this.results = contents.firstOfType(ItemSection)?.contents;
const card_list = this.results?.get({ type: 'HorizontalCardList' }, true)?.as(HorizontalCardList);
const universal_watch_card = secondary_contents?.firstOfType(UniversalWatchCard);
this.refinements = this.page.refinements || [];
this.estimated_results = this.page.estimated_results;
this.watch_card = {
header: universal_watch_card?.header.item() || null,
call_to_action: universal_watch_card?.call_to_action?.item()?.as(WatchCardHeroVideo) || null,
sections: universal_watch_card?.sections?.array()?.filterType(WatchCardSectionSequence) || []
};
this.refinement_cards = {
header: card_list?.header.item().as(RichListHeader) || null,
cards: card_list?.cards.array().filterType(SearchRefinementCard) || observe([] as SearchRefinementCard[])
};
this.watch_card = this.page?.contents_memo.getType(UniversalWatchCard)?.[0];
this.refinement_cards = this.results?.get({ type: 'HorizontalCardList' }, true)?.as(HorizontalCardList);
}
/**
@@ -57,7 +39,8 @@ class Search extends Feed {
let target_card: SearchRefinementCard | undefined;
if (typeof card === 'string') {
target_card = this.refinement_cards.cards.get({ query: card });
if (!this.refinement_cards) throw new InnertubeError('No refinement cards found.');
target_card = this.refinement_cards?.cards.get({ query: card });
if (!target_card)
throw new InnertubeError(`Refinement card "${card}" not found`, { available_cards: this.refinement_card_queries });
} else if (card.type === 'SearchRefinementCard') {
@@ -71,8 +54,11 @@ class Search extends Feed {
return new Search(this.actions, page, true);
}
/**
* Returns a list of refinement card queries.
*/
get refinement_card_queries() {
return this.refinement_cards.cards.map((card) => card.query);
return this.refinement_cards?.cards.map((card) => card.query);
}
/**
@@ -82,6 +68,4 @@ class Search extends Feed {
const continuation = await this.getContinuationData();
return new Search(this.actions, continuation, true);
}
}
export default Search;
}