diff --git a/src/client/mod.rs b/src/client/mod.rs index 4c5a549..4de9d87 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -991,12 +991,14 @@ impl RustyPipeQuery { if !mapres.warnings.is_empty() { create_report( Level::WRN, - Some(ExtractionError::Warnings.to_string()), + Some(ExtractionError::DeserializationWarnings.to_string()), mapres.warnings, ); if self.opts.strict { - return Err(Error::Extraction(ExtractionError::Warnings)); + return Err(Error::Extraction( + ExtractionError::DeserializationWarnings, + )); } } else if self.opts.report { create_report(Level::DBG, None, vec![]); diff --git a/src/client/response/channel.rs b/src/client/response/channel.rs index f98d502..3f37ca3 100644 --- a/src/client/response/channel.rs +++ b/src/client/response/channel.rs @@ -9,7 +9,7 @@ use crate::serializer::ignore_any; use crate::serializer::{text::Text, MapResult, VecLogError}; #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Channel { pub header: Header, @@ -19,13 +19,13 @@ pub struct Channel { } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ChannelCont { pub on_response_received_actions: Vec, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Contents { pub two_column_browse_results_renderer: TabsRenderer, @@ -34,26 +34,26 @@ pub struct Contents { /// YouTube channel tab view. Contains multiple tabs /// (Home, Videos, Playlists, About...). We can ignore unknown tabs. #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TabsRenderer { #[serde_as(as = "VecSkipError<_>")] pub tabs: Vec, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TabRendererWrap { pub tab_renderer: ContentRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SectionListRendererWrap { pub section_list_renderer: SectionListRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SectionListRenderer { pub contents: Vec, @@ -63,14 +63,14 @@ pub struct SectionListRenderer { pub target_id: Option, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ItemSectionRendererWrap { pub item_section_renderer: ContentsRenderer, } #[serde_as] -#[derive(Default, Clone, Debug, Deserialize)] +#[derive(Default, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub enum ChannelContent { GridRenderer { @@ -83,14 +83,14 @@ pub enum ChannelContent { None, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Header { pub c4_tabbed_header_renderer: HeaderRenderer, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct HeaderRenderer { pub channel_id: String, @@ -114,26 +114,26 @@ pub struct HeaderRenderer { pub tv_banner: Thumbnails, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Metadata { pub channel_metadata_renderer: ChannelMetadataRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ChannelMetadataRenderer { pub description: String, pub vanity_channel_url: Option, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Microformat { pub microformat_data_renderer: MicroformatDataRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MicroformatDataRenderer { #[serde(default)] @@ -141,7 +141,7 @@ pub struct MicroformatDataRenderer { } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ChannelFullMetadata { #[serde_as(as = "Text")] @@ -153,7 +153,7 @@ pub struct ChannelFullMetadata { } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PrimaryLink { #[serde_as(as = "Text")] @@ -161,26 +161,26 @@ pub struct PrimaryLink { pub navigation_endpoint: NavigationEndpoint, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct NavigationEndpoint { pub url_endpoint: UrlEndpoint, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UrlEndpoint { pub url: String, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct OnResponseReceivedAction { pub append_continuation_items_action: AppendAction, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AppendAction { #[serde_as(as = "VecLogError<_>")] diff --git a/src/client/response/channel_rss.rs b/src/client/response/channel_rss.rs index b054832..e5eff72 100644 --- a/src/client/response/channel_rss.rs +++ b/src/client/response/channel_rss.rs @@ -3,7 +3,7 @@ use serde::Deserialize; use super::Thumbnail; -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] pub struct ChannelRss { #[serde(rename = "$unflatten=yt:channelId")] pub channel_id: String, @@ -14,7 +14,7 @@ pub struct ChannelRss { pub entry: Vec, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] pub struct Entry { #[serde(rename = "$unflatten=yt:videoId")] pub video_id: String, @@ -28,7 +28,7 @@ pub struct Entry { pub media_group: MediaGroup, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] pub struct MediaGroup { #[serde(rename = "$unflatten=media:thumbnail")] pub thumbnail: Thumbnail, @@ -38,7 +38,7 @@ pub struct MediaGroup { pub community: Community, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] pub struct Community { #[serde(rename = "$unflatten=media:starRating")] pub rating: Rating, @@ -46,12 +46,12 @@ pub struct Community { pub statistics: Statistics, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] pub struct Rating { pub count: u32, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] pub struct Statistics { pub views: u64, } diff --git a/src/client/response/mod.rs b/src/client/response/mod.rs index 3b43b17..8ee2c6a 100644 --- a/src/client/response/mod.rs +++ b/src/client/response/mod.rs @@ -27,20 +27,20 @@ use crate::serializer::{ text::{Text, TextComponent}, }; -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ContentRenderer { pub content: T, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ContentsRenderer { #[serde(alias = "tabs")] pub contents: Vec, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ThumbnailsWrap { #[serde(default)] @@ -49,14 +49,14 @@ pub struct ThumbnailsWrap { /// List of images in different resolutions. /// Not only used for thumbnails, but also for avatars and banners. -#[derive(Default, Clone, Debug, Deserialize)] +#[derive(Default, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Thumbnails { #[serde(default)] pub thumbnails: Vec, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Thumbnail { pub url: String, @@ -64,7 +64,7 @@ pub struct Thumbnail { pub height: u32, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub enum VideoListItem { GridVideoRenderer(GridVideoRenderer), @@ -90,7 +90,7 @@ pub enum VideoListItem { /// Video displayed on a channel page #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GridVideoRenderer { pub video_id: String, @@ -111,7 +111,7 @@ pub struct GridVideoRenderer { /// Video displayed in recommendations #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CompactVideoRenderer { pub video_id: String, @@ -145,7 +145,7 @@ pub struct CompactVideoRenderer { /// Video displayed in a playlist #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PlaylistVideoRenderer { pub video_id: String, @@ -160,7 +160,7 @@ pub struct PlaylistVideoRenderer { /// Playlist displayed on a channel page #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GridPlaylistRenderer { pub playlist_id: String, @@ -172,7 +172,7 @@ pub struct GridPlaylistRenderer { } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UpcomingEventData { /// Unixtime in seconds @@ -180,26 +180,26 @@ pub struct UpcomingEventData { pub start_time: i64, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ContinuationItemRenderer { pub continuation_endpoint: ContinuationEndpoint, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ContinuationEndpoint { pub continuation_command: ContinuationCommand, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ContinuationCommand { pub token: String, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Icon { pub icon_type: IconType, @@ -216,14 +216,14 @@ pub enum IconType { Like, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VideoOwner { pub video_owner_renderer: VideoOwnerRenderer, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VideoOwnerRenderer { pub title: TextComponent, @@ -235,13 +235,13 @@ pub struct VideoOwnerRenderer { pub badges: Vec, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ChannelBadge { pub metadata_badge_renderer: ChannelBadgeRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ChannelBadgeRenderer { pub style: ChannelBadgeStyle, @@ -254,14 +254,14 @@ pub enum ChannelBadgeStyle { BadgeStyleTypeVerifiedArtist, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TimeOverlay { pub thumbnail_overlay_time_status_renderer: TimeOverlayRenderer, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TimeOverlayRenderer { /// `29:54` @@ -285,7 +285,7 @@ pub enum TimeOverlayStyle { /// Badges are displayed on the video thumbnail and /// show certain video properties (e.g. active livestream) -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VideoBadge { pub metadata_badge_renderer: VideoBadgeRenderer, @@ -293,7 +293,7 @@ pub struct VideoBadge { /// Badges are displayed on the video thumbnail and /// show certain video properties (e.g. active livestream) -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VideoBadgeRenderer { pub style: VideoBadgeStyle, @@ -309,7 +309,7 @@ pub enum VideoBadgeStyle { // YouTube Music #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MusicItem { pub thumbnail: MusicThumbnailRenderer, @@ -322,21 +322,21 @@ pub struct MusicItem { pub fixed_columns: Vec, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MusicThumbnailRenderer { #[serde(alias = "croppedSquareThumbnailRenderer")] pub music_thumbnail_renderer: ThumbnailsWrap, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PlaylistItemData { pub video_id: String, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MusicContentsRenderer { pub contents: Vec, @@ -344,7 +344,7 @@ pub struct MusicContentsRenderer { pub continuations: Option>, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] pub struct MusicColumn { #[serde( rename = "musicResponsiveListItemFlexColumnRenderer", @@ -354,18 +354,18 @@ pub struct MusicColumn { } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] pub struct MusicColumnRenderer { pub text: TextComponent, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MusicContinuation { pub next_continuation_data: MusicContinuationData, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MusicContinuationData { pub continuation: String, diff --git a/src/client/response/player.rs b/src/client/response/player.rs index 55c3a1c..ee8fce6 100644 --- a/src/client/response/player.rs +++ b/src/client/response/player.rs @@ -8,7 +8,7 @@ use serde_with::{json::JsonString, DefaultOnError}; use super::Thumbnails; use crate::serializer::{text::Text, MapResult, VecLogError}; -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Player { pub playability_status: PlayabilityStatus, @@ -18,7 +18,7 @@ pub struct Player { pub microformat: Option, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(tag = "status", rename_all = "SCREAMING_SNAKE_CASE")] pub enum PlayabilityStatus { #[serde(rename_all = "camelCase")] @@ -36,11 +36,11 @@ pub enum PlayabilityStatus { Error { reason: String }, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] pub struct Empty {} #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct StreamingData { #[serde_as(as = "JsonString")] @@ -58,7 +58,7 @@ pub struct StreamingData { } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Format { pub itag: u32, @@ -152,7 +152,7 @@ pub enum FormatType { FormatStreamTypeOtf, } -#[derive(Default, Clone, Debug, Deserialize)] +#[derive(Default, Debug, Deserialize)] #[serde(default, rename_all = "camelCase")] pub struct ColorInfo { pub primaries: Primaries, @@ -166,7 +166,7 @@ pub enum Primaries { ColorPrimariesBt2020, } -#[derive(Default, Clone, Debug, Deserialize)] +#[derive(Default, Debug, Deserialize)] #[serde(default, rename_all = "camelCase")] pub struct AudioTrack { pub id: String, @@ -174,20 +174,20 @@ pub struct AudioTrack { pub audio_is_default: bool, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Captions { pub player_captions_tracklist_renderer: PlayerCaptionsTracklistRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PlayerCaptionsTracklistRenderer { pub caption_tracks: Vec, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CaptionTrack { pub base_url: String, @@ -197,7 +197,7 @@ pub struct CaptionTrack { } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VideoDetails { pub video_id: String, @@ -215,7 +215,7 @@ pub struct VideoDetails { pub is_live_content: bool, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Microformat { #[serde(alias = "microformatDataRenderer")] @@ -223,7 +223,7 @@ pub struct Microformat { } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PlayerMicroformatRenderer { #[serde(alias = "familySafe")] diff --git a/src/client/response/playlist.rs b/src/client/response/playlist.rs index 5c90ba6..7fe0d31 100644 --- a/src/client/response/playlist.rs +++ b/src/client/response/playlist.rs @@ -7,7 +7,7 @@ use crate::serializer::{MapResult, VecLogError}; use super::{ContentRenderer, ContentsRenderer, ThumbnailsWrap, VideoListItem}; -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Playlist { pub contents: Contents, @@ -16,59 +16,59 @@ pub struct Playlist { } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PlaylistCont { #[serde_as(as = "VecSkipError<_>")] pub on_response_received_actions: Vec, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Contents { pub two_column_browse_results_renderer: ContentsRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Tab { pub tab_renderer: ContentRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SectionList { pub section_list_renderer: ContentsRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ItemSection { pub item_section_renderer: ContentsRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PlaylistVideoListRenderer { pub playlist_video_list_renderer: PlaylistVideoList, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PlaylistVideoList { #[serde_as(as = "VecLogError<_>")] pub contents: MapResult>, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Header { pub playlist_header_renderer: HeaderRenderer, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct HeaderRenderer { pub playlist_id: String, @@ -87,48 +87,48 @@ pub struct HeaderRenderer { pub byline: Vec, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PlaylistHeaderBanner { pub hero_playlist_thumbnail_renderer: ThumbnailsWrap, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Byline { pub playlist_byline_renderer: BylineRenderer, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct BylineRenderer { #[serde_as(as = "Text")] pub text: String, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Sidebar { pub playlist_sidebar_renderer: SidebarRenderer, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SidebarRenderer { #[serde_as(as = "VecSkipError<_>")] pub items: Vec, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SidebarItemPrimary { pub playlist_sidebar_primary_info_renderer: SidebarPrimaryInfoRenderer, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SidebarPrimaryInfoRenderer { pub thumbnail_renderer: PlaylistThumbnailRenderer, @@ -139,7 +139,7 @@ pub struct SidebarPrimaryInfoRenderer { pub stats: Vec, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PlaylistThumbnailRenderer { // the alternative field name is used by YTM playlists @@ -147,14 +147,14 @@ pub struct PlaylistThumbnailRenderer { pub playlist_video_thumbnail_renderer: ThumbnailsWrap, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct OnResponseReceivedAction { pub append_continuation_items_action: AppendAction, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AppendAction { #[serde_as(as = "VecLogError<_>")] diff --git a/src/client/response/playlist_music.rs b/src/client/response/playlist_music.rs index 86e854c..85ad5ff 100644 --- a/src/client/response/playlist_music.rs +++ b/src/client/response/playlist_music.rs @@ -9,33 +9,33 @@ use super::{ ContentRenderer, ContentsRenderer, MusicContentsRenderer, MusicContinuation, MusicItem, }; -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PlaylistMusic { pub contents: Contents, pub header: Header, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Contents { pub single_column_browse_results_renderer: ContentsRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Tab { pub tab_renderer: ContentRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SectionList { /// Includes a continuation token for fetching recommendations pub section_list_renderer: MusicContentsRenderer, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ItemSection { #[serde(alias = "musicPlaylistShelfRenderer")] @@ -43,7 +43,7 @@ pub struct ItemSection { } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MusicShelf { /// Playlist ID (only for playlists) @@ -55,20 +55,20 @@ pub struct MusicShelf { pub continuations: Option>, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PlaylistMusicItem { pub music_responsive_list_item_renderer: MusicItem, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Header { pub music_detail_header_renderer: HeaderRenderer, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct HeaderRenderer { #[serde_as(as = "crate::serializer::text::Text")] diff --git a/src/client/response/video_details.rs b/src/client/response/video_details.rs index fc23707..4b9b6f1 100644 --- a/src/client/response/video_details.rs +++ b/src/client/response/video_details.rs @@ -22,7 +22,7 @@ use super::{ /// Video details response #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VideoDetails { /// Video metadata + recommended videos @@ -35,13 +35,13 @@ pub struct VideoDetails { } /// Video details main object, contains video metadata and recommended videos -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Contents { pub two_column_watch_next_results: TwoColumnWatchNextResults, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TwoColumnWatchNextResults { /// Metadata about the video @@ -53,7 +53,7 @@ pub struct TwoColumnWatchNextResults { } /// Metadata about the video -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VideoResultsWrap { pub results: VideoResults, @@ -61,7 +61,7 @@ pub struct VideoResultsWrap { /// Video metadata items #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VideoResults { #[serde_as(as = "VecLogError<_>")] @@ -70,7 +70,7 @@ pub struct VideoResults { /// Video metadata item #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub enum VideoResultsItem { #[serde(rename_all = "camelCase")] @@ -104,14 +104,14 @@ pub enum VideoResultsItem { None, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ViewCount { pub video_view_count_renderer: ViewCountRenderer, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ViewCountRenderer { /// View count (`232,975,196 views`) @@ -122,7 +122,7 @@ pub struct ViewCountRenderer { } /// Like/Dislike buttons -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VideoActions { pub menu_renderer: VideoActionsMenu, @@ -130,7 +130,7 @@ pub struct VideoActions { /// Like/Dislike buttons #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VideoActionsMenu { #[serde_as(as = "VecSkipError<_>")] @@ -143,7 +143,7 @@ pub struct VideoActionsMenu { /// /// See: https://github.com/TeamNewPipe/NewPipeExtractor/pull/926 #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub enum TopLevelButton { ToggleButtonRenderer(ToggleButton), @@ -154,7 +154,7 @@ pub enum TopLevelButton { } /// Like/Dislike button -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ToggleButtonWrap { pub toggle_button_renderer: ToggleButton, @@ -162,7 +162,7 @@ pub struct ToggleButtonWrap { /// Like/Dislike button #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ToggleButton { /// Icon type: `LIKE` / `DISLIKE` @@ -176,7 +176,7 @@ pub struct ToggleButton { /// Shows additional video metadata. Its only known use is for /// the Creative Commonse License. -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MetadataRowContainer { pub metadata_row_container_renderer: MetadataRowContainerRenderer, @@ -184,14 +184,14 @@ pub struct MetadataRowContainer { /// Shows additional video metadata. Its only known use is for /// the Creative Commonse License. -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MetadataRowContainerRenderer { pub rows: Vec, } /// Additional video metadata item (Creative Commons License) -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MetadataRow { pub metadata_row_renderer: MetadataRowRenderer, @@ -199,7 +199,7 @@ pub struct MetadataRow { /// Additional video metadata item (Creative Commons License) #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MetadataRowRenderer { // `License` @@ -214,13 +214,13 @@ pub struct MetadataRowRenderer { } /// Contains current video ID -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CurrentVideoEndpoint { pub watch_endpoint: CurrentVideoWatchEndpoint, } /// Contains current video ID -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CurrentVideoWatchEndpoint { pub video_id: String, @@ -231,7 +231,7 @@ pub struct CurrentVideoWatchEndpoint { /// 1. CommentsEntryPointHeaderRenderer: contains number of comments /// 2. ContinuationItemRenderer: contains continuation token #[serde_as] -#[derive(Default, Clone, Debug, Deserialize)] +#[derive(Default, Debug, Deserialize)] #[serde(rename_all = "kebab-case", tag = "sectionIdentifier")] pub enum ItemSection { CommentsEntryPoint { @@ -247,7 +247,7 @@ pub enum ItemSection { } /// Item section containing comment count -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ItemSectionCommentCount { pub comments_entry_point_header_renderer: CommentsEntryPointHeaderRenderer, @@ -255,7 +255,7 @@ pub struct ItemSectionCommentCount { /// Renderer of item section containing comment count #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommentsEntryPointHeaderRenderer { #[serde_as(as = "Text")] @@ -263,14 +263,14 @@ pub struct CommentsEntryPointHeaderRenderer { } /// Item section containing comments ctoken -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ItemSectionComments { pub continuation_item_renderer: ContinuationItemRenderer, } /// Video recommendations -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RecommendationResultsWrap { pub secondary_results: RecommendationResults, @@ -278,7 +278,7 @@ pub struct RecommendationResultsWrap { /// Video recommendations #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RecommendationResults { /// Can be `None` for age-restricted videos @@ -288,7 +288,7 @@ pub struct RecommendationResults { /// The engagement panels are displayed below the video and contain chapter markers /// and the comment section. -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct EngagementPanel { pub engagement_panel_section_list_renderer: EngagementPanelRenderer, @@ -296,7 +296,7 @@ pub struct EngagementPanel { /// The engagement panels are displayed below the video and contain chapter markers /// and the comment section. -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "kebab-case", tag = "targetId")] pub enum EngagementPanelRenderer { /// Chapter markers @@ -315,7 +315,7 @@ pub enum EngagementPanelRenderer { } /// Chapter markers -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ChapterMarkersContent { pub macro_markers_list_renderer: MacroMarkersListRenderer, @@ -323,7 +323,7 @@ pub struct ChapterMarkersContent { /// Chapter markers #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MacroMarkersListRenderer { #[serde_as(as = "VecLogError<_>")] @@ -331,7 +331,7 @@ pub struct MacroMarkersListRenderer { } /// Chapter marker -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MacroMarkersListItem { pub macro_markers_list_item_renderer: MacroMarkersListItemRenderer, @@ -339,7 +339,7 @@ pub struct MacroMarkersListItem { /// Chapter marker #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MacroMarkersListItemRenderer { /// Contains chapter start time in seconds @@ -352,13 +352,13 @@ pub struct MacroMarkersListItemRenderer { } /// Contains chapter start time in seconds -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MacroMarkersListItemOnTap { pub watch_endpoint: MacroMarkersListItemWatchEndpoint, } /// Contains chapter start time in seconds -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MacroMarkersListItemWatchEndpoint { /// Chapter start time in seconds @@ -367,7 +367,7 @@ pub struct MacroMarkersListItemWatchEndpoint { /// Comment section header /// (contains continuation tokens for fetching top/latest comments) -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommentItemSectionHeader { pub engagement_panel_title_header_renderer: CommentItemSectionHeaderRenderer, @@ -376,7 +376,7 @@ pub struct CommentItemSectionHeader { /// Comment section header /// (contains continuation tokens for fetching top/latest comments) #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommentItemSectionHeaderRenderer { /// Approximate comment count (e.g. `81`, `2.2K`, `705K`) @@ -390,7 +390,7 @@ pub struct CommentItemSectionHeaderRenderer { } /// Comment section menu -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommentItemSectionHeaderMenu { pub sort_filter_sub_menu_renderer: CommentItemSectionHeaderMenuRenderer, @@ -401,14 +401,14 @@ pub struct CommentItemSectionHeaderMenu { /// Items: /// - Top comments /// - Latest comments -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommentItemSectionHeaderMenuRenderer { pub sub_menu_items: Vec, } /// Comment section menu item -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommentItemSectionHeaderMenuItem { /// Continuation token for fetching comments @@ -420,14 +420,14 @@ pub struct CommentItemSectionHeaderMenuItem { */ /// Video recommendations continuation response -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VideoRecommendations { pub on_response_received_endpoints: Vec, } /// Video recommendations continuation -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RecommendationsContItem { pub append_continuation_items_action: AppendRecommendations, @@ -435,7 +435,7 @@ pub struct RecommendationsContItem { /// Video recommendations continuation #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AppendRecommendations { #[serde_as(as = "VecLogError<_>")] @@ -448,7 +448,7 @@ pub struct AppendRecommendations { /// Video comments continuation response #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct VideoComments { /// - Initial response: 2*reloadContinuationItemsCommand @@ -466,7 +466,7 @@ pub struct VideoComments { } /// Video comments continuation -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommentsContItem { #[serde(alias = "reloadContinuationItemsCommand")] @@ -475,7 +475,7 @@ pub struct CommentsContItem { /// Video comments continuation action #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AppendComments { #[serde_as(as = "VecLogError<_>")] @@ -483,7 +483,7 @@ pub struct AppendComments { } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub enum CommentListItem { /// Top-level comment @@ -513,14 +513,14 @@ pub enum CommentListItem { }, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Comment { pub comment_renderer: CommentRenderer, } #[serde_as] -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommentRenderer { /// Author name @@ -551,19 +551,19 @@ pub struct CommentRenderer { pub action_buttons: CommentActionButtons, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AuthorEndpoint { pub browse_endpoint: BrowseEndpoint, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct BrowseEndpoint { pub browse_id: String, } -#[derive(Default, Clone, Copy, Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Default, Clone, Copy, Debug, Deserialize, PartialEq, Eq)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum CommentPriority { /// Default rendering priority @@ -575,7 +575,7 @@ pub enum CommentPriority { /// Does not contain replies directly but a continuation token /// for fetching them. -#[derive(Default, Clone, Debug, Deserialize)] +#[derive(Default, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Replies { pub comment_replies_renderer: RepliesRenderer, @@ -584,7 +584,7 @@ pub struct Replies { /// Does not contain replies directly but a continuation token /// for fetching them. #[serde_as] -#[derive(Default, Clone, Debug, Deserialize)] +#[derive(Default, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RepliesRenderer { #[serde_as(as = "VecSkipError<_>")] @@ -593,7 +593,7 @@ pub struct RepliesRenderer { /// These are the buttons for comment interaction (Like/Dislike/Reply). /// Contains the CreatorHeart. -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommentActionButtons { pub comment_action_buttons_renderer: CommentActionButtonsRenderer, @@ -601,7 +601,7 @@ pub struct CommentActionButtons { /// These are the buttons for comment interaction (Like/Dislike/Reply). /// Contains the CreatorHeart. -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommentActionButtonsRenderer { pub like_button: ToggleButtonWrap, @@ -609,27 +609,27 @@ pub struct CommentActionButtonsRenderer { } /// Video creators can endorse comments by marking them with a ❤️. -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CreatorHeart { pub creator_heart_renderer: CreatorHeartRenderer, } /// Video creators can endorse comments by marking them with a ❤️. -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CreatorHeartRenderer { pub is_hearted: bool, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AuthorCommentBadge { pub author_comment_badge_renderer: AuthorCommentBadgeRenderer, } /// YouTube channel badge (verified) of the comment author -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AuthorCommentBadgeRenderer { /// Verified: `CHECK` diff --git a/src/error.rs b/src/error.rs index 97b061c..572fd9e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -82,7 +82,7 @@ pub enum ExtractionError { #[error("got wrong result from YT: {0}")] WrongResult(String), #[error("Warnings during deserialization/mapping")] - Warnings, + DeserializationWarnings, } /// Internal error diff --git a/src/model/mod.rs b/src/model/mod.rs index 8096227..3d0e9c3 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -453,11 +453,11 @@ pub struct VideoDetails { pub view_count: u64, /// Number of likes /// - /// `None` if the like count was hidden by the creator. + /// [`None`] if the like count was hidden by the creator. pub like_count: Option, /// Video publishing date. Start date in case of a livestream. /// - /// `None` if the date could not be parsed. + /// [`None`] if the date could not be parsed. pub publish_date: Option>, /// Textual video publishing date (e.g. `Aug 2, 2013`, depends on language) pub publish_date_txt: String, @@ -516,7 +516,7 @@ pub struct RecommendedVideo { pub title: String, /// Video length in seconds. /// - /// Is `None` for livestreams. + /// Is [`None`] for livestreams. pub length: Option, /// Video thumbnail pub thumbnail: Vec, @@ -524,15 +524,15 @@ pub struct RecommendedVideo { pub channel: ChannelTag, /// Video publishing date. /// - /// `None` if the date could not be parsed. + /// [`None`] if the date could not be parsed. pub publish_date: Option>, /// Textual video publish date (e.g. `11 months ago`, depends on language) /// - /// Is `None` for livestreams. + /// Is [`None`] for livestreams. pub publish_date_txt: Option, /// View count /// - /// `None` if it could not be extracted. + /// [`None`] if it could not be extracted. pub view_count: Option, /// Is the video an active livestream? pub is_live: bool, @@ -554,7 +554,7 @@ pub struct ChannelTag { pub verification: Verification, /// Approximate number of subscribers /// - /// `None` if hidden by the owner or not present. + /// [`None`] if hidden by the owner or not present. /// /// Info: This is only present in the `VideoDetails` response pub subscriber_count: Option, @@ -600,7 +600,7 @@ pub struct Comment { pub author: Option, /// Comment publishing date. /// - /// `None` if the date could not be parsed. + /// [`None`] if the date could not be parsed. pub publish_date: Option>, /// Textual comment publish date (e.g. `14 hours ago`), depends on language setting pub publish_date_txt: String, @@ -635,7 +635,7 @@ pub struct Channel { pub name: String, /// Channel subscriber count /// - /// `None` if the subscriber count was hidden by the owner + /// [`None`] if the subscriber count was hidden by the owner /// or could not be parsed. pub subscriber_count: Option, /// Channel avatar / profile picture @@ -667,22 +667,22 @@ pub struct ChannelVideo { pub title: String, /// Video length in seconds. /// - /// Is `None` for livestreams. + /// Is [`None`] for livestreams. pub length: Option, /// Video thumbnail pub thumbnail: Vec, /// Video publishing date. /// - /// `None` if the date could not be parsed. + /// [`None`] if the date could not be parsed. /// May be in the future for upcoming videos pub publish_date: Option>, /// Textual video publish date (e.g. `11 months ago`, depends on language) /// - /// Is `None` for livestreams and upcoming videos. + /// Is [`None`] for livestreams and upcoming videos. pub publish_date_txt: Option, /// Number of views / current viewers in case of a livestream. /// - /// `None` if it could not be extracted. + /// [`None`] if it could not be extracted. pub view_count: Option, /// Is the video an active livestream? pub is_live: bool,