Compare commits

...

3 Commits

Author SHA1 Message Date
8aac11e370 Added prototype function for skin retrieval 2026-09-03 02:02:55 +02:00
7ef7983ee8 Added parsing for sqlx error 2026-09-03 02:01:49 +02:00
ea4dffbdc6 Updated database schemas 2026-09-03 02:01:38 +02:00
5 changed files with 137 additions and 2 deletions

View File

@@ -15,11 +15,21 @@ CREATE TABLE IF NOT EXISTS rarity (
CREATE TABLE IF NOT EXISTS skins ( CREATE TABLE IF NOT EXISTS skins (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY, id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
weapon uuid REFERENCES weapons(id), weapon uuid REFERENCES weapons(id) NOT NULL,
rarity uuid REFERENCES rarity(id), rarity uuid REFERENCES rarity(id) NOT NULL,
paint_index integer NOT NULL, paint_index integer NOT NULL,
display varchar NOT NULL, display varchar NOT NULL,
min_float float NOT NULL, min_float float NOT NULL,
max_float float NOT NULL, max_float float NOT NULL,
legacy boolean NOT NULL legacy boolean NOT NULL
); );
CREATE TABLE IF NOT EXISTS agents (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
rarity uuid REFERENCES rarity(id) NOT NULL,
name varchar NOT NULL,
display varchar NOT NULL,
def_index integer NOT NULL,
team integer NOT NULL, -- 0 = CT, 1 = T, 2 = BOTH
model_player varchar NOT NULl
);

View File

@@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS user_skins (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
user_id uuid REFERENCES users(id) NOT NULL,
skin_id uuid REFERENCES skins(id),
agent_id uuid REFERENCES agents(id),
team integer NOT NULL -- 0 = CT, 1 = T, 2 = BOTH
);

View File

@@ -34,3 +34,9 @@ impl From<tower_sessions::session::Error> for AppError {
AppError::InternalError(value.to_string()) AppError::InternalError(value.to_string())
} }
} }
impl From<sqlx::Error> for AppError {
fn from(value: sqlx::Error) -> Self {
AppError::InternalError(value.to_string())
}
}

View File

@@ -15,7 +15,9 @@ use tower_sessions_sqlx_store::PostgresStore;
use tower_sessions_sqlx_store::sqlx::PgPool as SessionPgPool; use tower_sessions_sqlx_store::sqlx::PgPool as SessionPgPool;
mod error; mod error;
mod skins;
mod users; mod users;
use skins::{gloves, knife, weapons};
use users::{login, logout, me, reload, update}; use users::{login, logout, me, reload, update};
#[tokio::main] #[tokio::main]
@@ -36,6 +38,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
.route("/logout", get(logout)) .route("/logout", get(logout))
.route("/update", post(update)) .route("/update", post(update))
.route("/reload", get(reload)) .route("/reload", get(reload))
.route("/weapons", get(weapons))
.route("/knife", get(knife))
.route("/gloves", get(gloves))
.layer( .layer(
CorsLayer::new() CorsLayer::new()
.allow_origin("http://localhost:5173".parse::<HeaderValue>().unwrap()) .allow_origin("http://localhost:5173".parse::<HeaderValue>().unwrap())

107
src/skins.rs Normal file
View File

@@ -0,0 +1,107 @@
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;
use crate::error::AppError;
#[derive(Deserialize, Serialize)]
pub struct Weapon {
id: Uuid,
name: String,
display: String,
def_index: i32,
category: String,
team: i32,
}
#[derive(Deserialize, Serialize)]
pub struct WeaponInfo {
id: Uuid,
name: String,
paint_index: i32,
color: String,
}
#[axum::debug_handler]
pub async fn weapons(State(pool): State<PgPool>) -> Result<Json<Vec<Weapon>>, AppError> {
let weapons = query_as!(Weapon, "SELECT * FROM weapons")
.fetch_all(&pool)
.await?;
Ok(Json(weapons))
}
#[derive(Deserialize, Serialize)]
pub struct TeamQuery {
team: String,
}
pub async fn knife(
State(pool): State<PgPool>,
session: Session,
Query(team): Query<TeamQuery>,
) -> Result<Json<WeaponInfo>, AppError> {
if let Some(uuid) = session.get::<Uuid>("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(),
name: info.name,
paint_index: 0,
color: info.color
}}
};
Ok(Json(knife))
} else {
Err(AppError::Unauthorised)
}
}
pub async fn gloves(
State(pool): State<PgPool>,
session: Session,
Query(team): Query<TeamQuery>,
) -> Result<Json<WeaponInfo>, AppError> {
if let Some(uuid) = session.get::<Uuid>("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))
} else {
Err(AppError::Unauthorised)
}
}