Initial Commit
This commit is contained in:
commit
c07410b1a7
4 changed files with 134 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
/target
|
||||||
|
Cargo.lock
|
||||||
|
.env
|
||||||
|
/miis
|
||||||
13
Cargo.toml
Normal file
13
Cargo.toml
Normal 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
5
README.md
Normal 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
112
src/main.rs
Normal 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])
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue