Skip to content

Commit

Permalink
fix(music#getPlaylist): Handle ContinuationItem nodes
Browse files Browse the repository at this point in the history
Closes #904
  • Loading branch information
LuanRT committed Feb 21, 2025
1 parent ca7c316 commit a3fafe2
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 24 deletions.
13 changes: 7 additions & 6 deletions src/parser/classes/MusicPlaylistShelf.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { YTNode, type ObservedArray } from '../helpers.js';
import { type ObservedArray, YTNode } from '../helpers.js';
import { Parser, type RawNode } from '../index.js';
import MusicResponsiveListItem from './MusicResponsiveListItem.js';
import ContinuationItem from './ContinuationItem.js';

export default class MusicPlaylistShelf extends YTNode {
static type = 'MusicPlaylistShelf';

playlist_id: string;
contents: ObservedArray<MusicResponsiveListItem>;
collapsed_item_count: number;
continuation: string | null;
public playlist_id: string;
public contents: ObservedArray<MusicResponsiveListItem | ContinuationItem>;
public collapsed_item_count: number;
public continuation: string | null;

constructor(data: RawNode) {
super();
this.playlist_id = data.playlistId;
this.contents = Parser.parseArray(data.contents, MusicResponsiveListItem);
this.contents = Parser.parseArray(data.contents, [ MusicResponsiveListItem, ContinuationItem ]);
this.collapsed_item_count = data.collapsedItemCount;
this.continuation = data.continuations?.[0]?.nextContinuationData?.continuation || null;
}
Expand Down
46 changes: 29 additions & 17 deletions src/parser/ytmusic/Playlist.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// noinspection ES6MissingAwait

import { Parser, MusicPlaylistShelfContinuation, SectionListContinuation } from '../index.js';
import { MusicPlaylistShelfContinuation, Parser, SectionListContinuation } from '../index.js';

import MusicCarouselShelf from '../classes/MusicCarouselShelf.js';
import MusicDetailHeader from '../classes/MusicDetailHeader.js';
Expand All @@ -13,17 +13,19 @@ import MusicResponsiveHeader from '../classes/MusicResponsiveHeader.js';

import { InnertubeError } from '../../utils/Utils.js';
import { observe, type ObservedArray } from '../helpers.js';
import type { ApiResponse, Actions } from '../../core/index.js';
import type { Actions, ApiResponse } from '../../core/index.js';
import type { IBrowseResponse } from '../types/index.js';
import type MusicThumbnail from '../classes/MusicThumbnail.js';
import ContinuationItem from '../classes/ContinuationItem.js';
import AppendContinuationItemsAction from '../classes/actions/AppendContinuationItemsAction.js';

export default class Playlist {
readonly #page: IBrowseResponse;
readonly #actions: Actions;
readonly #continuation: string | null;
readonly #continuation?: string | ContinuationItem;

public header?: MusicResponsiveHeader | MusicDetailHeader | MusicEditablePlaylistDetailHeader;
public contents?: ObservedArray<MusicResponsiveListItem>;
public contents?: ObservedArray<MusicResponsiveListItem | ContinuationItem>;
public background?: MusicThumbnail;

#last_fetched_suggestions: ObservedArray<MusicResponsiveListItem> | null;
Expand All @@ -40,15 +42,19 @@ export default class Playlist {
const data = this.#page.continuation_contents?.as(MusicPlaylistShelfContinuation);
if (!data.contents)
throw new InnertubeError('No contents found in the response');
this.contents = data.contents.as(MusicResponsiveListItem);
this.#continuation = data.continuation;
} else {
if (!this.#page.contents_memo)
throw new InnertubeError('No contents found in the response');
this.contents = data.contents.as(MusicResponsiveListItem, ContinuationItem);
const continuation_item = this.contents.firstOfType(ContinuationItem);
this.#continuation = data.continuation || continuation_item;
} else if (this.#page.contents_memo) {
this.header = this.#page.contents_memo.getType(MusicResponsiveHeader, MusicEditablePlaylistDetailHeader, MusicDetailHeader)?.[0];
this.contents = this.#page.contents_memo.getType(MusicPlaylistShelf)?.[0]?.contents || observe([]);
this.contents = this.#page.contents_memo.getType(MusicPlaylistShelf)?.[0]?.contents.as(MusicResponsiveListItem, ContinuationItem) || observe([]);
this.background = this.#page.background;
this.#continuation = this.#page.contents_memo.getType(MusicPlaylistShelf)?.[0]?.continuation || null;
const continuation_item = this.contents.firstOfType(ContinuationItem);
this.#continuation = this.#page.contents_memo.getType(MusicPlaylistShelf)?.[0]?.continuation || continuation_item;
} else if (this.#page.on_response_received_actions) {
const append_continuation_action = this.#page.on_response_received_actions.firstOfType(AppendContinuationItemsAction);
this.contents = append_continuation_action?.contents?.as(MusicResponsiveListItem, ContinuationItem);
this.#continuation = this.contents?.firstOfType(ContinuationItem);
}
}

Expand All @@ -59,11 +65,17 @@ export default class Playlist {
if (!this.#continuation)
throw new InnertubeError('Continuation not found.');

const response = await this.#actions.execute('/browse', {
client: 'YTMUSIC',
continuation: this.#continuation
});

let response: ApiResponse;

if (typeof this.#continuation === 'string') {
response = await this.#actions.execute('/browse', {
client: 'YTMUSIC',
continuation: this.#continuation
});
} else {
response = await this.#continuation.endpoint.call(this.#actions, { client: 'YTMUSIC' });
}

return new Playlist(response, this.#actions);
}

Expand Down Expand Up @@ -144,7 +156,7 @@ export default class Playlist {
return this.#page;
}

get items(): ObservedArray<MusicResponsiveListItem> {
get items(): ObservedArray<MusicResponsiveListItem | ContinuationItem> {
return this.contents || observe([]);
}

Expand Down
2 changes: 1 addition & 1 deletion src/utils/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const CLIENTS = {
},
YTMUSIC: {
NAME: 'WEB_REMIX',
VERSION: '1.20211213.00.00'
VERSION: '1.20250219.01.00'
},
ANDROID: {
NAME: 'ANDROID',
Expand Down

0 comments on commit a3fafe2

Please sign in to comment.