public void SendMode(string nick, UserModeInfo modeInfo) { string mode_set = modeInfo.Set ? "+" : "-"; _IRC.SendTCPMessage(string.Format("MODE {0} {1}", nick, mode_set + modeInfo.Mode)); if (UserModeCommandEvent != null) { UserModeCommandEvent(this, new UserModeCommand { Nick = nick, Mode = modeInfo }); } }
public UserModeCommand() { Nick = string.Empty; Mode = new UserModeInfo(); }
/// <summary> /// Parses the raw messages coming from the server and triggers an event based on the type of message. /// </summary> /// <param name="tcpMessage">The raw string read from the TCP stream.</param> internal async void ParseTCPMessage(string tcpMessage) { DateTime messageTime = DateTime.Now; Regex messageRegex = new Regex(@"^:(?<Sender>[^\s]+)\s(?<Type>[^\s]+)\s(?<Recipient>[^\s]+)\s?:?(?<Args>.*)", RegexOptions.None); Regex senderRegex = new Regex(@"^(?<Nick>[^\s]+)!(?<Realname>[^\s]+)@(?<Host>[^\s]+)", RegexOptions.None); Regex pingRegex = new Regex(@"^PING :(?<Message>.+)", RegexOptions.None); Regex pongRegex = new Regex(@"^PONG :(?<Message>.+)", RegexOptions.None); Regex errorRegex = new Regex(@"^ERROR :(?<Message>.+)", RegexOptions.None); Regex CTCPRegex = new Regex(@"^\u0001(?<Command>[^\s]+)\s?(?<Args>.*)\u0001", RegexOptions.None); string[] messages = tcpMessage.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (string message in messages) { if (messageRegex.IsMatch(message)) { Match match = messageRegex.Match(message); string type = match.Groups["Type"].Value; string sender = match.Groups["Sender"].Value; string recipient = match.Groups["Recipient"].Value; string args = match.Groups["Args"].Value; Match senderMatch = senderRegex.Match(sender); string senderNick = sender; string senderRealname = null; string senderHost = null; if (senderMatch.Success) { senderNick = senderMatch.Groups["Nick"].Value; senderRealname = senderMatch.Groups["Realname"].Value; senderHost = senderMatch.Groups["Host"].Value; } int replyCode; if (int.TryParse(type, out replyCode)) { // The message was a reply to a command sent if (Enum.IsDefined(typeof(IRCReplyCode), replyCode)) { await Task.Run(() => { if (ServerReplyEvent != null) { ServerReplyEvent(this, new ServerReplyMessage() { TimeStamp = messageTime, ReplyCode = (IRCReplyCode)replyCode, Message = args }); } }); } else if (Enum.IsDefined(typeof(IRCErrorCode), replyCode)) { await Task.Run(() => { if (ServerReplyEvent != null) { ServerReplyEvent(this, new ServerErrorMessage() { TimeStamp = messageTime, ErrorCode = (IRCErrorCode)replyCode, Message = args }); } }); } } else { switch (type) { // The message was a private message to a channel or nick case "PRIVMSG": if (CTCPRegex.IsMatch(args)) { Match ctcpMatch = CTCPRegex.Match(args); CTCPMessage ctcpMessage = new CTCPMessage(); ctcpMessage.Location = recipient; ctcpMessage.Sender = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; ctcpMessage.Command = ctcpMatch.Groups["Command"].Value; ctcpMessage.Arguments = ctcpMatch.Groups["Args"].Value; await Task.Run(() => { if (CTCPMessageReceivedEvent != null) { CTCPMessageReceivedEvent(this, ctcpMessage); } }); } else { if (Channel.IsChannel(recipient)) { ChannelMessage msg = new ChannelMessage(); msg.Channel = recipient; msg.Sender = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; msg.Message = args; await Task.Run(() => { if (ChannelMessageReceivedEvent != null) { ChannelMessageReceivedEvent(this, msg); } }); } else { PrivateMessage msg = new PrivateMessage(); msg.Sender = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; msg.Message = args; await Task.Run(() => { if (PrivateMessageReceivedEvent != null) { PrivateMessageReceivedEvent(this, msg); } }); } } break; // The message was a notice to a channel or nick case "NOTICE": if (CTCPRegex.IsMatch(args)) { Match ctcpMatch = CTCPRegex.Match(args); CTCPMessage ctcpMessage = new CTCPMessage(); ctcpMessage.Sender = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; ctcpMessage.Command = ctcpMatch.Groups["Command"].Value; ctcpMessage.Arguments = ctcpMatch.Groups["Args"].Value; await Task.Run(() => { if (CTCPNoticeReceivedEvent != null) { CTCPNoticeReceivedEvent(this, ctcpMessage); } }); } if (Channel.IsChannel(recipient)) { ChannelNotice msg = new ChannelNotice(); msg.Channel = recipient; msg.Sender = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; msg.Message = args; await Task.Run(() => { if (ChannelNoticeReceivedEvent != null) { ChannelNoticeReceivedEvent(this, msg); } }); } else { PrivateNotice msg = new PrivateNotice(); msg.Sender = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; msg.Message = args; await Task.Run(() => { if (PrivateNoticeReceivedEvent != null) { PrivateNoticeReceivedEvent(this, msg); } }); } break; // The message was a mode change message for a channel or nick case "MODE": if (Channel.IsChannel(recipient)) { ChannelModeChangeInfo modeMsg = new ChannelModeChangeInfo(); modeMsg.Modes = new List <ChannelModeInfo>(); modeMsg.Channel = recipient; modeMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; if (!string.IsNullOrEmpty(args)) { string[] modeArgs = args.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); List <string> argList = modeArgs.ToList(); argList.RemoveAt(0); modeMsg.Modes.AddRange(_IRC.ParseChannelModeString(modeArgs[0].TrimStart(':'), string.Join(" ", argList))); } await Task.Run(() => { if (ChannelModeChangeEvent != null) { ChannelModeChangeEvent(this, modeMsg); } }); } else { UserModeChangeInfo modeMsg = new UserModeChangeInfo(); modeMsg.Modes = new List <UserModeInfo>(); modeMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; if (!string.IsNullOrEmpty(args)) { string[] modeArgs = args.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); char[] modeInfo = modeArgs[0].TrimStart(':').ToCharArray(); bool set = true; foreach (char mode in modeInfo) { if (mode.Equals('-')) { set = false; } else if (mode.Equals('+')) { set = true; } else if (!string.IsNullOrEmpty(mode.ToString())) { UserModeInfo newMode = new UserModeInfo(); newMode.Set = set; UserMode md; Enum.TryParse(mode.ToString(), out md); newMode.Mode = md; modeMsg.Modes.Add(newMode); } } } await Task.Run(() => { if (UserModeChangeEvent != null) { UserModeChangeEvent(this, modeMsg); } }); } break; // The message was a topic change for a channel case "TOPIC": TopicChangeInfo topicMsg = new TopicChangeInfo(); topicMsg.Channel = recipient; topicMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; topicMsg.Topic = args; await Task.Run(() => { if (TopicChangeEvent != null) { TopicChangeEvent(this, topicMsg); } }); break; // The message was a nick change case "NICK": NickChangeInfo nickMsg = new NickChangeInfo(); nickMsg.OldNick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; nickMsg.NewNick = new Nick() { Nickname = recipient.TrimStart(':'), Realname = senderRealname, Host = senderHost }; await Task.Run(() => { if (NickChangeEvent != null) { NickChangeEvent(this, nickMsg); } }); break; // The message was an invite to a channel case "INVITE": InviteChannelInfo inviteMsg = new InviteChannelInfo(); inviteMsg.Requester = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; inviteMsg.Recipient = new Nick() { Nickname = recipient }; inviteMsg.Channel = args; await Task.Run(() => { if (InviteChannelEvent != null) { InviteChannelEvent(this, inviteMsg); } }); break; // The message was a nick joining a channel case "JOIN": JoinChannelInfo joinMsg = new JoinChannelInfo(); joinMsg.Channel = recipient.TrimStart(':'); joinMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; await Task.Run(() => { if (JoinChannelEvent != null) { JoinChannelEvent(this, joinMsg); } }); break; // The message was a nick parting a channel case "PART": PartChannelInfo partMsg = new PartChannelInfo(); partMsg.Channel = recipient; partMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; await Task.Run(() => { if (PartChannelEvent != null) { PartChannelEvent(this, partMsg); } }); break; // The message was a nick being kicked from a channel case "KICK": KickInfo kickMsg = new KickInfo(); kickMsg.Channel = recipient; kickMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; string[] argSplit = args.Split(new char[] { ' ' }, StringSplitOptions.None); kickMsg.KickedNick = new Nick() { Nickname = argSplit[0] }; List <string> reasonArgs = argSplit.ToList <string>(); reasonArgs.RemoveAt(0); kickMsg.Reason = string.Join(" ", reasonArgs.ToArray()).Remove(0, 1); await Task.Run(() => { if (KickEvent != null) { KickEvent(this, kickMsg); } }); break; // The message was a nick quiting the irc network case "QUIT": QuitInfo quitMsg = new QuitInfo(); quitMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost }; quitMsg.Message = string.Join(" ", recipient.Remove(0, 1), args); await Task.Run(() => { if (QuitEvent != null) { QuitEvent(this, quitMsg); } }); break; default: break; } } } else if (pingRegex.IsMatch(message)) // The message was a PING { Match match = pingRegex.Match(message); PingInfo ping = new PingInfo(); ping.Message = match.Groups["Message"].Value; await Task.Run(() => { if (PingEvent != null) { PingEvent(this, ping); } }); } else if (pongRegex.IsMatch(message)) // The message was a PONG { Match match = pongRegex.Match(message); PongInfo pong = new PongInfo(); pong.Message = match.Groups["Message"].Value; await Task.Run(() => { if (PongEvent != null) { PongEvent(this, pong); } }); } else if (errorRegex.IsMatch(message)) // The message was a server error { Match match = errorRegex.Match(message); ErrorMessage error = new ErrorMessage(); error.Message = match.Groups["Message"].Value; await Task.Run(() => { if (ErrorMessageEvent != null) { ErrorMessageEvent(this, error); } }); } string rawMessage = message; await Task.Run(() => { if (RawMessageEvent != null) { RawMessageEvent(this, rawMessage); } }); } }