clemsbot/src/app/web/route/commands.rs

119 lines
3.8 KiB
Rust

use warp::{
Filter, Reply,
filters::BoxedFilter,
http::Uri,
};
use crate::app::{
State,
config::{CommandExecutor, Command, Cooldowns},
web::{
CustomRejection,
template::commands::{CommandsTemplate, AddCommandTemplate},
},
};
use std::{
collections::HashMap,
convert::Infallible,
sync::Arc,
};
pub fn commands_routes(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
warp::get()
.and(
commands_get(Arc::clone(&state))
.or(commands_add_get())
)
.or(warp::post().and(
commands_add_post(Arc::clone(&state))
.or(commands_delete_post(Arc::clone(&state)))
))
.boxed()
}
fn commands_get(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
warp::path("commands")
.and(warp::path::end())
.and_then(move || {
let state = Arc::clone(&state);
async move {
Result::<CommandsTemplate, Infallible>::Ok(CommandsTemplate {
commands: state.config.read().await.commands.clone(),
})
}
})
.boxed()
}
fn commands_add_get() -> BoxedFilter<(impl Reply, )> {
warp::path("commands")
.and(warp::path("add"))
.and(warp::path::end())
.map(|| AddCommandTemplate)
.boxed()
}
fn commands_add_post(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
warp::path("commands")
.and(warp::path("add"))
.and(warp::path::end())
.and(warp::body::content_length_limit(1024 * 5))
.and(warp::body::form())
.and_then(move |mut form: HashMap<String, String>| {
let state = Arc::clone(&state);
async move {
let form_get = try {
let name = form.remove("name")?;
let aliases = form.remove("aliases")?;
let kind = form.remove("type")?;
let script = form.remove("executor_data")?;
(name, aliases, kind, script)
};
let (name, aliases, kind, script) = match form_get {
Some(x) => x,
None => return Err(warp::reject::custom(CustomRejection::InvalidForm)),
};
let executor = match &*kind {
"Text" => CommandExecutor::Text(script),
"Rhai" => CommandExecutor::Rhai(script),
_ => return Err(warp::reject::custom(CustomRejection::InvalidForm)),
};
let command = Command {
name,
executor,
aliases: aliases.split("\n").map(|x| x.trim().to_string()).filter(|x| !x.is_empty()).collect(),
cooldowns: Cooldowns::default(),
};
state.config.write().await.commands.push(command);
Ok(warp::redirect(Uri::from_static("/commands")))
}
})
.boxed()
}
fn commands_delete_post(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
warp::path("commands")
.and(warp::path("delete"))
.and(warp::path::end())
.and(warp::body::content_length_limit(1024 * 5))
.and(warp::body::form())
.and_then(move |mut form: HashMap<String, String>| {
let state = Arc::clone(&state);
async move {
let name = match form.remove("name") {
Some(n) => n,
None => return Err(warp::reject::custom(CustomRejection::InvalidForm)),
};
state.config.write().await.commands.drain_filter(|command| command.name == name);
Ok(warp::redirect(Uri::from_static("/commands")))
}
})
.boxed()
}