Skip to content

Commit

Permalink
Add parent_commands to Context
Browse files Browse the repository at this point in the history
  • Loading branch information
kangalio committed Nov 1, 2022
1 parent f85b3ce commit cf61765
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 11 deletions.
30 changes: 24 additions & 6 deletions src/dispatch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,17 @@ pub async fn dispatch_event<U: Send + Sync, E>(
match event {
crate::Event::Message { new_message } => {
let invocation_data = tokio::sync::Mutex::new(Box::new(()) as _);
let mut parent_commands = Vec::new();
let trigger = crate::MessageDispatchTrigger::MessageCreate;
if let Err(error) =
prefix::dispatch_message(framework, ctx, new_message, trigger, &invocation_data)
.await
if let Err(error) = prefix::dispatch_message(
framework,
ctx,
new_message,
trigger,
&invocation_data,
&mut parent_commands,
)
.await
{
error.handle(framework.options).await;
}
Expand All @@ -77,13 +84,20 @@ pub async fn dispatch_event<U: Send + Sync, E>(

if let Some((msg, previously_tracked)) = msg {
let invocation_data = tokio::sync::Mutex::new(Box::new(()) as _);
let mut parent_commands = Vec::new();
let trigger = match previously_tracked {
true => crate::MessageDispatchTrigger::MessageEditFromInvalid,
false => crate::MessageDispatchTrigger::MessageEdit,
};
if let Err(error) =
prefix::dispatch_message(framework, ctx, &msg, trigger, &invocation_data)
.await
if let Err(error) = prefix::dispatch_message(
framework,
ctx,
&msg,
trigger,
&invocation_data,
&mut parent_commands,
)
.await
{
error.handle(framework.options).await;
}
Expand All @@ -94,12 +108,14 @@ pub async fn dispatch_event<U: Send + Sync, E>(
interaction: serenity::Interaction::ApplicationCommand(interaction),
} => {
let invocation_data = tokio::sync::Mutex::new(Box::new(()) as _);
let mut parent_commands = Vec::new();
if let Err(error) = slash::dispatch_interaction(
framework,
ctx,
interaction,
&std::sync::atomic::AtomicBool::new(false),
&invocation_data,
&mut parent_commands,
)
.await
{
Expand All @@ -110,12 +126,14 @@ pub async fn dispatch_event<U: Send + Sync, E>(
interaction: serenity::Interaction::Autocomplete(interaction),
} => {
let invocation_data = tokio::sync::Mutex::new(Box::new(()) as _);
let mut parent_commands = Vec::new();
if let Err(error) = slash::dispatch_autocomplete(
framework,
ctx,
interaction,
&std::sync::atomic::AtomicBool::new(false),
&invocation_data,
&mut parent_commands,
)
.await
{
Expand Down
30 changes: 25 additions & 5 deletions src/dispatch/prefix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ pub fn find_command<'a, U, E>(
commands: &'a [crate::Command<U, E>],
remaining_message: &'a str,
case_insensitive: bool,
parent_commands: &mut Vec<&'a crate::Command<U, E>>,
) -> Option<(&'a crate::Command<U, E>, &'a str, &'a str)>
where
U: Send + Sync,
Expand All @@ -157,12 +158,18 @@ where
continue;
}

parent_commands.push(command);
return Some(
find_command(&command.subcommands, remaining_message, case_insensitive).unwrap_or((
command,
command_name,
find_command(
&command.subcommands,
remaining_message,
)),
case_insensitive,
parent_commands,
)
.unwrap_or_else(|| {
parent_commands.pop();
(command, command_name, remaining_message)
}),
);
}

Expand All @@ -176,8 +183,18 @@ pub async fn dispatch_message<'a, U: Send + Sync, E>(
msg: &'a serenity::Message,
trigger: crate::MessageDispatchTrigger,
invocation_data: &'a tokio::sync::Mutex<Box<dyn std::any::Any + Send + Sync>>,
parent_commands: &'a mut Vec<&'a crate::Command<U, E>>,
) -> Result<(), crate::FrameworkError<'a, U, E>> {
if let Some(ctx) = parse_invocation(framework, ctx, msg, trigger, invocation_data).await? {
if let Some(ctx) = parse_invocation(
framework,
ctx,
msg,
trigger,
invocation_data,
parent_commands,
)
.await?
{
run_invocation(ctx).await?;
}
Ok(())
Expand All @@ -191,6 +208,7 @@ pub async fn parse_invocation<'a, U: Send + Sync, E>(
msg: &'a serenity::Message,
trigger: crate::MessageDispatchTrigger,
invocation_data: &'a tokio::sync::Mutex<Box<dyn std::any::Any + Send + Sync>>,
parent_commands: &'a mut Vec<&'a crate::Command<U, E>>,
) -> Result<Option<crate::PrefixContext<'a, U, E>>, crate::FrameworkError<'a, U, E>> {
// Check if we're allowed to invoke from bot messages
if msg.author.bot && framework.options.prefix_options.ignore_bots {
Expand All @@ -214,6 +232,7 @@ pub async fn parse_invocation<'a, U: Send + Sync, E>(
&framework.options.commands,
msg_content,
framework.options.prefix_options.case_insensitive_commands,
parent_commands,
)
.ok_or(crate::FrameworkError::UnknownCommand {
ctx,
Expand All @@ -238,6 +257,7 @@ pub async fn parse_invocation<'a, U: Send + Sync, E>(
args,
framework,
data: framework.user_data().await,
parent_commands,
command,
invocation_data,
trigger,
Expand Down
12 changes: 12 additions & 0 deletions src/dispatch/slash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ fn find_matching_command<'a, 'b, U, E>(
interaction_name: &str,
interaction_options: &'b [serenity::CommandDataOption],
commands: &'a [crate::Command<U, E>],
parent_commands: &mut Vec<&'a crate::Command<U, E>>,
) -> Option<(&'a crate::Command<U, E>, &'b [serenity::CommandDataOption])> {
commands.iter().find_map(|cmd| {
if interaction_name != cmd.name && Some(interaction_name) != cmd.context_menu_name {
Expand All @@ -17,10 +18,12 @@ fn find_matching_command<'a, 'b, U, E>(
option.kind == serenity::CommandOptionType::SubCommand
|| option.kind == serenity::CommandOptionType::SubCommandGroup
}) {
parent_commands.push(cmd);
find_matching_command(
&sub_interaction.name,
&sub_interaction.options,
&cmd.subcommands,
parent_commands,
)
} else {
Some((cmd, interaction_options))
Expand All @@ -36,11 +39,13 @@ pub async fn extract_command_and_run_checks<'a, U, E>(
interaction: crate::ApplicationCommandOrAutocompleteInteraction<'a>,
has_sent_initial_response: &'a std::sync::atomic::AtomicBool,
invocation_data: &'a tokio::sync::Mutex<Box<dyn std::any::Any + Send + Sync>>,
parent_commands: &'a mut Vec<&'a crate::Command<U, E>>,
) -> Result<crate::ApplicationContext<'a, U, E>, crate::FrameworkError<'a, U, E>> {
let search_result = find_matching_command(
&interaction.data().name,
&interaction.data().options,
&framework.options.commands,
parent_commands,
);
let (command, leaf_interaction_options) =
search_result.ok_or(crate::FrameworkError::UnknownInteraction {
Expand All @@ -56,6 +61,7 @@ pub async fn extract_command_and_run_checks<'a, U, E>(
interaction,
args: leaf_interaction_options,
command,
parent_commands,
has_sent_initial_response,
invocation_data,
__non_exhaustive: (),
Expand All @@ -75,13 +81,16 @@ pub async fn dispatch_interaction<'a, U, E>(
has_sent_initial_response: &'a std::sync::atomic::AtomicBool,
// Need to pass this in from outside because of lifetime issues
invocation_data: &'a tokio::sync::Mutex<Box<dyn std::any::Any + Send + Sync>>,
// Need to pass this in from outside because of lifetime issues
parent_commands: &'a mut Vec<&'a crate::Command<U, E>>,
) -> Result<(), crate::FrameworkError<'a, U, E>> {
let ctx = extract_command_and_run_checks(
framework,
ctx,
crate::ApplicationCommandOrAutocompleteInteraction::ApplicationCommand(interaction),
has_sent_initial_response,
invocation_data,
parent_commands,
)
.await?;

Expand Down Expand Up @@ -142,13 +151,16 @@ pub async fn dispatch_autocomplete<'a, U, E>(
has_sent_initial_response: &'a std::sync::atomic::AtomicBool,
// Need to pass this in from outside because of lifetime issues
invocation_data: &'a tokio::sync::Mutex<Box<dyn std::any::Any + Send + Sync>>,
// Need to pass this in from outside because of lifetime issues
parent_commands: &'a mut Vec<&'a crate::Command<U, E>>,
) -> Result<(), crate::FrameworkError<'a, U, E>> {
let ctx = extract_command_and_run_checks(
framework,
ctx,
crate::ApplicationCommandOrAutocompleteInteraction::Autocomplete(interaction),
has_sent_initial_response,
invocation_data,
parent_commands,
)
.await?;

Expand Down
9 changes: 9 additions & 0 deletions src/structs/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,15 @@ impl<'a, U, E> Context<'a, U, E> {
}
}

/// If the invoked command was a subcommand, these are the parent commands, ordered top-level
/// downwards.
pub fn parent_commands(&self) -> &'a [&'a crate::Command<U, E>] {
match self {
Self::Prefix(x) => x.parent_commands,
Self::Application(x) => x.parent_commands,
}
}

/// Returns a reference to the command.
pub fn command(&self) -> &'a crate::Command<U, E> {
match self {
Expand Down
2 changes: 2 additions & 0 deletions src/structs/prefix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub struct PrefixContext<'a, U, E> {
/// Useful if you need the list of commands, for example for a custom help command
#[derivative(Debug = "ignore")]
pub framework: crate::FrameworkContext<'a, U, E>,
/// If the invoked command was a subcommand, these are the parent commands, ordered top down.
pub parent_commands: &'a [&'a crate::Command<U, E>],
/// The command object which is the current command
pub command: &'a crate::Command<U, E>,
/// Your custom user data
Expand Down
2 changes: 2 additions & 0 deletions src/structs/slash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ pub struct ApplicationContext<'a, U, E> {
/// Useful if you need the list of commands, for example for a custom help command
#[derivative(Debug = "ignore")]
pub framework: crate::FrameworkContext<'a, U, E>,
/// If the invoked command was a subcommand, these are the parent commands, ordered top down.
pub parent_commands: &'a [&'a crate::Command<U, E>],
/// The command object which is the current command
pub command: &'a crate::Command<U, E>,
/// Your custom user data
Expand Down

0 comments on commit cf61765

Please sign in to comment.