Skip to main content

qbit_rs/model/
app.rs

1use std::{collections::HashMap, path::PathBuf};
2
3use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
4use serde_with::skip_serializing_none;
5
6use crate::model::IntOrStr;
7
8#[derive(Debug, Clone, serde::Deserialize, PartialEq, Eq)]
9pub struct BuildInfo {
10    /// QT version
11    qt: String,
12    /// libtorrent version
13    libtorrent: String,
14    /// Boost version
15    boost: String,
16    /// OpenSSL version
17    openssl: String,
18    /// Application bitness (e.g. 64-bit)
19    bitness: i8,
20}
21
22/// Process info returned by `app/processInfo`.
23/// Added in qBittorrent 5.2.0 (Web API v2.15.1).
24#[derive(Debug, Clone, serde::Deserialize, PartialEq, Eq)]
25pub struct ProcessInfo {
26    /// Process launch time as UTC epoch seconds.
27    pub launch_time: i64,
28}
29
30#[cfg_attr(feature = "builder", derive(typed_builder::TypedBuilder))]
31#[cfg_attr(
32    feature = "builder",
33    builder(field_defaults(default, setter(strip_option)))
34)]
35#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize, PartialEq)]
36#[skip_serializing_none]
37pub struct Preferences {
38    /// Currently selected language (e.g. en_GB for English)
39    pub locale: Option<String>,
40    /// True if a subfolder should be created when adding a torrent
41    pub create_subfolder_enabled: Option<bool>,
42    /// True if torrents should be added in a Paused state
43    pub start_paused_enabled: Option<bool>,
44    /// TODO
45    pub auto_delete_mode: Option<i64>,
46    /// True if disk space should be pre-allocated for all files
47    pub preallocate_all: Option<bool>,
48    /// True if ".!qB" should be appended to incomplete files
49    pub incomplete_files_ext: Option<bool>,
50    /// True if Automatic Torrent Management is enabled by default
51    pub auto_tmm_enabled: Option<bool>,
52    /// True if torrent should be relocated when its Category changes
53    pub torrent_changed_tmm_enabled: Option<bool>,
54    /// True if torrent should be relocated when the default save path changes
55    pub save_path_changed_tmm_enabled: Option<bool>,
56    /// True if torrent should be relocated when its Category's save path
57    /// changes
58    pub category_changed_tmm_enabled: Option<bool>,
59    /// Default save path for torrents, separated by slashes
60    pub save_path: Option<String>,
61    /// True if folder for incomplete torrents is enabled
62    pub temp_path_enabled: Option<bool>,
63    /// Path for incomplete torrents, separated by slashes
64    pub temp_path: Option<String>,
65    /// Property: directory to watch for torrent files, value: where torrents
66    /// loaded from this directory should be downloaded to (see list of possible
67    /// values below). Slashes are used as path separators; multiple key/value
68    /// pairs can be specified
69    pub scan_dirs: Option<HashMap<PathBuf, ScanDirValue>>,
70    /// Path to directory to copy .torrent files to. Slashes are used as path
71    /// separators
72    pub export_dir: Option<String>,
73    /// Path to directory to copy .torrent files of completed downloads to.
74    /// Slashes are used as path separators
75    pub export_dir_fin: Option<String>,
76    /// Log file directory path
77    pub file_log_path: Option<String>,
78    /// True if e-mail notification should be enabled
79    pub mail_notification_enabled: Option<bool>,
80    /// e-mail where notifications should originate from
81    pub mail_notification_sender: Option<String>,
82    /// e-mail to send notifications to
83    pub mail_notification_email: Option<String>,
84    /// smtp server for e-mail notifications
85    pub mail_notification_smtp: Option<String>,
86    /// True if smtp server requires SSL connection
87    pub mail_notification_ssl_enabled: Option<bool>,
88    /// True if smtp server requires authentication
89    pub mail_notification_auth_enabled: Option<bool>,
90    /// Username for smtp authentication
91    pub mail_notification_username: Option<String>,
92    /// Password for smtp authentication
93    pub mail_notification_password: Option<String>,
94    /// True if external program should be run after torrent has finished
95    /// downloading
96    pub autorun_enabled: Option<bool>,
97    /// Program path/name/arguments to run if `autorun_enabled` is enabled; path
98    /// is separated by slashes; you can use `%f` and `%n` arguments, which will
99    /// be expanded by qBittorent as path_to_torrent_file and torrent_name (from
100    /// the GUI; not the .torrent file name) respectively
101    pub autorun_program: Option<String>,
102    /// True if torrent queuing is enabled
103    pub queueing_enabled: Option<bool>,
104    /// Maximum number of active simultaneous downloads
105    pub max_active_downloads: Option<i64>,
106    /// Maximum number of active simultaneous downloads and uploads
107    pub max_active_torrents: Option<i64>,
108    /// Maximum number of active simultaneous uploads
109    pub max_active_uploads: Option<i64>,
110    /// If true torrents w/o any activity (stalled ones) will not be counted towards `max_active_*` limits; see [dont_count_slow_torrents](https://www.libtorrent.org/reference-Settings.html#dont_count_slow_torrents) for more information
111    pub dont_count_slow_torrents: Option<bool>,
112    /// Download rate in KiB/s for a torrent to be considered "slow"
113    pub slow_torrent_dl_rate_threshold: Option<i64>,
114    /// Upload rate in KiB/s for a torrent to be considered "slow"
115    pub slow_torrent_ul_rate_threshold: Option<i64>,
116    /// Seconds a torrent should be inactive before considered "slow"
117    pub slow_torrent_inactive_timer: Option<i64>,
118    /// True if share ratio limit is enabled
119    pub max_ratio_enabled: Option<bool>,
120    /// Get the global share ratio limit
121    pub max_ratio: Option<f64>,
122    /// Action performed when a torrent reaches the maximum share ratio. See
123    /// list of possible values here below.
124    pub max_ratio_act: Option<i64>,
125    /// Port for incoming connections
126    pub listen_port: Option<i64>,
127    /// True if UPnP/NAT-PMP is enabled
128    pub upnp: Option<bool>,
129    /// True if the port is randomly selected
130    pub random_port: Option<bool>,
131    /// Global download speed limit in KiB/s; `-1` means no limit is applied
132    pub dl_limit: Option<i64>,
133    /// Global upload speed limit in KiB/s; `-1` means no limit is applied
134    pub up_limit: Option<i64>,
135    /// Maximum global number of simultaneous connections
136    pub max_connec: Option<i64>,
137    /// Maximum number of simultaneous connections per torrent
138    pub max_connec_per_torrent: Option<i64>,
139    /// Maximum number of upload slots
140    pub max_uploads: Option<i64>,
141    /// Maximum number of upload slots per torrent
142    pub max_uploads_per_torrent: Option<i64>,
143    /// Timeout in seconds for a `stopped` announce request to trackers
144    pub stop_tracker_timeout: Option<i64>,
145    /// True if the advanced libtorrent option `piece_extent_affinity` is
146    /// enabled
147    pub enable_piece_extent_affinity: Option<bool>,
148    /// Bittorrent Protocol to use (see list of possible values below)
149    pub bittorrent_protocol: Option<i64>,
150    /// True if `[du]l_limit` should be applied to uTP connections; this option
151    /// is only available in qBittorent built against libtorrent version 0.16.X
152    /// and higher
153    pub limit_utp_rate: Option<bool>,
154    /// True if `[du]l_limit` should be applied to estimated TCP overhead
155    /// (service data: e.g. packet headers)
156    pub limit_tcp_overhead: Option<bool>,
157    /// True if `[du]l_limit` should be applied to peers on the LAN
158    pub limit_lan_peers: Option<bool>,
159    /// Alternative global download speed limit in KiB/s
160    pub alt_dl_limit: Option<i64>,
161    /// Alternative global upload speed limit in KiB/s
162    pub alt_up_limit: Option<i64>,
163    /// True if alternative limits should be applied according to schedule
164    pub scheduler_enabled: Option<bool>,
165    /// Scheduler starting hour
166    pub schedule_from_hour: Option<i64>,
167    /// Scheduler starting minute
168    pub schedule_from_min: Option<i64>,
169    /// Scheduler ending hour
170    pub schedule_to_hour: Option<i64>,
171    /// Scheduler ending minute
172    pub schedule_to_min: Option<i64>,
173    /// Scheduler days. See possible values here below
174    pub scheduler_days: Option<i64>,
175    /// True if DHT is enabled
176    pub dht: Option<bool>,
177    /// True if PeX is enabled
178    pub pex: Option<bool>,
179    /// True if LSD is enabled
180    pub lsd: Option<bool>,
181    /// See list of possible values here below
182    pub encryption: Option<i64>,
183    /// If true anonymous mode will be enabled; read more
184    /// [here](Anonymous-Mode); this option is only available in qBittorent
185    /// built against libtorrent version 0.16.X and higher
186    pub anonymous_mode: Option<bool>,
187    /// In old versions (before 4.6.1 or early), this returns an interger. In
188    /// newer versions, this returns a string.
189    pub proxy_type: Option<IntOrStr>,
190    /// Proxy IP address or domain name
191    pub proxy_ip: Option<String>,
192    /// Proxy port
193    pub proxy_port: Option<i64>,
194    /// True if peer and web seed connections should be proxified; this option
195    /// will have any effect only in qBittorent built against libtorrent version
196    /// 0.16.X and higher
197    pub proxy_peer_connections: Option<bool>,
198    /// True proxy requires authentication; doesn't apply to SOCKS4 proxies
199    pub proxy_auth_enabled: Option<bool>,
200    /// Username for proxy authentication
201    pub proxy_username: Option<String>,
202    /// Password for proxy authentication
203    pub proxy_password: Option<String>,
204    /// True if proxy is only used for torrents
205    pub proxy_torrents_only: Option<bool>,
206    /// True if external IP filter should be enabled
207    pub ip_filter_enabled: Option<bool>,
208    /// Path to IP filter file (.dat, .p2p, .p2b files are supported); path is
209    /// separated by slashes
210    pub ip_filter_path: Option<String>,
211    /// True if IP filters are applied to trackers
212    pub ip_filter_trackers: Option<bool>,
213    /// Comma-separated list of domains to accept when performing Host header
214    /// validation
215    pub web_ui_domain_list: Option<String>,
216    /// IP address to use for the WebUI
217    pub web_ui_address: Option<String>,
218    /// WebUI port
219    pub web_ui_port: Option<i64>,
220    /// True if UPnP is used for the WebUI port
221    pub web_ui_upnp: Option<bool>,
222    /// WebUI username
223    pub web_ui_username: Option<String>,
224    /// For API ≥ v2.3.0: Plaintext WebUI password, not readable, write-only.
225    /// For API < v2.3.0: MD5 hash of WebUI password, hash is generated from the
226    /// following string: `username:Web UI
227    /// Access:plain_text_web_ui_password`
228    pub web_ui_password: Option<String>,
229    /// True if WebUI CSRF protection is enabled
230    pub web_ui_csrf_protection_enabled: Option<bool>,
231    /// True if WebUI clickjacking protection is enabled
232    pub web_ui_clickjacking_protection_enabled: Option<bool>,
233    /// True if WebUI cookie `Secure` flag is enabled
234    pub web_ui_secure_cookie_enabled: Option<bool>,
235    /// Maximum number of authentication failures before WebUI access ban
236    pub web_ui_max_auth_fail_count: Option<i64>,
237    /// WebUI access ban duration in seconds
238    pub web_ui_ban_duration: Option<i64>,
239    /// Seconds until WebUI is automatically signed off
240    pub web_ui_session_timeout: Option<i64>,
241    /// True if WebUI host header validation is enabled
242    pub web_ui_host_header_validation_enabled: Option<bool>,
243    /// True if authentication challenge for loopback address (127.0.0.1) should
244    /// be disabled
245    pub bypass_local_auth: Option<bool>,
246    /// True if webui authentication should be bypassed for clients whose ip
247    /// resides within (at least) one of the subnets on the whitelist
248    pub bypass_auth_subnet_whitelist_enabled: Option<bool>,
249    /// (White)list of ipv4/ipv6 subnets for which webui authentication should
250    /// be bypassed; list entries are separated by commas
251    pub bypass_auth_subnet_whitelist: Option<String>,
252    /// True if an alternative WebUI should be used
253    pub alternative_webui_enabled: Option<bool>,
254    /// File path to the alternative WebUI
255    pub alternative_webui_path: Option<String>,
256    /// True if WebUI HTTPS access is enabled
257    pub use_https: Option<bool>,
258    /// For API < v2.0.1: SSL keyfile contents (this is a not a path)
259    pub ssl_key: Option<String>,
260    /// For API < v2.0.1: SSL certificate contents (this is a not a path)
261    pub ssl_cert: Option<String>,
262    /// For API ≥ v2.0.1: Path to SSL keyfile
263    pub web_ui_https_key_path: Option<String>,
264    /// For API ≥ v2.0.1: Path to SSL certificate
265    pub web_ui_https_cert_path: Option<String>,
266    /// True if server DNS should be updated dynamically
267    pub dyndns_enabled: Option<bool>,
268    /// See list of possible values here below
269    pub dyndns_service: Option<i64>,
270    /// Username for DDNS service
271    pub dyndns_username: Option<String>,
272    /// Password for DDNS service
273    pub dyndns_password: Option<String>,
274    /// Your DDNS domain name
275    pub dyndns_domain: Option<String>,
276    /// RSS refresh interval
277    pub rss_refresh_interval: Option<i64>,
278    /// Max stored articles per RSS feed
279    pub rss_max_articles_per_feed: Option<i64>,
280    /// Enable processing of RSS feeds
281    pub rss_processing_enabled: Option<bool>,
282    /// Enable auto-downloading of torrents from the RSS feeds
283    pub rss_auto_downloading_enabled: Option<bool>,
284    /// For API ≥ v2.5.1: Enable downloading of repack/proper Episodes
285    pub rss_download_repack_proper_episodes: Option<bool>,
286    /// For API ≥ v2.5.1: List of RSS Smart Episode Filters
287    pub rss_smart_episode_filters: Option<String>,
288    /// Enable automatic adding of trackers to new torrents
289    pub add_trackers_enabled: Option<bool>,
290    /// List of trackers to add to new torrent
291    pub add_trackers: Option<String>,
292    /// For API ≥ v2.5.1: Enable custom http headers
293    pub web_ui_use_custom_http_headers_enabled: Option<bool>,
294    /// For API ≥ v2.5.1: List of custom http headers
295    pub web_ui_custom_http_headers: Option<String>,
296    /// True enables max seeding time
297    pub max_seeding_time_enabled: Option<bool>,
298    /// Number of minutes to seed a torrent
299    pub max_seeding_time: Option<i64>,
300    /// TODO
301    pub announce_ip: Option<String>,
302    /// True always announce to all tiers
303    pub announce_to_all_tiers: Option<bool>,
304    /// True always announce to all trackers in a tier
305    pub announce_to_all_trackers: Option<bool>,
306    /// Number of asynchronous I/O threads
307    pub async_io_threads: Option<i64>,
308    /// List of banned IPs
309    #[serde(rename = "banned_IPs")]
310    pub banned_ips: Option<String>,
311    /// Outstanding memory when checking torrents in MiB
312    pub checking_memory_use: Option<i64>,
313    /// IP Address to bind to. Empty String means All addresses
314    pub current_interface_address: Option<String>,
315    /// Network Interface used
316    pub current_network_interface: Option<String>,
317    /// Disk cache used in MiB
318    pub disk_cache: Option<i64>,
319    /// Disk cache expiry interval in seconds
320    pub disk_cache_ttl: Option<i64>,
321    /// Port used for embedded tracker
322    pub embedded_tracker_port: Option<i64>,
323    /// True enables coalesce reads & writes
324    pub enable_coalesce_read_write: Option<bool>,
325    /// True enables embedded tracker
326    pub enable_embedded_tracker: Option<bool>,
327    /// True allows multiple connections from the same IP address
328    pub enable_multi_connections_from_same_ip: Option<bool>,
329    /// True enables os cache
330    pub enable_os_cache: Option<bool>,
331    /// True enables sending of upload piece suggestions
332    pub enable_upload_suggestions: Option<bool>,
333    /// File pool size
334    pub file_pool_size: Option<i64>,
335    /// Maximal outgoing port (0: Disabled)
336    pub outgoing_ports_max: Option<i64>,
337    /// Minimal outgoing port (0: Disabled)
338    pub outgoing_ports_min: Option<i64>,
339    /// True rechecks torrents on completion
340    pub recheck_completed_torrents: Option<bool>,
341    /// True resolves peer countries
342    pub resolve_peer_countries: Option<bool>,
343    /// Save resume data interval in min
344    pub save_resume_data_interval: Option<i64>,
345    /// Send buffer low watermark in KiB
346    pub send_buffer_low_watermark: Option<i64>,
347    /// Send buffer watermark in KiB
348    pub send_buffer_watermark: Option<i64>,
349    /// Send buffer watermark factor in percent
350    pub send_buffer_watermark_factor: Option<i64>,
351    /// Socket backlog size
352    pub socket_backlog_size: Option<i64>,
353    /// Upload choking algorithm used (see list of possible values below)
354    pub upload_choking_algorithm: Option<i64>,
355    /// Upload slots behavior used (see list of possible values below)
356    pub upload_slots_behavior: Option<i64>,
357    /// UPnP lease duration (0: Permanent lease)
358    pub upnp_lease_duration: Option<i64>,
359    /// μTP-TCP mixed mode algorithm (see list of possible values below)
360    pub utp_tcp_mixed_mode: Option<i64>,
361}
362
363#[derive(Debug, Clone, Eq, PartialEq)]
364pub enum ScanDirValue {
365    MonitoredFolder,
366    DefaultSavingPath,
367    Path(PathBuf),
368}
369
370impl Serialize for ScanDirValue {
371    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
372    where
373        S: Serializer,
374    {
375        match self {
376            ScanDirValue::MonitoredFolder => serializer.serialize_i64(0),
377            ScanDirValue::DefaultSavingPath => serializer.serialize_i64(1),
378            ScanDirValue::Path(path) => serializer.serialize_str(path.to_str().unwrap()),
379        }
380    }
381}
382
383impl<'de> Deserialize<'de> for ScanDirValue {
384    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
385    where
386        D: Deserializer<'de>,
387    {
388        deserializer.deserialize_any(ScanDirsVisitor)
389    }
390}
391
392struct ScanDirsVisitor;
393
394/// Possible values of `scan_dirs`:
395///
396/// Value                       | Description
397/// ----------------------------|------------
398/// `0`                         | Download to the monitored folder
399/// `1`                         | Download to the default save path
400/// `"/path/to/download/to"`    | Download to this path
401impl Visitor<'_> for ScanDirsVisitor {
402    type Value = ScanDirValue;
403
404    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
405        formatter.write_str("0, 1 or a path")
406    }
407
408    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
409    where
410        E: serde::de::Error,
411    {
412        match v {
413            0 => Ok(ScanDirValue::MonitoredFolder),
414            1 => Ok(ScanDirValue::DefaultSavingPath),
415            _ => Err(E::custom(format!("Invalid value for ScanDirs: {}", v))),
416        }
417    }
418
419    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
420    where
421        E: serde::de::Error,
422    {
423        Ok(ScanDirValue::Path(PathBuf::from(v)))
424    }
425}
426
427/// A single cookie entry returned by `app/cookies` (GET).
428/// All fields are guaranteed to be present in the response.
429/// Added in qBittorrent 5.2.0 (Web API v2.11.3).
430#[derive(Debug, Clone, serde::Deserialize, PartialEq, Eq)]
431pub struct CookieEntry {
432    /// Cookie name
433    pub name: String,
434    /// Cookie domain
435    pub domain: String,
436    /// Cookie path
437    pub path: String,
438    /// Cookie value
439    pub value: String,
440    /// Cookie expiration date (seconds since epoch)
441    pub expiration_date: i64,
442}
443
444/// Arguments for setting cookies via `app/setCookies` (POST).
445/// All fields are optional.
446/// Added in qBittorrent 5.2.0 (Web API v2.11.3).
447#[derive(Debug, Clone, serde::Serialize, PartialEq, Eq)]
448pub struct SetCookieArg {
449    /// Cookie name
450    pub name: Option<String>,
451    /// Cookie domain
452    pub domain: Option<String>,
453    /// Cookie path
454    pub path: Option<String>,
455    /// Cookie value
456    pub value: Option<String>,
457    /// Cookie expiration date (seconds since epoch)
458    pub expiration_date: Option<i64>,
459}