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