Skip to content

Commit

Permalink
feat(parser): Add SearchHeader
Browse files Browse the repository at this point in the history
We may want to remove the old SearchSubMenu node in the future but YouTube still uses it sometimes, so we will keep it for now.

Closes #452
  • Loading branch information
LuanRT committed Jul 24, 2023
1 parent 18cbc8c commit 6997982
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 21 deletions.
16 changes: 5 additions & 11 deletions src/parser/classes/Button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,20 @@ export default class Button extends YTNode {

constructor(data: RawNode) {
super();

if (Reflect.has(data, 'text')) {
if (Reflect.has(data, 'text'))
this.text = new Text(data.text).toString();
}

if (Reflect.has(data, 'accessibility') && Reflect.has(data.accessibility, 'label')) {
if (Reflect.has(data, 'accessibility') && Reflect.has(data.accessibility, 'label'))
this.label = data.accessibility.label;
}

if (Reflect.has(data, 'tooltip')) {
if (Reflect.has(data, 'tooltip'))
this.tooltip = data.tooltip;
}

if (Reflect.has(data, 'icon') && Reflect.has(data.icon, 'iconType')) {
if (Reflect.has(data, 'icon') && Reflect.has(data.icon, 'iconType'))
this.icon_type = data.icon.iconType;
}

if (Reflect.has(data, 'isDisabled')) {
if (Reflect.has(data, 'isDisabled'))
this.is_disabled = data.isDisabled;
}

this.endpoint = new NavigationEndpoint(data.navigationEndpoint || data.serviceEndpoint || data.command);
}
Expand Down
12 changes: 9 additions & 3 deletions src/parser/classes/NavigationEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { YTNode } from '../helpers.js';
import Parser, { type RawNode } from '../index.js';
import type { IParsedResponse } from '../types/ParsedResponse.js';
import CreatePlaylistDialog from './CreatePlaylistDialog.js';
import OpenPopupAction from './actions/OpenPopupAction.js';

export default class NavigationEndpoint extends YTNode {
static type = 'NavigationEndpoint';

payload;
dialog?: CreatePlaylistDialog | YTNode | null;
open_popup?: OpenPopupAction | null;

metadata: {
url?: string;
Expand All @@ -24,6 +26,9 @@ export default class NavigationEndpoint extends YTNode {
if (Reflect.has(data || {}, 'innertubeCommand'))
data = data.innertubeCommand;

if (Reflect.has(data || {}, 'openPopupAction'))
this.open_popup = new OpenPopupAction(data.openPopupAction);

const name = Object.keys(data || {})
.find((item) =>
item.endsWith('Endpoint') ||
Expand All @@ -36,6 +41,7 @@ export default class NavigationEndpoint extends YTNode {
this.dialog = Parser.parseItem(this.payload.dialog || this.payload.content);
}


if (data?.serviceEndpoint) {
data = data.serviceEndpoint;
}
Expand Down Expand Up @@ -85,9 +91,9 @@ export default class NavigationEndpoint extends YTNode {
}
}

call<T extends IParsedResponse>(actions: Actions, args: { [ key: string ]: any; parse: true }): Promise<T>;
call(actions: Actions, args?: { [ key: string ]: any; parse?: false }): Promise<ApiResponse>;
call(actions: Actions, args?: { [ key: string ]: any; parse?: boolean }): Promise<IParsedResponse | ApiResponse> {
call<T extends IParsedResponse>(actions: Actions, args: { [key: string]: any; parse: true }): Promise<T>;
call(actions: Actions, args?: { [key: string]: any; parse?: false }): Promise<ApiResponse>;
call(actions: Actions, args?: { [key: string]: any; parse?: boolean }): Promise<IParsedResponse | ApiResponse> {
if (!actions)
throw new Error('An active caller must be provided');
if (!this.metadata.api_url)
Expand Down
18 changes: 18 additions & 0 deletions src/parser/classes/SearchFilterOptionsDialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { ObservedArray } from '../helpers.js';
import { YTNode } from '../helpers.js';
import { Parser, type RawNode } from '../index.js';
import SearchFilterGroup from './SearchFilterGroup.js';
import Text from './misc/Text.js';

export default class SearchFilterOptionsDialog extends YTNode {
static type = 'SearchFilterOptionsDialog';

title: Text;
groups: ObservedArray<SearchFilterGroup>;

constructor(data: RawNode) {
super();
this.title = new Text(data.title);
this.groups = Parser.parseArray(data.groups, SearchFilterGroup);
}
}
18 changes: 18 additions & 0 deletions src/parser/classes/SearchHeader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { YTNode } from '../helpers.js';
import { Parser, type RawNode } from '../index.js';
import Button from './Button.js';
import ChipCloud from './ChipCloud.js';

export default class SearchHeader extends YTNode {
static type = 'SearchHeader';

chip_bar: ChipCloud | null;
search_filter_button: Button | null;

constructor(data: RawNode) {
super();
this.chip_bar = Parser.parseItem(data.chipBar, ChipCloud);
this.search_filter_button = Parser.parseItem(data.searchFilterButton, Button);
console.log(this.search_filter_button?.endpoint.open_popup);
}
}
17 changes: 11 additions & 6 deletions src/parser/classes/SearchSubMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ import ToggleButton from './ToggleButton.js';
export default class SearchSubMenu extends YTNode {
static type = 'SearchSubMenu';

title: Text;
groups: ObservedArray<SearchFilterGroup>;
button: ToggleButton | null;
title?: Text;
groups?: ObservedArray<SearchFilterGroup>;
button?: ToggleButton | null;

constructor(data: RawNode) {
super();
this.title = new Text(data.title);
this.groups = Parser.parseArray(data.groups, SearchFilterGroup);
this.button = Parser.parseItem(data.button, ToggleButton);
if (Reflect.has(data, 'title'))
this.title = new Text(data.title);

if (!Reflect.has(data, 'groups'))
this.groups = Parser.parseArray(data.groups, SearchFilterGroup);

if (Reflect.has(data, 'button'))
this.button = Parser.parseItem(data.button, ToggleButton);
}
}
2 changes: 2 additions & 0 deletions src/parser/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ export { default as RichShelf } from './classes/RichShelf.js';
export { default as SearchBox } from './classes/SearchBox.js';
export { default as SearchFilter } from './classes/SearchFilter.js';
export { default as SearchFilterGroup } from './classes/SearchFilterGroup.js';
export { default as SearchFilterOptionsDialog } from './classes/SearchFilterOptionsDialog.js';
export { default as SearchHeader } from './classes/SearchHeader.js';
export { default as SearchRefinementCard } from './classes/SearchRefinementCard.js';
export { default as SearchSubMenu } from './classes/SearchSubMenu.js';
export { default as SearchSuggestion } from './classes/SearchSuggestion.js';
Expand Down
6 changes: 5 additions & 1 deletion src/parser/youtube/Search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Feed from '../../core/mixins/Feed.js';
import { InnertubeError } from '../../utils/Utils.js';
import HorizontalCardList from '../classes/HorizontalCardList.js';
import ItemSection from '../classes/ItemSection.js';
import SearchHeader from '../classes/SearchHeader.js';
import SearchRefinementCard from '../classes/SearchRefinementCard.js';
import SearchSubMenu from '../classes/SearchSubMenu.js';
import SectionList from '../classes/SectionList.js';
Expand All @@ -11,8 +12,8 @@ import type Actions from '../../core/Actions.js';
import type { ApiResponse } from '../../core/Actions.js';
import type { ObservedArray, YTNode } from '../helpers.js';
import type { ISearchResponse } from '../types/ParsedResponse.js';

class Search extends Feed<ISearchResponse> {
header?: SearchHeader;
results?: ObservedArray<YTNode> | null;
refinements: string[];
estimated_results: number;
Expand All @@ -30,6 +31,9 @@ class Search extends Feed<ISearchResponse> {
if (!contents)
throw new InnertubeError('No contents found in search response');

if (this.page.header)
this.header = this.page.header.item().as(SearchHeader);

this.results = contents.find((content) => content.is(ItemSection) && content.contents && content.contents.length > 0)?.as(ItemSection).contents;

this.refinements = this.page.refinements || [];
Expand Down

0 comments on commit 6997982

Please sign in to comment.