diff --git a/src/bot/command.rs b/src/bot/command.rs index 749cdac..3032f05 100644 --- a/src/bot/command.rs +++ b/src/bot/command.rs @@ -76,10 +76,10 @@ impl Context { } #[async_trait] -pub trait Command { +pub trait Command { fn description(&self) -> Option { None } - async fn execute(&self, arg: &str, msg: &Message, ctx: &Context, bot: &mut B); + async fn execute(&self, arg: &str, msg: &Message, ctx: &Context, bot: &mut B) -> Result<(), E>; } diff --git a/src/bot/command/clap.rs b/src/bot/command/clap.rs index 975f2c6..b828e96 100644 --- a/src/bot/command/clap.rs +++ b/src/bot/command/clap.rs @@ -2,14 +2,21 @@ use async_trait::async_trait; use clap::{CommandFactory, Parser}; use crate::api::Message; +use crate::conn; use super::{Command, Context}; #[async_trait] -pub trait ClapCommand { +pub trait ClapCommand { type Args; - async fn execute(&self, args: Self::Args, msg: &Message, ctx: &Context, bot: &mut B); + async fn execute( + &self, + args: Self::Args, + msg: &Message, + ctx: &Context, + bot: &mut B, + ) -> Result<(), E>; } /// Parse bash-like quoted arguments separated by whitespace. @@ -92,22 +99,23 @@ fn parse_quoted_args(text: &str) -> Result, &'static str> { pub struct Clap(pub C); #[async_trait] -impl Command for Clap +impl Command for Clap where B: Send, - C: ClapCommand + Send + Sync, + E: From, + C: ClapCommand + Send + Sync, C::Args: Parser + Send, { fn description(&self) -> Option { C::Args::command().get_about().map(|s| format!("{s}")) } - async fn execute(&self, arg: &str, msg: &Message, ctx: &Context, bot: &mut B) { + async fn execute(&self, arg: &str, msg: &Message, ctx: &Context, bot: &mut B) -> Result<(), E> { let mut args = match parse_quoted_args(arg) { Ok(args) => args, Err(err) => { - let _ = ctx.reply(msg.id, err); - return; + ctx.reply(msg.id, err).await?; + return Ok(()); } }; @@ -116,8 +124,8 @@ where let args = match C::Args::try_parse_from(args) { Ok(args) => args, Err(err) => { - let _ = ctx.reply(msg.id, format!("{}", err.render())); - return; + ctx.reply(msg.id, format!("{}", err.render())).await?; + return Ok(()); } }; diff --git a/src/bot/commands.rs b/src/bot/commands.rs index c33ff07..d477a09 100644 --- a/src/bot/commands.rs +++ b/src/bot/commands.rs @@ -46,18 +46,18 @@ pub struct CommandInfo { pub visible: bool, } -struct CommandWrapper { - command: Box>, +struct CommandWrapper { + command: Box>, visible: bool, } -pub struct Commands { - global: HashMap>, - general: HashMap>, - specific: HashMap>, +pub struct Commands { + global: HashMap>, + general: HashMap>, + specific: HashMap>, } -impl Commands { +impl Commands { /// Global commands always respond. They override any specific or general /// commands of the same name. /// @@ -65,7 +65,7 @@ impl Commands { pub fn global(mut self, name: S, command: C, visible: bool) -> Self where S: ToString, - C: Command + 'static, + C: Command + 'static, { let command = Box::new(command); let info = CommandWrapper { command, visible }; @@ -80,7 +80,7 @@ impl Commands { pub fn general(mut self, name: S, command: C, visible: bool) -> Self where S: ToString, - C: Command + 'static, + C: Command + 'static, { let command = Box::new(command); let info = CommandWrapper { command, visible }; @@ -92,7 +92,7 @@ impl Commands { pub fn specific(mut self, name: S, command: C, visible: bool) -> Self where S: ToString, - C: Command + 'static, + C: Command + 'static, { let command = Box::new(command); let info = CommandWrapper { command, visible }; @@ -149,20 +149,20 @@ impl Commands { packet: &ParsedPacket, snapshot: &Snapshot, bot: &mut B, - ) -> bool { + ) -> Result { let msg = match &packet.content { Ok(Data::SendEvent(SendEvent(msg))) => msg, - _ => return false, + _ => return Ok(false), }; let joined = match &snapshot.state { - conn::State::Joining(_) => return false, + conn::State::Joining(_) => return Ok(false), conn::State::Joined(joined) => joined.clone(), }; let (cmd_name, rest) = match parse_command(&msg.content) { Some(parsed) => parsed, - None => return false, + None => return Ok(false), }; let mut ctx = Context { @@ -175,8 +175,8 @@ impl Commands { if let Some(wrapper) = self.global.get(cmd_name) { ctx.kind = Kind::Global; - wrapper.command.execute(rest, msg, &ctx, bot).await; - return true; + wrapper.command.execute(rest, msg, &ctx, bot).await?; + return Ok(true); } if let Some((cmd_nick, rest)) = parse_specific(rest) { @@ -185,8 +185,8 @@ impl Commands { let cmd_nick_norm = normalize_specific_nick(cmd_nick); if nick_norm == cmd_nick_norm { ctx.kind = Kind::Specific; - wrapper.command.execute(rest, msg, &ctx, bot).await; - return true; + wrapper.command.execute(rest, msg, &ctx, bot).await?; + return Ok(true); } } @@ -196,16 +196,16 @@ impl Commands { // // To call a specific command with a mention as its first positional // argument, -- can be used. - return false; + return Ok(false); } if let Some(wrapper) = self.general.get(cmd_name) { ctx.kind = Kind::General; - wrapper.command.execute(rest, msg, &ctx, bot).await; - return true; + wrapper.command.execute(rest, msg, &ctx, bot).await?; + return Ok(true); } - false + Ok(false) } }