From 3b63fe94a71903d31c491a4e280ce8cc6e19d169 Mon Sep 17 00:00:00 2001 From: AINDUSTRIES Date: Tue, 8 Sep 2026 18:25:46 +0200 Subject: [PATCH] Reworked skins api into a single endpoint with parameters --- src/main.rs | 9 ++- src/skins.rs | 174 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 117 insertions(+), 66 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1b11db0..379f59a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,7 @@ use tower_sessions_sqlx_store::sqlx::PgPool as SessionPgPool; mod error; mod skins; mod users; -use skins::{gloves, knife, weapons}; +use skins::{skin_info, weapons}; use users::{login, logout, me, reload, update}; #[tokio::main] @@ -39,8 +39,7 @@ async fn main() -> Result<(), Box> { .route("/update", post(update)) .route("/reload", get(reload)) .route("/weapons", get(weapons)) - .route("/knife", get(knife)) - .route("/gloves", get(gloves)) + .route("/skin", get(skin_info)) .layer( CorsLayer::new() .allow_origin("http://localhost:5173".parse::().unwrap()) @@ -50,10 +49,10 @@ async fn main() -> Result<(), Box> { ) .layer(session) .with_state(pool); - let listener = TcpListener::bind("0.0.0.0:8080").await?; + let listener = TcpListener::bind(var("BIND_ADDRESS")?).await?; Ok(serve(listener, app).await?) } async fn status() -> &'static str { - "api online" + "API online" } diff --git a/src/skins.rs b/src/skins.rs index eb8ab64..55233f0 100644 --- a/src/skins.rs +++ b/src/skins.rs @@ -1,11 +1,8 @@ -use std::error::Error; - use axum::{ Json, extract::{Query, State}, }; use serde::{Deserialize, Serialize}; -use serde_json::Value; use sqlx::{PgPool, query, query_as, types::Uuid}; use tower_sessions::Session; @@ -22,11 +19,14 @@ pub struct Weapon { } #[derive(Deserialize, Serialize)] -pub struct WeaponInfo { +pub struct SkinInfo { id: Uuid, name: String, + display: String, paint_index: i32, color: String, + float: f64, + pattern: i32, } #[axum::debug_handler] @@ -37,70 +37,122 @@ pub async fn weapons(State(pool): State) -> Result>, Ap Ok(Json(weapons)) } +#[derive(Deserialize, Serialize, Copy, Clone, Debug)] +enum Teams { + CT, + T, + BOTH, +} + +impl Teams { + fn as_i32(self) -> i32 { + match self { + Teams::CT => 0, + Teams::T => 1, + Teams::BOTH => 2, + } + } +} + +#[derive(Deserialize, Serialize, Copy, Clone, Debug)] +enum Categories { + Knives, + Gloves, + Rifles, + SMGs, + Pistols, + Heavy, + Equipment, +} + +impl Categories { + fn as_str(self) -> &'static str { + match self { + Categories::Knives => "Knives", + Categories::Gloves => "Gloves", + Categories::Rifles => "Rifles", + Categories::SMGs => "SMGs", + Categories::Pistols => "Pistols", + Categories::Heavy => "Heavy", + Categories::Equipment => "Equipment", + } + } +} + #[derive(Deserialize, Serialize)] -pub struct TeamQuery { - team: String, +pub struct SkinInfoQuery { + category: Option, + team: Option, } -pub async fn knife( +pub async fn skin_info( State(pool): State, session: Session, - Query(team): Query, -) -> Result, AppError> { + Query(info_query): Query, +) -> Result>, AppError> { if let Some(uuid) = session.get::("uuid").await? { - let team = match team.team.as_str() { - "CT" => 0, - "T" => 1, - _ => 2, - }; - let knife = match query_as!(WeaponInfo, "SELECT us.id, wp.name, sk.paint_index, r.color FROM user_skins us LEFT JOIN skins sk ON sk.id = us.skin_id LEFT JOIN rarity r ON r.id = sk.rarity LEFT JOIN weapons wp ON wp.id = sk.weapon WHERE us.user_id = $1 AND us.team = $2 AND wp.category='Knives'", uuid, team).fetch_optional(&pool).await? { - Some(knife) => knife, - None => { - let name = match team { - 0 => "weapon_knife", - _ => "weapon_knife_t" - }; - let info = query!("SELECT wp.name, r.color FROM weapons wp LEFT JOIN skins sk ON sk.weapon = wp.id LEFT JOIN rarity r ON r.id = sk.rarity WHERE wp.name = $1", name).fetch_one(&pool).await?; - WeaponInfo { - id: Uuid::nil(), + let mut skins = query!("SELECT sk.id, w.team, w.category FROM user_skins sk left join skins s on s.id = sk.skin_id left join weapons w on w.id = s.weapon LEFT JOIN users us ON us.id = sk.user_id WHERE us.id = $1", uuid).fetch_all(&pool).await?; + if let Some(team) = info_query.team { + skins = skins + .into_iter() + .filter(|x| team.as_i32() == x.team || Teams::BOTH.as_i32() == x.team) + .collect(); + } + if let Some(category) = info_query.category { + skins = skins + .into_iter() + .filter(|x| category.as_str() == x.category) + .collect(); + } + let mut skin_infos = Vec::new(); + let ids: Vec = skins.iter().map(|x| x.id).collect(); + for id in ids { + let info = query!("SELECT w.name, w.display as wdisplay, s.display as sdisplay, s.paint_index, r.color, us.float, us.pattern FROM user_skins us JOIN skins s ON s.id = us.skin_id JOIN rarity r on r.id = s.rarity JOIN weapons w on w.id = s.weapon WHERE us.id = $1", id).fetch_one(&pool).await?; + let display = if info.sdisplay.is_empty() { + info.wdisplay + } else { + format!("{} | {}", info.wdisplay, info.sdisplay) + }; + let skin_info = SkinInfo { + id, + display, name: info.name, - paint_index: 0, - color: info.color - }} - }; - Ok(Json(knife)) - } else { - Err(AppError::Unauthorised) - } -} - -pub async fn gloves( - State(pool): State, - session: Session, - Query(team): Query, -) -> Result, AppError> { - if let Some(uuid) = session.get::("uuid").await? { - let team = match team.team.as_str() { - "CT" => 0, - "T" => 1, - _ => 2, - }; - let gloves = match query_as!(WeaponInfo, "SELECT us.id, wp.name, sk.paint_index, r.color FROM user_skins us LEFT JOIN skins sk ON sk.id = us.skin_id LEFT JOIN rarity r ON r.id = sk.rarity LEFT JOIN weapons wp ON wp.id = sk.weapon WHERE us.user_id = $1 AND us.team = $2 AND wp.category = 'Gloves'", uuid, team).fetch_optional(&pool).await? { - Some(gloves) => gloves, - None => { - let name = match team { - 0 => "ct_gloves", - _ => "t_gloves" - }; - let info = query!("SELECT wp.name, r.color FROM weapons wp LEFT JOIN skins sk ON sk.weapon = wp.id LEFT JOIN rarity r ON r.id = sk.rarity WHERE wp.name = $1", name).fetch_one(&pool).await?; - WeaponInfo { - id: Uuid::nil(), - name: info.name, - paint_index: 0, - color: info.color - }} - }; - Ok(Json(gloves)) + paint_index: info.paint_index, + color: info.color, + float: info.float, + pattern: info.pattern, + }; + skin_infos.push(skin_info); + } + if skin_infos.is_empty() { + // fetch default skins + let mut infos = query!("SELECT w.name, w.display, w.team, w.category, r.color FROM skins s JOIN rarity r ON r.id = s.rarity JOIN weapons w ON w.id = s.weapon WHERE s.paint_index = 0").fetch_all(&pool).await?; + if let Some(team) = info_query.team { + infos = infos + .into_iter() + .filter(|x| team.as_i32() == x.team) + .collect(); + } + if let Some(category) = info_query.category { + infos = infos + .into_iter() + .filter(|x| category.as_str() == x.category) + .collect(); + } + skin_infos = infos + .into_iter() + .map(|x| SkinInfo { + id: Uuid::nil(), + name: x.name, + display: x.display, + color: x.color, + paint_index: 0, + float: 0.0, + pattern: 0, + }) + .collect(); + } + Ok(Json(skin_infos)) } else { Err(AppError::Unauthorised) }