189 lines
6.2 KiB
Rust
189 lines
6.2 KiB
Rust
use warp::{Filter, Reply, filters::BoxedFilter, http::Uri, Rejection};
|
|
use crate::app::{
|
|
State,
|
|
config::{CommandExecutor, Command, Cooldowns},
|
|
web::{
|
|
CustomRejection,
|
|
template::commands::{CommandsTemplate, AddCommandTemplate, EditCommandTemplate},
|
|
},
|
|
};
|
|
use std::{
|
|
collections::HashMap,
|
|
convert::Infallible,
|
|
sync::Arc,
|
|
};
|
|
use std::str::FromStr;
|
|
use chrono::Duration;
|
|
|
|
pub fn commands_routes(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
|
|
warp::get()
|
|
.and(
|
|
commands_get(Arc::clone(&state))
|
|
.or(commands_add_get())
|
|
.or(commands_edit_get(Arc::clone(&state)))
|
|
)
|
|
.or(warp::post().and(
|
|
commands_add_post(Arc::clone(&state))
|
|
.or(commands_delete_post(Arc::clone(&state)))
|
|
.or(commands_edit_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 get_command_from_body(mut form: HashMap<String, String>) -> Result<Command, Rejection> {
|
|
let form_get = try {
|
|
let name = form.remove("name")?;
|
|
let aliases = form.remove("aliases")?;
|
|
let cooldown = form.remove("cooldown").and_then(|t| if t.trim().is_empty() { None } else { Some(t) });
|
|
let gcd = form.remove("gcd").and_then(|t| if t.trim().is_empty() { None } else { Some(t) });
|
|
let kind = form.remove("type")?;
|
|
let script = form.remove("executor_data")?;
|
|
(name, aliases, cooldown, gcd, kind, script)
|
|
};
|
|
|
|
let (name, aliases, cooldown, gcd, kind, script) = match form_get {
|
|
Some(x) => x,
|
|
None => return Err(warp::reject::custom(CustomRejection::InvalidForm)),
|
|
};
|
|
|
|
let gcd = gcd
|
|
.and_then(|t| f64::from_str(&t).ok())
|
|
.map(|f| Duration::milliseconds((f * 1_000.0) as i64));
|
|
|
|
let cooldown = cooldown
|
|
.and_then(|t| f64::from_str(&t).ok())
|
|
.map(|f| Duration::milliseconds((f * 1_000.0) as i64));
|
|
|
|
let executor = match &*kind {
|
|
"Text" => CommandExecutor::Text(script),
|
|
"Rhai" => CommandExecutor::Rhai(script),
|
|
_ => return Err(warp::reject::custom(CustomRejection::InvalidForm)),
|
|
};
|
|
|
|
Ok(Command {
|
|
name,
|
|
executor,
|
|
aliases: aliases.split("\n").map(|x| x.trim().to_string()).filter(|x| !x.is_empty()).collect(),
|
|
cooldowns: Cooldowns {
|
|
global: gcd,
|
|
user: cooldown,
|
|
},
|
|
})
|
|
}
|
|
|
|
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 |form: HashMap<String, String>| {
|
|
let state = Arc::clone(&state);
|
|
async move {
|
|
let command = match get_command_from_body(form) {
|
|
Ok(c) => c,
|
|
Err(e) => return Err(e),
|
|
};
|
|
state.config.write().await.commands.push(command);
|
|
|
|
Ok(warp::redirect(Uri::from_static("/commands")))
|
|
}
|
|
})
|
|
.boxed()
|
|
}
|
|
|
|
fn commands_edit_get(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
|
|
warp::path("commands")
|
|
.and(warp::path("edit"))
|
|
.and(warp::path::param())
|
|
.and(warp::path::end())
|
|
.and_then(move |name: String| {
|
|
let state = Arc::clone(&state);
|
|
async move {
|
|
match state.config.read().await.commands
|
|
.iter()
|
|
.find(|command| command.name == name)
|
|
.cloned()
|
|
{
|
|
Some(command) => Ok(command),
|
|
None => Err(warp::reject::custom(CustomRejection::InvalidCommand)),
|
|
}
|
|
}
|
|
})
|
|
.map(|command: Command| EditCommandTemplate {
|
|
command,
|
|
})
|
|
.boxed()
|
|
}
|
|
|
|
fn commands_edit_post(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
|
|
warp::path("commands")
|
|
.and(warp::path("edit"))
|
|
.and(warp::path::end())
|
|
.and(warp::body::content_length_limit(1024 * 5))
|
|
.and(warp::body::form())
|
|
.and_then(move |form: HashMap<String, String>| {
|
|
let state = Arc::clone(&state);
|
|
async move {
|
|
let command = match get_command_from_body(form) {
|
|
Ok(c) => c,
|
|
Err(e) => return Err(e),
|
|
};
|
|
let mut config = state.config.write().await;
|
|
for existing in config.commands.iter_mut() {
|
|
if existing.name == &*command.name {
|
|
*existing = command;
|
|
break;
|
|
}
|
|
}
|
|
|
|
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()
|
|
}
|