feat: add channel playlists
- add tests for channel videos - small model refactor (rename Channel to ChannelTag)
This commit is contained in:
parent
45707c4d01
commit
6f1a1c4440
30 changed files with 16831 additions and 241 deletions
|
|
@ -5,13 +5,17 @@ use serde_with::VecSkipError;
|
|||
use super::ChannelBadge;
|
||||
use super::Thumbnails;
|
||||
use super::{ContentRenderer, ContentsRenderer, VideoListItem};
|
||||
use crate::serializer::ignore_any;
|
||||
use crate::serializer::{text::Text, MapResult, VecLogError};
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Channel {
|
||||
pub header: Header,
|
||||
pub contents: Contents,
|
||||
pub metadata: Metadata,
|
||||
pub microformat: Microformat,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
|
|
@ -46,27 +50,30 @@ pub struct SectionListRendererWrap {
|
|||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SectionListRenderer {
|
||||
pub contents: Vec<ItemSectionRendererWrap>,
|
||||
pub target_id: String,
|
||||
/// - **Videos**: browse-feedUC2DjFE7Xf11URZqWBigcVOQvideos (...)
|
||||
/// - **Playlists**: browse-feedUC2DjFE7Xf11URZqWBigcVOQplaylists104 (...)
|
||||
/// - **Info**: None
|
||||
pub target_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ItemSectionRendererWrap {
|
||||
pub item_section_renderer: ContentsRenderer<GridRendererWrap>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GridRendererWrap {
|
||||
pub grid_renderer: GridRenderer,
|
||||
pub item_section_renderer: ContentsRenderer<ChannelContent>,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[derive(Default, Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GridRenderer {
|
||||
#[serde_as(as = "VecLogError<_>")]
|
||||
pub items: MapResult<Vec<VideoListItem>>,
|
||||
pub enum ChannelContent {
|
||||
GridRenderer {
|
||||
#[serde_as(as = "VecLogError<_>")]
|
||||
items: MapResult<Vec<VideoListItem>>,
|
||||
},
|
||||
ChannelAboutFullMetadataRenderer(ChannelFullMetadata),
|
||||
#[default]
|
||||
#[serde(other, deserialize_with = "ignore_any")]
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
|
|
@ -87,11 +94,74 @@ pub struct HeaderRenderer {
|
|||
/// `None` if the subscriber count is hidden.
|
||||
#[serde_as(as = "Option<Text>")]
|
||||
pub subscriber_count_text: Option<String>,
|
||||
#[serde(default)]
|
||||
pub avatar: Thumbnails,
|
||||
#[serde_as(as = "Option<VecSkipError<_>>")]
|
||||
pub badges: Option<Vec<ChannelBadge>>,
|
||||
#[serde(default)]
|
||||
pub banner: Thumbnails,
|
||||
#[serde(default)]
|
||||
pub mobile_banner: Thumbnails,
|
||||
/// Fullscreen (16:9) channel banner
|
||||
#[serde(default)]
|
||||
pub tv_banner: Thumbnails,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Metadata {
|
||||
pub channel_metadata_renderer: ChannelMetadataRenderer,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ChannelMetadataRenderer {
|
||||
pub description: String,
|
||||
pub vanity_channel_url: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Microformat {
|
||||
pub microformat_data_renderer: MicroformatDataRenderer,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MicroformatDataRenderer {
|
||||
#[serde(default)]
|
||||
pub tags: Vec<String>,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ChannelFullMetadata {
|
||||
#[serde_as(as = "Text")]
|
||||
pub joined_date_text: String,
|
||||
#[serde_as(as = "Text")]
|
||||
pub view_count_text: String,
|
||||
#[serde_as(as = "VecSkipError<_>")]
|
||||
pub primary_links: Vec<PrimaryLink>,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PrimaryLink {
|
||||
#[serde_as(as = "Text")]
|
||||
pub title: String,
|
||||
pub navigation_endpoint: NavigationEndpoint,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct NavigationEndpoint {
|
||||
pub url_endpoint: UrlEndpoint,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UrlEndpoint {
|
||||
pub url: String,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ pub struct ContentsRenderer<T> {
|
|||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ThumbnailsWrap {
|
||||
#[serde(default)]
|
||||
pub thumbnail: Thumbnails,
|
||||
}
|
||||
|
||||
|
|
@ -45,6 +46,7 @@ pub struct ThumbnailsWrap {
|
|||
#[derive(Default, Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Thumbnails {
|
||||
#[serde(default)]
|
||||
pub thumbnails: Vec<Thumbnail>,
|
||||
}
|
||||
|
||||
|
|
@ -155,8 +157,6 @@ pub struct GridPlaylistRenderer {
|
|||
pub title: String,
|
||||
pub thumbnail: Thumbnails,
|
||||
#[serde_as(as = "Text")]
|
||||
pub published_time_text: String,
|
||||
#[serde_as(as = "Text")]
|
||||
pub video_count_short_text: String,
|
||||
}
|
||||
|
||||
|
|
@ -244,6 +244,9 @@ pub struct TimeOverlay {
|
|||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TimeOverlayRenderer {
|
||||
/// `29:54`
|
||||
///
|
||||
/// Is `LIVE` in case of a livestream
|
||||
#[serde_as(as = "Text")]
|
||||
pub text: String,
|
||||
#[serde(default)]
|
||||
|
|
|
|||
|
|
@ -207,7 +207,8 @@ pub struct VideoDetails {
|
|||
pub keywords: Option<Vec<String>>,
|
||||
pub channel_id: String,
|
||||
pub short_description: Option<String>,
|
||||
pub thumbnail: Option<Thumbnails>,
|
||||
#[serde(default)]
|
||||
pub thumbnail: Thumbnails,
|
||||
#[serde_as(as = "JsonString")]
|
||||
pub view_count: u64,
|
||||
pub author: String,
|
||||
|
|
|
|||
|
|
@ -344,6 +344,7 @@ pub struct MacroMarkersListItem {
|
|||
pub struct MacroMarkersListItemRenderer {
|
||||
/// Contains chapter start time in seconds
|
||||
pub on_tap: MacroMarkersListItemOnTap,
|
||||
#[serde(default)]
|
||||
pub thumbnail: Thumbnails,
|
||||
/// Chapter title
|
||||
#[serde_as(as = "Text")]
|
||||
|
|
@ -528,6 +529,7 @@ pub struct CommentRenderer {
|
|||
#[serde(default)]
|
||||
#[serde_as(as = "DefaultOnError<Option<Text>>")]
|
||||
pub author_text: Option<String>,
|
||||
#[serde(default)]
|
||||
pub author_thumbnail: Thumbnails,
|
||||
#[serde(default)]
|
||||
/// ID of the author's channel
|
||||
|
|
|
|||
Reference in a new issue