224 lines
13 KiB
C#
224 lines
13 KiB
C#
|
|
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")
|
||
|
|
};
|
||
|
|
}
|