use super::ListenerSession; use crate::DResult; use crate::db::DBPool; use ansi_macro::ansi; use phf::phf_map; use async_trait::async_trait; mod parsing; mod ignore; mod help; #[derive(Debug)] pub struct VerbContext<'l> { session: &'l ListenerSession, pool: &'l DBPool } pub enum CommandHandlingError { UserError(String), SystemError(Box) } use CommandHandlingError::*; #[async_trait] pub trait UserVerb { async fn handle(self: &Self, ctx: &VerbContext, verb: &str, remaining: &str) -> UResult<()>; } pub type UserVerbRef = &'static (dyn UserVerb + Sync + Send); pub type UResult = Result; impl From> for CommandHandlingError { fn from(input: Box) -> CommandHandlingError { SystemError(input) } } pub fn user_error(msg: String) -> UResult { Err(UserError(msg)) } type UserVerbRegistry = phf::Map<&'static str, UserVerbRef>; static ALWAYS_AVAILABLE_COMMANDS: UserVerbRegistry = phf_map! { "" => ignore::VERB, "help" => help::VERB }; pub async fn handle(session: &ListenerSession, msg: &str, pool: &DBPool) -> DResult<()> { let (cmd, params) = parsing::parse_command_name(msg); let handler_opt = ALWAYS_AVAILABLE_COMMANDS.get(cmd); match handler_opt { None => { pool.queue_for_session(session, ansi!( "That's not a command I know. Try help\r\n" ) ).await?; } Some(handler) => { match handler.handle(&VerbContext { session, pool }, cmd, params).await { Ok(()) => {} Err(UserError(err_msg)) => { pool.queue_for_session(session, &err_msg).await?; } Err(SystemError(e)) => Err(e)? } } } /* pool.queue_for_session(session, &format!(ansi!( "You hear an echo saying: {}\r\n" ), msg)).await?; */ Ok(()) }