about summary refs log tree commit diff stats
path: root/crates/yt_dlp/src/wrapper/info_json.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/yt_dlp/src/wrapper/info_json.rs')
-rw-r--r--crates/yt_dlp/src/wrapper/info_json.rs278
1 files changed, 273 insertions, 5 deletions
diff --git a/crates/yt_dlp/src/wrapper/info_json.rs b/crates/yt_dlp/src/wrapper/info_json.rs
index 35d155e..a2c00df 100644
--- a/crates/yt_dlp/src/wrapper/info_json.rs
+++ b/crates/yt_dlp/src/wrapper/info_json.rs
@@ -13,7 +13,7 @@
 
 use std::{collections::HashMap, path::PathBuf};
 
-use pyo3::{types::PyDict, Bound, PyResult, Python};
+use pyo3::{Bound, PyResult, Python, types::PyDict};
 use serde::{Deserialize, Deserializer, Serialize};
 use serde_json::Value;
 use url::Url;
@@ -29,123 +29,385 @@ type ExtractorKey = String;
 #[derive(Debug, Deserialize, Serialize, PartialEq)]
 #[serde(deny_unknown_fields)]
 pub struct InfoJson {
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub __files_to_move: Option<FilesToMove>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub __last_playlist_index: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub __post_extractor: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub __x_forwarded_for_ip: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub _filename: Option<PathBuf>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub _format_sort_fields: Option<Vec<String>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub _has_drm: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub _type: Option<InfoType>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub _version: Option<Version>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub abr: Option<f64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub acodec: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub age_limit: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub artists: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub aspect_ratio: Option<f64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub asr: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub audio_channels: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub audio_ext: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub automatic_captions: Option<HashMap<String, Vec<Caption>>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub availability: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub average_rating: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub categories: Option<Vec<String>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub channel: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub channel_follower_count: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub channel_id: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub channel_is_verified: Option<bool>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub channel_url: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub chapters: Option<Vec<Chapter>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub comment_count: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub comments: Option<Vec<Comment>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub concurrent_view_count: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub container: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub description: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub direct: Option<bool>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub display_id: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub downloader_options: Option<DownloaderOptions>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub duration: Option<f64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub duration_string: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub dynamic_range: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub entries: Option<Vec<InfoJson>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub episode: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub episode_number: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub epoch: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub ext: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub extractor: Option<Extractor>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub extractor_key: Option<ExtractorKey>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub filename: Option<PathBuf>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub filesize: Option<u64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub filesize_approx: Option<u64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub format: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub format_id: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub format_index: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub format_note: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub formats: Option<Vec<Format>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub fps: Option<f64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub fulltitle: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub genre: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub genres: Option<Vec<String>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub has_drm: Option<bool>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub heatmap: Option<Vec<HeatMapEntry>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub height: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub hls_aes: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub http_headers: Option<HttpHeader>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub id: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub ie_key: Option<ExtractorKey>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub is_live: Option<bool>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub language: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub language_preference: Option<i32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub license: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub like_count: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub live_status: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub location: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub manifest_url: Option<Url>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub media_type: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub modified_date: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub n_entries: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub original_url: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub playable_in_embed: Option<bool>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub playlist: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub playlist_autonumber: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub playlist_channel: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub playlist_channel_id: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub playlist_count: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub playlist_id: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub playlist_index: Option<u64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub playlist_title: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub playlist_uploader: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub playlist_uploader_id: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub playlist_webpage_url: Option<Url>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub preference: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub protocol: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub quality: Option<f64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub release_date: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub release_timestamp: Option<u64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub release_year: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub repost_count: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub requested_downloads: Option<Vec<RequestedDownloads>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub requested_entries: Option<Vec<u32>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub requested_formats: Option<Vec<Format>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub requested_subtitles: Option<HashMap<String, Subtitle>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub resolution: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub season: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub season_number: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub series: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub source_preference: Option<i32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub sponsorblock_chapters: Option<Vec<SponsorblockChapter>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub stretched_ratio: Option<Todo>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub subtitles: Option<HashMap<String, Vec<Caption>>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub tags: Option<Vec<String>>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub tbr: Option<f64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub thumbnail: Option<Url>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub thumbnails: Option<Vec<ThumbNail>>,
-    pub timestamp: Option<u64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub timestamp: Option<f64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub title: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub upload_date: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub uploader: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub uploader_id: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub uploader_url: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub url: Option<Url>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub vbr: Option<f64>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub vcodec: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub video_ext: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub view_count: Option<u32>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub was_live: Option<bool>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub webpage_url: Option<Url>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub webpage_url_basename: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub webpage_url_domain: Option<String>,
+
+    #[serde(skip_serializing_if = "Option::is_none")]
     pub width: Option<u32>,
 }
 
@@ -181,7 +443,7 @@ pub struct RequestedDownloads {
     pub filesize_approx: Option<u64>,
     pub format: String,
     pub format_id: String,
-    pub format_note: String,
+    pub format_note: Option<String>,
     pub fps: Option<f64>,
     pub has_drm: Option<bool>,
     pub height: Option<u32>,
@@ -190,6 +452,7 @@ pub struct RequestedDownloads {
     pub language: Option<String>,
     pub manifest_url: Option<Url>,
     pub protocol: String,
+    pub quality: Option<i64>,
     pub requested_formats: Option<Vec<Format>>,
     pub resolution: String,
     pub tbr: f64,
@@ -350,12 +613,15 @@ pub struct HeatMapEntry {
 #[serde(deny_unknown_fields)]
 pub enum InfoType {
     #[serde(alias = "playlist")]
+    #[serde(rename(serialize = "playlist"))]
     Playlist,
 
     #[serde(alias = "url")]
+    #[serde(rename(serialize = "url"))]
     Url,
 
     #[serde(alias = "video")]
+    #[serde(rename(serialize = "video"))]
     Video,
 }
 
@@ -432,7 +698,7 @@ pub struct Comment {
     // Can't also be deserialized, as it's already used in 'edited'
     // _time_text: String,
     pub timestamp: i64,
-    pub author_url: Url,
+    pub author_url: Option<Url>,
     pub author_is_uploader: bool,
     pub is_favorited: bool,
 }
@@ -496,6 +762,7 @@ pub struct Format {
     pub height: Option<u32>,
     pub http_headers: Option<HttpHeader>,
     pub is_dash_periods: Option<bool>,
+    pub is_live: Option<bool>,
     pub language: Option<String>,
     pub language_preference: Option<i32>,
     pub manifest_stream_number: Option<u32>,
@@ -543,9 +810,10 @@ pub struct HttpHeader {
 #[derive(Debug, Deserialize, Serialize, PartialEq, PartialOrd)]
 #[serde(deny_unknown_fields)]
 pub struct Fragment {
-    pub url: Option<Url>,
     pub duration: Option<f64>,
+    pub fragment_count: Option<usize>,
     pub path: Option<PathBuf>,
+    pub url: Option<Url>,
 }
 
 impl InfoJson {