From 8445fefaf9953ed0a62375644b8875650bb90f69 Mon Sep 17 00:00:00 2001 From: Toastie <toastie@toastiet0ast.com> Date: Tue, 4 Feb 2025 22:05:30 +1300 Subject: [PATCH] Merged add and remove message into set message --- Commands/AddMessageCommand.cs | 60 ---------- Commands/RemoveMessageCommand.cs | 49 -------- Commands/SetMessageCommand.cs | 200 +++++++++++++++++++++++++++++++ Database.cs | 20 ++++ EventHandler.cs | 23 ++++ SupportChild.cs | 5 +- Utilities.cs | 5 + 7 files changed, 250 insertions(+), 112 deletions(-) delete mode 100644 Commands/AddMessageCommand.cs delete mode 100644 Commands/RemoveMessageCommand.cs create mode 100644 Commands/SetMessageCommand.cs diff --git a/Commands/AddMessageCommand.cs b/Commands/AddMessageCommand.cs deleted file mode 100644 index ff9057c..0000000 --- a/Commands/AddMessageCommand.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System.ComponentModel; -using System.Globalization; -using DSharpPlus.Entities; -using System.Threading.Tasks; -using DSharpPlus.Commands; -using DSharpPlus.Commands.ContextChecks; -using DSharpPlus.Commands.Processors.SlashCommands; -using DSharpPlus.Exceptions; - -namespace SupportChild.Commands; - -public class AddMessageCommand -{ - [RequireGuild] - [Command("addmessage")] - [Description("Adds a new message for the 'say' command.")] - public async Task OnExecute(SlashCommandContext command, - [Parameter("identifier")][Description("The identifier word used in the /say command.")] string identifier, - [Parameter("message")][Description("The message the /say command will return.")] string message) - { - if (string.IsNullOrEmpty(message)) - { - await command.RespondAsync(new DiscordEmbedBuilder - { - Color = DiscordColor.Red, - Description = "No message specified." - }, true); - return; - } - - if (Database.TryGetMessage(identifier.ToLower(CultureInfo.InvariantCulture), out Database.Message _)) - { - await command.RespondAsync(new DiscordEmbedBuilder - { - Color = DiscordColor.Red, - Description = "There is already a message with that identifier." - }, true); - return; - } - - if (Database.AddMessage(identifier, command.Member.Id, message)) - { - await command.RespondAsync(new DiscordEmbedBuilder - { - Color = DiscordColor.Green, - Description = "Message added." - }, true); - } - else - { - await command.RespondAsync(new DiscordEmbedBuilder - { - Color = DiscordColor.Red, - Description = "Error: Failed adding the message to the database." - }, true); - } - - await LogChannel.Success(command.User.Mention + " added or updated `" + identifier + "` in the /say command.\n\nContent:\n\n" + message); - } -} \ No newline at end of file diff --git a/Commands/RemoveMessageCommand.cs b/Commands/RemoveMessageCommand.cs deleted file mode 100644 index 1506c6b..0000000 --- a/Commands/RemoveMessageCommand.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.ComponentModel; -using System.Globalization; -using DSharpPlus.Entities; -using System.Threading.Tasks; -using DSharpPlus.Commands; -using DSharpPlus.Commands.ContextChecks; -using DSharpPlus.Commands.Processors.SlashCommands; -using DSharpPlus.Exceptions; - -namespace SupportChild.Commands; - -public class RemoveMessageCommand -{ - [RequireGuild] - [Command("removemessage")] - [Description("Removes a message from the 'say' command.")] - public async Task OnExecute(SlashCommandContext command, - [Parameter("identifier")][Description("The identifier word used in the /say command.")] string identifier) - { - if (!Database.TryGetMessage(identifier.ToLower(CultureInfo.InvariantCulture), out Database.Message _)) - { - await command.RespondAsync(new DiscordEmbedBuilder - { - Color = DiscordColor.Red, - Description = "There is no message with that identifier." - }, true); - return; - } - - if (Database.RemoveMessage(identifier)) - { - await command.RespondAsync(new DiscordEmbedBuilder - { - Color = DiscordColor.Green, - Description = "Message removed." - }, true); - } - else - { - await command.RespondAsync(new DiscordEmbedBuilder - { - Color = DiscordColor.Red, - Description = "Error: Failed removing the message from the database." - }, true); - } - - await LogChannel.Success("`" + identifier + "` was removed from the /say command by " + command.User.Mention + "."); - } -} \ No newline at end of file diff --git a/Commands/SetMessageCommand.cs b/Commands/SetMessageCommand.cs new file mode 100644 index 0000000..0e0127e --- /dev/null +++ b/Commands/SetMessageCommand.cs @@ -0,0 +1,200 @@ +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using DSharpPlus.Entities; +using System.Threading.Tasks; +using DSharpPlus.Commands; +using DSharpPlus.Commands.ContextChecks; +using DSharpPlus.Commands.Processors.SlashCommands; + +namespace SupportChild.Commands; + +public class SetMessageCommand +{ + private readonly struct CommandInfo(string identifier, string message) + { + public string identifier { get; } = identifier; + public string message { get; } = message; + } + + private static Dictionary<ulong, CommandInfo> waitingCommands = new(); + + [RequireGuild] + [Command("setmessage")] + [Description("Adds or updates message for the 'say' command.")] + public async Task OnExecute(SlashCommandContext command, + [Parameter("identifier")][Description("The identifier word used in the /say command.")] string identifier, + [Parameter("message")][Description("The message the /say command will return. Empty to delete message.")] string message = "") + { + + + if (Database.TryGetMessage(identifier.ToLower(CultureInfo.InvariantCulture), out Database.Message oldMessage)) + { + if (string.IsNullOrEmpty(message)) + { + await command.RespondAsync(new DiscordInteractionResponseBuilder() + .AddEmbed(new DiscordEmbedBuilder + { + Color = DiscordColor.Orange, + Description = "Are you sure you want to delete the `" + identifier + "` message?" + }) + .AddComponents(new DiscordButtonComponent(DiscordButtonStyle.Danger, "supportchild_confirmmessagedelete " + command.Interaction.Id, "Confirm"), + new DiscordButtonComponent(DiscordButtonStyle.Secondary, "supportchild_cancelmessagedelete " + command.Interaction.Id, "Cancel"))); + } + else + { + await command.RespondAsync(new DiscordInteractionResponseBuilder() + .AddEmbed(new DiscordEmbedBuilder + { + Color = DiscordColor.Cyan, + Title = "Replace the `" + identifier + "` message?" + } + .AddField("Old message:", oldMessage.message.Truncate(1024)).AddField("New message:", message.Truncate(1024))) + .AddComponents(new DiscordButtonComponent(DiscordButtonStyle.Success, "supportchild_confirmmessageupdate " + command.Interaction.Id, "Confirm"), + new DiscordButtonComponent(DiscordButtonStyle.Secondary, "supportchild_cancelmessageupdate " + command.Interaction.Id, "Cancel"))); + } + + waitingCommands.Add(command.Interaction.Id, new CommandInfo(identifier, message)); + } + else + { + if (string.IsNullOrEmpty(message)) + { + await command.RespondAsync(new DiscordEmbedBuilder + { + Color = DiscordColor.Red, + Description = "Cannot delete that message, it does not exist." + }, true); + } + else + { + await AddNewMessage(command, identifier, message); + } + } + } + + private static async Task AddNewMessage(SlashCommandContext command, string identifier, string message) + { + if (Database.AddMessage(identifier, command.Member.Id, message)) + { + await command.RespondAsync(new DiscordEmbedBuilder + { + Color = DiscordColor.Green, + Description = "Message added." + }, true); + } + else + { + await command.RespondAsync(new DiscordEmbedBuilder + { + Color = DiscordColor.Red, + Description = "Error: Failed adding the message to the database." + }, true); + } + + await LogChannel.Success(command.User.Mention + " added the `" + identifier + "` message for the /say command.\n\n**Content:**\n\n" + message); + } + + public static async Task ConfirmMessageDeletion(DiscordInteraction interaction, ulong previousInteractionID) + { + if (!waitingCommands.Remove(previousInteractionID, out CommandInfo command)) + { + await interaction.CreateResponseAsync(DiscordInteractionResponseType.UpdateMessage, new DiscordInteractionResponseBuilder().AddEmbed(new DiscordEmbedBuilder + { + Color = DiscordColor.Red, + Description = "I don't remember which message you wanted to delete, has the bot been restarted since the command was used?" + })); + return; + } + + if (!Database.TryGetMessage(command.identifier.ToLower(CultureInfo.InvariantCulture), out Database.Message _)) + { + await interaction.CreateResponseAsync(DiscordInteractionResponseType.UpdateMessage, new DiscordInteractionResponseBuilder().AddEmbed(new DiscordEmbedBuilder + { + Color = DiscordColor.Red, + Description = "There is no message with that identifier." + })); + return; + } + + if (Database.RemoveMessage(command.identifier)) + { + await interaction.CreateResponseAsync(DiscordInteractionResponseType.UpdateMessage, new DiscordInteractionResponseBuilder().AddEmbed(new DiscordEmbedBuilder + { + Color = DiscordColor.Green, + Description = "Message removed." + })); + } + else + { + await interaction.CreateResponseAsync(DiscordInteractionResponseType.UpdateMessage, new DiscordInteractionResponseBuilder().AddEmbed(new DiscordEmbedBuilder + { + Color = DiscordColor.Red, + Description = "Error: Failed removing the message from the database." + })); + } + + await LogChannel.Success("`" + command.identifier + "` was removed from the /say command by " + interaction.User.Mention + "."); + } + + public static async Task CancelMessageDeletion(DiscordInteraction interaction, ulong previousInteractionID) + { + waitingCommands.Remove(previousInteractionID); + if (interaction.Message != null) + { + await interaction.Message.DeleteAsync(); + } + } + + public static async Task ConfirmMessageUpdate(DiscordInteraction interaction, ulong previousInteractionID) + { + if (!waitingCommands.Remove(previousInteractionID, out CommandInfo command)) + { + await interaction.CreateResponseAsync(DiscordInteractionResponseType.UpdateMessage, new DiscordInteractionResponseBuilder().AddEmbed(new DiscordEmbedBuilder + { + Color = DiscordColor.Red, + Description = "I don't remember which message you wanted to update, has the bot been restarted since the command was used?" + })); + return; + } + + if (!Database.TryGetMessage(command.identifier.ToLower(CultureInfo.InvariantCulture), out Database.Message _)) + { + await interaction.CreateResponseAsync(DiscordInteractionResponseType.UpdateMessage, new DiscordInteractionResponseBuilder().AddEmbed(new DiscordEmbedBuilder + { + Color = DiscordColor.Red, + Description = "There is no message with that identifier." + })); + return; + } + + if (Database.UpdateMessage(command.identifier, interaction.User.Id, command.message)) + { + await interaction.CreateResponseAsync(DiscordInteractionResponseType.UpdateMessage, new DiscordInteractionResponseBuilder().AddEmbed(new DiscordEmbedBuilder + { + Color = DiscordColor.Green, + Description = "Message updated." + })); + } + else + { + await interaction.CreateResponseAsync(DiscordInteractionResponseType.UpdateMessage, new DiscordInteractionResponseBuilder().AddEmbed(new DiscordEmbedBuilder + { + Color = DiscordColor.Red, + Description = "Error: Failed updating the message in the database." + })); + } + + await LogChannel.Success("`" + command.identifier + "` was updated for the /say command by " + interaction.User.Mention + "."); + } + + public static async Task CancelMessageUpdate(DiscordInteraction interaction, ulong previousInteractionID) + { + waitingCommands.Remove(previousInteractionID); + if (interaction.Message != null) + { + await interaction.Message.DeleteAsync(); + } + } +} \ No newline at end of file diff --git a/Database.cs b/Database.cs index 7f2b610..40a55a6 100644 --- a/Database.cs +++ b/Database.cs @@ -619,6 +619,26 @@ public static class Database } } + public static bool UpdateMessage(string identifier, ulong userID, string message) + { + try + { + using MySqlConnection c = GetConnection(); + c.Open(); + using MySqlCommand cmd = new MySqlCommand(@"UPDATE messages SET message = @message, user_id = @user_id WHERE identifier=@identifier", c); + cmd.Parameters.AddWithValue("@identifier", identifier); + cmd.Parameters.AddWithValue("@user_id", userID); + cmd.Parameters.AddWithValue("@message", message); + cmd.Prepare(); + return cmd.ExecuteNonQuery() > 0; + } + catch (MySqlException e) + { + Logger.Error("Could not add message to database.", e); + return false; + } + } + public static bool RemoveMessage(string identifier) { try diff --git a/EventHandler.cs b/EventHandler.cs index f9ba1fd..04ae879 100644 --- a/EventHandler.cs +++ b/EventHandler.cs @@ -205,6 +205,18 @@ public static class EventHandler case not null when e.Id.StartsWith("supportchild_interviewbutton"): await Interviewer.ProcessButtonOrSelectorResponse(e.Interaction); return; + case not null when e.Id.StartsWith("supportchild_confirmmessagedelete"): + await SetMessageCommand.ConfirmMessageDeletion(e.Interaction, GetIDFromCustomID(e.Id)); + return; + case not null when e.Id.StartsWith("supportchild_cancelmessagedelete"): + await SetMessageCommand.CancelMessageDeletion(e.Interaction, GetIDFromCustomID(e.Id)); + return; + case not null when e.Id.StartsWith("supportchild_confirmmessageupdate"): + await SetMessageCommand.ConfirmMessageUpdate(e.Interaction, GetIDFromCustomID(e.Id)); + return; + case not null when e.Id.StartsWith("supportchild_cancelmessageupdate"): + await SetMessageCommand.CancelMessageUpdate(e.Interaction, GetIDFromCustomID(e.Id)); + return; case "right": case "left": case "rightskip": @@ -289,6 +301,17 @@ public static class EventHandler } } + private static ulong GetIDFromCustomID(string customID) + { + List<string> values = customID.Split(' ').ToList(); + if (values.Count < 2 || !ulong.TryParse(values[1], out ulong id)) + { + Logger.Warn("Got an invalid button/selector ID: " + customID); + return 0; + } + return id; + } + private static async Task OnNewTicketButtonUsed(DiscordInteraction interaction) { await interaction.CreateResponseAsync(DiscordInteractionResponseType.DeferredChannelMessageWithSource, new DiscordInteractionResponseBuilder().AsEphemeral()); diff --git a/SupportChild.cs b/SupportChild.cs index 2fd07ed..4484a28 100644 --- a/SupportChild.cs +++ b/SupportChild.cs @@ -193,7 +193,6 @@ internal static class SupportChild [ typeof(AddCategoryCommand), typeof(AddCommand), - typeof(AddMessageCommand), typeof(AddStaffCommand), typeof(AdminCommands), typeof(AssignCommand), @@ -201,6 +200,7 @@ internal static class SupportChild typeof(CloseCommand), typeof(CreateButtonPanelCommand), typeof(CreateSelectionBoxPanelCommand), + typeof(InterviewCommands), typeof(InterviewTemplateCommands), typeof(ListAssignedCommand), typeof(ListCommand), @@ -211,10 +211,9 @@ internal static class SupportChild typeof(NewCommand), typeof(RandomAssignCommand), typeof(RemoveCategoryCommand), - typeof(RemoveMessageCommand), typeof(RemoveStaffCommand), - typeof(InterviewCommands), typeof(SayCommand), + typeof(SetMessageCommand), typeof(SetSummaryCommand), typeof(StatusCommand), typeof(SummaryCommand), diff --git a/Utilities.cs b/Utilities.cs index 792d8a9..5a5d6f2 100644 --- a/Utilities.cs +++ b/Utilities.cs @@ -20,6 +20,11 @@ public static class Extensions { return needles.Any(haystack.Contains); } + + public static string Truncate(this string value, int maxChars) + { + return value.Length <= maxChars ? value : string.Concat(value.AsSpan(0, maxChars - 3), "..."); + } } public static class Utilities