public HandleReply ( |
||
message | The reply message to process. | |
return | void |
/// <summary> /// Process a message that is categorised as being a numeric reply in the RFC documents. /// </summary> /// <param name="message">The message to process.</param> private void ProcessNumericReply(Message message) { Reply reply = (Reply)int.Parse(message.Command); Action<IRCTabPage> appendMessage = (IRCTabPage tabPage) => { MessageTypeAttribute attributes = IRCMarshal.GetReplyAttributes(reply); MessageType messageType = attributes.MessageType; GlobalSettings settings = GlobalSettings.Instance; string source = attributes.Source; string content; if (attributes.OutputAction == null) { content = message.ToString(attributes.OutputFormat, attributes.ParameterDelimiter, attributes.RemoveFirstParameter); } else { content = attributes.OutputAction.Invoke(message); } if (settings.DebugMode == GlobalSettings.Boolean.Yes) { tabPage.AppendMessage(reply.ToString(), "[RAW]", message.ToString(), MessageType.WarningMessage); } tabPage.AppendMessage(reply.ToString(), source, content, messageType); }; // If we are retrieving list replies we need to populate the channel browser if (reply == Reply.RPL_LISTSTART) { this.parent.InvokeAction(() => this.ChannelBrowser.BeginRefresh(true)); return; } else if (reply == Reply.RPL_LIST) { this.ChannelBrowser.AddChannel(message); return; } else if (reply == Reply.RPL_LISTEND) { this.parent.InvokeAction(() => this.ChannelBrowser.FlushChannels()); return; } // If we are still awaiting the UserHost reply (i.e. we are awaiting confirmation of the full userhost // prefix that we will use to determine the max PRIVMSG lengths) then cache it in the marshal for future // reference. if (this.AwaitingUserHostMessage && reply == Reply.RPL_USERHOST) { this.fullUserHost = message.TrailingParameter; this.AwaitingUserHostMessage = false; // Execute any auto commands. if (!this.hasExecutedAutoCommands && this.AutoCommands.Count > 0) { for (int i = 0; i < this.AutoCommands.Count; i++) { MessageParseResult parseResult = MessageFactory.CreateFromUserInput(this.AutoCommands[i], null); if (parseResult.Success) { this.Send(this.ServerTab, parseResult.IRCMessage); } } this.hasExecutedAutoCommands = true; } if (this.reconnecting) { // Pause the thread for a second to give time for any authentication to // take place and then rejoin the channels. System.Threading.Thread.Sleep(1000); this.Channels.ForEach(i => { if (i.TabPage.TabType == IRCTabType.Channel) { this.Send(this.ServerTab, new JoinMessage(i.Name)); } }); this.reconnecting = false; } return; } // If the user has received a new hidden host then we need to re-evaluate // their full user host mask that will be seen by other clients. if (reply == Reply.RPL_HOSTHIDDEN) { this.AwaitingUserHostMessage = true; this.Send(this.ServerTab, new UserHostMessage(new string[] { this.connection.Nickname })); } // If we have a names reply or an end of names reply, then we need to check the channel // it is in regards to exists in our channel list, and if it does check to see if it // is awaiting a reply from a names request (i.e. it is wanting to refresh the user list). // // If this is indeed the case, we need to force it through to that channel rather than // following the default procedure of going to the selected tab. if ((reply == Reply.RPL_NAMREPLY) || (reply == Reply.RPL_ENDOFNAMES)) { string target = string.Empty; if (reply == Reply.RPL_NAMREPLY) { target = message.Parameters[2]; } else { target = message.Parameters[1]; } IRCChannel channel = this.channels.Find(i => i.Name.Equals(target, StringComparison.OrdinalIgnoreCase)); if (channel != null && channel.ExpectingNamesMessage) { channel.HandleReply(message); return; } } // If the currently selected tab belongs to the channel list for this connection // AND we aren't awaiting a mode message (i.e. connecting to the server) // then marshal the message to the owning channel, otherwise default to the server tab this.TabHost.InvokeAction(() => { IRCChannel selectedChannel = this.Channels.Find(i => this.TabHost.SelectedTab.Equals(i.TabPage)); if ((selectedChannel != null) && (!this.AwaitingModeMessage)) { selectedChannel.HandleReply(message); } else { appendMessage.Invoke(this.ServerTab); } }); // If a nick in use message comes through, we need to revert the nick against the connection // back to the previously assigned nick (if there is one). // If there wasn't one, then we'll append an underscore to the current one and resend the nick message // we couldn't possibly get stuck in a loop, right? if (reply == Reply.ERR_NICKNAMEINUSE) { if (this.previousNickName.Equals(this.Connection.Nickname, StringComparison.OrdinalIgnoreCase)) { this.previousNickName = string.Format("{0}_", this.previousNickName); this.connection.Nickname = this.previousNickName; this.Send(this.ServerTab, new NickMessage(this.previousNickName)); } else { if (!this.AwaitingModeMessage) { this.Connection.Nickname = this.previousNickName; } else { this.previousNickName = string.Format("{0}_", this.connection.Nickname); this.connection.Nickname = this.previousNickName; this.Send(this.ServerTab, new NickMessage(this.previousNickName)); } } } }