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); }
public async Task AddMessage(ChatMessageViewModel message) { try { message.ProcessingStartTime = DateTimeOffset.Now; Logger.Log(LogLevel.Debug, string.Format("Message Received - {0} - {1} - {2}", message.ID.ToString(), message.ProcessingStartTime, message)); // Pre message processing if (message is UserChatMessageViewModel) { if (message.User != null) { if (message.Platform == StreamingPlatformTypeEnum.Twitch) { UserViewModel activeUser = ChannelSession.Services.User.GetUserByTwitchID(message.User.TwitchID); if (activeUser != null) { message.User = activeUser; } } message.User.UpdateLastActivity(); if (message.IsWhisper && ChannelSession.Settings.TrackWhispererNumber && !message.IsStreamerOrBot && message.User.WhispererNumber == 0) { 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)); }); } } } // Add message to chat list bool showMessage = true; if (ChannelSession.Settings.HideBotMessages && message.User != null && ChannelSession.TwitchBotNewAPI != null && message.User.TwitchID.Equals(ChannelSession.TwitchBotNewAPI.id)) { showMessage = false; } if (!(message is AlertChatMessageViewModel) || !ChannelSession.Settings.OnlyShowAlertsInDashboard) { this.messagesLookup[message.ID] = message; if (showMessage) { if (ChannelSession.Settings.LatestChatAtTop) { this.Messages.Insert(0, message); } else { this.Messages.Add(message); } } if (this.Messages.Count > ChannelSession.Settings.MaxMessagesInChat) { ChatMessageViewModel removedMessage = (ChannelSession.Settings.LatestChatAtTop) ? this.Messages.Last() : this.Messages.First(); this.messagesLookup.Remove(removedMessage.ID); this.Messages.Remove(removedMessage); } } // Post message processing if (message is UserChatMessageViewModel && message.User != null) { if (message.IsWhisper && !message.IsStreamerOrBot) { if (!string.IsNullOrEmpty(ChannelSession.Settings.NotificationChatWhisperSoundFilePath)) { await ChannelSession.Services.AudioService.Play(ChannelSession.Settings.NotificationChatWhisperSoundFilePath, ChannelSession.Settings.NotificationChatWhisperSoundVolume, ChannelSession.Settings.NotificationsAudioOutput); } if (!string.IsNullOrEmpty(message.PlainTextMessage)) { EventTrigger trigger = new EventTrigger(EventTypeEnum.ChatWhisperReceived, message.User); trigger.SpecialIdentifiers["message"] = message.PlainTextMessage; await ChannelSession.Services.Events.PerformEvent(trigger); } // Don't send this if it's in response to another "You are whisperer #" message if (ChannelSession.Settings.TrackWhispererNumber && message.User.WhispererNumber > 0 && !message.PlainTextMessage.StartsWith("You are whisperer #", StringComparison.InvariantCultureIgnoreCase)) { await ChannelSession.Services.Chat.Whisper(message.User, $"You are whisperer #{message.User.WhispererNumber}.", sendAsStreamer : false); } } else { if (this.DisableChat) { Logger.Log(LogLevel.Debug, string.Format("Deleting Message As Chat Disabled - {0} - {1}", message.ID, message)); await this.DeleteMessage(message); return; } if (!string.IsNullOrEmpty(ChannelSession.Settings.NotificationChatTaggedSoundFilePath) && message.IsStreamerTagged) { await ChannelSession.Services.AudioService.Play(ChannelSession.Settings.NotificationChatTaggedSoundFilePath, ChannelSession.Settings.NotificationChatTaggedSoundVolume, ChannelSession.Settings.NotificationsAudioOutput); } else if (!string.IsNullOrEmpty(ChannelSession.Settings.NotificationChatMessageSoundFilePath)) { await ChannelSession.Services.AudioService.Play(ChannelSession.Settings.NotificationChatMessageSoundFilePath, ChannelSession.Settings.NotificationChatMessageSoundVolume, ChannelSession.Settings.NotificationsAudioOutput); } if (message.User != null && !this.userEntranceCommands.Contains(message.User.ID)) { this.userEntranceCommands.Add(message.User.ID); if (ChannelSession.Settings.GetCommand(message.User.Data.EntranceCommandID) != null) { await ChannelSession.Settings.GetCommand(message.User.Data.EntranceCommandID).Perform(new CommandParametersModel(message.User, message.Platform, message.ToArguments())); } } if (!string.IsNullOrEmpty(message.PlainTextMessage)) { EventTrigger trigger = new EventTrigger(EventTypeEnum.ChatMessageReceived, message.User); trigger.SpecialIdentifiers["message"] = message.PlainTextMessage; await ChannelSession.Services.Events.PerformEvent(trigger); } message.User.Data.TotalChatMessageSent++; string primaryTaggedUsername = message.PrimaryTaggedUsername; if (!string.IsNullOrEmpty(primaryTaggedUsername)) { UserViewModel primaryTaggedUser = ChannelSession.Services.User.GetUserByUsername(primaryTaggedUsername, message.Platform); if (primaryTaggedUser != null) { primaryTaggedUser.Data.TotalTimesTagged++; } } } await message.User.RefreshDetails(); if (!message.IsWhisper && await message.CheckForModeration()) { await this.DeleteMessage(message); return; } IEnumerable <string> arguments = null; if (!string.IsNullOrEmpty(message.PlainTextMessage) && message.User != null && !message.User.UserRoles.Contains(UserRoleEnum.Banned)) { if (!ChannelSession.Settings.AllowCommandWhispering && message.IsWhisper) { return; } if (ChannelSession.Settings.IgnoreBotAccountCommands) { if (ChannelSession.TwitchBotNewAPI != null && message.User.TwitchID.Equals(ChannelSession.TwitchBotNewAPI.id)) { return; } } Logger.Log(LogLevel.Debug, string.Format("Checking Message For Command - {0} - {1}", message.ID, message)); bool commandTriggered = false; if (message.User.Data.CustomCommandIDs.Count > 0) { Dictionary <string, CommandModelBase> userOnlyTriggersToCommands = new Dictionary <string, CommandModelBase>(); List <ChatCommandModel> userOnlyWildcardCommands = new List <ChatCommandModel>(); foreach (Guid commandID in message.User.Data.CustomCommandIDs) { ChatCommandModel command = (ChatCommandModel)ChannelSession.Settings.GetCommand(commandID); if (command != null && command.IsEnabled) { if (command.Wildcards) { userOnlyWildcardCommands.Add(command); } else { foreach (string trigger in command.GetFullTriggers()) { userOnlyTriggersToCommands[trigger.ToLower()] = command; } } } } if (!commandTriggered && userOnlyWildcardCommands.Count > 0) { foreach (ChatCommandModel command in userOnlyWildcardCommands) { if (command.DoesMessageMatchWildcardTriggers(message, out arguments)) { await this.RunChatCommand(message, command, arguments); commandTriggered = true; break; } } } if (!commandTriggered && userOnlyTriggersToCommands.Count > 0) { commandTriggered = await this.CheckForChatCommandAndRun(message, userOnlyTriggersToCommands); } } if (!commandTriggered) { foreach (ChatCommandModel command in this.wildcardCommands) { if (command.DoesMessageMatchWildcardTriggers(message, out arguments)) { await this.RunChatCommand(message, command, arguments); commandTriggered = true; break; } } } if (!commandTriggered) { commandTriggered = await this.CheckForChatCommandAndRun(message, this.triggersToCommands); } } foreach (InventoryModel inventory in ChannelSession.Settings.Inventory.Values.ToList()) { if (inventory.ShopEnabled && ChatCommandModel.DoesMessageMatchTriggers(message, new List <string>() { inventory.ShopCommand }, out arguments)) { await inventory.PerformShopCommand(message.User, arguments, message.Platform); } else if (inventory.TradeEnabled && ChatCommandModel.DoesMessageMatchTriggers(message, new List <string>() { inventory.TradeCommand }, out arguments)) { await inventory.PerformTradeCommand(message.User, arguments, message.Platform); } } if (ChannelSession.Settings.RedemptionStoreEnabled) { if (ChatCommandModel.DoesMessageMatchTriggers(message, new List <string>() { ChannelSession.Settings.RedemptionStoreChatPurchaseCommand }, out arguments)) { await RedemptionStorePurchaseModel.Purchase(message.User, arguments); } else if (ChatCommandModel.DoesMessageMatchTriggers(message, new List <string>() { ChannelSession.Settings.RedemptionStoreModRedeemCommand }, out arguments)) { await RedemptionStorePurchaseModel.Redeem(message.User, arguments); } } GlobalEvents.ChatMessageReceived(message); await this.WriteToChatEventLog(message); } Logger.Log(LogLevel.Debug, string.Format("Message Processing Complete: {0} - {1} ms", message.ID, message.ProcessingTime)); if (message.ProcessingTime > 500) { Logger.Log(LogLevel.Error, string.Format("Long processing time detected for the following message: {0} - {1} ms - {2}", message.ID.ToString(), message.ProcessingTime, message)); } } catch (Exception ex) { Logger.Log(ex); } }