public async Task ProcessChatMessage(XivChatType type, StdString message, StdString sender) { // Special case for outgoing tells, these should be sent under Incoming tells var wasOutgoingTell = false; if (type == XivChatType.TellOutgoing) { type = XivChatType.TellIncoming; wasOutgoingTell = true; } var chatTypeConfigs = this.config.ChatTypeConfigurations.Where(typeConfig => typeConfig.ChatType == type); if (!chatTypeConfigs.Any()) { return; } var chatTypeDetail = type.GetDetails(); var channels = chatTypeConfigs.Select(c => GetChannel(c.Channel).GetAwaiter().GetResult()); var parsedSender = SeString.Parse(sender.RawData); var playerLink = parsedSender.Payloads.FirstOrDefault(x => x.Type == PayloadType.Player) as PlayerPayload; string senderName; string senderWorld; if (playerLink == null) { // chat messages from the local player do not include a player link, and are just the raw name // but we should still track other instances to know if this is ever an issue otherwise // Special case 2 - When the local player talks in party/alliance, the name comes through as raw text, // but prefixed by their position number in the party (which for local player may always be 1) if (parsedSender.TextValue.EndsWith(this.dalamud.ClientState.LocalPlayer.Name)) { senderName = this.dalamud.ClientState.LocalPlayer.Name; } else { Log.Error("playerLink was null. Sender: {0}", BitConverter.ToString(sender.RawData)); senderName = wasOutgoingTell ? this.dalamud.ClientState.LocalPlayer.Name : parsedSender.TextValue; } senderWorld = this.dalamud.ClientState.LocalPlayer.HomeWorld.GameData.Name; } else { senderName = wasOutgoingTell ? this.dalamud.ClientState.LocalPlayer.Name : playerLink.PlayerName; senderWorld = playerLink.World.Name; } var rawMessage = SeString.Parse(message.RawData).TextValue; var avatarUrl = string.Empty; var lodestoneId = string.Empty; if (!this.config.DisableEmbeds && !string.IsNullOrEmpty(senderName)) { var searchResult = await GetCharacterInfo(senderName, senderWorld); lodestoneId = searchResult.LodestoneId; avatarUrl = searchResult.AvatarUrl; } Thread.Sleep(this.config.ChatDelayMs); var name = wasOutgoingTell ? "You" : senderName + (string.IsNullOrEmpty(senderWorld) || string.IsNullOrEmpty(senderName) ? "" : $" on {senderWorld}"); for (var chatTypeIndex = 0; chatTypeIndex < chatTypeConfigs.Count(); chatTypeIndex++) { if (!this.config.DisableEmbeds) { var embedBuilder = new EmbedBuilder { Author = new EmbedAuthorBuilder { IconUrl = avatarUrl, Name = name, Url = !string.IsNullOrEmpty(lodestoneId) ? "https://eu.finalfantasyxiv.com/lodestone/character/" + lodestoneId : null }, Description = rawMessage, Timestamp = DateTimeOffset.Now, Footer = new EmbedFooterBuilder { Text = type.GetDetails().FancyName }, Color = new Color((uint)(chatTypeConfigs.ElementAt(chatTypeIndex).Color & 0xFFFFFF)) }; if (this.config.CheckForDuplicateMessages) { var recentMsg = this.recentMessages.FirstOrDefault( msg => msg.Embeds.FirstOrDefault( embed => embed.Description == embedBuilder.Description && embed.Author.HasValue && embed.Author.Value.Name == embedBuilder.Author.Name && embed.Timestamp.HasValue && Math.Abs( (embed.Timestamp.Value.ToUniversalTime().Date - embedBuilder .Timestamp.Value.ToUniversalTime().Date) .Milliseconds) < 15000) != null); if (recentMsg != null) { Log.Verbose("Duplicate message: [{0}] {1}", embedBuilder.Author.Name, embedBuilder.Description); this.recentMessages.Remove(recentMsg); return; } } await channels.ElementAt(chatTypeIndex).SendMessageAsync(embed: embedBuilder.Build()); } else { var simpleMessage = $"{name}: {rawMessage}"; if (this.config.CheckForDuplicateMessages) { var recentMsg = this.recentMessages.FirstOrDefault( msg => msg.Content == simpleMessage); if (recentMsg != null) { Log.Verbose("Duplicate message: {0}", simpleMessage); this.recentMessages.Remove(recentMsg); return; } } await channels.ElementAt(chatTypeIndex).SendMessageAsync($"**[{chatTypeDetail.Slug}]{name}**: {rawMessage}"); } } }
public async Task ProcessChatMessage(XivChatType type, string message, string sender) { // Special case for outgoing tells, these should be sent under Incoming tells var wasOutgoingTell = false; if (type == XivChatType.TellOutgoing) { type = XivChatType.TellIncoming; sender = this.dalamud.ClientState.LocalPlayer.Name; wasOutgoingTell = true; } var chatTypeConfigs = this.config.ChatTypeConfigurations.Where(typeConfig => typeConfig.ChatType == type); if (!chatTypeConfigs.Any()) { return; } var chatTypeDetail = type.GetDetails(); var channels = chatTypeConfigs.Select(c => GetChannel(c.Channel).GetAwaiter().GetResult()); var senderSplit = sender.Split(new[] { this.worldIcon }, StringSplitOptions.None); var world = string.Empty; if (this.dalamud.ClientState.Actors.Length > 0) { world = this.dalamud.ClientState.LocalPlayer.CurrentWorld.Name; } if (senderSplit.Length == 2) { world = senderSplit[1]; sender = senderSplit[0]; } sender = SeString.Parse(sender).Output; message = SeString.Parse(message).Output; sender = RemoveAllNonLanguageCharacters(sender); var avatarUrl = ""; var lodestoneId = ""; if (!this.config.DisableEmbeds) { var searchResult = await GetCharacterInfo(sender, world); lodestoneId = searchResult.LodestoneId; avatarUrl = searchResult.AvatarUrl; } Thread.Sleep(this.config.ChatDelayMs); var name = wasOutgoingTell ? "You" : sender + (string.IsNullOrEmpty(world) || string.IsNullOrEmpty(sender) ? "" : $" on {world}"); for (var chatTypeIndex = 0; chatTypeIndex < chatTypeConfigs.Count(); chatTypeIndex++) { if (!this.config.DisableEmbeds) { var embedBuilder = new EmbedBuilder { Author = new EmbedAuthorBuilder { IconUrl = avatarUrl, Name = name, Url = !string.IsNullOrEmpty(lodestoneId) ? "https://eu.finalfantasyxiv.com/lodestone/character/" + lodestoneId : null }, Description = message, Timestamp = DateTimeOffset.Now, Footer = new EmbedFooterBuilder { Text = type.GetDetails().FancyName }, Color = new Color((uint)(chatTypeConfigs.ElementAt(chatTypeIndex).Color & 0xFFFFFF)) }; if (this.config.CheckForDuplicateMessages) { var recentMsg = this.recentMessages.FirstOrDefault( msg => msg.Embeds.FirstOrDefault( embed => embed.Description == embedBuilder.Description && embed.Author.HasValue && embed.Author.Value.Name == embedBuilder.Author.Name && embed.Timestamp.HasValue && Math.Abs( (embed.Timestamp.Value.ToUniversalTime().Date - embedBuilder .Timestamp.Value.ToUniversalTime().Date) .Milliseconds) < 15000) != null); if (recentMsg != null) { Log.Verbose("Duplicate message: [{0}] {1}", embedBuilder.Author.Name, embedBuilder.Description); this.recentMessages.Remove(recentMsg); return; } } await channels.ElementAt(chatTypeIndex).SendMessageAsync(embed: embedBuilder.Build()); } else { var simpleMessage = $"{name}: {message}"; if (this.config.CheckForDuplicateMessages) { var recentMsg = this.recentMessages.FirstOrDefault( msg => msg.Content == simpleMessage); if (recentMsg != null) { Log.Verbose("Duplicate message: {0}", simpleMessage); this.recentMessages.Remove(recentMsg); return; } } await channels.ElementAt(chatTypeIndex).SendMessageAsync($"**[{chatTypeDetail.Slug}]{name}**: {message}"); } } }