From 11ac7418c6c40e8b2da2ba67bf892103eda20d00 Mon Sep 17 00:00:00 2001 From: Noi Date: Sat, 22 Oct 2022 17:39:11 -0700 Subject: [PATCH 1/9] Fix unexpected error message on nonexistent user --- Modules/ModCommands/Commands/NoteWarn.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/ModCommands/Commands/NoteWarn.cs b/Modules/ModCommands/Commands/NoteWarn.cs index 4b820f1..e809a94 100644 --- a/Modules/ModCommands/Commands/NoteWarn.cs +++ b/Modules/ModCommands/Commands/NoteWarn.cs @@ -65,10 +65,10 @@ abstract class NoteWarn : CommandConfig { var targetUser = g.GetUser(targetId); // Go to specific action - try { + if (targetUser == null) { + await msg.Channel.SendMessageAsync(":x: Unable to find the specified user."); + } else { await ContinueInvoke(g, msg, logMessage, targetUser); - } catch (Discord.Net.HttpException ex) when (ex.HttpCode == System.Net.HttpStatusCode.Forbidden) { - await msg.Channel.SendMessageAsync(":x: " + Messages.ForbiddenGenericError); } } From 9d04d22a713332db1b2ebf76b3aa1dc3577ec86b Mon Sep 17 00:00:00 2001 From: Noi Date: Sat, 22 Oct 2022 17:47:23 -0700 Subject: [PATCH 2/9] Nullable incoming module config --- Modules/AutoResponder/AutoResponder.cs | 2 +- Modules/EntryRole/EntryRole.cs | 2 +- Modules/ModCommands/ModCommands.cs | 2 +- Modules/ModLogs/ModLogs.cs | 2 +- Modules/PendingOutRole/PendingOutRole.cs | 2 +- Modules/RegexModerator/RegexModerator.cs | 2 +- Modules/VoiceRoleSync/VoiceRoleSync.cs | 2 +- RegexbotModule.cs | 2 +- Services/ModuleState/ModuleStateService.cs | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Modules/AutoResponder/AutoResponder.cs b/Modules/AutoResponder/AutoResponder.cs index 96a8d58..64b5d70 100644 --- a/Modules/AutoResponder/AutoResponder.cs +++ b/Modules/AutoResponder/AutoResponder.cs @@ -12,7 +12,7 @@ internal class AutoResponder : RegexbotModule { DiscordClient.MessageReceived += DiscordClient_MessageReceived; } - public override Task CreateGuildStateAsync(ulong guildID, JToken config) { + public override Task CreateGuildStateAsync(ulong guildID, JToken? config) { if (config == null) return Task.FromResult(null); var defs = new List(); diff --git a/Modules/EntryRole/EntryRole.cs b/Modules/EntryRole/EntryRole.cs index 0042099..74b4440 100644 --- a/Modules/EntryRole/EntryRole.cs +++ b/Modules/EntryRole/EntryRole.cs @@ -52,7 +52,7 @@ internal sealed class EntryRole : RegexbotModule, IDisposable { return Task.CompletedTask; } - public override Task CreateGuildStateAsync(ulong guildID, JToken config) { + public override Task CreateGuildStateAsync(ulong guildID, JToken? config) { if (config == null) return Task.FromResult(null); if (config.Type != JTokenType.Object) diff --git a/Modules/ModCommands/ModCommands.cs b/Modules/ModCommands/ModCommands.cs index d9575ce..25cb3cf 100644 --- a/Modules/ModCommands/ModCommands.cs +++ b/Modules/ModCommands/ModCommands.cs @@ -15,7 +15,7 @@ internal class ModCommands : RegexbotModule { } } - public override Task CreateGuildStateAsync(ulong guildID, JToken config) { + public override Task CreateGuildStateAsync(ulong guildID, JToken? config) { if (config == null) return Task.FromResult(null); var conf = new ModuleConfig(this, config); diff --git a/Modules/ModLogs/ModLogs.cs b/Modules/ModLogs/ModLogs.cs index 5eb3a0d..7c3d5eb 100644 --- a/Modules/ModLogs/ModLogs.cs +++ b/Modules/ModLogs/ModLogs.cs @@ -15,7 +15,7 @@ internal partial class ModLogs : RegexbotModule { bot.SharedEventReceived += HandleReceivedSharedEvent; } - public override Task CreateGuildStateAsync(ulong guildID, JToken config) { + public override Task CreateGuildStateAsync(ulong guildID, JToken? config) { if (config == null) return Task.FromResult(null); if (config.Type != JTokenType.Object) throw new ModuleLoadException("Configuration for this section is invalid."); diff --git a/Modules/PendingOutRole/PendingOutRole.cs b/Modules/PendingOutRole/PendingOutRole.cs index f02db71..f2b019f 100644 --- a/Modules/PendingOutRole/PendingOutRole.cs +++ b/Modules/PendingOutRole/PendingOutRole.cs @@ -41,7 +41,7 @@ internal class PendingOutRole : RegexbotModule { } } - public override Task CreateGuildStateAsync(ulong guildID, JToken config) { + public override Task CreateGuildStateAsync(ulong guildID, JToken? config) { if (config == null) return Task.FromResult(null); if (config.Type != JTokenType.Object) throw new ModuleLoadException("Configuration for this section is invalid."); diff --git a/Modules/RegexModerator/RegexModerator.cs b/Modules/RegexModerator/RegexModerator.cs index 7239390..24de7d8 100644 --- a/Modules/RegexModerator/RegexModerator.cs +++ b/Modules/RegexModerator/RegexModerator.cs @@ -12,7 +12,7 @@ internal class RegexModerator : RegexbotModule { DiscordClient.MessageUpdated += DiscordClient_MessageUpdated; } - public override Task CreateGuildStateAsync(ulong guildID, JToken config) { + public override Task CreateGuildStateAsync(ulong guildID, JToken? config) { if (config == null) return Task.FromResult(null); var defs = new List(); diff --git a/Modules/VoiceRoleSync/VoiceRoleSync.cs b/Modules/VoiceRoleSync/VoiceRoleSync.cs index b7c675f..196573f 100644 --- a/Modules/VoiceRoleSync/VoiceRoleSync.cs +++ b/Modules/VoiceRoleSync/VoiceRoleSync.cs @@ -43,7 +43,7 @@ internal class VoiceRoleSync : RegexbotModule { } } - public override Task CreateGuildStateAsync(ulong guildID, JToken config) { + public override Task CreateGuildStateAsync(ulong guildID, JToken? config) { if (config == null) return Task.FromResult(null); if (config.Type != JTokenType.Object) throw new ModuleLoadException("Configuration for this section is invalid."); diff --git a/RegexbotModule.cs b/RegexbotModule.cs index 033817b..ca84ada 100644 --- a/RegexbotModule.cs +++ b/RegexbotModule.cs @@ -43,7 +43,7 @@ public abstract class RegexbotModule { /// /// An object instance containing state and/or configuration information for the guild currently being processed. /// - public abstract Task CreateGuildStateAsync(ulong guildID, JToken config); + public abstract Task CreateGuildStateAsync(ulong guildID, JToken? config); /// /// Retrieves the state object that corresponds with the given guild. diff --git a/Services/ModuleState/ModuleStateService.cs b/Services/ModuleState/ModuleStateService.cs index e2592f6..ecaf395 100644 --- a/Services/ModuleState/ModuleStateService.cs +++ b/Services/ModuleState/ModuleStateService.cs @@ -76,7 +76,7 @@ class ModuleStateService : Service { foreach (var module in BotClient.Modules) { var t = module.GetType(); try { - var state = await module.CreateGuildStateAsync(guild.Id, guildConf[module.Name]!); + var state = await module.CreateGuildStateAsync(guild.Id, guildConf[module.Name]); newStates.Add(t, state); } catch (ModuleLoadException ex) { Log($"{module.Name} failed to read configuration for {guild.Name}: {ex.Message}"); From 36c050afc8e54e001d7acd60e876c21859311c64 Mon Sep 17 00:00:00 2001 From: Noi Date: Fri, 2 Dec 2022 20:06:51 -0800 Subject: [PATCH 3/9] Move message ID from context to footer --- Modules/ModLogs/ModLogs.cs | 1 + Modules/ModLogs/ModLogs_Messages.cs | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/ModLogs/ModLogs.cs b/Modules/ModLogs/ModLogs.cs index 7c3d5eb..b5f1906 100644 --- a/Modules/ModLogs/ModLogs.cs +++ b/Modules/ModLogs/ModLogs.cs @@ -8,6 +8,7 @@ namespace RegexBot.Modules.ModLogs; [RegexbotModule] internal partial class ModLogs : RegexbotModule { // TODO consider resurrecting 2.x idea of logging actions to db, making it searchable? + // TODO more robust channel filtering. define channels in config array, add check to it out here. public ModLogs(RegexbotClient bot) : base(bot) { // TODO missing logging features: joins, leaves, user edits (nick/username/discr) diff --git a/Modules/ModLogs/ModLogs_Messages.cs b/Modules/ModLogs/ModLogs_Messages.cs index 1c07284..70e9e1a 100644 --- a/Modules/ModLogs/ModLogs_Messages.cs +++ b/Modules/ModLogs/ModLogs_Messages.cs @@ -31,7 +31,7 @@ internal partial class ModLogs { var reportEmbed = new EmbedBuilder() .WithTitle("Message deleted") .WithCurrentTimestamp() - .WithFooter($"User ID: {(cachedMsg == null ? "Unknown" : cachedMsg.AuthorId)}"); + .WithFooter($"Message ID: {argMsg.Id}"); if (cachedMsg != null) { if (cachedMsg.Content == null) { @@ -80,7 +80,7 @@ internal partial class ModLogs { var reportEmbed = new EmbedBuilder() .WithTitle("Message edited") .WithCurrentTimestamp() - .WithFooter($"User ID: {newMsg.Author.Id}"); + .WithFooter($"Message ID: {newMsg.Id}"); reportEmbed.Author = new EmbedAuthorBuilder() { Name = $"{newMsg.Author.Username}#{newMsg.Author.Discriminator}", @@ -138,7 +138,6 @@ internal partial class ModLogs { contextStr.AppendLine($"User: {userDisplay}"); contextStr.AppendLine($"Channel: <#{channel.Id}> (#{channel.Name})"); contextStr.AppendLine(editLine); - contextStr.AppendLine($"Message ID: {msgId}"); e.AddField(new EmbedFieldBuilder() { Name = "Context", From 6bdf528c666bf4f112ea3222d56ea0c8b338a568 Mon Sep 17 00:00:00 2001 From: Noi Date: Fri, 2 Dec 2022 20:28:23 -0800 Subject: [PATCH 4/9] Replace RemovalType with bool In general: `RemovalType.Ban` was replaced with `true` and `RemovalType.Kick` with `false`. `RemovalType.None` was never used. --- Modules/RegexModerator/ResponseExecutor.cs | 8 +++---- Services/CommonFunctions/BanKickResult.cs | 21 ++++++++++++------- Services/CommonFunctions/CF_Removals.Hooks.cs | 8 +++---- Services/CommonFunctions/CF_Removals.cs | 21 +++++++++---------- Services/CommonFunctions/RemovalType.cs | 21 ------------------- 5 files changed, 32 insertions(+), 47 deletions(-) delete mode 100644 Services/CommonFunctions/RemovalType.cs diff --git a/Modules/RegexModerator/ResponseExecutor.cs b/Modules/RegexModerator/ResponseExecutor.cs index e7fba21..3124549 100644 --- a/Modules/RegexModerator/ResponseExecutor.cs +++ b/Modules/RegexModerator/ResponseExecutor.cs @@ -135,11 +135,11 @@ class ResponseExecutor { #region Response delegates private static Task CmdComment(string? parameter) => Task.FromResult(FromSuccess(parameter)); - private Task CmdBan(string? parameter) => CmdBanKick(RemovalType.Ban, parameter); - private Task CmdKick(string? parameter) => CmdBanKick(RemovalType.Kick, parameter); - private async Task CmdBanKick(RemovalType rt, string? parameter) { + private Task CmdBan(string? parameter) => CmdBanKick(true, parameter); + private Task CmdKick(string? parameter) => CmdBanKick(false, parameter); + private async Task CmdBanKick(bool isBan, string? parameter) { BanKickResult result; - if (rt == RemovalType.Ban) { + if (isBan) { result = await _bot.BanAsync(_guild, LogSource, _user.Id, _rule.BanPurgeDays, parameter, _rule.NotifyUser); } else { diff --git a/Services/CommonFunctions/BanKickResult.cs b/Services/CommonFunctions/BanKickResult.cs index 1021179..ac8d574 100644 --- a/Services/CommonFunctions/BanKickResult.cs +++ b/Services/CommonFunctions/BanKickResult.cs @@ -7,7 +7,6 @@ namespace RegexBot; /// public class BanKickResult { private readonly bool _userNotFound; // possible to receive this error by means other than exception - private readonly RemovalType _rptRemovalType; private readonly ulong _rptTargetId; /// @@ -59,12 +58,22 @@ public class BanKickResult { /// public bool MessageSendSuccess { get; } + /// + /// Gets a value indicating if this result represents a ban. + /// + public bool IsBan { get; } + + /// + /// Gets a value indicating if this result represents a kick. + /// + public bool IsKick { get => !IsBan; } + internal BanKickResult(HttpException? error, bool notificationSuccess, bool errorNotFound, - RemovalType rtype, ulong rtarget) { + bool isBan, ulong rtarget) { OperationError = error; MessageSendSuccess = notificationSuccess; _userNotFound = errorNotFound; - _rptRemovalType = rtype; + IsBan = isBan; _rptTargetId = rtarget; } @@ -78,14 +87,12 @@ public class BanKickResult { if (OperationSuccess) msg = ":white_check_mark: "; else msg = ":x: Failed to "; - if (_rptRemovalType == RemovalType.Ban) { + if (IsBan) { if (OperationSuccess) msg += "Banned"; else msg += "ban"; - } else if (_rptRemovalType == RemovalType.Kick) { + } else { if (OperationSuccess) msg += "Kicked"; else msg += "kick"; - } else { - throw new InvalidOperationException("Cannot create a message for removal type of None."); } if (_rptTargetId != 0) { diff --git a/Services/CommonFunctions/CF_Removals.Hooks.cs b/Services/CommonFunctions/CF_Removals.Hooks.cs index bb62344..c8d97f0 100644 --- a/Services/CommonFunctions/CF_Removals.Hooks.cs +++ b/Services/CommonFunctions/CF_Removals.Hooks.cs @@ -18,7 +18,7 @@ partial class RegexbotClient { int purgeDays, string? reason, bool sendDMToTarget) - => _svcCommonFunctions.BanOrKickAsync(RemovalType.Ban, guild, source, targetUser, purgeDays, reason, sendDMToTarget); + => _svcCommonFunctions.BanOrKickAsync(true, guild, source, targetUser, purgeDays, reason, sendDMToTarget); /// /// Similar to , but making use of an @@ -37,7 +37,7 @@ partial class RegexbotClient { string? reason, bool sendDMToTarget) { var result = EcQueryGuildUser(guild.Id, targetSearch); - if (result == null) return new BanKickResult(null, false, true, RemovalType.Ban, 0); + if (result == null) return new BanKickResult(null, false, true, true, 0); return await BanAsync(guild, source, (ulong)result.UserId, purgeDays, reason, sendDMToTarget); } @@ -60,7 +60,7 @@ partial class RegexbotClient { ulong targetUser, string? reason, bool sendDMToTarget) - => _svcCommonFunctions.BanOrKickAsync(RemovalType.Kick, guild, source, targetUser, default, reason, sendDMToTarget); + => _svcCommonFunctions.BanOrKickAsync(false, guild, source, targetUser, default, reason, sendDMToTarget); /// /// Similar to , but making use of an @@ -80,7 +80,7 @@ partial class RegexbotClient { string? reason, bool sendDMToTarget) { var result = EcQueryGuildUser(guild.Id, targetSearch); - if (result == null) return new BanKickResult(null, false, true, RemovalType.Kick, 0); + if (result == null) return new BanKickResult(null, false, true, false, 0); return await KickAsync(guild, source, (ulong)result.UserId, reason, sendDMToTarget); } } diff --git a/Services/CommonFunctions/CF_Removals.cs b/Services/CommonFunctions/CF_Removals.cs index e543203..941b4cf 100644 --- a/Services/CommonFunctions/CF_Removals.cs +++ b/Services/CommonFunctions/CF_Removals.cs @@ -4,42 +4,41 @@ using Discord.Net; namespace RegexBot.Services.CommonFunctions; internal partial class CommonFunctionsService : Service { // Hooked (indirectly) - internal async Task BanOrKickAsync(RemovalType t, SocketGuild guild, string source, ulong target, + internal async Task BanOrKickAsync(bool isBan, SocketGuild guild, string source, ulong target, int banPurgeDays, string? logReason, bool sendDmToTarget) { - if (t == RemovalType.None) throw new ArgumentException("Removal type must be 'ban' or 'kick'."); var dmSuccess = true; SocketGuildUser utarget = guild.GetUser(target); // Can't kick without obtaining user object. Quit here. - if (t == RemovalType.Kick && utarget == null) return new BanKickResult(null, false, true, RemovalType.Kick, 0); + if (isBan == false && utarget == null) return new BanKickResult(null, false, true, false, 0); // Send DM notification // Must be done before removal, or we risk not being able to send a notification afterwards if (sendDmToTarget) { - if (utarget != null) dmSuccess = await BanKickSendNotificationAsync(utarget, t, logReason); + if (utarget != null) dmSuccess = await BanKickSendNotificationAsync(utarget, isBan, logReason); else dmSuccess = false; } // Perform the action var auditReason = $"(By: {source}) {logReason}"; try { - if (t == RemovalType.Ban) await guild.AddBanAsync(target, banPurgeDays, auditReason); + if (isBan) await guild.AddBanAsync(target, banPurgeDays, auditReason); else await utarget!.KickAsync(auditReason); } catch (HttpException ex) { - return new BanKickResult(ex, dmSuccess, false, t, target); + return new BanKickResult(ex, dmSuccess, false, isBan, target); } - ModLogsProcessRemoval(guild.Id, target, t == RemovalType.Ban ? ModLogType.Ban : ModLogType.Kick, source, logReason); + ModLogsProcessRemoval(guild.Id, target, isBan ? ModLogType.Ban : ModLogType.Kick, source, logReason); - return new BanKickResult(null, dmSuccess, false, t, target); + return new BanKickResult(null, dmSuccess, false, isBan, target); } - private async Task BanKickSendNotificationAsync(SocketGuildUser target, RemovalType action, string? reason) { + private async Task BanKickSendNotificationAsync(SocketGuildUser target, bool isBan, string? reason) { const string DMTemplate = "You have been {0} from {1}"; const string DMTemplateReason = " for the following reason:\n{2}"; var outMessage = string.IsNullOrWhiteSpace(reason) - ? string.Format(DMTemplate + ".", action == RemovalType.Ban ? "banned" : "kicked", target.Guild.Name) - : string.Format(DMTemplate + DMTemplateReason, action == RemovalType.Ban ? "banned" : "kicked", target.Guild.Name, reason); + ? string.Format(DMTemplate + ".", isBan ? "banned" : "kicked", target.Guild.Name) + : string.Format(DMTemplate + DMTemplateReason, isBan ? "banned" : "kicked", target.Guild.Name, reason); var dch = await target.CreateDMChannelAsync(); try { await dch.SendMessageAsync(outMessage); } catch (HttpException) { return false; } diff --git a/Services/CommonFunctions/RemovalType.cs b/Services/CommonFunctions/RemovalType.cs deleted file mode 100644 index 750054c..0000000 --- a/Services/CommonFunctions/RemovalType.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace RegexBot; -/// -/// Specifies possible outcomes for the removal of a user from a guild. -/// -// Despite specific to CommonFunctionsService, this enum is meant to be visible by modules too, -// thus it is placed within the root namespace. -// TODO Tends to be unused except internally. Look into removing. -public enum RemovalType { - /// - /// Default value. Not used in any actual circumstances. - /// - None, - /// - /// Specifies that the type of removal includes placing the user on the guild's ban list. - /// - Ban, - /// - /// Specifies that the user is removed from the server via kick. - /// - Kick -} From a707792fe4cc941bedea679dfe4f133f2b16db7f Mon Sep 17 00:00:00 2001 From: Noi Date: Sat, 3 Dec 2022 17:18:48 -0800 Subject: [PATCH 5/9] Add color codes to logging embeds --- Common/Utilities.cs | 30 ------------------------- Modules/ModLogs/ModLogs_Logging.cs | 35 ++++++++++++++++++++++++++++- Modules/ModLogs/ModLogs_Messages.cs | 8 ++++--- 3 files changed, 39 insertions(+), 34 deletions(-) diff --git a/Common/Utilities.cs b/Common/Utilities.cs index ee2a4fc..4ffe0b9 100644 --- a/Common/Utilities.cs +++ b/Common/Utilities.cs @@ -66,36 +66,6 @@ public static class Utilities { return results; } - /// - /// Builds and returns an embed which displays this log entry. - /// - public static Embed BuildEmbed(this Data.ModLogEntry entry, RegexbotClient bot) { - var issuedDisplay = TryFromEntityNameString(entry.IssuedBy, bot); - string targetDisplay; - var targetq = bot.EcQueryUser(entry.UserId.ToString()); - if (targetq != null) targetDisplay = $"<@{targetq.UserId}> - {targetq.Username}#{targetq.Discriminator} `{targetq.UserId}`"; - else targetDisplay = $"User with ID `{entry.UserId}`"; - - var logEmbed = new EmbedBuilder() - .WithTitle(Enum.GetName(typeof(ModLogType), entry.LogType) + " logged:") - .WithTimestamp(entry.Timestamp) - .WithFooter($"Log #{entry.LogId}", bot.DiscordClient.CurrentUser.GetAvatarUrl()); // Escaping '#' not necessary here - if (entry.Message != null) { - logEmbed.Description = entry.Message; - } - - var contextStr = new StringBuilder(); - contextStr.AppendLine($"User: {targetDisplay}"); - contextStr.AppendLine($"Logged by: {issuedDisplay}"); - - logEmbed.AddField(new EmbedFieldBuilder() { - Name = "Context", - Value = contextStr.ToString() - }); - - return logEmbed.Build(); - } - /// /// Returns a representation of this entity that can be parsed by the constructor. /// diff --git a/Modules/ModLogs/ModLogs_Logging.cs b/Modules/ModLogs/ModLogs_Logging.cs index 147078a..cd9a2dd 100644 --- a/Modules/ModLogs/ModLogs_Logging.cs +++ b/Modules/ModLogs/ModLogs_Logging.cs @@ -1,5 +1,7 @@ +using Discord; using RegexBot.Common; using RegexBot.Data; +using System.Text; namespace RegexBot.Modules.ModLogs; // Contains all logic relating to reporting new database mod log entries @@ -12,6 +14,37 @@ internal partial class ModLogs { var reportChannel = conf?.ReportingChannel?.FindChannelIn(guild, true); if (reportChannel == null) return; - await reportChannel.SendMessageAsync(embed: entry.BuildEmbed(Bot)); + await reportChannel.SendMessageAsync(embed: BuildLogEmbed(entry)); + } + + /// + /// Builds and returns an embed which displays this log entry. + /// + private Embed BuildLogEmbed(ModLogEntry entry) { + var issuedDisplay = Utilities.TryFromEntityNameString(entry.IssuedBy, bot); + string targetDisplay; + var targetq = Bot.EcQueryUser(entry.UserId.ToString()); + if (targetq != null) targetDisplay = $"<@{targetq.UserId}> - {targetq.Username}#{targetq.Discriminator} `{targetq.UserId}`"; + else targetDisplay = $"User with ID `{entry.UserId}`"; + + var logEmbed = new EmbedBuilder() + .WithColor(Color.DarkGrey) + .WithTitle(Enum.GetName(typeof(ModLogType), entry.LogType) + " logged:") + .WithTimestamp(entry.Timestamp) + .WithFooter($"Log #{entry.LogId}", Bot.DiscordClient.CurrentUser.GetAvatarUrl()); // Escaping '#' not necessary here + if (entry.Message != null) { + logEmbed.Description = entry.Message; + } + + var contextStr = new StringBuilder(); + contextStr.AppendLine($"User: {targetDisplay}"); + contextStr.AppendLine($"Logged by: {issuedDisplay}"); + + logEmbed.AddField(new EmbedFieldBuilder() { + Name = "Context", + Value = contextStr.ToString() + }); + + return logEmbed.Build(); } } \ No newline at end of file diff --git a/Modules/ModLogs/ModLogs_Messages.cs b/Modules/ModLogs/ModLogs_Messages.cs index 70e9e1a..c6859e2 100644 --- a/Modules/ModLogs/ModLogs_Messages.cs +++ b/Modules/ModLogs/ModLogs_Messages.cs @@ -29,6 +29,7 @@ internal partial class ModLogs { .SingleOrDefault(); var reportEmbed = new EmbedBuilder() + .WithColor(Color.Red) .WithTitle("Message deleted") .WithCurrentTimestamp() .WithFooter($"Message ID: {argMsg.Id}"); @@ -60,7 +61,7 @@ internal partial class ModLogs { var editLine = $"Posted: {MakeTimestamp(SnowflakeUtils.FromSnowflake(argMsg.Id))}"; if (cachedMsg?.EditedAt != null) editLine += $"\nLast edit: {MakeTimestamp(cachedMsg.EditedAt.Value)}"; - SetContextField(reportEmbed, (ulong?)cachedMsg?.AuthorId, channel, editLine, argMsg.Id); + SetContextField(reportEmbed, (ulong?)cachedMsg?.AuthorId, channel, editLine); await reportChannel.SendMessageAsync(embed: reportEmbed.Build()); } @@ -78,6 +79,7 @@ internal partial class ModLogs { } var reportEmbed = new EmbedBuilder() + .WithColor(new Color(0xffff00)) // yellow .WithTitle("Message edited") .WithCurrentTimestamp() .WithFooter($"Message ID: {newMsg.Id}"); @@ -119,12 +121,12 @@ internal partial class ModLogs { string editLine; if ((oldMsg?.EditedAt) == null) editLine = $"Posted: {MakeTimestamp(SnowflakeUtils.FromSnowflake(newMsg.Id))}"; else editLine = $"Previous edit: {MakeTimestamp(oldMsg.EditedAt.Value)}"; - SetContextField(reportEmbed, newMsg.Author.Id, channel, editLine, newMsg.Id); + SetContextField(reportEmbed, newMsg.Author.Id, channel, editLine); await reportChannel.SendMessageAsync(embed: reportEmbed.Build()); } - private void SetContextField(EmbedBuilder e, ulong? userId, SocketTextChannel channel, string editLine, ulong msgId) { + private void SetContextField(EmbedBuilder e, ulong? userId, SocketTextChannel channel, string editLine) { string userDisplay; if (userId.HasValue) { var q = Bot.EcQueryUser(userId.Value.ToString()); From 12f8359b909f897a0b80ea7c8fa52e5a4111fbf8 Mon Sep 17 00:00:00 2001 From: Noi Date: Sat, 3 Dec 2022 17:21:20 -0800 Subject: [PATCH 6/9] Move member cache updating off main thread --- Services/EntityCache/UserCachingSubservice.cs | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/Services/EntityCache/UserCachingSubservice.cs b/Services/EntityCache/UserCachingSubservice.cs index 292ec19..e7c5c2f 100644 --- a/Services/EntityCache/UserCachingSubservice.cs +++ b/Services/EntityCache/UserCachingSubservice.cs @@ -18,15 +18,22 @@ class UserCachingSubservice { bot.DiscordClient.GuildMemberUpdated += DiscordClient_GuildMemberUpdated; bot.DiscordClient.UserUpdated += DiscordClient_UserUpdated; } - private async Task DiscordClient_GuildMembersDownloaded(SocketGuild arg) { - _log($"{arg.Name}: Full member list obtained. Cache update in progress."); - using var db = new BotDatabaseContext(); - foreach (var user in arg.Users) { - UpdateUser(user, db); - UpdateGuildUser(user, db); - } - var changes = await db.SaveChangesAsync(); - _log($"{arg.Name}: Member caches updated ({changes} database writes)."); + private Task DiscordClient_GuildMembersDownloaded(SocketGuild arg) { + var userlist = arg.Users.ToList(); + _ = Task.Run(async () => { + try { + using var db = new BotDatabaseContext(); + foreach (var user in userlist) { + UpdateUser(user, db); + UpdateGuildUser(user, db); + } + var changes = await db.SaveChangesAsync(); + _log($"{arg.Name}: Member caches updated ({changes} database writes)."); + } catch (Exception ex) { + _log($"{arg.Name}: {ex}"); + } + }); + return Task.CompletedTask; } private async Task DiscordClient_GuildMemberUpdated(Discord.Cacheable old, SocketGuildUser current) { From fc8826b37f3554fc9572fd31b243f1fe7f435601 Mon Sep 17 00:00:00 2001 From: Noi Date: Sat, 3 Dec 2022 17:21:42 -0800 Subject: [PATCH 7/9] Also cache bot messages --- Services/EntityCache/MessageCachingSubservice.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Services/EntityCache/MessageCachingSubservice.cs b/Services/EntityCache/MessageCachingSubservice.cs index 6f4f894..8346da6 100644 --- a/Services/EntityCache/MessageCachingSubservice.cs +++ b/Services/EntityCache/MessageCachingSubservice.cs @@ -21,7 +21,11 @@ class MessageCachingSubservice { } private async Task AddOrUpdateCacheItemAsync(SocketMessage arg, bool isUpdate) { - if (!Common.Utilities.IsValidUserMessage(arg, out _)) return; + //if (!Common.Utilities.IsValidUserMessage(arg, out _)) return; + if (arg.Channel is not SocketTextChannel) return; + if (arg.Author.IsWebhook) return; // do get bot messages, don't get webhooks + if (((IMessage)arg).Type != MessageType.Default) return; + if (arg is SocketSystemMessage) return; using var db = new BotDatabaseContext(); CachedGuildMessage? cachedMsg = db.GuildMessageCache.Where(m => m.MessageId == (long)arg.Id).SingleOrDefault(); From 55453cf7957be8e0a6b41ebba42e39e5f176dc94 Mon Sep 17 00:00:00 2001 From: Noi Date: Sat, 3 Dec 2022 17:28:59 -0800 Subject: [PATCH 8/9] Bump version --- RegexBot.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RegexBot.csproj b/RegexBot.csproj index 8d25f46..44d59b5 100644 --- a/RegexBot.csproj +++ b/RegexBot.csproj @@ -5,7 +5,7 @@ net6.0 NoiTheCat Advanced and flexible Discord moderation bot. - 3.1.0 + 3.1.1 enable enable True @@ -29,7 +29,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + From 8b5f0e83c45184fadae0136dd7b68c2c8253f6d6 Mon Sep 17 00:00:00 2001 From: Noi Date: Sat, 3 Dec 2022 17:35:34 -0800 Subject: [PATCH 9/9] oops --- Modules/ModLogs/ModLogs_Logging.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/ModLogs/ModLogs_Logging.cs b/Modules/ModLogs/ModLogs_Logging.cs index cd9a2dd..45add4d 100644 --- a/Modules/ModLogs/ModLogs_Logging.cs +++ b/Modules/ModLogs/ModLogs_Logging.cs @@ -21,7 +21,7 @@ internal partial class ModLogs { /// Builds and returns an embed which displays this log entry. /// private Embed BuildLogEmbed(ModLogEntry entry) { - var issuedDisplay = Utilities.TryFromEntityNameString(entry.IssuedBy, bot); + var issuedDisplay = Utilities.TryFromEntityNameString(entry.IssuedBy, Bot); string targetDisplay; var targetq = Bot.EcQueryUser(entry.UserId.ToString()); if (targetq != null) targetDisplay = $"<@{targetq.UserId}> - {targetq.Username}#{targetq.Discriminator} `{targetq.UserId}`";