forked from lavina/lavina
add support for additional irc messages types
This commit is contained in:
parent
e5d0722fe0
commit
5d57df3219
|
@ -7,13 +7,25 @@ pub enum ClientMessage {
|
||||||
Capability {
|
Capability {
|
||||||
subcommand: CapabilitySubcommand,
|
subcommand: CapabilitySubcommand,
|
||||||
},
|
},
|
||||||
/// PING
|
/// PING <token>
|
||||||
Ping {
|
Ping {
|
||||||
token: ByteVec,
|
token: ByteVec,
|
||||||
},
|
},
|
||||||
|
/// PONG <token>
|
||||||
Pong {
|
Pong {
|
||||||
token: ByteVec,
|
token: ByteVec,
|
||||||
},
|
},
|
||||||
|
/// NICK <name>
|
||||||
|
Nick {
|
||||||
|
nickname: ByteVec,
|
||||||
|
},
|
||||||
|
User {
|
||||||
|
username: ByteVec,
|
||||||
|
realname: ByteVec,
|
||||||
|
},
|
||||||
|
Quit {
|
||||||
|
reason: ByteVec,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn client_message(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
pub fn client_message(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
||||||
|
@ -21,6 +33,9 @@ pub fn client_message(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
||||||
client_message_capability,
|
client_message_capability,
|
||||||
client_message_ping,
|
client_message_ping,
|
||||||
client_message_pong,
|
client_message_pong,
|
||||||
|
client_message_nick,
|
||||||
|
client_message_user,
|
||||||
|
client_message_quit,
|
||||||
))(input)
|
))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +70,47 @@ fn client_message_pong(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn client_message_nick(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
||||||
|
let (input, _) = tag("NICK ")(input)?;
|
||||||
|
let (input, nickname) = receiver(input)?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
ClientMessage::Nick {
|
||||||
|
nickname: nickname.to_owned(),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn client_message_user(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
||||||
|
let (input, _) = tag("USER ")(input)?;
|
||||||
|
let (input, username) = receiver(input)?;
|
||||||
|
let (input, _) = tag(" ")(input)?;
|
||||||
|
let (input, _) = take(1_usize)(input)?; // 0 in spec, but any in fact
|
||||||
|
let (input, _) = tag(" * :")(input)?;
|
||||||
|
let (input, realname) = token(input)?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
ClientMessage::User {
|
||||||
|
username: username.to_owned(),
|
||||||
|
realname: realname.to_owned(),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn client_message_quit(input: &[u8]) -> IResult<&[u8], ClientMessage> {
|
||||||
|
let (input, _) = tag("QUIT :")(input)?;
|
||||||
|
let (input, reason) = token(input)?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
ClientMessage::Quit {
|
||||||
|
reason: reason.to_vec(),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum CapabilitySubcommand {
|
pub enum CapabilitySubcommand {
|
||||||
/// CAP LS {code}
|
/// CAP LS {code}
|
||||||
|
@ -128,6 +184,27 @@ mod test {
|
||||||
token: b"1337".to_vec(),
|
token: b"1337".to_vec(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let result = client_message(input);
|
||||||
|
assert_matches!(result, Ok((_, result)) => assert_eq!(expected, result));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_client_message_nick() {
|
||||||
|
let input = b"NICK SomeNick";
|
||||||
|
let expected = ClientMessage::Nick {
|
||||||
|
nickname: b"SomeNick".to_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = client_message(input);
|
||||||
|
assert_matches!(result, Ok((_, result)) => assert_eq!(expected, result));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_client_message_user() {
|
||||||
|
let input = b"USER SomeNick 8 * :Real Name";
|
||||||
|
let expected = ClientMessage::User {
|
||||||
|
username: b"SomeNick".to_vec(),
|
||||||
|
realname: b"Real Name".to_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
let result = client_message(input);
|
let result = client_message(input);
|
||||||
assert_matches!(result, Ok((_, result)) => assert_eq!(expected, result));
|
assert_matches!(result, Ok((_, result)) => assert_eq!(expected, result));
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,3 +26,26 @@ fn receiver(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||||
fn token(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
fn token(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||||
take_while(|i| i != b'\n' && i != b'\r')(input)
|
take_while(|i| i != b'\n' && i != b'\r')(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum Chan {
|
||||||
|
/// #<name> — network-global channel, available from any server in the network.
|
||||||
|
Global(ByteVec),
|
||||||
|
/// &<name> — server-local channel, available only to connections to the same server. Rarely used in practice.
|
||||||
|
Local(ByteVec),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn chan(input: &[u8]) -> IResult<&[u8], Chan> {
|
||||||
|
fn chan_global(input: &[u8]) -> IResult<&[u8], Chan> {
|
||||||
|
let (input, _) = tag("#")(input)?;
|
||||||
|
let (input, name) = receiver(input)?;
|
||||||
|
Ok((input, Chan::Global(name.to_vec())))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn chan_local(input: &[u8]) -> IResult<&[u8], Chan> {
|
||||||
|
let (input, _) = tag("&")(input)?;
|
||||||
|
let (input, name) = receiver(input)?;
|
||||||
|
Ok((input, Chan::Local(name.to_vec())))
|
||||||
|
}
|
||||||
|
|
||||||
|
alt((chan_global, chan_local))(input)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue