feat(ytmusic): add music#getInfo()

Already functional but still WIP.
This commit is contained in:
LuanRT
2022-08-04 16:49:20 -03:00
parent 3ff3d3c633
commit d5f34982f4
3 changed files with 89 additions and 0 deletions

View File

@@ -1,4 +1,7 @@
import Session from './Session';
import TrackInfo from '../parser/ytmusic/TrackInfo';
import Search from '../parser/ytmusic/Search';
import HomeFeed from '../parser/ytmusic/HomeFeed';
import Explore from '../parser/ytmusic/Explore';
@@ -31,6 +34,17 @@ class Music {
this.#actions = session.actions;
}
/**
* Retrieves track info.
*/
async getInfo(video_id: string) {
const initial_info = this.#actions.execute('/player', { client: 'YTMUSIC', videoId: video_id });
const continuation = this.#actions.execute('/next', { client: 'YTMUSIC', videoId: video_id });
const response = await Promise.all([ initial_info, continuation ]);
return new TrackInfo(response, this.#actions);
}
/**
* Searches on YouTube Music.
*/

View File

@@ -3,6 +3,7 @@ import VideoDetails from './classes/misc/VideoDetails';
import GetParserByName from './map';
import Endscreen from './classes/Endscreen';
import CardCollection from './classes/CardCollection';
import NavigationEndpoint from './classes/NavigationEndpoint';
import { InnertubeError, ParsingError } from '../utils/Utils';
import { YTNode, YTNodeConstructor, SuperParsedResult, ObservedArray, observe, Memo } from './helpers';
@@ -197,6 +198,7 @@ export default class Parser {
dash_manifest_url: data.streamingData?.dashManifestUrl || null,
dls_manifest_url: data.streamingData?.dashManifestUrl || null
} : undefined,
current_video_endpoint: data.currentVideoEndpoint ? new NavigationEndpoint(data.currentVideoEndpoint) : null,
// TODO: PlayerCaptionsTracklist ?
captions: Parser.parse(data.captions),
video_details: data.videoDetails ? new VideoDetails(data.videoDetails) : undefined,

View File

@@ -0,0 +1,73 @@
import Parser, { ParsedResponse } from '..';
import Actions, { AxioslikeResponse } from '../../core/Actions';
import { InnertubeError } from '../../utils/Utils';
import Tab from '../classes/Tab';
import Tabbed from '../classes/Tabbed';
import WatchNextTabbedResults from '../classes/WatchNextTabbedResults';
import SingleColumnMusicWatchNextResults from '../classes/SingleColumnMusicWatchNextResults';
import MicroformatData from '../classes/MicroformatData';
import PlayerOverlay from '../classes/PlayerOverlay';
// TODO: add a way to get specific tabs
class TrackInfo {
#page: [ ParsedResponse, ParsedResponse? ];
#actions: Actions;
basic_info;
streaming_data;
playability_status;
storyboards;
endscreen;
tabs;
current_video_endpoint;
constructor(data: [AxioslikeResponse, AxioslikeResponse?], actions: Actions) {
this.#actions = actions;
const info = Parser.parseResponse(data[0].data);
const next = data?.[1]?.data ? Parser.parseResponse(data[1].data) : undefined;
this.#page = [ info, next ];
if (info.playability_status?.status === 'ERROR')
throw new InnertubeError('This video is unavailable', info.playability_status);
if (!info.microformat?.is(MicroformatData))
throw new InnertubeError('Invalid microformat', info.microformat);
this.basic_info = {
...info.video_details,
...{
description: info.microformat?.description,
is_unlisted: info.microformat?.is_unlisted,
is_family_safe: info.microformat?.is_family_safe,
url_canonical: info.microformat?.url_canonical,
tags: info.microformat?.tags
}
};
this.streaming_data = info.streaming_data;
this.playability_status = info.playability_status;
this.storyboards = info.storyboards;
this.endscreen = info.endscreen;
if (next) {
const single_col = next.contents.item().as(SingleColumnMusicWatchNextResults);
const tabbed_results = single_col.contents.item().as(Tabbed).contents.item().as(WatchNextTabbedResults);
this.tabs = tabbed_results.tabs.array().as(Tab);
this.current_video_endpoint = next.current_video_endpoint;
// TODO: update PlayerOverlay, YTMusic's is a little bit different.
this.player_overlays = next.player_overlays.item().as(PlayerOverlay);
}
}
get page() {
return this.#page;
}
}
export default TrackInfo;