WIP: add music_details
This commit is contained in:
parent
9b6c952fd3
commit
556575f5ff
9 changed files with 28554 additions and 0 deletions
|
|
@ -49,6 +49,7 @@ pub async fn download_testfiles(project_root: &Path) {
|
||||||
music_search_playlists(&testfiles).await;
|
music_search_playlists(&testfiles).await;
|
||||||
music_search_cont(&testfiles).await;
|
music_search_cont(&testfiles).await;
|
||||||
music_artist(&testfiles).await;
|
music_artist(&testfiles).await;
|
||||||
|
music_radio(&testfiles).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CLIENT_TYPES: [ClientType; 5] = [
|
const CLIENT_TYPES: [ClientType; 5] = [
|
||||||
|
|
@ -698,3 +699,17 @@ async fn music_artist(testfiles: &Path) {
|
||||||
rp.query().music_artist(id, true).await.unwrap();
|
rp.query().music_artist(id, true).await.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn music_radio(testfiles: &Path) {
|
||||||
|
for (name, id) in [("mv", "RDAMVMZeerrnuLi5E"), ("track", "RDAMVM7nigXQS1Xb0")] {
|
||||||
|
let mut json_path = testfiles.to_path_buf();
|
||||||
|
json_path.push("music_details");
|
||||||
|
json_path.push(format!("details_{}.json", name));
|
||||||
|
if json_path.exists() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let rp = rp_testfile(&json_path);
|
||||||
|
rp.query().music_radio(id).await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
9
notes/radios.txt
Normal file
9
notes/radios.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
Track radio: RDAMVM + video id
|
||||||
|
Example: RDAMVMZeerrnuLi5E
|
||||||
|
|
||||||
|
Artist radio: RDEMieiteXw81tMLBdKv8qkChg
|
||||||
|
ID has to be extracted from artist page
|
||||||
|
|
||||||
|
Playlist/album radio: RDAMPL + playlist id
|
||||||
|
|
||||||
|
Genre radio: RDQM1xqCV6EdPUw
|
||||||
|
|
@ -4,6 +4,7 @@ pub(crate) mod response;
|
||||||
|
|
||||||
mod channel;
|
mod channel;
|
||||||
mod music_artist;
|
mod music_artist;
|
||||||
|
mod music_details;
|
||||||
mod music_playlist;
|
mod music_playlist;
|
||||||
mod music_search;
|
mod music_search;
|
||||||
mod pagination;
|
mod pagination;
|
||||||
|
|
|
||||||
69
src/client/music_details.rs
Normal file
69
src/client/music_details.rs
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
error::{Error, ExtractionError},
|
||||||
|
model::MusicDetails,
|
||||||
|
param::Language,
|
||||||
|
serializer::MapResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{response, ClientType, MapResponse, RustyPipeQuery, YTContext};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
struct QMusicDetails<'a> {
|
||||||
|
context: YTContext<'a>,
|
||||||
|
// YouTube video ID
|
||||||
|
video_id: &'a str,
|
||||||
|
enable_persistent_playlist_panel: bool,
|
||||||
|
is_audio_only: bool,
|
||||||
|
tuner_setting_value: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
struct QRadio<'a> {
|
||||||
|
context: YTContext<'a>,
|
||||||
|
playlist_id: &'a str,
|
||||||
|
params: &'a str,
|
||||||
|
enable_persistent_playlist_panel: bool,
|
||||||
|
is_audio_only: bool,
|
||||||
|
tuner_setting_value: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RustyPipeQuery {
|
||||||
|
pub async fn music_radio(&self, radio_id: &str) -> Result<MusicDetails, Error> {
|
||||||
|
let context = self.get_context(ClientType::DesktopMusic, true, None).await;
|
||||||
|
let request_body = QRadio {
|
||||||
|
context,
|
||||||
|
playlist_id: radio_id,
|
||||||
|
params: "wAEB8gECeAE%3D",
|
||||||
|
enable_persistent_playlist_panel: true,
|
||||||
|
is_audio_only: true,
|
||||||
|
tuner_setting_value: "AUTOMIX_SETTING_NORMAL",
|
||||||
|
};
|
||||||
|
|
||||||
|
self.execute_request::<response::MusicDetails, _, _>(
|
||||||
|
ClientType::DesktopMusic,
|
||||||
|
"music_radio",
|
||||||
|
radio_id,
|
||||||
|
"next",
|
||||||
|
&request_body,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MapResponse<MusicDetails> for response::MusicDetails {
|
||||||
|
fn map_response(
|
||||||
|
self,
|
||||||
|
id: &str,
|
||||||
|
lang: Language,
|
||||||
|
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
|
||||||
|
) -> Result<MapResult<MusicDetails>, ExtractionError> {
|
||||||
|
dbg!(&self);
|
||||||
|
|
||||||
|
Ok(MapResult {
|
||||||
|
c: MusicDetails {},
|
||||||
|
warnings: Vec::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
pub(crate) mod channel;
|
pub(crate) mod channel;
|
||||||
pub(crate) mod music_artist;
|
pub(crate) mod music_artist;
|
||||||
|
pub(crate) mod music_details;
|
||||||
pub(crate) mod music_item;
|
pub(crate) mod music_item;
|
||||||
pub(crate) mod music_playlist;
|
pub(crate) mod music_playlist;
|
||||||
pub(crate) mod music_search;
|
pub(crate) mod music_search;
|
||||||
|
|
@ -14,6 +15,7 @@ pub(crate) mod video_item;
|
||||||
pub(crate) use channel::Channel;
|
pub(crate) use channel::Channel;
|
||||||
pub(crate) use music_artist::MusicArtist;
|
pub(crate) use music_artist::MusicArtist;
|
||||||
pub(crate) use music_artist::MusicArtistAlbums;
|
pub(crate) use music_artist::MusicArtistAlbums;
|
||||||
|
pub(crate) use music_details::MusicDetails;
|
||||||
pub(crate) use music_item::MusicContinuation;
|
pub(crate) use music_item::MusicContinuation;
|
||||||
pub(crate) use music_playlist::MusicPlaylist;
|
pub(crate) use music_playlist::MusicPlaylist;
|
||||||
pub(crate) use music_search::MusicSearch;
|
pub(crate) use music_search::MusicSearch;
|
||||||
|
|
|
||||||
6
src/client/response/music_details.rs
Normal file
6
src/client/response/music_details.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
/// Response model for YouTube Music track details
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct MusicDetails {}
|
||||||
|
|
@ -1181,6 +1181,7 @@ pub struct MusicArtist {
|
||||||
|
|
||||||
/// YouTube Music search result
|
/// YouTube Music search result
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct MusicSearchResult {
|
pub struct MusicSearchResult {
|
||||||
/// Found tracks
|
/// Found tracks
|
||||||
pub tracks: Vec<TrackItem>,
|
pub tracks: Vec<TrackItem>,
|
||||||
|
|
@ -1219,6 +1220,7 @@ pub enum MusicEntityType {
|
||||||
|
|
||||||
/// Filtered YouTube Music search result
|
/// Filtered YouTube Music search result
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct MusicSearchFiltered<T> {
|
pub struct MusicSearchFiltered<T> {
|
||||||
pub items: Paginator<T>,
|
pub items: Paginator<T>,
|
||||||
/// Corrected search query
|
/// Corrected search query
|
||||||
|
|
@ -1228,3 +1230,8 @@ pub struct MusicSearchFiltered<T> {
|
||||||
/// search results page.
|
/// search results page.
|
||||||
pub corrected_query: Option<String>,
|
pub corrected_query: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Music track details
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct MusicDetails {}
|
||||||
|
|
|
||||||
13516
testfiles/music_details/radio_mv.json
Normal file
13516
testfiles/music_details/radio_mv.json
Normal file
File diff suppressed because it is too large
Load diff
14929
testfiles/music_details/radio_track.json
Normal file
14929
testfiles/music_details/radio_track.json
Normal file
File diff suppressed because it is too large
Load diff
Reference in a new issue