#[allow(unused_imports)] use crate::serenity::json::*;
#[allow(unused_imports)] use crate::serenity_prelude as serenity;
#[derive(Debug)]
pub enum SlashArgError {
#[non_exhaustive]
CommandStructureMismatch {
description: &'static str,
},
#[non_exhaustive]
Parse {
error: Box<dyn std::error::Error + Send + Sync>,
input: String,
},
#[non_exhaustive]
Invalid(
&'static str,
),
Http(serenity::Error),
#[doc(hidden)]
__NonExhaustive,
}
#[doc(hidden)]
impl SlashArgError {
pub fn new_command_structure_mismatch(description: &'static str) -> Self {
Self::CommandStructureMismatch { description }
}
pub fn to_framework_error<U, E>(
self,
ctx: crate::ApplicationContext<'_, U, E>,
) -> crate::FrameworkError<'_, U, E> {
match self {
Self::CommandStructureMismatch { description } => {
crate::FrameworkError::CommandStructureMismatch { ctx, description }
}
Self::Parse { error, input } => crate::FrameworkError::ArgumentParse {
ctx: ctx.into(),
error,
input: Some(input),
},
Self::Invalid(description) => crate::FrameworkError::ArgumentParse {
ctx: ctx.into(),
error: description.into(),
input: None,
},
Self::Http(error) => crate::FrameworkError::ArgumentParse {
ctx: ctx.into(),
error: error.into(),
input: None,
},
Self::__NonExhaustive => unreachable!(),
}
}
}
impl std::fmt::Display for SlashArgError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::CommandStructureMismatch { description } => {
write!(
f,
"Bot author did not register their commands correctly ({description})",
)
}
Self::Parse { error, input } => {
write!(f, "Failed to parse `{input}` as argument: {error}")
}
Self::Invalid(description) => {
write!(f, "You can't use this parameter here: {description}",)
}
Self::Http(error) => {
write!(
f,
"Error occurred while retrieving data from Discord: {error}",
)
}
Self::__NonExhaustive => unreachable!(),
}
}
}
impl std::error::Error for SlashArgError {
fn cause(&self) -> Option<&dyn std::error::Error> {
match self {
Self::Http(error) => Some(error),
Self::Parse { error, input: _ } => Some(&**error),
Self::Invalid { .. } | Self::CommandStructureMismatch { .. } => None,
Self::__NonExhaustive => unreachable!(),
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! _parse_slash {
($ctx:ident, $interaction:ident, $args:ident => $name:literal: INLINE_CHOICE $type:ty [$($index:literal: $value:literal),*]) => {
if let Some(arg) = $args.iter().find(|arg| arg.name == $name) {
let $crate::serenity_prelude::ResolvedValue::Integer(index) = arg.value else {
return Err($crate::SlashArgError::new_command_structure_mismatch("expected integer, as the index for an inline choice parameter"));
};
match index {
$( $index => $value, )*
_ => return Err($crate::SlashArgError::new_command_structure_mismatch("out of range index for inline choice parameter")),
}
} else {
return Err($crate::SlashArgError::new_command_structure_mismatch("a required argument is missing"));
}
};
($ctx:ident, $interaction:ident, $args:ident => $name:literal: Option<$type:ty $(,)*>) => {
if let Some(arg) = $args.iter().find(|arg| arg.name == $name) {
Some($crate::extract_slash_argument!($type, $ctx, $interaction, &arg.value)
.await?)
} else {
None
}
};
($ctx:ident, $interaction:ident, $args:ident => $name:literal: Vec<$type:ty $(,)*>) => {
match $crate::_parse_slash!($ctx, $interaction, $args => $name: Option<$type>) {
Some(value) => vec![value],
None => vec![],
}
};
($ctx:ident, $interaction:ident, $args:ident => $name:literal: FLAG) => {
$crate::_parse_slash!($ctx, $interaction, $args => $name: Option<bool>)
.unwrap_or(false)
};
($ctx:ident, $interaction:ident, $args:ident => $name:literal: $($type:tt)*) => {
$crate::_parse_slash!($ctx, $interaction, $args => $name: Option<$($type)*>)
.ok_or($crate::SlashArgError::new_command_structure_mismatch("a required argument is missing"))?
};
}
#[macro_export]
macro_rules! parse_slash_args {
($ctx:expr, $interaction:expr, $args:expr => $(
( $name:literal: $($type:tt)* )
),* $(,)? ) => {
async {
use $crate::SlashArgumentHack;
let (ctx, interaction, args) = ($ctx, $interaction, $args);
Ok::<_, $crate::SlashArgError>(( $(
$crate::_parse_slash!( ctx, interaction, args => $name: $($type)* ),
)* ))
}
};
}