From 5f1ffd753af42357c8b074c7a8bc9be2eade002e Mon Sep 17 00:00:00 2001 From: Till Hoeppner Date: Mon, 20 Apr 2015 22:38:56 +0200 Subject: Add reply generation --- src/command.rs | 126 +++--- src/lib.rs | 8 +- src/reply.rs | 1331 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1397 insertions(+), 68 deletions(-) create mode 100644 src/reply.rs (limited to 'src') diff --git a/src/command.rs b/src/command.rs index 828c7a5..1a2324a 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,4 +1,4 @@ -use std::borrow::{ ToOwned, Cow }; +#![allow(non_camel_case_types)] use message::{ Message, MsgType }; @@ -1530,54 +1530,55 @@ pub enum Command<'a> { USERHOST(Vec<&'a str>), } -impl<'a> Command<'a> { - fn to_name(&self) -> &'static str { +/*impl<'a> Command<'a> { + pub fn to_name(&self) -> &'static str { + use self::Command::*; match self { - PASS => "PING", - NICK => "NICK", - USER => "USER", - OPER => "1004", - MODE => "1005", - SERVICE => "1006", - QUIT => "1007", - SQUIT => "1008", - JOIN => "1009", - PART => "1010", - TOPIC => "1011", - NAMES => "1012", - LIST => "1013", - INVITE => "1014", - KICK => "1015", - PRIVMSG => "1016", - NOTICE => "1017", - MOTD => "1018", - LUSERS => "1019", - VERSION => "1020", - STATS => "1021", - LINKS => "1022", - TIME => "1023", - CONNECT => "1024", - TRACE => "1025", - ADMIN => "1026", - INFO => "1027", - SERVLIST => "1028", - SQUERY => "1029", - WHO => "1030", - WHOIS => "1031", - WHOWAS => "1032", - KILL => "1033", - PING => "1034", - PONG => "1035", - ERROR => "1036", - AWAY => "1037", - REHASH => "1038", - DIE => "1039", - RESTART => "1040", - SUMMON => "1041", - USERS => "1042", - WALLOPS => "1043", - USERHOST => "1044", - ISON => "1045", + &PASS => "PING", + &NICK => "NICK", + &USER => "USER", + &OPER => "1004", + &MODE => "1005", + &SERVICE => "1006", + &QUIT => "1007", + &SQUIT => "1008", + &JOIN => "1009", + &PART => "1010", + &TOPIC => "1011", + &NAMES => "1012", + &LIST => "1013", + &INVITE => "1014", + &KICK => "1015", + &PRIVMSG => "1016", + &NOTICE => "1017", + &MOTD => "1018", + &LUSERS => "1019", + &VERSION => "1020", + &STATS => "1021", + &LINKS => "1022", + &TIME => "1023", + &CONNECT => "1024", + &TRACE => "1025", + &ADMIN => "1026", + &INFO => "1027", + &SERVLIST => "1028", + &SQUERY => "1029", + &WHO => "1030", + &WHOIS => "1031", + &WHOWAS => "1032", + &KILL => "1033", + &PING => "1034", + &PONG => "1035", + &ERROR => "1036", + &AWAY => "1037", + &REHASH => "1038", + &DIE => "1039", + &RESTART => "1040", + &SUMMON => "1041", + &USERS => "1042", + &WALLOPS => "1043", + &USERHOST => "1044", + &ISON => "1045", /* RPL_WELCOME => "001", RPL_YOURHOST => "002", @@ -1718,37 +1719,32 @@ impl<'a> Command<'a> { ERR_UMODEUNKNOWNFLAG => "501",*/ } } -} +}*/ impl<'a> Command<'a> { pub fn from_message(msg: &'a Message) -> Option> { - match &msg.command.as_ref()[..] { - "NOTICE" => msg.content.get(0).and_then(|c| msg.content.get(1).map(|t| - Command::NOTICE { to: Cow::Borrowed(&t), content: Cow::Borrowed(&c) })), - "PING" => msg.content.get(0).and_then(|s1| msg.content.get(1).map(|s2| - Command::PING { server1: Some(Cow::Borrowed(&s1)), server2: Some(Cow::Borrowed(&s2)) })), - "001" => Some(Command::RPL_WELCOME), - "002" => Some(Command::RPL_YOURHOST), - "003" => Some(Command::RPL_CREATED), - "004" => Some(Command::RPL_MYINFO), - "451" => Some(Command::ErrNotRegistered), + match msg.command() { + "NOTICE" => msg.content().get(0).and_then(|c| msg.content().get(1).map(|t| + Command::NOTICE(t, c))), + "PING" => msg.content().get(0).map(|s1| + Command::PING(&s1, msg.content().get(1).map(|&s| s))), _ => unimplemented!() } } pub fn to_message(&'a self) -> Message { match self { - &Command::PING { ref server1, ref server2 } => { + &Command::PING(ref server1, ref server2) => { let mut c = Vec::new(); - if let &Some(ref s) = server1 { c.push(s.clone()) } + c.push(server1.clone()); if let &Some(ref s) = server2 { c.push(s.clone()) } - Message::new(None, Cow::Owned("PING".to_owned()), c, None, MsgType::Irc) + Message::format(None, "PING", c, None, MsgType::Irc) }, - &Command::PONG { ref server1, ref server2 } => { + &Command::PONG(ref server1, ref server2) => { let mut c = Vec::new(); - if let &Some(ref s) = server1 { c.push(s.clone()) } + c.push(server1.clone()); if let &Some(ref s) = server2 { c.push(s.clone()) } - Message::new(None, Cow::Owned("PONG".to_owned()), c, None, MsgType::Irc) + Message::format(None, "PONG", c, None, MsgType::Irc) }, _ => unimplemented!() } diff --git a/src/lib.rs b/src/lib.rs index f37c9a4..bf85c49 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(plugin, collections)] +#![feature(plugin, collections, custom_derive)] #![plugin(regex_macros)] extern crate regex; @@ -11,7 +11,8 @@ pub mod color; pub mod ident; pub mod callback; pub mod message; -// pub mod command; +pub mod command; +pub mod reply; use std::io; use std::result; @@ -20,7 +21,8 @@ use std::result; pub enum IrscError { Io(io::Error), AlreadyConnected, - NotConnected + NotConnected, + NotFound } pub type Result = result::Result; diff --git a/src/reply.rs b/src/reply.rs new file mode 100644 index 0000000..005ec80 --- /dev/null +++ b/src/reply.rs @@ -0,0 +1,1331 @@ +use ::{ Result, IrscError }; +use std::str::FromStr; +use std::borrow::ToOwned; +#[allow(non_camel_case_types)] +#[derive(Debug, Hash, PartialEq, Eq)] +pub enum Reply { + /// 001 RPL_WELCOME + /// "Welcome to the Internet Relay Network + /// !@" + RPL_WELCOME = 001, + + /// 002 RPL_YOURHOST + /// "Your host is , running version " + RPL_YOURHOST = 002, + + /// 003 RPL_CREATED + /// "This server was created " + RPL_CREATED = 003, + + /// 004 RPL_MYINFO + /// " + /// " + /// + /// - The server sends Replies 001 to 004 to a user upon + /// successful registration. + /// + RPL_MYINFO = 004, + + /// 005 RPL_BOUNCE + /// "Try server , port " + /// + /// - Sent by the server to a user to suggest an alternative + /// server. This is often used when the connection is + /// refused because the server is already full. + /// + RPL_BOUNCE = 005, + + /// 302 RPL_USERHOST + /// ":*1 *( " " )" + /// + /// - Reply format used by USERHOST to list replies to + /// the query list. The reply string is composed as + /// follows: + /// + /// reply = nickname [ "*" ] "=" ( "+" / "-" ) hostname + /// + /// The '*' indicates whether the client has registered + /// as an Operator. The '-' or '+' characters represent + /// whether the client has set an AWAY message or not + /// respectively. + /// + RPL_USERHOST = 302, + + /// 303 RPL_ISON + /// ":*1 *( " " )" + /// + /// - Reply format used by ISON to list replies to the + /// query list. + /// + RPL_ISON = 303, + + /// 301 RPL_AWAY + /// " :" + RPL_AWAY = 301, + + /// 305 RPL_UNAWAY + /// ":You are no longer marked as being away" + RPL_UNAWAY = 305, + + /// 306 RPL_NOWAWAY + /// ":You have been marked as being away" + /// + /// - These replies are used with the AWAY command (if + /// allowed). RPL_AWAY is sent to any client sending a + /// PRIVMSG to a client which is away. RPL_AWAY is only + /// sent by the server to which the client is connected. + /// Replies RPL_UNAWAY and RPL_NOWAWAY are sent when the + /// client removes and sets an AWAY message. + /// + RPL_NOWAWAY = 306, + + /// 311 RPL_WHOISUSER + /// " * :" + RPL_WHOISUSER = 311, + + /// 312 RPL_WHOISSERVER + /// " :" + RPL_WHOISSERVER = 312, + + /// 313 RPL_WHOISOPERATOR + /// " :is an IRC operator" + RPL_WHOISOPERATOR = 313, + + /// 317 RPL_WHOISIDLE + /// " :seconds idle" + RPL_WHOISIDLE = 317, + + /// 318 RPL_ENDOFWHOIS + /// " :End of WHOIS list" + RPL_ENDOFWHOIS = 318, + + /// 319 RPL_WHOISCHANNELS + /// " :*( ( "@" / "+" ) " " )" + /// + /// - Replies 311 - 313, 317 - 319 are all replies + /// generated in response to a WHOIS message. Given that + /// there are enough parameters present, the answering + /// server MUST either formulate a reply out of the above + /// numerics (if the query nick is found) or return an + /// error reply. The '*' in RPL_WHOISUSER is there as + /// the literal character and not as a wild card. For + /// each reply set, only RPL_WHOISCHANNELS may appear + /// more than once (for long lists of channel names). + /// The '@' and '+' characters next to the channel name + /// indicate whether a client is a channel operator or + /// has been granted permission to speak on a moderated + /// channel. The RPL_ENDOFWHOIS reply is used to mark + /// the end of processing a WHOIS message. + /// + RPL_WHOISCHANNELS = 319, + + /// 314 RPL_WHOWASUSER + /// " * :" + RPL_WHOWASUSER = 314, + + /// 369 RPL_ENDOFWHOWAS + /// " :End of WHOWAS" + /// + /// - When replying to a WHOWAS message, a server MUST use + /// the replies RPL_WHOWASUSER, RPL_WHOISSERVER or + /// ERR_WASNOSUCHNICK for each nickname in the presented + /// list. At the end of all reply batches, there MUST + /// be RPL_ENDOFWHOWAS (even if there was only one reply + /// and it was an error). + /// + RPL_ENDOFWHOWAS = 369, + + /// 321 RPL_LISTSTART + /// Obsolete. Not used. + /// + RPL_LISTSTART = 321, + + /// 322 RPL_LIST + /// " <# visible> :" + RPL_LIST = 322, + + /// 323 RPL_LISTEND + /// ":End of LIST" + /// + /// - Replies RPL_LIST, RPL_LISTEND mark the actual replies + /// with data and end of the server's response to a LIST + /// command. If there are no channels available to return, + /// only the end reply MUST be sent. + /// + RPL_LISTEND = 323, + + /// 325 RPL_UNIQOPIS + /// " " + /// + RPL_UNIQOPIS = 325, + + /// 324 RPL_CHANNELMODEIS + /// " " + /// + RPL_CHANNELMODEIS = 324, + + /// 331 RPL_NOTOPIC + /// " :No topic is set" + RPL_NOTOPIC = 331, + + /// 332 RPL_TOPIC + /// " :" + /// + /// - When sending a TOPIC message to determine the + /// channel topic, one of two replies is sent. If + /// the topic is set, RPL_TOPIC is sent back else + /// RPL_NOTOPIC. + /// + RPL_TOPIC = 332, + + /// 341 RPL_INVITING + /// " " + /// + /// - Returned by the server to indicate that the + /// attempted INVITE message was successful and is + /// being passed onto the end client. + /// + RPL_INVITING = 341, + + /// 342 RPL_SUMMONING + /// " :Summoning user to IRC" + /// + /// - Returned by a server answering a SUMMON message to + /// indicate that it is summoning that user. + /// + RPL_SUMMONING = 342, + + /// 346 RPL_INVITELIST + /// " " + RPL_INVITELIST = 346, + + /// 347 RPL_ENDOFINVITELIST + /// " :End of channel invite list" + /// + /// - When listing the 'invitations masks' for a given channel, + /// a server is required to send the list back using the + /// RPL_INVITELIST and RPL_ENDOFINVITELIST messages. A + /// separate RPL_INVITELIST is sent for each active mask. + /// After the masks have been listed (or if none present) a + /// RPL_ENDOFINVITELIST MUST be sent. + /// + RPL_ENDOFINVITELIST = 347, + + /// 348 RPL_EXCEPTLIST + /// " " + RPL_EXCEPTLIST = 348, + + /// 349 RPL_ENDOFEXCEPTLIST + /// " :End of channel exception list" + /// + /// - When listing the 'exception masks' for a given channel, + /// a server is required to send the list back using the + /// RPL_EXCEPTLIST and RPL_ENDOFEXCEPTLIST messages. A + /// separate RPL_EXCEPTLIST is sent for each active mask. + /// After the masks have been listed (or if none present) + /// a RPL_ENDOFEXCEPTLIST MUST be sent. + /// + RPL_ENDOFEXCEPTLIST = 349, + + /// 351 RPL_VERSION + /// ". :" + /// + /// - Reply by the server showing its version details. + /// The is the version of the software being + /// used (including any patchlevel revisions) and the + /// is used to indicate if the server is + /// running in "debug mode". + /// + /// The "comments" field may contain any comments about + /// the version or further version details. + /// + RPL_VERSION = 351, + + /// 352 RPL_WHOREPLY + /// " + /// ( "H" / "G" > ["*"] [ ( "@" / "+" ) ] + /// : " + /// + RPL_WHOREPLY = 352, + + /// 315 RPL_ENDOFWHO + /// " :End of WHO list" + /// + /// - The RPL_WHOREPLY and RPL_ENDOFWHO pair are used + /// to answer a WHO message. The RPL_WHOREPLY is only + /// sent if there is an appropriate match to the WHO + /// query. If there is a list of parameters supplied + /// with a WHO message, a RPL_ENDOFWHO MUST be sent + /// after processing each list item with being + /// the item. + /// + RPL_ENDOFWHO = 315, + + /// 353 RPL_NAMREPLY + /// "( "=" / "*" / "@" ) + /// :[ "@" / "+" ] *( " " [ "@" / "+" ] ) + /// - "@" is used for secret channels, "*" for private + /// channels, and "=" for others (public channels). + /// + RPL_NAMREPLY = 353, + + /// 366 RPL_ENDOFNAMES + /// " :End of NAMES list" + /// + /// - To reply to a NAMES message, a reply pair consisting + /// of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the + /// server back to the client. If there is no channel + /// found as in the query, then only RPL_ENDOFNAMES is + /// returned. The exception to this is when a NAMES + /// message is sent with no parameters and all visible + /// channels and contents are sent back in a series of + /// RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark + /// the end. + /// + RPL_ENDOFNAMES = 366, + + /// 364 RPL_LINKS + /// " : " + RPL_LINKS = 364, + + /// 365 RPL_ENDOFLINKS + /// " :End of LINKS list" + /// + /// - In replying to the LINKS message, a server MUST send + /// replies back using the RPL_LINKS numeric and mark the + /// end of the list using an RPL_ENDOFLINKS reply. + /// + RPL_ENDOFLINKS = 365, + + /// 367 RPL_BANLIST + /// " " + RPL_BANLIST = 367, + + /// 368 RPL_ENDOFBANLIST + /// " :End of channel ban list" + /// + /// - When listing the active 'bans' for a given channel, + /// a server is required to send the list back using the + /// RPL_BANLIST and RPL_ENDOFBANLIST messages. A separate + /// RPL_BANLIST is sent for each active banmask. After the + /// banmasks have been listed (or if none present) a + /// RPL_ENDOFBANLIST MUST be sent. + /// + RPL_ENDOFBANLIST = 368, + + /// 371 RPL_INFO + /// ":" + RPL_INFO = 371, + + /// 374 RPL_ENDOFINFO + /// ":End of INFO list" + /// + /// - A server responding to an INFO message is required to + /// send all its 'info' in a series of RPL_INFO messages + /// with a RPL_ENDOFINFO reply to indicate the end of the + /// replies. + /// + RPL_ENDOFINFO = 374, + + /// 375 RPL_MOTDSTART + /// ":- Message of the day - " + RPL_MOTDSTART = 375, + + /// 372 RPL_MOTD + /// ":- " + RPL_MOTD = 372, + + /// 376 RPL_ENDOFMOTD + /// ":End of MOTD command" + /// + /// - When responding to the MOTD message and the MOTD file + /// is found, the file is displayed line by line, with + /// each line no longer than 80 characters, using + /// RPL_MOTD format replies. These MUST be surrounded + /// by a RPL_MOTDSTART (before the RPL_MOTDs) and an + /// RPL_ENDOFMOTD (after). + /// + RPL_ENDOFMOTD = 376, + + /// 381 RPL_YOUREOPER + /// ":You are now an IRC operator" + /// + /// - RPL_YOUREOPER is sent back to a client which has + /// just successfully issued an OPER message and gained + /// operator status. + /// + RPL_YOUREOPER = 381, + + /// 382 RPL_REHASHING + /// " :Rehashing" + /// + /// - If the REHASH option is used and an operator sends + /// a REHASH message, an RPL_REHASHING is sent back to + /// the operator. + /// + RPL_REHASHING = 382, + + /// 383 RPL_YOURESERVICE + /// "You are service " + /// + /// - Sent by the server to a service upon successful + /// registration. + /// + RPL_YOURESERVICE = 383, + + /// 391 RPL_TIME + /// " :" + /// + /// - When replying to the TIME message, a server MUST send + /// the reply using the RPL_TIME format above. The string + /// showing the time need only contain the correct day and + /// time there. There is no further requirement for the + /// time string. + /// + RPL_TIME = 391, + + /// 392 RPL_USERSSTART + /// ":UserID Terminal Host" + RPL_USERSSTART = 392, + + /// 393 RPL_USERS + /// ": " + RPL_USERS = 393, + + /// 394 RPL_ENDOFUSERS + /// ":End of users" + RPL_ENDOFUSERS = 394, + + /// 395 RPL_NOUSERS + /// ":Nobody logged in" + /// + /// - If the USERS message is handled by a server, the + /// replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and + /// RPL_NOUSERS are used. RPL_USERSSTART MUST be sent + /// first, following by either a sequence of RPL_USERS + /// or a single RPL_NOUSER. Following this is + /// RPL_ENDOFUSERS. + /// + RPL_NOUSERS = 395, + + /// 200 RPL_TRACELINK + /// "Link + /// V + /// + /// " + RPL_TRACELINK = 200, + + /// 201 RPL_TRACECONNECTING + /// "Try. " + RPL_TRACECONNECTING = 201, + + /// 202 RPL_TRACEHANDSHAKE + /// "H.S. " + RPL_TRACEHANDSHAKE = 202, + + /// 203 RPL_TRACEUNKNOWN + /// "???? []" + RPL_TRACEUNKNOWN = 203, + + /// 204 RPL_TRACEOPERATOR + /// "Oper " + RPL_TRACEOPERATOR = 204, + + /// 205 RPL_TRACEUSER + /// "User " + RPL_TRACEUSER = 205, + + /// 206 RPL_TRACESERVER + /// "Serv S C + /// @ V" + RPL_TRACESERVER = 206, + + /// 207 RPL_TRACESERVICE + /// "Service " + RPL_TRACESERVICE = 207, + + /// 208 RPL_TRACENEWTYPE + /// " 0 " + RPL_TRACENEWTYPE = 208, + + /// 209 RPL_TRACECLASS + /// "Class " + RPL_TRACECLASS = 209, + + /// 210 RPL_TRACERECONNECT + /// Unused. + RPL_TRACERECONNECT = 210, + + /// 261 RPL_TRACELOG + /// "File " + RPL_TRACELOG = 261, + + /// 262 RPL_TRACEEND + /// " :End of TRACE" + /// + /// - The RPL_TRACE* are all returned by the server in + /// response to the TRACE message. How many are + /// returned is dependent on the TRACE message and + /// whether it was sent by an operator or not. There + /// is no predefined order for which occurs first. + /// Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and + /// RPL_TRACEHANDSHAKE are all used for connections + /// which have not been fully established and are either + /// unknown, still attempting to connect or in the + /// process of completing the 'server handshake'. + /// RPL_TRACELINK is sent by any server which handles + /// a TRACE message and has to pass it on to another + /// server. The list of RPL_TRACELINKs sent in + /// response to a TRACE command traversing the IRC + /// network should reflect the actual connectivity of + /// the servers themselves along that path. + /// + /// RPL_TRACENEWTYPE is to be used for any connection + /// which does not fit in the other categories but is + /// being displayed anyway. + /// RPL_TRACEEND is sent to indicate the end of the list. + /// + RPL_TRACEEND = 262, + + /// 211 RPL_STATSLINKINFO + /// " + /// + ///