feat: extend music getInfo to allow MusicResponsiveListItem and Nav Endpoints (#751)

* feat: extend music getInfo to allow MusicResponsiveListItem nav endpoints

* chore: remove debug statements from test

* chore: adapt test

* feat: add nav endpoints to music getInfo

---------

Co-authored-by: Luan <luan.lrt4@gmail.com>
This commit is contained in:
Konstantin
2024-09-19 14:19:48 +02:00
committed by GitHub
parent 2e61b99428
commit 5db449cc6d
2 changed files with 39 additions and 9 deletions

View File

@@ -11,6 +11,8 @@ import Message from '../../parser/classes/Message.js';
import MusicDescriptionShelf from '../../parser/classes/MusicDescriptionShelf.js';
import MusicQueue from '../../parser/classes/MusicQueue.js';
import MusicTwoRowItem from '../../parser/classes/MusicTwoRowItem.js';
import MusicResponsiveListItem from '../../parser/classes/MusicResponsiveListItem.js';
import NavigationEndpoint from '../../parser/classes/NavigationEndpoint.js';
import PlaylistPanel from '../../parser/classes/PlaylistPanel.js';
import SearchSuggestionsSection from '../../parser/classes/SearchSuggestionsSection.js';
import SectionList from '../../parser/classes/SectionList.js';
@@ -44,9 +46,13 @@ export default class Music {
* Retrieves track info. Passing a list item of type MusicTwoRowItem automatically starts a radio.
* @param target - Video id or a list item.
*/
getInfo(target: string | MusicTwoRowItem): Promise<TrackInfo> {
getInfo(target: string | MusicTwoRowItem | MusicResponsiveListItem | NavigationEndpoint): Promise<TrackInfo> {
if (target instanceof MusicTwoRowItem) {
return this.#fetchInfoFromListItem(target);
return this.#fetchInfoFromEndpoint(target.endpoint);
} else if (target instanceof MusicResponsiveListItem) {
return this.#fetchInfoFromEndpoint(target.overlay?.content?.endpoint ?? target.endpoint);
} else if (target instanceof NavigationEndpoint) {
return this.#fetchInfoFromEndpoint(target);
} else if (typeof target === 'string') {
return this.#fetchInfoFromVideoId(target);
}
@@ -75,14 +81,11 @@ export default class Music {
return new TrackInfo(response, this.#actions, cpn);
}
async #fetchInfoFromListItem(list_item: MusicTwoRowItem | undefined): Promise<TrackInfo> {
if (!list_item)
throw new InnertubeError('List item cannot be undefined');
if (!list_item.endpoint)
async #fetchInfoFromEndpoint(endpoint?: NavigationEndpoint): Promise<TrackInfo> {
if (!endpoint)
throw new Error('This item does not have an endpoint.');
const player_response = list_item.endpoint.call(this.#actions, {
const player_response = endpoint.call(this.#actions, {
client: 'YTMUSIC',
playbackContext: {
contentPlaybackContext: {
@@ -93,7 +96,7 @@ export default class Music {
}
});
const next_response = list_item.endpoint.call(this.#actions, {
const next_response = endpoint.call(this.#actions, {
client: 'YTMUSIC',
enablePersistentPlaylistPanel: true,
override_endpoint: '/next'

View File

@@ -302,6 +302,33 @@ describe('YouTube.js Tests', () => {
// expect(info.basic_info.id).toBe('WSeNSzJ2-Jw');
// });
test('Innertube#music.getInfo.MusicResponsiveListItem', async () => {
const playlist = await innertube.music.getPlaylist('PLQxo8OvVvJ1WI_Bp67F2wdIl_R2Rc_1-u');
expect(playlist).toBeDefined();
expect(playlist.header).toBeDefined();
expect(playlist.contents).toBeDefined();
expect(playlist.contents?.length).toBeGreaterThan(0);
const info = await innertube.music.getInfo(playlist.contents!.first())
expect(info).toBeDefined();
});
test('Innertube#music.getInfo.NavEndpoint', async () => {
const playlist = await innertube.music.getPlaylist('PLQxo8OvVvJ1WI_Bp67F2wdIl_R2Rc_1-u');
expect(playlist).toBeDefined();
expect(playlist.header).toBeDefined();
expect(playlist.contents).toBeDefined();
expect(playlist.contents?.length).toBeGreaterThan(0);
const playlistPlayEndpoint = playlist.header!.as(YTNodes.MusicResponsiveHeader).buttons.firstOfType(YTNodes.MusicPlayButton)!.endpoint
const info = await innertube.music.getInfo(playlistPlayEndpoint)
expect(info).toBeDefined();
const upNext = await info.getUpNext();
expect(upNext.playlist_id).toBe("PLQxo8OvVvJ1WI_Bp67F2wdIl_R2Rc_1-u");
});
describe('Innertube#music.search', () => {
let search: YTMusic.Search;