Catalogger.NET/Catalogger.Backend/Bot/Commands/ChannelCommands.cs

224 lines
13 KiB
C#
Raw Normal View History

2024-08-14 16:05:43 +02:00
using System.ComponentModel;
using Catalogger.Backend.Cache;
using Catalogger.Backend.Database;
using Catalogger.Backend.Database.Queries;
using Catalogger.Backend.Extensions;
using Catalogger.Backend.Services;
using Remora.Commands.Attributes;
using Remora.Commands.Groups;
using Remora.Discord.API.Abstractions.Objects;
using Remora.Discord.API.Objects;
using Remora.Discord.Commands.Attributes;
using Remora.Discord.Commands.Contexts;
using Remora.Discord.Commands.Extensions;
using Remora.Discord.Commands.Feedback.Messages;
using Remora.Discord.Commands.Feedback.Services;
using Remora.Discord.Commands.Services;
using Remora.Discord.Interactivity;
using Remora.Discord.Interactivity.Services;
using Remora.Rest.Core;
using Remora.Results;
using DbGuild = Catalogger.Backend.Database.Models.Guild;
using IResult = Remora.Results.IResult;
namespace Catalogger.Backend.Bot.Commands;
public class ChannelCommands(
ILogger logger,
DatabaseContext db,
GuildCacheService guildCache,
ChannelCacheService channelCache,
IFeedbackService feedbackService,
ContextInjectionService contextInjection,
InMemoryDataService<Snowflake, ChannelCommandData> dataService) : CommandGroup
{
private readonly ILogger _logger = logger.ForContext<ChannelCommands>();
[Command("configure-channels")]
[Description("Configure log channels for this server.")]
[DiscordDefaultMemberPermissions(DiscordPermission.ManageGuild)]
public async Task<IResult> ConfigureChannelsAsync()
{
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.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 db.GetGuildAsync(guildId);
var (embeds, components) = BuildRootMenu(guildChannels, guild, guildConfig);
var msg = await feedbackService.SendContextualAsync(embeds: embeds,
options: new FeedbackMessageOptions(MessageComponents: components)).GetOrThrow();
dataService.TryAddData(msg.ID, new ChannelCommandData(userId, CurrentPage: null));
return Result.Success;
}
public static (List<IEmbed>, List<IMessageComponent>) BuildRootMenu(List<IChannel> guildChannels, IGuild guild,
DbGuild guildConfig)
{
List<IEmbed> embeds =
[
new Embed(
Title: $"Log channels for {guild.Name}",
Description: "Press one of the buttons below to change the channel for that log type.",
Colour: DiscordUtils.Purple,
Fields: new[]
{
new EmbedField("Server changes", PrettyChannelString(guildConfig.Channels.GuildUpdate), true),
new EmbedField("Emoji changes", PrettyChannelString(guildConfig.Channels.GuildEmojisUpdate), true),
new EmbedField("New roles", PrettyChannelString(guildConfig.Channels.GuildRoleCreate), true),
new EmbedField("Edited roles", PrettyChannelString(guildConfig.Channels.GuildRoleUpdate), true),
new EmbedField("Deleted roles", PrettyChannelString(guildConfig.Channels.GuildRoleDelete), true),
new EmbedField("New channels", PrettyChannelString(guildConfig.Channels.ChannelCreate), true),
new EmbedField("Edited channels", PrettyChannelString(guildConfig.Channels.ChannelUpdate), true),
new EmbedField("Deleted channels", PrettyChannelString(guildConfig.Channels.ChannelDelete), true),
new EmbedField("Members joining", PrettyChannelString(guildConfig.Channels.GuildMemberAdd), true),
new EmbedField("Members leaving", PrettyChannelString(guildConfig.Channels.GuildMemberRemove),
true),
new EmbedField("Member role changes", PrettyChannelString(guildConfig.Channels.GuildMemberUpdate),
true),
new EmbedField("Key role changes", PrettyChannelString(guildConfig.Channels.GuildKeyRoleUpdate),
true),
new EmbedField("Member name changes",
PrettyChannelString(guildConfig.Channels.GuildMemberNickUpdate),
true),
new EmbedField("Member avatar changes",
PrettyChannelString(guildConfig.Channels.GuildMemberAvatarUpdate), true),
new EmbedField("Kicks", PrettyChannelString(guildConfig.Channels.GuildMemberKick), true),
new EmbedField("Bans", PrettyChannelString(guildConfig.Channels.GuildBanAdd), true),
new EmbedField("Unbans", PrettyChannelString(guildConfig.Channels.GuildBanRemove), true),
new EmbedField("New invites", PrettyChannelString(guildConfig.Channels.InviteCreate), true),
new EmbedField("Deleted invites", PrettyChannelString(guildConfig.Channels.InviteDelete), true),
new EmbedField("Edited messages", PrettyChannelString(guildConfig.Channels.MessageUpdate), true),
new EmbedField("Deleted messages", PrettyChannelString(guildConfig.Channels.MessageDelete), true),
new EmbedField("Bulk deleted messages", PrettyChannelString(guildConfig.Channels.MessageDeleteBulk),
true),
})
];
List<IMessageComponent> components =
[
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: "Members avatar changes",
CustomID: CustomIDHelpers.CreateButtonIDWithState("config-channels",
nameof(LogChannelType.GuildMemberAvatarUpdate))),
new ButtonComponent(ButtonComponentStyle.Primary, Label: "Kicks",
CustomID: CustomIDHelpers.CreateButtonIDWithState("config-channels",
nameof(LogChannelType.GuildMemberKick))),
]),
new ActionRowComponent([
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 ButtonComponent(ButtonComponentStyle.Primary, Label: "Edited messages",
CustomID: CustomIDHelpers.CreateButtonIDWithState("config-channels",
nameof(LogChannelType.MessageUpdate))),
]),
new ActionRowComponent([
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",
CustomID: CustomIDHelpers.CreateButtonIDWithState("config-channels", "close")),
]),
];
return (embeds, components);
string PrettyChannelString(ulong id)
{
if (id == 0) return "Not set";
if (guildChannels.All(c => c.ID != id)) return $"unknown channel {id}";
return $"<#{id}>";
}
}
public static string PrettyLogTypeName(LogChannelType type) => type switch
{
LogChannelType.GuildUpdate => "Server changes",
LogChannelType.GuildEmojisUpdate => "Emoji changes",
LogChannelType.GuildRoleCreate => "New roles",
LogChannelType.GuildRoleUpdate => "Edited roles",
LogChannelType.GuildRoleDelete => "Deleted roles",
LogChannelType.ChannelCreate => "New channels",
LogChannelType.ChannelUpdate => "Edited channels",
LogChannelType.ChannelDelete => "Deleted channels",
LogChannelType.GuildMemberAdd => "Members joining",
LogChannelType.GuildMemberUpdate => "Members leaving",
LogChannelType.GuildKeyRoleUpdate => "Key role changes",
LogChannelType.GuildMemberNickUpdate => "Member name changes",
LogChannelType.GuildMemberAvatarUpdate => "Member avatar changes",
LogChannelType.GuildMemberRemove => "Members leaving",
LogChannelType.GuildMemberKick => "Kicks",
LogChannelType.GuildBanAdd => "Bans",
LogChannelType.GuildBanRemove => "Unbans",
LogChannelType.InviteCreate => "New invites",
LogChannelType.InviteDelete => "Deleted invites",
LogChannelType.MessageUpdate => "Edited messages",
LogChannelType.MessageDelete => "Deleted messages",
LogChannelType.MessageDeleteBulk => "Bulk deleted messages",
_ => throw new ArgumentOutOfRangeException(nameof(type), type, "Invalid LogChannelType value")
};
}