From 8196b4b9a8e372b2bf683aa78e956e13e3c96ab7 Mon Sep 17 00:00:00 2001 From: stdpi Date: Thu, 1 Aug 2024 00:39:16 +0700 Subject: [PATCH] feat: fallback server (ugu pls don't rlm) --- Cargo.lock | 1 + Cargo.toml | 2 ++ src/main.rs | 84 ++++++++++++++++++++++++++++++----------------------- 3 files changed, 50 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96c0829..e8107d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2031,6 +2031,7 @@ dependencies = [ "serde_json", "sqlx", "surf", + "thiserror", "tide", "tide-prometheus", ] diff --git a/Cargo.toml b/Cargo.toml index c5ca939..cd46395 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ path = "src/main.rs" [features] default = [] simd = [] +nomn = [] [dependencies] async-std = { version = "1.12.0", features = ["attributes"] } @@ -26,5 +27,6 @@ sqlx = { version = "0.8", features = [ surf = { version = "2.3.2", default-features = false, features = [ "h1-client-rustls", ] } +thiserror = "1" tide = "0.16.0" tide-prometheus = { version = "0.1.0", features = ["process"] } diff --git a/src/main.rs b/src/main.rs index 7eb87e0..38efdc3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use image::{codecs::png::PngEncoder, GenericImage, ImageBuffer, Pixel, Rgba, RgbaImage}; use regex::Regex; +use thiserror::Error; use tide::{Body, Request, Response}; use image::ImageReader; @@ -39,10 +40,24 @@ struct AvatarMeta { textures: TextureListMeta, } +#[derive(Error, Debug)] +enum AppError { + #[error("Database Error")] + Database(#[from] sqlx::Error), + #[error("Serialization Error")] + Serialization, + #[error("Framework Error")] + Framework, + #[error("QueryBody Error")] + QueryBody(#[from] surf::DecodeError), + #[error("Query Error")] + Query(String), +} + static PLACEHOLDER: &[u8] = include_bytes!("placeholder.png"); -async fn query(pool: &Pool, nick: &String) -> Result { - let sq: sqlx::Result<(String, i32)> = sqlx::query_as( +async fn query(pool: &Pool, nick: &String) -> Result { + let sq: (String, i32) = sqlx::query_as( if env::var("SOFT_DATABASE").unwrap_or("".to_string()) == "yes" { "SELECT CONVERT(FROM_BASE64(sk.Value) USING UTF8) as data, 0 as t FROM Skins as sk @@ -59,14 +74,12 @@ async fn query(pool: &Pool, nick: &String) -> Result(&sqd)?) - } else if let Some(er) = sq.err() { - Err(tide::Error::from_str(404, format!("{}", er))) + .await?; + return if let Ok(de) = serde_json::from_str::(&sq.0) { + Ok(de) } else { - Err(tide::Error::from_str(404, "unk err")) - } + Err(AppError::Serialization) + }; } async fn fetch(met: &AvatarMeta, path: &Path) -> Result, tide::Error> { @@ -130,21 +143,9 @@ struct PlayerQuery { scale: Option, } -fn face_err(state: &State, not_ok_str: String) -> tide::Result { +fn face_err(state: &State) -> tide::Result { state.counter_cache.with_label_values(&["failed"]).inc(); Ok(Response::builder(404) - .header( - "X-Not-Ok", - match not_ok_str.as_str() { - "no rows returned by a query that expected to return at least one row" => { - "no entry" - } - _ => { - println!("{not_ok_str}"); - "yeah not ok" - } - }, - ) .header("Cache-Control", "no-cache") .header("Content-Type", "image/png") .body(PLACEHOLDER) @@ -179,24 +180,33 @@ async fn face(res: Request) -> tide::Result { let url = env::var("DATABASE_URL")?; let pool = MySqlPool::connect(&url).await?; let query = query(&pool, &name).await; - if let Ok(meta) = query { + let (raw_path, meta) = if let Ok(meta) = query { let _pth = format!("./.cache/moj/{}.png", &meta.profile_id); - let raw_path = Path::new(&_pth); - - let f = File::create(face_path)?; - let enc = PngEncoder::new(f); - cached_1x_buffer = Some(draw_face(res.state(), raw_path, &meta).await?); - cached_1x_buffer.clone().unwrap().write_with_encoder(enc)?; + fetch(&meta, raw_path).await?; + (_pth, meta) } else { - return face_err( - res.state(), - query - .err() - .map(|e: surf::Error| format!("{e}")) - .unwrap_or_default(), - ); - } + #[cfg(feature = "nomn")] + face_err(res.state()); + + let _pth = format!("./.cache/moj/{}.png", name); + let raw_path = Path::new(&_pth); + let meta = AvatarMeta { + profile_id: "".to_string(), + textures: TextureListMeta { + skin: TextureMeta { + url: format!("https://minotar.net/skin/{}.png", name), + }, + }, + }; + fetch(&meta, raw_path).await?; + (_pth, meta) + }; + + let f = File::create(face_path)?; + let enc = PngEncoder::new(f); + cached_1x_buffer = Some(draw_face(res.state(), Path::new(&raw_path), &meta).await?); + cached_1x_buffer.clone().unwrap().write_with_encoder(enc)?; } else { cache_hit = true; if should_upscale {