feat: add music genres

This commit is contained in:
ThetaDev 2022-12-02 00:02:07 +01:00
parent c6cd364b9e
commit de7bd2a965
21 changed files with 154217 additions and 49 deletions

View file

@ -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;

View file

@ -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>>>,
}

View 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,
}

View file

@ -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())
});

View file

@ -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>>>,
}

View file

@ -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 {