Skip to content

Commit

Permalink
Add the name of the command to the Dispatch error hook (#1344)
Browse files Browse the repository at this point in the history
Closes #876.

The dispatch error hook now receives a fourth parameter with the command name.
  • Loading branch information
kangalio authored and arqunis committed Mar 15, 2022
1 parent afb3c37 commit c2130a8
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 23 deletions.
3 changes: 2 additions & 1 deletion examples/e05_command_framework/src/main.rs
Expand Up @@ -187,7 +187,7 @@ async fn delay_action(ctx: &Context, msg: &Message) {
}

#[hook]
async fn dispatch_error(ctx: &Context, msg: &Message, error: DispatchError) {
async fn dispatch_error(ctx: &Context, msg: &Message, error: DispatchError, _command_name: &str) {
if let DispatchError::Ratelimited(info) = error {
// We notify them only once.
if info.is_first_try {
Expand All @@ -206,6 +206,7 @@ fn _dispatch_error_no_macro<'fut>(
ctx: &'fut mut Context,
msg: &'fut Message,
error: DispatchError,
_command_name: &str,
) -> BoxFuture<'fut, ()> {
async move {
if let DispatchError::Ratelimited(info) = error {
Expand Down
23 changes: 16 additions & 7 deletions src/framework/standard/mod.rs
Expand Up @@ -51,7 +51,7 @@ pub enum DispatchError {
/// When the command caller has exceeded a ratelimit bucket.
Ratelimited(RateLimitInfo),
/// When the requested command is disabled in bot configuration.
CommandDisabled(String),
CommandDisabled,
/// When the user is blocked in bot configuration.
BlockedUser,
/// When the guild or its owner is blocked in bot configuration.
Expand All @@ -77,7 +77,7 @@ pub enum DispatchError {
}

type DispatchHook =
for<'fut> fn(&'fut Context, &'fut Message, DispatchError) -> BoxFuture<'fut, ()>;
for<'fut> fn(&'fut Context, &'fut Message, DispatchError, &'fut str) -> BoxFuture<'fut, ()>;
type BeforeHook = for<'fut> fn(&'fut Context, &'fut Message, &'fut str) -> BoxFuture<'fut, bool>;
type AfterHook = for<'fut> fn(
&'fut Context,
Expand Down Expand Up @@ -414,7 +414,12 @@ impl StandardFramework {
/// use serenity::framework::StandardFramework;
///
/// #[hook]
/// async fn dispatch_error_hook(context: &Context, msg: &Message, error: DispatchError) {
/// async fn dispatch_error_hook(
/// context: &Context,
/// msg: &Message,
/// error: DispatchError,
/// command_name: &str,
/// ) {
/// match error {
/// DispatchError::NotEnoughArguments {
/// min,
Expand All @@ -432,7 +437,7 @@ impl StandardFramework {
///
/// let _ = msg.channel_id.say(&context, &s).await;
/// },
/// _ => println!("Unhandled dispatch error."),
/// _ => println!("Unhandled dispatch error in {}.", command_name),
/// }
/// }
///
Expand Down Expand Up @@ -654,9 +659,12 @@ impl Framework for StandardFramework {

return;
},
Err(ParseError::Dispatch(error)) => {
Err(ParseError::Dispatch {
error,
command_name,
}) => {
if let Some(dispatch) = &self.dispatch {
dispatch(&mut ctx, &msg, error).await;
dispatch(&mut ctx, &msg, error, &command_name).await;
}

return;
Expand Down Expand Up @@ -725,7 +733,8 @@ impl Framework for StandardFramework {
self.should_fail(&ctx, &msg, &mut args, command.options, group.options).await
{
if let Some(dispatch) = &self.dispatch {
dispatch(&mut ctx, &msg, error).await;
let command_name = command.options.names[0];
dispatch(&mut ctx, &msg, error, command_name).await;
}

return;
Expand Down
59 changes: 44 additions & 15 deletions src/framework/standard/parse/mod.rs
Expand Up @@ -337,7 +337,10 @@ fn parse_cmd<'a>(
try_parse(stream, map, config.by_space, |s| to_lowercase(config, s).into_owned());

if config.disabled_commands.contains(&n) {
return Err(ParseError::Dispatch(DispatchError::CommandDisabled(n)));
return Err(ParseError::Dispatch {
error: DispatchError::CommandDisabled,
command_name: n,
});
}

if let Some((cmd, map)) = r {
Expand All @@ -347,7 +350,12 @@ fn parse_cmd<'a>(
stream.take_while_char(|c| c.is_whitespace());
}

check_discrepancy(ctx, msg, config, &cmd.options).await?;
check_discrepancy(ctx, msg, config, &cmd.options).await.map_err(|e| {
ParseError::Dispatch {
error: e,
command_name: n,
}
})?;

if map.is_empty() {
return Ok(cmd);
Expand Down Expand Up @@ -381,7 +389,12 @@ fn parse_group<'a>(
stream.take_while_char(|c| c.is_whitespace());
}

check_discrepancy(ctx, msg, config, &group.options).await?;
check_discrepancy(ctx, msg, config, &group.options).await.map_err(|e| {
ParseError::Dispatch {
error: e,
command_name: n,
}
})?;

if map.is_empty() {
return Ok((group, commands));
Expand Down Expand Up @@ -443,14 +456,7 @@ async fn handle_group<'a>(
#[derive(Debug)]
pub enum ParseError {
UnrecognisedCommand(Option<String>),
Dispatch(DispatchError),
}

impl From<DispatchError> for ParseError {
#[inline]
fn from(err: DispatchError) -> Self {
ParseError::Dispatch(err)
}
Dispatch { error: DispatchError, command_name: String },
}

fn is_unrecognised<T>(res: &Result<T, ParseError>) -> bool {
Expand Down Expand Up @@ -509,17 +515,40 @@ pub async fn command(
Map::Prefixless(subgroups, commands) => {
is_prefixless = true;

fn command_name_if_recognised(res: &Result<Invoke, ParseError>) -> Option<&str> {
match res {
Ok(Invoke::Command {
command, ..
}) => Some(command.options.names[0]),
Ok(Invoke::Help(name)) => Some(name), /* unreachable, but fallback just in case */
Err(ParseError::UnrecognisedCommand(_)) => None,
Err(ParseError::Dispatch {
command_name, ..
}) => Some(command_name),
}
}

let res = handle_group(stream, ctx, msg, config, subgroups).await;

if !is_unrecognised(&res) {
check_discrepancy(ctx, msg, config, &group.options).await?;
if let Some(command_name) = command_name_if_recognised(&res) {
check_discrepancy(ctx, msg, config, &group.options).await.map_err(|e| {
ParseError::Dispatch {
error: e,
command_name: command_name.to_owned(),
}
})?;
return res;
}

let res = handle_command(stream, ctx, msg, config, commands, group).await;

if !is_unrecognised(&res) {
check_discrepancy(ctx, msg, config, &group.options).await?;
if let Some(command_name) = command_name_if_recognised(&res) {
check_discrepancy(ctx, msg, config, &group.options).await.map_err(|e| {
ParseError::Dispatch {
error: e,
command_name: command_name.to_owned(),
}
})?;
return res;
}

Expand Down

0 comments on commit c2130a8

Please sign in to comment.