Skip to main content

gosh_dl/protocol/
options.rs

1//! Download options and priority types
2//!
3//! Types for configuring individual downloads.
4
5use super::checksum::ExpectedChecksum;
6use serde::{Deserialize, Serialize};
7use std::path::PathBuf;
8
9/// Priority levels for downloads
10#[derive(
11    Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
12)]
13#[serde(rename_all = "lowercase")]
14#[repr(i8)]
15pub enum DownloadPriority {
16    /// Low priority - downloads last
17    Low = -1,
18    /// Normal priority - default for most downloads
19    #[default]
20    Normal = 0,
21    /// High priority - downloads before normal
22    High = 1,
23    /// Critical priority - downloads first
24    Critical = 2,
25}
26
27impl std::fmt::Display for DownloadPriority {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        match self {
30            Self::Low => write!(f, "low"),
31            Self::Normal => write!(f, "normal"),
32            Self::High => write!(f, "high"),
33            Self::Critical => write!(f, "critical"),
34        }
35    }
36}
37
38impl std::str::FromStr for DownloadPriority {
39    type Err = String;
40
41    fn from_str(s: &str) -> Result<Self, Self::Err> {
42        match s.to_lowercase().as_str() {
43            "low" | "-1" => Ok(Self::Low),
44            "normal" | "0" => Ok(Self::Normal),
45            "high" | "1" => Ok(Self::High),
46            "critical" | "2" => Ok(Self::Critical),
47            _ => Err(format!("Invalid priority: {}", s)),
48        }
49    }
50}
51
52/// Options for adding a new download
53#[derive(Debug, Clone, Default, Serialize, Deserialize)]
54pub struct DownloadOptions {
55    /// Download priority (affects queue ordering)
56    #[serde(default)]
57    pub priority: DownloadPriority,
58    /// Directory to save files
59    pub save_dir: Option<PathBuf>,
60    /// Output filename
61    pub filename: Option<String>,
62    /// Custom user agent
63    pub user_agent: Option<String>,
64    /// Referer header
65    pub referer: Option<String>,
66    /// Additional headers
67    pub headers: Vec<(String, String)>,
68    /// Cookies for authenticated downloads (e.g., ["session=abc123", "token=xyz"])
69    pub cookies: Option<Vec<String>>,
70    /// Expected checksum for verification after download (e.g., MD5 or SHA256)
71    pub checksum: Option<ExpectedChecksum>,
72    /// Mirror/fallback URLs for redundancy (tried in order on failure)
73    pub mirrors: Vec<String>,
74    /// Max connections for this download
75    pub max_connections: Option<usize>,
76    /// Max download speed (bytes/sec)
77    pub max_download_speed: Option<u64>,
78    /// Max upload speed (bytes/sec, torrent only)
79    pub max_upload_speed: Option<u64>,
80    /// Seed ratio limit (torrent only)
81    pub seed_ratio: Option<f64>,
82    /// Selected file indices (torrent only)
83    pub selected_files: Option<Vec<usize>>,
84    /// Sequential download mode (torrent only) - downloads pieces in order for streaming
85    pub sequential: Option<bool>,
86}
87
88impl DownloadOptions {
89    /// Create new download options with defaults
90    pub fn new() -> Self {
91        Self::default()
92    }
93
94    /// Set download priority
95    pub fn priority(mut self, priority: DownloadPriority) -> Self {
96        self.priority = priority;
97        self
98    }
99
100    /// Set the directory to save files
101    pub fn save_dir(mut self, dir: impl Into<PathBuf>) -> Self {
102        self.save_dir = Some(dir.into());
103        self
104    }
105
106    /// Set the output filename
107    pub fn filename(mut self, name: impl Into<String>) -> Self {
108        self.filename = Some(name.into());
109        self
110    }
111
112    /// Set a custom user agent
113    pub fn user_agent(mut self, ua: impl Into<String>) -> Self {
114        self.user_agent = Some(ua.into());
115        self
116    }
117
118    /// Set the referer header
119    pub fn referer(mut self, referer: impl Into<String>) -> Self {
120        self.referer = Some(referer.into());
121        self
122    }
123
124    /// Add a custom header
125    pub fn header(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
126        self.headers.push((key.into(), value.into()));
127        self
128    }
129
130    /// Set cookies for authenticated downloads
131    pub fn cookies(mut self, cookies: Vec<String>) -> Self {
132        self.cookies = Some(cookies);
133        self
134    }
135
136    /// Set expected checksum for verification
137    pub fn checksum(mut self, checksum: ExpectedChecksum) -> Self {
138        self.checksum = Some(checksum);
139        self
140    }
141
142    /// Add a mirror/fallback URL
143    pub fn mirror(mut self, url: impl Into<String>) -> Self {
144        self.mirrors.push(url.into());
145        self
146    }
147
148    /// Set max connections for this download
149    pub fn max_connections(mut self, n: usize) -> Self {
150        self.max_connections = Some(n);
151        self
152    }
153
154    /// Set max download speed in bytes/sec
155    pub fn max_download_speed(mut self, bps: u64) -> Self {
156        self.max_download_speed = Some(bps);
157        self
158    }
159
160    /// Set max upload speed in bytes/sec (torrent only)
161    pub fn max_upload_speed(mut self, bps: u64) -> Self {
162        self.max_upload_speed = Some(bps);
163        self
164    }
165
166    /// Set seed ratio limit (torrent only)
167    pub fn seed_ratio(mut self, ratio: f64) -> Self {
168        self.seed_ratio = Some(ratio);
169        self
170    }
171
172    /// Set selected file indices (torrent only)
173    pub fn selected_files(mut self, indices: Vec<usize>) -> Self {
174        self.selected_files = Some(indices);
175        self
176    }
177
178    /// Enable sequential download mode for streaming (torrent only)
179    pub fn sequential(mut self, enabled: bool) -> Self {
180        self.sequential = Some(enabled);
181        self
182    }
183}