feat: add album description

This commit is contained in:
ThetaDev 2022-11-06 19:43:24 +01:00
parent 6f07095757
commit dfd33d5e9b
19 changed files with 6200 additions and 79 deletions

View file

@ -540,6 +540,7 @@ async fn music_album(testfiles: &Path) {
("one_artist", "MPREb_nlBWQROfvjo"),
("various_artists", "MPREb_8QkDeEIawvX"),
("single", "MPREb_bHfHGoy7vuv"),
("description", "MPREb_PiyfuVl6aYd"),
] {
let mut json_path = testfiles.to_path_buf();
json_path.push("music_playlist");

View file

@ -177,7 +177,7 @@ fn map_artist_page(
for section in sections {
match section {
response::music_artist::ItemSection::MusicShelfRenderer(shelf) => {
response::music_item::ItemSection::MusicShelfRenderer(shelf) => {
if tracks_playlist_id.is_none() {
if let Some(ep) = shelf.bottom_endpoint {
if let Some(cfg) =
@ -194,10 +194,7 @@ fn map_artist_page(
mapper.map_response(shelf.contents);
}
response::music_artist::ItemSection::MusicCarouselShelfRenderer {
header,
contents,
} => {
response::music_item::ItemSection::MusicCarouselShelfRenderer { header, contents } => {
let mut extendable_albums = false;
if let Some(h) = header {
let ep = h
@ -228,7 +225,7 @@ fn map_artist_page(
mapper.map_response(contents);
}
}
response::music_artist::ItemSection::None => {}
response::music_item::ItemSection::None => {}
}
}

View file

@ -72,7 +72,7 @@ impl MapResponse<MusicPlaylist> for response::MusicPlaylist {
.contents
.into_iter()
.find_map(|section| match section {
response::music_playlist::ItemSection::MusicShelfRenderer(shelf) => Some(shelf),
response::music_item::ItemSection::MusicShelfRenderer(shelf) => Some(shelf),
_ => None,
})
.ok_or(ExtractionError::InvalidData(Cow::Borrowed(
@ -167,11 +167,11 @@ impl MapResponse<MusicAlbum> for response::MusicPlaylist {
let mut album_variants = None;
for section in sections {
match section {
response::music_playlist::ItemSection::MusicShelfRenderer(sh) => shelf = Some(sh),
response::music_playlist::ItemSection::MusicCarouselShelfRenderer { contents } => {
album_variants = Some(contents)
}
response::music_playlist::ItemSection::None => (),
response::music_item::ItemSection::MusicShelfRenderer(sh) => shelf = Some(sh),
response::music_item::ItemSection::MusicCarouselShelfRenderer {
contents, ..
} => album_variants = Some(contents),
response::music_item::ItemSection::None => (),
}
}
let shelf = shelf.ok_or(ExtractionError::InvalidData(Cow::Borrowed(
@ -230,6 +230,7 @@ impl MapResponse<MusicAlbum> for response::MusicPlaylist {
name: header.title,
cover: header.thumbnail.into(),
artists,
description: header.description,
album_type,
year,
by_va,
@ -278,6 +279,7 @@ mod tests {
#[case::one_artist("one_artist", "MPREb_nlBWQROfvjo")]
#[case::various_artists("various_artists", "MPREb_8QkDeEIawvX")]
#[case::single("single", "MPREb_bHfHGoy7vuv")]
#[case::description("description", "MPREb_PiyfuVl6aYd")]
fn map_music_album(#[case] name: &str, #[case] id: &str) {
let filename = format!("testfiles/music_playlist/album_{}.json", name);
let json_path = Path::new(&filename);

View file

@ -1,11 +1,10 @@
use serde::Deserialize;
use serde_with::{serde_as, DefaultOnError};
use crate::serializer::{ignore_any, text::Text, MapResult, VecLogError};
use crate::serializer::{text::Text, MapResult, VecLogError};
use super::{
music_item::{MusicResponseItem, MusicShelf, MusicThumbnailRenderer},
url_endpoint::NavigationEndpoint,
music_item::{ItemSection, MusicResponseItem, MusicThumbnailRenderer},
ContentsRenderer, Tab,
};
@ -29,22 +28,6 @@ pub(crate) struct SectionList<T> {
pub section_list_renderer: ContentsRenderer<T>,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) enum ItemSection {
MusicShelfRenderer(MusicShelf),
MusicCarouselShelfRenderer {
#[serde(default)]
#[serde_as(as = "DefaultOnError")]
header: Option<MusicCarouselShelfHeader>,
#[serde_as(as = "VecLogError<_>")]
contents: MapResult<Vec<MusicResponseItem>>,
},
#[serde(other, deserialize_with = "ignore_any")]
None,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct Header {
@ -82,30 +65,6 @@ pub(crate) struct SubscriptionButtonRenderer {
pub subscriber_count_text: String,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct MusicCarouselShelfHeader {
pub music_carousel_shelf_basic_header_renderer: MusicCarouselShelfHeaderRenderer,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct MusicCarouselShelfHeaderRenderer {
pub more_content_button: MoreContentButton,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct MoreContentButton {
pub button_renderer: ButtonRenderer,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct ButtonRenderer {
pub navigation_endpoint: NavigationEndpoint,
}
/// Response model for YouTube Music artist album page
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]

View file

@ -8,6 +8,7 @@ use crate::{
},
param::Language,
serializer::{
ignore_any,
text::{Text, TextComponents},
MapResult, VecLogError,
},
@ -19,6 +20,23 @@ use super::{
MusicContinuationData, ThumbnailsWrap,
};
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) enum ItemSection {
#[serde(alias = "musicPlaylistShelfRenderer")]
MusicShelfRenderer(MusicShelf),
MusicCarouselShelfRenderer {
#[serde(default)]
#[serde_as(as = "DefaultOnError")]
header: Option<MusicCarouselShelfHeader>,
#[serde_as(as = "VecLogError<_>")]
contents: MapResult<Vec<MusicResponseItem>>,
},
#[serde(other, deserialize_with = "ignore_any")]
None,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
@ -191,6 +209,30 @@ pub(crate) struct ContinuationContents {
pub music_shelf_continuation: MusicShelf,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct MusicCarouselShelfHeader {
pub music_carousel_shelf_basic_header_renderer: MusicCarouselShelfHeaderRenderer,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct MusicCarouselShelfHeaderRenderer {
pub more_content_button: MoreContentButton,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct MoreContentButton {
pub button_renderer: ButtonRenderer,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct ButtonRenderer {
pub navigation_endpoint: NavigationEndpoint,
}
/*
#MAPPER
*/

View file

@ -1,15 +1,9 @@
use serde::Deserialize;
use serde_with::{serde_as, DefaultOnError, VecSkipError};
use crate::serializer::{
ignore_any,
text::{Text, TextComponents},
MapResult, VecLogError,
};
use crate::serializer::text::{Text, TextComponents};
use super::music_item::{
MusicContentsRenderer, MusicResponseItem, MusicShelf, MusicThumbnailRenderer,
};
use super::music_item::{ItemSection, MusicContentsRenderer, MusicThumbnailRenderer};
use super::{ContentsRenderer, Tab};
/// Response model for YouTube Music playlists and albums
@ -33,20 +27,6 @@ pub(crate) struct SectionList {
pub section_list_renderer: MusicContentsRenderer<ItemSection>,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) enum ItemSection {
#[serde(alias = "musicPlaylistShelfRenderer")]
MusicShelfRenderer(MusicShelf),
MusicCarouselShelfRenderer {
#[serde_as(as = "VecLogError<_>")]
contents: MapResult<Vec<MusicResponseItem>>,
},
#[serde(other, deserialize_with = "ignore_any")]
None,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct Header {
@ -67,7 +47,7 @@ pub(crate) struct HeaderRenderer {
/// `"Album", " • ", <"Helene Fischer">, " • ", "2021"`
#[serde(default)]
pub subtitle: TextComponents,
/// Playlist description. May contain hashtags which are
/// Playlist/album description. May contain hashtags which are
/// displayed as search links on the YouTube website.
#[serde_as(as = "Option<Text>")]
pub description: Option<String>,

View file

@ -0,0 +1,253 @@
---
source: src/client/music_playlist.rs
expression: map_res.c
---
MusicAlbum(
id: "MPREb_PiyfuVl6aYd",
playlist_id: Some("OLAK5uy_k-Bi6NLrq5DrDKPLuiRvm7NsbMccKIcEY"),
name: "25",
cover: [
Thumbnail(
url: "https://lh3.googleusercontent.com/LRj9RZOKcS7PrG-NvXKnwSekCqXNWMItrnuF6WXmr3MeujS1HxqjiATe6H5HCM6-hoHNYncjmlIovaaH=w60-h60-l90-rj",
width: 60,
height: 60,
),
Thumbnail(
url: "https://lh3.googleusercontent.com/LRj9RZOKcS7PrG-NvXKnwSekCqXNWMItrnuF6WXmr3MeujS1HxqjiATe6H5HCM6-hoHNYncjmlIovaaH=w120-h120-l90-rj",
width: 120,
height: 120,
),
Thumbnail(
url: "https://lh3.googleusercontent.com/LRj9RZOKcS7PrG-NvXKnwSekCqXNWMItrnuF6WXmr3MeujS1HxqjiATe6H5HCM6-hoHNYncjmlIovaaH=w226-h226-l90-rj",
width: 226,
height: 226,
),
Thumbnail(
url: "https://lh3.googleusercontent.com/LRj9RZOKcS7PrG-NvXKnwSekCqXNWMItrnuF6WXmr3MeujS1HxqjiATe6H5HCM6-hoHNYncjmlIovaaH=w544-h544-l90-rj",
width: 544,
height: 544,
),
],
artists: [
ArtistId(
id: Some("UCRw0x9_EfawqmgDI2IgQLLg"),
name: "Adele",
),
],
description: Some("25 is the third studio album by English singer-songwriter Adele, released on 20 November 2015 by XL Recordings and Columbia Records. The album is titled as a reflection of her life and frame of mind at 25 years old and is termed a \"make-up record\". Its lyrical content features themes of Adele \"yearning for her old self, her nostalgia\", and \"melancholia about the passage of time\" according to an interview with the singer by Rolling Stone, as well as themes of motherhood and regret. In contrast to Adele\'s previous works, the production of 25 incorporated the use of electronic elements and creative rhythmic patterns, with elements of 1980s R&B and organs. Like when recording 21, Adele worked with producer and songwriter Paul Epworth and Ryan Tedder, along with new collaborations with Max Martin and Shellback, Bruno Mars, Greg Kurstin, Danger Mouse, the Smeezingtons, Samuel Dixon, and Tobias Jesso Jr.\n25 received generally positive reviews from music critics, who commended its production and Adele\'s vocal performance.\n\nFrom Wikipedia (https://en.wikipedia.org/wiki/25_(Adele_album)) under Creative Commons Attribution CC-BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0/legalcode)"),
album_type: Album,
year: Some(2015),
by_va: false,
tracks: [
TrackItem(
id: "YQHsXMglC9A",
title: "Hello",
duration: Some(296),
cover: [],
artists: [
ArtistId(
id: Some("UCRw0x9_EfawqmgDI2IgQLLg"),
name: "Adele",
),
],
album: Some(AlbumId(
id: "MPREb_PiyfuVl6aYd",
name: "25",
)),
view_count: None,
is_video: false,
track_nr: Some(1),
),
TrackItem(
id: "fk4BbF7B29w",
title: "Send My Love (To Your New Lover)",
duration: Some(224),
cover: [],
artists: [
ArtistId(
id: Some("UCRw0x9_EfawqmgDI2IgQLLg"),
name: "Adele",
),
],
album: Some(AlbumId(
id: "MPREb_PiyfuVl6aYd",
name: "25",
)),
view_count: None,
is_video: false,
track_nr: Some(2),
),
TrackItem(
id: "z7NEG3SGZ_g",
title: "I Miss You",
duration: Some(349),
cover: [],
artists: [
ArtistId(
id: Some("UCRw0x9_EfawqmgDI2IgQLLg"),
name: "Adele",
),
],
album: Some(AlbumId(
id: "MPREb_PiyfuVl6aYd",
name: "25",
)),
view_count: None,
is_video: false,
track_nr: Some(3),
),
TrackItem(
id: "a1IuJLebHgM",
title: "When We Were Young",
duration: Some(291),
cover: [],
artists: [
ArtistId(
id: Some("UCRw0x9_EfawqmgDI2IgQLLg"),
name: "Adele",
),
],
album: Some(AlbumId(
id: "MPREb_PiyfuVl6aYd",
name: "25",
)),
view_count: None,
is_video: false,
track_nr: Some(4),
),
TrackItem(
id: "-fsCc7Be1H0",
title: "Remedy",
duration: Some(246),
cover: [],
artists: [
ArtistId(
id: Some("UCRw0x9_EfawqmgDI2IgQLLg"),
name: "Adele",
),
],
album: Some(AlbumId(
id: "MPREb_PiyfuVl6aYd",
name: "25",
)),
view_count: None,
is_video: false,
track_nr: Some(5),
),
TrackItem(
id: "l8djdhhFuxo",
title: "Water Under the Bridge",
duration: Some(241),
cover: [],
artists: [
ArtistId(
id: Some("UCRw0x9_EfawqmgDI2IgQLLg"),
name: "Adele",
),
],
album: Some(AlbumId(
id: "MPREb_PiyfuVl6aYd",
name: "25",
)),
view_count: None,
is_video: false,
track_nr: Some(6),
),
TrackItem(
id: "Qiu59lZShCo",
title: "River Lea",
duration: Some(226),
cover: [],
artists: [
ArtistId(
id: Some("UCRw0x9_EfawqmgDI2IgQLLg"),
name: "Adele",
),
],
album: Some(AlbumId(
id: "MPREb_PiyfuVl6aYd",
name: "25",
)),
view_count: None,
is_video: false,
track_nr: Some(7),
),
TrackItem(
id: "-hzFTJDJGkQ",
title: "Love in the Dark",
duration: Some(286),
cover: [],
artists: [
ArtistId(
id: Some("UCRw0x9_EfawqmgDI2IgQLLg"),
name: "Adele",
),
],
album: Some(AlbumId(
id: "MPREb_PiyfuVl6aYd",
name: "25",
)),
view_count: None,
is_video: false,
track_nr: Some(8),
),
TrackItem(
id: "Db9ciJPIaEU",
title: "Million Years Ago",
duration: Some(228),
cover: [],
artists: [
ArtistId(
id: Some("UCRw0x9_EfawqmgDI2IgQLLg"),
name: "Adele",
),
],
album: Some(AlbumId(
id: "MPREb_PiyfuVl6aYd",
name: "25",
)),
view_count: None,
is_video: false,
track_nr: Some(9),
),
TrackItem(
id: "jb5g4UFHmfQ",
title: "All I Ask",
duration: Some(272),
cover: [],
artists: [
ArtistId(
id: Some("UCRw0x9_EfawqmgDI2IgQLLg"),
name: "Adele",
),
],
album: Some(AlbumId(
id: "MPREb_PiyfuVl6aYd",
name: "25",
)),
view_count: None,
is_video: false,
track_nr: Some(10),
),
TrackItem(
id: "1kZsaRkVEUY",
title: "Sweetest Devotion",
duration: Some(252),
cover: [],
artists: [
ArtistId(
id: Some("UCRw0x9_EfawqmgDI2IgQLLg"),
name: "Adele",
),
],
album: Some(AlbumId(
id: "MPREb_PiyfuVl6aYd",
name: "25",
)),
view_count: None,
is_video: false,
track_nr: Some(11),
),
],
variants: [],
)

View file

@ -34,6 +34,7 @@ MusicAlbum(
name: "Oonagh",
),
],
description: None,
album_type: Album,
year: Some(2016),
by_va: false,

View file

@ -38,6 +38,7 @@ MusicAlbum(
name: "Vanessa Mai",
),
],
description: None,
album_type: Single,
year: Some(2020),
by_va: false,

View file

@ -29,6 +29,7 @@ MusicAlbum(
),
],
artists: [],
description: None,
album_type: Single,
year: Some(2022),
by_va: true,

View file

@ -1030,6 +1030,8 @@ pub struct MusicAlbum {
pub cover: Vec<Thumbnail>,
/// Artists of the album
pub artists: Vec<ArtistId>,
/// Album description in plaintext format
pub description: Option<String>,
/// Album type (Album/Single/EP)
pub album_type: AlbumType,
/// Release year

File diff suppressed because it is too large Load diff

View file

@ -17,6 +17,7 @@ MusicAlbum(
name: "Dirk Jacobs",
),
],
description: None,
album_type: Audiobook,
year: Some(2022),
by_va: false,

View file

@ -13,6 +13,7 @@ MusicAlbum(
name: "Madeline Juno",
),
],
description: None,
album_type: Ep,
year: Some(2016),
by_va: false,

View file

@ -13,6 +13,7 @@ MusicAlbum(
name: "Oonagh",
),
],
description: None,
album_type: Album,
year: Some(2016),
by_va: false,

View file

@ -13,6 +13,7 @@ MusicAlbum(
name: "Kingdom Force",
),
],
description: None,
album_type: Show,
year: Some(2022),
by_va: false,

View file

@ -17,6 +17,7 @@ MusicAlbum(
name: "Vanessa Mai",
),
],
description: None,
album_type: Single,
year: Some(2020),
by_va: false,

View file

@ -8,6 +8,7 @@ MusicAlbum(
name: "Queendom2 FINAL",
cover: "[cover]",
artists: [],
description: None,
album_type: Single,
year: Some(2022),
by_va: true,

View file

@ -1587,7 +1587,11 @@ async fn music_search_albums(
#[tokio::test]
async fn music_search_artists() {
let rp = RustyPipe::builder().strict().build();
let res = rp.query().music_search_artists("namika").await.unwrap();
let res = rp
.query()
.music_search_artists("namika lieblingsmensch")
.await
.unwrap();
let artist = &res.items.items[0];
assert_eq!(artist.id, "UCIh4j8fXWf2U0ro0qnGU8Mg");