diff options
author | Tom Gilbert <tom@linuxbrit.co.uk> | 2004-10-09 01:51:05 +0000 |
---|---|---|
committer | Tom Gilbert <tom@linuxbrit.co.uk> | 2004-10-09 01:51:05 +0000 |
commit | 0f3e302547363ea237454dda891ddb5de1be4476 (patch) | |
tree | ec45be24a669ee28b5e2da4ff65e39265a418e0b /rbot/rfc2812.rb |
initial import of rbot
Diffstat (limited to 'rbot/rfc2812.rb')
-rw-r--r-- | rbot/rfc2812.rb | 1027 |
1 files changed, 1027 insertions, 0 deletions
diff --git a/rbot/rfc2812.rb b/rbot/rfc2812.rb new file mode 100644 index 00000000..6f459c80 --- /dev/null +++ b/rbot/rfc2812.rb @@ -0,0 +1,1027 @@ +module Irc + # RFC 2812 Internet Relay Chat: Client Protocol + # + RPL_WELCOME=001 + # "Welcome to the Internet Relay Network + # <nick>!<user>@<host>" + RPL_YOURHOST=002 + # "Your host is <servername>, running version <ver>" + RPL_CREATED=003 + # "This server was created <date>" + RPL_MYINFO=004 + # "<servername> <version> <available user modes> + # <available channel modes>" + # + # - The server sends Replies 001 to 004 to a user upon + # successful registration. + # + RPL_BOUNCE=005 + # "Try server <server name>, port <port number>" + # + # - 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_USERHOST=302 + # ":*1<reply> *( " " <reply> )" + # + # - 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_ISON=303 + # ":*1<nick> *( " " <nick> )" + # + # - Reply format used by ISON to list replies to the + # query list. + # + RPL_AWAY=301 + # "<nick> :<away message>" + RPL_UNAWAY=305 + # ":You are no longer marked as being away" + RPL_NOWAWAY=306 + # ":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_WHOISUSER=311 + # "<nick> <user> <host> * :<real name>" + RPL_WHOISSERVER=312 + # "<nick> <server> :<server info>" + RPL_WHOISOPERATOR=313 + # "<nick> :is an IRC operator" + RPL_WHOISIDLE=317 + # "<nick> <integer> :seconds idle" + RPL_ENDOFWHOIS=318 + # "<nick> :End of WHOIS list" + RPL_WHOISCHANNELS=319 + # "<nick> :*( ( "@" / "+" ) <channel> " " )" + # + # - 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_WHOWASUSER=314 + # "<nick> <user> <host> * :<real name>" + RPL_ENDOFWHOWAS=369 + # "<nick> :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_LISTSTART=321 + # Obsolete. Not used. + # + RPL_LIST=322 + # "<channel> <# visible> :<topic>" + RPL_LISTEND=323 + # ":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_UNIQOPIS=325 + # "<channel> <nickname>" + # + RPL_CHANNELMODEIS=324 + # "<channel> <mode> <mode params>" + # + RPL_NOTOPIC=331 + # "<channel> :No topic is set" + RPL_TOPIC=332 + # "<channel> :<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_INFO=333 + # <channel> <set by> <unixtime> + RPL_INVITING=341 + # "<channel> <nick>" + # + # - Returned by the server to indicate that the + # attempted INVITE message was successful and is + # being passed onto the end client. + # + RPL_SUMMONING=342 + # "<user> :Summoning user to IRC" + # + # - Returned by a server answering a SUMMON message to + # indicate that it is summoning that user. + # + RPL_INVITELIST=346 + # "<channel> <invitemask>" + RPL_ENDOFINVITELIST=347 + # "<channel> :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_EXCEPTLIST=348 + # "<channel> <exceptionmask>" + RPL_ENDOFEXCEPTLIST=349 + # "<channel> :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_VERSION=351 + # "<version>.<debuglevel> <server> :<comments>" + # + # - Reply by the server showing its version details. + # The <version> is the version of the software being + # used (including any patchlevel revisions) and the + # <debuglevel> 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_WHOREPLY=352 + # "<channel> <user> <host> <server> <nick> + # ( "H" / "G" > ["*"] [ ( "@" / "+" ) ] + # :<hopcount> <real name>" + # + RPL_ENDOFWHO=315 + # "<name> :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 <name> being + # the item. + # + RPL_NAMREPLY=353 + # "( "=" / "*" / "@" ) <channel> + # :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> ) + # - "@" is used for secret channels, "*" for private + # channels, and "=" for others (public channels). + # + RPL_ENDOFNAMES=366 + # "<channel> :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_LINKS=364 + # "<mask> <server> :<hopcount> <server info>" + RPL_ENDOFLINKS=365 + # "<mask> :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_BANLIST=367 + # "<channel> <banmask>" + RPL_ENDOFBANLIST=368 + # "<channel> :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_INFO=371 + # ":<string>" + RPL_ENDOFINFO=374 + # ":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_MOTDSTART=375 + # ":- <server> Message of the day - " + RPL_MOTD=372 + # ":- <text>" + RPL_ENDOFMOTD=376 + # ":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_YOUREOPER=381 + # ":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_REHASHING=382 + # "<config file> :Rehashing" + # + # - If the REHASH option is used and an operator sends + # a REHASH message, an RPL_REHASHING is sent back to + # the operator. + # + RPL_YOURESERVICE=383 + # "You are service <servicename>" + # + # - Sent by the server to a service upon successful + # registration. + # + RPL_TIME=391 + # "<server> :<string showing server's local 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_USERSSTART=392 + # ":UserID Terminal Host" + RPL_USERS=393 + # ":<username> <ttyline> <hostname>" + RPL_ENDOFUSERS=394 + # ":End of users" + RPL_NOUSERS=395 + # ":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_TRACELINK=200 + # "Link <version & debug level> <destination> + # <next server> V<protocol version> + # <link uptime in seconds> <backstream sendq> + # <upstream sendq>" + RPL_TRACECONNECTING=201 + # "Try. <class> <server>" + RPL_TRACEHANDSHAKE=202 + # "H.S. <class> <server>" + RPL_TRACEUNKNOWN=203 + # "???? <class> [<client IP address in dot form>]" + RPL_TRACEOPERATOR=204 + # "Oper <class> <nick>" + RPL_TRACEUSER=205 + # "User <class> <nick>" + RPL_TRACESERVER=206 + # "Serv <class> <int>S <int>C <server> + # <nick!user|*!*>@<host|server> V<protocol version>" + RPL_TRACESERVICE=207 + # "Service <class> <name> <type> <active type>" + RPL_TRACENEWTYPE=208 + # "<newtype> 0 <client name>" + RPL_TRACECLASS=209 + # "Class <class> <count>" + RPL_TRACERECONNECT=210 + # Unused. + RPL_TRACELOG=261 + # "File <logfile> <debug level>" + RPL_TRACEEND=262 + # "<server name> <version & debug level> :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_STATSLINKINFO=211 + # "<linkname> <sendq> <sent messages> + # <sent Kbytes> <received messages> + # <received Kbytes> <time open>" + # + # - reports statistics on a connection. <linkname> + # identifies the particular connection, <sendq> is + # the amount of data that is queued and waiting to be + # sent <sent messages> the number of messages sent, + # and <sent Kbytes> the amount of data sent, in + # Kbytes. <received messages> and <received Kbytes> + # are the equivalent of <sent messages> and <sent + # Kbytes> for received data, respectively. <time + # open> indicates how long ago the connection was + # opened, in seconds. + # + RPL_STATSCOMMANDS=212 + # "<command> <count> <byte count> <remote count>" + # + # - reports statistics on commands usage. + # + RPL_ENDOFSTATS=219 + # "<stats letter> :End of STATS report" + # + RPL_STATSUPTIME=242 + # ":Server Up %d days %d:%02d:%02d" + # + # - reports the server uptime. + # + RPL_STATSOLINE=243 + # "O <hostmask> * <name>" + # + # - reports the allowed hosts from where user may become IRC + # operators. + # + RPL_UMODEIS=221 + # "<user mode string>" + # + # - To answer a query about a client's own mode, + # RPL_UMODEIS is sent back. + # + RPL_SERVLIST=234 + # "<name> <server> <mask> <type> <hopcount> <info>" + # + RPL_SERVLISTEND=235 + # "<mask> <type> :End of service listing" + # + # - When listing services in reply to a SERVLIST message, + # a server is required to send the list back using the + # RPL_SERVLIST and RPL_SERVLISTEND messages. A separate + # RPL_SERVLIST is sent for each service. After the + # services have been listed (or if none present) a + # RPL_SERVLISTEND MUST be sent. + # + RPL_LUSERCLIENT=251 + # ":There are <integer> users and <integer> + # services on <integer> servers" + RPL_LUSEROP=252 + # "<integer> :operator(s) online" + RPL_LUSERUNKNOWN=253 + # "<integer> :unknown connection(s)" + RPL_LUSERCHANNELS=254 + # "<integer> :channels formed" + RPL_LUSERME=255 + # ":I have <integer> clients and <integer> + # servers" + # + # - In processing an LUSERS message, the server + # sends a set of replies from RPL_LUSERCLIENT, + # RPL_LUSEROP, RPL_USERUNKNOWN, + # RPL_LUSERCHANNELS and RPL_LUSERME. When + # replying, a server MUST send back + # RPL_LUSERCLIENT and RPL_LUSERME. The other + # replies are only sent back if a non-zero count + # is found for them. + # + RPL_ADMINME=256 + # "<server> :Administrative info" + RPL_ADMINLOC1=257 + # ":<admin info>" + RPL_ADMINLOC2=258 + # ":<admin info>" + RPL_ADMINEMAIL=259 + # ":<admin info>" + # + # - When replying to an ADMIN message, a server + # is expected to use replies RPL_ADMINME + # through to RPL_ADMINEMAIL and provide a text + # message with each. For RPL_ADMINLOC1 a + # description of what city, state and country + # the server is in is expected, followed by + # details of the institution (RPL_ADMINLOC2) + # and finally the administrative contact for the + # server (an email address here is REQUIRED) + # in RPL_ADMINEMAIL. + # + RPL_TRYAGAIN=263 + # "<command> :Please wait a while and try again." + # + # - When a server drops a command without processing it, + # it MUST use the reply RPL_TRYAGAIN to inform the + # originating client. + # + # 5.2 Error Replies + # + # Error replies are found in the range from 400 to 599. + # + ERR_NOSUCHNICK=401 + # "<nickname> :No such nick/channel" + # + # - Used to indicate the nickname parameter supplied to a + # command is currently unused. + # + ERR_NOSUCHSERVER=402 + # "<server name> :No such server" + # + # - Used to indicate the server name given currently + # does not exist. + # + ERR_NOSUCHCHANNEL=403 + # "<channel name> :No such channel" + # + # - Used to indicate the given channel name is invalid. + # + ERR_CANNOTSENDTOCHAN=404 + # "<channel name> :Cannot send to channel" + # + # - Sent to a user who is either (a) not on a channel + # which is mode +n or (b) not a chanop (or mode +v) on + # a channel which has mode +m set or where the user is + # banned and is trying to send a PRIVMSG message to + # that channel. + # + ERR_TOOMANYCHANNELS=405 + # "<channel name> :You have joined too many channels" + # + # - Sent to a user when they have joined the maximum + # number of allowed channels and they try to join + # another channel. + # + ERR_WASNOSUCHNICK=406 + # "<nickname> :There was no such nickname" + # + # - Returned by WHOWAS to indicate there is no history + # information for that nickname. + # + ERR_TOOMANYTARGETS=407 + # "<target> :<error code> recipients. <abort message>" + # + # - Returned to a client which is attempting to send a + # PRIVMSG/NOTICE using the user@host destination format + # and for a user@host which has several occurrences. + # + # - Returned to a client which trying to send a + # PRIVMSG/NOTICE to too many recipients. + # + # - Returned to a client which is attempting to JOIN a safe + # channel using the shortname when there are more than one + # such channel. + # + ERR_NOSUCHSERVICE=408 + # "<service name> :No such service" + # + # - Returned to a client which is attempting to send a SQUERY + # to a service which does not exist. + # + ERR_NOORIGIN=409 + # ":No origin specified" + # + # - PING or PONG message missing the originator parameter. + # + ERR_NORECIPIENT=411 + # ":No recipient given (<command>)" + ERR_NOTEXTTOSEND=412 + # ":No text to send" + ERR_NOTOPLEVEL=413 + # "<mask> :No toplevel domain specified" + ERR_WILDTOPLEVEL=414 + # "<mask> :Wildcard in toplevel domain" + ERR_BADMASK=415 + # "<mask> :Bad Server/host mask" + # + # - 412 - 415 are returned by PRIVMSG to indicate that + # the message wasn't delivered for some reason. + # ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that + # are returned when an invalid use of + # "PRIVMSG $<server>" or "PRIVMSG #<host>" is attempted. + # + ERR_UNKNOWNCOMMAND=421 + # "<command> :Unknown command" + # + # - Returned to a registered client to indicate that the + # command sent is unknown by the server. + # + ERR_NOMOTD=422 + # ":MOTD File is missing" + # + # - Server's MOTD file could not be opened by the server. + # + ERR_NOADMININFO=423 + # "<server> :No administrative info available" + # + # - Returned by a server in response to an ADMIN message + # when there is an error in finding the appropriate + # information. + # + ERR_FILEERROR=424 + # ":File error doing <file op> on <file>" + # + # - Generic error message used to report a failed file + # operation during the processing of a message. + # + ERR_NONICKNAMEGIVEN=431 + # ":No nickname given" + # + # - Returned when a nickname parameter expected for a + # command and isn't found. + # + ERR_ERRONEUSNICKNAME=432 + # "<nick> :Erroneous nickname" + # + # - Returned after receiving a NICK message which contains + # characters which do not fall in the defined set. See + # section 2.3.1 for details on valid nicknames. + # + ERR_NICKNAMEINUSE=433 + # "<nick> :Nickname is already in use" + # + # - Returned when a NICK message is processed that results + # in an attempt to change to a currently existing + # nickname. + # + ERR_NICKCOLLISION=436 + # "<nick> :Nickname collision KILL from <user>@<host>" + # + # - Returned by a server to a client when it detects a + # nickname collision (registered of a NICK that + # already exists by another server). + # + ERR_UNAVAILRESOURCE=437 + # "<nick/channel> :Nick/channel is temporarily unavailable" + # + # - Returned by a server to a user trying to join a channel + # currently blocked by the channel delay mechanism. + # + # - Returned by a server to a user trying to change nickname + # when the desired nickname is blocked by the nick delay + # mechanism. + # + ERR_USERNOTINCHANNEL=441 + # "<nick> <channel> :They aren't on that channel" + # + # - Returned by the server to indicate that the target + # user of the command is not on the given channel. + # + ERR_NOTONCHANNEL=442 + # "<channel> :You're not on that channel" + # + # - Returned by the server whenever a client tries to + # perform a channel affecting command for which the + # client isn't a member. + # + ERR_USERONCHANNEL=443 + # "<user> <channel> :is already on channel" + # + # - Returned when a client tries to invite a user to a + # channel they are already on. + # + ERR_NOLOGIN=444 + # "<user> :User not logged in" + # + # - Returned by the summon after a SUMMON command for a + # user was unable to be performed since they were not + # logged in. + # + # + ERR_SUMMONDISABLED=445 + # ":SUMMON has been disabled" + # + # - Returned as a response to the SUMMON command. MUST be + # returned by any server which doesn't implement it. + # + ERR_USERSDISABLED=446 + # ":USERS has been disabled" + # + # - Returned as a response to the USERS command. MUST be + # returned by any server which does not implement it. + # + ERR_NOTREGISTERED=451 + # ":You have not registered" + # + # - Returned by the server to indicate that the client + # MUST be registered before the server will allow it + # to be parsed in detail. + # + ERR_NEEDMOREPARAMS=461 + # "<command> :Not enough parameters" + # + # - Returned by the server by numerous commands to + # indicate to the client that it didn't supply enough + # parameters. + # + ERR_ALREADYREGISTRED=462 + # ":Unauthorized command (already registered)" + # + # - Returned by the server to any link which tries to + # change part of the registered details (such as + # password or user details from second USER message). + # + ERR_NOPERMFORHOST=463 + # ":Your host isn't among the privileged" + # + # - Returned to a client which attempts to register with + # a server which does not been setup to allow + # connections from the host the attempted connection + # is tried. + # + ERR_PASSWDMISMATCH=464 + # ":Password incorrect" + # + # - Returned to indicate a failed attempt at registering + # a connection for which a password was required and + # was either not given or incorrect. + # + ERR_YOUREBANNEDCREEP=465 + # ":You are banned from this server" + # + # - Returned after an attempt to connect and register + # yourself with a server which has been setup to + # explicitly deny connections to you. + # + ERR_YOUWILLBEBANNED=466 + # + # - Sent by a server to a user to inform that access to the + # server will soon be denied. + # + ERR_KEYSET=467 + # "<channel> :Channel key already set" + ERR_CHANNELISFULL=471 + # "<channel> :Cannot join channel (+l)" + ERR_UNKNOWNMODE=472 + # "<char> :is unknown mode char to me for <channel>" + ERR_INVITEONLYCHAN=473 + # "<channel> :Cannot join channel (+i)" + ERR_BANNEDFROMCHAN=474 + # "<channel> :Cannot join channel (+b)" + ERR_BADCHANNELKEY=475 + # "<channel> :Cannot join channel (+k)" + ERR_BADCHANMASK=476 + # "<channel> :Bad Channel Mask" + ERR_NOCHANMODES=477 + # "<channel> :Channel doesn't support modes" + ERR_BANLISTFULL=478 + # "<channel> <char> :Channel list is full" + # + ERR_NOPRIVILEGES=481 + # ":Permission Denied- You're not an IRC operator" + # + # - Any command requiring operator privileges to operate + # MUST return this error to indicate the attempt was + # unsuccessful. + # + ERR_CHANOPRIVSNEEDED=482 + # "<channel> :You're not channel operator" + # + # - Any command requiring 'chanop' privileges (such as + # MODE messages) MUST return this error if the client + # making the attempt is not a chanop on the specified + # channel. + # + # + ERR_CANTKILLSERVER=483 + # ":You can't kill a server!" + # + # - Any attempts to use the KILL command on a server + # are to be refused and this error returned directly + # to the client. + # + ERR_RESTRICTED=484 + # ":Your connection is restricted!" + # + # - Sent by the server to a user upon connection to indicate + # the restricted nature of the connection (user mode "+r"). + # + ERR_UNIQOPPRIVSNEEDED=485 + # ":You're not the original channel operator" + # + # - Any MODE requiring "channel creator" privileges MUST + # return this error if the client making the attempt is not + # a chanop on the specified channel. + # + ERR_NOOPERHOST=491 + # ":No O-lines for your host" + # + # - If a client sends an OPER message and the server has + # not been configured to allow connections from the + # client's host as an operator, this error MUST be + # returned. + # + ERR_UMODEUNKNOWNFLAG=501 + # ":Unknown MODE flag" + # + # - Returned by the server to indicate that a MODE + # message was sent with a nickname parameter and that + # the a mode flag sent was not recognized. + # + ERR_USERSDONTMATCH=502 + # ":Cannot change mode for other users" + # + # - Error sent to any user trying to view or change the + # user mode for a user other than themselves. + # + # 5.3 Reserved numerics + # + # These numerics are not described above since they fall into one of + # the following categories: + # + # 1. no longer in use; + # + # 2. reserved for future planned use; + # + # 3. in current use but are part of a non-generic 'feature' of + # the current IRC server. + RPL_SERVICEINFO=231 + RPL_ENDOFSERVICES=232 + RPL_SERVICE=233 + RPL_NONE=300 + RPL_WHOISCHANOP=316 + RPL_KILLDONE=361 + RPL_CLOSING=362 + RPL_CLOSEEND=363 + RPL_INFOSTART=373 + RPL_MYPORTIS=384 + RPL_STATSCLINE=213 + RPL_STATSNLINE=214 + RPL_STATSILINE=215 + RPL_STATSKLINE=216 + RPL_STATSQLINE=217 + RPL_STATSYLINE=218 + RPL_STATSVLINE=240 + RPL_STATSLLINE=241 + RPL_STATSHLINE=244 + RPL_STATSSLINE=244 + RPL_STATSPING=246 + RPL_STATSBLINE=247 + RPL_STATSDLINE=250 + ERR_NOSERVICEHOST=492 + + # implements RFC 2812 and prior IRC RFCs. + # clients register handler proc{}s for different server events and IrcClient + # handles dispatch + class IrcClient + # create a new IrcClient instance + def initialize + @handlers = Hash.new + @users = Array.new + end + + # key:: server event to handle + # value:: proc object called when event occurs + # set a handler for a server event + # + # ==server events currently supported: + # + # PING:: server pings you (default handler returns a pong) + # NICKTAKEN:: you tried to change nick to one that's in use + # BADNICK:: you tried to change nick to one that's invalid + # TOPIC:: someone changed the topic of a channel + # TOPICINFO:: on joining a channel or asking for the topic, tells you + # who set it and when + # NAMES:: server sends list of channel members when you join + # WELCOME:: server welcome message on connect + # MOTD:: server message of the day + # PRIVMSG:: privmsg, the core of IRC, a message to you from someone + # PUBLIC:: optionally instead of getting privmsg you can hook to only + # the public ones... + # MSG:: or only the private ones, or both + # KICK:: someone got kicked from a channel + # PART:: someone left a channel + # QUIT:: someone quit IRC + # JOIN:: someone joined a channel + # CHANGETOPIC:: the topic of a channel changed + # INVITE:: you are invited to a channel + # NICK:: someone changed their nick + # MODE:: a mode change + # NOTICE:: someone sends you a notice + # UNKNOWN:: any other message not handled by the above + def []=(key, value) + @handlers[key] = value + end + + # key:: event name + # remove a handler for a server event + def deletehandler(key) + @handlers.delete(key) + end + + # takes a server string, checks for PING, PRIVMSG, NOTIFY, etc, and parses + # numeric server replies, calling the appropriate handler for each, and + # sending it a hash containing the data from the server + def process(serverstring) + data = Hash.new + data["SERVERSTRING"] = serverstring + + unless serverstring =~ /^(:(\S+)\s)?(\S+)(\s(.*))?/ + raise "Unparseable Server Message!!!: #{serverstring}" + end + + prefix, command, params = $2, $3, $5 + + if prefix != nil + data['SOURCE'] = prefix + if prefix =~ /^(\S+)!(\S+)$/ + data['SOURCENICK'] = $1 + data['SOURCEADDRESS'] = $2 + end + end + + # split parameters in an array + argv = [] + params.scan(/(?!:)(\S+)|:(.*)/) { argv << ($1 || $2) } if params + + case command + when 'PING' + data['PINGID'] = argv[0] + handle('PING', data) + when /^(\d+)$/ # numeric server message + num=command.to_i + case num + when ERR_NICKNAMEINUSE + # "* <nick> :Nickname is already in use" + data['NICK'] = argv[1] + data['MESSAGE'] = argv[2] + handle('NICKTAKEN', data) + when ERR_ERRONEUSNICKNAME + # "* <nick> :Erroneous nickname" + data['NICK'] = argv[1] + data['MESSAGE'] = argv[2] + handle('BADNICK', data) + when RPL_TOPIC + data['CHANNEL'] = argv[1] + data['TOPIC'] = argv[2] + handle('TOPIC', data) + when RPL_TOPIC_INFO + data['NICK'] = argv[0] + data['CHANNEL'] = argv[1] + data['SOURCE'] = argv[2] + data['UNIXTIME'] = argv[3] + handle('TOPICINFO', data) + when RPL_NAMREPLY + # "( "=" / "*" / "@" ) <channel> + # :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> ) + # - "@" is used for secret channels, "*" for private + # channels, and "=" for others (public channels). + argv[3].scan(/\S+/).each { |u| + if(u =~ /^([@+])?(.*)$/) + umode = $1 || "" + user = $2 + @users << [user, umode] + end + } + when RPL_ENDOFNAMES + data['CHANNEL'] = argv[1] + data['USERS'] = @users + handle('NAMES', data) + @users = Array.new + when RPL_WELCOME + # "Welcome to the Internet Relay Network + # <nick>!<user>@<host>" + case argv[1] + when /((\S+)!(\S+))/ + data['NETMASK'] = $1 + data['NICK'] = $2 + data['ADDRESS'] = $3 + when /Welcome to the Internet Relay Network\s(\S+)/ + data['NICK'] = $1 + when /Welcome.*\s+(\S+)$/ + data['NICK'] = $1 + when /^(\S+)$/ + data['NICK'] = $1 + end + handle('WELCOME', data) + when RPL_MOTDSTART + # "<nick> :- <server> Message of the Day -" + if argv[1] =~ /^-\s+(\S+)\s/ + server = $1 + @motd = "" + end + when RPL_MOTD + if(argv[1] =~ /^-\s+(.*)$/) + @motd << $1 + @motd << "\n" + end + when RPL_ENDOFMOTD + data['MOTD'] = @motd + handle('MOTD', data) + else + handle('UNKNOWN', data) + end + # end of numeric replies + when 'PRIVMSG' + # you can either bind to 'PRIVMSG', to get every one and + # parse it yourself, or you can bind to 'MSG', 'PUBLIC', + # etc and get it all nicely split up for you. + data['TARGET'] = argv[0] + data['MESSAGE'] = argv[1] + handle('PRIVMSG', data) + + # Now we split it + if(data['TARGET'] =~ /^(#|&).*/) + handle('PUBLIC', data) + else + handle('MSG', data) + end + when 'KICK' + data['CHANNEL'] = argv[0] + data['TARGET'] = argv[1] + data['MESSAGE'] = argv[2] + handle('KICK', data) + when 'PART' + data['CHANNEL'] = argv[0] + data['MESSAGE'] = argv[1] + handle('PART', data) + when 'QUIT' + data['MESSAGE'] = argv[0] + handle('QUIT', data) + when 'JOIN' + data['CHANNEL'] = argv[0] + handle('JOIN', data) + when 'TOPIC' + data['CHANNEL'] = argv[0] + data['TOPIC'] = argv[1] + handle('CHANGETOPIC', data) + when 'INVITE' + data['TARGET'] = argv[0] + data['CHANNEL'] = argv[1] + handle('INVITE', data) + when 'NICK' + data['NICK'] = argv[0] + handle('NICK', data) + when 'MODE' + data['CHANNEL'] = argv[0] + data['MODESTRING'] = argv[1] + data['TARGETS'] = argv[2] + handle('MODE', data) + when 'NOTICE' + data['TARGET'] = argv[0] + data['MESSAGE'] = argv[1] + if data['SOURCENICK'] + handle('NOTICE', data) + else + # "server notice" (not from user, noone to reply to + handle('SNOTICE', data) + end + else + handle('UNKNOWN', data) + end + end + + private + + # key:: server event name + # data:: hash containing data about the event, passed to the proc + # call client's proc for an event, if they set one as a handler + def handle(key, data) + if(@handlers.has_key?(key)) + @handlers[key].call(data) + end + end + end +end |