serenity-rs / poise

Discord bot command framework for serenity, with advanced features like edit tracking and flexible argument parsing
MIT License
653 stars 114 forks source link

is there any way to compare ArgumentParse error? #159

Closed sadorowo closed 1 year ago

sadorowo commented 1 year ago

https://github.com/serenity-rs/poise/blob/e5ffe6bd48ec7a49fd983c5d821ffc0e035251b9/src/prefix_argument/mod.rs#L84

is there any way to check for these errors in `on_error afaik I can't compare these errors in match:

on_error: |error| {
   Box::pin(async move {
      match error {
         FrameworkError::ArgumentParse { ctx, error, input, .. } => {
            // use 'match error {...}' here is not possible, because error is 'Box<dyn std::error::Error + Send + Sync>' and I can't compare it to e.g. poise::InvalidChoice :/

            /*
            match error {

            }
            */
         }
      }
   })
}

am I doing sth wrong?

sadorowo commented 1 year ago

I discovered solution, closing

kangalio commented 1 year ago

Yeah, you can use the downcasting methods on Box<dyn Error>: https://doc.rust-lang.org/std/error/trait.Error.html#implementations

sadorowo commented 1 year ago

Yeah, you can use the downcasting methods on Box<dyn Error>: https://doc.rust-lang.org/std/error/trait.Error.html#implementations

All is working until I have to use ChannelParseError or RoleParseError. error.is::() returns false even if error is enum member of e.g. RoleParseError (for example RoleParseError::NotFoundOrMalformed)

if error.is::<RoleParseError>() {
   // this won't execute
   // but error.to_string() returns "Role not found or unknown format", this is the return of Display trait for RoleParseError
}

My IDE shows that there are 2 implementations of these types, maybe this is the issue

kangalio commented 1 year ago

Can't reproduce

Error handler:

on_error: |error| {
    Box::pin(async move {
        match error {
            poise::FrameworkError::ArgumentParse { error, .. } => {
                if let Some(error) = error.downcast_ref::<serenity::RoleParseError>() {
                    println!("Found a RoleParseError: {:?}", error);
                } else {
                    println!("Not a RoleParseError :(");
                }
            }
            other => poise::builtins::on_error(other).await.unwrap(),
        }
    })
},

Test command:

#[poise::command(prefix_command)]
pub async fn role(ctx: Context<'_>, role: serenity::Role) -> Result<(), Error> {
    ctx.say(format!("yes this is indeed a role: {:?}", role))
        .await?;
    Ok(())
}

Command invocation in Discord:

~role booboo

Console output:

Found a RoleParseError: NotFoundOrMalformed
sadorowo commented 1 year ago

for me it's not working.

use poise::serenity_prelude as serenity;

handler:

on_error: |error| {
  Box::pin(async move {
      match error {
          FrameworkError::ArgumentParse {error, .. } => {
              if let Some(error) = error.downcast_ref::<serenity::RoleParseError>() {
                  println!("working");
              } else {
                  println!("not working");
              }
          }

          // ...
     }
  })
}

output:

not working

command:

.role abcdef
sadorowo commented 1 year ago

can u provide your Cargo.toml or something?

kangalio commented 1 year ago

I'm testing directly within the poise repo (i.e. latest crates.io release), so there's not really a Cargo.toml I can give you.

Can you show your command where the error is triggered?

sadorowo commented 1 year ago
use crate::commands::{Context, Error};
/*
^^^
struct Data {...}
pub type Context<'a> = poise::Context<'a, Data, Error>;
pub type Error = Box<(dyn std::error::Error + Send + Sync + 'static)>;
*/

use poise::serenity_prelude::Role;

#[poise::command(
slash_command,
prefix_command,
category = "info"
)]
pub async fn role(
    ctx: Context<'_>,
    // if I remove the #[rest] here, issue persists
    #[rest]
    role: Role,
) -> Result<(), Error> {
    // ...
}
kangalio commented 1 year ago

My IDE shows that there are 2 implementations of these types, maybe this is the issue

Oh wait, this may be important. Maybe you're running two different versions of serenity in parallel. Can you show your Cargo.toml?

sadorowo commented 1 year ago

no problem

[package]
name = "zine"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.28.0", features = ["time", "macros", "rt-multi-thread"] }
serde = { version = "1.0.160", features = ["derive"] }
serde_json = "1.0.96"
sysinfo = "0.28.4"
dotenv = "0.15.0"
mongodb = "2.5.0"
poise = "0.5.4"
toml = "0.7.3"
kangalio commented 1 year ago

Okay.. I see no problem there. Can you send a screenshot of the IDE errors you mentioned?

sadorowo commented 1 year ago

My IDE shows that there are 2 implementations of these types, maybe this is the issue

Oh wait, this may be important. Maybe you're running two different versions of serenity in parallel. Can you show your Cargo.toml?

RoleParseError implementations are in serenity::model::guild and serenity::utils::argument_convert crates. argument_convert crate is private but items from here are exported to the parent scope

sadorowo commented 1 year ago

Okay.. I see no problem there. Can you send a screenshot of the IDE errors you mentioned?

Zrzut ekranu 2023-05-3 o 22 05 19 Zrzut ekranu 2023-05-3 o 22 06 35

kangalio commented 1 year ago

Oh jeez there's multiple RoleParseError's and ChannelParseError's. That's kinda stupid on serenity's side lol

Okay but in the meantime you should import the same one throughout your project (the one from argument_convert). You currently seem to mix the two types throughout the project, which causes incompatibility

sadorowo commented 1 year ago

i can't import type from argument_convert, bc it is private. i can't import it from parent module too. i can only import this type directly from poise::serenity_prelude, which causes incompatibility as you said

kangalio commented 1 year ago

Oh wow I have no idea how that happened. Screenshot_20230503_222350 For some reason RoleParseError and ChannelParseError have been knocked out, just because another type of the same value exists somewhere else. I'll create a serenity issue for this

sadorowo commented 1 year ago

thanks for creating issue, i also saw that Role- & Channel- ParseErrors aren't showing up in docs but I didn't thought that this may be bug

kangalio commented 1 year ago

Closing in favor of the serenity issue