pub mod locale; mod ordering; mod paginator; pub mod stream_filter; pub use locale::{Country, Language}; pub use paginator::Paginator; use std::ops::Range; use chrono::{DateTime, Local}; use serde::{Deserialize, Serialize}; /* #PLAYER */ pub trait FileFormat { fn extension(&self) -> &str; } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct VideoPlayer { pub details: VideoPlayerDetails, pub video_streams: Vec, pub video_only_streams: Vec, pub audio_streams: Vec, pub subtitles: Vec, pub expires_in_seconds: u32, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct VideoPlayerDetails { pub id: String, pub title: String, pub description: Option, pub length: u32, pub thumbnails: Vec, pub channel: ChannelId, pub publish_date: Option>, pub view_count: u64, pub keywords: Vec, pub category: Option, pub is_live_content: bool, pub is_family_safe: Option, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct VideoStream { pub url: String, pub itag: u32, pub bitrate: u32, pub average_bitrate: u32, pub size: Option, pub index_range: Option>, pub init_range: Option>, pub width: u32, pub height: u32, pub fps: u8, pub quality: String, pub hdr: bool, pub mime: String, pub format: VideoFormat, pub codec: VideoCodec, pub throttled: bool, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct AudioStream { pub url: String, pub itag: u32, pub bitrate: u32, pub average_bitrate: u32, pub size: u64, pub index_range: Option>, pub init_range: Option>, pub mime: String, pub format: AudioFormat, pub codec: AudioCodec, pub throttled: bool, pub track: Option, } #[derive( Default, Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, )] #[serde(rename_all = "snake_case")] #[non_exhaustive] pub enum VideoCodec { #[default] Unknown, /// MPEG-4 Part 14 Mp4v, /// avc1 aka H.264: Avc1, /// VP9: Vp9, /// AV1, the latest codec: Av01, } #[derive( Default, Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, )] #[serde(rename_all = "snake_case")] #[non_exhaustive] pub enum AudioCodec { #[default] Unknown, /// MP4A aka AAC: Mp4a, /// Opus: Opus, } /// The video file format #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] #[serde(rename_all = "snake_case")] #[non_exhaustive] pub enum VideoFormat { #[serde(rename = "3gp")] ThreeGp, Mp4, Webm, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct AudioTrack { pub id: String, pub lang: Option, pub lang_name: String, pub is_default: bool, } impl FileFormat for VideoFormat { fn extension(&self) -> &str { match self { VideoFormat::ThreeGp => ".3gp", VideoFormat::Mp4 => ".mp4", VideoFormat::Webm => ".webm", } } } #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] #[serde(rename_all = "snake_case")] #[non_exhaustive] pub enum AudioFormat { M4a, Webm, } impl FileFormat for AudioFormat { fn extension(&self) -> &str { match self { AudioFormat::M4a => ".m4a", AudioFormat::Webm => ".webm", } } } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct Thumbnail { pub url: String, pub width: u32, pub height: u32, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct Subtitle { pub url: String, pub lang: String, pub lang_name: String, pub auto_generated: bool, } /* #PLAYLIST */ #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Playlist { pub id: String, pub name: String, pub videos: Paginator, pub n_videos: u32, pub thumbnails: Vec, pub description: Option, pub channel: Option, pub last_update: Option>, pub last_update_txt: Option, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct PlaylistVideo { pub id: String, pub title: String, pub length: u32, pub thumbnails: Vec, pub channel: ChannelId, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct ChannelId { pub id: String, pub name: String, } /* #VIDEO DETAILS */ #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct VideoDetails { pub id: String, pub title: String, pub description: String, } /* @COMMENTS */ #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct Channel { pub id: String, pub name: String, pub avatars: Vec, pub verified: bool, } // TODO: impl popularity comparison #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Comment { /// Unique YouTube Comment-ID (e.g. `UgynScMrsqGSL8qvePl4AaABAg`) pub id: String, /// Comment text pub text: String, /// Comment author /// /// There may be comments with missing authors (possibly deleted users?). pub author: Option, /// Number of upvotes pub upvotes: u32, /// Number of replies pub n_replies: u32, /// Paginator to fetch comment replies pub replies: Paginator, /// Is the comment from the channel owner? pub by_owner: bool, /// Has the channel owner pinned the comment to the top? pub pinned: bool, /// Has the channel owner marked the comment with a ❤️ ? pub hearted: bool, }