protected void DownloadAllEmotes()
 {
     Task.Factory.StartNew(() =>
     {
         try
         {
             Action invokation = () =>
             {
                 TwitchEmoteResolver.DownloadFrankerFaceZGlobalEmotesList();
                 TwitchEmoteResolver.DownloadTwitchEmotesList();
             };
             if (InvokeRequired)
             {
                 Invoke(invokation);
             }
             else
             {
                 invokation();
             }
         }
         catch (Exception ex)
         {
             Log.Error(ex);
         }
     });
 }
        private void ChatBoxAppend(string message, Color color)
        {
            Action action = () =>
            {
                int begin = chatBox.Text.Length;
                chatBox.AppendText(DateTime.Now.ToString("HH:mm "));
                chatBox.Select(begin, chatBox.Text.Length);
                chatBox.SelectionColor = Color.Gray;

                bool   colorSplit       = message[0] == 3;
                Color  origColor        = color;
                string colorlessMessage = "";
                int    actualBegin      = chatBox.Text.Length;
                foreach (var split in message.Split(new[] { (char)3 }, StringSplitOptions.RemoveEmptyEntries))
                {
                    begin = chatBox.Text.Length;
                    string useSplit = split;
                    if (colorSplit && split.Length > 1 && split[1] >= '0' && split[1] <= '9')
                    {
                        int  code   = -1;
                        bool parsed = int.TryParse(split.Substring(0, 2), out code);
                        color    = parsed ? GetColorByCode(code) : origColor;
                        useSplit = split.Substring(2);
                    }
                    else if (colorSplit)
                    {
                        int  code   = -1;
                        bool parsed = int.TryParse(split.Substring(0, 1), out code);
                        color = parsed ? GetColorByCode(code) : origColor;
                        if (parsed)
                        {
                            useSplit = split.Substring(1);
                        }
                    }
                    var  replacedText = useSplit.Replace(((char)2).ToString(), "");
                    bool isFirst      = true;
                    foreach (var word in replacedText.Split(' '))
                    {
                        if (TwitchEmoteResolver.IsEmote(word))
                        {
                            chatBox.AppendText((isFirst ? "" : " "));
                            var image      = TwitchEmoteResolver.Resolve(word);
                            var whiteImage = new Bitmap(image.Width, image.Height);
                            var g          = Graphics.FromImage(whiteImage);
                            g.FillRectangle(Brushes.White, 0, 0, image.Width, image.Height);
                            g.DrawImage(image, 0, 0, image.Width, image.Height);
                            Clipboard.SetDataObject(whiteImage);
                            chatBox.ReadOnly = false;
                            chatBox.Paste();
                            chatBox.ReadOnly = true;
                        }
                        else
                        {
                            chatBox.AppendText((isFirst ? "" : " ") + word);
                        }
                        isFirst = false;
                    }
                    colorlessMessage += useSplit;
                    chatBox.Select(begin, chatBox.Text.Length);
                    chatBox.SelectionColor = color;
                    colorSplit             = true;
                }
                bool bold = false;
                int  boldBeginPosition = actualBegin;
                foreach (string boldSplit in colorlessMessage.Split((char)2))
                {
                    if (bold)
                    {
                        chatBox.Select(boldBeginPosition, boldSplit.Length);
                        chatBox.SelectionFont = new Font(chatBox.SelectionFont, FontStyle.Bold);
                    }
                    bold = !bold;
                    boldBeginPosition += boldSplit.Length;
                }

                chatBox.AppendText("\r\n");
                chatBox.Select(chatBox.TextLength, 0);
                chatBox.ScrollToCaret();
            };

            if (chatBox.InvokeRequired)
            {
                chatBox.Invoke(action);
            }
            else
            {
                action();
            }
        }
        private void Channel_ChatUpdate(object sender, IEnumerable <ChatMessage> chatMessages)
        {
            if (formClosing)
            {
                return;
            }

            foreach (ChatMessage m in chatMessages)
            {
                if (m.Type == MessageType.Race)
                {
                    continue;
                }
                if (Channel.Race?.State == RaceState.Started && hideFinishesCheckBox.Checked && m is SystemMessage && ((SystemMessage)m).IsFinishingMessage)
                {
                    continue;
                }
                if (Channel.Race?.State == RaceState.Started && hideChatCheckBox.Checked && ((m.User.Role & (UserRole.ChannelCreator | UserRole.Monitor | UserRole.Bot | UserRole.Staff | UserRole.System)) == 0))
                {
                    continue;
                }

                chatBox.AppendText("\n");
                chatBox.AppendText(m.Posted.ToString("HH:mm"), Color.Silver, Color.White);
                chatBox.AppendText("  ");

                Color        col          = Color.White;
                RacetimeUser u            = RacetimeUser.Anonymous;
                bool         hideUsername = m.User == RacetimeUser.LiveSplit || m.User == RacetimeUser.System;

                if (m.User == RacetimeUser.Bot)
                {
                    col = Color.FromArgb(115, 100, 255);
                }
                else
                {
                    col = ColorList[Math.Abs(m.User.Class) % ColorList.Length];
                }

                if (!hideUsername)
                {
                    chatBox.AppendText(m is BotMessage ? "[" + (((BotMessage)m).BotName) + "]" : m.User.Name, col, Color.White, false, m.User == RacetimeUser.System);
                }
                else if (m.User == RacetimeUser.System)
                {
                    chatBox.AppendText("» ");
                }


                chatBox.AppendText("  ");

                string[] words     = m.Message.Split(' ');
                bool     firstWord = true;

                if (m.Highlight)
                {
                    chatBox.SelectionColor = PickHighlightColor(m);
                }
                else if (m.User == RacetimeUser.Bot)
                {
                    chatBox.SelectionColor = Color.FromArgb(170, 170, 255);
                }

                foreach (var word in words)
                {
                    if (TwitchEmoteResolver.IsEmote(word))
                    {
                        chatBox.AppendText((firstWord ? "" : " "));
                        var image      = TwitchEmoteResolver.Resolve(word);
                        var whiteImage = new Bitmap(image.Width, image.Height);
                        var g          = Graphics.FromImage(whiteImage);
                        g.FillRectangle(Brushes.White, 0, 0, image.Width, image.Height);
                        g.DrawImage(image, 0, 0, image.Width, image.Height);
                        Clipboard.SetDataObject(whiteImage);
                        chatBox.ReadOnly = false;
                        chatBox.Paste();
                        chatBox.ReadOnly = true;
                    }
                    else
                    {
                        chatBox.AppendText((firstWord ? "" : " ") + word);
                    }

                    firstWord = false;
                }

                if (m.Highlight)
                {
                    chatBox.SelectionColor = chatBox.ForeColor;
                }

                chatBox.SelectionStart = chatBox.Text.Length;
                chatBox.ScrollToCaret();
            }
        }