use crate::utils; use clap::ArgMatches; use std::fs::{create_dir, rename}; use std::io; use std::path::PathBuf; use std::process::{exit, Command}; const MAX_DOWNLOAD_ATTEMPTS: i32 = 5; pub async fn download(arg_m: &ArgMatches) { let print_only = arg_m.is_present("print"); let id = arg_m.value_of("id").unwrap(); let client = utils::create_client(); let mut return_fail = false; let hentai_info = utils::get_hentai(client.clone(), id).await; match hentai_info { Ok(hentai_info) => { match hentai_info { Some(hentai_info) => { let tcloned_client = client.clone(); let iter = (1..=hentai_info.episode_urls.len()).zip(hentai_info.episode_urls); for (episode_number, episode_url) in iter { let mut filename = PathBuf::from(&hentai_info.slug); filename.push(&format!("{}.mkv", episode_number)); if filename.exists() { continue; } let download_url = match utils::get_url(tcloned_client.clone(), &episode_url).await { Ok(Some(i)) => i, Ok(None) => { eprintln!( "Failed to get {}: get_url returned None", filename.display() ); continue; } Err(err) => { eprintln!("Failed to get {}: {}", filename.display(), err); continue; } }; if print_only { println!("{}", download_url); continue; } match create_dir(&hentai_info.slug) { Ok(_) => (), Err(err) => { if err.kind() != io::ErrorKind::AlreadyExists { eprintln!("Failed to create parent directory due to {}", err); exit(1); } } }; let mut tmp_filename = filename.clone(); tmp_filename.set_extension("tmp"); let mut fail_dl = true; for i in 0..MAX_DOWNLOAD_ATTEMPTS { eprintln!("Downloading {} (attempt {})", filename.display(), i); let mut command = Command::new("ffmpeg"); let command = command.args(&["-v", "warning", "-stats", "-nostdin", "-y", "-i"]); let mut command = command.arg(&download_url.video); if let Some(ref captions) = download_url.captions { command = command.args(&["-i", &captions]); } match command .args(&["-c", "copy", "-f", "matroska"]) .arg(&tmp_filename) .spawn() { Ok(mut child) => { match child.wait() { Ok(exit_status) => { if exit_status.success() { fail_dl = false; match rename(&tmp_filename, &filename) { Ok(_) => (), Err(err) => eprintln!( "Failed to rename {} to {} due to {}", tmp_filename.display(), filename.display(), err ), }; break; } eprintln!( "ffmpeg exited with {:?}", exit_status.code() ); } Err(err) => eprintln!( "Failed to wait on ffmpeg process due to {}", err ), }; } Err(err) => { eprintln!("Failed to spawn ffmpeg process due to {}", err) } }; } if fail_dl { eprintln!("Failed to download {}", filename.display()); return_fail = true; } } } None => { eprintln!("Failed to get {}: does not exist", id); return_fail = true; } }; } Err(err) => { eprintln!("Failed to get {}: {}", id, err); return_fail = true; } }; if return_fail { exit(1); } }