Skip to main content

mangofetch_core/models/
media.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use std::path::PathBuf;
4
5use crate::platforms::Platform;
6use tokio_util::sync::CancellationToken;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct MediaInfo {
10    pub title: String,
11    pub author: String,
12    pub platform: String,
13    pub duration_seconds: Option<f64>,
14    pub thumbnail_url: Option<String>,
15    pub available_qualities: Vec<VideoQuality>,
16    pub media_type: MediaType,
17    pub file_size_bytes: Option<u64>,
18}
19
20impl MediaInfo {
21    pub fn get_closest_quality(&self, wanted_quality: &str) -> Option<&VideoQuality> {
22        if self.available_qualities.is_empty() {
23            return None;
24        }
25        if wanted_quality == "best" || wanted_quality == "highest" {
26            return self.available_qualities.first();
27        }
28
29        let target_height = match wanted_quality
30            .to_lowercase()
31            .trim_end_matches('p')
32            .parse::<u32>()
33        {
34            Ok(h) => h,
35            Err(_) => return self.available_qualities.first(),
36        };
37
38        let mut closest = &self.available_qualities[0];
39        let mut min_diff = (closest.height as i32 - target_height as i32).abs() as u32;
40
41        for q in &self.available_qualities {
42            let diff = (q.height as i32 - target_height as i32).abs() as u32;
43            if diff < min_diff {
44                min_diff = diff;
45                closest = q;
46            }
47        }
48
49        Some(closest)
50    }
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
54pub enum MediaType {
55    Video,
56    Audio,
57    Photo,
58    Gif,
59    Carousel,
60    Playlist,
61    Course,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct VideoQuality {
66    pub label: String,
67    pub width: u32,
68    pub height: u32,
69    pub url: String,
70    pub format: String,
71    #[serde(default)]
72    pub filesize_bytes: Option<u64>,
73}
74
75#[derive(Clone)]
76pub struct DownloadOptions {
77    pub quality: Option<String>,
78    pub output_dir: PathBuf,
79    pub filename_template: Option<String>,
80    pub download_subtitles: bool,
81    pub include_auto_subtitles: bool,
82    pub download_mode: Option<String>,
83    pub format_id: Option<String>,
84    pub referer: Option<String>,
85    pub extra_headers: Option<HashMap<String, String>>,
86    pub page_url: Option<String>,
87    pub user_agent: Option<String>,
88    pub cancel_token: CancellationToken,
89    pub concurrent_fragments: u32,
90    pub ytdlp_path: Option<PathBuf>,
91    pub torrent_listen_port: Option<u16>,
92    pub torrent_id_slot: Option<std::sync::Arc<tokio::sync::Mutex<Option<usize>>>>,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct FormatInfo {
97    pub format_id: String,
98    pub ext: String,
99    pub resolution: Option<String>,
100    pub width: Option<u32>,
101    pub height: Option<u32>,
102    pub fps: Option<f64>,
103    pub vcodec: Option<String>,
104    pub acodec: Option<String>,
105    pub filesize: Option<u64>,
106    pub tbr: Option<f64>,
107    pub has_video: bool,
108    pub has_audio: bool,
109    pub format_note: Option<String>,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct DownloadResult {
114    pub file_path: PathBuf,
115    pub file_size_bytes: u64,
116    pub duration_seconds: f64,
117    /// Torrent ID within the shared librqbit session (magnet downloads only).
118    #[serde(default)]
119    pub torrent_id: Option<usize>,
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
123pub struct MediaItem {
124    pub url: String,
125    pub media_type: MediaType,
126    pub thumbnail_url: Option<String>,
127    pub width: Option<u32>,
128    pub height: Option<u32>,
129    pub duration_seconds: Option<f64>,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct GenericDownloadResult {
134    pub platform: Platform,
135    pub title: String,
136    pub author: String,
137    pub files: Vec<DownloadedFile>,
138    pub total_bytes: u64,
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct DownloadedFile {
143    pub path: PathBuf,
144    pub media_type: MediaType,
145    pub size_bytes: u64,
146}