private async Task <ChatMessageViewModel> AddMessage(ChatMessageEventModel messageEvent)
        {
            UserViewModel user = await ChannelSession.ActiveUsers.AddOrUpdateUser(messageEvent.GetUser());

            if (user == null)
            {
                user = new UserViewModel(messageEvent);
            }
            else
            {
                await user.RefreshDetails();
            }
            user.UpdateLastActivity();

            ChatMessageViewModel message = new ChatMessageViewModel(messageEvent, user);

            Util.Logger.LogDiagnostic(string.Format("Message Received - {0}", message.ToString()));

            if (!message.IsWhisper && !this.userEntranceCommands.Contains(user.ID))
            {
                this.userEntranceCommands.Add(user.ID);
                if (user.Data.EntranceCommand != null)
                {
                    await user.Data.EntranceCommand.Perform(user);
                }
            }

            if (this.Messages.ContainsKey(message.ID))
            {
                return(null);
            }
            this.Messages[message.ID] = message;

            if (this.DisableChat && !message.ID.Equals(Guid.Empty))
            {
                Util.Logger.LogDiagnostic(string.Format("Deleting Message As Chat Disabled - {0}", message.Message));
                await this.DeleteMessage(message);

                return(message);
            }

            if (!ModerationHelper.MeetsChatInteractiveParticipationRequirement(user) || !ModerationHelper.MeetsChatEmoteSkillsOnlyParticipationRequirement(user, message))
            {
                Util.Logger.LogDiagnostic(string.Format("Deleting Message As User does not meet requirement - {0} - {1}", ChannelSession.Settings.ModerationChatInteractiveParticipation, message.Message));

                await this.DeleteMessage(message);

                await ModerationHelper.SendChatInteractiveParticipationWhisper(user, isChat : true);

                return(message);
            }

            string moderationReason = await message.ShouldBeModerated();

            if (!string.IsNullOrEmpty(moderationReason))
            {
                Util.Logger.LogDiagnostic(string.Format("Message Should Be Moderated - {0}", message.ToString()));

                bool shouldBeModerated         = true;
                PermissionsCommandBase command = this.CheckMessageForCommand(message);
                if (command != null && string.IsNullOrEmpty(await ModerationHelper.ShouldBeFilteredWordModerated(user, message.Message)))
                {
                    shouldBeModerated = false;
                }

                if (shouldBeModerated)
                {
                    Util.Logger.LogDiagnostic(string.Format("Moderation Being Performed - {0}", message.ToString()));

                    message.ModerationReason = moderationReason;
                    await this.DeleteMessage(message);

                    return(message);
                }
            }

            if (!string.IsNullOrEmpty(ChannelSession.Settings.NotificationChatWhisperSoundFilePath) && message.IsWhisper)
            {
                await ChannelSession.Services.AudioService.Play(ChannelSession.Settings.NotificationChatWhisperSoundFilePath, 100);
            }
            else if (!string.IsNullOrEmpty(ChannelSession.Settings.NotificationChatTaggedSoundFilePath) && message.IsUserTagged)
            {
                await ChannelSession.Services.AudioService.Play(ChannelSession.Settings.NotificationChatTaggedSoundFilePath, 100);
            }
            else if (!string.IsNullOrEmpty(ChannelSession.Settings.NotificationChatMessageSoundFilePath))
            {
                await ChannelSession.Services.AudioService.Play(ChannelSession.Settings.NotificationChatMessageSoundFilePath, 100);
            }

            GlobalEvents.ChatMessageReceived(message);

            if (!await this.CheckMessageForCommandAndRun(message))
            {
                if (message.IsWhisper && ChannelSession.Settings.TrackWhispererNumber && !message.IsStreamerOrBot())
                {
                    await this.whisperNumberLock.WaitAndRelease(() =>
                    {
                        if (!whisperMap.ContainsKey(message.User.ID))
                        {
                            whisperMap[message.User.ID] = whisperMap.Count + 1;
                        }
                        message.User.WhispererNumber = whisperMap[message.User.ID];
                        return(Task.FromResult(0));
                    });

                    await ChannelSession.Chat.Whisper(message.User.UserName, $"You are whisperer #{message.User.WhispererNumber}.", false);
                }
            }

            return(message);
        }