From f0fcfd7bd35447a40858ce4b6620efc375736275 Mon Sep 17 00:00:00 2001 From: sam Date: Tue, 5 Nov 2024 16:20:24 +0100 Subject: [PATCH] feat: replace buttons in /configure-channels with select menu --- .../Bot/Commands/ChannelCommands.cs | 288 ++++++------------ .../Bot/Commands/ChannelCommandsComponents.cs | 163 ++++++---- .../Cache/InMemoryCache/UserCache.cs | 1 - .../Database/Repositories/GuildRepository.cs | 1 - 4 files changed, 186 insertions(+), 267 deletions(-) diff --git a/Catalogger.Backend/Bot/Commands/ChannelCommands.cs b/Catalogger.Backend/Bot/Commands/ChannelCommands.cs index fcf54b9..2dab68f 100644 --- a/Catalogger.Backend/Bot/Commands/ChannelCommands.cs +++ b/Catalogger.Backend/Bot/Commands/ChannelCommands.cs @@ -222,6 +222,93 @@ public class ChannelCommands( return Result.Success; } + public static IStringSelectComponent LogTypeSelect => + new StringSelectComponent( + CustomID: CustomIDHelpers.CreateSelectMenuID("select-log-type"), + MinValues: 1, + MaxValues: 1, + Options: + [ + new SelectOption( + Label: "Server changes", + Value: nameof(LogChannelType.GuildUpdate) + ), + new SelectOption( + Label: "Emoji changes", + Value: nameof(LogChannelType.GuildEmojisUpdate) + ), + new SelectOption(Label: "New roles", Value: nameof(LogChannelType.GuildRoleCreate)), + new SelectOption( + Label: "Edited roles", + Value: nameof(LogChannelType.GuildRoleUpdate) + ), + new SelectOption( + Label: "Deleted roles", + Value: nameof(LogChannelType.GuildRoleDelete) + ), + new SelectOption( + Label: "New channels", + Value: nameof(LogChannelType.ChannelCreate) + ), + new SelectOption( + Label: "Edited channels", + Value: nameof(LogChannelType.ChannelUpdate) + ), + new SelectOption( + Label: "Deleted channels", + Value: nameof(LogChannelType.ChannelDelete) + ), + new SelectOption( + Label: "Members joining", + Value: nameof(LogChannelType.GuildMemberAdd) + ), + new SelectOption( + Label: "Members leaving", + Value: nameof(LogChannelType.GuildMemberRemove) + ), + new SelectOption( + Label: "Member role changes", + Value: nameof(LogChannelType.GuildMemberUpdate) + ), + new SelectOption( + Label: "Key role changes", + Value: nameof(LogChannelType.GuildKeyRoleUpdate) + ), + new SelectOption( + Label: "Member name changes", + Value: nameof(LogChannelType.GuildMemberNickUpdate) + ), + new SelectOption( + Label: "Member avatar changes", + Value: nameof(LogChannelType.GuildMemberAvatarUpdate) + ), + new SelectOption( + Label: "Timeouts", + Value: nameof(LogChannelType.GuildMemberTimeout) + ), + new SelectOption(Label: "Kicks", Value: nameof(LogChannelType.GuildMemberKick)), + new SelectOption(Label: "Bans", Value: nameof(LogChannelType.GuildBanAdd)), + new SelectOption(Label: "Unbans", Value: nameof(LogChannelType.GuildBanRemove)), + new SelectOption(Label: "New invites", Value: nameof(LogChannelType.InviteCreate)), + new SelectOption( + Label: "Deleted invites", + Value: nameof(LogChannelType.InviteDelete) + ), + new SelectOption( + Label: "Edited messages", + Value: nameof(LogChannelType.MessageUpdate) + ), + new SelectOption( + Label: "Deleted messages", + Value: nameof(LogChannelType.MessageDelete) + ), + new SelectOption( + Label: "Bulk deleted messages", + Value: nameof(LogChannelType.MessageDeleteBulk) + ), + ] + ); + public static (List, List) BuildRootMenu( List guildChannels, IGuild guild, @@ -357,208 +444,9 @@ public class ChannelCommands( List components = [ + new ActionRowComponent([LogTypeSelect]), new ActionRowComponent( [ - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Server changes", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildUpdate) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Emoji changes", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildEmojisUpdate) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "New roles", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildRoleCreate) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Edited roles", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildRoleUpdate) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Deleted roles", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildRoleDelete) - ) - ), - ] - ), - new ActionRowComponent( - [ - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "New channels", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.ChannelCreate) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Edited channels", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.ChannelUpdate) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Deleted channels", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.ChannelDelete) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Members joining", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildMemberAdd) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Members leaving", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildMemberRemove) - ) - ), - ] - ), - new ActionRowComponent( - [ - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Member role changes", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildMemberUpdate) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Key role changes", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildKeyRoleUpdate) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Member name changes", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildMemberNickUpdate) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Member avatar changes", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildMemberAvatarUpdate) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Timeouts", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildMemberTimeout) - ) - ), - ] - ), - new ActionRowComponent( - [ - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Kicks", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildMemberKick) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Bans", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildBanAdd) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Unbans", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.GuildBanRemove) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "New invites", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.InviteCreate) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Deleted invites", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.InviteDelete) - ) - ), - ] - ), - new ActionRowComponent( - [ - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Edited messages", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.MessageUpdate) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Deleted messages", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.MessageDelete) - ) - ), - new ButtonComponent( - ButtonComponentStyle.Primary, - Label: "Bulk deleted messages", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - nameof(LogChannelType.MessageDeleteBulk) - ) - ), new ButtonComponent( ButtonComponentStyle.Secondary, Label: "Close", diff --git a/Catalogger.Backend/Bot/Commands/ChannelCommandsComponents.cs b/Catalogger.Backend/Bot/Commands/ChannelCommandsComponents.cs index 1bda457..b94df0d 100644 --- a/Catalogger.Backend/Bot/Commands/ChannelCommandsComponents.cs +++ b/Catalogger.Backend/Bot/Commands/ChannelCommandsComponents.cs @@ -45,6 +45,103 @@ public class ChannelCommandsComponents( { private readonly ILogger _logger = logger.ForContext(); + [SelectMenu("select-log-type")] + [SuppressInteractionResponse(true)] + public async Task OnMenuSelectionAsync(IReadOnlyList values) + { + if (contextInjection.Context is not IInteractionCommandContext ctx) + throw new CataloggerError("No context"); + if (!ctx.TryGetUserID(out var userId)) + throw new CataloggerError("No user ID in context"); + if (!ctx.Interaction.Message.TryGet(out var msg)) + throw new CataloggerError("No message ID in context"); + if (!ctx.TryGetGuildID(out var guildId)) + throw new CataloggerError("No guild ID in context"); + if (!guildCache.TryGet(guildId, out var guild)) + throw new CataloggerError("Guild not in cache"); + var guildChannels = channelCache.GuildChannels(guildId).ToList(); + var guildConfig = await guildRepository.GetAsync(guildId); + + var result = await dataService.LeaseDataAsync(msg.ID); + await using var lease = result.GetOrThrow(); + if (lease.Data.UserId != userId) + { + return (Result) + await feedbackService.ReplyAsync( + "This is not your configuration menu.", + isEphemeral: true + ); + } + + var state = values[0]; + + if (!Enum.TryParse(state, out var logChannelType)) + throw new CataloggerError($"Invalid config-channels state {state}"); + + var channelId = WebhookExecutorService.GetDefaultLogChannel(guildConfig, logChannelType); + string? channelMention; + if (channelId is 0) + channelMention = null; + else if (guildChannels.All(c => c.ID != channelId)) + channelMention = $"unknown channel {channelId}"; + else + channelMention = $"<#{channelId}>"; + + List embeds = + [ + new Embed( + Title: ChannelCommands.PrettyLogTypeName(logChannelType), + Description: channelMention == null + ? "This event is not currently logged.\nTo start logging it somewhere, select a channel below." + : $"This event is currently set to log to {channelMention}." + + "\nTo change where it is logged, select a channel below." + + "\nTo disable logging this event entirely, select \"Stop logging\" below.", + Colour: DiscordUtils.Purple + ), + ]; + + List components = + [ + new ActionRowComponent( + new[] + { + new ChannelSelectComponent( + CustomID: CustomIDHelpers.CreateSelectMenuID("config-channels"), + ChannelTypes: new[] { ChannelType.GuildText } + ), + } + ), + new ActionRowComponent( + new[] + { + new ButtonComponent( + ButtonComponentStyle.Danger, + Label: "Stop logging", + CustomID: CustomIDHelpers.CreateButtonIDWithState( + "config-channels", + "reset" + ), + IsDisabled: channelMention == null + ), + new ButtonComponent( + ButtonComponentStyle.Secondary, + Label: "Return to menu", + CustomID: CustomIDHelpers.CreateButtonIDWithState( + "config-channels", + "return" + ) + ), + } + ), + ]; + + lease.Data = new ChannelCommandData(userId, CurrentPage: state); + return await interactionApi.UpdateMessageAsync( + ctx.Interaction, + new InteractionMessageCallbackData(Embeds: embeds, Components: components) + ); + } + [Button("config-channels")] [SuppressInteractionResponse(true)] public async Task OnButtonPressedAsync(string state) @@ -176,71 +273,7 @@ public class ChannelCommandsComponents( return Result.Success; } - if (!Enum.TryParse(state, out var logChannelType)) - throw new CataloggerError($"Invalid config-channels state {state}"); - - var channelId = WebhookExecutorService.GetDefaultLogChannel(guildConfig, logChannelType); - string? channelMention; - if (channelId is 0) - channelMention = null; - else if (guildChannels.All(c => c.ID != channelId)) - channelMention = $"unknown channel {channelId}"; - else - channelMention = $"<#{channelId}>"; - - List embeds = - [ - new Embed( - Title: ChannelCommands.PrettyLogTypeName(logChannelType), - Description: channelMention == null - ? "This event is not currently logged.\nTo start logging it somewhere, select a channel below." - : $"This event is currently set to log to {channelMention}." - + "\nTo change where it is logged, select a channel below." - + "\nTo disable logging this event entirely, select \"Stop logging\" below.", - Colour: DiscordUtils.Purple - ), - ]; - - List components = - [ - new ActionRowComponent( - new[] - { - new ChannelSelectComponent( - CustomID: CustomIDHelpers.CreateSelectMenuID("config-channels"), - ChannelTypes: new[] { ChannelType.GuildText } - ), - } - ), - new ActionRowComponent( - new[] - { - new ButtonComponent( - ButtonComponentStyle.Danger, - Label: "Stop logging", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - "reset" - ), - IsDisabled: channelMention == null - ), - new ButtonComponent( - ButtonComponentStyle.Secondary, - Label: "Return to menu", - CustomID: CustomIDHelpers.CreateButtonIDWithState( - "config-channels", - "return" - ) - ), - } - ), - ]; - - lease.Data = new ChannelCommandData(userId, CurrentPage: state); - return await interactionApi.UpdateMessageAsync( - ctx.Interaction, - new InteractionMessageCallbackData(Embeds: embeds, Components: components) - ); + return Result.Success; } [SelectMenu("config-channels")] diff --git a/Catalogger.Backend/Cache/InMemoryCache/UserCache.cs b/Catalogger.Backend/Cache/InMemoryCache/UserCache.cs index d5a1313..f99856e 100644 --- a/Catalogger.Backend/Cache/InMemoryCache/UserCache.cs +++ b/Catalogger.Backend/Cache/InMemoryCache/UserCache.cs @@ -13,7 +13,6 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -using System.Diagnostics.CodeAnalysis; using Catalogger.Backend.Extensions; using LazyCache; using Remora.Discord.API.Abstractions.Objects; diff --git a/Catalogger.Backend/Database/Repositories/GuildRepository.cs b/Catalogger.Backend/Database/Repositories/GuildRepository.cs index 5c1b3f7..0cf83bf 100644 --- a/Catalogger.Backend/Database/Repositories/GuildRepository.cs +++ b/Catalogger.Backend/Database/Repositories/GuildRepository.cs @@ -15,7 +15,6 @@ using Catalogger.Backend.Database.Models; using Dapper; -using Npgsql.Replication; using Remora.Discord.API; using Remora.Rest.Core;