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.
This commit is contained in:
2026-10-10 09:17:00 +02:00
parent eea1260f13
commit ef5cf04c52
+57
View File
@@ -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)) 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 /// One channel's pipeline; returns the number of failures (python
/// process_channel). /// process_channel).
pub fn process_channel( pub fn process_channel(
@@ -372,6 +383,20 @@ pub fn process_channel(
let found: Vec<FoundUrl> = found let found: Vec<FoundUrl> = found
.into_iter() .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)) .filter(|f| opts.only.as_ref().is_none_or(|o| o.as_str() == f.host))
.collect(); .collect();
@@ -619,7 +644,13 @@ pub fn run_gofile(
))); )));
} }
let mut files: Vec<Value> = Vec::new(); let mut files: Vec<Value> = Vec::new();
let mut skipped_torrents = 0usize;
for (relpath, name, link) in files_spec { 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 let dest = out_dir
.join("downloads") .join("downloads")
.join("gofile") .join("gofile")
@@ -635,6 +666,15 @@ pub fn run_gofile(
} }
files.push(entry); 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) Ok(files)
})(); })();
match files { match files {
@@ -648,6 +688,14 @@ pub fn run_gofile(
&source, &source,
manifest, manifest,
)?; )?;
if files.is_empty() {
state.mark(&f.url, |r| {
r.extra.insert(
"note".into(),
Value::from("only .torrent files - skipped"),
);
})?;
}
if opts.extract { if opts.extract {
extract_zips(&files); extract_zips(&files);
} }
@@ -1127,6 +1175,15 @@ mod tests {
assert!(parse_since("nonsense").is_err()); 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] #[test]
fn parse_message_ts_handles_export_formats() { fn parse_message_ts_handles_export_formats() {
assert_eq!( assert_eq!(