mattermost-bot 0.3.1

Create a Mattermost bot that listens and responds to commands
Documentation
use crate::response::IntoResponse;
use std::fmt::Debug;

pub trait IntoCommand<Args> {
    fn into_command(self) -> Command;
}

impl<H> IntoCommand<()> for H
where
    H: CommandHandler<()> + Send + Sync + 'static,
{
    fn into_command(self) -> Command {
        Command::NoArgs(Box::new(self))
    }
}

impl<H> IntoCommand<String> for H
where
    H: CommandHandler<String> + Send + Sync + 'static,
{
    fn into_command(self) -> Command {
        Command::OneArg(Box::new(self))
    }
}

#[async_trait::async_trait]
pub trait CommandHandler<Args> {
    async fn call(&self, args: Args) -> String;
}

#[async_trait::async_trait]
impl<F, Fut, Res> CommandHandler<()> for F
where
    F: Fn() -> Fut + Sync,
    Fut: Future<Output = Res> + Send,
    Res: IntoResponse,
{
    async fn call(&self, _args: ()) -> String {
        self().await.into_response()
    }
}

#[async_trait::async_trait]
impl<F, Fut, Res> CommandHandler<String> for F
where
    F: Fn(String) -> Fut + Sync,
    Fut: Future<Output = Res> + Send,
    Res: IntoResponse,
{
    async fn call(&self, args: String) -> String {
        self(args).await.into_response()
    }
}

pub enum Command {
    NoArgs(Box<dyn CommandHandler<()> + Send + Sync>),
    OneArg(Box<dyn CommandHandler<String> + Send + Sync>),
}

impl Debug for Command {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::NoArgs(_) => f
                .debug_tuple("NoArgs")
                .field(&"<CommandHandler<()> -> String")
                .finish(),
            Self::OneArg(_) => f
                .debug_tuple("OneArg")
                .field(&"<CommandHandler<String> -> String")
                .finish(),
        }
    }
}