diff --git a/crates/command_definitions/src/debug.rs b/crates/command_definitions/src/debug.rs index ac449eb3..52f50307 100644 --- a/crates/command_definitions/src/debug.rs +++ b/crates/command_definitions/src/debug.rs @@ -1,3 +1,5 @@ +use command_parser::parameter::MESSAGE_REF; + use super::*; pub fn debug() -> (&'static str, [&'static str; 1]) { @@ -12,7 +14,7 @@ pub fn cmds() -> impl IntoIterator { .help("Checks if PluralKit has the required permissions in a channel"), command!(debug, perms, ("guild", ["g"]), GuildRef => "permcheck_guild") .help("Checks whether a server's permission setup is correct"), - command!(debug, ("proxy", ["proxying", "proxycheck"]), MessageRef => "message_proxy_check") + command!(debug, ("proxy", ["proxying", "proxycheck"]), MESSAGE_REF => "message_proxy_check") .help("Checks why a message has not been proxied"), ] } diff --git a/crates/command_definitions/src/message.rs b/crates/command_definitions/src/message.rs index 9c930e4d..8531efd4 100644 --- a/crates/command_definitions/src/message.rs +++ b/crates/command_definitions/src/message.rs @@ -1,7 +1,9 @@ +use command_parser::parameter::{MESSAGE_LINK, MESSAGE_REF}; + use super::*; pub fn cmds() -> impl IntoIterator { - let message = tokens!(("message", ["msg", "messageinfo"]), Optional(MessageRef)); + let message = tokens!(("message", ["msg", "messageinfo"]), Optional(MESSAGE_REF)); let author = ("author", ["sender", "a"]); let delete = ("delete", ["del", "d"]); @@ -20,8 +22,8 @@ pub fn cmds() -> impl IntoIterator { }; [ - apply_edit(command!(edit, Optional(MessageRef), new_content_param => "message_edit")), - command!(reproxy, Optional(("msg", MessageRef)), ("member", MemberRef) => "message_reproxy") + apply_edit(command!(edit, Optional(MESSAGE_LINK), new_content_param => "message_edit")), + command!(reproxy, Optional(("msg", MESSAGE_REF)), ("member", MemberRef) => "message_reproxy") .help("Reproxies a previously proxied message with a different member"), command!(message, author => "message_author").help("Shows the author of a proxied message"), command!(message, delete => "message_delete").help("Deletes a proxied message"), diff --git a/crates/command_parser/src/parameter.rs b/crates/command_parser/src/parameter.rs index 6c6d63c6..6b8e7e5f 100644 --- a/crates/command_parser/src/parameter.rs +++ b/crates/command_parser/src/parameter.rs @@ -8,6 +8,15 @@ use smol_str::{SmolStr, format_smolstr}; use crate::token::{Token, TokenMatchResult}; +pub const MESSAGE_REF: ParameterKind = ParameterKind::MessageRef { + id: true, + link: true, +}; +pub const MESSAGE_LINK: ParameterKind = ParameterKind::MessageRef { + id: false, + link: true, +}; + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ParameterKind { OpaqueString, @@ -18,7 +27,7 @@ pub enum ParameterKind { GroupRefs, SystemRef, UserRef, - MessageRef, + MessageRef { id: bool, link: bool }, ChannelRef, GuildRef, MemberPrivacyTarget, @@ -41,7 +50,7 @@ impl ParameterKind { ParameterKind::GroupRefs => "targets", ParameterKind::SystemRef => "target", ParameterKind::UserRef => "target", - ParameterKind::MessageRef => "target", + ParameterKind::MessageRef { .. } => "target", ParameterKind::ChannelRef => "target", ParameterKind::GuildRef => "target", ParameterKind::MemberPrivacyTarget => "member_privacy_target", @@ -153,48 +162,56 @@ impl Parameter { Toggle::from_str(input).map(|t| ParameterValue::Toggle(t.into())) } ParameterKind::Avatar => Ok(ParameterValue::Avatar(input.into())), - ParameterKind::MessageRef => { - if let Ok(message_id) = input.parse::() { - return Ok(ParameterValue::MessageRef(None, None, message_id)); + ParameterKind::MessageRef { id, link } => { + if id { + if let Ok(message_id) = input.parse::() { + return Ok(ParameterValue::MessageRef(None, None, message_id)); + } } - static SERVER_RE: std::sync::LazyLock = std::sync::LazyLock::new( - || { - regex::Regex::new( - r"https://(?:\w+\.)?discord(?:app)?\.com/channels/(?P\d+)/(?P\d+)/(?P\d+)", - ) - .unwrap() - }, - ); + if link { + static SERVER_RE: std::sync::LazyLock = std::sync::LazyLock::new( + || { + regex::Regex::new( + r"https://(?:\w+\.)?discord(?:app)?\.com/channels/(?P\d+)/(?P\d+)/(?P\d+)", + ) + .unwrap() + }, + ); - static DM_RE: std::sync::LazyLock = std::sync::LazyLock::new(|| { - regex::Regex::new( - r"https://(?:\w+\.)?discord(?:app)?\.com/channels/@me/(?P\d+)/(?P\d+)", - ) - .unwrap() - }); + static DM_RE: std::sync::LazyLock = std::sync::LazyLock::new( + || { + regex::Regex::new( + r"https://(?:\w+\.)?discord(?:app)?\.com/channels/@me/(?P\d+)/(?P\d+)", + ) + .unwrap() + }, + ); - if let Some(captures) = SERVER_RE.captures(input) { - let guild_id = captures.parse_id("guild")?; - let channel_id = captures.parse_id("channel")?; - let message_id = captures.parse_id("message")?; + if let Some(captures) = SERVER_RE.captures(input) { + let guild_id = captures.parse_id("guild")?; + let channel_id = captures.parse_id("channel")?; + let message_id = captures.parse_id("message")?; - Ok(ParameterValue::MessageRef( - Some(guild_id), - Some(channel_id), - message_id, - )) - } else if let Some(captures) = DM_RE.captures(input) { - let channel_id = captures.parse_id("channel")?; - let message_id = captures.parse_id("message")?; + Ok(ParameterValue::MessageRef( + Some(guild_id), + Some(channel_id), + message_id, + )) + } else if let Some(captures) = DM_RE.captures(input) { + let channel_id = captures.parse_id("channel")?; + let message_id = captures.parse_id("message")?; - Ok(ParameterValue::MessageRef( - None, - Some(channel_id), - message_id, - )) + Ok(ParameterValue::MessageRef( + None, + Some(channel_id), + message_id, + )) + } else { + Err(SmolStr::new("invalid message reference")) + } } else { - Err(SmolStr::new("invalid message reference")) + unreachable!("link and id both cant be false") } } ParameterKind::ChannelRef => { @@ -234,7 +251,15 @@ impl Display for Parameter { ParameterKind::GroupRefs => write!(f, " "), ParameterKind::SystemRef => write!(f, ""), ParameterKind::UserRef => write!(f, ""), - ParameterKind::MessageRef => write!(f, ""), + ParameterKind::MessageRef { link, id } => write!( + f, + "", + link.then_some("link") + .into_iter() + .chain(id.then_some("id")) + .collect::>() + .join("/") + ), ParameterKind::ChannelRef => write!(f, ""), ParameterKind::GuildRef => write!(f, ""), ParameterKind::MemberPrivacyTarget => write!(f, ""), diff --git a/crates/commands/src/write_cs_glue.rs b/crates/commands/src/write_cs_glue.rs index 6d6fb414..6d693f20 100644 --- a/crates/commands/src/write_cs_glue.rs +++ b/crates/commands/src/write_cs_glue.rs @@ -276,7 +276,7 @@ fn get_param_ty(kind: ParameterKind) -> &'static str { ParameterKind::PrivacyLevel => "PrivacyLevel", ParameterKind::Toggle => "bool", ParameterKind::Avatar => "ParsedImage", - ParameterKind::MessageRef => "Message.Reference", + ParameterKind::MessageRef { .. } => "Message.Reference", ParameterKind::ChannelRef => "Channel", ParameterKind::GuildRef => "Guild", ParameterKind::ProxySwitchAction => "SystemConfig.ProxySwitchAction", @@ -299,7 +299,7 @@ fn get_param_param_ty(kind: ParameterKind) -> &'static str { ParameterKind::PrivacyLevel => "PrivacyLevel", ParameterKind::Toggle => "Toggle", ParameterKind::Avatar => "Avatar", - ParameterKind::MessageRef => "Message", + ParameterKind::MessageRef { .. } => "Message", ParameterKind::ChannelRef => "Channel", ParameterKind::GuildRef => "Guild", ParameterKind::ProxySwitchAction => "ProxySwitchAction",