diff --git a/Cargo.toml b/Cargo.toml index d699726..3e84f6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,8 @@ titanite = "0.3.2" tracing-subscriber = { version = "0.3.20", features = ["env-filter"] } librqbit-core = "5.0.0" plurify = "0.2.0" +url = "2.5.7" +urlencoding = "2.1.3" # development [patch.crates-io] diff --git a/README.md b/README.md index 22da2e4..e399a50 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,9 @@ openssl pkcs12 -export -out server.pfx -inkey server.pem -in server.crt ``` bash btracker-gemini -i /path/to/server.pfx\ - -s /path/to/btracker-fs + -s /path/to/btracker-fs\ + -t udp://tracker1:6969\ + -t udp://tracker2:6969 ``` * prepend `RUST_LOG=trace` or `RUST_LOG=btracker_gemini=trace` to debug * use `-b` to bind server on specified `host:port` diff --git a/src/config.rs b/src/config.rs index 0b15f55..27f7061 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,6 +3,7 @@ use std::{ net::{Ipv4Addr, SocketAddr, SocketAddrV4}, path::PathBuf, }; +use url::Url; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -13,7 +14,7 @@ pub struct Config { /// Tracker(s) to join / scrape requests #[arg(short, long)] - pub tracker: Option>, + pub tracker: Option>, /// Bind server `host:port` to listen incoming connections on it #[arg(short, long, default_value_t = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 1965)))] diff --git a/src/main.rs b/src/main.rs index 73545eb..469d8ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,7 @@ use std::{ thread, }; use titanite::*; +use url::Url; fn main() -> Result<()> { if std::env::var("RUST_LOG").is_ok() { @@ -225,7 +226,7 @@ fn index(config: &Config, public: &Public, page: Option) -> Result) -> Result {} {} • {} • {}\n", + "=> {} {} • {} • {}", i.info_hash.as_string(), torrent.time.format("%Y/%m/%d"), // @TODO optional size(&i), files(&i), )); + + b.push(format!( + "=> {} Magnet\n", + magnet(&i, config.tracker.as_ref()) + )) } b.push("## Navigation\n".into()); @@ -294,3 +300,18 @@ fn size(meta: &TorrentMetaV1Owned) -> String { + meta.info.length.unwrap_or_default(), ) } + +fn magnet(meta: &TorrentMetaV1Owned, trackers: Option<&Vec>) -> String { + let mut b = format!("magnet:?xt=urn:btih:{}", meta.info_hash.as_string()); + if let Some(ref n) = meta.info.name { + b.push_str("&dn="); + b.push_str(&urlencoding::encode(&n.to_string())) + } + if let Some(t) = trackers { + for tracker in t { + b.push_str("&tr="); + b.push_str(&urlencoding::encode(tracker.as_str())) + } + } + b +}