//! Basic command wrappers. use std::future::Future; use async_trait::async_trait; use euphoxide::api::Message; use super::{Command, Context, Info, Propagate}; /// Rewrite or hide command info. pub struct WithInfo { pub inner: C, pub trigger: Option>, pub description: Option>, } impl WithInfo { pub fn new(inner: C) -> Self { Self { inner, trigger: None, description: None, } } pub fn hidden(inner: C) -> Self { Self::new(inner) .with_trigger_hidden() .with_description_hidden() } pub fn with_trigger(mut self, trigger: impl ToString) -> Self { self.trigger = Some(Some(trigger.to_string())); self } pub fn with_trigger_hidden(mut self) -> Self { self.trigger = Some(None); self } pub fn with_description(mut self, description: impl ToString) -> Self { self.description = Some(Some(description.to_string())); self } pub fn with_description_hidden(mut self) -> Self { self.description = Some(None); self } } #[async_trait] impl Command for WithInfo where C: Command + Sync, { fn info(&self, ctx: &Context) -> Info { let info = self.inner.info(ctx); Info { trigger: self.trigger.clone().unwrap_or(info.trigger), description: self.description.clone().unwrap_or(info.description), } } async fn execute(&self, arg: &str, msg: &Message, ctx: &Context) -> Result { self.inner.execute(arg, msg, ctx).await } } pub struct Prefixed { pub prefix: String, pub inner: C, } impl Prefixed { pub fn new(prefix: S, inner: C) -> Self { Self { prefix: prefix.to_string(), inner, } } } #[async_trait] impl Command for Prefixed where C: Command + Sync, { fn info(&self, ctx: &Context) -> Info { self.inner.info(ctx).with_prepended_trigger(&self.prefix) } async fn execute(&self, arg: &str, msg: &Message, ctx: &Context) -> Result { if let Some(rest) = arg.trim_start().strip_prefix(&self.prefix) { self.inner.execute(rest, msg, ctx).await } else { Ok(Propagate::Yes) } } } // Black type magic, thanks a lot to https://github.com/kpreid and the // async_fn_traits crate! // TODO Simplify all this once AsyncFn becomes stable pub trait HandlerFn<'a0, 'a1, 'a2, E>: Fn(&'a0 str, &'a1 Message, &'a2 Context) -> Self::Future where E: 'a2, { type Future: Future> + Send; } impl<'a0, 'a1, 'a2, E, F, Fut> HandlerFn<'a0, 'a1, 'a2, E> for F where E: 'a2, F: Fn(&'a0 str, &'a1 Message, &'a2 Context) -> Fut + ?Sized, Fut: Future> + Send, { type Future = Fut; } pub struct FromHandler(pub F); impl FromHandler { pub fn new(f: F) -> Self { Self(f) } } #[async_trait] impl Command for FromHandler where F: for<'a0, 'a1, 'a2> HandlerFn<'a0, 'a1, 'a2, E> + Sync, { async fn execute(&self, arg: &str, msg: &Message, ctx: &Context) -> Result { (self.0)(arg, msg, ctx).await } }