use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
use crate::platforms::Platform;
use tokio_util::sync::CancellationToken;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MediaInfo {
pub title: String,
pub author: String,
pub platform: String,
pub duration_seconds: Option<f64>,
pub thumbnail_url: Option<String>,
pub available_qualities: Vec<VideoQuality>,
pub media_type: MediaType,
pub file_size_bytes: Option<u64>,
}
impl MediaInfo {
pub fn get_closest_quality(&self, wanted_quality: &str) -> Option<&VideoQuality> {
if self.available_qualities.is_empty() {
return None;
}
if wanted_quality == "best" || wanted_quality == "highest" {
return self.available_qualities.first();
}
let target_height = match wanted_quality
.to_lowercase()
.trim_end_matches('p')
.parse::<u32>()
{
Ok(h) => h,
Err(_) => return self.available_qualities.first(),
};
let mut closest = &self.available_qualities[0];
let mut min_diff = (closest.height as i32 - target_height as i32).abs() as u32;
for q in &self.available_qualities {
let diff = (q.height as i32 - target_height as i32).abs() as u32;
if diff < min_diff {
min_diff = diff;
closest = q;
}
}
Some(closest)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum MediaType {
Video,
Audio,
Photo,
Gif,
Carousel,
Playlist,
Course,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VideoQuality {
pub label: String,
pub width: u32,
pub height: u32,
pub url: String,
pub format: String,
#[serde(default)]
pub filesize_bytes: Option<u64>,
}
#[derive(Clone)]
pub struct DownloadOptions {
pub quality: Option<String>,
pub output_dir: PathBuf,
pub filename_template: Option<String>,
pub download_subtitles: bool,
pub include_auto_subtitles: bool,
pub download_mode: Option<String>,
pub format_id: Option<String>,
pub referer: Option<String>,
pub extra_headers: Option<HashMap<String, String>>,
pub page_url: Option<String>,
pub user_agent: Option<String>,
pub cancel_token: CancellationToken,
pub concurrent_fragments: u32,
pub ytdlp_path: Option<PathBuf>,
pub torrent_listen_port: Option<u16>,
pub torrent_id_slot: Option<std::sync::Arc<tokio::sync::Mutex<Option<usize>>>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FormatInfo {
pub format_id: String,
pub ext: String,
pub resolution: Option<String>,
pub width: Option<u32>,
pub height: Option<u32>,
pub fps: Option<f64>,
pub vcodec: Option<String>,
pub acodec: Option<String>,
pub filesize: Option<u64>,
pub tbr: Option<f64>,
pub has_video: bool,
pub has_audio: bool,
pub format_note: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DownloadResult {
pub file_path: PathBuf,
pub file_size_bytes: u64,
pub duration_seconds: f64,
#[serde(default)]
pub torrent_id: Option<usize>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MediaItem {
pub url: String,
pub media_type: MediaType,
pub thumbnail_url: Option<String>,
pub width: Option<u32>,
pub height: Option<u32>,
pub duration_seconds: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GenericDownloadResult {
pub platform: Platform,
pub title: String,
pub author: String,
pub files: Vec<DownloadedFile>,
pub total_bytes: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DownloadedFile {
pub path: PathBuf,
pub media_type: MediaType,
pub size_bytes: u64,
}