Represents an IRC channel accessible via an IRCTabPage.
Inheritance: IDisposable
Exemple #1
0
        /// <summary>
        /// Sends the message to the associated server.
        /// </summary>
        /// <param name="sender">The source tab page.</param>
        /// <param name="message">The message to send.</param>
        public void Send(IRCTabPage sender, Message message)
        {
            message = MessageFactory.AssimilateMessage(message);
            if (this.Connection.IsConnected)
            {
                if ((message is PrivMsgMessage) || (message is NoticeMessage))
                {
                    IRCTabPage tabPage = null;
                    string source = this.Connection.Nickname;

                    if (message is PrivMsgMessage)
                    {
                        IRCChannel channel = this.Channels.Find(i => i.Name.Equals(message.Target, StringComparison.OrdinalIgnoreCase));
                        if (channel == null)
                        {
                            channel = this.CreateChannel(message.Target, true);
                        }

                        tabPage = channel.TabPage;
                    }
                    else
                    {
                        source = string.Format("to({0})", message.Target);
                        tabPage = sender;
                    }

                    tabPage.AppendMessage(message.Command, source, message.Content, message.Type);
                }
                else if (message is JoinMessage)
                {
                    IRCChannel channel = this.Channels.Find(i => i.Name.Equals(message.Parameters[0], StringComparison.OrdinalIgnoreCase));
                    if (channel == null)
                    {
                        channel = this.CreateChannel(message.Parameters[0], true);
                    }
                    else
                    {
                        // If we're already in the channel, just switch tabs.
                        this.TabHost.InvokeAction(() => this.TabHost.SelectedTab = channel.TabPage);
                    }
                }
                else if (message is NickMessage)
                {
                    this.previousNickName = this.connection.Nickname;
                    this.connection.Nickname = (message as NickMessage).NewNickname;
                }

                if (message is QuitMessage)
                {
                    this.disconnecting = true;
                }

                this.Connection.Send(message.ToString());
            }

            if (message is QuitMessage)
            {
                this.Dispose();
            }
        }
Exemple #2
0
 /// <summary>
 /// Handles the Disposed event of Yaircc.UI.IRCChannel.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 private void ChannelDisposed(object sender)
 {
     if ((!this.disposing) && (sender is IRCChannel))
     {
         IRCChannel channel = sender as IRCChannel;
         this.Channels.Remove(channel);
     }
 }
Exemple #3
0
        /// <summary>
        /// Creates a new channel and tab.
        /// </summary>
        /// <param name="displayName">The name of the channel.</param>
        /// <param name="switchTo">A value indicating whether or not to switch to the new channel.</param>
        /// <returns>The new channel.</returns>
        public IRCChannel CreateChannel(string displayName, bool switchTo)
        {
            IRCChannel retval = new IRCChannel(this, this.Connection);
            retval.Disposed += new IRCChannel.DisposedHandler(this.ChannelDisposed);

            IRCTabType type = IRCTabType.Channel;
            Regex regex = new Regex(@"(?<channel>[#&][^\x07\x2C\s]{1,199})", RegexOptions.IgnoreCase);
            if (!regex.Match(displayName).Success)
            {
                type = IRCTabType.PM;
            }

            this.TabHost.InvokeAction(() =>
                {
                    string tabName = string.Format("{0}_{1}", this.Connection.ToString(), displayName);
                    IRCTabPage tabPage = new IRCTabPage(this.ServerTab.OwningForm, tabName, displayName, type);
                    tabPage.Connection = this.Connection;
                    tabPage.ConnectionSpecificName = displayName;

                    retval.TabPage = tabPage;
                    retval.TabPage.Marshal = this;
                    retval.Name = displayName;

                    // Iterate through the tab pages to figure out how to place
                    // this channels tab page in a group of other ones on the
                    // same network, in alphabetical order.
                    int index = this.TabHost.TabPages.IndexOf(this.ServerTab) + 1;
                    for (int i = index; i < this.TabHost.TabPages.Count; i++)
                    {
                        IRCTabPage tab = this.TabHost.TabPages[i] as IRCTabPage;
                        if (tab != null && tab.Marshal == this && tab.Text.CompareTo(retval.TabPage.Text) < 0)
                        {
                            index = i + 1;
                        }
                        else if (tab != null && tab.Marshal != this)
                        {
                            break;
                        }
                    }
                    
                    this.TabHost.TabPages.Insert(index, tabPage);
                    if (switchTo)
                    {
                        this.TabHost.SelectedTab = tabPage;
                    }
                });

            this.Channels.Add(retval);

            if (this.channelCreated != null)
            {
                this.channelCreated.Invoke(this, retval);
            }

            return retval;
        }
Exemple #4
0
        /// <summary>
        /// Handles the ChannelCreated event of Yaircc.UI.IRCMarshal.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="channel">The newly created channel.</param>
        public void ChannelCreated(object sender, IRCChannel channel)
        {
            this.splitContainer.Panel1.InvokeAction(() =>
            {
                channel.NamesPopulated += new IRCChannel.NamesPopulatedHandler(this.ChannelUsersPopulated);

                TreeView userTreeView = new TreeView();
                userTreeView.Name = string.Format("{0}_TreeView", channel.ToString());
                userTreeView.ImageList = userModeImageList;
                userTreeView.TreeViewNodeSorter = new UserNodeSorter();
                userTreeView.MouseDown += new MouseEventHandler(UserTreeView_MouseDown);

                if (channel.TabPage.TabType == IRCTabType.Channel)
                {
                    userTreeView.Nodes.Add("Fetching user list...");
                }
                else if (channel.TabPage.TabType == IRCTabType.PM)
                {
                    TreeNode node = new TreeNode();
                    node.Text = channel.Name;
                    node.ImageKey = "user";
                    node.SelectedImageKey = node.ImageKey;
                    userTreeView.Nodes.Add(node);
                }

                splitContainer.Panel1.Controls.Add(userTreeView);
                userTreeView.Dock = DockStyle.Fill;

                channel.TabPage.UserTreeView = userTreeView;
                channel.TabPage.NickNameMentioned += new IRCTabPage.NickNameMentionedHandler(this.FlashWindowInTaskBar);

                if (channelsTabControl.SelectedTab == channel.TabPage)
                {
                    userTreeView.BringToFront();
                    this.inputTextBox.MaxLength = this.CurrentTab.Marshal.GetChannelByTab(this.CurrentTab).MaximumMessageSize;
                    this.UpdateStatusBarText();
                }

                this.RefreshWindowsMenuItems(null);
            });
        }
Exemple #5
0
        /// <summary>
        /// Creates a new channel and tab.
        /// </summary>
        /// <param name="displayName">The name of the channel.</param>
        /// <param name="switchTo">A value indicating whether or not to switch to the new channel.</param>
        /// <returns>The new channel.</returns>
        public IRCChannel CreateChannel(string displayName, bool switchTo)
        {
            IRCChannel retval = new IRCChannel(this, this.Connection);
            retval.Disposed += new IRCChannel.DisposedHandler(this.ChannelDisposed);

            IRCTabType type = IRCTabType.Channel;
            Regex regex = new Regex(@"(?<channel>[#&][^\x07\x2C\s]{1,199})", RegexOptions.IgnoreCase);
            if (!regex.Match(displayName).Success)
            {
                type = IRCTabType.PM;
            }

            this.TabHost.InvokeAction(() =>
                {
                    string tabName = string.Format("{0}_{1}", this.Connection.ToString(), displayName);
                    IRCTabPage tabPage = new IRCTabPage(this.ServerTab.OwningForm, tabName, displayName, type);
                    tabPage.Connection = this.Connection;
                    tabPage.ConnectionSpecificName = displayName;

                    retval.TabPage = tabPage;
                    retval.TabPage.Marshal = this;
                    retval.Name = displayName;

                    // Iterate through the tab pages to figure out how to place
                    // this channels tab page in a group of other ones on the
                    // same network, in alphabetical order.
                    int index = this.TabHost.TabPages.IndexOf(this.ServerTab) + 1;
                    for (int i = index; i < this.TabHost.TabPages.Count; i++)
                    {
                        IRCTabPage tab = this.TabHost.TabPages[i] as IRCTabPage;
                        if (tab != null && tab.Marshal == this && tab.Text.CompareTo(retval.TabPage.Text) < 0)
                        {
                            index = i + 1;
                        }
                        else if (tab != null && tab.Marshal != this)
                        {
                            break;
                        }
                    }

                    this.TabHost.TabPages.Insert(index, tabPage);
                    if (switchTo)
                    {
                        this.TabHost.SelectedTab = tabPage;
                    }
                });

            this.Channels.Add(retval);

            if (this.channelCreated != null)
            {
                this.channelCreated.Invoke(this, retval);
            }

            return retval;
        }
Exemple #6
0
        /// <summary>
        /// Process a message that contains a text based command.
        /// </summary>
        /// <param name="message">The message to process.</param>
        private void ProcessMessage(Message message)
        {
            message = MessageFactory.AssimilateMessage(message);
            string target = message.Target.Equals(this.Connection.Nickname, StringComparison.OrdinalIgnoreCase) ? message.Source : message.Target;

            if (message.MustBeHandledByTarget)
            {
                IRCChannel channel = this.Channels.Find(i => i.Name.Equals(target, StringComparison.OrdinalIgnoreCase));
                if (channel == null)
                {
                    channel = this.CreateChannel(target, false);
                }

                channel.HandleMessage(message);
            }
            else if (message.IsMultiChannelMessage)
            {
                for (int i = 0; i < this.Channels.Count; i++)
                {
                    this.Channels[i].HandleMessage(message);
                }
            }
            else if (message.IsGlobalMessage)
            {
                this.Channels.ForEach(i => i.HandleMessage(message));
                this.ServerTab.AppendMessage(message.Command, message.Source, message.Content, message.Type);
            }
            else
            {
                // If the message can be handled by both the server tab
                // and a channel tab, then we need to check if the currently
                // focused tab is a channel and if so handle it in the channel.
                // Otherwise we can just print it in the server tab
                this.TabHost.InvokeAction(() =>
                    {
                        if (this.TabHost.SelectedTab is IRCTabPage)
                        {
                            IRCChannel channel = this.Channels.Find(i => i.TabPage.Equals(this.TabHost.SelectedTab));
                            if ((channel != null) && (!this.AwaitingModeMessage))
                            {
                                channel.HandleMessage(message);
                            }
                            else
                            {
                                this.ServerTab.AppendMessage(message.Command, message.Source, message.Content, message.Type);
                            }
                        }
                    });
            }

            // If we are still awaiting the MODE message (i.e. we are awaiting confirmation we have finished connecting)
            // then also re-join any channels that we have in the Channels collection (i.e. reconnect to any channels)
            if (this.AwaitingModeMessage && message is ModeMessage)
            {
                this.AwaitingModeMessage = false;
                this.Send(this.ServerTab, new ModeMessage(new string[] { this.Connection.Nickname, this.Connection.Mode }));

                // Send the user host message so we can determine the full user host string.
                this.Send(this.ServerTab, new UserHostMessage(new string[] { this.connection.Nickname }));
            }
        }
Exemple #7
0
        /// <summary>
        /// Process a message that is categorised as being a numeric reply in the RFC documents.
        /// </summary>
        /// <param name="message">The message to process.</param>
        private void ProcessNumericReply(Message message)
        {
            Reply reply = (Reply)int.Parse(message.Command);
            Action<IRCTabPage> appendMessage = (IRCTabPage tabPage) =>
            {
                MessageTypeAttribute attributes = IRCMarshal.GetReplyAttributes(reply);
                MessageType messageType = attributes.MessageType;
                GlobalSettings settings = GlobalSettings.Instance;
                string source = attributes.Source;

                string content;
                if (attributes.OutputAction == null)
                {
                    content = message.ToString(attributes.OutputFormat, attributes.ParameterDelimiter, attributes.RemoveFirstParameter);
                }
                else
                {
                    content = attributes.OutputAction.Invoke(message);
                }

                if (settings.DebugMode == GlobalSettings.Boolean.Yes)
                {
                    tabPage.AppendMessage(reply.ToString(), "[RAW]", message.ToString(), MessageType.WarningMessage);
                }

                tabPage.AppendMessage(reply.ToString(), source, content, messageType);
            };

            // If we are retrieving list replies we need to populate the channel browser
            if (reply == Reply.RPL_LISTSTART)
            {
                this.parent.InvokeAction(() => this.ChannelBrowser.BeginRefresh(true));
                return;
            }
            else if (reply == Reply.RPL_LIST)
            {
                this.ChannelBrowser.AddChannel(message);
                return;
            }
            else if (reply == Reply.RPL_LISTEND)
            {
                this.parent.InvokeAction(() => this.ChannelBrowser.FlushChannels());
                return;
            }

            // If we are still awaiting the UserHost reply (i.e. we are awaiting confirmation of the full userhost 
            // prefix that we will use to determine the max PRIVMSG lengths) then cache it in the marshal for future
            // reference.
            if (this.AwaitingUserHostMessage && reply == Reply.RPL_USERHOST)
            {
                this.fullUserHost = message.TrailingParameter;
                this.AwaitingUserHostMessage = false;

                // Execute any auto commands.
                if (!this.hasExecutedAutoCommands && this.AutoCommands.Count > 0)
                {
                    for (int i = 0; i < this.AutoCommands.Count; i++)
                    {
                        MessageParseResult parseResult = MessageFactory.CreateFromUserInput(this.AutoCommands[i], null);
                        if (parseResult.Success)
                        {
                            this.Send(this.ServerTab, parseResult.IRCMessage);
                        }
                    }

                    this.hasExecutedAutoCommands = true;
                }

                if (this.reconnecting)
                {
                    // Pause the thread for a second to give time for any authentication to 
                    // take place and then rejoin the channels.
                    System.Threading.Thread.Sleep(1000);
                    this.Channels.ForEach(i =>
                    {
                        if (i.TabPage.TabType == IRCTabType.Channel)
                        {
                            this.Send(this.ServerTab, new JoinMessage(i.Name));
                        }
                    });

                    this.reconnecting = false;
                }

                return;
            }

            // If the user has received a new hidden host then we need to re-evaluate
            // their full user host mask that will be seen by other clients.
            if (reply == Reply.RPL_HOSTHIDDEN)
            {
                this.AwaitingUserHostMessage = true;
                this.Send(this.ServerTab, new UserHostMessage(new string[] { this.connection.Nickname }));
            }

            // If we have a names reply or an end of names reply, then we need to check the channel 
            // it is in regards to exists in our channel list, and if it does check to see if it 
            // is awaiting a reply from a names request (i.e. it is wanting to refresh the user list).
            //
            // If this is indeed the case, we need to force it through to that channel rather than
            // following the default procedure of going to the selected tab.
            if ((reply == Reply.RPL_NAMREPLY) || (reply == Reply.RPL_ENDOFNAMES))
            {
                string target = string.Empty;
                if (reply == Reply.RPL_NAMREPLY)
                {
                    target = message.Parameters[2];
                }
                else
                {
                    target = message.Parameters[1];
                }

                IRCChannel channel = this.channels.Find(i => i.Name.Equals(target, StringComparison.OrdinalIgnoreCase));
                if (channel != null && channel.ExpectingNamesMessage)
                {
                    channel.HandleReply(message);
                    return;
                }
            }

            // If the currently selected tab belongs to the channel list for this connection
            // AND we aren't awaiting a mode message (i.e. connecting to the server)
            // then marshal the message to the owning channel, otherwise default to the server tab
            this.TabHost.InvokeAction(() =>
                {
                    IRCChannel selectedChannel = this.Channels.Find(i => this.TabHost.SelectedTab.Equals(i.TabPage));
                    if ((selectedChannel != null) && (!this.AwaitingModeMessage))
                    {
                        selectedChannel.HandleReply(message);
                    }
                    else
                    {
                        appendMessage.Invoke(this.ServerTab);
                    }
                });

            // If a nick in use message comes through, we need to revert the nick against the connection
            // back to the previously assigned nick (if there is one).
            // If there wasn't one, then we'll append an underscore to the current one and resend the nick message
            // we couldn't possibly get stuck in a loop, right?
            if (reply == Reply.ERR_NICKNAMEINUSE)
            {
                if (this.previousNickName.Equals(this.Connection.Nickname, StringComparison.OrdinalIgnoreCase))
                {
                    this.previousNickName = string.Format("{0}_", this.previousNickName);
                    this.connection.Nickname = this.previousNickName;
                    this.Send(this.ServerTab, new NickMessage(this.previousNickName));
                }
                else
                {
                    if (!this.AwaitingModeMessage)
                    {
                        this.Connection.Nickname = this.previousNickName;
                    }
                    else
                    {
                        this.previousNickName = string.Format("{0}_", this.connection.Nickname);
                        this.connection.Nickname = this.previousNickName;
                        this.Send(this.ServerTab, new NickMessage(this.previousNickName));
                    }
                }
            }
        }