diff --git a/Cargo.lock b/Cargo.lock index 76df55e..6b9caef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,7 +163,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.87", ] [[package]] @@ -194,6 +194,17 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "derive-deref-rs" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb44ba65b4c7afe45d03d8e33ecb53a21c57d0ffff196f04aefa15c43671f8a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -202,7 +213,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.87", ] [[package]] @@ -273,6 +284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -281,6 +293,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + [[package]] name = "futures-sink" version = "0.3.31" @@ -300,9 +318,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", + "futures-io", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -580,7 +602,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.87", ] [[package]] @@ -589,6 +611,7 @@ version = "0.4.0" dependencies = [ "base64", "clap", + "derive-deref-rs", "idmangler-lib", "reqwest", "serde", @@ -776,7 +799,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.87", ] [[package]] @@ -848,6 +871,7 @@ dependencies = [ "base64", "bytes", "encoding_rs", + "futures-channel", "futures-core", "futures-util", "h2", @@ -1010,7 +1034,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.87", ] [[package]] @@ -1092,6 +1116,17 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.87" @@ -1120,7 +1155,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.87", ] [[package]] @@ -1174,7 +1209,7 @@ checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.87", ] [[package]] @@ -1358,7 +1393,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -1393,7 +1428,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1558,7 +1593,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.87", "synstructure", ] @@ -1579,7 +1614,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.87", "synstructure", ] @@ -1608,5 +1643,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.87", ] diff --git a/Cargo.toml b/Cargo.toml index d521a25..0b79885 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,8 +10,9 @@ description = "A cli tool to generate fake wynntils items" [dependencies] base64 = "0.22.1" clap = { version = "4.5.20", features = ["derive"] } +derive-deref-rs = "0.1.1" idmangler-lib = "0.4.0" -reqwest = "0.12.9" +reqwest = { version = "0.12.9", features = ["blocking", "json"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0.68" diff --git a/src/errorfr/mod.rs b/src/errorfr/mod.rs index c080996..3300012 100644 --- a/src/errorfr/mod.rs +++ b/src/errorfr/mod.rs @@ -4,30 +4,42 @@ use thiserror::Error; #[derive(Error, Debug)] pub enum Errorfr { /// item config json is missing - #[error("Error 1: item config json is missing")] + #[error("Error 1.1: item config json is missing.")] ItemJsonMissing, /// item config json is corrupt - #[error("Error 2: item config json is corrupt, Reread config.md\n{0}")] + #[error("Error 1.2: item config json is corrupt, Reread config.md.\n{0}")] ItemJsonCorrupt(serde_json::Error), /// idmap is missing - #[error("Error 3: id_keys.json is missing")] + #[error("Error 1.3: id_keys.json is missing")] IDMapJsonMissing, /// idmap is corrupt - #[error("Error 4: id_keys.json is corrupt")] + #[error("Error 2.1: id_keys.json is corrupt")] IDMapJsonCorrupt, /// shiny data json is missing - #[error("Error 5: shiny_stats.json is missing.")] + #[error("Error 2.2: shiny_stats.json is missing.")] ShinyJsonMissing, /// shiny data json is corrupt - #[error("Error 6: shiny_stats.json is corrupt.")] + #[error("Error 2.3: shiny_stats.json is corrupt.")] ShinyJsonCorrupt, - /// - #[error("Error 7: Item Type is missing from json (add an \"item_type\" field")] - ItemTypeMissing -} \ No newline at end of file + /// could not download the file + #[error("Error 3.1: Download request failed. Check your network settings.")] + JsonDlReqFail, + + /// invalid body response after downloading + #[error("Error 3.2: Download body is invalid. Something is broken.")] + JsonDlReqBodyInvalid, + + /// unable to create file after download + #[error("Error 3.3: Download successful, but unable to actually create the file.")] + JsonDlReqFileCreateFail, + + /// unable to copy (write in) file content + #[error("Error 9: Download successful, but unable to write to file.")] + JsonDlReqFileWriteFail, +} diff --git a/src/main.rs b/src/main.rs index 3f1310e..e9add9b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,19 +1,14 @@ use idmangler_lib::{ encoding::encode_string, types::{ - ItemType, TransformVersion, {RollType, Stat}, Element + Element, ItemType, TransformVersion, {RollType, Stat}, }, DataEncoder, EndData, IdentificationData, NameData, PowderData, RerollData, ShinyData, StartData, TypeData, }; -use std::{ - collections::HashMap, - env, - fs, - panic -}; -use std::path::PathBuf; +use std::ops::Deref; +use std::{collections::HashMap, env, fs, io, panic, path::PathBuf}; mod structures; use crate::structures::*; @@ -21,8 +16,9 @@ mod errorfr; use crate::errorfr::Errorfr; use clap::Parser; +use reqwest::Url; -#[derive(Parser, Debug)] +#[derive(Parser, Debug, Clone)] #[command(version, about, long_about = None)] struct Args { /// Path for config path @@ -32,67 +28,120 @@ struct Args { /// Enable debug mode #[arg(short, long, default_value_t = false)] debug: bool, + + /// Download jsons (for ease of use) + #[arg(long)] + download: Option, } -// const fallbackconfigpath: String = "config.json".to_owned(); +fn dl_json( + url: Url, + savename: String, + args: Args, + executablePath: &str, + debug_mode: bool, +) -> Result<(), Errorfr> { + let resp = reqwest::blocking::get(url).map_err(|_| Errorfr::JsonDlReqFail)?; + let body = resp.text().map_err(|_| Errorfr::JsonDlReqBodyInvalid)?; + let savepath = format!("{}",savename); + println!("Downloading to {savepath}"); + let mut out = fs::File::create(savepath) + .map_err(|_| Errorfr::JsonDlReqFileCreateFail)?; + io::copy(&mut body.as_bytes(), &mut out).map_err(|_| Errorfr::JsonDlReqFileWriteFail)?; + Ok(()) +} fn main() { - if let Err(e) = cook() { - println!("{}",e); - } -} -fn cook() -> Result<(), Errorfr> { // enable fancypanic when building for release // fancypanic(); let args = Args::parse(); let mut executablePath = env::current_exe().unwrap(); PathBuf::pop(&mut executablePath); - let executablePath = executablePath.to_str().unwrap(); + let executable_path = executablePath.to_str().unwrap(); let mut debug_mode = false; if args.debug == true { debug_mode = true; println!("Debug mode enabled"); }; - let mut config: String = String::from(executablePath.to_owned()+"config.json"); + + // download jsons if necessary + if let Some(dlvalue) = &args.download { + let jsons = DownloadJsons::from(dlvalue.clone()); + if jsons == DownloadJsons::all || jsons == DownloadJsons::shiny_stats { + if let Err(e) = dl_json( + "https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Data-Storage/shiny_stats.json".parse().unwrap(), + format!("{}{}", executable_path, "shiny_stats.json"), + args.clone(), + executable_path, + debug_mode + ) { // error handling below + println!("{} Filename: {}",e,dlvalue) + } + } + if jsons == DownloadJsons::all || jsons == DownloadJsons::id_keys { + if let Err(e) = dl_json( + "https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/id_keys.json".parse().unwrap(), + format!("{}{}", executable_path, "id_keys.json"), + args.clone(), + executable_path, + debug_mode + ) { // error handling below + println!("{} Filename: {}",e,dlvalue) + } + } + }; + + if let Err(e) = cook(args, executable_path, debug_mode) { + println!("{}", e); + } +} + +fn cook(args: Args, executable_path: &str, mut debug_mode: bool) -> Result<(), Errorfr> { + let mut config: String = String::from(executable_path.to_owned() + "config.json"); if let Some(configpathargs) = args.config { config = configpathargs; } // load configs - let json_config: Jsonconfig = serde_json::from_reader(fs::File::open(config) - .map_err(|_| Errorfr::ItemJsonMissing)?) - .map_err(|e| Errorfr::ItemJsonCorrupt(e))?; - let idsmap: HashMap = serde_json::from_reader(fs::File::open(executablePath.to_owned()+"id_keys.json") - .map_err(|_| Errorfr::IDMapJsonMissing)?) - .map_err(|_| Errorfr::IDMapJsonCorrupt)?; - let json_shiny: Vec = serde_json::from_reader(fs::File::open(executablePath.to_owned()+"shiny_stats.json") - .map_err(|_| Errorfr::ShinyJsonMissing)?) - .map_err(|_| Errorfr::ShinyJsonCorrupt)?; + let json_config: Jsonconfig = + serde_json::from_reader(fs::File::open(config).map_err(|_| Errorfr::ItemJsonMissing)?) + .map_err(|e| Errorfr::ItemJsonCorrupt(e))?; + let idsmap: HashMap = serde_json::from_reader( + fs::File::open(executable_path.to_owned() + "id_keys.json") + .map_err(|_| Errorfr::IDMapJsonMissing)?, + ) + .map_err(|_| Errorfr::IDMapJsonCorrupt)?; + let json_shiny: Vec = serde_json::from_reader( + fs::File::open(executable_path.to_owned() + "shiny_stats.json") + .map_err(|_| Errorfr::ShinyJsonMissing)?, + ) + .map_err(|_| Errorfr::ShinyJsonCorrupt)?; // println!("{:?}",idsmap.get("airDamage")); + if let Some(debugconfig) = json_config.debug { + if debugconfig { + debug_mode = true + } + } // create necessary variables let mut out = Vec::new(); let ver = TransformVersion::Version1; - // ENCODE: StartData - StartData(ver) - .encode(ver, &mut out) - .unwrap(); + StartData(ver).encode(ver, &mut out).unwrap(); // ENCODE: TypeData TypeData(ItemType::from(json_config.item_type)) .encode(ver, &mut out) - .map_err(|_| Errorfr::ItemTypeMissing)?; + .unwrap(); // ENCODE: NameData NameData(String::from(format!("{}", json_config.name.trim()))) .encode(ver, &mut out) .unwrap(); - // json identification data handling let mut idvec = Vec::new(); for eachid in json_config.ids { @@ -125,8 +174,6 @@ fn cook() -> Result<(), Errorfr> { .encode(ver, &mut out) .unwrap(); - - // json powder data handling let mut powdervec = Vec::new(); for eachpowder in json_config.powders { @@ -135,34 +182,19 @@ fn cook() -> Result<(), Errorfr> { // match for the powder type for _ in 0..powderamount { let eletype = match eachpowder.r#type.to_ascii_lowercase() { - 'e' => { - Element::Earth - } - 't' => { - Element::Thunder - } - 'w' => { - Element::Water - } - 'f' => { - Element::Fire - } - 'a' => { - Element::Air - } - _ => { - Element::Thunder - } + 'e' => Element::Earth, + 't' => Element::Thunder, + 'w' => Element::Water, + 'f' => Element::Fire, + 'a' => Element::Air, + _ => Element::Thunder, }; if debug_mode { dbg!(powdertier); dbg!(eletype); } - powdervec.push(Some((eletype,powdertier))); - - - }; - + powdervec.push(Some((eletype, powdertier))); + } } if debug_mode { dbg!(&powdervec); @@ -176,8 +208,6 @@ fn cook() -> Result<(), Errorfr> { .encode(ver, &mut out) .unwrap(); - - match json_config.rerolls { Some(rerollcount) => { if rerollcount != 0 { @@ -191,8 +221,6 @@ fn cook() -> Result<(), Errorfr> { None => pass(), }; - - let mut realshinykey: u8; if let Some(shiny) = json_config.shiny { if let ref _shinykey = shiny.key { @@ -218,7 +246,6 @@ fn cook() -> Result<(), Errorfr> { } .encode(ver, &mut out) .unwrap(); - } } } @@ -247,7 +274,6 @@ fn cook() -> Result<(), Errorfr> { // println!("{:#?}", out); Ok(()) - } fn fancypanic() { diff --git a/src/structures/mod.rs b/src/structures/mod.rs index 1ea9eaa..a9decb2 100644 --- a/src/structures/mod.rs +++ b/src/structures/mod.rs @@ -53,7 +53,41 @@ impl From for ItemType { ItemTypeDeser::Tome => ItemType::Tome, ItemTypeDeser::Charm => ItemType::Charm, ItemTypeDeser::CraftedConsu => ItemType::CraftedConsu, - ItemTypeDeser::CraftedGear => ItemType::CraftedGear + ItemTypeDeser::CraftedGear => ItemType::CraftedGear, } } -} \ No newline at end of file +} + +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug, Deserialize)] +pub enum DownloadJsons { + none, + id_keys, + shiny_stats, + all, +} +impl From for DownloadJsons { + fn from(value: String) -> Self { + match value.to_lowercase().as_str().trim() { + "none" => { + println!("download NONE"); + DownloadJsons::none + } + "id_keys" | "idkeys" | "idkeys.json" | "id_keys.json" => { + println!("download ID_KEYS"); + DownloadJsons::id_keys + } + "shiny_stats" | "shinystats" | "shiny_stats.json" | "shinystats.json" => { + println!("download SHINY_STATS"); + DownloadJsons::shiny_stats + } + "all" | "everything" | "both" => { + println!("download BOTH"); + DownloadJsons::all + } + _ => { + println!("Could not understand what Jsons to download, sorry."); + DownloadJsons::none + } + } + } +}