kget/
lib.rs

1//! KGet - A powerful download library for Rust
2//!
3//! `kget` provides robust downloading capabilities including HTTP/HTTPS,
4//! FTP, SFTP, and torrent downloads with progress tracking, proxy support,
5//! and various optimizations.
6
7mod config;
8mod download;
9mod advanced_download;
10mod progress;
11mod utils;
12mod optimization;
13mod ftp;
14mod sftp;
15mod torrent;
16mod gui_types;
17
18// Re-export public API
19pub use crate::config::{Config, ProxyConfig, ProxyType, OptimizationConfig, TorrentConfig, FtpConfig, SftpConfig};
20pub use crate::optimization::Optimizer;
21pub use crate::progress::create_progress_bar;
22
23/// Main download client for the KGet library
24pub struct KGet {
25    config: Config,
26}
27
28impl KGet {
29    /// Create a new KGet client with default configuration
30    pub fn new() -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
31        let config = Config::load()?;
32        Ok(Self { config })
33    }
34
35    /// Create a new KGet client with custom configuration
36    pub fn with_config(config: Config) -> Self {
37        Self { config }
38    }
39
40    /// Download a file from a URL to a local path
41    pub fn download(
42        &self,
43        url: &str,
44        output_path: Option<String>,
45        quiet_mode: bool,
46    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
47        // Create optimizer from config
48        let optimizer = Optimizer::new(self.config.optimization.clone());
49
50        if url.starts_with("ftp://") {
51            use crate::ftp::FtpDownloader;
52            let downloader = FtpDownloader::new(
53                url.to_string(), 
54                output_path.unwrap_or_else(|| crate::utils::get_filename_from_url_or_default(url, "ftp_output")), 
55                quiet_mode, 
56                self.config.proxy.clone(),
57                optimizer,
58            );
59            return downloader.download();
60        } else if url.starts_with("sftp://") {
61            use crate::sftp::SftpDownloader;
62            let downloader = SftpDownloader::new(
63                url.to_string(),
64                output_path.unwrap_or_else(|| crate::utils::get_filename_from_url_or_default(url, "sftp_output")),
65                quiet_mode,
66                self.config.proxy.clone(),
67                optimizer,
68            );
69            return downloader.download();
70        } else if url.starts_with("magnet:?") {
71            use crate::torrent::TorrentDownloader;
72            let downloader = TorrentDownloader::new(
73                url.to_string(),
74                output_path.unwrap_or_else(|| "torrent_output".to_string()),
75                quiet_mode,
76                self.config.proxy.clone(),
77                optimizer,
78            );
79            
80            // Create tokio runtime for async torrent downloads
81            let runtime = tokio::runtime::Runtime::new()?;
82            return runtime.block_on(downloader.download());
83        } else {
84            // Regular HTTP/HTTPS download
85            return download::download(url, quiet_mode, output_path, self.config.proxy.clone(), optimizer);
86        }
87    }
88
89    /// Advanced download with parallel chunks and resumable capability
90    pub fn advanced_download(
91        &self,
92        url: &str,
93        output_path: Option<String>,
94        quiet_mode: bool,
95    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
96        let optimizer = Optimizer::new(self.config.optimization.clone());
97        
98        // Use the existing advanced_download implementation
99        let downloader = crate::advanced_download::AdvancedDownloader::new(
100            url.to_string(),
101            output_path.unwrap_or_else(|| crate::utils::get_filename_from_url_or_default(url, "advanced_output")),
102            quiet_mode,
103            self.config.proxy.clone(),
104            optimizer,
105        );
106        
107        downloader.download()
108    }
109
110    /// Get current configuration
111    pub fn get_config(&self) -> &Config {
112        &self.config
113    }
114    
115    /// Update configuration
116    pub fn set_config(&mut self, config: Config) {
117        self.config = config;
118    }
119}
120
121/// Custom progress callback type for integration with other libraries
122pub type ProgressCallback = Box<dyn Fn(u64, u64, f64) -> () + Send + Sync>;
123
124/// Download options for fine-tuning the download process
125pub struct DownloadOptions {
126    pub quiet_mode: bool,
127    pub retry_count: Option<u32>,
128    pub retry_delay: Option<std::time::Duration>,
129    pub progress_callback: Option<ProgressCallback>,
130}
131
132impl Default for DownloadOptions {
133    fn default() -> Self {
134        Self {
135            quiet_mode: false,
136            retry_count: Some(3),
137            retry_delay: Some(std::time::Duration::from_secs(2)),
138            progress_callback: None,
139        }
140    }
141}
142
143/// Simplified API for quick downloads without creating a KelpsGet instance
144pub mod simple {
145    use super::*;
146
147    /// Download a file with minimal configuration
148    pub fn download(
149        url: &str, 
150        output_path: Option<&str>
151    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
152        let client = KGet::new()?;
153        client.download(
154            url,
155            output_path.map(|s| s.to_string()),
156            false
157        )
158    }
159
160    /// Download a file with custom options
161    pub fn download_with_options(
162        url: &str, 
163        output_path: Option<&str>,
164        options: DownloadOptions
165    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
166        let client = KGet::new()?;
167
168       
169        
170        client.download(
171            url,
172            output_path.map(|s| s.to_string()),
173            options.quiet_mode
174        )
175    }
176}
177
178/// Convenience top-level API so other crates can call downloads without
179/// instantiating `KGet` themselves.
180pub fn download(
181    url: &str,
182    output_path: Option<&str>,
183    quiet_mode: bool,
184) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
185    let client = KGet::new()?;
186    client.download(url, output_path.map(|s| s.to_string()), quiet_mode)
187}
188
189/// Convenience top-level API for advanced (parallel/resumable) downloads.
190pub fn advanced_download(
191    url: &str,
192    output_path: Option<&str>,
193    quiet_mode: bool,
194) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
195    let client = KGet::new()?;
196    client.advanced_download(url, output_path.map(|s| s.to_string()), quiet_mode)
197}
198
199/// Expose progress bar factory for consumers who want to render their own bars.
200/// This simply forwards to `create_progress_bar` defined in `progress.rs`.
201pub fn create_progress_bar_factory(
202    quiet_mode: bool,
203    msg: String,
204    length: Option<u64>,
205    is_parallel: bool,
206) -> indicatif::ProgressBar {
207    create_progress_bar(quiet_mode, msg, length, is_parallel)
208}