Example #1
0
        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;
            }
Example #2
0
 /// <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);
 }