use serde::{Deserialize, Serialize}; /// A YouTube channel the user is subscribed to, as imported from Takeout. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Channel { pub id: String, pub title: String, pub url: String, } /// A video as described by a channel's public Atom feed. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Video { pub id: String, pub channel_id: String, pub title: String, pub description: String, /// Unix seconds, so feed ordering is a plain indexed sort. pub published: i64, pub thumb_url: String, pub views: i64, pub is_short: bool, } /// A channel plus how many of its videos we currently know about. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ChannelWithCount { pub id: String, pub title: String, pub url: String, pub video_count: i64, pub downloaded_count: i64, /// Why the last refresh of this channel failed, if it did. pub last_error: Option, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum DownloadState { Queued, Running, Done, Failed, Cancelled, } impl DownloadState { pub fn as_str(&self) -> &'static str { match self { DownloadState::Queued => "queued", DownloadState::Running => "running", DownloadState::Done => "done", DownloadState::Failed => "failed", DownloadState::Cancelled => "cancelled", } } pub fn from_str(s: &str) -> Option { match s { "queued" => Some(DownloadState::Queued), "running" => Some(DownloadState::Running), "done" => Some(DownloadState::Done), "failed" => Some(DownloadState::Failed), "cancelled" => Some(DownloadState::Cancelled), _ => None, } } } /// A feed row: video metadata joined with whatever we know about its download. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FeedItem { pub id: String, pub channel_id: String, pub channel_title: String, pub title: String, pub description: String, pub published: i64, pub thumb_url: String, pub thumb_path: Option, pub views: i64, pub is_short: bool, pub state: Option, pub path: Option, pub pct: Option, pub error: Option, /// Seconds watched, and the video's length — drives the feed progress bar. pub position: Option, pub duration: Option, } #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct FeedFilter { pub channel_id: Option, pub search: Option, #[serde(default)] pub downloaded_only: bool, #[serde(default)] pub hide_shorts: bool, pub limit: Option, } /// Result of checking that the external binaries we shell out to exist. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Prereqs { pub yt_dlp: Option, pub ffmpeg: Option, pub library_path: String, } /// What a replacing Takeout import would add and destroy. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ImportPreview { pub incoming: i64, pub removed_channels: i64, pub removed_videos: i64, pub removed_downloads: i64, }