From 986d9e4ff3b27d1b423bc7d3b85ed57ee6c67bce Mon Sep 17 00:00:00 2001 From: Noi Date: Sat, 8 Jun 2024 21:08:03 -0700 Subject: [PATCH] Implement suggestions; minor command refactoring --- Modules/ModCommands/Commands/BanKick.cs | 6 ++--- Modules/ModCommands/Commands/CommandConfig.cs | 26 ++++++++++++------- Modules/ModCommands/Commands/ConfReload.cs | 5 +--- Modules/ModCommands/Commands/NoteWarn.cs | 10 +++---- .../ModCommands/Commands/RoleManipulation.cs | 8 +++--- Modules/ModCommands/Commands/Say.cs | 4 +-- Modules/ModCommands/Commands/ShowModLogs.cs | 7 +++-- Modules/ModCommands/Commands/Timeout.cs | 2 +- Modules/ModCommands/Commands/Unban.cs | 2 +- Modules/ModCommands/Commands/Untimeout.cs | 2 +- Modules/PendingOutRole/ModuleConfig.cs | 1 - 11 files changed, 33 insertions(+), 40 deletions(-) diff --git a/Modules/ModCommands/Commands/BanKick.cs b/Modules/ModCommands/Commands/BanKick.cs index 2f44bef..0732f8b 100644 --- a/Modules/ModCommands/Commands/BanKick.cs +++ b/Modules/ModCommands/Commands/BanKick.cs @@ -22,9 +22,7 @@ class Ban : BanKick { } } -class Kick : BanKick { - public Kick(ModCommands module, JObject config) : base(module, config, false) { } - +class Kick(ModCommands module, JObject config) : BanKick(module, config, false) { protected override async Task ContinueInvoke(SocketGuild g, SocketMessage msg, string? reason, ulong targetId, CachedGuildUser? targetQuery, SocketUser? targetUser) { // Kick: Unlike ban, must find the guild user in order to proceed @@ -76,7 +74,7 @@ abstract class BanKick : CommandConfig { // Usage: (command) (user) (reason) public override async Task Invoke(SocketGuild g, SocketMessage msg) { - var line = msg.Content.Split(new char[] { ' ' }, 3, StringSplitOptions.RemoveEmptyEntries); + var line = SplitToParams(msg, 3); string targetstr; string? reason; if (line.Length < 2) { diff --git a/Modules/ModCommands/Commands/CommandConfig.cs b/Modules/ModCommands/Commands/CommandConfig.cs index bda304c..82629c3 100644 --- a/Modules/ModCommands/Commands/CommandConfig.cs +++ b/Modules/ModCommands/Commands/CommandConfig.cs @@ -3,16 +3,10 @@ using System.Diagnostics; namespace RegexBot.Modules.ModCommands.Commands; [DebuggerDisplay("Command definition '{Label}'")] -abstract class CommandConfig { - public string Label { get; } - public string Command { get; } - protected ModCommands Module { get; } - - protected CommandConfig(ModCommands module, JObject config) { - Module = module; - Label = config[nameof(Label)]!.Value()!; - Command = config[nameof(Command)]!.Value()!; - } +abstract class CommandConfig(ModCommands module, JObject config) { + public string Label { get; } = config[nameof(Label)]!.Value()!; + public string Command { get; } = config[nameof(Command)]!.Value()!; + protected ModCommands Module { get; } = module; public abstract Task Invoke(SocketGuild g, SocketMessage msg); @@ -20,6 +14,7 @@ abstract class CommandConfig { protected const string TargetNotFound = ":x: **Unable to find the given user.**"; protected abstract string DefaultUsageMsg { get; } + /// /// Sends out the default usage message () within an embed. /// An optional message can be included, for uses such as notifying users of incorrect usage. @@ -36,4 +31,15 @@ abstract class CommandConfig { }; await target.SendMessageAsync(message ?? "", embed: usageEmbed.Build()); } + + internal static readonly char[] separator = [' ']; + /// + /// For the given message's content, assumes its message is a command and returns its parameters + /// as an array of substrings. + /// + /// The incoming message to process. + /// The number of parameters to expect. + /// A string array with 0 to maxParams - 1 elements. + protected static string[] SplitToParams(SocketMessage msg, int maxParams) + => msg.Content.Split(separator, maxParams, StringSplitOptions.RemoveEmptyEntries); } diff --git a/Modules/ModCommands/Commands/ConfReload.cs b/Modules/ModCommands/Commands/ConfReload.cs index fadbd06..5e76927 100644 --- a/Modules/ModCommands/Commands/ConfReload.cs +++ b/Modules/ModCommands/Commands/ConfReload.cs @@ -1,10 +1,7 @@ namespace RegexBot.Modules.ModCommands.Commands; -class ConfReload : CommandConfig { +class ConfReload(ModCommands module, JObject config) : CommandConfig(module, config) { protected override string DefaultUsageMsg => null!; - // No configuration. - public ConfReload(ModCommands module, JObject config) : base(module, config) { } - // Usage: (command) public override Task Invoke(SocketGuild g, SocketMessage msg) { throw new NotImplementedException(); diff --git a/Modules/ModCommands/Commands/NoteWarn.cs b/Modules/ModCommands/Commands/NoteWarn.cs index e809a94..8126c90 100644 --- a/Modules/ModCommands/Commands/NoteWarn.cs +++ b/Modules/ModCommands/Commands/NoteWarn.cs @@ -2,9 +2,7 @@ using RegexBot.Common; namespace RegexBot.Modules.ModCommands.Commands; // Note and Warn commands are highly similar in implementnation, and thus are handled in a single class. -class Note : NoteWarn { - public Note(ModCommands module, JObject config) : base(module, config) { } - +class Note(ModCommands module, JObject config) : NoteWarn(module, config) { protected override string DefaultUsageMsg => string.Format(_usageHeader, Command) + "Appends a note to the moderation log for the given user."; protected override async Task ContinueInvoke(SocketGuild g, SocketMessage msg, string logMessage, SocketUser targetUser) { @@ -13,9 +11,7 @@ class Note : NoteWarn { } } -class Warn : NoteWarn { - public Warn(ModCommands module, JObject config) : base(module, config) { } - +class Warn(ModCommands module, JObject config) : NoteWarn(module, config) { protected override string DefaultUsageMsg => string.Format(_usageHeader, Command) + "Issues a warning to the given user, logging the instance to this bot's moderation log " + "and notifying the offending user over DM of the issued warning."; @@ -45,7 +41,7 @@ abstract class NoteWarn : CommandConfig { // Usage: (command) (user) (message) public override async Task Invoke(SocketGuild g, SocketMessage msg) { - var line = msg.Content.Split(new char[] { ' ' }, 3, StringSplitOptions.RemoveEmptyEntries); + var line = SplitToParams(msg, 3); if (line.Length != 3) { await SendUsageMessageAsync(msg.Channel, ":x: Not all required parameters were specified."); return; diff --git a/Modules/ModCommands/Commands/RoleManipulation.cs b/Modules/ModCommands/Commands/RoleManipulation.cs index 99e0483..0dd9bec 100644 --- a/Modules/ModCommands/Commands/RoleManipulation.cs +++ b/Modules/ModCommands/Commands/RoleManipulation.cs @@ -1,17 +1,15 @@ using RegexBot.Common; namespace RegexBot.Modules.ModCommands.Commands; -class RoleAdd : RoleManipulation { +class RoleAdd(ModCommands module, JObject config) : RoleManipulation(module, config) { protected override (string, string) String1 => ("Adds", "to"); protected override string String2 => "set"; - public RoleAdd(ModCommands module, JObject config) : base(module, config) { } protected override async Task ContinueInvoke(SocketGuildUser target, SocketRole role) => await target.AddRoleAsync(role); } -class RoleDel : RoleManipulation { +class RoleDel(ModCommands module, JObject config) : RoleManipulation(module, config) { protected override (string, string) String1 => ("Removes", "from"); protected override string String2 => "unset"; - public RoleDel(ModCommands module, JObject config) : base(module, config) { } protected override async Task ContinueInvoke(SocketGuildUser target, SocketRole role) => await target.RemoveRoleAsync(role); } @@ -46,7 +44,7 @@ abstract class RoleManipulation : CommandConfig { public override async Task Invoke(SocketGuild g, SocketMessage msg) { // TODO reason in further parameters? - var line = msg.Content.Split(new char[] { ' ' }, 3, StringSplitOptions.RemoveEmptyEntries); + var line = SplitToParams(msg, 3); string targetstr; if (line.Length < 2) { await SendUsageMessageAsync(msg.Channel, null); diff --git a/Modules/ModCommands/Commands/Say.cs b/Modules/ModCommands/Commands/Say.cs index f35de3d..7be632b 100644 --- a/Modules/ModCommands/Commands/Say.cs +++ b/Modules/ModCommands/Commands/Say.cs @@ -13,7 +13,7 @@ class Say : CommandConfig { } public override async Task Invoke(SocketGuild g, SocketMessage msg) { - var line = msg.Content.Split(new char[] { ' ' }, 3, StringSplitOptions.RemoveEmptyEntries); + var line = SplitToParams(msg, 3); if (line.Length <= 1) { await SendUsageMessageAsync(msg.Channel, ":x: You must specify a channel."); return; @@ -23,7 +23,7 @@ class Say : CommandConfig { return; } - var getCh = Utilities.ChannelMention.Match(line[1]); + var getCh = Utilities.ChannelMentionRegex().Match(line[1]); if (!getCh.Success) { await SendUsageMessageAsync(msg.Channel, ":x: Unable to find given channel."); return; diff --git a/Modules/ModCommands/Commands/ShowModLogs.cs b/Modules/ModCommands/Commands/ShowModLogs.cs index dab9c6f..6ef44fd 100644 --- a/Modules/ModCommands/Commands/ShowModLogs.cs +++ b/Modules/ModCommands/Commands/ShowModLogs.cs @@ -20,7 +20,7 @@ class ShowModLogs : CommandConfig { // Usage: (command) (query) [page] public override async Task Invoke(SocketGuild g, SocketMessage msg) { - var line = msg.Content.Split(new char[] { ' ' }, 3, StringSplitOptions.RemoveEmptyEntries); + var line = SplitToParams(msg, 3); if (line.Length < 2) { await SendUsageMessageAsync(msg.Channel, null); return; @@ -47,13 +47,12 @@ class ShowModLogs : CommandConfig { .Where(l => l.GuildId == query.GuildId && l.UserId == query.UserId) .Count(); totalPages = (int)Math.Ceiling((double)totalEntries / LogEntriesPerMessage); - results = db.ModLogs + results = [.. db.ModLogs .Where(l => l.GuildId == query.GuildId && l.UserId == query.UserId) .OrderByDescending(l => l.LogId) .Skip((pagenum - 1) * LogEntriesPerMessage) .Take(LogEntriesPerMessage) - .AsNoTracking() - .ToList(); + .AsNoTracking()]; } var resultList = new EmbedBuilder() { diff --git a/Modules/ModCommands/Commands/Timeout.cs b/Modules/ModCommands/Commands/Timeout.cs index a106a91..964284e 100644 --- a/Modules/ModCommands/Commands/Timeout.cs +++ b/Modules/ModCommands/Commands/Timeout.cs @@ -26,7 +26,7 @@ class Timeout : CommandConfig { // Usage: (command) (user) (duration) (reason) public override async Task Invoke(SocketGuild g, SocketMessage msg) { - var line = msg.Content.Split(new char[] { ' ' }, 4, StringSplitOptions.RemoveEmptyEntries); + var line = SplitToParams(msg, 4); string targetstr; string? reason; if (line.Length < 3) { diff --git a/Modules/ModCommands/Commands/Unban.cs b/Modules/ModCommands/Commands/Unban.cs index 9013ef4..f2be40b 100644 --- a/Modules/ModCommands/Commands/Unban.cs +++ b/Modules/ModCommands/Commands/Unban.cs @@ -16,7 +16,7 @@ class Unban : CommandConfig { // Usage: (command) (user query) public override async Task Invoke(SocketGuild g, SocketMessage msg) { - var line = msg.Content.Split(new char[] { ' ' }, 3, StringSplitOptions.RemoveEmptyEntries); + var line = SplitToParams(msg, 3); string targetstr; if (line.Length < 2) { await SendUsageMessageAsync(msg.Channel, null); diff --git a/Modules/ModCommands/Commands/Untimeout.cs b/Modules/ModCommands/Commands/Untimeout.cs index 87903a6..ae208ec 100644 --- a/Modules/ModCommands/Commands/Untimeout.cs +++ b/Modules/ModCommands/Commands/Untimeout.cs @@ -16,7 +16,7 @@ class Untimeout : CommandConfig { // Usage: (command) (user query) public override async Task Invoke(SocketGuild g, SocketMessage msg) { - var line = msg.Content.Split(new char[] { ' ' }, 3, StringSplitOptions.RemoveEmptyEntries); + var line = SplitToParams(msg, 3); string targetstr; if (line.Length < 2) { await SendUsageMessageAsync(msg.Channel, null); diff --git a/Modules/PendingOutRole/ModuleConfig.cs b/Modules/PendingOutRole/ModuleConfig.cs index 90c601a..8c555b6 100644 --- a/Modules/PendingOutRole/ModuleConfig.cs +++ b/Modules/PendingOutRole/ModuleConfig.cs @@ -12,6 +12,5 @@ class ModuleConfig { } catch (FormatException) { throw new ModuleLoadException("Name specified in configuration is not a role."); } - } }