Give Techbot the ability to check for and ghost existing bots, then rename itself
[reactos.git] / irc / TechBot / TechBot.IRCLibrary / IrcClient.cs
index 6682bd7..3610715 100644 (file)
@@ -191,6 +191,7 @@ namespace TechBot.IRCLibrary
 \r
                #region Private fields\r
                private bool firstPingReceived = false;\r
+               private bool awaitingGhostDeath = false;\r
                private System.Text.Encoding encoding = System.Text.Encoding.UTF8;\r
                private TcpClient tcpClient;\r
                private NetworkStream networkStream;\r
@@ -198,6 +199,9 @@ namespace TechBot.IRCLibrary
                private LineBuffer messageStream;\r
                private ArrayList ircCommandEventRegistrations = new ArrayList();\r
                private ArrayList channels = new ArrayList();\r
+               private string reqNickname;\r
+               private string curNickname;\r
+               private string password;\r
                #endregion\r
 \r
                #region Public events\r
@@ -240,6 +244,16 @@ namespace TechBot.IRCLibrary
                        }\r
                }\r
 \r
+               /// <summary>\r
+               /// Nickname for the bot.\r
+               /// </summary>\r
+               public string Nickname\r
+               {\r
+                       get\r
+                       {\r
+                               return curNickname;\r
+                       }\r
+               }\r
                #endregion\r
 \r
                #region Private methods\r
@@ -361,6 +375,24 @@ namespace TechBot.IRCLibrary
                        firstPingReceived = true;\r
                }\r
 \r
+                       /// <summary>\r
+               /// Send a PONG message when a PING message is received.\r
+               /// </summary>\r
+               /// <param name="message">Received IRC message.</param>\r
+               private void NoticeMessageReceived(IrcMessage message)\r
+               {\r
+                       if (awaitingGhostDeath)\r
+                       {\r
+                               string str = string.Format("\ 2{0}\ 2 has been ghosted", reqNickname);\r
+                               if (message.Parameters.Contains(str))\r
+                               {\r
+                                       ChangeNick(reqNickname);\r
+                                       SubmitPassword(password);\r
+                                       awaitingGhostDeath = false;\r
+                               }\r
+                       }\r
+               }\r
+\r
                /// <summary>\r
                /// Process RPL_NAMREPLY message.\r
                /// </summary>\r
@@ -472,6 +504,31 @@ namespace TechBot.IRCLibrary
                        }\r
                }\r
 \r
+               /// <summary>\r
+               /// Process ERR_NICKNAMEINUSE message.\r
+               /// </summary>\r
+               /// <param name="message">Received IRC message.</param>\r
+               private void ERR_NICKNAMEINUSEMessageReceived(IrcMessage message)\r
+               {\r
+                       try\r
+                       {\r
+                               if (message.Parameters == null)\r
+                               {\r
+                                       System.Diagnostics.Debug.WriteLine(String.Format("Message has no parameters."));\r
+                                       return;\r
+                               }\r
+                               \r
+                               /* Connect with a different name */\r
+                               string[] parameters = message.Parameters.Split(new char[] { ' ' });\r
+                               string nickname = parameters[1];\r
+                               ChangeNick(nickname + "__");\r
+                       }\r
+                       catch (Exception ex)\r
+                       {\r
+                               System.Diagnostics.Debug.WriteLine(String.Format("Ex. {0}", ex));\r
+                       }\r
+               }\r
+\r
                #endregion\r
 \r
                /// <summary>\r
@@ -500,10 +557,14 @@ namespace TechBot.IRCLibrary
                                }\r
                                /* Install PING message handler */\r
                                MonitorCommand(IRC.PING, new MessageReceivedHandler(PingMessageReceived));\r
+                               /* Install NOTICE message handler */\r
+                               MonitorCommand(IRC.NOTICE, new MessageReceivedHandler(NoticeMessageReceived));\r
                                /* Install RPL_NAMREPLY message handler */\r
                                MonitorCommand(IRC.RPL_NAMREPLY, new MessageReceivedHandler(RPL_NAMREPLYMessageReceived));\r
                                /* Install RPL_ENDOFNAMES message handler */\r
                                MonitorCommand(IRC.RPL_ENDOFNAMES, new MessageReceivedHandler(RPL_ENDOFNAMESMessageReceived));\r
+                               /* Install ERR_NICKNAMEINUSE message handler */\r
+                               MonitorCommand(IRC.ERR_NICKNAMEINUSE, new MessageReceivedHandler(ERR_NICKNAMEINUSEMessageReceived));\r
                                /* Start receiving data */\r
                                Receive();\r
                        }\r
@@ -520,8 +581,6 @@ namespace TechBot.IRCLibrary
                        }\r
                        else\r
                        {\r
-                               \r
-\r
                                connected = false;\r
                                tcpClient.Close();\r
                                tcpClient = null;\r
@@ -606,10 +665,32 @@ namespace TechBot.IRCLibrary
                        if (nickname == null)\r
                                throw new ArgumentNullException("nickname", "Nickname cannot be null.");\r
 \r
+                       Console.WriteLine("Changing nick to {0}\n", nickname);\r
+                       curNickname = nickname;\r
+\r
                        /* NICK <nickname> [ <hopcount> ] */\r
                        SendMessage(new IrcMessage(IRC.NICK, nickname));\r
                }\r
 \r
+        /// <summary>\r
+        /// Ghost nickname.\r
+        /// </summary>\r
+        /// <param name="nickname">Nickname.</param>\r
+        public void GhostNick(string nickname,\r
+                              string password)\r
+        {\r
+            if (nickname == null)\r
+                throw new ArgumentNullException("nickname", "Nickname cannot be null.");\r
+\r
+            if (password == null)\r
+                throw new ArgumentNullException("password", "Password cannot be null.");\r
+\r
+            awaitingGhostDeath = true;\r
+\r
+            /* GHOST <nickname> <password> */\r
+            SendMessage(new IrcMessage(IRC.GHOST, nickname + " " + password));\r
+        }\r
+\r
                /// <summary>\r
                /// Submit password to identify user.\r
                /// </summary>\r
@@ -619,6 +700,8 @@ namespace TechBot.IRCLibrary
                        if (password == null)\r
                                throw new ArgumentNullException("password", "Password cannot be null.");\r
 \r
+                       this.password = password;\r
+\r
                        /* PASS <password> */\r
                        SendMessage(new IrcMessage(IRC.PASS, password));\r
                }\r
@@ -635,12 +718,10 @@ namespace TechBot.IRCLibrary
                {\r
                        if (nickname == null)\r
                                throw new ArgumentNullException("nickname", "Nickname cannot be null.");\r
+                       reqNickname = nickname;\r
                        firstPingReceived = false;\r
                        if (password != null)\r
                        {\r
-                               /* First ghost ourself and then register */\r
-                               if (nickname != null)\r
-                                       SendMessage(new IrcMessage(IRC.GHOST, nickname + " " + password));\r
                                SubmitPassword(password);\r
                        }\r
                        ChangeNick(nickname);\r