Merge pull request #199 from belak/fix-suffix-handling
Handle suffix as a plain param
This commit is contained in:
commit
bbc99b1d20
5 changed files with 647 additions and 1322 deletions
|
@ -29,7 +29,7 @@ async fn main() -> irc::error::Result<()> {
|
||||||
|
|
||||||
while let Some(message) = stream.next().await.transpose()? {
|
while let Some(message) = stream.next().await.transpose()? {
|
||||||
match message.command {
|
match message.command {
|
||||||
Command::Response(Response::RPL_ISUPPORT, _, _) => {
|
Command::Response(Response::RPL_ISUPPORT, _) => {
|
||||||
client.send_privmsg(
|
client.send_privmsg(
|
||||||
"#commits",
|
"#commits",
|
||||||
format!(
|
format!(
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -36,7 +36,7 @@ impl Message {
|
||||||
/// # use irc_proto::Message;
|
/// # use irc_proto::Message;
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
/// let message = Message::new(
|
/// let message = Message::new(
|
||||||
/// Some("nickname!username@hostname"), "JOIN", vec!["#channel"], None
|
/// Some("nickname!username@hostname"), "JOIN", vec!["#channel"]
|
||||||
/// ).unwrap();
|
/// ).unwrap();
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -44,9 +44,8 @@ impl Message {
|
||||||
prefix: Option<&str>,
|
prefix: Option<&str>,
|
||||||
command: &str,
|
command: &str,
|
||||||
args: Vec<&str>,
|
args: Vec<&str>,
|
||||||
suffix: Option<&str>,
|
|
||||||
) -> Result<Message, MessageParseError> {
|
) -> Result<Message, MessageParseError> {
|
||||||
Message::with_tags(None, prefix, command, args, suffix)
|
Message::with_tags(None, prefix, command, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new IRCv3.2 message from the given components, including message tags. These tags
|
/// Creates a new IRCv3.2 message from the given components, including message tags. These tags
|
||||||
|
@ -57,12 +56,11 @@ impl Message {
|
||||||
prefix: Option<&str>,
|
prefix: Option<&str>,
|
||||||
command: &str,
|
command: &str,
|
||||||
args: Vec<&str>,
|
args: Vec<&str>,
|
||||||
suffix: Option<&str>,
|
|
||||||
) -> Result<Message, error::MessageParseError> {
|
) -> Result<Message, error::MessageParseError> {
|
||||||
Ok(Message {
|
Ok(Message {
|
||||||
tags: tags,
|
tags: tags,
|
||||||
prefix: prefix.map(|p| p.into()),
|
prefix: prefix.map(|p| p.into()),
|
||||||
command: Command::new(command, args, suffix)?,
|
command: Command::new(command, args)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +72,7 @@ impl Message {
|
||||||
/// # use irc_proto::Message;
|
/// # use irc_proto::Message;
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
/// let message = Message::new(
|
/// let message = Message::new(
|
||||||
/// Some("nickname!username@hostname"), "JOIN", vec!["#channel"], None
|
/// Some("nickname!username@hostname"), "JOIN", vec!["#channel"]
|
||||||
/// ).unwrap();
|
/// ).unwrap();
|
||||||
/// assert_eq!(message.source_nickname(), Some("nickname"));
|
/// assert_eq!(message.source_nickname(), Some("nickname"));
|
||||||
/// # }
|
/// # }
|
||||||
|
@ -98,11 +96,11 @@ impl Message {
|
||||||
/// # use irc_proto::Message;
|
/// # use irc_proto::Message;
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
/// let msg1 = Message::new(
|
/// let msg1 = Message::new(
|
||||||
/// Some("ada"), "PRIVMSG", vec!["#channel"], Some("Hi, everyone!")
|
/// Some("ada"), "PRIVMSG", vec!["#channel", "Hi, everyone!"]
|
||||||
/// ).unwrap();
|
/// ).unwrap();
|
||||||
/// assert_eq!(msg1.response_target(), Some("#channel"));
|
/// assert_eq!(msg1.response_target(), Some("#channel"));
|
||||||
/// let msg2 = Message::new(
|
/// let msg2 = Message::new(
|
||||||
/// Some("ada"), "PRIVMSG", vec!["betsy"], Some("betsy: hi")
|
/// Some("ada"), "PRIVMSG", vec!["betsy", "betsy: hi"]
|
||||||
/// ).unwrap();
|
/// ).unwrap();
|
||||||
/// assert_eq!(msg2.response_target(), Some("ada"));
|
/// assert_eq!(msg2.response_target(), Some("ada"));
|
||||||
/// # }
|
/// # }
|
||||||
|
@ -123,7 +121,7 @@ impl Message {
|
||||||
/// # use irc_proto::Message;
|
/// # use irc_proto::Message;
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
/// let msg = Message::new(
|
/// let msg = Message::new(
|
||||||
/// Some("ada"), "PRIVMSG", vec!["#channel"], Some("Hi, everyone!")
|
/// Some("ada"), "PRIVMSG", vec!["#channel", "Hi, everyone!"]
|
||||||
/// ).unwrap();
|
/// ).unwrap();
|
||||||
/// assert_eq!(msg.to_string(), ":ada PRIVMSG #channel :Hi, everyone!\r\n");
|
/// assert_eq!(msg.to_string(), ":ada PRIVMSG #channel :Hi, everyone!\r\n");
|
||||||
/// # }
|
/// # }
|
||||||
|
@ -243,9 +241,12 @@ impl FromStr for Message {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let args: Vec<_> = state.splitn(14, ' ').filter(|s| !s.is_empty()).collect();
|
let mut args: Vec<_> = state.splitn(14, ' ').filter(|s| !s.is_empty()).collect();
|
||||||
|
if let Some(suffix) = suffix {
|
||||||
|
args.push(suffix);
|
||||||
|
}
|
||||||
|
|
||||||
Message::with_tags(tags, prefix, command, args, suffix).map_err(|e| {
|
Message::with_tags(tags, prefix, command, args).map_err(|e| {
|
||||||
ProtocolError::InvalidMessage {
|
ProtocolError::InvalidMessage {
|
||||||
string: s.to_owned(),
|
string: s.to_owned(),
|
||||||
cause: e,
|
cause: e,
|
||||||
|
@ -286,7 +287,7 @@ mod test {
|
||||||
command: PRIVMSG(format!("test"), format!("Testing!")),
|
command: PRIVMSG(format!("test"), format!("Testing!")),
|
||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Message::new(None, "PRIVMSG", vec!["test"], Some("Testing!")).unwrap(),
|
Message::new(None, "PRIVMSG", vec!["test", "Testing!"]).unwrap(),
|
||||||
message
|
message
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -294,56 +295,56 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn source_nickname() {
|
fn source_nickname() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Message::new(None, "PING", vec![], Some("data"))
|
Message::new(None, "PING", vec!["data"])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.source_nickname(),
|
.source_nickname(),
|
||||||
None
|
None
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Message::new(Some("irc.test.net"), "PING", vec![], Some("data"))
|
Message::new(Some("irc.test.net"), "PING", vec!["data"])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.source_nickname(),
|
.source_nickname(),
|
||||||
None
|
None
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Message::new(Some("test!test@test"), "PING", vec![], Some("data"))
|
Message::new(Some("test!test@test"), "PING", vec!["data"])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.source_nickname(),
|
.source_nickname(),
|
||||||
Some("test")
|
Some("test")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Message::new(Some("test@test"), "PING", vec![], Some("data"))
|
Message::new(Some("test@test"), "PING", vec!["data"])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.source_nickname(),
|
.source_nickname(),
|
||||||
Some("test")
|
Some("test")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Message::new(Some("test!test@irc.test.com"), "PING", vec![], Some("data"))
|
Message::new(Some("test!test@irc.test.com"), "PING", vec!["data"])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.source_nickname(),
|
.source_nickname(),
|
||||||
Some("test")
|
Some("test")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Message::new(Some("test!test@127.0.0.1"), "PING", vec![], Some("data"))
|
Message::new(Some("test!test@127.0.0.1"), "PING", vec!["data"])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.source_nickname(),
|
.source_nickname(),
|
||||||
Some("test")
|
Some("test")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Message::new(Some("test@test.com"), "PING", vec![], Some("data"))
|
Message::new(Some("test@test.com"), "PING", vec!["data"])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.source_nickname(),
|
.source_nickname(),
|
||||||
Some("test")
|
Some("test")
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Message::new(Some("test"), "PING", vec![], Some("data"))
|
Message::new(Some("test"), "PING", vec!["data"])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.source_nickname(),
|
.source_nickname(),
|
||||||
Some("test")
|
Some("test")
|
||||||
|
@ -357,7 +358,7 @@ mod test {
|
||||||
prefix: None,
|
prefix: None,
|
||||||
command: PRIVMSG(format!("test"), format!("Testing!")),
|
command: PRIVMSG(format!("test"), format!("Testing!")),
|
||||||
};
|
};
|
||||||
assert_eq!(&message.to_string()[..], "PRIVMSG test :Testing!\r\n");
|
assert_eq!(&message.to_string()[..], "PRIVMSG test Testing!\r\n");
|
||||||
let message = Message {
|
let message = Message {
|
||||||
tags: None,
|
tags: None,
|
||||||
prefix: Some("test!test@test".into()),
|
prefix: Some("test!test@test".into()),
|
||||||
|
@ -465,8 +466,7 @@ mod test {
|
||||||
prefix: Some("test!test@test".into()),
|
prefix: Some("test!test@test".into()),
|
||||||
command: Raw(
|
command: Raw(
|
||||||
format!("COMMAND"),
|
format!("COMMAND"),
|
||||||
vec![format!("ARG:test")],
|
vec![format!("ARG:test"), format!("Testing!")],
|
||||||
Some(format!("Testing!")),
|
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let msg: Message = ":test!test@test COMMAND ARG:test :Testing!\r\n".into();
|
let msg: Message = ":test!test@test COMMAND ARG:test :Testing!\r\n".into();
|
||||||
|
|
|
@ -13,6 +13,9 @@ pub trait ModeType: fmt::Display + fmt::Debug + Clone + PartialEq {
|
||||||
|
|
||||||
/// Returns true if this mode takes an argument, and false otherwise.
|
/// Returns true if this mode takes an argument, and false otherwise.
|
||||||
fn takes_arg(&self) -> bool;
|
fn takes_arg(&self) -> bool;
|
||||||
|
|
||||||
|
/// Creates a Mode from a given char.
|
||||||
|
fn from_char(c: char) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// User modes for the MODE command.
|
/// User modes for the MODE command.
|
||||||
|
@ -47,9 +50,7 @@ impl ModeType for UserMode {
|
||||||
fn takes_arg(&self) -> bool {
|
fn takes_arg(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl UserMode {
|
|
||||||
fn from_char(c: char) -> UserMode {
|
fn from_char(c: char) -> UserMode {
|
||||||
use self::UserMode::*;
|
use self::UserMode::*;
|
||||||
|
|
||||||
|
@ -144,9 +145,7 @@ impl ModeType for ChannelMode {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ChannelMode {
|
|
||||||
fn from_char(c: char) -> ChannelMode {
|
fn from_char(c: char) -> ChannelMode {
|
||||||
use self::ChannelMode::*;
|
use self::ChannelMode::*;
|
||||||
|
|
||||||
|
@ -252,49 +251,8 @@ enum PlusMinus {
|
||||||
impl Mode<UserMode> {
|
impl Mode<UserMode> {
|
||||||
// TODO: turning more edge cases into errors.
|
// TODO: turning more edge cases into errors.
|
||||||
/// Parses the specified mode string as user modes.
|
/// Parses the specified mode string as user modes.
|
||||||
pub fn as_user_modes(s: &str) -> Result<Vec<Mode<UserMode>>, MessageParseError> {
|
pub fn as_user_modes(pieces: &[&str]) -> Result<Vec<Mode<UserMode>>, MessageParseError> {
|
||||||
use self::PlusMinus::*;
|
parse_modes(pieces)
|
||||||
|
|
||||||
let mut res = vec![];
|
|
||||||
let mut pieces = s.split(' ');
|
|
||||||
for term in pieces.clone() {
|
|
||||||
if term.starts_with('+') || term.starts_with('-') {
|
|
||||||
let _ = pieces.next();
|
|
||||||
|
|
||||||
let mut chars = term.chars();
|
|
||||||
let init = match chars.next() {
|
|
||||||
Some('+') => Plus,
|
|
||||||
Some('-') => Minus,
|
|
||||||
Some(c) => {
|
|
||||||
return Err(InvalidModeString {
|
|
||||||
string: s.to_owned(),
|
|
||||||
cause: InvalidModeModifier { modifier: c },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return Err(InvalidModeString {
|
|
||||||
string: s.to_owned(),
|
|
||||||
cause: MissingModeModifier,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for c in chars {
|
|
||||||
let mode = UserMode::from_char(c);
|
|
||||||
let arg = if mode.takes_arg() {
|
|
||||||
pieces.next()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
res.push(match init {
|
|
||||||
Plus => Mode::Plus(mode, arg.map(|s| s.to_owned())),
|
|
||||||
Minus => Mode::Minus(mode, arg.map(|s| s.to_owned())),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,48 +260,67 @@ impl Mode<UserMode> {
|
||||||
impl Mode<ChannelMode> {
|
impl Mode<ChannelMode> {
|
||||||
// TODO: turning more edge cases into errors.
|
// TODO: turning more edge cases into errors.
|
||||||
/// Parses the specified mode string as channel modes.
|
/// Parses the specified mode string as channel modes.
|
||||||
pub fn as_channel_modes(s: &str) -> Result<Vec<Mode<ChannelMode>>, MessageParseError> {
|
pub fn as_channel_modes(pieces: &[&str]) -> Result<Vec<Mode<ChannelMode>>, MessageParseError> {
|
||||||
use self::PlusMinus::*;
|
parse_modes(pieces)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut res = vec![];
|
fn parse_modes<T>(pieces: &[&str]) -> Result<Vec<Mode<T>>, MessageParseError>
|
||||||
let mut pieces = s.split(' ');
|
where
|
||||||
for term in pieces.clone() {
|
T: ModeType,
|
||||||
if term.starts_with('+') || term.starts_with('-') {
|
{
|
||||||
let _ = pieces.next();
|
use self::PlusMinus::*;
|
||||||
|
|
||||||
let mut chars = term.chars();
|
let mut res = vec![];
|
||||||
let init = match chars.next() {
|
|
||||||
Some('+') => Plus,
|
|
||||||
Some('-') => Minus,
|
|
||||||
Some(c) => {
|
|
||||||
return Err(InvalidModeString {
|
|
||||||
string: s.to_owned(),
|
|
||||||
cause: InvalidModeModifier { modifier: c },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return Err(InvalidModeString {
|
|
||||||
string: s.to_owned(),
|
|
||||||
cause: MissingModeModifier,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for c in chars {
|
if let Some((first, rest)) = pieces.split_first() {
|
||||||
let mode = ChannelMode::from_char(c);
|
let mut modes = first.chars();
|
||||||
|
let mut args = rest.iter();
|
||||||
|
|
||||||
|
let mut cur_mod = match modes.next() {
|
||||||
|
Some('+') => Plus,
|
||||||
|
Some('-') => Minus,
|
||||||
|
Some(c) => {
|
||||||
|
return Err(InvalidModeString {
|
||||||
|
string: pieces.join(" ").to_owned(),
|
||||||
|
cause: InvalidModeModifier { modifier: c },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Err(InvalidModeString {
|
||||||
|
string: pieces.join(" ").to_owned(),
|
||||||
|
cause: MissingModeModifier,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for c in modes {
|
||||||
|
match c {
|
||||||
|
'+' => cur_mod = Plus,
|
||||||
|
'-' => cur_mod = Minus,
|
||||||
|
_ => {
|
||||||
|
let mode = T::from_char(c);
|
||||||
let arg = if mode.takes_arg() {
|
let arg = if mode.takes_arg() {
|
||||||
pieces.next()
|
// TODO: if there's no arg, this should error
|
||||||
|
args.next()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
res.push(match init {
|
res.push(match cur_mod {
|
||||||
Plus => Mode::Plus(mode, arg.map(|s| s.to_owned())),
|
Plus => Mode::Plus(mode, arg.map(|s| s.to_string())),
|
||||||
Minus => Mode::Minus(mode, arg.map(|s| s.to_owned())),
|
Minus => Mode::Minus(mode, arg.map(|s| s.to_string())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: if there are extra args left, this should error
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
|
} else {
|
||||||
|
Err(InvalidModeString {
|
||||||
|
string: pieces.join(" ").to_owned(),
|
||||||
|
cause: MissingModeModifier,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -570,11 +570,9 @@ impl ClientState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Response(Response::RPL_NAMREPLY, ref args, ref suffix) => {
|
Command::Response(Response::RPL_NAMREPLY, ref args) => self.handle_namreply(args),
|
||||||
self.handle_namreply(args, suffix)
|
Command::Response(Response::RPL_ENDOFMOTD, _)
|
||||||
}
|
| Command::Response(Response::ERR_NOMOTD, _) => {
|
||||||
Command::Response(Response::RPL_ENDOFMOTD, _, _)
|
|
||||||
| Command::Response(Response::ERR_NOMOTD, _, _) => {
|
|
||||||
self.send_nick_password()?;
|
self.send_nick_password()?;
|
||||||
self.send_umodes()?;
|
self.send_umodes()?;
|
||||||
|
|
||||||
|
@ -593,8 +591,8 @@ impl ClientState {
|
||||||
self.send_join(chan)?
|
self.send_join(chan)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Response(Response::ERR_NICKNAMEINUSE, _, _)
|
Command::Response(Response::ERR_NICKNAMEINUSE, _)
|
||||||
| Command::Response(Response::ERR_ERRONEOUSNICKNAME, _, _) => {
|
| Command::Response(Response::ERR_ERRONEOUSNICKNAME, _) => {
|
||||||
let alt_nicks = self.config().alternate_nicknames();
|
let alt_nicks = self.config().alternate_nicknames();
|
||||||
let mut index = self.alt_nick_index.write();
|
let mut index = self.alt_nick_index.write();
|
||||||
|
|
||||||
|
@ -623,20 +621,19 @@ impl ClientState {
|
||||||
};
|
};
|
||||||
|
|
||||||
for s in seq {
|
for s in seq {
|
||||||
self.send(NICKSERV(format!(
|
self.send(NICKSERV(vec!(
|
||||||
"{} {} {}",
|
s.to_string(),
|
||||||
s,
|
self.config().nickname()?.to_string(),
|
||||||
self.config().nickname()?,
|
self.config().nick_password().to_string(),
|
||||||
self.config().nick_password()
|
|
||||||
)))?;
|
)))?;
|
||||||
}
|
}
|
||||||
*index = 0;
|
*index = 0;
|
||||||
self.send(NICK(self.config().nickname()?.to_owned()))?
|
self.send(NICK(self.config().nickname()?.to_owned()))?
|
||||||
}
|
}
|
||||||
|
|
||||||
self.send(NICKSERV(format!(
|
self.send(NICKSERV(vec!(
|
||||||
"IDENTIFY {}",
|
"IDENTIFY".to_string(),
|
||||||
self.config().nick_password()
|
self.config().nick_password().to_string()
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -647,15 +644,20 @@ impl ClientState {
|
||||||
} else {
|
} else {
|
||||||
self.send_mode(
|
self.send_mode(
|
||||||
self.current_nickname(),
|
self.current_nickname(),
|
||||||
&Mode::as_user_modes(self.config().umodes()).map_err(|e| {
|
&Mode::as_user_modes(
|
||||||
error::Error::InvalidMessage {
|
self.config()
|
||||||
string: format!(
|
.umodes()
|
||||||
"MODE {} {}",
|
.split(' ')
|
||||||
self.current_nickname(),
|
.collect::<Vec<_>>()
|
||||||
self.config().umodes()
|
.as_ref(),
|
||||||
),
|
)
|
||||||
cause: e,
|
.map_err(|e| error::Error::InvalidMessage {
|
||||||
}
|
string: format!(
|
||||||
|
"MODE {} {}",
|
||||||
|
self.current_nickname(),
|
||||||
|
self.config().umodes()
|
||||||
|
),
|
||||||
|
cause: e,
|
||||||
})?,
|
})?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -740,20 +742,18 @@ impl ClientState {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "nochanlists")]
|
#[cfg(feature = "nochanlists")]
|
||||||
fn handle_namreply(&self, _: &[String], _: &Option<String>) {}
|
fn handle_namreply(&self, _: &[String]) {}
|
||||||
|
|
||||||
#[cfg(not(feature = "nochanlists"))]
|
#[cfg(not(feature = "nochanlists"))]
|
||||||
fn handle_namreply(&self, args: &[String], suffix: &Option<String>) {
|
fn handle_namreply(&self, args: &[String]) {
|
||||||
if let Some(ref users) = *suffix {
|
if args.len() == 4 {
|
||||||
if args.len() == 3 {
|
let chan = &args[2];
|
||||||
let chan = &args[2];
|
for user in args[3].split(' ') {
|
||||||
for user in users.split(' ') {
|
self.chanlists
|
||||||
self.chanlists
|
.write()
|
||||||
.write()
|
.entry(chan.clone())
|
||||||
.entry(chan.clone())
|
.or_insert_with(Vec::new)
|
||||||
.or_insert_with(Vec::new)
|
.push(User::new(user))
|
||||||
.push(User::new(user))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1219,8 +1219,8 @@ mod test {
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&get_client_value(client)[..],
|
&get_client_value(client)[..],
|
||||||
"NICK :test2\r\nNICKSERV GHOST test password\r\n\
|
"NICK test2\r\nNICKSERV GHOST test password\r\n\
|
||||||
NICK :test\r\nNICKSERV IDENTIFY password\r\nJOIN #test\r\nJOIN #test2\r\n"
|
NICK test\r\nNICKSERV IDENTIFY password\r\nJOIN #test\r\nJOIN #test2\r\n"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1243,8 +1243,8 @@ mod test {
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&get_client_value(client)[..],
|
&get_client_value(client)[..],
|
||||||
"NICK :test2\r\nNICKSERV RECOVER test password\
|
"NICK test2\r\nNICKSERV RECOVER test password\
|
||||||
\r\nNICKSERV RELEASE test password\r\nNICK :test\r\nNICKSERV IDENTIFY password\
|
\r\nNICKSERV RELEASE test password\r\nNICK test\r\nNICKSERV IDENTIFY password\
|
||||||
\r\nJOIN #test\r\nJOIN #test2\r\n"
|
\r\nJOIN #test\r\nJOIN #test2\r\n"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1278,7 +1278,7 @@ mod test {
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(&get_client_value(client)[..], "NICK :test2\r\n");
|
assert_eq!(&get_client_value(client)[..], "NICK test2\r\n");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1332,10 +1332,10 @@ mod test {
|
||||||
async fn send_raw_is_really_raw() -> Result<()> {
|
async fn send_raw_is_really_raw() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
assert!(client
|
assert!(client
|
||||||
.send(Raw("PASS".to_owned(), vec!["password".to_owned()], None))
|
.send(Raw("PASS".to_owned(), vec!["password".to_owned()]))
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(client
|
assert!(client
|
||||||
.send(Raw("NICK".to_owned(), vec!["test".to_owned()], None))
|
.send(Raw("NICK".to_owned(), vec!["test".to_owned()]))
|
||||||
.is_ok());
|
.is_ok());
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -1622,7 +1622,7 @@ mod test {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn ctcp_ping_no_timestamp() -> Result<()> {
|
async fn ctcp_ping_no_timestamp() -> Result<()> {
|
||||||
let value = ":test!test@test PRIVMSG test :\u{001}PING\u{001}\r\n";
|
let value = ":test!test@test PRIVMSG test \u{001}PING\u{001}\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
..test_config()
|
..test_config()
|
||||||
|
@ -1640,8 +1640,8 @@ mod test {
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&get_client_value(client)[..],
|
&get_client_value(client)[..],
|
||||||
"CAP END\r\nNICK :test\r\n\
|
"CAP END\r\nNICK test\r\n\
|
||||||
USER test 0 * :test\r\n"
|
USER test 0 * test\r\n"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1658,8 +1658,8 @@ mod test {
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&get_client_value(client)[..],
|
&get_client_value(client)[..],
|
||||||
"CAP END\r\nPASS :password\r\nNICK :test\r\n\
|
"CAP END\r\nPASS password\r\nNICK test\r\n\
|
||||||
USER test 0 * :test\r\n"
|
USER test 0 * test\r\n"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1669,7 +1669,7 @@ mod test {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_pong("irc.test.net")?;
|
client.send_pong("irc.test.net")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(&get_client_value(client)[..], "PONG :irc.test.net\r\n");
|
assert_eq!(&get_client_value(client)[..], "PONG irc.test.net\r\n");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1699,7 +1699,7 @@ mod test {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_oper("test", "test")?;
|
client.send_oper("test", "test")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(&get_client_value(client)[..], "OPER test :test\r\n");
|
assert_eq!(&get_client_value(client)[..], "OPER test test\r\n");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1846,7 +1846,7 @@ mod test {
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&get_client_value(client)[..],
|
&get_client_value(client)[..],
|
||||||
"PRIVMSG test :\u{001}MESSAGE\u{001}\r\n"
|
"PRIVMSG test \u{001}MESSAGE\u{001}\r\n"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1872,7 +1872,7 @@ mod test {
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&get_client_value(client)[..],
|
&get_client_value(client)[..],
|
||||||
"PRIVMSG test :\u{001}FINGER\u{001}\r\n"
|
"PRIVMSG test \u{001}FINGER\u{001}\r\n"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1885,7 +1885,7 @@ mod test {
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&get_client_value(client)[..],
|
&get_client_value(client)[..],
|
||||||
"PRIVMSG test :\u{001}VERSION\u{001}\r\n"
|
"PRIVMSG test \u{001}VERSION\u{001}\r\n"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1898,7 +1898,7 @@ mod test {
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&get_client_value(client)[..],
|
&get_client_value(client)[..],
|
||||||
"PRIVMSG test :\u{001}SOURCE\u{001}\r\n"
|
"PRIVMSG test \u{001}SOURCE\u{001}\r\n"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1911,7 +1911,7 @@ mod test {
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&get_client_value(client)[..],
|
&get_client_value(client)[..],
|
||||||
"PRIVMSG test :\u{001}USERINFO\u{001}\r\n"
|
"PRIVMSG test \u{001}USERINFO\u{001}\r\n"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1937,7 +1937,7 @@ mod test {
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&get_client_value(client)[..],
|
&get_client_value(client)[..],
|
||||||
"PRIVMSG test :\u{001}TIME\u{001}\r\n"
|
"PRIVMSG test \u{001}TIME\u{001}\r\n"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue