diff --git a/launcher/Cargo.toml b/launcher/Cargo.toml index a0b854e..d74e0be 100644 --- a/launcher/Cargo.toml +++ b/launcher/Cargo.toml @@ -1,11 +1,14 @@ [package] name = "launcher" -version = "0.1.0" +version = "0.1.1" edition = "2021" [dependencies] shell-escape = "0.1.5" tracing = "0.1.41" -tracing-subscriber = "0.3.19" +tracing-subscriber = { version = "0.3.19", features = ["env-filter", "chrono"] } url = "2.5.4" clap = { version = "4.5.23", features = ["derive"] } +reqwest = { version = "0.12.15", features = ["json"] } +serde_json = "1.0.140" +tokio = { version = "1.0.0", features = ["rt", "rt-multi-thread", "macros"] } \ No newline at end of file diff --git a/launcher/src/main.rs b/launcher/src/main.rs index a8758cc..dfd12bd 100644 --- a/launcher/src/main.rs +++ b/launcher/src/main.rs @@ -1,17 +1,22 @@ mod launcher; +mod version; +use crate::version::version_check; use std::process::Command; use std::{env, io}; use tracing::{debug, error, info, Level}; +use tracing_subscriber::EnvFilter; use url::Url; #[derive(Debug)] enum Commands { Launch, Update, + Check, } -fn main() -> Result<(), Box> { +#[tokio::main] +async fn main() -> Result<(), Box> { let verbose = 0; let verbose = match verbose { 0 => Level::INFO, @@ -20,7 +25,9 @@ fn main() -> Result<(), Box> { }; // Set our logging level - tracing_subscriber::fmt().with_max_level(verbose).init(); + let filter = EnvFilter::try_new(format!("launcher=debug")) + .unwrap_or_else(|_| EnvFilter::new(format!("launcher=info"))); + tracing_subscriber::fmt().with_env_filter(filter).init(); let args: Vec = env::args().collect(); if args.len() < 2 { @@ -42,6 +49,7 @@ fn main() -> Result<(), Box> { let action = match method { "launch" => Commands::Launch, "update" => Commands::Update, + "version" => Commands::Check, other => return Err(format!("Unknown method: {}", other).into()), }; @@ -54,6 +62,10 @@ fn main() -> Result<(), Box> { error!("Update action not implemented"); return Err("Update action not implemented".into()); } + Commands::Check => { + version_check(uri.to_string()).await; + wait_for_keypress(); + } } Ok(()) diff --git a/launcher/src/version.rs b/launcher/src/version.rs new file mode 100644 index 0000000..1ced068 --- /dev/null +++ b/launcher/src/version.rs @@ -0,0 +1,87 @@ +use crate::format_shell_command; +use crate::wait_for_keypress; +use reqwest::Client; +use serde_json::json; +use std::borrow::Cow; +use std::env; +use std::process::exit; +use std::process::{Command, Stdio}; +use tracing::{debug, error, info, warn}; +use url::Url; + +static APP_USER_AGENT: &str = concat!( +"osirose-", +env!("CARGO_PKG_NAME"), +"/", +env!("CARGO_PKG_VERSION"), +); + +async fn send_version_to_browser(callback_url: Option, client_version: &str) { + if let Some(url) = callback_url { + let payload = json!({ + "version": client_version, + }); + + let client = reqwest::Client::builder() + .user_agent(APP_USER_AGENT) + .build(); + + if (client.is_err()) { + error!("Unable to build info client"); + return; + } + + match client.unwrap().post(url.clone()).json(&payload).send().await { + Ok(response) => { + if response.status().is_success() { + info!("Successfully sent version info to {url} URL!"); + } else { + error!("Failed to send data. Status: {}", response.status()); + } + } + Err(err) => { + error!("Error sending POST request: {}", err); + } + } + return; + } + + error!("Missing callback URL"); +} + +fn parse_url(url: &str) -> Option { + if let parsed_url = Url::parse(url).ok()? { + return Some(parsed_url.to_string()); + } + None +} + +fn check_client_version() -> String { + // This is temp until I can get an actual version check + "1.0.0".to_string() +} + +pub(crate) async fn version_check(url: String) { + match Url::parse(&url) { + Ok(parsed_url) => { + let params = parsed_url.query_pairs(); + + let mut callback_url = None; + for (key, value) in params { + debug!("Query pairs: [{}, {}]", key, value); + + match key { + Cow::Borrowed("callback") => { + callback_url = parse_url(&value); + } + _ => { + warn!("Unexpected parameter: [{}, {}]", key, value); + } + } + } + + send_version_to_browser(callback_url, &check_client_version()).await; + } + Err(e) => error!("Failed to parse URL: {}", e), + } +} \ No newline at end of file