nhentairs/src/commands/download.rs

103 lines
4.0 KiB
Rust
Raw Normal View History

2020-09-12 12:26:07 +00:00
use crate::utils;
use crate::structs;
2020-09-12 12:26:07 +00:00
use std::env;
use std::sync::Arc;
2020-09-12 12:26:07 +00:00
use std::path::Path;
use std::process::exit;
use tokio::sync::Mutex;
2020-09-12 12:26:07 +00:00
use tokio::task::JoinHandle;
2020-12-01 17:33:26 +00:00
use std::fs::{rename, create_dir, write};
2020-09-12 12:26:07 +00:00
extern crate tokio;
extern crate reqwest;
const DOWNLOAD_WORKERS: usize = 5;
pub async fn run(args: env::Args) {
let sauces = utils::get_arg_sauces(args).unwrap();
if sauces.len() < 1 {
eprintln!("Missing sauce(s)");
exit(1);
}
let client = reqwest::Client::new();
let mut pages_vec: Vec<(String, String)> = Vec::new();
{
let mut handles: Vec<JoinHandle<structs::GalleryInfoSuccess>> = Vec::with_capacity(sauces.len());
let mut sauce_info_vec: Vec<structs::GalleryInfoSuccess> = Vec::with_capacity(sauces.len());
for sauce in sauces {
let cloned_client = client.clone();
handles.push(tokio::spawn(async move {
match utils::get_sauce_info(cloned_client, sauce).await.unwrap() {
structs::GalleryInfo::Info(sauce_info) => sauce_info,
structs::GalleryInfo::Error(sauce_error) => panic!("{} returned: {}", sauce, sauce_error.error)
}
}));
}
for handle in handles {
sauce_info_vec.push(handle.await.unwrap());
}
for sauce_info in sauce_info_vec {
2020-09-12 12:26:07 +00:00
let base_path = sauce_info.id.to_string();
let base_path = Path::new(&base_path);
match create_dir(base_path) {
2020-12-20 10:14:55 +00:00
Ok(()) => write(base_path.join("info.txt"), format!("{}\n", &sauce_info)).unwrap(),
2020-09-12 12:26:07 +00:00
Err(err) => match err.kind() {
std::io::ErrorKind::AlreadyExists => (),
_ => panic!("Got a weird error while creating dir: {}", err)
}
};
2020-12-02 15:34:42 +00:00
let mut page_num: i32 = 1;
2020-09-12 12:26:07 +00:00
for page in sauce_info.images.pages {
let file_ext = match page.t.as_str() {
"j" => ".jpg",
"p" => ".png",
"g" => ".gif",
_ => panic!("Unknown extension type: {}", page.t)
};
let mut file_name = page_num.to_string();
file_name.push_str(file_ext);
let file_path = base_path.join(&file_name);
if !file_path.exists() {
pages_vec.push((
2020-09-12 12:26:07 +00:00
String::from(file_path.to_str().unwrap()),
format!("https://i.nhentai.net/galleries/{}/{}",
sauce_info.media_id,
file_name)
));
2020-09-12 12:26:07 +00:00
}
page_num += 1;
}
}
2020-09-12 12:26:07 +00:00
}
2020-09-12 13:54:26 +00:00
let mut handles = Vec::with_capacity(DOWNLOAD_WORKERS);
let mutex = Arc::new(Mutex::new(pages_vec));
2020-09-12 12:26:07 +00:00
for worker_id in 0..DOWNLOAD_WORKERS {
let tcloned_client = client.clone();
let tcloned_mutex = Arc::clone(&mutex);
2020-09-12 12:26:07 +00:00
handles.push(tokio::spawn(async move {
eprintln!("[DW{}] Up!", worker_id);
2020-09-12 12:26:07 +00:00
loop {
let cloned_client = tcloned_client.clone();
let cloned_mutex = Arc::clone(&tcloned_mutex);
let mut pages_vec = cloned_mutex.lock().await;
if pages_vec.len() < 1 {
eprintln!("[DW{}] Down!", worker_id);
2020-09-12 12:26:07 +00:00
break;
}
let (file_path, url) = pages_vec.remove(0);
drop(pages_vec);
eprintln!("[DW{}] Downloading {} to {}", worker_id, url, file_path);
let mut tmp_file_path = file_path.clone();
2020-09-12 12:26:07 +00:00
tmp_file_path.push_str(".tmp");
utils::download_file(cloned_client, &url, &tmp_file_path).await.unwrap();
rename(&tmp_file_path, &file_path).unwrap();
eprintln!("[DW{}] {} downloaded", worker_id, file_path);
2020-09-12 12:26:07 +00:00
}
}));
}
for handle in handles {
handle.await.unwrap();
}
}