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).unsigned_abs();
40
41        for q in &self.available_qualities {
42            let diff = (q.height as i32 - target_height as i32).unsigned_abs();
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 video_format: Option<String>,
79    pub audio_format: Option<String>,
80    pub audio_quality: Option<String>,
81    pub output_dir: PathBuf,
82    pub filename_template: Option<String>,
83    pub download_subtitles: bool,
84    pub include_auto_subtitles: bool,
85    pub download_mode: Option<String>,
86    pub format_id: Option<String>,
87    pub referer: Option<String>,
88    pub extra_headers: Option<HashMap<String, String>>,
89    pub page_url: Option<String>,
90    pub user_agent: Option<String>,
91    pub cancel_token: CancellationToken,
92    pub concurrent_fragments: u32,
93    pub ytdlp_path: Option<PathBuf>,
94    pub torrent_listen_port: Option<u16>,
95    pub torrent_id_slot: Option<std::sync::Arc<tokio::sync::Mutex<Option<usize>>>>,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct FormatInfo {
100    pub format_id: String,
101    pub ext: String,
102    pub resolution: Option<String>,
103    pub width: Option<u32>,
104    pub height: Option<u32>,
105    pub fps: Option<f64>,
106    pub vcodec: Option<String>,
107    pub acodec: Option<String>,
108    pub filesize: Option<u64>,
109    pub tbr: Option<f64>,
110    pub has_video: bool,
111    pub has_audio: bool,
112    pub format_note: Option<String>,
113}
114
115#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct DownloadResult {
117    pub file_path: PathBuf,
118    pub file_size_bytes: u64,
119    pub duration_seconds: f64,
120    /// Torrent ID within the shared librqbit session (magnet downloads only).
121    #[serde(default)]
122    pub torrent_id: Option<usize>,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct MediaItem {
127    pub url: String,
128    pub media_type: MediaType,
129    pub thumbnail_url: Option<String>,
130    pub width: Option<u32>,
131    pub height: Option<u32>,
132    pub duration_seconds: Option<f64>,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct GenericDownloadResult {
137    pub platform: Platform,
138    pub title: String,
139    pub author: String,
140    pub files: Vec<DownloadedFile>,
141    pub total_bytes: u64,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct DownloadedFile {
146    pub path: PathBuf,
147    pub media_type: MediaType,
148    pub size_bytes: u64,
149}