Implemented IRCv3 metadata (without metadata-notify).
This commit is contained in:
parent
3afef46198
commit
edc770e22e
3 changed files with 94 additions and 2 deletions
|
@ -28,6 +28,8 @@ pub enum Capability {
|
||||||
ServerTime,
|
ServerTime,
|
||||||
/// [userhost-in-names](http://ircv3.net/specs/extensions/userhost-in-names-3.2.html)
|
/// [userhost-in-names](http://ircv3.net/specs/extensions/userhost-in-names-3.2.html)
|
||||||
UserhostInNames,
|
UserhostInNames,
|
||||||
|
/// [metadata](http://ircv3.net/specs/core/metadata-3.2.html)
|
||||||
|
Metadata,
|
||||||
/// Custom IRCv3 capability extensions
|
/// Custom IRCv3 capability extensions
|
||||||
Custom(&'static str),
|
Custom(&'static str),
|
||||||
}
|
}
|
||||||
|
@ -55,6 +57,7 @@ impl AsRef<str> for Capability {
|
||||||
Capability::InviteNotify => "invite-notify",
|
Capability::InviteNotify => "invite-notify",
|
||||||
Capability::ServerTime => "server-time",
|
Capability::ServerTime => "server-time",
|
||||||
Capability::UserhostInNames => "userhost-in-names",
|
Capability::UserhostInNames => "userhost-in-names",
|
||||||
|
Capability::Metadata => "metadata",
|
||||||
Capability::Custom(s) => s,
|
Capability::Custom(s) => s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +81,7 @@ mod test {
|
||||||
assert_eq!(InviteNotify.as_ref(), "invite-notify");
|
assert_eq!(InviteNotify.as_ref(), "invite-notify");
|
||||||
assert_eq!(ServerTime.as_ref(), "server-time");
|
assert_eq!(ServerTime.as_ref(), "server-time");
|
||||||
assert_eq!(UserhostInNames.as_ref(), "userhost-in-names");
|
assert_eq!(UserhostInNames.as_ref(), "userhost-in-names");
|
||||||
|
assert_eq!(Metadata.as_ref(), "metadata");
|
||||||
assert_eq!(Custom("example").as_ref(), "example");
|
assert_eq!(Custom("example").as_ref(), "example");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,8 @@ pub enum Command {
|
||||||
// JOIN(String, Option<String>, Option<String>),
|
// JOIN(String, Option<String>, Option<String>),
|
||||||
|
|
||||||
// IRCv3.2 extensions
|
// IRCv3.2 extensions
|
||||||
|
/// METADATA target COMMAND [params] :[param]
|
||||||
|
METADATA(String, MetadataSubCommand, Option<Vec<String>>, Option<String>),
|
||||||
/// MONITOR command [nicklist]
|
/// MONITOR command [nicklist]
|
||||||
MONITOR(String, Option<String>),
|
MONITOR(String, Option<String>),
|
||||||
/// CHGHOST user host
|
/// CHGHOST user host
|
||||||
|
@ -333,6 +335,11 @@ impl Into<Message> for Command {
|
||||||
Command::ACCOUNT(a) =>
|
Command::ACCOUNT(a) =>
|
||||||
Message::from_owned(None, string("ACCOUNT"), Some(vec![a]), None),
|
Message::from_owned(None, string("ACCOUNT"), Some(vec![a]), None),
|
||||||
|
|
||||||
|
Command::METADATA(t, c, None, p) =>
|
||||||
|
Message::from_owned(None, string("METADATA"), Some(vec![t, c.string()]), p),
|
||||||
|
Command::METADATA(t, c, Some(a), p) =>
|
||||||
|
Message::from_owned(None, string("METADATA"),
|
||||||
|
Some(vec![t, c.string()].into_iter().chain(a).collect()), p),
|
||||||
Command::MONITOR(c, Some(t)) =>
|
Command::MONITOR(c, Some(t)) =>
|
||||||
Message::from_owned(None, string("MONITOR"), Some(vec![c, t]), None),
|
Message::from_owned(None, string("MONITOR"), Some(vec![c, t]), None),
|
||||||
Command::MONITOR(c, None) =>
|
Command::MONITOR(c, None) =>
|
||||||
|
@ -1085,6 +1092,24 @@ impl<'a> From<&'a Message> for Result<Command> {
|
||||||
return Err(invalid_input())
|
return Err(invalid_input())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if let "METADATA" = &m.command[..] {
|
||||||
|
if m.args.len() == 2 {
|
||||||
|
match m.suffix {
|
||||||
|
Some(_) => return Err(invalid_input()),
|
||||||
|
None => match m.args[1].parse() {
|
||||||
|
Ok(c) => Command::METADATA(m.args[0].clone(), c, None, None),
|
||||||
|
Err(_) => return Err(invalid_input()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else if m.args.len() > 2 {
|
||||||
|
match m.args[1].parse() {
|
||||||
|
Ok(c) => Command::METADATA(m.args[0].clone(), c, Some(m.args[1..].to_owned()),
|
||||||
|
m.suffix.clone()),
|
||||||
|
Err(_) => return Err(invalid_input()),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(invalid_input())
|
||||||
|
}
|
||||||
} else if let "MONITOR" = &m.command[..] {
|
} else if let "MONITOR" = &m.command[..] {
|
||||||
if m.args.len() == 1 {
|
if m.args.len() == 1 {
|
||||||
Command::MONITOR(m.args[0].clone(), m.suffix.clone())
|
Command::MONITOR(m.args[0].clone(), m.suffix.clone())
|
||||||
|
@ -1176,6 +1201,51 @@ impl FromStr for CapSubCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A list of all the subcommands for the
|
||||||
|
/// [metadata extension](http://ircv3.net/specs/core/metadata-3.2.html).
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub enum MetadataSubCommand {
|
||||||
|
/// Looks up the value for some keys.
|
||||||
|
GET,
|
||||||
|
/// Lists all of the metadata keys and values.
|
||||||
|
LIST,
|
||||||
|
/// Sets the value for some key.
|
||||||
|
SET,
|
||||||
|
/// Removes all metadata.
|
||||||
|
CLEAR,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MetadataSubCommand {
|
||||||
|
/// Gets the string that corresponds to this subcommand.
|
||||||
|
pub fn to_str(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
&MetadataSubCommand::GET => "GET",
|
||||||
|
&MetadataSubCommand::LIST => "LIST",
|
||||||
|
&MetadataSubCommand::SET => "SET",
|
||||||
|
&MetadataSubCommand::CLEAR => "CLEAR",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This makes some earlier lines shorter.
|
||||||
|
fn string(&self) -> String {
|
||||||
|
self.to_str().to_owned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for MetadataSubCommand {
|
||||||
|
type Err = &'static str;
|
||||||
|
fn from_str(s: &str) -> StdResult<MetadataSubCommand, &'static str> {
|
||||||
|
match s {
|
||||||
|
"GET" => Ok(MetadataSubCommand::GET),
|
||||||
|
"LIST" => Ok(MetadataSubCommand::LIST),
|
||||||
|
"SET" => Ok(MetadataSubCommand::SET),
|
||||||
|
"CLEAR" => Ok(MetadataSubCommand::CLEAR),
|
||||||
|
_ => Err("Failed to parse METADATA subcommand."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Produces an invalid_input IoError.
|
/// Produces an invalid_input IoError.
|
||||||
fn invalid_input() -> Error {
|
fn invalid_input() -> Error {
|
||||||
Error::new(ErrorKind::InvalidInput, "Failed to parse malformed message as command.")
|
Error::new(ErrorKind::InvalidInput, "Failed to parse malformed message as command.")
|
||||||
|
|
|
@ -189,7 +189,12 @@ pub enum Response {
|
||||||
RPL_MONLIST = 732,
|
RPL_MONLIST = 732,
|
||||||
/// 733 <nick> :End of MONITOR list
|
/// 733 <nick> :End of MONITOR list
|
||||||
RPL_ENDOFMONLIST = 733,
|
RPL_ENDOFMONLIST = 733,
|
||||||
|
/// 760 <target> <key> <visibility> :<value>
|
||||||
|
RPL_WHOISKEYVALUE = 760,
|
||||||
|
/// 761 <target> <key> <visibility> :[<value>]
|
||||||
|
RPL_KEYVALUE = 761,
|
||||||
|
/// 762 :end of metadata
|
||||||
|
RPL_METADATAEND = 762,
|
||||||
|
|
||||||
// Error replies
|
// Error replies
|
||||||
/// 401 <nickname> :No such nick/channel
|
/// 401 <nickname> :No such nick/channel
|
||||||
|
@ -300,6 +305,19 @@ pub enum Response {
|
||||||
ERR_USERSDONTMATCH = 502,
|
ERR_USERSDONTMATCH = 502,
|
||||||
/// 734 <nick> <limit> <targets> :Monitor list is full.
|
/// 734 <nick> <limit> <targets> :Monitor list is full.
|
||||||
ERR_MONLISTFULL = 734,
|
ERR_MONLISTFULL = 734,
|
||||||
|
/// 764 <target> :metadata limit reached
|
||||||
|
ERR_METADATALIMIT = 764,
|
||||||
|
/// 765 <target> :invalid metadata target
|
||||||
|
ERR_TARGETINVALID = 765,
|
||||||
|
/// 766 <key> :no matching key
|
||||||
|
ERR_NOMATCHINGKEY = 766,
|
||||||
|
/// 767 <key> :invalid metadata key
|
||||||
|
ERR_KEYINVALID = 767,
|
||||||
|
/// 768 <target> <key> :key not set
|
||||||
|
ERR_KEYNOTSET = 768,
|
||||||
|
/// 769 <target> <key> :permission denied
|
||||||
|
ERR_KEYNOPERMISSION = 779,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
|
@ -329,7 +347,7 @@ impl FromStr for Response {
|
||||||
(rc > 420 && rc < 425) || (rc > 430 && rc < 434) || rc == 436 || rc == 437 ||
|
(rc > 420 && rc < 425) || (rc > 430 && rc < 434) || rc == 436 || rc == 437 ||
|
||||||
(rc > 440 && rc < 447) || rc == 451 || (rc > 460 && rc < 468) ||
|
(rc > 440 && rc < 447) || rc == 451 || (rc > 460 && rc < 468) ||
|
||||||
(rc > 470 && rc < 479) || (rc > 480 && rc < 486) || rc == 491 || rc == 501 ||
|
(rc > 470 && rc < 479) || (rc > 480 && rc < 486) || rc == 491 || rc == 501 ||
|
||||||
rc == 502 || (rc > 729 && rc < 735) {
|
rc == 502 || (rc > 729 && rc < 735) || (rc > 759 && rc < 770 && rc != 763) {
|
||||||
Ok(unsafe { transmute(rc) })
|
Ok(unsafe { transmute(rc) })
|
||||||
} else {
|
} else {
|
||||||
Err("Failed to parse due to unknown response code.")
|
Err("Failed to parse due to unknown response code.")
|
||||||
|
|
Loading…
Add table
Reference in a new issue