From 1f0c75d6771e43ed781eafd810be8414c199ec60 Mon Sep 17 00:00:00 2001 From: spiral Date: Fri, 7 May 2021 17:35:09 +0100 Subject: [PATCH] Add logging message edits --- PluralKit.Bot/Commands/MessageEdit.cs | 8 ++- PluralKit.Bot/Services/EmbedService.cs | 13 ++++ PluralKit.Bot/Services/LogChannelService.cs | 68 ++++++++++++++++----- 3 files changed, 73 insertions(+), 16 deletions(-) diff --git a/PluralKit.Bot/Commands/MessageEdit.cs b/PluralKit.Bot/Commands/MessageEdit.cs index c979bc59..782a6f6f 100644 --- a/PluralKit.Bot/Commands/MessageEdit.cs +++ b/PluralKit.Bot/Commands/MessageEdit.cs @@ -20,14 +20,16 @@ namespace PluralKit.Bot private readonly IClock _clock; private readonly DiscordApiClient _rest; private readonly WebhookExecutorService _webhookExecutor; + private readonly LogChannelService _logChannel; - public MessageEdit(IDatabase db, ModelRepository repo, IClock clock, DiscordApiClient rest, WebhookExecutorService webhookExecutor) + public MessageEdit(IDatabase db, ModelRepository repo, IClock clock, DiscordApiClient rest, WebhookExecutorService webhookExecutor, LogChannelService logChannel) { _db = db; _repo = repo; _clock = clock; _rest = rest; _webhookExecutor = webhookExecutor; + _logChannel = logChannel; } public async Task EditMessage(Context ctx) @@ -41,12 +43,16 @@ namespace PluralKit.Bot var newContent = ctx.RemainderOrNull(); + var originalMsg = await _rest.GetMessage(msg.Channel, msg.Mid); + try { await _webhookExecutor.EditWebhookMessage(msg.Channel, msg.Mid, newContent); if (ctx.BotPermissions.HasFlag(PermissionSet.ManageMessages)) await _rest.DeleteMessage(ctx.Channel.Id, ctx.Message.Id); + + await _logChannel.LogEditedMessage(ctx.MessageContext, msg, ctx.Message, originalMsg!, newContent); } catch (NotFoundException) { diff --git a/PluralKit.Bot/Services/EmbedService.cs b/PluralKit.Bot/Services/EmbedService.cs index 2e88a81e..6c5111c8 100644 --- a/PluralKit.Bot/Services/EmbedService.cs +++ b/PluralKit.Bot/Services/EmbedService.cs @@ -112,6 +112,19 @@ namespace PluralKit.Bot { .Build(); } + public Embed CreateEditedMessageEmbed(PKSystem system, PKMember member, ulong messageId, ulong originalMsgId, User sender, string content, string oldContent, Channel channel) { + var timestamp = DiscordUtils.SnowflakeToInstant(messageId); + var name = member.NameFor(LookupContext.ByNonOwner); + return new EmbedBuilder() + .Author(new($"[Edited] #{channel.Name}: {name}", IconUrl: DiscordUtils.WorkaroundForUrlBug(member.AvatarFor(LookupContext.ByNonOwner)))) + .Thumbnail(new(member.AvatarFor(LookupContext.ByNonOwner))) + .Field(new("Old message", oldContent?.NormalizeLineEndSpacing().Truncate(1000))) + .Description(content?.NormalizeLineEndSpacing()) + .Footer(new($"System ID: {system.Hid} | Member ID: {member.Hid} | Sender: {sender.Username}#{sender.Discriminator} ({sender.Id}) | Message ID: {messageId} | Original Message ID: {originalMsgId}")) + .Timestamp(timestamp.ToDateTimeOffset().ToString("O")) + .Build(); + } + public async Task CreateMemberEmbed(PKSystem system, PKMember member, Guild guild, LookupContext ctx) { diff --git a/PluralKit.Bot/Services/LogChannelService.cs b/PluralKit.Bot/Services/LogChannelService.cs index 6501181f..308d452f 100644 --- a/PluralKit.Bot/Services/LogChannelService.cs +++ b/PluralKit.Bot/Services/LogChannelService.cs @@ -1,3 +1,4 @@ +using System.Linq; using System.Threading.Tasks; using Dapper; @@ -34,24 +35,11 @@ namespace PluralKit.Bot { public async ValueTask LogMessage(MessageContext ctx, ProxyMatch proxy, Message trigger, ulong hookMessage) { - if (ctx.SystemId == null || ctx.LogChannel == null || ctx.InLogBlacklist) return; - - // Find log channel and check if valid - var logChannel = await FindLogChannel(trigger.GuildId!.Value, ctx.LogChannel.Value); - if (logChannel == null || logChannel.Type != Channel.ChannelType.GuildText) return; + var logChannel = await GetAndCheckLogChannel(ctx, trigger); + if (logChannel == null) return; var triggerChannel = _cache.GetChannel(trigger.ChannelId); - // Check bot permissions - var perms = _bot.PermissionsIn(logChannel.Id); - if (!perms.HasFlag(PermissionSet.SendMessages | PermissionSet.EmbedLinks)) - { - _logger.Information( - "Does not have permission to proxy log, ignoring (channel: {ChannelId}, guild: {GuildId}, bot permissions: {BotPermissions})", - ctx.LogChannel.Value, trigger.GuildId!.Value, perms); - return; - } - // Send embed! await using var conn = await _db.Obtain(); var embed = _embed.CreateLoggedMessageEmbed(await _repo.GetSystem(conn, ctx.SystemId.Value), @@ -61,6 +49,56 @@ namespace PluralKit.Bot { await _rest.CreateMessage(logChannel.Id, new() {Content = url, Embed = embed}); } + public async ValueTask LogEditedMessage(MessageContext ctx, PKMessage proxy, Message trigger, Message originalMessage, string newContent) + { + var logChannel = await GetAndCheckLogChannel(ctx, trigger, proxy); + if (logChannel == null) return; + + var triggerChannel = _cache.GetChannel(proxy.Channel); + + // Send embed! + await using var conn = await _db.Obtain(); + var embed = _embed.CreateEditedMessageEmbed(await _repo.GetSystem(conn, ctx.SystemId.Value), + await _repo.GetMember(conn, proxy.Member), originalMessage.Id, trigger.Id, trigger.Author, newContent, originalMessage.Content, + triggerChannel); + var url = $"https://discord.com/channels/{proxy.Guild.Value}/{proxy.Channel}/{proxy.Mid}"; + await _rest.CreateMessage(logChannel.Id, new() {Content = url, Embed = embed}); + } + + private async Task GetAndCheckLogChannel(MessageContext ctx, Message trigger, PKMessage original = null) + { + var guildId = trigger.GuildId != null ? trigger.GuildId!.Value : original.Guild.Value; + var logChannelId = ctx.LogChannel; + var isBlacklisted = ctx.InLogBlacklist; + + if (original != null) + { + // we're editing a message, get log channel info from the database + var guild = await _db.Execute(c => _repo.GetGuild(c, original.Guild.Value)); + logChannelId = guild.LogChannel; + isBlacklisted = guild.Blacklist.Any(x => x == logChannelId); + } + + if (ctx.SystemId == null || logChannelId == null || isBlacklisted) return null; + + + // Find log channel and check if valid + var logChannel = await FindLogChannel(guildId, logChannelId.Value); + if (logChannel == null || logChannel.Type != Channel.ChannelType.GuildText) return null; + + // Check bot permissions + var perms = _bot.PermissionsIn(logChannel.Id); + if (!perms.HasFlag(PermissionSet.SendMessages | PermissionSet.EmbedLinks)) + { + _logger.Information( + "Does not have permission to proxy log, ignoring (channel: {ChannelId}, guild: {GuildId}, bot permissions: {BotPermissions})", + ctx.LogChannel.Value, trigger.GuildId!.Value, perms); + return null; + } + + return logChannel; + } + private async Task FindLogChannel(ulong guildId, ulong channelId) { // TODO: fetch it directly on cache miss?