Skip to content

Commit

Permalink
fix(VideoInfo): watch next feed not being parsed when logged out (#276)
Browse files Browse the repository at this point in the history
  • Loading branch information
LuanRT authored Jan 5, 2023
1 parent cd4d28c commit d69d701
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 11 deletions.
6 changes: 3 additions & 3 deletions src/parser/classes/TwoColumnWatchNextResults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ class TwoColumnWatchNextResults extends YTNode {

constructor(data: any) {
super();
this.results = Parser.parse(data.results?.results.contents, true);
this.secondary_results = Parser.parse(data.secondaryResults?.secondaryResults.results, true);
this.conversation_bar = Parser.parse(data?.conversationBar);
this.results = Parser.parseArray(data.results?.results.contents);
this.secondary_results = Parser.parseArray(data.secondaryResults?.secondaryResults.results);
this.conversation_bar = Parser.parseItem(data?.conversationBar);
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/parser/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,10 @@ export type ObservedArray<T extends YTNode = YTNode> = Array<T> & {
* Get the first of a specific type
*/
firstOfType<R extends YTNode, K extends YTNodeConstructor<R>[]>(...types: K): InstanceType<K[number]> | undefined;
/**
* Get the first item
*/
first: () => T | undefined;
/**
* This is similar to filter but throws if there's a type mismatch.
*/
Expand Down Expand Up @@ -435,6 +439,7 @@ export function observe<T extends YTNode>(obj: Array<T>): ObservedArray<T> {
};
}


if (prop == 'firstOfType') {
return (...types: YTNodeConstructor<YTNode>[]) => {
return target.find((node: YTNode) => {
Expand All @@ -445,6 +450,10 @@ export function observe<T extends YTNode>(obj: Array<T>): ObservedArray<T> {
};
}

if (prop == 'first') {
return () => target[0];
}

if (prop == 'as') {
return (...types: YTNodeConstructor<YTNode>[]) => {
return observe(target.map((node: YTNode) => {
Expand Down
30 changes: 22 additions & 8 deletions src/parser/youtube/VideoInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,11 @@ class VideoInfo {

this.basic_info = { // This type is inferred so no need for an explicit type
...info.video_details,
/**
* Microformat is a bit redundant, so only
* a few things there are interesting to us.
*/
...{
/**
* Microformat is a bit redundant, so only
* a few things there are interesting to us.
*/
embed: info.microformat?.is(PlayerMicroformat) ? info.microformat?.embed : null,
channel: info.microformat?.is(PlayerMicroformat) ? info.microformat?.channel : null,
is_unlisted: info.microformat?.is_unlisted,
Expand Down Expand Up @@ -162,7 +162,7 @@ class VideoInfo {
this.merchandise = results.firstOfType(MerchandiseShelf);
this.related_chip_cloud = secondary_results.firstOfType(RelatedChipCloud)?.content.item().as(ChipCloud);

this.watch_next_feed = secondary_results.firstOfType(ItemSection)?.contents;
this.watch_next_feed = actions.session.logged_in ? secondary_results.firstOfType(ItemSection)?.contents : secondary_results;

if (this.watch_next_feed && Array.isArray(this.watch_next_feed))
this.#watch_next_continuation = this.watch_next_feed.pop()?.as(ContinuationItem);
Expand All @@ -178,7 +178,7 @@ class VideoInfo {
const comments_entry_point = results.get({ target_id: 'comments-entry-point' })?.as(ItemSection);

this.comments_entry_point_header = comments_entry_point?.contents?.firstOfType(CommentsEntryPointHeader);
this.livechat = next?.contents_memo.getType(LiveChat)?.[0];
this.livechat = next?.contents_memo.getType(LiveChat).first();
}
}

Expand All @@ -187,6 +187,9 @@ class VideoInfo {
* @param target_filter - Filter to apply.
*/
async selectFilter(target_filter: string | ChipCloudChip | undefined): Promise<VideoInfo> {
if (!this.related_chip_cloud)
throw new InnertubeError('Chip cloud not found, cannot apply filter');

let cloud_chip: ChipCloudChip;

if (typeof target_filter === 'string') {
Expand Down Expand Up @@ -236,15 +239,19 @@ class VideoInfo {
return response;
}


/**
* Retrieves watch next feed continuation.
*/
async getWatchNextContinuation(): Promise<VideoInfo> {
if (!this.#watch_next_continuation)
throw new InnertubeError('Watch next feed continuation not found');

const response = await this.#watch_next_continuation?.endpoint.call(this.#actions, { parse: true });
const data = response?.on_response_received_endpoints?.get({ type: 'appendContinuationItemsAction' });

if (!data)
throw new InnertubeError('Continuation not found');
throw new InnertubeError('AppendContinuationItemsAction not found');

this.watch_next_feed = data?.contents;
this.#watch_next_continuation = this.watch_next_feed?.pop()?.as(ContinuationItem);
Expand Down Expand Up @@ -342,10 +349,17 @@ class VideoInfo {
return this.#cpn;
}

/**
* Checks if continuation is available for the watch next feed.
*/
get wn_has_continuation(): boolean {
return !!this.#watch_next_continuation;
}

/**
* Original parsed InnerTube response.
*/
get page(): [ ParsedResponse, ParsedResponse? ] {
get page(): [ParsedResponse, ParsedResponse?] {
return this.#page;
}

Expand Down
4 changes: 4 additions & 0 deletions test/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ describe('YouTube.js Tests', () => {
expect(heatmap).toBeDefined();
});

it('should have watch next feed', () => {
expect(info.watch_next_feed).toBeDefined();
});

it('should retrieve basic video info', async () => {
const b_info = await yt.getBasicInfo(VIDEOS[0].ID);
expect(b_info.basic_info.id).toBe(VIDEOS[0].ID);
Expand Down

0 comments on commit d69d701

Please sign in to comment.