0.9: almost working

This commit is contained in:
2025-07-06 19:15:04 +03:00
parent f101dd7539
commit ff8a63da2d
+72 -3
View File
@@ -3,6 +3,7 @@ use clap::Parser;
use std::error::Error; use std::error::Error;
use std::fs::File; use std::fs::File;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command;
use walkdir::WalkDir; use walkdir::WalkDir;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@@ -24,6 +25,10 @@ struct Args {
/// Rename flag (whether to rename root directory of torrent, if exists) /// Rename flag (whether to rename root directory of torrent, if exists)
#[arg(short = 'r', long = "rename", default_value_t = false)] #[arg(short = 'r', long = "rename", default_value_t = false)]
rename: bool, rename: bool,
/// Do no harm, only print actions
#[arg(short = 'n', long = "dry-run", default_value_t = false)]
dry_run: bool,
} }
fn find_torrent_files(start_path: &Path) -> Vec<PathBuf> { fn find_torrent_files(start_path: &Path) -> Vec<PathBuf> {
@@ -50,19 +55,71 @@ enum TorrentType {
fn get_torrent_type(torrent: &Path) -> Result<TorrentType, Box<dyn Error>> { fn get_torrent_type(torrent: &Path) -> Result<TorrentType, Box<dyn Error>> {
let f = File::open(torrent)?; let f = File::open(torrent)?;
let value: Value = bt_bencode::from_reader(f)?; let value: Value = bt_bencode::from_reader(f)?;
let torrenttype = match value.get("info").unwrap().get("files") { let torrenttype = match value
.get("info")
.ok_or("torrent sould have 'info' section")?
.get("files")
{
Some(_) => TorrentType::Directory( Some(_) => TorrentType::Directory(
value value
.get("info") .get("info")
.and_then(|v| v.get("name")) .and_then(|v| v.get("name"))
.and_then(|v| v.as_str()) .and_then(|v| v.as_str())
.unwrap() .ok_or("torrent with multiple files should have recommended directory name")?
.to_owned(), .to_owned(),
), ),
_ => TorrentType::SingleFile, _ => TorrentType::SingleFile,
}; };
Ok(torrenttype) Ok(torrenttype)
} }
fn make_destination(torrent: &Path, source: &Path, dest: &Path) -> PathBuf {
let filename = Path::new(
torrent
.file_stem()
.expect("torrent file should have '.torrent' extension"),
);
let rel_path = torrent
.parent()
.expect("torrent file should have a parent directory")
.strip_prefix(source)
.expect("torrent file should have prefix equal to source");
[dest, rel_path, filename].iter().collect()
}
fn exec_transmission_remote(
source: &Path,
dest: &Path,
torrent_type: &TorrentType,
rename: bool,
dry_run: bool,
) -> Result<(), Box<dyn Error>> {
let mut command = Command::new("transmission-remote");
command
.arg("--json")
.arg("--add")
.arg(source)
.arg("--download-dir")
.arg(dest);
if rename {
if let TorrentType::Directory(old_name) = torrent_type {
command
.arg("--rename")
.arg(dest)
.arg("--path")
.arg(old_name);
}
}
println!(
"Running {:?} with {:?}",
command.get_program(),
command.get_args()
);
if !dry_run {
let output = command.output()?;
println!("Result: {:?}", output);
}
Ok(())
}
fn main() { fn main() {
let args = Args::parse(); let args = Args::parse();
@@ -72,8 +129,20 @@ fn main() {
println!("Destination path: {}", args.destination); println!("Destination path: {}", args.destination);
println!("Rename: {}", args.rename); println!("Rename: {}", args.rename);
let source = Path::new(&args.source); let source = Path::new(&args.source);
let dest = Path::new(&args.destination);
let torrent_files = find_torrent_files(source); let torrent_files = find_torrent_files(source);
for file in torrent_files { for file in torrent_files {
println!("{:?}", get_torrent_type(&file)); // println!("{:?}", get_torrent_type(&file));
// println!("{:?}", make_destination(&file, source, dest));
let torrent_type = get_torrent_type(&file).unwrap();
let destination = make_destination(&file, source, dest);
exec_transmission_remote(
&file,
&destination,
&torrent_type,
args.rename,
args.dry_run,
)
.unwrap();
} }
} }