Return original message ID to log channel

Logs the original (deleted) message's ID in addition to the proxied message's ID to the log channel if configured
This commit is contained in:
xBelladonna 2019-08-08 15:06:09 +09:30 committed by Astrid
parent cf263af44c
commit fabf772085
3 changed files with 21 additions and 21 deletions

View File

@ -53,13 +53,13 @@ namespace PluralKit.Bot {
return eb.Build(); return eb.Build();
} }
public Embed CreateLoggedMessageEmbed(PKSystem system, PKMember member, ulong messageId, IUser sender, string content, IGuildChannel channel) { public Embed CreateLoggedMessageEmbed(PKSystem system, PKMember member, ulong messageId, ulong originalMsgId, IUser sender, string content, IGuildChannel channel) {
// TODO: pronouns in ?-reacted response using this card // TODO: pronouns in ?-reacted response using this card
var timestamp = SnowflakeUtils.FromSnowflake(messageId); var timestamp = SnowflakeUtils.FromSnowflake(messageId);
return new EmbedBuilder() return new EmbedBuilder()
.WithAuthor($"#{channel.Name}: {member.Name}", member.AvatarUrl) .WithAuthor($"#{channel.Name}: {member.Name}", member.AvatarUrl)
.WithDescription(content) .WithDescription(content)
.WithFooter($"System ID: {system.Hid} | Member ID: {member.Hid} | Sender: {sender.Username}#{sender.Discriminator} ({sender.Id}) | Message ID: {messageId}") .WithFooter($"System ID: {system.Hid} | Member ID: {member.Hid} | Sender: {sender.Username}#{sender.Discriminator} ({sender.Id}) | Message ID: {messageId} | Original Message ID: {originalMsgId}")
.WithTimestamp(timestamp) .WithTimestamp(timestamp)
.Build(); .Build();
} }

View File

@ -6,7 +6,7 @@ using Serilog;
namespace PluralKit.Bot { namespace PluralKit.Bot {
public class ServerDefinition { public class ServerDefinition {
public ulong Id { get; set; } public ulong Id { get; set; }
public ulong? LogChannel { get; set; } public ulong? LogChannel { get; set; }
} }
public class LogChannelService { public class LogChannelService {
@ -23,11 +23,11 @@ namespace PluralKit.Bot {
_logger = logger.ForContext<LogChannelService>(); _logger = logger.ForContext<LogChannelService>();
} }
public async Task LogMessage(PKSystem system, PKMember member, ulong messageId, IGuildChannel originalChannel, IUser sender, string content) { public async Task LogMessage(PKSystem system, PKMember member, ulong messageId, ulong originalMsgId, IGuildChannel originalChannel, IUser sender, string content) {
var logChannel = await GetLogChannel(originalChannel.Guild); var logChannel = await GetLogChannel(originalChannel.Guild);
if (logChannel == null) return; if (logChannel == null) return;
var embed = _embed.CreateLoggedMessageEmbed(system, member, messageId, sender, content, originalChannel); var embed = _embed.CreateLoggedMessageEmbed(system, member, messageId, originalMsgId, sender, content, originalChannel);
var url = $"https://discordapp.com/channels/{originalChannel.GuildId}/{originalChannel.Id}/{messageId}"; var url = $"https://discordapp.com/channels/{originalChannel.GuildId}/{originalChannel.Id}/{messageId}";
await logChannel.SendMessageAsync(text: url, embed: embed); await logChannel.SendMessageAsync(text: url, embed: embed);
@ -56,7 +56,7 @@ namespace PluralKit.Bot {
"insert into servers (id, log_channel) values (@Id, @LogChannel) on conflict (id) do update set log_channel = @LogChannel", "insert into servers (id, log_channel) values (@Id, @LogChannel) on conflict (id) do update set log_channel = @LogChannel",
def); def);
} }
_logger.Information("Set guild {Guild} log channel to {Channel}", guild.Id, newLogChannel?.Id); _logger.Information("Set guild {Guild} log channel to {Channel}", guild.Id, newLogChannel?.Id);
} }
} }

View File

@ -39,7 +39,7 @@ namespace PluralKit.Bot
private ILogger _logger; private ILogger _logger;
private HttpClient _httpClient; private HttpClient _httpClient;
public ProxyService(IDiscordClient client, WebhookCacheService webhookCache, DbConnectionFactory conn, LogChannelService logChannel, MessageStore messageStorage, EmbedService embeds, IMetrics metrics, ILogger logger) public ProxyService(IDiscordClient client, WebhookCacheService webhookCache, DbConnectionFactory conn, LogChannelService logChannel, MessageStore messageStorage, EmbedService embeds, IMetrics metrics, ILogger logger)
{ {
_client = client; _client = client;
@ -50,7 +50,7 @@ namespace PluralKit.Bot
_embeds = embeds; _embeds = embeds;
_metrics = metrics; _metrics = metrics;
_logger = logger.ForContext<ProxyService>(); _logger = logger.ForContext<ProxyService>();
_httpClient = new HttpClient(); _httpClient = new HttpClient();
} }
@ -72,7 +72,7 @@ namespace PluralKit.Bot
foreach (var potential in ordered) foreach (var potential in ordered)
{ {
if (potential.Member.Prefix == null && potential.Member.Suffix == null) continue; if (potential.Member.Prefix == null && potential.Member.Suffix == null) continue;
var prefix = potential.Member.Prefix ?? ""; var prefix = potential.Member.Prefix ?? "";
var suffix = potential.Member.Suffix ?? ""; var suffix = potential.Member.Suffix ?? "";
@ -82,7 +82,7 @@ namespace PluralKit.Bot
return new ProxyMatch { Member = potential.Member, System = potential.System, InnerText = inner }; return new ProxyMatch { Member = potential.Member, System = potential.System, InnerText = inner };
} }
} }
return null; return null;
} }
@ -90,7 +90,7 @@ namespace PluralKit.Bot
{ {
// Bail early if this isn't in a guild channel // Bail early if this isn't in a guild channel
if (!(message.Channel is IGuildChannel)) return; if (!(message.Channel is IGuildChannel)) return;
IEnumerable<ProxyDatabaseResult> results; IEnumerable<ProxyDatabaseResult> results;
using (var conn = await _conn.Obtain()) using (var conn = await _conn.Obtain())
{ {
@ -103,11 +103,11 @@ namespace PluralKit.Bot
// Find a member with proxy tags matching the message // Find a member with proxy tags matching the message
var match = GetProxyTagMatch(message.Content, results); var match = GetProxyTagMatch(message.Content, results);
if (match == null) return; if (match == null) return;
// We know message.Channel can only be ITextChannel as PK doesn't work in DMs/groups // We know message.Channel can only be ITextChannel as PK doesn't work in DMs/groups
// Afterwards we ensure the bot has the right permissions, otherwise bail early // Afterwards we ensure the bot has the right permissions, otherwise bail early
if (!await EnsureBotPermissions(message.Channel as ITextChannel)) return; if (!await EnsureBotPermissions(message.Channel as ITextChannel)) return;
// Can't proxy a message with no content and no attachment // Can't proxy a message with no content and no attachment
if (match.InnerText.Trim().Length == 0 && message.Attachments.Count == 0) if (match.InnerText.Trim().Length == 0 && message.Attachments.Count == 0)
return; return;
@ -122,7 +122,7 @@ namespace PluralKit.Bot
// Store the message in the database, and log it in the log channel (if applicable) // Store the message in the database, and log it in the log channel (if applicable)
await _messageStorage.Store(message.Author.Id, hookMessageId, message.Channel.Id, message.Id, match.Member); await _messageStorage.Store(message.Author.Id, hookMessageId, message.Channel.Id, message.Id, match.Member);
await _logChannel.LogMessage(match.System, match.Member, hookMessageId, message.Channel as IGuildChannel, message.Author, match.InnerText); await _logChannel.LogMessage(match.System, match.Member, hookMessageId, message.Id, message.Channel as IGuildChannel, message.Author, match.InnerText);
// Wait a second or so before deleting the original message // Wait a second or so before deleting the original message
await Task.Delay(1000); await Task.Delay(1000);
@ -151,7 +151,7 @@ namespace PluralKit.Bot
$"{Emojis.Error} PluralKit does not have the *Manage Webhooks* permission in this channel, and thus cannot proxy messages. Please contact a server administrator to remedy this."); $"{Emojis.Error} PluralKit does not have the *Manage Webhooks* permission in this channel, and thus cannot proxy messages. Please contact a server administrator to remedy this.");
return false; return false;
} }
if (!permissions.ManageMessages) if (!permissions.ManageMessages)
{ {
await channel.SendMessageAsync( await channel.SendMessageAsync(
@ -165,7 +165,7 @@ namespace PluralKit.Bot
private async Task<ulong> ExecuteWebhook(IWebhook webhook, string text, string username, string avatarUrl, IAttachment attachment) private async Task<ulong> ExecuteWebhook(IWebhook webhook, string text, string username, string avatarUrl, IAttachment attachment)
{ {
username = FixClyde(username); username = FixClyde(username);
// TODO: DiscordWebhookClient's ctor does a call to GetWebhook that may be unnecessary, see if there's a way to do this The Hard Way :tm: // TODO: DiscordWebhookClient's ctor does a call to GetWebhook that may be unnecessary, see if there's a way to do this The Hard Way :tm:
// TODO: this will probably crash if there are multiple consecutive failures, perhaps have a loop instead? // TODO: this will probably crash if there are multiple consecutive failures, perhaps have a loop instead?
DiscordWebhookClient client; DiscordWebhookClient client;
@ -176,7 +176,7 @@ namespace PluralKit.Bot
catch (InvalidOperationException) catch (InvalidOperationException)
{ {
// TODO: does this leak internal stuff in the (now-invalid) client? // TODO: does this leak internal stuff in the (now-invalid) client?
// webhook was deleted or invalid // webhook was deleted or invalid
webhook = await _webhookCache.InvalidateAndRefreshWebhook(webhook); webhook = await _webhookCache.InvalidateAndRefreshWebhook(webhook);
client = new DiscordWebhookClient(webhook); client = new DiscordWebhookClient(webhook);
@ -217,7 +217,7 @@ namespace PluralKit.Bot
_metrics.Measure.Meter.Mark(BotMetrics.MessagesProxied, "failure"); _metrics.Measure.Meter.Mark(BotMetrics.MessagesProxied, "failure");
throw; throw;
} }
// TODO: figure out a way to return the full message object (without doing a GetMessageAsync call, which // TODO: figure out a way to return the full message object (without doing a GetMessageAsync call, which
// doesn't work if there's no permission to) // doesn't work if there's no permission to)
return messageId; return messageId;
@ -248,10 +248,10 @@ namespace PluralKit.Bot
// Find the message in the DB // Find the message in the DB
var msg = await _messageStorage.Get(message.Id); var msg = await _messageStorage.Get(message.Id);
if (msg == null) return; if (msg == null) return;
// DM them the message card // DM them the message card
await user.SendMessageAsync(embed: await _embeds.CreateMessageInfoEmbed(msg)); await user.SendMessageAsync(embed: await _embeds.CreateMessageInfoEmbed(msg));
// And finally remove the original reaction (if we can) // And finally remove the original reaction (if we can)
var msgObj = await message.GetOrDownloadAsync(); var msgObj = await message.GetOrDownloadAsync();
if (await msgObj.Channel.HasPermission(ChannelPermission.ManageMessages)) if (await msgObj.Channel.HasPermission(ChannelPermission.ManageMessages))
@ -295,7 +295,7 @@ namespace PluralKit.Bot
{ {
var match = Regex.Match(name, "clyde", RegexOptions.IgnoreCase); var match = Regex.Match(name, "clyde", RegexOptions.IgnoreCase);
if (!match.Success) return name; if (!match.Success) return name;
// Put a hair space (\u200A) between the "c" and the "lyde" in the match to avoid Discord matching it // Put a hair space (\u200A) between the "c" and the "lyde" in the match to avoid Discord matching it
// since Discord blocks webhooks containing the word "Clyde"... for some reason. /shrug // since Discord blocks webhooks containing the word "Clyde"... for some reason. /shrug
return name.Substring(0, match.Index + 1) + '\u200A' + name.Substring(match.Index + 1); return name.Substring(0, match.Index + 1) + '\u200A' + name.Substring(match.Index + 1);