From 07343735a0d2f2c5679590eb86bc97d691e2a94c Mon Sep 17 00:00:00 2001 From: Noi Date: Thu, 24 Feb 2022 20:53:08 -0800 Subject: [PATCH] Add and implement preconditions --- ApplicationCommands/BirthdayModule.cs | 27 +++++++++++++-------------- ApplicationCommands/Preconditions.cs | 26 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 14 deletions(-) create mode 100644 ApplicationCommands/Preconditions.cs diff --git a/ApplicationCommands/BirthdayModule.cs b/ApplicationCommands/BirthdayModule.cs index 977f866..40d15d5 100644 --- a/ApplicationCommands/BirthdayModule.cs +++ b/ApplicationCommands/BirthdayModule.cs @@ -4,6 +4,7 @@ using System.Text; namespace BirthdayBot.ApplicationCommands; +[RequireContext(ContextType.Guild)] [Group("birthday", "Commands relating to birthdays.")] public class BirthdayModule : BotModuleBase { public const string HelpExport = "Generates a text file with all known and available birthdays."; @@ -11,6 +12,8 @@ public class BirthdayModule : BotModuleBase { public const string HelpRecentUpcoming = "Get a list of users who recently had or will have a birthday."; public const string HelpRemove = "Removes your birthday information from this bot."; + // Note that these methods have largely been copied to BirthdayOverrideModule. Changes here should be reflected there as needed. + [Group("set", "Subcommands for setting birthday information.")] public class SubCmdsBirthdaySet : BotModuleBase { public const string HelpSetBday = "Sets or updates your birthday."; @@ -38,18 +41,18 @@ public class BirthdayModule : BotModuleBase { } } - var user = await Context.GetGuildUserConfAsync().ConfigureAwait(false); + var user = await ((SocketGuildUser)Context.User).GetConfigAsync().ConfigureAwait(false); await user.UpdateAsync(inmonth, inday, inzone ?? user.TimeZone).ConfigureAwait(false); await RespondAsync($":white_check_mark: Your birthday has been set to **{FormatDate(inmonth, inday)}**" + - (inzone == null ? "" : $", with time zone {inzone}") + "."); + (inzone == null ? "" : $", with time zone {inzone}") + ".").ConfigureAwait(false); } [SlashCommand("zone", HelpSetZone)] public async Task CmdSetZone([Summary(description: HelpOptZone)] string zone) { - var user = await Context.GetGuildUserConfAsync().ConfigureAwait(false); + var user = await ((SocketGuildUser)Context.User).GetConfigAsync().ConfigureAwait(false); if (!user.IsKnown) { - await RespondAsync(":x: You must first set your birthday to use this command.", ephemeral: true).ConfigureAwait(false); + await RespondAsync(":x: You do not have a birthday set.", ephemeral: true).ConfigureAwait(false); return; } @@ -67,12 +70,14 @@ public class BirthdayModule : BotModuleBase { [SlashCommand("remove", HelpRemove)] public async Task CmdRemove() { - var user = await Context.GetGuildUserConfAsync().ConfigureAwait(false); + var user = await ((SocketGuildUser)Context.User).GetConfigAsync().ConfigureAwait(false); if (user.IsKnown) { await user.DeleteAsync().ConfigureAwait(false); - await RespondAsync(":white_check_mark: Your information for this server has been removed."); + await RespondAsync(":white_check_mark: Your birthday in this server has been removed.") + .ConfigureAwait(false); } else { - await RespondAsync(":white_check_mark: This bot already does not have your birthday for this server."); + await RespondAsync(":white_check_mark: Your birthday is not registered.") + .ConfigureAwait(false); } } @@ -169,15 +174,9 @@ public class BirthdayModule : BotModuleBase { await doOutput(output.ToString()).ConfigureAwait(false); } + [RequireBotModerator] [SlashCommand("export", HelpPfxModOnly + HelpExport)] public async Task CmdExport([Summary(description: "Specify whether to export the list in CSV format.")] bool asCsv = false) { - // For now, we're restricting this command to moderators only. This may turn into an option later. - if (!(await Context.GetGuildConfAsync()).IsBotModerator((SocketGuildUser)Context.User)) { - // Do not add detailed usage information to this error message. - await RespondAsync(":x: Only bot moderators may use this command.", ephemeral: true).ConfigureAwait(false); - return; - } - if (!await HasMemberCacheAsync(Context.Guild)) { await RespondAsync(MemberCacheEmptyError).ConfigureAwait(false); return; diff --git a/ApplicationCommands/Preconditions.cs b/ApplicationCommands/Preconditions.cs new file mode 100644 index 0000000..0bf9cc9 --- /dev/null +++ b/ApplicationCommands/Preconditions.cs @@ -0,0 +1,26 @@ +using BirthdayBot.Data; +using Discord.Interactions; + +namespace BirthdayBot.ApplicationCommands; + +// Contains preconditions used by our interaction modules. + +/// +/// Precondition requiring the executing user be considered a bot moderator. +/// That is, they must either have the Manage Server permission or be a member of the designated bot moderator role. +/// +class RequireBotModeratorAttribute : PreconditionAttribute { + public override string ErrorMessage => ":x: Only bot moderators may use this command."; + + public override async Task CheckRequirementsAsync(IInteractionContext context, + ICommandInfo commandInfo, IServiceProvider services) { + if (context.User is not SocketGuildUser user) { + return PreconditionResult.FromError("Mod check automatically failed due to non-guild context."); + } + + var gconf = await GuildConfiguration.LoadAsync(context.Guild.Id, false); + var isMod = gconf!.IsBotModerator(user); + if (isMod) return PreconditionResult.FromSuccess(); + else return PreconditionResult.FromError("User did not pass the mod check."); + } +}