Skip to content

Commit

Permalink
Remove content and prefix from PrefixContext
Browse files Browse the repository at this point in the history
  • Loading branch information
GnomedDev committed Jun 3, 2024
1 parent 7dd4904 commit cba2108
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 37 deletions.
5 changes: 2 additions & 3 deletions src/builtins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,9 @@ pub async fn on_error<U, E: std::fmt::Display + std::fmt::Debug>(
);
}
crate::FrameworkError::UnknownCommand {
msg_content,
prefix,
..
msg, content_start, ..
} => {
let (prefix, msg_content) = msg.content.split_at(content_start.into());
tracing::warn!(
"Recognized prefix `{}`, but didn't recognize command name in `{}`",
prefix,
Expand Down
48 changes: 27 additions & 21 deletions src/dispatch/prefix.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
//! Dispatches incoming messages and message edits onto framework commands

use std::convert::TryInto as _;

use crate::serenity_prelude as serenity;

/// Converts a prefix string's length into u16, panicking if it doesn't fit.
fn prefix_len_to_u16(prefix: &str) -> u16 {
prefix
.len()
.try_into()
.expect("messages should not be more than 64k bytes, let alone a prefix")
}

/// Checks if this message is a bot invocation by attempting to strip the prefix
///
/// Returns tuple of stripped prefix and rest of the message, if any prefix matches
async fn strip_prefix<'a, U, E>(
framework: crate::FrameworkContext<'a, U, E>,
msg: &'a serenity::Message,
) -> Option<(&'a str, &'a str)> {
) -> Option<u16> {
let partial_ctx = crate::PartialContext {
guild_id: msg.guild_id,
channel_id: msg.channel_id,
Expand All @@ -22,7 +32,7 @@ async fn strip_prefix<'a, U, E>(
Ok(prefix) => {
if let Some(prefix) = prefix {
if msg.content.starts_with(prefix.as_ref()) {
return Some(msg.content.split_at(prefix.len()));
return Some(prefix_len_to_u16(&prefix));
}
}
}
Expand All @@ -38,39 +48,36 @@ async fn strip_prefix<'a, U, E>(
}

if let Some(prefix) = framework.options.prefix_options.prefix.as_deref() {
if let Some(content) = msg.content.strip_prefix(prefix) {
return Some((prefix, content));
if msg.content.starts_with(prefix) {
return Some(prefix_len_to_u16(prefix));
}
}

if let Some((prefix, content)) = framework
if let Some(prefix) = framework
.options
.prefix_options
.additional_prefixes
.iter()
.find_map(|prefix| match prefix {
&crate::Prefix::Literal(prefix) => Some((prefix, msg.content.strip_prefix(prefix)?)),
&crate::Prefix::Literal(prefix) => Some(prefix),
crate::Prefix::Regex(prefix) => {
let regex_match = prefix.find(&msg.content)?;
if regex_match.start() == 0 {
Some(msg.content.split_at(regex_match.end()))
Some(&msg.content[..regex_match.end()])
} else {
None
}
}
crate::Prefix::__NonExhaustive => unreachable!(),
})
{
return Some((prefix, content));
return Some(prefix_len_to_u16(prefix));
}

if let Some(dynamic_prefix) = framework.options.prefix_options.stripped_dynamic_prefix {
match dynamic_prefix(framework.serenity_context, msg, framework.user_data).await {
Ok(result) => {
if let Some((prefix, content)) = result {
return Some((prefix, content));
}
}
Ok(Some(prefix)) => return Some(prefix_len_to_u16(prefix)),
Ok(None) => {}
Err(error) => {
(framework.options.on_error)(crate::FrameworkError::DynamicPrefix {
error,
Expand All @@ -92,7 +99,7 @@ async fn strip_prefix<'a, U, E>(
.strip_prefix('>')
})() {
let mention_prefix = &msg.content[..(msg.content.len() - stripped_content.len())];
return Some((mention_prefix, stripped_content));
return Some(prefix_len_to_u16(mention_prefix));
}
}

Expand Down Expand Up @@ -242,11 +249,11 @@ pub async fn parse_invocation<'a, U: Send + Sync, E>(
}

// Strip prefix, trim whitespace between prefix and rest, split rest into command name and args
let (prefix, msg_content) = match strip_prefix(framework, msg).await {
Some(x) => x,
None => return Ok(None),
let Some(content_start) = strip_prefix(framework, msg).await else {
return Ok(None);
};
let msg_content = msg_content.trim_start();

let msg_content = msg.content[content_start.into()..].trim_start();

let (command, invoked_command_name, args) = find_command(
&framework.options.commands,
Expand All @@ -256,8 +263,7 @@ pub async fn parse_invocation<'a, U: Send + Sync, E>(
)
.ok_or(crate::FrameworkError::UnknownCommand {
msg,
prefix,
msg_content,
content_start,
framework,
invocation_data,
trigger,
Expand All @@ -269,7 +275,7 @@ pub async fn parse_invocation<'a, U: Send + Sync, E>(

Ok(Some(crate::PrefixContext {
msg,
prefix,
content_start,
invoked_command_name,
args,
framework,
Expand Down
2 changes: 1 addition & 1 deletion src/structs/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ context_methods! {
(prefix self)
(pub fn prefix(self) -> &'a str) {
match self {
Context::Prefix(ctx) => ctx.prefix,
Context::Prefix(ctx) => &ctx.msg.content[..ctx.content_start.into()],
Context::Application(_) => "/",
}
}
Expand Down
13 changes: 6 additions & 7 deletions src/structs/framework_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,8 @@ pub enum FrameworkError<'a, U, E> {
UnknownCommand {
/// The message in question
msg: &'a serenity::Message,
/// The prefix that was recognized
prefix: &'a str,
/// The rest of the message (after the prefix) which was not recognized as a command
///
/// This is a single field instead of two fields (command name and args) due to subcommands
msg_content: &'a str,
/// The position in the message that the prefix ends.
content_start: u16,
/// Framework context
#[derivative(Debug = "ignore")]
framework: crate::FrameworkContext<'a, U, E>,
Expand Down Expand Up @@ -403,7 +399,10 @@ impl<U, E: std::fmt::Display> std::fmt::Display for FrameworkError<'_, U, E> {
msg.content
)
}
Self::UnknownCommand { msg_content, .. } => {
Self::UnknownCommand {
content_start, msg, ..
} => {
let msg_content = &msg.content[(*content_start).into()..];
write!(f, "unknown command `{}`", msg_content)
}
Self::UnknownInteraction { interaction, .. } => {
Expand Down
10 changes: 5 additions & 5 deletions src/structs/prefix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ pub enum MessageDispatchTrigger {
pub struct PrefixContext<'a, U, E> {
/// The invoking user message
pub msg: &'a serenity::Message,
/// Prefix used by the user to invoke this command
pub prefix: &'a str,
/// Position in the string that the prefix used by the user to invoke this command ends.
pub content_start: u16,
/// Command name used by the user to invoke this command
pub invoked_command_name: &'a str,
/// Entire argument string
Expand Down Expand Up @@ -97,12 +97,12 @@ pub struct PrefixFrameworkOptions<U, E> {
///
/// Override this field for advanced dynamic prefixes which change depending on guild or user.
///
/// Return value is a tuple of the prefix and the rest of the message:
/// Return value is the prefix found
/// ```rust,no_run
/// # poise::PrefixFrameworkOptions::<(), ()> { stripped_dynamic_prefix: Some(|_, msg, _| Box::pin(async move {
/// let my_cool_prefix = "$";
/// if msg.content.starts_with(my_cool_prefix) {
/// return Ok(Some(msg.content.split_at(my_cool_prefix.len())));
/// return Ok(Some(msg.content[..my_cool_prefix.len()]));
/// }
/// Ok(None)
/// # })), ..Default::default() };
Expand All @@ -113,7 +113,7 @@ pub struct PrefixFrameworkOptions<U, E> {
&'a serenity::Context,
&'a serenity::Message,
&'a U,
) -> BoxFuture<'a, Result<Option<(&'a str, &'a str)>, E>>,
) -> BoxFuture<'a, Result<Option<&'a str>, E>>,
>,
/// Treat a bot mention (a ping) like a prefix
pub mention_as_prefix: bool,
Expand Down

0 comments on commit cba2108

Please sign in to comment.