Initial Commit

This commit is contained in:
BloxerHD 2025-07-09 23:09:30 +01:00
commit c07410b1a7
4 changed files with 134 additions and 0 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
/target
Cargo.lock
.env
/miis

13
Cargo.toml Normal file
View file

@ -0,0 +1,13 @@
[package]
name = "cache-mii"
version = "0.1.0"
edition = "2024"
[dependencies]
rocket = "0.5.1"
tokio = { version = "1", features = ["full"] }
dotenvy = "0.15.7"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
reqwest = { version = "0.12.12", features = ["json"] }
bytes = "1"

5
README.md Normal file
View file

@ -0,0 +1,5 @@
# Cache Mii
Mii Render Caching Server that saves a .png and .tga render of a user's mii for use across SPFN's services
### Credits:
- [Mii Renderer](https://mii-unsecure.ariankordi.net/): Arian Kordi

112
src/main.rs Normal file
View file

@ -0,0 +1,112 @@
use dotenvy::dotenv;
use rocket::http::Status;
use rocket::fs::NamedFile;
use rocket::State;
use reqwest::Client;
use bytes::Bytes;
static MII_RENDERER_URL: &str = "https://mii-unsecure.ariankordi.net/";
static ALLOWED_FORMATS: [&str; 2] = [
"png",
"tga",
];
async fn request_mii_render(client: &State<Client>, mii_data: &str, ext: &str) -> Option<Bytes> {
let req_str = format!("{}/miis/image.{}?data={}", MII_RENDERER_URL, ext, mii_data);
let response = client.get(req_str)
.send()
.await
.ok()?;
Some(response.bytes().await.expect("Failed to parse Mii Render to Bytes"))
}
#[rocket::get("/<pid_str>/<path>")]
pub async fn mii_render(pid_str: &str, path: &str, client: &State<Client>) -> Option<NamedFile> {
let ext = path.splitn(2, ".").nth(1)?;
let pid: i32 = pid_str.parse().expect("PID is not an i32");
if !ALLOWED_FORMATS.contains(&ext) {return None}
let mii_data = {
let route = format!("https://account.spfn.net/api/v2/users/{}/mii", pid);
let response = client.get(route)
.send()
.await
.ok()
.expect("Error Retrieving Mii Data");
let data: String = response.json().await.expect("Failed to parse Mii Data Response");
data
};
let cache_path = std::path::Path::new("miis/").join(pid.to_string());
let img_path = cache_path.clone().join(path);
let data_path = cache_path.clone().join("data");
// Update Cache
if cache_path.exists() && cache_path.is_dir() { // Mii data was previously cached - Verify it is correct
if data_path.exists() && data_path.is_file() { // Data exists - Check if it's the same
let cache_data = std::fs::read_to_string(&data_path);
match cache_data {
Ok(hash) => {
if hash == mii_data { // Cached images are correct
if !img_path.exists() || !img_path.is_file() { // File type was not found - Request data
let img_data = request_mii_render(client, &mii_data, ext).await?;
let _ = std::fs::write(&img_path, &img_data);
}
} else { // Cached images are outdated - Update data
let img_data = request_mii_render(client, &mii_data, ext).await?;
let _ = std::fs::write(&img_path, &img_data);
};
}
Err(_) => { // Data cannot be read - Request data
println!("Data is not valid");
let _ = std::fs::write(data_path, &mii_data);
let img_data = request_mii_render(client, &mii_data, ext).await?;
let _ = std::fs::write(&img_path, &img_data);
}
}
} else { // Data isn't saved - Request data
println!("Data is not recorded");
let _ = std::fs::write(data_path, &mii_data);
let img_file = request_mii_render(client, &mii_data, ext).await?;
let _ = std::fs::write(&img_path, &img_file);
}
} else { // Mii data was never cached - Request data
println!("Mii Data was Never Cached");
let _ = std::fs::create_dir(format!("miis/{}", pid.to_string()));
let _ = std::fs::write(data_path, &mii_data);
let img_data = request_mii_render(client, &mii_data, ext).await?;
let _ = std::fs::write(&img_path, &img_data);
};
let img = NamedFile::open(img_path).await.map_err(|_| Status::InternalServerError).expect("Error opening Image");
Some(img)
}
#[rocket::launch]
async fn launch() -> _ {
dotenv().ok();
let client = Client::new();
let mii_path = std::path::Path::new("miis");
if !mii_path.exists() || !mii_path.is_dir() {
let _ = std::fs::create_dir("miis");
}
rocket::build()
.manage(client)
.mount("/", rocket::routes![mii_render])
}