From ce53ac18435cbcb20d6d4c4ab52fd156091e7592 Mon Sep 17 00:00:00 2001
From: Daniel Wykerd <45672955+Wykerd@users.noreply.github.com>
Date: Fri, 3 Mar 2023 08:41:04 +0200
Subject: [PATCH 01/13] feat(parser): SharedPost (#332)
Add support for SharedPost in community tab.
Related to issue #331
---
src/core/Feed.ts | 3 ++-
src/parser/classes/SharedPost.ts | 36 ++++++++++++++++++++++++++++++++
src/parser/map.ts | 3 +++
3 files changed, 41 insertions(+), 1 deletion(-)
create mode 100644 src/parser/classes/SharedPost.ts
diff --git a/src/core/Feed.ts b/src/core/Feed.ts
index cde6e0913..0a1013145 100644
--- a/src/core/Feed.ts
+++ b/src/core/Feed.ts
@@ -4,6 +4,7 @@ import { concatMemos, InnertubeError } from '../utils/Utils.js';
import type Actions from './Actions.js';
import BackstagePost from '../parser/classes/BackstagePost.js';
+import SharedPost from '../parser/classes/SharedPost.js';
import Channel from '../parser/classes/Channel.js';
import CompactVideo from '../parser/classes/CompactVideo.js';
import GridChannel from '../parser/classes/GridChannel.js';
@@ -100,7 +101,7 @@ class Feed {
* Get all the community posts in the feed
*/
get posts() {
- return this.#memo.getType([ BackstagePost, Post ]);
+ return this.#memo.getType([ BackstagePost, Post, SharedPost ]);
}
/**
diff --git a/src/parser/classes/SharedPost.ts b/src/parser/classes/SharedPost.ts
new file mode 100644
index 000000000..e536b44b3
--- /dev/null
+++ b/src/parser/classes/SharedPost.ts
@@ -0,0 +1,36 @@
+import { YTNode } from '../helpers.js';
+import Author from './misc/Author.js';
+import { YTNodes } from '../index.js';
+import Parser from '../parser.js';
+import Thumbnail from './misc/Thumbnail.js';
+import NavigationEndpoint from './NavigationEndpoint.js';
+import Text from './misc/Text.js';
+
+class SharedPost extends YTNode {
+ static type = 'SharedPost';
+
+ thumbnail: Thumbnail[];
+ content: Text;
+ published: Text;
+ menu: YTNodes.Menu | null;
+ original_post: YTNodes.BackstagePost | null;
+ id: string;
+ endpoint: NavigationEndpoint;
+ expand_button: YTNodes.Button | null;
+ author: Author;
+
+ constructor(data: any) {
+ super();
+ this.thumbnail = Thumbnail.fromResponse(data.thumbnail);
+ this.content = new Text(data.content);
+ this.published = new Text(data.publishedTimeText);
+ this.menu = Parser.parseItem(data.actionMenu, [ YTNodes.Menu ]);
+ this.original_post = Parser.parseItem(data.originalPost, [ YTNodes.BackstagePost ]);
+ this.id = data.postId;
+ this.endpoint = new NavigationEndpoint(data.navigationEndpoint);
+ this.expand_button = Parser.parseItem(data.expandButton, [ YTNodes.Button ]);
+ this.author = new Author(data.displayName, undefined);
+ }
+}
+
+export default SharedPost;
\ No newline at end of file
diff --git a/src/parser/map.ts b/src/parser/map.ts
index ecbbe52da..487e5cca3 100644
--- a/src/parser/map.ts
+++ b/src/parser/map.ts
@@ -528,6 +528,8 @@ import { default as SettingsSidebar } from './classes/SettingsSidebar.js';
export { SettingsSidebar };
import { default as SettingsSwitch } from './classes/SettingsSwitch.js';
export { SettingsSwitch };
+import { default as SharedPost } from './classes/SharedPost.js';
+export { SharedPost };
import { default as Shelf } from './classes/Shelf.js';
export { Shelf };
import { default as ShowingResultsFor } from './classes/ShowingResultsFor.js';
@@ -912,6 +914,7 @@ const map: Record = {
SettingsOptions,
SettingsSidebar,
SettingsSwitch,
+ SharedPost,
Shelf,
ShowingResultsFor,
SimpleCardContent,
From 214aa147ce6306e37a6bf860a7bed5635db4797e Mon Sep 17 00:00:00 2001
From: Nico K
Date: Fri, 3 Mar 2023 07:47:20 +0100
Subject: [PATCH 02/13] feat(VideoInfo): add `game_info` and `category` (#333)
---
src/parser/classes/RichMetadata.ts | 32 +++++++++++++++++++++++++++
src/parser/classes/RichMetadataRow.ts | 15 +++++++++++++
src/parser/map.ts | 6 +++++
src/parser/youtube/VideoInfo.ts | 14 ++++++++++++
4 files changed, 67 insertions(+)
create mode 100644 src/parser/classes/RichMetadata.ts
create mode 100644 src/parser/classes/RichMetadataRow.ts
diff --git a/src/parser/classes/RichMetadata.ts b/src/parser/classes/RichMetadata.ts
new file mode 100644
index 000000000..76dc7b1e2
--- /dev/null
+++ b/src/parser/classes/RichMetadata.ts
@@ -0,0 +1,32 @@
+import Text from './misc/Text.js';
+import Thumbnail from './misc/Thumbnail.js';
+import NavigationEndpoint from './NavigationEndpoint.js';
+import { YTNode } from '../helpers.js';
+
+class RichMetadata extends YTNode {
+ static type = 'RichMetadata';
+
+ thumbnail: Thumbnail[];
+ title: Text;
+ subtitle?: Text;
+ call_to_action: Text;
+ icon_type?: string;
+ endpoint: NavigationEndpoint;
+
+ constructor(data: any) {
+ super();
+
+ this.thumbnail = Thumbnail.fromResponse(data.thumbnail);
+ this.title = new Text(data.title);
+ this.subtitle = new Text(data.subtitle);
+ this.call_to_action = new Text(data.callToAction);
+
+ if (data.callToActionIcon?.iconType) {
+ this.icon_type = data.callToActionIcon?.iconType;
+ }
+
+ this.endpoint = new NavigationEndpoint(data.endpoint);
+ }
+}
+
+export default RichMetadata;
\ No newline at end of file
diff --git a/src/parser/classes/RichMetadataRow.ts b/src/parser/classes/RichMetadataRow.ts
new file mode 100644
index 000000000..189b8f4cc
--- /dev/null
+++ b/src/parser/classes/RichMetadataRow.ts
@@ -0,0 +1,15 @@
+import Parser from '../index.js';
+import { YTNode } from '../helpers.js';
+
+class RichMetadataRow extends YTNode {
+ static type = 'RichMetadataRow';
+
+ contents;
+
+ constructor(data: any) {
+ super();
+ this.contents = Parser.parseArray(data.contents);
+ }
+}
+
+export default RichMetadataRow;
\ No newline at end of file
diff --git a/src/parser/map.ts b/src/parser/map.ts
index 487e5cca3..3fbc46517 100644
--- a/src/parser/map.ts
+++ b/src/parser/map.ts
@@ -500,6 +500,10 @@ import { default as RichItem } from './classes/RichItem.js';
export { RichItem };
import { default as RichListHeader } from './classes/RichListHeader.js';
export { RichListHeader };
+import { default as RichMetadata } from './classes/RichMetadata.js';
+export { RichMetadata };
+import { default as RichMetadataRow } from './classes/RichMetadataRow.js';
+export { RichMetadataRow };
import { default as RichSection } from './classes/RichSection.js';
export { RichSection };
import { default as RichShelf } from './classes/RichShelf.js';
@@ -900,6 +904,8 @@ const map: Record = {
RichGrid,
RichItem,
RichListHeader,
+ RichMetadata,
+ RichMetadataRow,
RichSection,
RichShelf,
SearchBox,
diff --git a/src/parser/youtube/VideoInfo.ts b/src/parser/youtube/VideoInfo.ts
index 5b43bde87..f17c66d06 100644
--- a/src/parser/youtube/VideoInfo.ts
+++ b/src/parser/youtube/VideoInfo.ts
@@ -12,6 +12,8 @@ import MicroformatData from '../classes/MicroformatData.js';
import PlayerMicroformat from '../classes/PlayerMicroformat.js';
import PlayerOverlay from '../classes/PlayerOverlay.js';
import RelatedChipCloud from '../classes/RelatedChipCloud.js';
+import RichMetadata from '../classes/RichMetadata.js';
+import RichMetadataRow from '../classes/RichMetadataRow.js';
import SegmentedLikeDislikeButton from '../classes/SegmentedLikeDislikeButton.js';
import ToggleButton from '../classes/ToggleButton.js';
import TwoColumnWatchNextResults from '../classes/TwoColumnWatchNextResults.js';
@@ -58,6 +60,7 @@ class VideoInfo {
primary_info?: VideoPrimaryInfo | null;
secondary_info?: VideoSecondaryInfo | null;
+ game_info?;
merchandise?: MerchandiseShelf | null;
related_chip_cloud?: ChipCloud | null;
watch_next_feed?: ObservedArray | null;
@@ -98,6 +101,7 @@ class VideoInfo {
channel: info.microformat?.is(PlayerMicroformat) ? info.microformat?.channel : null,
is_unlisted: info.microformat?.is_unlisted,
is_family_safe: info.microformat?.is_family_safe,
+ category: info.microformat?.is(PlayerMicroformat) ? info.microformat?.category : null,
has_ypc_metadata: info.microformat?.is(PlayerMicroformat) ? info.microformat?.has_ypc_metadata : null,
start_timestamp: info.microformat?.is(PlayerMicroformat) ? info.microformat.start_timestamp : null
},
@@ -122,6 +126,16 @@ class VideoInfo {
const secondary_results = two_col?.secondary_results;
if (results && secondary_results) {
+ if (info.microformat?.is(PlayerMicroformat) && info.microformat?.category === 'Gaming') {
+ const row = results.firstOfType(VideoSecondaryInfo)?.metadata?.rows?.firstOfType(RichMetadataRow);
+ if (row?.is(RichMetadataRow)) {
+ this.game_info = {
+ title: row?.contents?.firstOfType(RichMetadata)?.title,
+ release_year: row?.contents?.firstOfType(RichMetadata)?.subtitle
+ };
+ }
+ }
+
this.primary_info = results.firstOfType(VideoPrimaryInfo);
this.secondary_info = results.firstOfType(VideoSecondaryInfo);
this.merchandise = results.firstOfType(MerchandiseShelf);
From 2d774e26aae79f3d1b115e0e85c148ae80985529 Mon Sep 17 00:00:00 2001
From: LuanRT
Date: Sat, 4 Mar 2023 04:06:19 -0300
Subject: [PATCH 03/13] feat: export `FormatUtils`' types
---
src/utils/index.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/utils/index.ts b/src/utils/index.ts
index ce7be7dda..04c5c86a5 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -5,6 +5,7 @@ export * as Constants from './Constants.js';
export { default as EventEmitter } from './EventEmitterLike.js';
export { default as FormatUtils } from './FormatUtils.js';
+export * from './FormatUtils.js';
export { default as HTTPClient } from './HTTPClient.js';
export * from './HTTPClient.js';
From 2cc7b8bcd6938c7fb3af4f854a1d78b86d153873 Mon Sep 17 00:00:00 2001
From: Patrick Kan <55383971+patrickkfkan@users.noreply.github.com>
Date: Sat, 4 Mar 2023 17:23:17 +0800
Subject: [PATCH 04/13] feat(yt): add `getGuide()` (#335)
* feat(yt): add `getGuide()`
* chore: lint
* fix(Guide): wrong prop
* fix(Guide): include subscription section
* fix(Guide): wrong import
* feat(Guide): add `page`
---
README.md | 7 ++++
src/Innertube.ts | 9 +++++
src/parser/classes/GuideCollapsibleEntry.ts | 35 +++++++++++++++++++
.../classes/GuideCollapsibleSectionEntry.ts | 23 ++++++++++++
src/parser/classes/GuideDownloadsEntry.ts | 14 ++++++++
src/parser/classes/GuideEntry.ts | 33 +++++++++++++++++
src/parser/classes/GuideSection.ts | 20 +++++++++++
.../classes/GuideSubscriptionsSection.ts | 7 ++++
src/parser/map.ts | 18 ++++++++++
src/parser/parser.ts | 11 +++++-
src/parser/types/ParsedResponse.ts | 7 ++++
src/parser/types/RawResponse.ts | 1 +
src/parser/youtube/Guide.ts | 20 +++++++++++
13 files changed, 204 insertions(+), 1 deletion(-)
create mode 100644 src/parser/classes/GuideCollapsibleEntry.ts
create mode 100644 src/parser/classes/GuideCollapsibleSectionEntry.ts
create mode 100644 src/parser/classes/GuideDownloadsEntry.ts
create mode 100644 src/parser/classes/GuideEntry.ts
create mode 100644 src/parser/classes/GuideSection.ts
create mode 100644 src/parser/classes/GuideSubscriptionsSection.ts
create mode 100644 src/parser/youtube/Guide.ts
diff --git a/README.md b/README.md
index 000ec116b..a3c77b054 100644
--- a/README.md
+++ b/README.md
@@ -254,6 +254,7 @@ const yt = await Innertube.create({
* [.getSearchSuggestions(query)](#getsearchsuggestions)
* [.getComments(video_id, sort_by?)](#getcomments)
* [.getHomeFeed()](#gethomefeed)
+ * [.getGuide()](#getguide)
* [.getLibrary()](#getlibrary)
* [.getHistory()](#gethistory)
* [.getTrending()](#gettrending)
@@ -426,6 +427,12 @@ Retrieves YouTube's home feed.
+
+### getGuide()
+Retrieves YouTube's content guide.
+
+**Returns**: `Promise`
+
### getLibrary()
Retrieves the account's library.
diff --git a/src/Innertube.ts b/src/Innertube.ts
index 6bb0ac3e2..18fd36c4e 100644
--- a/src/Innertube.ts
+++ b/src/Innertube.ts
@@ -21,6 +21,7 @@ import PlaylistManager from './core/PlaylistManager.js';
import YTStudio from './core/Studio.js';
import TabbedFeed from './core/TabbedFeed.js';
import HomeFeed from './parser/youtube/HomeFeed.js';
+import Guide from './parser/youtube/Guide.js';
import Proto from './proto/index.js';
import Constants from './utils/Constants.js';
@@ -170,6 +171,14 @@ class Innertube {
return new HomeFeed(this.actions, response);
}
+ /**
+ * Retrieves YouTube's content guide.
+ */
+ async getGuide(): Promise {
+ const response = await this.actions.execute('/guide');
+ return new Guide(response.data);
+ }
+
/**
* Returns the account's library.
*/
diff --git a/src/parser/classes/GuideCollapsibleEntry.ts b/src/parser/classes/GuideCollapsibleEntry.ts
new file mode 100644
index 000000000..cece67e62
--- /dev/null
+++ b/src/parser/classes/GuideCollapsibleEntry.ts
@@ -0,0 +1,35 @@
+import Text from './misc/Text.js';
+import { YTNode } from '../helpers.js';
+import Parser from '../parser.js';
+
+class GuideCollapsibleEntry extends YTNode {
+ static type = 'GuideCollapsibleEntry';
+
+ expander_item: {
+ title: string,
+ icon_type: string
+ };
+ collapser_item: {
+ title: string,
+ icon_type: string
+ };
+ expandable_items;
+
+ constructor(data: any) {
+ super();
+
+ this.expander_item = {
+ title: new Text(data.expanderItem.guideEntryRenderer.formattedTitle).toString(),
+ icon_type: data.expanderItem.guideEntryRenderer.icon.iconType
+ };
+
+ this.collapser_item = {
+ title: new Text(data.collapserItem.guideEntryRenderer.formattedTitle).toString(),
+ icon_type: data.collapserItem.guideEntryRenderer.icon.iconType
+ };
+
+ this.expandable_items = Parser.parseArray(data.expandableItems);
+ }
+}
+
+export default GuideCollapsibleEntry;
\ No newline at end of file
diff --git a/src/parser/classes/GuideCollapsibleSectionEntry.ts b/src/parser/classes/GuideCollapsibleSectionEntry.ts
new file mode 100644
index 000000000..aaab66ab9
--- /dev/null
+++ b/src/parser/classes/GuideCollapsibleSectionEntry.ts
@@ -0,0 +1,23 @@
+import { YTNode } from '../helpers.js';
+import Parser from '../parser.js';
+
+class GuideCollapsibleSectionEntry extends YTNode {
+ static type = 'GuideCollapsibleSectionEntry';
+
+ header_entry;
+ expander_icon: string;
+ collapser_icon: string;
+ section_items;
+
+ constructor(data: any) {
+ super();
+
+ this.header_entry = Parser.parseItem(data.headerEntry);
+ this.expander_icon = data.expanderIcon.iconType;
+ this.collapser_icon = data.collapserIcon.iconType;
+ this.section_items = Parser.parseArray(data.sectionItems);
+
+ }
+}
+
+export default GuideCollapsibleSectionEntry;
\ No newline at end of file
diff --git a/src/parser/classes/GuideDownloadsEntry.ts b/src/parser/classes/GuideDownloadsEntry.ts
new file mode 100644
index 000000000..8f06a1063
--- /dev/null
+++ b/src/parser/classes/GuideDownloadsEntry.ts
@@ -0,0 +1,14 @@
+import GuideEntry from './GuideEntry.js';
+
+class GuideDownloadsEntry extends GuideEntry {
+ static type = 'GuideDownloadsEntry';
+
+ always_show: boolean;
+
+ constructor(data: any) {
+ super(data.entryRenderer.guideEntryRenderer);
+ this.always_show = !!data.alwaysShow;
+ }
+}
+
+export default GuideDownloadsEntry;
\ No newline at end of file
diff --git a/src/parser/classes/GuideEntry.ts b/src/parser/classes/GuideEntry.ts
new file mode 100644
index 000000000..593740111
--- /dev/null
+++ b/src/parser/classes/GuideEntry.ts
@@ -0,0 +1,33 @@
+import Text from './misc/Text.js';
+import NavigationEndpoint from './NavigationEndpoint.js';
+import { YTNode } from '../helpers.js';
+import Thumbnail from './misc/Thumbnail.js';
+
+class GuideEntry extends YTNode {
+ static type = 'GuideEntry';
+
+ title: Text;
+ endpoint: NavigationEndpoint;
+ icon_type?: string;
+ thumbnails?: Thumbnail[];
+ badges?: any;
+ is_primary: boolean;
+
+ constructor(data: any) {
+ super();
+ this.title = new Text(data.formattedTitle);
+ this.endpoint = new NavigationEndpoint(data.navigationEndpoint || data.serviceEndpoint);
+ if (data.icon?.iconType) {
+ this.icon_type = data.icon.iconType;
+ }
+ if (data.thumbnail) {
+ this.thumbnails = Thumbnail.fromResponse(data.thumbnail);
+ }
+ if (data.badges) {
+ this.badges = data.badges;
+ }
+ this.is_primary = !!data.isPrimary;
+ }
+}
+
+export default GuideEntry;
\ No newline at end of file
diff --git a/src/parser/classes/GuideSection.ts b/src/parser/classes/GuideSection.ts
new file mode 100644
index 000000000..2bb0f4d08
--- /dev/null
+++ b/src/parser/classes/GuideSection.ts
@@ -0,0 +1,20 @@
+import Text from './misc/Text.js';
+import { YTNode } from '../helpers.js';
+import Parser from '../parser.js';
+
+class GuideSection extends YTNode {
+ static type = 'GuideSection';
+
+ title?: Text;
+ items;
+
+ constructor(data: any) {
+ super();
+ if (data.formattedTitle) {
+ this.title = new Text(data.formattedTitle);
+ }
+ this.items = Parser.parseArray(data.items);
+ }
+}
+
+export default GuideSection;
\ No newline at end of file
diff --git a/src/parser/classes/GuideSubscriptionsSection.ts b/src/parser/classes/GuideSubscriptionsSection.ts
new file mode 100644
index 000000000..6cd053f4d
--- /dev/null
+++ b/src/parser/classes/GuideSubscriptionsSection.ts
@@ -0,0 +1,7 @@
+import GuideSection from './GuideSection.js';
+
+class GuideSubscriptionsSection extends GuideSection {
+ static type = 'GuideSubscriptionsSection';
+}
+
+export default GuideSubscriptionsSection;
\ No newline at end of file
diff --git a/src/parser/map.ts b/src/parser/map.ts
index 3fbc46517..a9fc75d03 100644
--- a/src/parser/map.ts
+++ b/src/parser/map.ts
@@ -196,6 +196,18 @@ import { default as GridPlaylist } from './classes/GridPlaylist.js';
export { GridPlaylist };
import { default as GridVideo } from './classes/GridVideo.js';
export { GridVideo };
+import { default as GuideCollapsibleEntry } from './classes/GuideCollapsibleEntry.js';
+export { GuideCollapsibleEntry };
+import { default as GuideCollapsibleSectionEntry } from './classes/GuideCollapsibleSectionEntry.js';
+export { GuideCollapsibleSectionEntry };
+import { default as GuideDownloadsEntry } from './classes/GuideDownloadsEntry.js';
+export { GuideDownloadsEntry };
+import { default as GuideEntry } from './classes/GuideEntry.js';
+export { GuideEntry };
+import { default as GuideSection } from './classes/GuideSection.js';
+export { GuideSection };
+import { default as GuideSubscriptionsSection } from './classes/GuideSubscriptionsSection.js';
+export { GuideSubscriptionsSection };
import { default as HashtagHeader } from './classes/HashtagHeader.js';
export { HashtagHeader };
import { default as Heatmap } from './classes/Heatmap.js';
@@ -757,6 +769,12 @@ const map: Record = {
GridHeader,
GridPlaylist,
GridVideo,
+ GuideCollapsibleEntry,
+ GuideCollapsibleSectionEntry,
+ GuideDownloadsEntry,
+ GuideEntry,
+ GuideSection,
+ GuideSubscriptionsSection,
HashtagHeader,
Heatmap,
HeatMarker,
diff --git a/src/parser/parser.ts b/src/parser/parser.ts
index 88aaa68e2..0344eb343 100644
--- a/src/parser/parser.ts
+++ b/src/parser/parser.ts
@@ -262,6 +262,14 @@ export default class Parser {
parsed_data.cards = cards;
}
+ this.#createMemo();
+ const items = this.parse(data.items);
+ if (items) {
+ parsed_data.items = items;
+ parsed_data.items_memo = this.#getMemo();
+ }
+ this.#clearMemo();
+
return parsed_data;
}
@@ -481,7 +489,8 @@ export default class Parser {
'RunAttestationCommand',
'CompactPromotedVideo',
'StatementBanner',
- 'SearchSubMenu'
+ 'SearchSubMenu',
+ 'GuideSigninPromo'
]);
static shouldIgnore(classname: string) {
diff --git a/src/parser/types/ParsedResponse.ts b/src/parser/types/ParsedResponse.ts
index bf69a47b1..709efd714 100644
--- a/src/parser/types/ParsedResponse.ts
+++ b/src/parser/types/ParsedResponse.ts
@@ -29,6 +29,7 @@ export interface IParsedResponse {
sidebar_memo?: Memo;
live_chat_item_context_menu_supported_renderers?: YTNode;
live_chat_item_context_menu_supported_renderers_memo?: Memo;
+ items_memo?: Memo;
on_response_received_actions?: ObservedArray;
on_response_received_actions_memo?: Memo;
on_response_received_endpoints?: ObservedArray;
@@ -72,6 +73,7 @@ export interface IParsedResponse {
storyboards?: PlayerStoryboardSpec | PlayerLiveStoryboardSpec;
endscreen?: Endscreen;
cards?: CardCollection;
+ items?: SuperParsedResult;
}
export interface IPlayerResponse {
@@ -156,4 +158,9 @@ export interface IUpdatedMetadataResponse {
actions: SuperParsedResult;
actions_memo: Memo;
continuation?: Continuation;
+}
+
+export interface IGuideResponse {
+ items: SuperParsedResult;
+ items_memo: Memo;
}
\ No newline at end of file
diff --git a/src/parser/types/RawResponse.ts b/src/parser/types/RawResponse.ts
index 08d950ac1..92fe7eadc 100644
--- a/src/parser/types/RawResponse.ts
+++ b/src/parser/types/RawResponse.ts
@@ -51,5 +51,6 @@ export interface IRawResponse {
storyboards?: RawNode;
endscreen?: RawNode;
cards?: RawNode;
+ items?: RawNode[];
frameworkUpdates?: any;
}
\ No newline at end of file
diff --git a/src/parser/youtube/Guide.ts b/src/parser/youtube/Guide.ts
new file mode 100644
index 000000000..4e261bcef
--- /dev/null
+++ b/src/parser/youtube/Guide.ts
@@ -0,0 +1,20 @@
+import type { IGuideResponse } from '../types/ParsedResponse.js';
+import { IRawResponse, Parser } from '../index.js';
+import { ObservedArray } from '../helpers.js';
+import GuideSection from '../classes/GuideSection.js';
+import GuideSubscriptionsSection from '../classes/GuideSubscriptionsSection.js';
+
+export default class Guide {
+
+ #page: IGuideResponse;
+ contents: ObservedArray;
+
+ constructor(data: IRawResponse) {
+ this.#page = Parser.parseResponse(data);
+ this.contents = this.#page.items.array().as(GuideSection, GuideSubscriptionsSection);
+ }
+
+ get page(): IGuideResponse {
+ return this.#page;
+ }
+}
\ No newline at end of file
From 95033e723ef912706e4d176de6b2760f017184e1 Mon Sep 17 00:00:00 2001
From: Patrick Kan <55383971+patrickkfkan@users.noreply.github.com>
Date: Mon, 6 Mar 2023 09:44:09 +0800
Subject: [PATCH 05/13] feat(parser): add `banner` to `PlaylistHeader` (#337)
---
src/parser/classes/HeroPlaylistThumbnail.ts | 19 +++++++++++++++++++
src/parser/classes/PlaylistHeader.ts | 2 ++
src/parser/map.ts | 3 +++
3 files changed, 24 insertions(+)
create mode 100644 src/parser/classes/HeroPlaylistThumbnail.ts
diff --git a/src/parser/classes/HeroPlaylistThumbnail.ts b/src/parser/classes/HeroPlaylistThumbnail.ts
new file mode 100644
index 000000000..1d83b2af0
--- /dev/null
+++ b/src/parser/classes/HeroPlaylistThumbnail.ts
@@ -0,0 +1,19 @@
+import { YTNode } from '../helpers.js';
+import NavigationEndpoint from './NavigationEndpoint.js';
+import Thumbnail from './misc/Thumbnail.js';
+
+class HeroPlaylistThumbnail extends YTNode {
+ static type = 'HeroPlaylistThumbnail';
+
+ thumbnails: Thumbnail[];
+ on_tap_endpoint: NavigationEndpoint;
+
+ constructor(data: any) {
+ super();
+
+ this.thumbnails = Thumbnail.fromResponse(data.thumbnail);
+ this.on_tap_endpoint = new NavigationEndpoint(data.onTap);
+ }
+}
+
+export default HeroPlaylistThumbnail;
\ No newline at end of file
diff --git a/src/parser/classes/PlaylistHeader.ts b/src/parser/classes/PlaylistHeader.ts
index a670538d4..18c5a4c2a 100644
--- a/src/parser/classes/PlaylistHeader.ts
+++ b/src/parser/classes/PlaylistHeader.ts
@@ -21,6 +21,7 @@ class PlaylistHeader extends YTNode {
save_button;
shuffle_play_button;
menu;
+ banner;
constructor(data: any) {
super();
@@ -39,6 +40,7 @@ class PlaylistHeader extends YTNode {
this.save_button = Parser.parse(data.saveButton);
this.shuffle_play_button = Parser.parse(data.shufflePlayButton);
this.menu = Parser.parse(data.moreActionsMenu);
+ this.banner = Parser.parseItem(data.playlistHeaderBanner);
}
}
diff --git a/src/parser/map.ts b/src/parser/map.ts
index a9fc75d03..d20ab7351 100644
--- a/src/parser/map.ts
+++ b/src/parser/map.ts
@@ -214,6 +214,8 @@ import { default as Heatmap } from './classes/Heatmap.js';
export { Heatmap };
import { default as HeatMarker } from './classes/HeatMarker.js';
export { HeatMarker };
+import { default as HeroPlaylistThumbnail } from './classes/HeroPlaylistThumbnail.js';
+export { HeroPlaylistThumbnail };
import { default as HighlightsCarousel } from './classes/HighlightsCarousel.js';
export { HighlightsCarousel };
import { default as HistorySuggestion } from './classes/HistorySuggestion.js';
@@ -778,6 +780,7 @@ const map: Record = {
HashtagHeader,
Heatmap,
HeatMarker,
+ HeroPlaylistThumbnail,
HighlightsCarousel,
HistorySuggestion,
HorizontalCardList,
From cfc1a183e05de6dff979ad884260abf0d03b764e Mon Sep 17 00:00:00 2001
From: Chinmay Kumar <37647219+chinmay021@users.noreply.github.com>
Date: Tue, 7 Mar 2023 10:32:07 +0530
Subject: [PATCH 06/13] refactor(parser): type YTNodes' data arg as `RawNode`
(wip) (#339)
* replaced YTNode's data arg as RawNode
* updated documentation
* removed unused import
---- Note that there are still many nodes that need to be updated, hence the WIP status.
---
docs/updating-the-parser.md | 14 +++++++++-----
src/parser/classes/AccountChannel.ts | 3 ++-
src/parser/classes/AccountItemSection.ts | 5 +++--
src/parser/classes/AccountItemSectionHeader.ts | 4 ++--
src/parser/classes/AccountSectionList.ts | 4 ++--
src/parser/classes/Alert.ts | 4 ++--
src/parser/classes/AudioOnlyPlayability.ts | 4 ++--
src/parser/classes/AutomixPreviewVideo.ts | 4 ++--
.../actions/AppendContinuationItemsAction.ts | 3 ++-
src/parser/classes/actions/OpenPopupAction.ts | 3 ++-
.../analytics/AnalyticsMainAppKeyMetrics.ts | 3 ++-
src/parser/classes/analytics/AnalyticsRoot.ts | 3 ++-
.../analytics/AnalyticsShortsCarouselCard.ts | 3 ++-
src/parser/classes/analytics/AnalyticsVideo.ts | 3 ++-
.../classes/analytics/AnalyticsVodCarouselCard.ts | 3 ++-
.../classes/analytics/CtaGoToCreatorStudio.ts | 3 ++-
src/parser/classes/analytics/DataModelSection.ts | 3 ++-
src/parser/classes/analytics/StatRow.ts | 3 ++-
src/parser/classes/comments/AuthorCommentBadge.ts | 3 ++-
src/parser/classes/comments/Comment.ts | 3 ++-
.../classes/comments/CommentActionButtons.ts | 3 ++-
src/parser/classes/comments/CommentDialog.ts | 3 ++-
src/parser/classes/comments/CommentReplies.ts | 4 ++--
src/parser/classes/comments/CommentReplyDialog.ts | 3 ++-
src/parser/classes/comments/CommentSimplebox.ts | 3 ++-
src/parser/classes/comments/CommentThread.ts | 3 ++-
.../classes/comments/CommentsEntryPointHeader.ts | 3 ++-
src/parser/classes/comments/CommentsHeader.ts | 3 ++-
src/parser/classes/comments/CreatorHeart.ts | 3 ++-
src/parser/classes/comments/EmojiPicker.ts | 3 ++-
src/parser/classes/comments/PdgCommentChip.ts | 3 ++-
src/parser/classes/comments/SponsorCommentBadge.ts | 3 ++-
.../classes/livechat/AddBannerToLiveChatCommand.ts | 3 ++-
src/parser/classes/livechat/AddChatItemAction.ts | 3 ++-
.../livechat/AddLiveChatTickerItemAction.ts | 3 ++-
src/parser/classes/livechat/DimChatItemAction.ts | 4 ++--
src/parser/classes/livechat/LiveChatActionPanel.ts | 4 ++--
.../livechat/MarkChatItemAsDeletedAction.ts | 4 ++--
.../MarkChatItemsByAuthorAsDeletedAction.ts | 4 ++--
.../livechat/RemoveBannerForLiveChatCommand.ts | 4 ++--
.../classes/livechat/RemoveChatItemAction.ts | 4 ++--
.../livechat/RemoveChatItemByAuthorAction.ts | 4 ++--
.../classes/livechat/ReplaceChatItemAction.ts | 4 ++--
.../classes/livechat/ReplayChatItemAction.ts | 4 ++--
.../livechat/ShowLiveChatActionPanelAction.ts | 4 ++--
.../classes/livechat/ShowLiveChatDialogAction.ts | 4 ++--
.../classes/livechat/ShowLiveChatTooltipCommand.ts | 4 ++--
.../classes/livechat/UpdateDateTextAction.ts | 4 ++--
.../classes/livechat/UpdateDescriptionAction.ts | 4 ++--
.../classes/livechat/UpdateLiveChatPollAction.ts | 4 ++--
src/parser/classes/livechat/UpdateTitleAction.ts | 4 ++--
.../livechat/UpdateToggleButtonTextAction.ts | 4 ++--
.../classes/livechat/UpdateViewershipAction.ts | 4 ++--
.../livechat/items/LiveChatAutoModMessage.ts | 3 ++-
.../classes/livechat/items/LiveChatBanner.ts | 3 ++-
.../classes/livechat/items/LiveChatBannerHeader.ts | 3 ++-
.../classes/livechat/items/LiveChatBannerPoll.ts | 4 ++--
.../livechat/items/LiveChatMembershipItem.ts | 4 ++--
.../classes/livechat/items/LiveChatPaidMessage.ts | 4 ++--
.../classes/livechat/items/LiveChatPaidSticker.ts | 3 ++-
.../livechat/items/LiveChatPlaceholderItem.ts | 3 ++-
.../classes/livechat/items/LiveChatProductItem.ts | 3 ++-
.../items/LiveChatRestrictedParticipation.ts | 3 ++-
.../classes/livechat/items/LiveChatTextMessage.ts | 3 ++-
.../items/LiveChatTickerPaidMessageItem.ts | 3 ++-
.../items/LiveChatTickerPaidStickerItem.ts | 3 ++-
.../livechat/items/LiveChatTickerSponsorItem.ts | 3 ++-
.../items/LiveChatViewerEngagementMessage.ts | 3 ++-
src/parser/classes/livechat/items/PollHeader.ts | 3 ++-
src/parser/classes/menus/Menu.ts | 4 ++--
src/parser/classes/menus/MenuNavigationItem.ts | 4 ++--
src/parser/classes/menus/MenuServiceItem.ts | 4 ++--
.../classes/menus/MenuServiceItemDownload.ts | 4 ++--
src/parser/classes/menus/MultiPageMenu.ts | 4 ++--
.../menus/MultiPageMenuNotificationSection.ts | 4 ++--
src/parser/classes/menus/MusicMenuItemDivider.ts | 4 ++--
src/parser/classes/menus/MusicMultiSelectMenu.ts | 4 ++--
.../classes/menus/MusicMultiSelectMenuItem.ts | 4 ++--
src/parser/classes/menus/SimpleMenuHeader.ts | 4 ++--
src/parser/classes/misc/ChildElement.ts | 4 +++-
src/parser/classes/misc/EmojiRun.ts | 3 ++-
src/parser/classes/misc/Format.ts | 3 ++-
src/parser/classes/misc/NavigatableText.ts | 3 ++-
src/parser/classes/misc/Text.ts | 3 ++-
src/parser/classes/misc/Thumbnail.ts | 4 +++-
src/parser/classes/misc/VideoDetails.ts | 3 ++-
src/parser/classes/ytkids/AnchoredSection.ts | 3 ++-
src/parser/classes/ytkids/KidsCategoriesHeader.ts | 3 ++-
src/parser/classes/ytkids/KidsCategoryTab.ts | 3 ++-
src/parser/classes/ytkids/KidsHomeScreen.ts | 3 ++-
90 files changed, 190 insertions(+), 132 deletions(-)
diff --git a/docs/updating-the-parser.md b/docs/updating-the-parser.md
index b392f7123..45a04ad89 100644
--- a/docs/updating-the-parser.md
+++ b/docs/updating-the-parser.md
@@ -1,8 +1,9 @@
# Updating the parser
-YouTube is constantly changing, so it is not rare to see YouTube crawlers/scrapers breaking every now and then.
+YouTube is constantly changing, so it is not rare to see YouTube crawlers/scrapers breaking every now and then.
+
+Our parser, on the other hand, was written so that it behaves similarly to an official client, parsing and mapping renderers (a.k.a YTNodes) dynamically without hard-coding their path in the response. This way, whenever a new renderer pops up (e.g; YouTube adds a new feature / minor UI changes) the library will print a warning similar to this:
-Our parser, on the other hand, was written so that it behaves similarly to an official client, parsing and mapping renderers (a.k.a YTNodes) dynamically without hard-coding their path in the response. This way, whenever a new renderer pops up (e.g; YouTube adds a new feature / minor UI changes) the library will print a warning similar to this:
```
InnertubeError: SomeRenderer not found!
This is a bug, want to help us fix it? Follow the instructions at https://github.com/LuanRT/YouTube.js/blob/main/docs/updating-the-parser.md or report it at https://github.com/LuanRT/YouTube.js/issues!
@@ -26,17 +27,19 @@ Thanks to the modularity of the parser, a renderer can be implemented by simply
For example, say we found a new renderer named `verticalListRenderer`, to let the parser know it exists we would have to create a file with the following structure:
> `../classes/VerticalList.ts`
+
```ts
import Parser from '..';
import { YTNode } from '../helpers';
+import type { RawNode } from '../index.js';
class VerticalList extends YTNode {
static type = 'VerticalList';
-
+
header;
contents;
- constructor(data: any) {
+ constructor(data: RawNode) {
// parse the data here, ex;
this.header = Parser.parseItem(data.header);
this.contents = Parser.parseArray(data.contents);
@@ -47,8 +50,9 @@ export default VerticalList;
```
Then update the parser map:
+
```bash
npm run build:parser-map
```
-And that's it!
\ No newline at end of file
+And that's it!
diff --git a/src/parser/classes/AccountChannel.ts b/src/parser/classes/AccountChannel.ts
index cec2b19fa..6c3af8471 100644
--- a/src/parser/classes/AccountChannel.ts
+++ b/src/parser/classes/AccountChannel.ts
@@ -1,6 +1,7 @@
import Text from './misc/Text.js';
import NavigationEndpoint from './NavigationEndpoint.js';
import { YTNode } from '../helpers.js';
+import type { RawNode } from '../index.js';
class AccountChannel extends YTNode {
static type = 'AccountChannel';
@@ -8,7 +9,7 @@ class AccountChannel extends YTNode {
title: Text;
endpoint: NavigationEndpoint;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.title = new Text(data.title);
this.endpoint = new NavigationEndpoint(data.navigationEndpoint);
diff --git a/src/parser/classes/AccountItemSection.ts b/src/parser/classes/AccountItemSection.ts
index 40daceb1b..89aa7d5bf 100644
--- a/src/parser/classes/AccountItemSection.ts
+++ b/src/parser/classes/AccountItemSection.ts
@@ -6,6 +6,7 @@ import NavigationEndpoint from './NavigationEndpoint.js';
import AccountItemSectionHeader from './AccountItemSectionHeader.js';
import { YTNode } from '../helpers.js';
+import type { RawNode } from '../index.js';
class AccountItem {
static type = 'AccountItem';
@@ -18,7 +19,7 @@ class AccountItem {
endpoint: NavigationEndpoint;
account_byline: Text;
- constructor(data: any) {
+ constructor(data: RawNode) {
this.account_name = new Text(data.accountName);
this.account_photo = Thumbnail.fromResponse(data.accountPhoto);
this.is_selected = data.isSelected;
@@ -35,7 +36,7 @@ class AccountItemSection extends YTNode {
contents;
header;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.contents = data.contents.map((ac: any) => new AccountItem(ac.accountItem));
this.header = Parser.parseItem(data.header, AccountItemSectionHeader);
diff --git a/src/parser/classes/AccountItemSectionHeader.ts b/src/parser/classes/AccountItemSectionHeader.ts
index 91d40edb7..1653392a8 100644
--- a/src/parser/classes/AccountItemSectionHeader.ts
+++ b/src/parser/classes/AccountItemSectionHeader.ts
@@ -1,12 +1,12 @@
import Text from './misc/Text.js';
import { YTNode } from '../helpers.js';
-
+import type { RawNode } from '../index.js';
class AccountItemSectionHeader extends YTNode {
static type = 'AccountItemSectionHeader';
title: Text;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.title = new Text(data.title);
}
diff --git a/src/parser/classes/AccountSectionList.ts b/src/parser/classes/AccountSectionList.ts
index 03bc27cc4..31f54efbe 100644
--- a/src/parser/classes/AccountSectionList.ts
+++ b/src/parser/classes/AccountSectionList.ts
@@ -3,14 +3,14 @@ import AccountChannel from './AccountChannel.js';
import AccountItemSection from './AccountItemSection.js';
import { YTNode } from '../helpers.js';
-
+import type { RawNode } from '../index.js';
class AccountSectionList extends YTNode {
static type = 'AccountSectionList';
contents;
footers;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.contents = Parser.parseItem(data.contents[0], AccountItemSection);
this.footers = Parser.parseItem(data.footers[0], AccountChannel);
diff --git a/src/parser/classes/Alert.ts b/src/parser/classes/Alert.ts
index d095bee2a..e080d24cc 100644
--- a/src/parser/classes/Alert.ts
+++ b/src/parser/classes/Alert.ts
@@ -1,13 +1,13 @@
import Text from './misc/Text.js';
import { YTNode } from '../helpers.js';
-
+import type { RawNode } from '../index.js';
class Alert extends YTNode {
static type = 'Alert';
text: Text;
alert_type: string;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.text = new Text(data.text);
this.alert_type = data.type;
diff --git a/src/parser/classes/AudioOnlyPlayability.ts b/src/parser/classes/AudioOnlyPlayability.ts
index f1d4ed3a0..f5f6daaaa 100644
--- a/src/parser/classes/AudioOnlyPlayability.ts
+++ b/src/parser/classes/AudioOnlyPlayability.ts
@@ -1,11 +1,11 @@
import { YTNode } from '../helpers.js';
-
+import type { RawNode } from '../index.js';
class AudioOnlyPlayability extends YTNode {
static type = 'AudioOnlyPlayability';
audio_only_availability: string;
- constructor (data: any) {
+ constructor (data: RawNode) {
super();
this.audio_only_availability = data.audioOnlyAvailability;
}
diff --git a/src/parser/classes/AutomixPreviewVideo.ts b/src/parser/classes/AutomixPreviewVideo.ts
index e697106f4..0759f3fa3 100644
--- a/src/parser/classes/AutomixPreviewVideo.ts
+++ b/src/parser/classes/AutomixPreviewVideo.ts
@@ -1,12 +1,12 @@
import { YTNode } from '../helpers.js';
import NavigationEndpoint from './NavigationEndpoint.js';
-
+import type { RawNode } from '../index.js';
class AutomixPreviewVideo extends YTNode {
static type = 'AutomixPreviewVideo';
playlist_video?: { endpoint: NavigationEndpoint };
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
if (data?.content?.automixPlaylistVideoRenderer?.navigationEndpoint) {
this.playlist_video = {
diff --git a/src/parser/classes/actions/AppendContinuationItemsAction.ts b/src/parser/classes/actions/AppendContinuationItemsAction.ts
index a9fa65411..5ca0cc004 100644
--- a/src/parser/classes/actions/AppendContinuationItemsAction.ts
+++ b/src/parser/classes/actions/AppendContinuationItemsAction.ts
@@ -1,5 +1,6 @@
import Parser from '../../index.js';
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class AppendContinuationItemsAction extends YTNode {
static type = 'AppendContinuationItemsAction';
@@ -7,7 +8,7 @@ class AppendContinuationItemsAction extends YTNode {
items;
target: string;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.items = Parser.parse(data.continuationItems);
this.target = data.target;
diff --git a/src/parser/classes/actions/OpenPopupAction.ts b/src/parser/classes/actions/OpenPopupAction.ts
index 9286139e7..75c4701e6 100644
--- a/src/parser/classes/actions/OpenPopupAction.ts
+++ b/src/parser/classes/actions/OpenPopupAction.ts
@@ -1,5 +1,6 @@
import Parser from '../../index.js';
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class OpenPopupAction extends YTNode {
static type = 'OpenPopupAction';
@@ -7,7 +8,7 @@ class OpenPopupAction extends YTNode {
popup;
popup_type;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.popup = Parser.parse(data.popup);
this.popup_type = data.popupType;
diff --git a/src/parser/classes/analytics/AnalyticsMainAppKeyMetrics.ts b/src/parser/classes/analytics/AnalyticsMainAppKeyMetrics.ts
index 31715ed51..526de8e2c 100644
--- a/src/parser/classes/analytics/AnalyticsMainAppKeyMetrics.ts
+++ b/src/parser/classes/analytics/AnalyticsMainAppKeyMetrics.ts
@@ -1,5 +1,6 @@
import DataModelSection from './DataModelSection.js';
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class AnalyticsMainAppKeyMetrics extends YTNode {
static type = 'AnalyticsMainAppKeyMetrics';
@@ -7,7 +8,7 @@ class AnalyticsMainAppKeyMetrics extends YTNode {
period: string;
sections: DataModelSection[];
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.period = data.cardData.periodLabel;
const metrics_data = data.cardData.sections[0].analyticsKeyMetricsData;
diff --git a/src/parser/classes/analytics/AnalyticsRoot.ts b/src/parser/classes/analytics/AnalyticsRoot.ts
index a4bb3c9f3..bd3849b4a 100644
--- a/src/parser/classes/analytics/AnalyticsRoot.ts
+++ b/src/parser/classes/analytics/AnalyticsRoot.ts
@@ -1,4 +1,5 @@
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class AnalyticsRoot extends YTNode {
static type = 'AnalyticsRoot';
@@ -19,7 +20,7 @@ class AnalyticsRoot extends YTNode {
}[];
}[];
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
const cards = data.analyticsTableCarouselData.data.tableCards;
diff --git a/src/parser/classes/analytics/AnalyticsShortsCarouselCard.ts b/src/parser/classes/analytics/AnalyticsShortsCarouselCard.ts
index 8ea3048dc..ce169ce55 100644
--- a/src/parser/classes/analytics/AnalyticsShortsCarouselCard.ts
+++ b/src/parser/classes/analytics/AnalyticsShortsCarouselCard.ts
@@ -1,4 +1,5 @@
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
import NavigationEndpoint from '../NavigationEndpoint.js';
class AnalyticsShortsCarouselCard extends YTNode {
@@ -11,7 +12,7 @@ class AnalyticsShortsCarouselCard extends YTNode {
endpoint: NavigationEndpoint;
}[];
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.title = data.title;
this.shorts = data.shortsCarouselData.shorts.map((short: any) => ({
diff --git a/src/parser/classes/analytics/AnalyticsVideo.ts b/src/parser/classes/analytics/AnalyticsVideo.ts
index b17da865f..09b9334d6 100644
--- a/src/parser/classes/analytics/AnalyticsVideo.ts
+++ b/src/parser/classes/analytics/AnalyticsVideo.ts
@@ -1,5 +1,6 @@
import Thumbnail from '../misc/Thumbnail.js';
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class AnalyticsVideo extends YTNode {
static type = 'AnalyticsVideo';
@@ -13,7 +14,7 @@ class AnalyticsVideo extends YTNode {
is_short: boolean;
};
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.title = data.videoTitle;
diff --git a/src/parser/classes/analytics/AnalyticsVodCarouselCard.ts b/src/parser/classes/analytics/AnalyticsVodCarouselCard.ts
index 27a98a199..a77e54d74 100644
--- a/src/parser/classes/analytics/AnalyticsVodCarouselCard.ts
+++ b/src/parser/classes/analytics/AnalyticsVodCarouselCard.ts
@@ -1,5 +1,6 @@
import Video from './AnalyticsVideo.js';
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class AnalyticsVodCarouselCard extends YTNode {
static type = 'AnalyticsVodCarouselCard';
@@ -8,7 +9,7 @@ class AnalyticsVodCarouselCard extends YTNode {
videos: Video[] | null;
no_data_message?: string;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.title = data.title;
diff --git a/src/parser/classes/analytics/CtaGoToCreatorStudio.ts b/src/parser/classes/analytics/CtaGoToCreatorStudio.ts
index 3d2595572..f2378edc4 100644
--- a/src/parser/classes/analytics/CtaGoToCreatorStudio.ts
+++ b/src/parser/classes/analytics/CtaGoToCreatorStudio.ts
@@ -1,4 +1,5 @@
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class CtaGoToCreatorStudio extends YTNode {
static type = 'CtaGoToCreatorStudio';
@@ -6,7 +7,7 @@ class CtaGoToCreatorStudio extends YTNode {
title: string;
use_new_specs: boolean;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.title = data.buttonLabel;
this.use_new_specs = data.useNewSpecs;
diff --git a/src/parser/classes/analytics/DataModelSection.ts b/src/parser/classes/analytics/DataModelSection.ts
index d0967343f..cbc716449 100644
--- a/src/parser/classes/analytics/DataModelSection.ts
+++ b/src/parser/classes/analytics/DataModelSection.ts
@@ -1,4 +1,5 @@
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class DataModelSection extends YTNode {
static type = 'DataModelSection';
@@ -36,7 +37,7 @@ class DataModelSection extends YTNode {
}
};
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.title = data.title;
diff --git a/src/parser/classes/analytics/StatRow.ts b/src/parser/classes/analytics/StatRow.ts
index d0bf0f224..cea7e738e 100644
--- a/src/parser/classes/analytics/StatRow.ts
+++ b/src/parser/classes/analytics/StatRow.ts
@@ -1,6 +1,7 @@
import Text from '../misc/Text.js';
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class StatRow extends YTNode {
static type = 'StatRow';
@@ -8,7 +9,7 @@ class StatRow extends YTNode {
title: Text;
contents: Text;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.title = new Text(data.title);
this.contents = new Text(data.contents);
diff --git a/src/parser/classes/comments/AuthorCommentBadge.ts b/src/parser/classes/comments/AuthorCommentBadge.ts
index f15098b41..6d04a88b7 100644
--- a/src/parser/classes/comments/AuthorCommentBadge.ts
+++ b/src/parser/classes/comments/AuthorCommentBadge.ts
@@ -1,4 +1,5 @@
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class AuthorCommentBadge extends YTNode {
static type = 'AuthorCommentBadge';
@@ -9,7 +10,7 @@ class AuthorCommentBadge extends YTNode {
tooltip: string;
style?: string;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.icon_type = data.icon?.iconType || null;
diff --git a/src/parser/classes/comments/Comment.ts b/src/parser/classes/comments/Comment.ts
index 3a787593a..d9ea0be29 100644
--- a/src/parser/classes/comments/Comment.ts
+++ b/src/parser/classes/comments/Comment.ts
@@ -16,6 +16,7 @@ import type Actions from '../../../core/Actions.js';
import Proto from '../../../proto/index.js';
import { InnertubeError } from '../../../utils/Utils.js';
import { YTNode, SuperParsedResult } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class Comment extends YTNode {
static type = 'Comment';
@@ -44,7 +45,7 @@ class Comment extends YTNode {
is_pinned: boolean;
is_member: boolean;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.content = new Text(data.contentText);
this.published = new Text(data.publishedTimeText);
diff --git a/src/parser/classes/comments/CommentActionButtons.ts b/src/parser/classes/comments/CommentActionButtons.ts
index 94732f86d..5e77be749 100644
--- a/src/parser/classes/comments/CommentActionButtons.ts
+++ b/src/parser/classes/comments/CommentActionButtons.ts
@@ -3,6 +3,7 @@ import type Button from '../Button.js';
import type ToggleButton from '../ToggleButton.js';
import type CreatorHeart from './CreatorHeart.js';
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class CommentActionButtons extends YTNode {
static type = 'CommentActionButtons';
@@ -12,7 +13,7 @@ class CommentActionButtons extends YTNode {
reply_button;
creator_heart;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.like_button = Parser.parseItem(data.likeButton);
this.dislike_button = Parser.parseItem(data.dislikeButton);
diff --git a/src/parser/classes/comments/CommentDialog.ts b/src/parser/classes/comments/CommentDialog.ts
index 6144c6b26..c0b7459bb 100644
--- a/src/parser/classes/comments/CommentDialog.ts
+++ b/src/parser/classes/comments/CommentDialog.ts
@@ -4,6 +4,7 @@ import Thumbnail from '../misc/Thumbnail.js';
import type Button from '../Button.js';
import type EmojiPicker from './EmojiPicker.js';
import { YTNode } from '../../helpers.js';
+import type { RawNode } from '../../index.js';
class CommentDialog extends YTNode {
static type = 'CommentDialog';
@@ -16,7 +17,7 @@ class CommentDialog extends YTNode {
emoji_button: Button | null;
emoji_picker: any | null;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.editable_text = new Text(data.editableText);
this.author_thumbnail = Thumbnail.fromResponse(data.authorThumbnail);
diff --git a/src/parser/classes/comments/CommentReplies.ts b/src/parser/classes/comments/CommentReplies.ts
index 24bccd40b..d80849423 100644
--- a/src/parser/classes/comments/CommentReplies.ts
+++ b/src/parser/classes/comments/CommentReplies.ts
@@ -2,7 +2,7 @@ import Parser from '../../index.js';
import Thumbnail from '../misc/Thumbnail.js';
import type Button from '../Button.js';
import { YTNode } from '../../helpers.js';
-
+import type { RawNode } from '../../index.js';
class CommentReplies extends YTNode {
static type = 'CommentReplies';
@@ -12,7 +12,7 @@ class CommentReplies extends YTNode {
view_replies_creator_thumbnail: Thumbnail[];
has_channel_owner_replied: boolean;
- constructor(data: any) {
+ constructor(data: RawNode) {
super();
this.contents = Parser.parseArray(data.contents);
this.view_replies = Parser.parseItem