190 lines
5.8 KiB
Rust
190 lines
5.8 KiB
Rust
use actix_web::{get, post, put, delete, web, HttpResponse, HttpRequest, ResponseError};
|
|
use log::error;
|
|
use serde::{Serialize, Deserialize};
|
|
use siren::{GetResponse, Metadata, ServiceError};
|
|
|
|
use crate::db::spells::{QuerySpell, QueryFilters};
|
|
|
|
use super::{Spell, InsertSpell};
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
struct GetAllParams {
|
|
name: Option<String>,
|
|
like_name: Option<String>,
|
|
schools: Option<String>,
|
|
levels: Option<String>,
|
|
ritual: Option<bool>,
|
|
concentration: Option<bool>,
|
|
classes: Option<String>,
|
|
damage_inflict: Option<String>,
|
|
damage_resist: Option<String>,
|
|
conditions: Option<String>,
|
|
saving_throw: Option<String>,
|
|
attack_type: Option<String>,
|
|
limit: Option<i32>,
|
|
page: Option<i32>,
|
|
}
|
|
|
|
#[get("/spells")]
|
|
async fn get_all(req: HttpRequest) -> HttpResponse {
|
|
let params = match web::Query::<GetAllParams>::from_query(req.query_string()) {
|
|
Ok(params) => params,
|
|
Err(err) => return ResponseError::error_response(&ServiceError {
|
|
status: 422,
|
|
message: err.to_string()
|
|
})
|
|
};
|
|
let mut filters = QueryFilters::default();
|
|
filters.by_name = params.name.clone();
|
|
filters.like_name = params.like_name.clone();
|
|
filters.by_schools = match ¶ms.schools {
|
|
Some(schools) => Some(schools.split(",").map(|s| s.to_string()).collect()),
|
|
None => None
|
|
};
|
|
filters.by_levels = match ¶ms.levels {
|
|
Some(levels) => Some(levels.split(",").map(|s| match s.to_string().parse::<i32>() {
|
|
Ok(level) => level,
|
|
Err(_) => 0
|
|
}).collect()),
|
|
None => None
|
|
};
|
|
filters.by_ritual = params.ritual;
|
|
filters.by_concentration = params.concentration;
|
|
filters.by_classes = match ¶ms.classes {
|
|
Some(classes) => Some(classes.split(",").map(|s| s.to_string()).collect()),
|
|
None => None
|
|
};
|
|
filters.by_damage_inflict = match ¶ms.damage_inflict {
|
|
Some(damage_inflict) => Some(damage_inflict.split(",").map(|s| s.to_string()).collect()),
|
|
None => None
|
|
};
|
|
filters.by_damage_resist = match ¶ms.damage_resist {
|
|
Some(damage_resist) => Some(damage_resist.split(",").map(|s| s.to_string()).collect()),
|
|
None => None
|
|
};
|
|
filters.by_conditions = match ¶ms.conditions {
|
|
Some(conditions) => Some(conditions.split(",").map(|s| s.to_string()).collect()),
|
|
None => None
|
|
};
|
|
filters.by_saving_throw = match ¶ms.saving_throw {
|
|
Some(saving_throw) => Some(saving_throw.split(",").map(|s| s.to_string()).collect()),
|
|
None => None
|
|
};
|
|
filters.by_attack_type = match ¶ms.attack_type {
|
|
Some(attack_type) => Some(attack_type.split(",").map(|s| s.to_string()).collect()),
|
|
None => None
|
|
};
|
|
// Limit must be between 1 and 100
|
|
let limit = std::cmp::min(std::cmp::max(params.limit.unwrap_or(100), 1), 100);
|
|
let total_count = QuerySpell::get_count(&filters).unwrap();
|
|
let max_page = std::cmp::max((total_count as f64 / limit as f64).ceil() as i32, 1);
|
|
// Page must be between 1 and max_page
|
|
let page = std::cmp::min(std::cmp::max(params.page.unwrap_or(1), 1), max_page);
|
|
|
|
match web::block(move || QuerySpell::get_all(&filters, limit, page)).await.unwrap() {
|
|
Ok(spells) => {
|
|
let mut response: Vec<Spell> = Vec::new();
|
|
for query_spell in spells {
|
|
let id = query_spell.id;
|
|
let mut spell = Spell::from(query_spell);
|
|
spell.id = Some(id);
|
|
response.push(spell);
|
|
}
|
|
HttpResponse::Ok().json(GetResponse {
|
|
data: response,
|
|
metadata: Some(Metadata {
|
|
total: total_count as i32,
|
|
limit,
|
|
page,
|
|
pages: max_page
|
|
})
|
|
})
|
|
},
|
|
Err(err) => {
|
|
error!("{:?}", err.message);
|
|
ResponseError::error_response(&err)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[get("/spells/{id}")]
|
|
async fn get_by_id(id: web::Path<String>) -> HttpResponse {
|
|
let id = match id.parse::<i32>() {
|
|
Ok(id) => id,
|
|
Err(err) => return ResponseError::error_response(&ServiceError {
|
|
status: 422,
|
|
message: err.to_string()
|
|
})
|
|
};
|
|
match web::block(move || QuerySpell::get_by_id(id)).await.unwrap() {
|
|
Ok(query_spell) => {
|
|
let id = query_spell.id;
|
|
let mut spell = Spell::from(query_spell);
|
|
spell.id = Some(id);
|
|
HttpResponse::Ok().json(GetResponse {
|
|
data: spell,
|
|
metadata: None
|
|
})
|
|
},
|
|
Err(err) => {
|
|
error!("{:?}", err.message);
|
|
ResponseError::error_response(&err)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[post("/spells")]
|
|
async fn create(spell: web::Json<Spell>) -> HttpResponse {
|
|
match InsertSpell::insert(spell.into_inner().into()) {
|
|
Ok(spell) => HttpResponse::Created().json(Spell::from(spell)),
|
|
Err(err) => {
|
|
error!("{:?}", err.message);
|
|
ResponseError::error_response(&err)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[put("/spells/{id}")]
|
|
async fn update(id: web::Path<String>, spell: web::Json<Spell>) -> HttpResponse {
|
|
let id = match id.parse::<i32>() {
|
|
Ok(id) => id,
|
|
Err(err) => return ResponseError::error_response(&ServiceError {
|
|
status: 422,
|
|
message: err.to_string()
|
|
})
|
|
};
|
|
match web::block(move || InsertSpell::update(id, spell.into_inner().into())).await.unwrap() {
|
|
Ok(spell) => HttpResponse::Ok().json(Spell::from(spell)),
|
|
Err(err) => {
|
|
error!("{:?}", err.message);
|
|
ResponseError::error_response(&err)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[delete("/spells/{id}")]
|
|
async fn delete(id: web::Path<String>) -> HttpResponse {
|
|
let id = match id.parse::<i32>() {
|
|
Ok(id) => id,
|
|
Err(err) => return ResponseError::error_response(&ServiceError {
|
|
status: 422,
|
|
message: err.to_string()
|
|
})
|
|
};
|
|
match web::block(move || QuerySpell::delete(id)).await.unwrap() {
|
|
Ok(spell) => HttpResponse::Ok().json(Spell::from(spell)),
|
|
Err(err) => {
|
|
error!("{:?}", err.message);
|
|
ResponseError::error_response(&err)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn init_routes(config: &mut web::ServiceConfig) {
|
|
config.service(web::scope("dnd")
|
|
.service(get_all)
|
|
.service(get_by_id)
|
|
.service(create)
|
|
.service(update)
|
|
);
|
|
} |