fix: A/B test 16 (pageHeaderRenderer on playlist pages)
This commit is contained in:
parent
f3f2e1d3ca
commit
e65f14556f
17 changed files with 6435 additions and 182 deletions
|
|
@ -3,7 +3,8 @@ use serde_with::{rust::deserialize_ignore_any, serde_as, DefaultOnError, VecSkip
|
|||
|
||||
use super::{
|
||||
video_item::YouTubeListRenderer, Alert, ChannelBadge, ContentRenderer, ContentsRenderer,
|
||||
ContinuationActionWrap, ImageView, ResponseContext, Thumbnails, TwoColumnBrowseResults,
|
||||
ContinuationActionWrap, ImageView, PageHeaderRendererContent, PhMetadataView, ResponseContext,
|
||||
Thumbnails, TwoColumnBrowseResults,
|
||||
};
|
||||
use crate::serializer::text::{AttributedText, Text, TextComponent};
|
||||
|
||||
|
|
@ -76,7 +77,7 @@ pub(crate) enum Header {
|
|||
C4TabbedHeaderRenderer(HeaderRenderer),
|
||||
/// Used for special channels like YouTube Music
|
||||
CarouselHeaderRenderer(ContentsRenderer<CarouselHeaderRendererItem>),
|
||||
PageHeaderRenderer(ContentRenderer<PageHeaderRenderer>),
|
||||
PageHeaderRenderer(ContentRenderer<PageHeaderRendererContent<PageHeaderRendererInner>>),
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
|
|
@ -114,12 +115,6 @@ pub(crate) enum CarouselHeaderRendererItem {
|
|||
None,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PageHeaderRenderer {
|
||||
pub page_header_view_model: PageHeaderRendererInner,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
|
@ -225,38 +220,12 @@ pub(crate) struct PhAvatarView3 {
|
|||
pub avatar_view_model: ImageView,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhMetadataView {
|
||||
pub content_metadata_view_model: PhMetadataView2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhMetadataView2 {
|
||||
pub metadata_rows: Vec<PhMetadataRow>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhMetadataRow {
|
||||
pub metadata_parts: Vec<TextWrap>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhBannerView {
|
||||
pub image_banner_view_model: ImageView,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct TextWrap {
|
||||
#[serde_as(deserialize_as = "Text")]
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct Metadata {
|
||||
|
|
|
|||
|
|
@ -57,7 +57,8 @@ use serde::{
|
|||
use serde_with::{serde_as, DisplayFromStr, VecSkipError};
|
||||
|
||||
use crate::error::ExtractionError;
|
||||
use crate::serializer::{text::Text, MapResult, VecSkipErrorWrap};
|
||||
use crate::serializer::text::{AttributedText, Text, TextComponent};
|
||||
use crate::serializer::{MapResult, VecSkipErrorWrap};
|
||||
|
||||
use self::video_item::YouTubeListRenderer;
|
||||
|
||||
|
|
@ -464,3 +465,61 @@ where
|
|||
deserializer.deserialize_seq(SeqVisitor(PhantomData::<T>))
|
||||
}
|
||||
}
|
||||
|
||||
// PAGE HEADER
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PageHeaderRendererContent<T> {
|
||||
pub page_header_view_model: T,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhMetadataView {
|
||||
pub content_metadata_view_model: PhMetadataView2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhMetadataView2 {
|
||||
pub metadata_rows: Vec<PhMetadataRow>,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhMetadataRow {
|
||||
#[serde_as(as = "VecSkipError<_>")]
|
||||
pub metadata_parts: Vec<MetadataPart>,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) enum MetadataPart {
|
||||
Text(#[serde_as(deserialize_as = "AttributedText")] String),
|
||||
#[serde(rename_all = "camelCase")]
|
||||
AvatarStack {
|
||||
avatar_stack_view_model: AvatarStackViewModel,
|
||||
},
|
||||
}
|
||||
|
||||
impl MetadataPart {
|
||||
pub fn as_str(&self) -> &str {
|
||||
match self {
|
||||
MetadataPart::Text(s) => s,
|
||||
MetadataPart::AvatarStack {
|
||||
avatar_stack_view_model,
|
||||
} => avatar_stack_view_model.text.as_str(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct AvatarStackViewModel {
|
||||
#[serde_as(deserialize_as = "AttributedText")]
|
||||
pub text: TextComponent,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
use serde::Deserialize;
|
||||
use serde_with::{serde_as, DefaultOnError};
|
||||
use serde_with::{serde_as, DefaultOnError, VecSkipError};
|
||||
|
||||
use crate::serializer::text::{Text, TextComponent, TextComponents};
|
||||
use crate::serializer::text::{AttributedText, Text, TextComponent, TextComponents};
|
||||
|
||||
use super::{
|
||||
video_item::YouTubeListRenderer, Alert, ContentsRenderer, ResponseContext, SectionList, Tab,
|
||||
ThumbnailsWrap, TwoColumnBrowseResults,
|
||||
url_endpoint::NavigationEndpoint, video_item::YouTubeListRenderer, Alert, ContentRenderer,
|
||||
ContentsRenderer, ImageView, PageHeaderRendererContent, PhMetadataView, ResponseContext,
|
||||
SectionList, Tab, ThumbnailsWrap, TwoColumnBrowseResults,
|
||||
};
|
||||
|
||||
#[serde_as]
|
||||
|
|
@ -35,8 +36,9 @@ pub(crate) struct PlaylistVideoListRenderer {
|
|||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct Header {
|
||||
pub playlist_header_renderer: HeaderRenderer,
|
||||
pub(crate) enum Header {
|
||||
PlaylistHeaderRenderer(HeaderRenderer),
|
||||
PageHeaderRenderer(ContentRenderer<PageHeaderRendererContent<PageHeaderRendererInner>>),
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
|
|
@ -111,3 +113,85 @@ pub(crate) struct PlaylistThumbnailRenderer {
|
|||
#[serde(alias = "playlistCustomThumbnailRenderer")]
|
||||
pub playlist_video_thumbnail_renderer: ThumbnailsWrap,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PageHeaderRendererInner {
|
||||
pub title: PhTitleView,
|
||||
pub metadata: PhMetadataView,
|
||||
pub actions: PhActions,
|
||||
pub description: PhDescription,
|
||||
pub hero_image: PhHeroImage,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhDescription {
|
||||
pub description_preview_view_model: PhDescription2,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhDescription2 {
|
||||
#[serde_as(as = "Option<AttributedText>")]
|
||||
pub description: Option<TextComponents>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhHeroImage {
|
||||
pub content_preview_image_view_model: ImageView,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhTitleView {
|
||||
pub dynamic_text_view_model: PhTitleInner,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Default, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhTitleInner {
|
||||
#[serde_as(as = "AttributedText")]
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhActions {
|
||||
pub flexible_actions_view_model: PhActions2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct PhActions2 {
|
||||
pub actions_rows: Vec<ActionsRow>,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct ActionsRow {
|
||||
#[serde_as(as = "VecSkipError<_>")]
|
||||
pub actions: Vec<ButtonAction>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct ButtonAction {
|
||||
pub button_view_model: ButtonViewModel,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct ButtonViewModel {
|
||||
pub on_tap: ActionOnTap,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct ActionOnTap {
|
||||
pub innertube_command: NavigationEndpoint,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ pub(crate) struct WatchEndpointConfig {
|
|||
#[derive(Default, Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
|
||||
pub(crate) enum MusicVideoType {
|
||||
#[default]
|
||||
#[serde(rename = "MUSIC_VIDEO_TYPE_OMV")]
|
||||
#[serde(rename = "MUSIC_VIDEO_TYPE_OMV", alias = "MUSIC_VIDEO_TYPE_UGC")]
|
||||
Video,
|
||||
#[serde(rename = "MUSIC_VIDEO_TYPE_ATV")]
|
||||
Track,
|
||||
|
|
@ -333,4 +333,26 @@ impl NavigationEndpoint {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn into_playlist_id(self) -> Option<String> {
|
||||
match self {
|
||||
NavigationEndpoint::Watch { watch_endpoint } => watch_endpoint.playlist_id,
|
||||
NavigationEndpoint::Browse {
|
||||
browse_endpoint,
|
||||
command_metadata,
|
||||
} => Some(browse_endpoint.browse_id).filter(|_| {
|
||||
browse_endpoint
|
||||
.browse_endpoint_context_supported_configs
|
||||
.map(|c| c.browse_endpoint_context_music_config.page_type == PageType::Playlist)
|
||||
.unwrap_or_default()
|
||||
|| command_metadata
|
||||
.map(|c| c.web_command_metadata.web_page_type == PageType::Playlist)
|
||||
.unwrap_or_default()
|
||||
}),
|
||||
NavigationEndpoint::Url { .. } => None,
|
||||
NavigationEndpoint::WatchPlaylist {
|
||||
watch_playlist_endpoint,
|
||||
} => Some(watch_playlist_endpoint.playlist_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Reference in a new issue