feat: add music genres
This commit is contained in:
parent
c6cd364b9e
commit
de7bd2a965
21 changed files with 154217 additions and 49 deletions
|
|
@ -2,6 +2,7 @@ pub(crate) mod channel;
|
|||
pub(crate) mod music_artist;
|
||||
pub(crate) mod music_charts;
|
||||
pub(crate) mod music_details;
|
||||
pub(crate) mod music_genres;
|
||||
pub(crate) mod music_item;
|
||||
pub(crate) mod music_new;
|
||||
pub(crate) mod music_playlist;
|
||||
|
|
@ -21,6 +22,8 @@ pub(crate) use music_charts::MusicCharts;
|
|||
pub(crate) use music_details::MusicDetails;
|
||||
pub(crate) use music_details::MusicLyrics;
|
||||
pub(crate) use music_details::MusicRelated;
|
||||
pub(crate) use music_genres::MusicGenre;
|
||||
pub(crate) use music_genres::MusicGenres;
|
||||
pub(crate) use music_item::MusicContinuation;
|
||||
pub(crate) use music_new::MusicNew;
|
||||
pub(crate) use music_playlist::MusicPlaylist;
|
||||
|
|
|
|||
|
|
@ -4,24 +4,20 @@ use serde_with::{serde_as, DefaultOnError};
|
|||
use crate::serializer::text::Text;
|
||||
|
||||
use super::{
|
||||
music_item::{Grid, ItemSection, MusicThumbnailRenderer},
|
||||
ContentsRenderer, SectionList, Tab,
|
||||
music_item::{
|
||||
Grid, ItemSection, MusicThumbnailRenderer, SimpleHeader, SingleColumnBrowseResult,
|
||||
},
|
||||
SectionList, Tab,
|
||||
};
|
||||
|
||||
/// Response model for YouTube Music artists
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct MusicArtist {
|
||||
pub contents: Contents<ItemSection>,
|
||||
pub contents: SingleColumnBrowseResult<Tab<SectionList<ItemSection>>>,
|
||||
pub header: Header,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct Contents<T> {
|
||||
pub single_column_browse_results_renderer: ContentsRenderer<Tab<SectionList<T>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct Header {
|
||||
|
|
@ -64,19 +60,5 @@ pub(crate) struct SubscriptionButtonRenderer {
|
|||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct MusicArtistAlbums {
|
||||
pub header: SimpleHeader,
|
||||
pub contents: Contents<Grid>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct SimpleHeader {
|
||||
pub music_header_renderer: SimpleHeaderRenderer,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct SimpleHeaderRenderer {
|
||||
#[serde_as(as = "Text")]
|
||||
pub title: String,
|
||||
pub contents: SingleColumnBrowseResult<Tab<SectionList<Grid>>>,
|
||||
}
|
||||
|
|
|
|||
62
src/client/response/music_genres.rs
Normal file
62
src/client/response/music_genres.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
use serde::Deserialize;
|
||||
use serde_with::{rust::deserialize_ignore_any, serde_as};
|
||||
|
||||
use crate::serializer::{text::Text, MapResult, VecLogError};
|
||||
|
||||
use super::{
|
||||
music_item::{ItemSection, SimpleHeader, SingleColumnBrowseResult},
|
||||
url_endpoint::BrowseEndpointWrap,
|
||||
SectionList, Tab,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct MusicGenres {
|
||||
pub contents: SingleColumnBrowseResult<Tab<SectionList<Grid>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct Grid {
|
||||
pub grid_renderer: GridRenderer,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct GridRenderer {
|
||||
#[serde_as(as = "VecLogError<_>")]
|
||||
pub items: MapResult<Vec<NavigationButton>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) enum NavigationButton {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
MusicNavigationButtonRenderer(NavigationButtonRenderer),
|
||||
#[serde(other, deserialize_with = "deserialize_ignore_any")]
|
||||
None,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct NavigationButtonRenderer {
|
||||
#[serde_as(as = "Text")]
|
||||
pub button_text: String,
|
||||
pub solid: NavigationButtonColor,
|
||||
pub click_command: BrowseEndpointWrap,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct NavigationButtonColor {
|
||||
pub left_stripe_color: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct MusicGenre {
|
||||
pub contents: SingleColumnBrowseResult<Tab<SectionList<ItemSection>>>,
|
||||
pub header: SimpleHeader,
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ pub(crate) enum ItemSection {
|
|||
#[serde(alias = "musicPlaylistShelfRenderer")]
|
||||
MusicShelfRenderer(MusicShelf),
|
||||
MusicCarouselShelfRenderer(MusicCarouselShelf),
|
||||
GridRenderer(GridRenderer),
|
||||
#[serde(other, deserialize_with = "deserialize_ignore_any")]
|
||||
None,
|
||||
}
|
||||
|
|
@ -357,6 +358,41 @@ pub(crate) struct Grid {
|
|||
pub(crate) struct GridRenderer {
|
||||
#[serde_as(as = "VecLogError<_>")]
|
||||
pub items: MapResult<Vec<MusicResponseItem>>,
|
||||
pub header: Option<GridHeader>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct GridHeader {
|
||||
pub grid_header_renderer: GridHeaderRenderer,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct GridHeaderRenderer {
|
||||
#[serde_as(as = "Text")]
|
||||
pub title: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct SingleColumnBrowseResult<T> {
|
||||
pub single_column_browse_results_renderer: ContentsRenderer<T>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct SimpleHeader {
|
||||
pub music_header_renderer: SimpleHeaderRenderer,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct SimpleHeaderRenderer {
|
||||
#[serde_as(as = "Text")]
|
||||
pub title: String,
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -764,10 +800,12 @@ impl MusicListMapper {
|
|||
Ok(Some(MusicEntityType::Album))
|
||||
}
|
||||
MusicPageType::Playlist => {
|
||||
// When the playlist subtitle has only 1 part, it is a playlist from YT Music
|
||||
// (featured on the startpage or in genres)
|
||||
let from_ytm = subtitle_p2
|
||||
.as_ref()
|
||||
.map(|p| p.first_str() == util::YT_MUSIC_NAME)
|
||||
.unwrap_or_default();
|
||||
.unwrap_or(true);
|
||||
let channel = subtitle_p2.and_then(|p| {
|
||||
p.0.into_iter().find_map(|c| ChannelId::try_from(c).ok())
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
use super::{music_item::Grid, ContentsRenderer, SectionList, Tab};
|
||||
use super::{
|
||||
music_item::{Grid, SingleColumnBrowseResult},
|
||||
SectionList, Tab,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct MusicNew {
|
||||
pub contents: Contents,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct Contents {
|
||||
pub single_column_browse_results_renderer: ContentsRenderer<Tab<SectionList<Grid>>>,
|
||||
pub contents: SingleColumnBrowseResult<Tab<SectionList<Grid>>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,23 +3,21 @@ use serde_with::{serde_as, DefaultOnError, VecSkipError};
|
|||
|
||||
use crate::serializer::text::{Text, TextComponents};
|
||||
|
||||
use super::music_item::{ItemSection, MusicContentsRenderer, MusicThumbnailRenderer};
|
||||
use super::{ContentsRenderer, Tab};
|
||||
use super::{
|
||||
music_item::{
|
||||
ItemSection, MusicContentsRenderer, MusicThumbnailRenderer, SingleColumnBrowseResult,
|
||||
},
|
||||
Tab,
|
||||
};
|
||||
|
||||
/// Response model for YouTube Music playlists and albums
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct MusicPlaylist {
|
||||
pub contents: Contents,
|
||||
pub contents: SingleColumnBrowseResult<Tab<SectionList>>,
|
||||
pub header: Option<Header>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct Contents {
|
||||
pub single_column_browse_results_renderer: ContentsRenderer<Tab<SectionList>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct SectionList {
|
||||
|
|
|
|||
Reference in a new issue