private void HandleUserData(string sender, string[] content, string data) { var username = sender.Substring(0, sender.IndexOf('!')); if (!_cachedUsers.TryGetValue(username, out var user)) { user = new User(this) { Username = username }; _cachedUsers.TryAdd(username, user); } switch (content[0]) { case "JOIN": { if (!_cachedChannels.TryGetValue(content[1], out var channel)) { channel = new Channel(this) { Name = content[1] }; _cachedChannels.TryAdd(content[1], channel); Send($"MODE {channel.Name}"); Send($"NAMES {channel.Name}"); Send($"MODE {channel.Name} +b"); } var channelUser = new ChannelUser(this, user, channel); if (channel._users.All(x => x != user)) { channel._users.Add(channelUser); } if (user._channels.All(x => x != channel)) { user._channels.Add(channel); } UserJoined?.Invoke(new UserJoinedEventArgs { Client = this, CurrentUser = CurrentUser, Channel = channel, User = channelUser }); return; } case "PART": { var channelName = content[1]; if (channelName.StartsWith(':')) { channelName = channelName.Substring(1); } if (!_cachedChannels.TryGetValue(channelName, out var channel)) { channel = new Channel(this) { Name = channelName }; _cachedChannels.TryAdd(channelName, channel); } if (user._channels.Any(x => x == channel)) { user._channels.Remove(channel); } if (channel._users.Any(x => x == user)) { channel._users.RemoveAll(x => x == user); } UserLeft?.Invoke(new UserLeftEventArgs { Client = this, CurrentUser = CurrentUser, Channel = channel, User = user, Reason = content.Length > 2 ? data.Substring(data.IndexOf(':') + 1) : "" }); return; } case "QUIT": { _cachedUsers.TryRemove(user.Username, out _); foreach (var channel in _cachedChannels.Values) { channel._users.RemoveAll(x => x == user); } var reason = ""; var idof = data.IndexOf(':'); if (idof != -1) { reason = data.Substring(idof + 1); } UserQuit?.Invoke(new UserQuitEventArgs { Client = this, CurrentUser = CurrentUser, User = user, Reason = reason }); return; } case "NICK": { _cachedUsers.TryRemove(user.Username, out var oldUser); user.Username = content[1].Substring(1); _cachedUsers.TryRemove(user.Username, out _); _cachedUsers.TryAdd(user.Username, user); NicknameChanged?.Invoke(new NicknameChangedEventArgs { Client = this, CurrentUser = CurrentUser, User = user, OldUsername = oldUser.Username, NewUsername = user.Username }); return; } case "PRIVMSG": { var cnt = data.Substring(1); var message = cnt.Substring(cnt.IndexOf(':') + 1); if (!user._channelMessages.TryGetValue(content[1], out var list)) { list = new List <string> { message }; user._channelMessages.TryAdd(content[1], list); } else { list.Add(message); } if (content[1][0] == '#') { if (!_cachedChannels.TryGetValue(content[1], out var channel)) { channel = new Channel(this) { Name = content[1] }; _cachedChannels.TryAdd(content[1], channel); } channel._messages.Add((user, message)); MessageReceived?.Invoke(new MessageReceivedEventArgs { Client = this, Channel = channel, CurrentUser = CurrentUser, Message = message, User = channel.Users.FirstOrDefault(x => x == user) ?? user }); return; } MessageReceived?.Invoke(new MessageReceivedEventArgs { Client = this, Channel = null, CurrentUser = CurrentUser, Message = message, User = user }); return; } case "NOTICE": { var message = data.Substring(data.IndexOf(':') + 1); if (!user._channelMessages.TryGetValue(content[1], out var list)) { list = new List <string> { message }; user._channelMessages.TryAdd(content[1], list); } else { list.Add(message); } NoticeReceived?.Invoke(new NoticeReceivedEventArgs { Client = this, CurrentUser = CurrentUser, Message = message, User = user }); return; } case "MODE": { if (!_cachedChannels.TryGetValue(content[1], out var channel)) { channel = new Channel(this) { Name = content[1] }; _cachedChannels.TryAdd(content[1], channel); } var iofplus = content[2].IndexOf('+'); var iofminus = content[2].IndexOf('-'); var modesPlus = Array.Empty <char>(); var modesMinus = Array.Empty <char>(); if (iofplus != -1) { modesPlus = content[2].Substring(iofplus + 1).ToCharArray(); } if (iofminus != -1) { modesMinus = iofplus != -1 ? content[2].Substring(iofminus + 1, content[2].Length - iofplus - 1).ToCharArray() : content[2].Substring(iofminus + 1).ToCharArray(); } for (var i = 0; i < modesPlus.Length; i++) { if (!channel._modes.Contains(modesPlus[i]) && modesPlus[i] != 'b') { channel._modes.Add(modesPlus[i]); } } for (var i = 0; i < modesMinus.Length; i++) { if (!channel._modes.Contains(modesMinus[i]) && modesMinus[i] != 'b') { channel._modes.Add(modesMinus[i]); } } var complexModes = modesMinus.Where(x => _configuration.ComplexChanModes.Any(y => y == x && x != 'l')).ToList(); complexModes.AddRange(modesPlus.Where(x => _configuration.ComplexChanModes.Any(y => y == x))); var extraArgs = content.Skip(3).ToList(); var modesArgs = new Dictionary <char, (char, string)>(); for (var i = 0; i < complexModes.Count && i < extraArgs.Count; i++) { modesArgs.Add(complexModes[i], (modesMinus.Contains(complexModes[i]) ? '-' : '+', extraArgs[i])); } foreach (var complexMod in modesArgs) { switch (complexMod.Key) { case 'b': if (complexMod.Value.Item1 == '-') { channel._banList.RemoveWhere(x => x.Host == complexMod.Value.Item2); } else { channel._banList.Add(new ChannelBan { IssuedBy = user.Username, Host = complexMod.Value.Item2, IssuedOn = DateTimeOffset.UtcNow }); } break; case 'l': channel.Limit = int.Parse(complexMod.Value.Item2); break; case 'k': channel.Key = complexMod.Value.Item1 == '+' ? complexMod.Value.Item2 : ""; break; } } ChannelModeUpdated?.Invoke(new ChannelModesUpdatedEventArgs { Client = this, CurrentUser = CurrentUser, Channel = channel, ModesAdded = new ReadOnlyCollection <char>(modesPlus), ModesRemoved = new ReadOnlyCollection <char>(modesMinus), ModesArgs = new ReadOnlyDictionary <char, (char, string)>(modesArgs), User = channel.Users.FirstOrDefault(x => x == user) }); return; }
/// <summary> /// Raises the <see cref="NoticeReceived"/> event. /// </summary> /// <param name="e">The <see cref="EventArgs"/> instance holding the event data.</param> internal void OnNoticeReceived(IrcChannelMessageEventArgs e) { NoticeReceived?.Invoke(this, e); }