From 36035f52049ca36298152df68888b6e028c96af6 Mon Sep 17 00:00:00 2001 From: Vomitblood Date: Tue, 16 Apr 2024 23:20:41 +0800 Subject: [PATCH] added pokemon.json fetching --- Cargo.lock | 17 +-- Cargo.toml | 6 +- pokemon.json.bak => pokemon.bak.json | 0 src/bin/testing.rs | 48 ++++---- src/constants.rs | 20 ---- src/fetch.rs | 161 ++++++++++++++++++++++++++- src/main.rs | 5 +- 7 files changed, 191 insertions(+), 66 deletions(-) rename pokemon.json.bak => pokemon.bak.json (100%) diff --git a/Cargo.lock b/Cargo.lock index 4377dff..eefce86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -300,7 +300,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", - "clap_derive", ] [[package]] @@ -315,18 +314,6 @@ dependencies = [ "strsim", ] -[[package]] -name = "clap_derive" -version = "4.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "clap_lex" version = "0.7.0" @@ -1715,9 +1702,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", diff --git a/Cargo.toml b/Cargo.toml index 3cd982e..a9ed60f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -clap = { version = "4.5.4", features = ["cargo", "derive"] } +clap = { version = "4.5.4", features = ["cargo"] } crossterm = "0.27.0" ctrlc = "3.4.4" dirs = "5.0.1" @@ -13,6 +13,6 @@ once_cell = "1.19.0" rand = { version = "0.8.4", features = ["small_rng"] } reqwest = { version = "0.11", features = ["blocking", "json"] } rust-embed = "8.3.0" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" +serde = { version = "1.0.197", features = ["derive"] } +serde_json = "1.0.116" zip = "0.6.6" diff --git a/pokemon.json.bak b/pokemon.bak.json similarity index 100% rename from pokemon.json.bak rename to pokemon.bak.json diff --git a/src/bin/testing.rs b/src/bin/testing.rs index 9cb723c..a96a036 100644 --- a/src/bin/testing.rs +++ b/src/bin/testing.rs @@ -1,28 +1,32 @@ -use std::fs; - fn main() { - let contents = fs::read_to_string("testing/testing.fuck").unwrap(); - let mut found: bool = false; - - for line in contents.lines() { - match line { - "1" | "2" => { - found = true; - break; - } - - // if not found - _ => found = false, - } - } - - if found == true { - println!("Gotcha bitch"); - } else { - println!("Never mind") - } + let _bruh = "bruh"; } +// use std::fs; + +// fn main() { +// let contents = fs::read_to_string("testing/testing.fuck").unwrap(); +// let mut found: bool = false; + +// for line in contents.lines() { +// match line { +// "1" | "2" => { +// found = true; +// break; +// } + +// // if not found +// _ => found = false, +// } +// } + +// if found == true { +// println!("Gotcha bitch"); +// } else { +// println!("Never mind") +// } +// } + // use rand::{thread_rng, Rng}; // use std::io::{self, stdout, Write}; // use std::num::ParseIntError; diff --git a/src/constants.rs b/src/constants.rs index b30d9ac..08bf06c 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -14,23 +14,3 @@ pub static CACHE_DIRECTORY: once_cell::sync::Lazy = .map(|dir| dir.join("rustmon")) .expect("Cache directory not found") }); - -// fn get_directories() -> (std::path::PathBuf, std::path::PathBuf) { -// let data_directory: std::path::PathBuf = match dirs::data_dir() { -// Some(dir) => dir.join("rustmon"), -// None => { -// println!("Data directory not found"); -// std::process::exit(1); -// } -// }; - -// let cache_directory: std::path::PathBuf = match dirs::cache_dir() { -// Some(dir) => dir.join("rustmon"), -// None => { -// println!("Cache directory not found"); -// std::process::exit(1); -// } -// }; - -// return (data_directory, cache_directory); -// } diff --git a/src/fetch.rs b/src/fetch.rs index c1206fb..f41e0ee 100644 --- a/src/fetch.rs +++ b/src/fetch.rs @@ -10,6 +10,26 @@ pub fn fetch(extract_destination: &std::path::Path, verbose: bool) { } }; + // download pokemon.json + match fetch_pokemon_json() { + Ok(_) => (), + Err(e) => { + eprintln!("Error fetching pokemon_raw.json: {}", e); + cleanup().unwrap(); + std::process::exit(1); + } + } + + // process pokemon_raw.json + match process_pokemon_json() { + Ok(_) => (), + Err(e) => { + eprintln!("Error processing pokemon_raw.json: {}", e); + cleanup().unwrap(); + std::process::exit(1); + } + }; + // download colorscripts archive match fetch_colorscripts_archive(crate::constants::TARGET_URL) { Ok(_) => (), @@ -52,10 +72,11 @@ pub fn fetch(extract_destination: &std::path::Path, verbose: bool) { }; // cleanup - match cleanup() { - Ok(_) => (), - Err(e) => eprintln!("Error cleaning up: {}", e), - }; + // TODO: uncomment + // match cleanup() { + // Ok(_) => (), + // Err(e) => eprintln!("Error cleaning up: {}", e), + // }; } fn create_working_directory() -> std::io::Result<()> { @@ -69,6 +90,138 @@ fn create_working_directory() -> std::io::Result<()> { return Ok(()); } +fn fetch_pokemon_json() -> Result<(), Box> { + println!("Fetching pokemon_raw.json..."); + + let response = reqwest::blocking::get( + "https://raw.githubusercontent.com/Vomitblood/pokesprite/master/data/pokemon.json", + )?; + + let mut dest = std::fs::File::create( + &*crate::constants::CACHE_DIRECTORY + .to_path_buf() + .join("pokemon_raw.json"), + )?; + + let response_body = response.error_for_status()?.bytes()?; + std::io::copy(&mut response_body.as_ref(), &mut dest)?; + + println!("Downloaded pokemon_raw.json"); + + return Ok(()); +} + +#[derive(serde::Serialize, serde::Deserialize, Debug)] +struct Slug { + eng: String, +} + +#[derive(serde::Serialize, serde::Deserialize, Debug)] +struct Forms { + // ignoring actual details in the forms and just capturing form names +} + +#[derive(serde::Serialize, serde::Deserialize, Debug)] +struct Generation { + forms: std::collections::HashMap, +} + +#[derive(serde::Serialize, serde::Deserialize, Debug)] +struct Pokemon { + idx: String, + slug: Slug, + #[serde(rename = "gen-8")] + gen_8: Generation, +} + +#[derive(serde::Serialize, serde::Deserialize, Debug)] +struct PokemonCollection { + #[serde(flatten)] + entries: std::collections::HashMap, +} + +#[derive(serde::Serialize, Debug)] +struct ProcessedPokemon { + pokedex: String, + name: String, + forms: Vec, +} + +fn process_pokemon_json() -> Result<(), Box> { + println!("Generating pokemon.json..."); + + let pokemon_raw_json_path = &*crate::constants::CACHE_DIRECTORY.join("pokemon_raw.json"); + + let pokemon_collection = read_pokemon_file(pokemon_raw_json_path)?; + + let processed_pokemon = transform_pokemon_data(&pokemon_collection.entries); + + // serialize the processed data to JSON + let serialized_pokemon = serde_json::to_string_pretty(&processed_pokemon)?; + + // write processed data to file + std::fs::write( + crate::constants::CACHE_DIRECTORY.join("processed_pokemon.json"), + serialized_pokemon, + )?; + + println!("Generated pokemon.json"); + + Ok(()) +} + +fn read_pokemon_file( + file_path: &std::path::Path, +) -> Result> { + // open the file in read only mode + let file = std::fs::File::open(file_path)?; + let reader = std::io::BufReader::new(file); + + // deserialize the into pokemoncollection + let collection = serde_json::from_reader(reader)?; + + return Ok(collection); +} + +fn transform_pokemon_data( + pokemons: &std::collections::HashMap, +) -> Vec { + let mut processed_pokemons: Vec = pokemons + .iter() + .map(|(_key, p)| { + let forms = p + .gen_8 + .forms + .keys() + .map(|key| match key.as_str() { + "$" => "regular".to_string(), + _ => key.clone(), + }) + .collect::>(); + + ProcessedPokemon { + // remove leading zeros from the pokedex number + pokedex: p.idx.trim_start_matches('0').to_string(), + // use the slug as the name + // this is because i am too lazy to decapitalize the name + // also in case of name =/= slug + name: p.slug.eng.clone(), + forms, + } + }) + .collect(); + + // sort the vector by pokedex number + processed_pokemons.sort_by(|a, b| { + a.pokedex + .parse::() + .unwrap_or(0) + .cmp(&b.pokedex.parse::().unwrap_or(0)) + }); + + return processed_pokemons; +} + fn fetch_colorscripts_archive(target_url: &str) -> Result<(), Box> { println!("Fetching colorscripts archive..."); diff --git a/src/main.rs b/src/main.rs index 0a66ba4..e3b3803 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,11 +5,12 @@ - `verbose` - Print colorscripts when generating ## `print` - Print a Pokemon colorscript -- `name` - Select Pokemon by name - `big` - Print a bigger version of the colorscript +- `id` - Print Pokemon by ID - `list` - Print a list of all Pokemon names -- `random` - Print a random Pokemon colorscript +- `name` - Print Pokemon by name - `no-title` - Do not print Pokemon name +- `random` - Print a random Pokemon colorscript - `shiny` - Print the shiny version of the colorscript */