From 709151b94d9f92a79758e706e6bea219b449e56f Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 23 Jun 2023 21:27:47 +0900 Subject: [PATCH] irc-proto: allow modes with no prefix irc clients can query the details of some modes (e.g. request list of banned users) by sending a message with no plus or minus prefix, e.g. "MODE #chan b" --- irc-proto/src/mode.rs | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/irc-proto/src/mode.rs b/irc-proto/src/mode.rs index bc242f7..778e0a7 100644 --- a/irc-proto/src/mode.rs +++ b/irc-proto/src/mode.rs @@ -3,8 +3,6 @@ use std::fmt; use crate::command::Command; use crate::error::MessageParseError; -use crate::error::MessageParseError::InvalidModeString; -use crate::error::ModeParseError::*; /// A marker trait for different kinds of Modes. pub trait ModeType: fmt::Display + fmt::Debug + Clone + PartialEq { @@ -218,6 +216,8 @@ where Plus(T, Option), /// Removing the specified mode, optionally with an argument. Minus(T, Option), + /// No prefix mode, used to query ban list on channel join. + NoPrefix(T), } impl Mode @@ -233,6 +233,11 @@ where pub fn minus(inner: T, arg: Option<&str>) -> Mode { Mode::Minus(inner, arg.map(|s| s.to_owned())) } + + /// Create a no prefix mode with an `&str` argument. + pub fn no_prefix(inner: T) -> Mode { + Mode::NoPrefix(inner) + } } impl fmt::Display for Mode @@ -245,6 +250,7 @@ where Mode::Minus(ref mode, Some(ref arg)) => write!(f, "-{} {}", mode, arg), Mode::Plus(ref mode, None) => write!(f, "+{}", mode), Mode::Minus(ref mode, None) => write!(f, "-{}", mode), + Mode::NoPrefix(ref mode) => write!(f, "{}", mode), } } } @@ -252,6 +258,7 @@ where enum PlusMinus { Plus, Minus, + NoPrefix, } // MODE user [modes] @@ -287,11 +294,10 @@ where let mut cur_mod = match modes.next() { Some('+') => Plus, Some('-') => Minus, - Some(c) => { - return Err(InvalidModeString { - string: pieces.join(" "), - cause: InvalidModeModifier { modifier: c }, - }) + Some(_) => { + // rewind modes + modes = first.chars(); + NoPrefix } None => { // No modifier @@ -314,6 +320,7 @@ where res.push(match cur_mod { Plus => Mode::Plus(mode, arg.map(|s| s.to_string())), Minus => Mode::Minus(mode, arg.map(|s| s.to_string())), + NoPrefix => Mode::NoPrefix(mode), }) } } @@ -350,4 +357,13 @@ mod test { let cmd = "MODE #foo".parse::().unwrap().command; assert_eq!(Command::ChannelMODE("#foo".to_string(), vec![]), cmd); } + + #[test] + fn parse_no_plus() { + let cmd = "MODE #foo b".parse::().unwrap().command; + assert_eq!( + Command::ChannelMODE("#foo".to_string(), vec![Mode::NoPrefix(ChannelMode::Ban)]), + cmd + ); + } }