use std::cmp::min; use std::fs::File; use std::io::Write; use std::path::PathBuf; use futures_util::StreamExt; use indicatif::ProgressBar; use reqwest::Client; use crate::misc; pub async fn download_file_progress( client: &Client, pb: &ProgressBar, url: &str, path: &PathBuf, size: u64, ) -> Result<(), String> { let res = client .get(url) .header( "User-Agent", &format!( "AlterWare Launcher | github.com/{}/{}", crate::global::GH_OWNER, crate::global::GH_REPO ), ) .send() .await .or(Err(format!("Failed to GET from '{url}'")))?; // Fix for CF shenanigans let total_size = res.content_length().unwrap_or(size); pb.set_length(total_size); let msg = format!( "{}{} ({})", misc::prefix("downloading"), misc::cute_path(path), misc::human_readable_bytes(total_size) ); pb.println(&msg); info!("{msg}"); pb.set_message(path.file_name().unwrap().to_str().unwrap().to_string()); let mut file = File::create(path).or(Err(format!("Failed to create file '{}'", path.display())))?; let mut downloaded: u64 = 0; let mut stream = res.bytes_stream(); while let Some(item) = stream.next().await { let chunk = match item { Ok(v) => v, Err(e) => return Err(format!("Error while downloading file: {e}")), }; if let Err(e) = file.write_all(&chunk) { Err(format!("Error while writing to file: {e}"))? } let new = min(downloaded + (chunk.len() as u64), total_size); downloaded = new; pb.set_position(new); } pb.set_message(String::default()); Ok(()) } pub async fn download_file(url: &str, path: &PathBuf) -> Result<(), String> { let client = Client::new(); match client .get(url) .header( "User-Agent", &format!( "AlterWare Launcher | github.com/{}/{}", crate::global::GH_OWNER, crate::global::GH_REPO ), ) .send() .await { Ok(res) => { let body = res.bytes().await.or(Err("Failed to download file"))?; let mut file = File::create(path).or(Err("Failed to create file"))?; file.write_all(&body).or(Err("Failed to write to file"))?; Ok(()) } Err(e) => { misc::fatal_error(&e.to_string()); Err("Could not download file".to_string()) } } } pub async fn get_body(url: &str) -> Result, String> { let client = Client::new(); match client .get(url) .header( "User-Agent", &format!( "AlterWare Launcher | github.com/{}/{}", crate::global::GH_OWNER, crate::global::GH_REPO ), ) .send() .await { Ok(res) => { debug!("{} {url}", res.status().to_string()); let body = res.bytes().await.or(Err("Failed to get body"))?; Ok(body.to_vec()) } Err(e) => { misc::fatal_error(&e.to_string()); Err("Could not get body".to_string()) } } } pub async fn get_body_string(url: &str) -> Result { let body = get_body(url).await?; Ok(String::from_utf8(body).unwrap()) }