Beispiel #1
0
        /// <summary>
        /// Represents one connection to one IRC server
        /// </summary>
        public IrcClient()
        {
            ServerInfo = new ServerInfoType();

            Encoding = new System.Text.UTF8Encoding(false);
            Registered = false;
            LastMessageTime = DateTime.Now;
            Timeout = new TimeSpan(0, 2, 0);
            Connected = false;

            _thread = new IRCEventThread(this);

            _thread.OnRawMessageReceived += (sender, msg) =>
            {

                if (OnRawMessageReceived != null)
                {
                    foreach (var d in OnRawMessageReceived.GetInvocationList())
                    {
                        Task.Run(() => d.DynamicInvoke(this, msg));
                    }

                }

            };


            _thread.OnException += (sender, e) =>
            {

                // Call to clean up resources and set flags
                Disconnect();


                if (OnException != null)
                {
                    foreach (var d in OnException.GetInvocationList())
                    {
                        Task.Run(() => d.DynamicInvoke(this, e));
                    }

                }

                // Call on disconnect when there's an exception in the reading thread
                if (OnDisconnect != null)
                {
                    foreach (var d in OnDisconnect.GetInvocationList())
                    {
                        Task.Run(() => d.DynamicInvoke(this));
                    }

                }

            };

            #region Register Delegates

            OnRawMessageReceived += ErrorHandler; // This one looks for ERROR messages
            OnRawMessageReceived += PingHandler;
            OnRawMessageReceived += NumericHandler;
            OnRawMessageReceived += PrivmsgHandler;
            OnRfcNumeric += (sender, source, numeric, target, other) => { if (numeric == 1 && OnConnect != null) foreach (var d in OnConnect.GetInvocationList()) Task.Run(() => d.DynamicInvoke(this)); };
            OnRfcNumeric += (sender, source, numeric, target, other) =>
            {
                if (numeric == 353 && OnNamesReply != null)
                {
                    String[] words = other.Split(' ');
                    String channel = words[1];
                    foreach (var d in OnNamesReply.GetInvocationList())
                        Task.Run(() => d.DynamicInvoke(this, channel, other.Substring(other.IndexOf(':') + 1)));
                }
            };

            OnRfcNumeric += (sender, source, numeric, target, other) =>
            {
                // Parses numeric 5 (List of things the server supports) and calls event with the parsed list
                if (numeric == 5 && OnISupport != null)
                {
                    Dictionary<String, String> parameters = new Dictionary<string, string>();
                    String[] tokens = other.Split(' ');
                    foreach (String token in tokens)
                    {
                        int equalIndex = token.IndexOf('=');
                        if (equalIndex >= 0) parameters[token.Substring(0, equalIndex)] = token.Substring(equalIndex + 1);
                        else
                            parameters[token] = "";
                    }
                    foreach (var d in OnISupport.GetInvocationList())
                        Task.Run(() => d.DynamicInvoke(this, parameters));
                }
            };

            OnConnect += (sender) => { lock (_channels) { _channels.Clear(); } };

            OnISupport += (sender, parameters) =>
            {
                try
                {

                    sender.ServerInfo.PREFIX = parameters["PREFIX"];
                }
                catch (KeyNotFoundException) { };

                try
                {
                    sender.ServerInfo.CHANMODES = parameters["CHANMODES"];
                }
                catch (KeyNotFoundException) { };
                if (parameters.ContainsKey("UHNAMES"))
                {
                    var task = SendRawMessage("PROTOCTL UHNAMES");
                }


                if (parameters.ContainsKey("NAMESX"))
                {
                    var task = SendRawMessage("PROTOCTL NAMESX");
                }

            };

            OnRawMessageReceived += (source, message) =>
            {
                String[] tokens = message.Split(' ');
                if (OnRfcJoin != null && tokens.Length >= 3 && tokens[1].Equals("JOIN"))
                {
                    foreach (var d in OnRfcJoin.GetInvocationList())
                        Task.Run(() => d.DynamicInvoke(this, tokens[0].Replace(":", ""), tokens[2].Replace(":", "")));
                }
            };

            OnRfcJoin += (sender, source, channellist) =>
            {
                /// If the user joining is me, add it to the channel list.
                /// If we have a channel already, add the guy to it.


                foreach (String channelName in channellist.Split(','))
                {



                    Channel c = null;
                    lock (_channels)
                    {
                        _channels.TryGetValue(channelName.ToLower(), out c);
                        if (c == null && ChannelUser.GetNickFromFullAddress(source).Equals(Nick, StringComparison.CurrentCultureIgnoreCase))
                        {
                            c = new Channel(channelName);
                            _channels[channelName.ToLower()] = c;
                        }

                        if (c != null)
                        {
                            ChannelUser u = new ChannelUser(source, c);
                            c.Users[u.Nick.ToLower()] = u;
                        }
                    }
                }


            };

            OnRawMessageReceived += (sender, message) =>
            {
                String[] tokens = message.Split(' ');
                if (tokens.Length >= 5 && tokens[1].Equals("KICK"))
                {
                    String source = tokens[0].Replace(":", ""), channel = tokens[2], target = tokens[3];
                    String reason = message.Substring(message.IndexOf(':', 1));
                    if (OnRfcKick != null)
                        foreach (var d in OnRfcKick.GetInvocationList())
                            Task.Run(() => d.DynamicInvoke(this, source, target, channel, reason));
                }
            };
            // Catches a part
            OnRawMessageReceived += (sender, message) =>
            {
                String[] tokens = message.Split(' ');
                if (OnRfcPart != null && tokens.Length >= 3 && tokens[1].Equals("PART"))
                {
                    String reason = tokens.Length >= 4 ? message.Substring(message.IndexOf(':', 1)) : null;
                    foreach (var d in OnRfcPart.GetInvocationList())
                        Task.Run(() => d.DynamicInvoke(this, tokens[0].Replace(":", ""), tokens[2], reason));
                }
            };
            OnRawMessageReceived += (sender, message) =>
            {
                String[] tokens = message.Split(' ');
                if (tokens.Length >= 4 && tokens[1].Equals("MODE") && OnRfcMode != null)
                {
                    foreach (var d in OnRfcMode.GetInvocationList())
                        Task.Run(() => d.DynamicInvoke(sender, tokens[0].Replace(":", ""), tokens[2], message.Substring(message.IndexOf(tokens[2]) + tokens[2].Length + 1)));
                }

            };

            // On part, we should remove the nick from the channel. If it's US parting, we should remove the channel from channels
            OnRfcPart += (sender, source, channel, reason) =>
            {
                Channel channelObject = null;
                lock (_channels)
                {
                    _channels.TryGetValue(channel.ToLower(), out channelObject);
                    if (channelObject != null)
                    {
                        if (ChannelUser.GetNickFromFullAddress(source).Equals(Nick, StringComparison.CurrentCultureIgnoreCase))
                            _channels.Remove(channel.ToLower());
                        else
                        {
                            try
                            {
                                channelObject.Users.Remove(ChannelUser.GetNickFromFullAddress(source));
                            }
                            catch (Exception) { }
                        }
                    }
                }
            };

            OnRfcKick += (sender, source, target, channel, reason) =>
            {
                Channel channelObject = null;
                _channels.TryGetValue(channel.ToLower(), out channelObject);
                if (channelObject != null)
                {

                    if (Nick.Equals(target, StringComparison.CurrentCultureIgnoreCase)) // If it's us, remove the channel
                        _channels.Remove(channel.ToLower());
                    else // else remove the nick from the channel 
                    {
                        try
                        {
                            channelObject.Users.Remove(target.ToLower());
                        }
                        catch (Exception) { }
                    }
                }
            };
            OnRawMessageReceived += (source, message) => { LastMessageTime = DateTime.Now; };
            OnNamesReply += NamesReplyHandler;

            // Updates prefix list for users of a channel when modes are changed
            OnRfcMode += (sender, source, target, modes) =>
            {
                Channel channel = null;
                _channels.TryGetValue(target.ToLower(), out channel);
                if (_channels == null) return;


                String[] tokens = modes.Split(' ');

                bool isSet = false;
                for (int modeIndex = 0, parameterIndex = 1; modeIndex < tokens[0].Length; ++modeIndex)
                {
                    char mode = tokens[0][modeIndex];
                    if (mode == '+') isSet = true;
                    else if (mode == '-') isSet = false;
                    else if (ServerInfo.CHANMODES_parameterNever.Contains(mode)) continue;
                    else if (ServerInfo.CHANMODES_paramaterToSet.Contains(mode))
                    {
                        if (isSet) ++parameterIndex;
                        else continue;
                    }
                    else
                    {

                        try
                        {
                            // If it's a user access mode
                            if (ServerInfo.PREFIX_modes.Contains(mode))
                            {
                                ChannelUser user = null;
                                channel.Users.TryGetValue(tokens[parameterIndex].ToLower(), out user);
                                if (user != null)
                                {
                                    char prefix = ServerInfo.PREFIX_symbols[ServerInfo.PREFIX_modes.IndexOf(mode)];
                                    if (isSet)
                                        user.InsertPrefix(ServerInfo, target, prefix);
                                    else
                                        user.DeletePrefix(target, prefix);
                                }
                            }

                        }
                        catch (Exception) { }
                        finally
                        {
                            // These modes always have parameters so we need to always increase the index at the end
                            ++parameterIndex;
                        }
                    }

                }

            };

            OnRawMessageReceived += (sender, message) =>
            {
                String[] tokens = message.Split(' ');
                if (tokens.Length >= 3 && tokens[1].Equals("NICK") && OnRfcNick != null)
                {
                    foreach (var d in OnRfcNick.GetInvocationList())
                    {
                        Task.Run(() => d.DynamicInvoke(sender, tokens[0].Replace(":", ""), tokens[2].Replace(":", "")));
                    }
                }

            };

            OnRfcNick += (sender, source, newnick) =>
            {
                String oldnick = ChannelUser.GetNickFromFullAddress(source).ToLower();
                ChannelUser user = null;
                foreach (Channel c in _channels.Values)
                {
                    c.Users.TryGetValue(oldnick, out user);
                    if (user != null)
                    {
                        user.Nick = newnick;
                        c.Users.Remove(oldnick);
                        c.Users[newnick] = user;
                    }

                }

                if (ChannelUser.GetNickFromFullAddress(source) == this.Nick)
                {
                    this.Nick = newnick;
                }
            };

            OnRawMessageReceived += (sender, message) =>
            {
                String[] tokens = message.Split(' ');
                if (tokens.Length >= 3 && OnRfcQuit != null && tokens[1].Equals("QUIT"))
                {
                    foreach (var d in OnRfcQuit.GetInvocationList())
                        Task.Run(() => d.DynamicInvoke(sender, tokens[0].Replace(":", ""), message.Substring(message.IndexOf(":", 1))));
                }
            };
            OnRfcQuit += (sender, source, message) =>
            {
                String nick = ChannelUser.GetNickFromFullAddress(source);
                foreach (Channel c in _channels.Values)
                {
                    try { c.Users.Remove(nick.ToLower()); }
                    catch (Exception) { }

                }

            };
            #endregion Register Delegates
        }
Beispiel #2
0
        private void NamesReplyHandler(IrcClient sender, String channel, String names)
        {


            Channel channelObject = null;
            lock (_channels)
            {
                _channels.TryGetValue(channel.ToLower(), out channelObject);
                if (channelObject == null)
                    channelObject = new Channel(channel);

                String[] namesArray = names.Split(' ');
                foreach (String name in namesArray)
                {
                    if (String.IsNullOrEmpty(name)) continue;
                    int nameStart = 0;
                    for (nameStart = 0; sender.ServerInfo.PREFIX_symbols.Contains(name[nameStart]); ++nameStart) ;

                    String justName = name.Substring(nameStart);

                    ChannelUser user = null;

                    channelObject.Users.TryGetValue(ChannelUser.GetNickFromFullAddress(justName), out user);
                    if (user == null)
                    {
                        user = new ChannelUser(justName, channelObject);
                        channelObject.Users[user.Nick.ToLower()] = user;
                        /// If we are in the list, we need to be smart enough to add the channel to our list if it isnt there
                        if (user.Nick.Equals(Nick, StringComparison.CurrentCultureIgnoreCase))
                            _channels[channelObject.Name.ToLower()] = channelObject;
                    }

                    for (int i = 0; i < nameStart; ++i)
                        user.InsertPrefix(sender.ServerInfo, channel, name[i]);
                }
            }
        }
Beispiel #3
0
        public ChannelUser(String nickOrFullAddress, Channel channel)
        {
            if (nickOrFullAddress.Contains('!') && nickOrFullAddress.Contains('@') && nickOrFullAddress.IndexOf('@') > nickOrFullAddress.IndexOf('!'))
            {
                Nick = GetNickFromFullAddress(nickOrFullAddress);
                Username = GetUserFromFullAddress(nickOrFullAddress);
                Host = GetHostFromFullAddress(nickOrFullAddress);

            }
            else Nick = nickOrFullAddress;
        }