feat: add music album
This commit is contained in:
parent
566b3e5bfc
commit
3b738a55ad
12 changed files with 14904 additions and 17 deletions
|
|
@ -19,6 +19,7 @@ pub(crate) struct MusicItem {
|
|||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct InnerMusicItem {
|
||||
#[serde(default)]
|
||||
pub thumbnail: MusicThumbnailRenderer,
|
||||
#[serde(default)]
|
||||
#[serde_as(deserialize_as = "DefaultOnError")]
|
||||
|
|
@ -79,7 +80,7 @@ impl From<MusicThumbnailRenderer> for Vec<model::Thumbnail> {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct MusicListMapper<T> {
|
||||
artists: Option<Vec<ChannelId>>,
|
||||
artists: Option<(Vec<ChannelId>, String)>,
|
||||
|
||||
pub items: Vec<T>,
|
||||
pub warnings: Vec<String>,
|
||||
|
|
@ -94,9 +95,9 @@ impl<T> MusicListMapper<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn with_artists(artists: Vec<ChannelId>) -> Self {
|
||||
pub fn with_artists(artists: Vec<ChannelId>, artists_txt: String) -> Self {
|
||||
Self {
|
||||
artists: Some(artists),
|
||||
artists: Some((artists, artists_txt)),
|
||||
items: Vec::new(),
|
||||
warnings: Vec::new(),
|
||||
}
|
||||
|
|
@ -140,9 +141,9 @@ impl<T> MusicListMapper<T> {
|
|||
});
|
||||
|
||||
let artists_col = columns.try_swap_remove(1);
|
||||
let artists_txt = artists_col
|
||||
let mut artists_txt = artists_col
|
||||
.as_ref()
|
||||
.map(|col| col.renderer.text.to_string());
|
||||
.and_then(|col| col.renderer.text.to_opt_string());
|
||||
let mut artists = artists_col
|
||||
.map(|col| {
|
||||
col.renderer
|
||||
|
|
@ -154,8 +155,10 @@ impl<T> MusicListMapper<T> {
|
|||
})
|
||||
.unwrap_or_default();
|
||||
if let Some(a) = &self.artists {
|
||||
if artists.is_empty() {
|
||||
artists = a.clone();
|
||||
if artists.is_empty() && artists_txt.is_none() {
|
||||
let xa = a.clone();
|
||||
artists = xa.0;
|
||||
artists_txt = Some(xa.1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use serde::Deserialize;
|
||||
use serde_with::serde_as;
|
||||
use serde_with::VecSkipError;
|
||||
use serde_with::{serde_as, DefaultOnError, VecSkipError};
|
||||
|
||||
use crate::serializer::{
|
||||
ignore_any,
|
||||
text::{Text, TextComponents},
|
||||
MapResult, VecLogError,
|
||||
};
|
||||
|
|
@ -10,6 +10,7 @@ use crate::serializer::{
|
|||
use super::music_item::{MusicContentsRenderer, MusicItem, MusicThumbnailRenderer};
|
||||
use super::{ContentRenderer, ContentsRenderer, MusicContinuation};
|
||||
|
||||
/// Response model for YouTube Music playlists and albums
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct MusicPlaylist {
|
||||
|
|
@ -42,11 +43,18 @@ pub(crate) struct SectionList {
|
|||
pub section_list_renderer: MusicContentsRenderer<ItemSection>,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct ItemSection {
|
||||
pub(crate) enum ItemSection {
|
||||
#[serde(alias = "musicPlaylistShelfRenderer")]
|
||||
pub music_shelf_renderer: MusicShelf,
|
||||
MusicShelfRenderer(MusicShelf),
|
||||
MusicCarouselShelfRenderer {
|
||||
#[serde_as(as = "VecLogError<_>")]
|
||||
contents: MapResult<Vec<MusicItem>>,
|
||||
},
|
||||
#[serde(other, deserialize_with = "ignore_any")]
|
||||
None,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
|
|
@ -98,6 +106,48 @@ pub(crate) struct HeaderRenderer {
|
|||
#[serde(default)]
|
||||
#[serde_as(as = "Text")]
|
||||
pub second_subtitle: Vec<String>,
|
||||
#[serde(default)]
|
||||
#[serde_as(as = "DefaultOnError")]
|
||||
pub menu: Option<HeaderMenu>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct HeaderMenu {
|
||||
pub menu_renderer: HeaderMenuRenderer,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct HeaderMenuRenderer {
|
||||
#[serde(default)]
|
||||
#[serde_as(as = "VecSkipError<_>")]
|
||||
pub top_level_buttons: Vec<TopLevelButton>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct TopLevelButton {
|
||||
pub button_renderer: ButtonRenderer,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct ButtonRenderer {
|
||||
pub navigation_endpoint: PlaylistEndpoint,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PlaylistEndpoint {
|
||||
pub watch_playlist_endpoint: PlaylistWatchEndpoint,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PlaylistWatchEndpoint {
|
||||
pub playlist_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
|
|
|||
Reference in a new issue