This repository has been archived on 2026-05-27. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
rustypipe/src/client/response/music_playlist.rs

127 lines
3.5 KiB
Rust

use serde::Deserialize;
use serde_with::{serde_as, DefaultOnError, VecSkipError};
use crate::serializer::{
ignore_any,
text::{Text, TextComponents},
MapResult, VecLogError,
};
use super::music_item::{
MusicContentsRenderer, MusicResponseItem, MusicShelf, MusicThumbnailRenderer,
};
use super::{ContentsRenderer, Tab};
/// Response model for YouTube Music playlists and albums
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct MusicPlaylist {
pub contents: Contents,
pub header: 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 {
/// Includes a continuation token for fetching recommendations
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 {
pub music_detail_header_renderer: HeaderRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct HeaderRenderer {
#[serde_as(as = "Text")]
pub title: String,
/// Content type + Channel/Artist + Year.
/// Missing on artist_tracks view.
///
/// `"Playlist", " • ", <"Best Music">, " • ", "2022"`
///
/// `"Album", " • ", <"Helene Fischer">, " • ", "2021"`
#[serde(default)]
pub subtitle: TextComponents,
/// Playlist description. May contain hashtags which are
/// displayed as search links on the YouTube website.
#[serde_as(as = "Option<Text>")]
pub description: Option<String>,
/// Playlist thumbnail / album cover.
/// Missing on artist_tracks view.
#[serde(default)]
pub thumbnail: MusicThumbnailRenderer,
/// Number of tracks + playtime.
/// Missing on artist_tracks view.
///
/// `"64 songs", " • ", "3 hours, 40 minutes"`
#[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,
}