Example #1
0
        /// <summary>
        /// Send a message to all the users in a channel.</summary>
        /// <remarks>
        /// Possible Errors
        /// <list type="bullet">
        ///         <item><description>ERR_CANNOTSENDTOCHAN</description></item>
        ///         <item><description>ERR_NOTEXTTOSEND</description></item>
        /// </list>
        /// </remarks>
        /// <param name="channel">The target channel.</param>
        /// <param name="message">A message. If the message is too long it will be broken
        /// up into smaller piecese which will be sent sequentially.</param>
        /// <exception cref="ArgumentException">If the channel name is not valid or if the message is null.</exception>
        /// <seealso cref="Listener.OnPublic"/>
        public void PublicMessage(string channel, string message)
        {
            if (IsEmpty(message))
            {
                throw new ArgumentException("Public message cannot be null or empty.");
            }
            if (!Rfc2812Util.IsValidChannelName(channel))
            {
                throw new ArgumentException(channel + " is not a valid channel name.");
            }

            lock (this)
            {
                // 11 is PRIVMSG + 2 x Spaces + : + CR + LF
                int max = MAX_COMMAND_SIZE - 11 - channel.Length - MAX_HOSTNAME_LEN - MAX_NICKNAME_LEN;
                if (message.Length > max)
                {
                    string[] parts = BreakUpMessage(message, max);
                    foreach (string part in parts)
                    {
                        SendMessage("PRIVMSG", channel, part);
                    }
                }
                else
                {
                    SendMessage("PRIVMSG", channel, message);
                }
            }
        }
Example #2
0
 /// <summary>
 /// Join a passworded channel.
 /// </summary>
 /// <param name="channel">Channel to join</param>
 /// <param name="password">The channel's pasword. Cannot be null or empty.</param>
 /// <exception cref="ArgumentException">If the channel name is not valid or the password is null.</exception>
 /// <seealso cref="Listener.OnJoin"/>
 public void Join(string channel, string password)
 {
     lock (this)
     {
         if (IsEmpty(password))
         {
             ClearBuffer();
             throw new ArgumentException("Password cannot be empty or null.");
         }
         if (Rfc2812Util.IsValidChannelName(channel))
         {
             Buffer.Append("JOIN");
             Buffer.Append(SPACE);
             Buffer.Append(channel);
             Buffer.Append(SPACE);
             //8 is the JOIN + 2 spaces + CR + LF
             password = Truncate(password, 8);
             Buffer.Append(password);
             Connection.SendCommand(Buffer);
         }
         else
         {
             ClearBuffer();
             throw new ArgumentException(channel + " is not a valid channel name.");
         }
     }
 }
Example #3
0
        /// <summary>
        /// Request a list of all nicknames on a given channel.
        /// </summary>
        /// <remarks>
        /// Possible Errors
        /// <list type="bullet">
        ///         <item><description>ERR_TOOMANYMATCHES</description></item>
        /// </list>
        /// </remarks>
        /// <param name="channels">One or more channel names.</param>
        /// <example><code>
        /// //Make the request for a single channel
        /// connection.Sender.Names( "#test" );
        /// </code></example>
        /// <exception cref="ArgumentException">If the channel name is not valid.</exception>
        /// <seealso cref="Listener.OnNames"/>
        public void Names(string channel)
        {
            if (!Rfc2812Util.IsValidChannelName(channel))
            {
                throw new ArgumentException(channel + " is not a valid channel name.");
            }

            lock (this)
            {
                buffer.Append("NAMES");
                buffer.Append(SPACE);
                buffer.Append(channel);
                connection.SendCommand(buffer);
            }
        }
Example #4
0
 /// <summary>
 /// Join the specified channel.
 /// </summary>
 /// <remarks>
 /// <para>Once a user has joined a channel, he receives information about
 /// all commands his server receives affecting the channel. This
 /// includes JOIN, MODE, KICK, PART, QUIT and of course PRIVMSG/NOTICE.
 /// This allows channel members to keep track of the other channel
 /// members, as well as channel modes.</para>
 /// <para>If a JOIN is successful, the user receives a JOIN message as
 /// confirmation and is then sent the channel's topic ( <see cref="Listener.OnTopicRequest"/> and
 /// the list of users who are on the channel ( <see cref="Listener.OnNames"/> ), which
 /// MUST include the user joining.</para>
 ///
 /// Possible Errors
 /// <list type="bullet">
 ///     <item><description>ERR_NEEDMOREPARAMS</description></item>
 ///     <item><description>ERR_BANNEDFROMCHAN</description></item>
 ///     <item><description>ERR_INVITEONLYCHAN</description></item>
 ///     <item><description>ERR_BADCHANNELKEY</description></item>
 ///     <item><description>ERR_CHANNELISFULL</description></item>
 ///     <item><description>ERR_BADCHANMASK</description></item>
 ///     <item><description>ERR_NOSUCHCHANNEL</description></item>
 ///     <item><description>ERR_TOOMANYCHANNELS</description></item>
 ///     <item><description>ERR_TOOMANYTARGETS</description></item>
 ///     <item><description>ERR_UNAVAILRESOURCE</description></item>
 /// </list>
 /// </remarks>
 /// <param name="channel">The channel to join. Channel names must begin with '&amp;', '#', '+' or '!'.</param>
 /// <example><code>
 /// //Most channels you will see begin with the '#'. The others are reserved
 /// //for special channels and may not even be available on a particular server.
 /// connection.Sender.Join("#thresher");
 /// </code></example>
 /// <exception cref="ArgumentException">If the channel name is not valid.</exception>
 /// <seealso cref="Listener.OnJoin"/>
 public void Join(string channel)
 {
     lock (this)
     {
         if (Rfc2812Util.IsValidChannelName(channel))
         {
             Buffer.Append("JOIN");
             Buffer.Append(SPACE);
             Buffer.Append(channel);
             Connection.SendCommand(Buffer);
         }
         else
         {
             ClearBuffer();
             throw new ArgumentException(channel + " is not a valid channel name.");
         }
     }
 }
Example #5
0
 /// <summary>
 /// Send an action message to a channel.
 /// </summary>
 /// <remarks>
 /// This is actually a CTCP command but it is so widely used
 /// that it is included here. These are the '\me Laughs' type messages.
 /// </remarks>
 /// <param name="channel">The target channel.</param>
 /// <param name="description">A description of the action. If this is too long it will
 /// be truncated.</param>
 /// <example><code>
 /// //Express an emotion...
 /// connection.Sender.Action("#thresher", "Kicks down the door" );
 /// </code></example>
 /// <exception cref="ArgumentException">If the channel name is not valid. Will
 /// also be thrown if the description is null or empty.</exception>
 /// <seealso cref="Listener.OnAction"/>
 public void Action(string channel, string description)
 {
     lock (this)
     {
         if (IsEmpty(description))
         {
             ClearBuffer();
             throw new ArgumentException("Action description cannot be null or empty.");
         }
         if (Rfc2812Util.IsValidChannelName(channel))
         {
             // 19 is PRIVMSG + 2 x Spaces + : + CR + LF + 2xCtcpQuote + ACTION
             description = Truncate(description, 19 + channel.Length);
             SendMessage("PRIVMSG", channel, CtcpQuote + "ACTION " + description + CtcpQuote);
         }
         else
         {
             ClearBuffer();
             throw new ArgumentException(channel + " is not a valid channel name.");
         }
     }
 }
Example #6
0
        /// <summary>
        /// Parse the message and call the callback methods
        /// on the listeners.
        ///
        /// </summary>
        /// <param name="tokens">The text received from the IRC server</param>
        private void ParseCommand(string[] tokens)
        {
            //Remove colon user info string
            tokens[0] = RemoveLeadingColon(tokens[0]);
            switch (tokens[1])
            {
            case NOTICE:
                tokens[3] = RemoveLeadingColon(tokens[3]);
                if (Rfc2812Util.IsValidChannelName(tokens[2]))
                {
                    if (OnPublicNotice != null)
                    {
                        OnPublicNotice(
                            Rfc2812Util.UserInfoFromString(tokens[0]),
                            tokens[2],
                            CondenseStrings(tokens, 3));
                    }
                }
                else
                {
                    if (OnPrivateNotice != null)
                    {
                        OnPrivateNotice(
                            Rfc2812Util.UserInfoFromString(tokens[0]),
                            CondenseStrings(tokens, 3));
                    }
                }
                break;

            case JOIN:
                if (OnJoin != null)
                {
                    OnJoin(Rfc2812Util.UserInfoFromString(tokens[0]), RemoveLeadingColon(tokens[2]));
                }
                break;

            case PRIVMSG:
                tokens[3] = RemoveLeadingColon(tokens[3]);
                if (tokens[3] == ACTION)
                {
                    if (Rfc2812Util.IsValidChannelName(tokens[2]))
                    {
                        if (OnAction != null)
                        {
                            int last = tokens.Length - 1;
                            tokens[last] = RemoveTrailingQuote(tokens[last]);
                            OnAction(Rfc2812Util.UserInfoFromString(tokens[0]), tokens[2], CondenseStrings(tokens, 4));
                        }
                    }
                    else
                    {
                        if (OnPrivateAction != null)
                        {
                            int last = tokens.Length - 1;
                            tokens[last] = RemoveTrailingQuote(tokens[last]);
                            OnPrivateAction(Rfc2812Util.UserInfoFromString(tokens[0]), CondenseStrings(tokens, 4));
                        }
                    }
                }
                else if (channelPattern.IsMatch(tokens[2]))
                {
                    if (OnPublic != null)
                    {
                        OnPublic(Rfc2812Util.UserInfoFromString(tokens[0]), tokens[2], CondenseStrings(tokens, 3));
                    }
                }
                else
                {
                    if (OnPrivate != null)
                    {
                        OnPrivate(Rfc2812Util.UserInfoFromString(tokens[0]), CondenseStrings(tokens, 3));
                    }
                }
                break;

            case NICK:
                if (OnNick != null)
                {
                    OnNick(Rfc2812Util.UserInfoFromString(tokens[0]), RemoveLeadingColon(tokens[2]));
                }
                break;

            case PART:
                if (OnPart != null)
                {
                    OnPart(
                        Rfc2812Util.UserInfoFromString(tokens[0]),
                        tokens[2],
                        tokens.Length >= 4 ? RemoveLeadingColon(CondenseStrings(tokens, 3)) : "");
                }
                break;

            case QUIT:
                if (OnQuit != null)
                {
                    tokens[2] = RemoveLeadingColon(tokens[2]);
                    OnQuit(Rfc2812Util.UserInfoFromString(tokens[0]), CondenseStrings(tokens, 2));
                }
                break;

            case INVITE:
                if (OnInvite != null)
                {
                    OnInvite(
                        Rfc2812Util.UserInfoFromString(tokens[0]), RemoveLeadingColon(tokens[3]));
                }
                break;

            case KICK:
                if (OnKick != null)
                {
                    tokens[4] = RemoveLeadingColon(tokens[4]);
                    OnKick(Rfc2812Util.UserInfoFromString(tokens[0]), tokens[2], tokens[3], CondenseStrings(tokens, 4));
                }
                break;

            case MODE:
                if (channelPattern.IsMatch(tokens[2]))
                {
                    if (OnChannelModeChange != null)
                    {
                        UserInfo who = Rfc2812Util.UserInfoFromString(tokens[0]);
                        OnChannelModeChange(who, tokens[2]);
                    }
                }
                break;

            case KILL:
                if (OnKill != null)
                {
                    string reason = "";
                    if (tokens.Length >= 4)
                    {
                        tokens[3] = RemoveLeadingColon(tokens[3]);
                        reason    = CondenseStrings(tokens, 3);
                    }
                    OnKill(Rfc2812Util.UserInfoFromString(tokens[0]), tokens[2], reason);
                }
                break;

            default:
                if (OnError != null)
                {
                    OnError(ReplyCode.UnparseableMessage, CondenseStrings(tokens, 0));
                }
                break;
            }
        }
Example #7
0
        /// <summary>
        /// Parse the message and call the callback methods
        /// on the listeners.
        ///
        /// </summary>
        /// <param name="tokens">The text received from the IRC server</param>
        private void ParseCommand(string[] tokens)
        {
            //Remove colon user info string
            tokens[0] = RemoveLeadingColon(tokens[0]);
            switch (tokens[1])
            {
            case NOTICE:
                tokens[3] = RemoveLeadingColon(tokens[3]);
                if (Rfc2812Util.IsValidChannelName(tokens[2]))
                {
                    if (OnPublicNotice != null)
                    {
                        OnPublicNotice(
                            Rfc2812Util.UserInfoFromString(tokens[0]),
                            tokens[2],
                            CondenseStrings(tokens, 3));
                    }
                }
                else
                {
                    if (OnPrivateNotice != null)
                    {
                        OnPrivateNotice(
                            Rfc2812Util.UserInfoFromString(tokens[0]),
                            CondenseStrings(tokens, 3));
                    }
                }
                break;

            case JOIN:
                if (OnJoin != null)
                {
                    OnJoin(Rfc2812Util.UserInfoFromString(tokens[0]), RemoveLeadingColon(tokens[2]));
                }
                break;

            case PRIVMSG:
                tokens[3] = RemoveLeadingColon(tokens[3]);
                if (tokens[3] == ACTION)
                {
                    if (Rfc2812Util.IsValidChannelName(tokens[2]))
                    {
                        if (OnAction != null)
                        {
                            int last = tokens.Length - 1;
                            tokens[last] = RemoveTrailingQuote(tokens[last]);
                            OnAction(Rfc2812Util.UserInfoFromString(tokens[0]), tokens[2], CondenseStrings(tokens, 4));
                        }
                    }
                    else
                    {
                        if (OnPrivateAction != null)
                        {
                            int last = tokens.Length - 1;
                            tokens[last] = RemoveTrailingQuote(tokens[last]);
                            OnPrivateAction(Rfc2812Util.UserInfoFromString(tokens[0]), CondenseStrings(tokens, 4));
                        }
                    }
                }
                else if (channelPattern.IsMatch(tokens[2]))
                {
                    if (OnPublic != null)
                    {
                        OnPublic(Rfc2812Util.UserInfoFromString(tokens[0]), tokens[2], CondenseStrings(tokens, 3));
                    }
                }
                else
                {
                    if (OnPrivate != null)
                    {
                        OnPrivate(Rfc2812Util.UserInfoFromString(tokens[0]), CondenseStrings(tokens, 3));
                    }
                }
                break;

            case NICK:
                if (OnNick != null)
                {
                    OnNick(Rfc2812Util.UserInfoFromString(tokens[0]), RemoveLeadingColon(tokens[2]));
                }
                break;

            case TOPIC:
                if (OnTopicChanged != null)
                {
                    tokens[3] = RemoveLeadingColon(tokens[3]);
                    OnTopicChanged(
                        Rfc2812Util.UserInfoFromString(tokens[0]), tokens[2], CondenseStrings(tokens, 3));
                }
                break;

            case PART:
                if (OnPart != null)
                {
                    OnPart(
                        Rfc2812Util.UserInfoFromString(tokens[0]),
                        tokens[2],
                        tokens.Length >= 4 ? RemoveLeadingColon(CondenseStrings(tokens, 3)) : "");
                }
                break;

            case QUIT:
                if (OnQuit != null)
                {
                    tokens[2] = RemoveLeadingColon(tokens[2]);
                    OnQuit(Rfc2812Util.UserInfoFromString(tokens[0]), CondenseStrings(tokens, 2));
                }
                break;

            case INVITE:
                if (OnInvite != null)
                {
                    OnInvite(
                        Rfc2812Util.UserInfoFromString(tokens[0]), RemoveLeadingColon(tokens[3]));
                }
                break;

            case KICK:
                if (OnKick != null)
                {
                    tokens[4] = RemoveLeadingColon(tokens[4]);
                    OnKick(Rfc2812Util.UserInfoFromString(tokens[0]), tokens[2], tokens[3], CondenseStrings(tokens, 4));
                }
                break;

            case MODE:
                if (channelPattern.IsMatch(tokens[2]))
                {
                    if (OnChannelModeChange != null)
                    {
                        UserInfo who = Rfc2812Util.UserInfoFromString(tokens[0]);
                        try
                        {
                            ChannelModeInfo[] modes = ChannelModeInfo.ParseModes(tokens, 3);
                            OnChannelModeChange(who, tokens[2], modes);
                        }
                        catch (Exception)
                        {
                            if (OnError != null)
                            {
                                OnError(ReplyCode.UnparseableMessage, CondenseStrings(tokens, 0));
                            }
                            Debug.WriteLineIf(Rfc2812Util.IrcTrace.TraceWarning, "[" + Thread.CurrentThread.Name + "] Listener::ParseCommand() Bad IRC MODE string=" + tokens[0]);
                        }
                    }
                }
                else
                {
                    if (OnUserModeChange != null)
                    {
                        tokens[3] = RemoveLeadingColon(tokens[3]);
                        OnUserModeChange(Rfc2812Util.CharToModeAction(tokens[3][0]),
                                         Rfc2812Util.CharToUserMode(tokens[3][1]));
                    }
                }
                break;

            case KILL:
                if (OnKill != null)
                {
                    string reason = "";
                    if (tokens.Length >= 4)
                    {
                        tokens[3] = RemoveLeadingColon(tokens[3]);
                        reason    = CondenseStrings(tokens, 3);
                    }
                    OnKill(Rfc2812Util.UserInfoFromString(tokens[0]), tokens[2], reason);
                }
                break;

            default:
                if (OnError != null)
                {
                    OnError(ReplyCode.UnparseableMessage, CondenseStrings(tokens, 0));
                }
                Debug.WriteLineIf(Rfc2812Util.IrcTrace.TraceWarning, "[" + Thread.CurrentThread.Name + "] Listener::ParseCommand() Unknown IRC command=" + tokens[1]);
                break;
            }
        }