mirror of
https://github.com/LuanRT/YouTube.js.git
synced 2026-06-13 09:32:12 +00:00
chore: v5.7.0 release
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "youtubei.js",
|
||||
"version": "5.6.0",
|
||||
"version": "5.7.0",
|
||||
"description": "A wrapper around YouTube's private API. Supports YouTube, YouTube Music, YouTube Kids and YouTube Studio (WIP).",
|
||||
"type": "module",
|
||||
"types": "./dist/src/platform/lib.d.ts",
|
||||
|
||||
@@ -15,26 +15,20 @@ export default class Button extends YTNode {
|
||||
|
||||
constructor(data: RawNode) {
|
||||
super();
|
||||
|
||||
if (Reflect.has(data, 'text')) {
|
||||
if (Reflect.has(data, 'text'))
|
||||
this.text = new Text(data.text).toString();
|
||||
}
|
||||
|
||||
if (Reflect.has(data, 'accessibility') && Reflect.has(data.accessibility, 'label')) {
|
||||
if (Reflect.has(data, 'accessibility') && Reflect.has(data.accessibility, 'label'))
|
||||
this.label = data.accessibility.label;
|
||||
}
|
||||
|
||||
if (Reflect.has(data, 'tooltip')) {
|
||||
if (Reflect.has(data, 'tooltip'))
|
||||
this.tooltip = data.tooltip;
|
||||
}
|
||||
|
||||
if (Reflect.has(data, 'icon') && Reflect.has(data.icon, 'iconType')) {
|
||||
if (Reflect.has(data, 'icon') && Reflect.has(data.icon, 'iconType'))
|
||||
this.icon_type = data.icon.iconType;
|
||||
}
|
||||
|
||||
if (Reflect.has(data, 'isDisabled')) {
|
||||
if (Reflect.has(data, 'isDisabled'))
|
||||
this.is_disabled = data.isDisabled;
|
||||
}
|
||||
|
||||
this.endpoint = new NavigationEndpoint(data.navigationEndpoint || data.serviceEndpoint || data.command);
|
||||
}
|
||||
|
||||
16
deno/src/parser/classes/ContentPreviewImageView.ts
Normal file
16
deno/src/parser/classes/ContentPreviewImageView.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { YTNode } from '../helpers.ts';
|
||||
import type { RawNode } from '../index.ts';
|
||||
import Thumbnail from './misc/Thumbnail.ts';
|
||||
|
||||
export default class ContentPreviewImageView extends YTNode {
|
||||
static type = 'ContentPreviewImageView';
|
||||
|
||||
image: Thumbnail[];
|
||||
style: string;
|
||||
|
||||
constructor(data: RawNode) {
|
||||
super();
|
||||
this.image = data.image.sources.map((x: any) => new Thumbnail(x)).sort((a: Thumbnail, b: Thumbnail) => b.width - a.width);
|
||||
this.style = data.style;
|
||||
}
|
||||
}
|
||||
13
deno/src/parser/classes/DynamicTextView.ts
Normal file
13
deno/src/parser/classes/DynamicTextView.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { YTNode } from '../helpers.ts';
|
||||
import type { RawNode } from '../index.ts';
|
||||
|
||||
export default class DynamicTextView extends YTNode {
|
||||
static type = 'DynamicTextView';
|
||||
|
||||
text: string;
|
||||
|
||||
constructor(data: RawNode) {
|
||||
super();
|
||||
this.text = data.text.content;
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,14 @@ import { YTNode } from '../helpers.ts';
|
||||
import Parser, { type RawNode } from '../index.ts';
|
||||
import type { IParsedResponse } from '../types/ParsedResponse.ts';
|
||||
import CreatePlaylistDialog from './CreatePlaylistDialog.ts';
|
||||
import OpenPopupAction from './actions/OpenPopupAction.ts';
|
||||
|
||||
export default class NavigationEndpoint extends YTNode {
|
||||
static type = 'NavigationEndpoint';
|
||||
|
||||
payload;
|
||||
dialog?: CreatePlaylistDialog | YTNode | null;
|
||||
open_popup?: OpenPopupAction | null;
|
||||
|
||||
metadata: {
|
||||
url?: string;
|
||||
@@ -24,6 +26,9 @@ export default class NavigationEndpoint extends YTNode {
|
||||
if (Reflect.has(data || {}, 'innertubeCommand'))
|
||||
data = data.innertubeCommand;
|
||||
|
||||
if (Reflect.has(data || {}, 'openPopupAction'))
|
||||
this.open_popup = new OpenPopupAction(data.openPopupAction);
|
||||
|
||||
const name = Object.keys(data || {})
|
||||
.find((item) =>
|
||||
item.endsWith('Endpoint') ||
|
||||
@@ -36,6 +41,7 @@ export default class NavigationEndpoint extends YTNode {
|
||||
this.dialog = Parser.parseItem(this.payload.dialog || this.payload.content);
|
||||
}
|
||||
|
||||
|
||||
if (data?.serviceEndpoint) {
|
||||
data = data.serviceEndpoint;
|
||||
}
|
||||
@@ -85,9 +91,9 @@ export default class NavigationEndpoint extends YTNode {
|
||||
}
|
||||
}
|
||||
|
||||
call<T extends IParsedResponse>(actions: Actions, args: { [ key: string ]: any; parse: true }): Promise<T>;
|
||||
call(actions: Actions, args?: { [ key: string ]: any; parse?: false }): Promise<ApiResponse>;
|
||||
call(actions: Actions, args?: { [ key: string ]: any; parse?: boolean }): Promise<IParsedResponse | ApiResponse> {
|
||||
call<T extends IParsedResponse>(actions: Actions, args: { [key: string]: any; parse: true }): Promise<T>;
|
||||
call(actions: Actions, args?: { [key: string]: any; parse?: false }): Promise<ApiResponse>;
|
||||
call(actions: Actions, args?: { [key: string]: any; parse?: boolean }): Promise<IParsedResponse | ApiResponse> {
|
||||
if (!actions)
|
||||
throw new Error('An active caller must be provided');
|
||||
if (!this.metadata.api_url)
|
||||
|
||||
16
deno/src/parser/classes/PageHeader.ts
Normal file
16
deno/src/parser/classes/PageHeader.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { YTNode } from '../helpers.ts';
|
||||
import Parser, { type RawNode } from '../index.ts';
|
||||
import PageHeaderView from './PageHeaderView.ts';
|
||||
|
||||
export default class PageHeader extends YTNode {
|
||||
static type = 'PageHeader';
|
||||
|
||||
page_title: string;
|
||||
content: PageHeaderView | null;
|
||||
|
||||
constructor(data: RawNode) {
|
||||
super();
|
||||
this.page_title = data.pageTitle;
|
||||
this.content = Parser.parseItem(data.content, PageHeaderView);
|
||||
}
|
||||
}
|
||||
17
deno/src/parser/classes/PageHeaderView.ts
Normal file
17
deno/src/parser/classes/PageHeaderView.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { YTNode } from '../helpers.ts';
|
||||
import Parser, { type RawNode } from '../index.ts';
|
||||
import ContentPreviewImageView from './ContentPreviewImageView.ts';
|
||||
import DynamicTextView from './DynamicTextView.ts';
|
||||
|
||||
export default class PageHeaderView extends YTNode {
|
||||
static type = 'PageHeaderView';
|
||||
|
||||
image: ContentPreviewImageView | null;
|
||||
title: DynamicTextView | null;
|
||||
|
||||
constructor(data: RawNode) {
|
||||
super();
|
||||
this.image = Parser.parseItem(data.image, ContentPreviewImageView);
|
||||
this.title = Parser.parseItem(data.title, DynamicTextView);
|
||||
}
|
||||
}
|
||||
18
deno/src/parser/classes/SearchFilterOptionsDialog.ts
Normal file
18
deno/src/parser/classes/SearchFilterOptionsDialog.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { ObservedArray } from '../helpers.ts';
|
||||
import { YTNode } from '../helpers.ts';
|
||||
import { Parser, type RawNode } from '../index.ts';
|
||||
import SearchFilterGroup from './SearchFilterGroup.ts';
|
||||
import Text from './misc/Text.ts';
|
||||
|
||||
export default class SearchFilterOptionsDialog extends YTNode {
|
||||
static type = 'SearchFilterOptionsDialog';
|
||||
|
||||
title: Text;
|
||||
groups: ObservedArray<SearchFilterGroup>;
|
||||
|
||||
constructor(data: RawNode) {
|
||||
super();
|
||||
this.title = new Text(data.title);
|
||||
this.groups = Parser.parseArray(data.groups, SearchFilterGroup);
|
||||
}
|
||||
}
|
||||
18
deno/src/parser/classes/SearchHeader.ts
Normal file
18
deno/src/parser/classes/SearchHeader.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { YTNode } from '../helpers.ts';
|
||||
import { Parser, type RawNode } from '../index.ts';
|
||||
import Button from './Button.ts';
|
||||
import ChipCloud from './ChipCloud.ts';
|
||||
|
||||
export default class SearchHeader extends YTNode {
|
||||
static type = 'SearchHeader';
|
||||
|
||||
chip_bar: ChipCloud | null;
|
||||
search_filter_button: Button | null;
|
||||
|
||||
constructor(data: RawNode) {
|
||||
super();
|
||||
this.chip_bar = Parser.parseItem(data.chipBar, ChipCloud);
|
||||
this.search_filter_button = Parser.parseItem(data.searchFilterButton, Button);
|
||||
console.log(this.search_filter_button?.endpoint.open_popup);
|
||||
}
|
||||
}
|
||||
@@ -8,14 +8,19 @@ import ToggleButton from './ToggleButton.ts';
|
||||
export default class SearchSubMenu extends YTNode {
|
||||
static type = 'SearchSubMenu';
|
||||
|
||||
title: Text;
|
||||
groups: ObservedArray<SearchFilterGroup>;
|
||||
button: ToggleButton | null;
|
||||
title?: Text;
|
||||
groups?: ObservedArray<SearchFilterGroup>;
|
||||
button?: ToggleButton | null;
|
||||
|
||||
constructor(data: RawNode) {
|
||||
super();
|
||||
this.title = new Text(data.title);
|
||||
this.groups = Parser.parseArray(data.groups, SearchFilterGroup);
|
||||
this.button = Parser.parseItem(data.button, ToggleButton);
|
||||
if (Reflect.has(data, 'title'))
|
||||
this.title = new Text(data.title);
|
||||
|
||||
if (!Reflect.has(data, 'groups'))
|
||||
this.groups = Parser.parseArray(data.groups, SearchFilterGroup);
|
||||
|
||||
if (Reflect.has(data, 'button'))
|
||||
this.button = Parser.parseItem(data.button, ToggleButton);
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,7 @@ export { default as CompactPlaylist } from './classes/CompactPlaylist.ts';
|
||||
export { default as CompactStation } from './classes/CompactStation.ts';
|
||||
export { default as CompactVideo } from './classes/CompactVideo.ts';
|
||||
export { default as ConfirmDialog } from './classes/ConfirmDialog.ts';
|
||||
export { default as ContentPreviewImageView } from './classes/ContentPreviewImageView.ts';
|
||||
export { default as ContinuationItem } from './classes/ContinuationItem.ts';
|
||||
export { default as ConversationBar } from './classes/ConversationBar.ts';
|
||||
export { default as CopyLink } from './classes/CopyLink.ts';
|
||||
@@ -81,6 +82,7 @@ export { default as DidYouMean } from './classes/DidYouMean.ts';
|
||||
export { default as DownloadButton } from './classes/DownloadButton.ts';
|
||||
export { default as Dropdown } from './classes/Dropdown.ts';
|
||||
export { default as DropdownItem } from './classes/DropdownItem.ts';
|
||||
export { default as DynamicTextView } from './classes/DynamicTextView.ts';
|
||||
export { default as Element } from './classes/Element.ts';
|
||||
export { default as EmergencyOnebox } from './classes/EmergencyOnebox.ts';
|
||||
export { default as EmojiPickerCategory } from './classes/EmojiPickerCategory.ts';
|
||||
@@ -238,6 +240,8 @@ export { default as MusicTwoRowItem } from './classes/MusicTwoRowItem.ts';
|
||||
export { default as MusicVisualHeader } from './classes/MusicVisualHeader.ts';
|
||||
export { default as NavigationEndpoint } from './classes/NavigationEndpoint.ts';
|
||||
export { default as Notification } from './classes/Notification.ts';
|
||||
export { default as PageHeader } from './classes/PageHeader.ts';
|
||||
export { default as PageHeaderView } from './classes/PageHeaderView.ts';
|
||||
export { default as PageIntroduction } from './classes/PageIntroduction.ts';
|
||||
export { default as PlayerAnnotationsExpanded } from './classes/PlayerAnnotationsExpanded.ts';
|
||||
export { default as PlayerCaptionsTracklist } from './classes/PlayerCaptionsTracklist.ts';
|
||||
@@ -285,6 +289,8 @@ export { default as RichShelf } from './classes/RichShelf.ts';
|
||||
export { default as SearchBox } from './classes/SearchBox.ts';
|
||||
export { default as SearchFilter } from './classes/SearchFilter.ts';
|
||||
export { default as SearchFilterGroup } from './classes/SearchFilterGroup.ts';
|
||||
export { default as SearchFilterOptionsDialog } from './classes/SearchFilterOptionsDialog.ts';
|
||||
export { default as SearchHeader } from './classes/SearchHeader.ts';
|
||||
export { default as SearchRefinementCard } from './classes/SearchRefinementCard.ts';
|
||||
export { default as SearchSubMenu } from './classes/SearchSubMenu.ts';
|
||||
export { default as SearchSuggestion } from './classes/SearchSuggestion.ts';
|
||||
|
||||
@@ -9,6 +9,7 @@ import SubscribeButton from '../classes/SubscribeButton.ts';
|
||||
import ExpandableTab from '../classes/ExpandableTab.ts';
|
||||
import SectionList from '../classes/SectionList.ts';
|
||||
import Tab from '../classes/Tab.ts';
|
||||
import PageHeader from '../classes/PageHeader.ts';
|
||||
|
||||
import Feed from '../../core/mixins/Feed.ts';
|
||||
import FilterableFeed from '../../core/mixins/FilterableFeed.ts';
|
||||
@@ -25,7 +26,7 @@ import type { ApiResponse } from '../../core/Actions.ts';
|
||||
import type { IBrowseResponse } from '../types/index.ts';
|
||||
|
||||
export default class Channel extends TabbedFeed<IBrowseResponse> {
|
||||
header?: C4TabbedHeader | CarouselHeader | InteractiveTabbedHeader;
|
||||
header?: C4TabbedHeader | CarouselHeader | InteractiveTabbedHeader | PageHeader;
|
||||
metadata;
|
||||
subscribe_button?: SubscribeButton;
|
||||
current_tab?: Tab | ExpandableTab;
|
||||
@@ -33,7 +34,7 @@ export default class Channel extends TabbedFeed<IBrowseResponse> {
|
||||
constructor(actions: Actions, data: ApiResponse | IBrowseResponse, already_parsed = false) {
|
||||
super(actions, data, already_parsed);
|
||||
|
||||
this.header = this.page.header?.item()?.as(C4TabbedHeader, CarouselHeader, InteractiveTabbedHeader);
|
||||
this.header = this.page.header?.item()?.as(C4TabbedHeader, CarouselHeader, InteractiveTabbedHeader, PageHeader);
|
||||
|
||||
const metadata = this.page.metadata?.item().as(ChannelMetadata);
|
||||
const microformat = this.page.microformat?.as(MicroformatData);
|
||||
|
||||
@@ -2,6 +2,7 @@ import Feed from '../../core/mixins/Feed.ts';
|
||||
import { InnertubeError } from '../../utils/Utils.ts';
|
||||
import HorizontalCardList from '../classes/HorizontalCardList.ts';
|
||||
import ItemSection from '../classes/ItemSection.ts';
|
||||
import SearchHeader from '../classes/SearchHeader.ts';
|
||||
import SearchRefinementCard from '../classes/SearchRefinementCard.ts';
|
||||
import SearchSubMenu from '../classes/SearchSubMenu.ts';
|
||||
import SectionList from '../classes/SectionList.ts';
|
||||
@@ -11,8 +12,8 @@ import type Actions from '../../core/Actions.ts';
|
||||
import type { ApiResponse } from '../../core/Actions.ts';
|
||||
import type { ObservedArray, YTNode } from '../helpers.ts';
|
||||
import type { ISearchResponse } from '../types/ParsedResponse.ts';
|
||||
|
||||
class Search extends Feed<ISearchResponse> {
|
||||
header?: SearchHeader;
|
||||
results?: ObservedArray<YTNode> | null;
|
||||
refinements: string[];
|
||||
estimated_results: number;
|
||||
@@ -30,6 +31,9 @@ class Search extends Feed<ISearchResponse> {
|
||||
if (!contents)
|
||||
throw new InnertubeError('No contents found in search response');
|
||||
|
||||
if (this.page.header)
|
||||
this.header = this.page.header.item().as(SearchHeader);
|
||||
|
||||
this.results = contents.find((content) => content.is(ItemSection) && content.contents && content.contents.length > 0)?.as(ItemSection).contents;
|
||||
|
||||
this.refinements = this.page.refinements || [];
|
||||
|
||||
Reference in New Issue
Block a user