From ef5cf04c5289de537aa716ac3d76a3e8e8c5612a Mon Sep 17 00:00:00 2001 From: Ben_Kosytorz Date: Sat, 10 Oct 2026 09:17:00 +0200 Subject: [PATCH] feat(rust): never download .torrent links or torrent files in gofile content User policy: the channel hosts user-created torrents (one ~2.5 TB); this tool is for direct-download packs. Torrent links are recorded as done with a note so they never re-download. --- version-rust/src/orchestrate.rs | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/version-rust/src/orchestrate.rs b/version-rust/src/orchestrate.rs index d6a4432..9cb5feb 100644 --- a/version-rust/src/orchestrate.rs +++ b/version-rust/src/orchestrate.rs @@ -347,6 +347,17 @@ fn is_done(state: &State, gstore: Option<&GlobalStore>, url: &str) -> bool { state.is_done(url) || gstore.is_some_and(|g| g.is_done(url)) } +/// Torrent links are never downloaded (user policy): the channel hosts huge +/// user-created torrents; this tool is for direct-download packs. A skipped +/// torrent is recorded as done (with a note) so it never comes back. +fn is_torrent_url(url: &str) -> bool { + url.to_ascii_lowercase().ends_with(".torrent") +} + +fn is_torrent_file(name: &str) -> bool { + name.to_ascii_lowercase().ends_with(".torrent") +} + /// One channel's pipeline; returns the number of failures (python /// process_channel). pub fn process_channel( @@ -372,6 +383,20 @@ pub fn process_channel( let found: Vec = found .into_iter() + .filter(|f| { + if is_torrent_url(&f.url) { + log::info!("Skip torrent (never downloaded): {}", f.url); + if let Err(e) = state.mark(&f.url, |r| { + r.status = "ok".into(); + r.extra + .insert("note".into(), Value::from("torrent link skipped (policy)")); + }) { + log::error!("Could not record torrent skip for {}: {e}", f.url); + } + return false; + } + true + }) .filter(|f| opts.only.as_ref().is_none_or(|o| o.as_str() == f.host)) .collect(); @@ -619,7 +644,13 @@ pub fn run_gofile( ))); } let mut files: Vec = Vec::new(); + let mut skipped_torrents = 0usize; for (relpath, name, link) in files_spec { + if is_torrent_file(&name) { + skipped_torrents += 1; + log::info!("Skip torrent file in content (policy): {name}"); + continue; + } let dest = out_dir .join("downloads") .join("gofile") @@ -635,6 +666,15 @@ pub fn run_gofile( } files.push(entry); } + if files.is_empty() && skipped_torrents > 0 { + // content holds only torrents: nothing to fetch, ever + log::info!( + "OK {} (0 files, {} torrent(s) skipped by policy)", + f.url, + skipped_torrents + ); + return Ok(Vec::new()); + } Ok(files) })(); match files { @@ -648,6 +688,14 @@ pub fn run_gofile( &source, manifest, )?; + if files.is_empty() { + state.mark(&f.url, |r| { + r.extra.insert( + "note".into(), + Value::from("only .torrent files - skipped"), + ); + })?; + } if opts.extract { extract_zips(&files); } @@ -1127,6 +1175,15 @@ mod tests { assert!(parse_since("nonsense").is_err()); } + #[test] + fn torrent_detection() { + assert!(is_torrent_url("https://0807.st/rh0BzdD.torrent")); + assert!(is_torrent_url("https://0807.st/x.TORRENT")); + assert!(!is_torrent_url("https://0807.st/rh0BzdD.zip")); + assert!(is_torrent_file("Lord of Skulls.torrent")); + assert!(!is_torrent_file("Lord of Skulls.rar")); + } + #[test] fn parse_message_ts_handles_export_formats() { assert_eq!(