private Task MessageReceived(SocketMessage message) { if (message.Author.Id == _bot.DiscordClient.CurrentUser.Id) { return(Task.CompletedTask); } if (!(message.Author is SocketGuildUser guildUser)) { return(Task.CompletedTask); } if (!(message.Channel is SocketTextChannel messageChannel)) { return(Task.CompletedTask); } if (!(messageChannel.Category is SocketCategoryChannel categoryChannel)) { return(Task.CompletedTask); } if (messageChannel.Category.Name != TranslationConstants.CategoryName) { return(Task.CompletedTask); } if (TranslationConstants.PermanentChannels.Contains(messageChannel.Name)) { return(Task.CompletedTask); } var guildLang = _serverConfig.GetLanguageForGuild(messageChannel.Guild.Id); var safeGuildLang = GetSafeLangString(guildLang); var lang = messageChannel.GetLangFromChannelName(safeGuildLang); if (lang == null) { return(Task.CompletedTask); } var safeLang = GetSafeLangString(lang); if (!_channelPairs.TryGetValue(safeLang, out var pair)) { _logger.LogWarning("Message received from a loc channel without a valid pair"); return(Task.CompletedTask); } _logger.LogDebug("Starting translation of message"); _bot.ExecuteHandlerAsyncronously <(SocketCategoryChannel category, Translation?translation)>( handler: async discord => { if (pair?.TranslationChannel == null || pair?.StandardLangChanel == null) { throw new InvalidOperationException("Invalid channel pair"); } Translation?translation = null; if (messageChannel.Id == pair.StandardLangChanel.Id) { translation = await SendMessageToPartner(message, $"{guildUser.Nickname ?? guildUser.Username}", pair.TranslationChannel, guildLang, lang, Foreign); } else if (messageChannel.Id == pair.TranslationChannel.Id) { translation = await SendMessageToPartner(message, $"{guildUser.Nickname ?? guildUser.Username}", pair.StandardLangChanel, lang, guildLang, GuildLocale); } return(categoryChannel, translation); }, callback: async result => { var(category, translation) = result; if (category == null) { return; } var historyChannel = category.Channels.OfType <SocketTextChannel>() .SingleOrDefault(a => a.Name == TranslationConstants.HistoryChannelName); if (historyChannel == null) { return; } _logger.LogDebug("Sending messages to the history channel"); var nickname = guildUser.Nickname ?? guildUser.Username; var avatar = guildUser.GetAvatarUrl() ?? guildUser.GetDefaultAvatarUrl(); var embed = new EmbedBuilder() .WithAuthor(nickname, avatar, message.GetJumpUrl()); // Translations still look better side to side when brief. // In case any one of them exceeds 1024 limit, it will be split into chunks // and all of them will be inlined. var guildLocal = translation?.GuildLocal; var foreign = translation?.Foreign; if (!string.IsNullOrEmpty(guildLocal?.Text) && !string.IsNullOrEmpty(foreign?.Text)) { const int fieldLength = 1024; var lengthIsBrief = guildLocal.Text.Length < fieldLength && foreign.Text.Length < fieldLength; var hasCodeBlocks = TranslationService.CodeBlockPattern.IsMatch(translation !.Translated.Text); if (lengthIsBrief && !hasCodeBlocks) { embed .AddField(guildLocal.Language, guildLocal.Text, true) .AddField(foreign.Language, foreign.Text, true); } else { embed .AddChunks(guildLocal.Text.ChunkUpTo(fieldLength), guildLocal.Language) .AddChunks(foreign.Text.ChunkUpTo(fieldLength), foreign.Language); } } if (message.Attachments.Any()) { embed.WithImageUrl(message.Attachments.First().Url); var others = message.Attachments.Skip(1).Select(x => x.Url).ToArray(); if (others.Length > 0) { embed.AddField("Attachments", string.Join("\n", others)); } } await historyChannel.SendMessageAsync(embed: embed.Build()); _logger.LogDebug("Completed translating messages"); }); return(Task.CompletedTask); }