diff --git a/Cargo.lock b/Cargo.lock index 63b8803..2820634 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -472,6 +472,7 @@ dependencies = [ "env_logger", "lazy_static", "log", + "regex", "reqwest", "serde_json", "tokio", diff --git a/Cargo.toml b/Cargo.toml index afc945e..cd334ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ env_logger = "0.11.3" log = "0.4.21" async-trait = "0.1.79" clap = { version = "4.5.4", features = ["derive"] } +regex = "1.10.4" [profile.opt] inherits = "release" diff --git a/src/backend/qb.rs b/src/backend/qb.rs index dc2bd19..124fb6e 100644 --- a/src/backend/qb.rs +++ b/src/backend/qb.rs @@ -83,6 +83,7 @@ impl Backend for QBitBackend { name: t.get("name").unwrap().as_str().unwrap().to_string(), hash: t.get("hash").unwrap().as_str().unwrap().to_string(), size: t.get("size").unwrap().as_u64().unwrap(), + tracker: t.get("tracker").unwrap().as_str().unwrap().to_string(), }).collect()) } diff --git a/src/daemon.rs b/src/daemon.rs index 2703155..a812156 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -1,3 +1,4 @@ +use regex::Regex; use std::time::Instant; use anyhow::Result; @@ -8,6 +9,8 @@ use crate::peer::BannedPeer; use crate::rules::preload::PREDEFINED_RULES; use crate::rules::Rule; +const PT_KEYWORDS: [&str; 5] = ["?passkey=", "?authkey=", "?secure=", "?credential=", "private"]; + struct Statistic { pub torrents: u64, pub peers: u64, @@ -19,17 +22,19 @@ pub struct Daemon { banned: Vec, rules: Vec, scan_time: u64, + pt: bool, clear: bool, } impl Daemon { - pub fn new(backend: Box, scan: u64, clear: bool) -> Self { + pub fn new(backend: Box, scan: u64, pt: bool, clear: bool) -> Self { let rules = PREDEFINED_RULES.clone(); Daemon { backend, banned: Vec::new(), rules, scan_time: scan, + pt, clear, } } @@ -46,13 +51,25 @@ impl Daemon { self.backend.ban_clear().await?; info!("[startup] jail cleared."); } + let re = Regex::new(r"([a-zA-Z0-9]{32})").unwrap(); loop { let mut flag = false; let torrents = self.backend.get_uploading_torrents().await?; stat.torrents = torrents.len() as u64; stat.peers = 0; for torrent in torrents { - debug!("Torrent: {}({})", torrent.name, torrent.hash); + if !self.pt && !torrent.tracker.is_empty() { + let lower_tracker = torrent.tracker.to_lowercase(); + if PT_KEYWORDS.iter().any(|&keyword| lower_tracker.contains(keyword)) || re.is_match(&lower_tracker) { + debug!("Private tracker torrent: {}({})", torrent.name, torrent.hash); + continue; + } else { + debug!("Torrent: {}({})", torrent.name, torrent.hash); + } + } else { + debug!("Torrent: {}({})", torrent.name, torrent.hash); + } + let peers = self.backend.get_peers(&torrent.hash).await?; stat.peers += peers.len() as u64; for peer in peers { diff --git a/src/main.rs b/src/main.rs index a9b1821..8a84199 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,8 @@ struct Args { auth: String, #[arg(short, long, default_value = "5", help = "Scan interval in seconds.")] scan: u64, + #[arg(short, long, default_value = "false", help = "Handle private tracker torrents.")] + pt: bool, #[arg(short, long, default_value = "false", help = "Clear all bans before start.")] clear: bool, } @@ -39,7 +41,7 @@ async fn main() -> Result<(), Box> { info!("PeerBan/{} started.", env!("CARGO_PKG_VERSION")); let qb = QBitBackend::new(args.endpoint, args.auth); - let mut daemon = Daemon::new(Box::new(qb), args.scan, args.clear); + let mut daemon = Daemon::new(Box::new(qb), args.scan, args.pt, args.clear); loop { match daemon.run().await { Ok(_) => (), diff --git a/src/torrent.rs b/src/torrent.rs index 808eeb8..1fde54d 100644 --- a/src/torrent.rs +++ b/src/torrent.rs @@ -3,4 +3,5 @@ pub struct Torrent { pub name: String, pub hash: String, pub size: u64, + pub tracker: String, } \ No newline at end of file