fix(ytmusic): fix music#getLyrics() & music#getUpNext()

These were broken due to recent changes in the parser — both should be fixed now. Note that `music#getRelated()` is still broken.
This commit is contained in:
LuanRT
2022-07-30 05:37:23 -03:00
parent c66940ae65
commit 4d332402db
4 changed files with 57 additions and 38 deletions

View File

@@ -9,14 +9,23 @@ import Album from '../parser/ytmusic/Album';
import Parser from '../parser/index';
import { observe, YTNode } from '../parser/helpers';
import Tab from '../parser/classes/Tab';
import SingleColumnBrowseResults from '../parser/classes/SingleColumnBrowseResults';
import TabbedSearchResults from '../parser/classes/TabbedSearchResults';
import TwoColumnBrowseResults from '../parser/classes/TwoColumnBrowseResults';
import SearchSuggestionsSection from '../parser/classes/SearchSuggestionsSection';
import NavigationEndpoint from '../parser/classes/NavigationEndpoint';
import MusicQueue from '../parser/classes/MusicQueue';
import PlaylistPanel from '../parser/classes/PlaylistPanel';
import Message from '../parser/classes/Message';
import MusicDescriptionShelf from '../parser/classes/MusicDescriptionShelf';
import MusicCarouselShelf from '../parser/classes/MusicCarouselShelf';
import SearchSuggestionsSection from '../parser/classes/SearchSuggestionsSection';
import Tab from '../parser/classes/Tab';
import Tabbed from '../parser/classes/Tabbed';
import SingleColumnBrowseResults from '../parser/classes/SingleColumnBrowseResults';
import SingleColumnMusicWatchNextResults from '../parser/classes/SingleColumnMusicWatchNextResults';
import TabbedSearchResults from '../parser/classes/TabbedSearchResults';
import WatchNextTabbedResults from '../parser/classes/WatchNextTabbedResults';
import TwoColumnBrowseResults from '../parser/classes/TwoColumnBrowseResults';
import SectionList from '../parser/classes/SectionList';
import NavigationEndpoint from '../parser/classes/NavigationEndpoint';
import { InnertubeError, throwIfMissing } from '../utils/Utils';
@@ -99,21 +108,28 @@ class Music {
const response = await this.#actions.next({ video_id, client: 'YTMUSIC' });
const data = Parser.parseResponse(response.data);
const node = data.contents.item();
if (!node.is(SingleColumnBrowseResults, TabbedSearchResults, TwoColumnBrowseResults))
throw new InnertubeError('Invalid id', video_id);
const tabs = data.contents.item()
.as(SingleColumnMusicWatchNextResults).contents.item()
.as(Tabbed).contents.item()
.as(WatchNextTabbedResults)
.tabs.array().as(Tab);
const tab = node.tabs.array().get({ title: 'Lyrics' });
const page = await tab?.key('endpoint').nodeOfType(NavigationEndpoint).call(this.#actions, 'YTMUSIC', true);
const tab = tabs.get({ title: 'Lyrics' })?.as(Tab);
if (!tab)
throw new InnertubeError('Could not find target tab.');
const page = await tab.endpoint.call(this.#actions, 'YTMUSIC', true);
if (!page)
throw new InnertubeError('Invalid video id');
throw new InnertubeError('Could not retrieve tab contents, the given id may be invalid or is not a song.');
if (page.contents.constructor.name === 'Message')
throw new InnertubeError(page.contents.item().key('text').any(), video_id);
if (page.contents.item().key('type').string() === 'Message')
throw new InnertubeError(page.contents.item().as(Message).text, video_id);
const description_shelf = page.contents.item().key('contents').parsed().array().get({ type: 'MusicDescriptionShelf' })?.as(MusicDescriptionShelf);
const section_list = page.contents.item().as(SectionList).contents.array();
const description_shelf = section_list.firstOfType(MusicDescriptionShelf);
return {
text: description_shelf?.description.toString(),
@@ -130,25 +146,26 @@ class Music {
const response = await this.#actions.next({ video_id, client: 'YTMUSIC' });
const data = Parser.parseResponse(response.data);
const node = data.contents.item();
if (!node.is(SingleColumnBrowseResults, TabbedSearchResults, TwoColumnBrowseResults))
throw new InnertubeError('Invalid id', video_id);
const tabs = data.contents.item()
.as(SingleColumnMusicWatchNextResults).contents.item()
.as(Tabbed).contents.item()
.as(WatchNextTabbedResults)
.tabs.array().as(Tab);
const tab = node.tabs.array().get({ title: 'Up next' });
const tab = tabs.get({ title: 'Up next' })?.as(Tab);
// TODO: verify this is a Tab
const upnext_content = tab?.as(Tab).content.item().key('content').any();
if (!tab)
throw new InnertubeError('Could not find target tab.');
if (!upnext_content)
throw new InnertubeError('Invalid id', video_id);
const music_queue = tab.content.item().as(MusicQueue);
return {
id: upnext_content.playlist_id,
title: upnext_content.title,
is_editable: upnext_content.is_editable,
contents: observe(upnext_content.contents)
};
if (!music_queue.content)
throw new InnertubeError('Music queue was empty, the given id is probably invalid.', music_queue);
const playlist_panel = music_queue.content.item().as(PlaylistPanel);
return playlist_panel;
}
/**

View File

@@ -21,8 +21,8 @@ class PlaylistPanelVideo extends YTNode {
seconds: timeToSeconds(new Text(data.lengthText).toString())
};
const album = new Text(data.longBylineText).runs.find((run) => run.endpoint?.browse?.id.startsWith('MPR'));
const artists = new Text(data.longBylineText).runs.filter((run) => run.endpoint?.browse?.id.startsWith('UC'));
const album = new Text(data.longBylineText).runs?.find((run) => run.endpoint?.browse?.id.startsWith('MPR'));
const artists = new Text(data.longBylineText).runs?.filter((run) => run.endpoint?.browse?.id.startsWith('UC'));
this.author = new Text(data.shortBylineText).toString();
@@ -35,11 +35,13 @@ class PlaylistPanelVideo extends YTNode {
};
}
this.artists = artists.map((artist) => ({
name: artist.text,
channel_id: artist.endpoint?.browse.id,
endpoint: artist.endpoint
}));
if (artists) {
this.artists = artists.map((artist) => ({
name: artist.text,
channel_id: artist.endpoint?.browse.id,
endpoint: artist.endpoint
}));
}
this.badges = Parser.parse(data.badges);
this.menu = Parser.parse(data.menu);

View File

@@ -6,7 +6,7 @@ class SingleColumnMusicWatchNextResults extends YTNode {
constructor(data) {
super();
return Parser.parse(data);
this.contents = Parser.parse(data);
}
}

View File

@@ -6,7 +6,7 @@ class Tabbed extends YTNode {
constructor(data) {
super();
return Parser.parse(data);
this.contents = Parser.parse(data);
}
}