kget/torrent/
mod.rs

1use std::error::Error;
2use std::sync::Arc;
3
4use crate::config::ProxyConfig;
5use crate::optimization::Optimizer;
6
7mod external;
8mod settings;
9
10#[cfg(feature = "torrent-transmission")]
11mod transmission;
12
13pub type StatusCb = Arc<dyn Fn(String) + Send + Sync>;
14pub type ProgressCb = Arc<dyn Fn(f32) + Send + Sync>;
15
16#[derive(Default, Clone)]
17pub struct TorrentCallbacks {
18    pub status: Option<StatusCb>,
19    pub progress: Option<ProgressCb>,
20}
21
22fn emit_status(cb: &TorrentCallbacks, msg: impl Into<String>) {
23    if let Some(f) = &cb.status {
24        f(msg.into());
25    }
26}
27
28fn emit_progress(cb: &TorrentCallbacks, p: f32) {
29    if let Some(f) = &cb.progress {
30        f(p.clamp(0.0, 1.0));
31    }
32}
33
34/// Backend selection:
35/// - default: "external" (abre no cliente instalado)
36/// - "transmission": usa Transmission RPC (requer feature torrent-transmission)
37fn selected_backend() -> String {
38    std::env::var("KGET_TORRENT_BACKEND")
39        .unwrap_or_else(|_| "external".to_string())
40        .to_lowercase()
41}
42
43pub fn download_magnet(
44    magnet: &str,
45    output_dir: &str,
46    quiet: bool,
47    proxy: ProxyConfig,
48    optimizer: Optimizer,
49    cb: TorrentCallbacks,
50) -> Result<(), Box<dyn Error + Send + Sync>> {
51    emit_progress(&cb, 0.0);
52
53    match selected_backend().as_str() {
54        "transmission" => {
55            #[cfg(feature = "torrent-transmission")]
56            {
57                return transmission::download_via_transmission(
58                    magnet,
59                    output_dir,
60                    quiet,
61                    proxy,
62                    optimizer,
63                    cb,
64                );
65            }
66
67            #[cfg(not(feature = "torrent-transmission"))]
68            {
69                emit_status(
70                    &cb,
71                    "Torrent backend 'transmission' not available (compile with --features torrent-transmission). Falling back to external client.",
72                );
73            }
74        }
75        _ => {}
76    }
77
78    emit_status(
79        &cb,
80        format!(
81            "Opening magnet link in your default torrent client (output folder may be managed by that client): {}",
82            magnet
83        ),
84    );
85
86    external::open_magnet_in_default_client(magnet)?;
87    emit_progress(&cb, 1.0);
88    Ok(())
89}