use crate::commands::add_location::AddLocation; use crate::commands::find::FindCommand; use crate::commands::register::Register; use crate::context::Context; use crate::Result; use geoffrey_models::models::response::APIResponse; use geoffrey_models::models::CommandLevel; use serde::de::DeserializeOwned; use serde::Serialize; use std::sync::Arc; use warp::filters::BoxedFilter; use warp::Filter; use std::fmt::Debug; pub mod add_location; pub mod find; pub mod register; #[derive(Debug, Clone, PartialEq)] #[allow(clippy::upper_case_acronyms)] pub enum RequestType { POST, GET, } pub trait Command { type Req: Serialize + DeserializeOwned + Send + 'static + Debug; type Resp: Serialize + DeserializeOwned + Send; fn command_name() -> String; fn request_type() -> RequestType; fn command_level() -> CommandLevel; fn run_command(ctx: Arc, req: Self::Req) -> Result; } #[allow(clippy::needless_return)] pub fn create_command_filter(ctx: Arc) -> BoxedFilter<(impl warp::Reply,)> { let filter = warp::path(T::command_name()) .and(warp::any().map(move || ctx.clone())) .and(warp::body::json()) .map(|ctx: Arc, req: T::Req| { log::info!("Running command {}", T::command_name()); log::debug!("Request: {:?}", req); let reply = T::run_command(ctx, req); if let Ok(reply) = reply { log::debug!("Successfully processed command"); warp::reply::json(&APIResponse::Response::(reply)) } else { let e = reply.err().unwrap(); log::warn!("Got error when processing command: {:?}", e); warp::reply::json(&APIResponse::::Error(e)) } }); if T::request_type() == RequestType::POST { return filter.and(warp::post()).boxed(); } else { return filter.and(warp::get()).boxed(); } } pub fn command_filter( ctx: Arc, ) -> impl Filter + Clone { warp::path("command").and( create_command_filter::(ctx.clone()) .or(create_command_filter::(ctx.clone())) .or(create_command_filter::(ctx)), ) }