diff --git a/src/github.rs b/src/github.rs index 4573b63..bf33de5 100644 --- a/src/github.rs +++ b/src/github.rs @@ -1,19 +1,21 @@ use semver::Version; -pub fn latest_tag(owner: &str, repo: &str) -> String { - let github_body = crate::http::get_body_string( +pub async fn latest_tag(owner: &str, repo: &str) -> String { + let github_body = crate::http_async::get_body_string( format!( "https://api.github.com/repos/{}/{}/releases/latest", owner, repo ) .as_str(), - ); + ) + .await + .unwrap(); let github_json: serde_json::Value = serde_json::from_str(&github_body).unwrap(); github_json["tag_name"].to_string().replace('"', "") } -pub fn latest_version(owner: &str, repo: &str) -> Version { - let tag = latest_tag(owner, repo).replace('v', ""); +pub async fn latest_version(owner: &str, repo: &str) -> Version { + let tag = latest_tag(owner, repo).await.replace('v', ""); Version::parse(&tag).unwrap() } diff --git a/src/http.rs b/src/http.rs deleted file mode 100644 index ea122fb..0000000 --- a/src/http.rs +++ /dev/null @@ -1,84 +0,0 @@ -use crate::global; -use crate::misc; -use std::{fs, io::Write, path::Path, str}; - -pub fn get_body(url: &str) -> Vec { - let mut res: Vec = Vec::new(); - - match http_req::request::Request::new(&url.try_into().unwrap()) - .header( - "User-Agent", - &format!( - "AlterWare Launcher | github.com/{}/{}", - global::GH_OWNER, - global::GH_REPO - ), - ) - .send(&mut res) - { - Ok(req) => { - if req.status_code() == http_req::response::StatusCode::new(302) - || req.status_code() == http_req::response::StatusCode::new(301) - { - let location = req.headers().get("Location").unwrap().as_str(); - return get_body(location); - } - - if req.status_code() != http_req::response::StatusCode::new(200) { - misc::fatal_error(&format!( - "Could not get body from {}, got {}", - url, - req.status_code() - )); - } - } - Err(e) => { - misc::fatal_error(&format!("Could not get body from {}, got:\n{}", url, e)); - } - } - - res -} - -pub fn get_body_string(url: &str) -> String { - String::from_utf8(get_body(url)).unwrap() -} - -pub fn download_file(url: &str, file_path: &Path) { - let body = get_body(url); - - match fs::File::create(file_path) { - Ok(mut file) => match file.write_all(&body) { - Ok(_) => (), - Err(e) => { - misc::fatal_error(&format!( - "Could not write to file {}, got:\n{}", - file_path.to_str().unwrap(), - e - )); - } - }, - Err(e) => { - match e.kind() { - std::io::ErrorKind::NotFound => { - fs::create_dir_all(file_path.parent().unwrap()).unwrap(); - return download_file(url, file_path); - } - std::io::ErrorKind::PermissionDenied => { - misc::fatal_error(&format!( - "Permission to {} denied.\n Please try:\n 1. Running the launcher as administrator.\n 2. Manually deleting the last downloaded file.\n 3. If your game is in the program files directory try moving it to another location.\n 4. Create an exception/exclusion in your Anti-Virus Software for either the last downloaded file or the entire game directory.\n\n\n{}", - file_path.to_str().unwrap(), - e - )); - } - _ => (), - } - - misc::fatal_error(&format!( - "Could not create file {}, got:\n{}", - file_path.to_str().unwrap(), - e - )); - } - } -} diff --git a/src/http_async.rs b/src/http_async.rs index 7f45b8e..d0895c7 100644 --- a/src/http_async.rs +++ b/src/http_async.rs @@ -10,7 +10,7 @@ use reqwest::Client; use crate::misc; -pub async fn download_file( +pub async fn download_file_progress( client: &Client, pb: &ProgressBar, url: &str, @@ -58,3 +58,65 @@ pub async fn download_file( 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(&format!( + "Could not download file from {}, got:\n{}", + url, e + )); + 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) => { + let body = res.bytes().await.or(Err("Failed to get body"))?; + Ok(body.to_vec()) + } + Err(e) => { + misc::fatal_error(&format!("Could not get body from {}, got:\n{}", url, e)); + 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()) +} diff --git a/src/iw4x.rs b/src/iw4x.rs index 982576d..d9f2f25 100644 --- a/src/iw4x.rs +++ b/src/iw4x.rs @@ -1,6 +1,6 @@ use crate::github; use crate::global::*; -use crate::http; +use crate::http_async; use crate::misc; use colored::*; @@ -14,12 +14,12 @@ pub fn local_revision(dir: &Path) -> u16 { } } -pub fn remote_revision() -> u16 { - misc::rev_to_int(&github::latest_tag(GH_IW4X_OWNER, GH_IW4X_REPO)) +pub async fn remote_revision() -> u16 { + misc::rev_to_int(&github::latest_tag(GH_IW4X_OWNER, GH_IW4X_REPO).await) } -pub fn update(dir: &Path) { - let remote = remote_revision(); +pub async fn update(dir: &Path) { + let remote = remote_revision().await; let local = local_revision(dir); if remote <= local && dir.join("iw4x.dll").exists() { @@ -39,12 +39,14 @@ pub fn update(dir: &Path) { "Downloading".bright_yellow(), misc::cute_path(&dir.join("iw4x.dll")) ); - http::download_file( + http_async::download_file( &format!( "{}/download/iw4x.dll", github::latest_release_url(GH_IW4X_OWNER, GH_IW4X_REPO) ), &dir.join("iw4x.dll"), - ); + ) + .await + .unwrap(); fs::write(dir.join(".iw4xrevision"), format!("r{}", remote)).unwrap(); } diff --git a/src/main.rs b/src/main.rs index d2ba713..b7058a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ mod config; mod github; mod global; -mod http; mod http_async; mod iw4x; mod misc; @@ -271,7 +270,7 @@ async fn update_dir( fs::create_dir_all(parent).unwrap(); } } - http_async::download_file( + http_async::download_file_progress( &client, pb, &format!("{}/{}", master_url, file.name), @@ -292,15 +291,16 @@ async fn update( force: bool, skip_iw4x_sp: Option, master_url: &String, - ignore_required_files: Option + ignore_required_files: Option, ) { let skip_iw4x_sp = skip_iw4x_sp.unwrap_or(false); let ignore_required_files = ignore_required_files.unwrap_or(false); - let cdn_info: Vec = serde_json::from_str(&http::get_body_string( - format!("{}/files.json", master_url).as_str(), - )) - .unwrap(); + let res = http_async::get_body_string(format!("{}/files.json", master_url).as_str()) + .await + .unwrap(); + println!("{}", res); + let cdn_info: Vec = serde_json::from_str(&res).unwrap(); if !ignore_required_files && !game.required_files_exist(dir) { println!( @@ -324,7 +324,7 @@ async fn update( } if game.engine == "iw4" { - iw4x::update(dir); + iw4x::update(dir).await; let iw4x_dirs = vec!["iw4x", "zone/patch"]; for d in &iw4x_dirs { @@ -558,7 +558,7 @@ async fn main() { }; if !arg_bool(&args, "--skip-launcher-update") && !cfg.skip_self_update { - self_update::run(cfg.update_only); + self_update::run(cfg.update_only).await; } else { arg_remove(&mut args, "--skip-launcher-update"); } @@ -593,7 +593,9 @@ async fn main() { cfg.args = String::default(); } - let games_json = http::get_body_string(format!("{}/games.json", master_url).as_str()); + let games_json = http_async::get_body_string(format!("{}/games.json", master_url).as_str()) + .await + .unwrap(); let games: Vec = serde_json::from_str(&games_json).unwrap(); let mut game: String = String::new(); diff --git a/src/self_update.rs b/src/self_update.rs index 1a736a9..b2c3d4b 100644 --- a/src/self_update.rs +++ b/src/self_update.rs @@ -5,9 +5,9 @@ use semver::Version; #[cfg(not(windows))] use std::{thread, time}; -pub fn self_update_available() -> bool { +pub async fn self_update_available() -> bool { let current_version: Version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap(); - let latest_version = github::latest_version(GH_OWNER, GH_REPO); + let latest_version = github::latest_version(GH_OWNER, GH_REPO).await; current_version < latest_version } @@ -39,10 +39,10 @@ pub fn restart() -> std::io::Error { } #[cfg(windows)] -pub fn run(update_only: bool) { +pub async fn run(update_only: bool) { use std::{fs, path::PathBuf}; - use crate::http; + use crate::http_async; use crate::misc; let working_dir = std::env::current_dir().unwrap(); @@ -62,7 +62,7 @@ pub fn run(update_only: bool) { } } - if self_update_available() { + if self_update_available().await { println!("Performing launcher self-update."); println!( "If you run into any issues, please download the latest version at {}", @@ -82,14 +82,16 @@ pub fn run(update_only: bool) { "alterware-launcher.exe" }; - http::download_file( + http_async::download_file( &format!( "{}/download/{}", github::latest_release_url(GH_OWNER, GH_REPO), launcher_name ), &file_path, - ); + ) + .await + .unwrap(); if !file_path.exists() { println!("Failed to download launcher update.");