Skip to content

Commit

Permalink
chore: merge branch 'main' into Wykerd-jit-nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
Wykerd committed Mar 8, 2023
2 parents 92e5f99 + 197bb75 commit 65b057f
Show file tree
Hide file tree
Showing 121 changed files with 691 additions and 191 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Changelog

## [3.2.0](https://github.com/LuanRT/YouTube.js/compare/v3.1.1...v3.2.0) (2023-03-08)


### Features

* Add support for descriptive audio tracks ([#338](https://github.com/LuanRT/YouTube.js/issues/338)) ([574b67a](https://github.com/LuanRT/YouTube.js/commit/574b67a1f707a32378586dd2fe7b2f36f4ab6ddb))
* export `FormatUtils`' types ([2d774e2](https://github.com/LuanRT/YouTube.js/commit/2d774e26aae79f3d1b115e0e85c148ae80985529))
* **parser:** add `banner` to `PlaylistHeader` ([#337](https://github.com/LuanRT/YouTube.js/issues/337)) ([95033e7](https://github.com/LuanRT/YouTube.js/commit/95033e723ef912706e4d176de6b2760f017184e1))
* **parser:** SharedPost ([#332](https://github.com/LuanRT/YouTube.js/issues/332)) ([ce53ac1](https://github.com/LuanRT/YouTube.js/commit/ce53ac18435cbcb20d6d4c4ab52fd156091e7592))
* **VideoInfo:** add `game_info` and `category` ([#333](https://github.com/LuanRT/YouTube.js/issues/333)) ([214aa14](https://github.com/LuanRT/YouTube.js/commit/214aa147ce6306e37a6bf860a7bed5635db4797e))
* **YouTube/Search:** add `SearchSubMenu` node ([#340](https://github.com/LuanRT/YouTube.js/issues/340)) ([a511608](https://github.com/LuanRT/YouTube.js/commit/a511608f18b37b0d9f2c7958ed5128330fabcfa0))
* **yt:** add `getGuide()` ([#335](https://github.com/LuanRT/YouTube.js/issues/335)) ([2cc7b8b](https://github.com/LuanRT/YouTube.js/commit/2cc7b8bcd6938c7fb3af4f854a1d78b86d153873))


### Bug Fixes

* **SegmentedLikeDislikeButton:** like/dislike buttons can also be a simple `Button` ([9b2738f](https://github.com/LuanRT/YouTube.js/commit/9b2738f1285b278c3e83541857651be9a6248288))
* **YouTube:** fix warnings when retrieving members-only content ([#341](https://github.com/LuanRT/YouTube.js/issues/341)) ([95f1d40](https://github.com/LuanRT/YouTube.js/commit/95f1d4077ff3775f36967dca786139a09e2830a2))
* **ytmusic:** export search filters type ([cf8a33c](https://github.com/LuanRT/YouTube.js/commit/cf8a33c79f5432136b865d535fd0ecedc2393382))

## [3.1.1](https://github.com/LuanRT/YouTube.js/compare/v3.1.0...v3.1.1) (2023-03-01)


Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -426,6 +427,12 @@ Retrieves YouTube's home feed.
</p>
</details>

<a name="getguide"></a>
### getGuide()
Retrieves YouTube's content guide.

**Returns**: `Promise<Guide>`

<a name="getlibrary"></a>
### getLibrary()
Retrieves the account's library.
Expand Down
14 changes: 9 additions & 5 deletions docs/updating-the-parser.md
Original file line number Diff line number Diff line change
@@ -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!
Expand All @@ -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);
Expand All @@ -47,8 +50,9 @@ export default VerticalList;
```

Then update the parser map:

```bash
npm run build:parser-map
```

And that's it!
And that's it!
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "youtubei.js",
"version": "3.1.1",
"version": "3.2.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",
Expand Down
9 changes: 9 additions & 0 deletions src/Innertube.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -170,6 +171,14 @@ class Innertube {
return new HomeFeed(this.actions, response);
}

/**
* Retrieves YouTube's content guide.
*/
async getGuide(): Promise<Guide> {
const response = await this.actions.execute('/guide');
return new Guide(response.data);
}

/**
* Returns the account's library.
*/
Expand Down
3 changes: 2 additions & 1 deletion src/core/Feed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -100,7 +101,7 @@ class Feed<T extends IParsedResponse = IParsedResponse> {
* Get all the community posts in the feed
*/
get posts() {
return this.#memo.getType<Post | BackstagePost>([ BackstagePost, Post ]);
return this.#memo.getType<Post | BackstagePost | SharedPost>([ BackstagePost, Post, SharedPost ]);
}

/**
Expand Down
8 changes: 5 additions & 3 deletions src/core/Music.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ import type { ObservedArray, YTNode } from '../parser/helpers.js';
import type Actions from './Actions.js';
import type Session from './Session.js';

export type SearchFilters = {
type?: 'all' | 'song' | 'video' | 'album' | 'playlist' | 'artist';
};

class Music {
#session: Session;
#actions: Actions;
Expand Down Expand Up @@ -108,9 +112,7 @@ class Music {
* @param query - Search query.
* @param filters - Search filters.
*/
async search(query: string, filters: {
type?: 'all' | 'song' | 'video' | 'album' | 'playlist' | 'artist';
} = {}): Promise<Search> {
async search(query: string, filters: SearchFilters = {}): Promise<Search> {
throwIfMissing({ query });

const payload: {
Expand Down
3 changes: 2 additions & 1 deletion src/parser/classes/AccountChannel.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
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';

title: Text;
endpoint: NavigationEndpoint;

constructor(data: any) {
constructor(data: RawNode) {
super();
this.title = new Text(data.title);
this.endpoint = new NavigationEndpoint(data.navigationEndpoint);
Expand Down
5 changes: 3 additions & 2 deletions src/parser/classes/AccountItemSection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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;
Expand All @@ -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<AccountItemSectionHeader>(data.header, AccountItemSectionHeader);
Expand Down
4 changes: 2 additions & 2 deletions src/parser/classes/AccountItemSectionHeader.ts
Original file line number Diff line number Diff line change
@@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions src/parser/classes/AccountSectionList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<AccountItemSection>(data.contents[0], AccountItemSection);
this.footers = Parser.parseItem<AccountChannel>(data.footers[0], AccountChannel);
Expand Down
4 changes: 2 additions & 2 deletions src/parser/classes/Alert.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/parser/classes/AudioOnlyPlayability.ts
Original file line number Diff line number Diff line change
@@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions src/parser/classes/AutomixPreviewVideo.ts
Original file line number Diff line number Diff line change
@@ -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 = {
Expand Down
35 changes: 35 additions & 0 deletions src/parser/classes/GuideCollapsibleEntry.ts
Original file line number Diff line number Diff line change
@@ -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;
23 changes: 23 additions & 0 deletions src/parser/classes/GuideCollapsibleSectionEntry.ts
Original file line number Diff line number Diff line change
@@ -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;
14 changes: 14 additions & 0 deletions src/parser/classes/GuideDownloadsEntry.ts
Original file line number Diff line number Diff line change
@@ -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;
Loading

0 comments on commit 65b057f

Please sign in to comment.