Remove custom precondition; use Discord permissions

This commit is contained in:
Noi 2023-01-14 21:54:23 -08:00
parent 09ba9644dc
commit c8de71854b
5 changed files with 40 additions and 85 deletions

View file

@ -73,13 +73,6 @@ public class CommandsBase : InteractionModuleBase<ShardedInteractionContext> {
return $"**{username}**#{user.Discriminator}"; return $"**{username}**#{user.Discriminator}";
} }
/// <summary>
/// Checks if the given user can be considered a guild admin ('Manage Server' is set).
/// </summary>
// TODO replace this with a precondition, or there's also a new permission scheme going around?
protected static bool IsUserAdmin(SocketGuildUser user)
=> user.GuildPermissions.Administrator || user.GuildPermissions.ManageGuild;
/// <summary> /// <summary>
/// Checks if the member cache for the specified guild needs to be filled, and sends a request if needed. /// Checks if the member cache for the specified guild needs to be filled, and sends a request if needed.
/// </summary> /// </summary>

View file

@ -1,19 +1,16 @@
using Discord.Interactions; using Discord.Interactions;
namespace WorldTime.Commands; namespace WorldTime.Commands;
[Group("config", HelpSettings)] [Group("config", "Configuration commands for World Time.")]
[DefaultMemberPermissions(GuildPermission.ManageGuild)]
[EnabledInDm(false)]
public class ConfigCommands : CommandsBase { public class ConfigCommands : CommandsBase {
internal const string HelpSettings = "Configuration commands for World Time.";
internal const string HelpUse12 = "Sets whether to use the 12-hour (AM/PM) format in time zone listings."; internal const string HelpUse12 = "Sets whether to use the 12-hour (AM/PM) format in time zone listings.";
internal const string HelpSetFor = "Sets/updates time zone for a given user.";
internal const string HelpRemoveFor = "Removes time zone for a given user.";
[RequireGuildContext]
[SlashCommand("use-12hour", HelpUse12)] [SlashCommand("use-12hour", HelpUse12)]
public async Task Cmd12Hour([Summary(description: "True to enable, False to disable.")] bool setting) { public async Task Cmd12Hour([Summary(description: "True to enable, False to disable.")] bool setting) {
if (!IsUserAdmin((SocketGuildUser)Context.User)) {
await RespondAsync(ErrNotAllowed, ephemeral: true);
return;
}
using var db = DbContext; using var db = DbContext;
var gs = db.GuildSettings.Where(r => r.GuildId == Context.Guild.Id).SingleOrDefault(); var gs = db.GuildSettings.Where(r => r.GuildId == Context.Guild.Id).SingleOrDefault();
if (gs == null) { if (gs == null) {
@ -25,4 +22,28 @@ public class ConfigCommands : CommandsBase {
await db.SaveChangesAsync(); await db.SaveChangesAsync();
await RespondAsync($":white_check_mark: Time listing set to **{(setting ? "AM/PM" : "24 hour")}** format."); await RespondAsync($":white_check_mark: Time listing set to **{(setting ? "AM/PM" : "24 hour")}** format.");
} }
[SlashCommand("set-for", HelpSetFor)]
public async Task CmdSetFor([Summary(description: "The user whose time zone to modify.")] SocketGuildUser user,
[Summary(description: "The new time zone to set.")] string zone) {
// Extract parameters
var newtz = ParseTimeZone(zone);
if (newtz == null) {
await RespondAsync(ErrInvalidZone);
return;
}
using var db = DbContext;
db.UpdateUser(user, newtz);
await RespondAsync($":white_check_mark: Time zone for **{user}** set to **{newtz}**.");
}
[SlashCommand("remove-for", HelpRemoveFor)]
public async Task CmdRemoveFor([Summary(description: "The user whose time zone to remove.")] SocketGuildUser user) {
using var db = DbContext;
if (db.DeleteUser(user))
await RespondAsync($":white_check_mark: Removed zone information for {user}.");
else
await RespondAsync($":white_check_mark: No time zone is set for {user}.");
}
} }

View file

@ -1,14 +0,0 @@
using Discord.Interactions;
namespace WorldTime.Commands;
/// <summary>
/// Implements the included precondition from Discord.Net, requiring a guild context while using our custom error message.
/// </summary>
class RequireGuildContextAttribute : RequireContextAttribute {
public const string Error = "Command not received within a guild context.";
public const string Reply = ":x: This command is only available within a server.";
public override string ErrorMessage => Error;
public RequireGuildContextAttribute() : base(ContextType.Guild) { }
}

View file

@ -10,16 +10,15 @@ public class UserCommands : CommandsBase {
+ $"`/remove` - {HelpRemove}"; + $"`/remove` - {HelpRemove}";
const string EmbedHelpField2 = const string EmbedHelpField2 =
$"`/config use-12hour` - {ConfigCommands.HelpUse12}\n" $"`/config use-12hour` - {ConfigCommands.HelpUse12}\n"
+ $"`/set-for` - {HelpSetFor}\n" + $"`/set-for` - {ConfigCommands.HelpSetFor}\n"
+ $"`/remove-for` - {HelpRemoveFor}"; + $"`/remove-for` - {ConfigCommands.HelpRemoveFor}";
#region Help strings #region Help strings
const string HelpHelp = "Displays a list of available bot commands."; const string HelpHelp = "Displays a list of available bot commands.";
const string HelpList = "Shows the current time for all recently active known users."; const string HelpList = "Shows the current time for all recently active known users.";
const string HelpSet = "Adds or updates your time zone to the bot."; const string HelpSet = "Adds or updates your time zone to the bot.";
const string HelpSetFor = "Sets/updates time zone for a given user.";
const string HelpRemove = "Removes your time zone information from this bot."; const string HelpRemove = "Removes your time zone information from this bot.";
const string HelpRemoveFor = "Removes time zone for a given user.";
#endregion #endregion
[SlashCommand("help", HelpHelp)] [SlashCommand("help", HelpHelp)]
@ -46,8 +45,8 @@ public class UserCommands : CommandsBase {
).Build()); ).Build());
} }
[RequireGuildContext]
[SlashCommand("list", HelpList)] [SlashCommand("list", HelpList)]
[EnabledInDm(false)]
public async Task CmdList([Summary(description: "A specific user whose time to look up.")]SocketGuildUser? user = null) { public async Task CmdList([Summary(description: "A specific user whose time to look up.")]SocketGuildUser? user = null) {
if (!await AreUsersDownloadedAsync(Context.Guild)) { if (!await AreUsersDownloadedAsync(Context.Guild)) {
await RespondAsync(ErrNoUserCache, ephemeral: true); await RespondAsync(ErrNoUserCache, ephemeral: true);
@ -149,6 +148,7 @@ public class UserCommands : CommandsBase {
} }
[SlashCommand("set", HelpSet)] [SlashCommand("set", HelpSet)]
[EnabledInDm(false)]
public async Task CmdSet([Summary(description: "The new time zone to set.")]string zone) { public async Task CmdSet([Summary(description: "The new time zone to set.")]string zone) {
var parsedzone = ParseTimeZone(zone); var parsedzone = ParseTimeZone(zone);
if (parsedzone == null) { if (parsedzone == null) {
@ -160,48 +160,12 @@ public class UserCommands : CommandsBase {
await RespondAsync($":white_check_mark: Your time zone has been set to **{parsedzone}**."); await RespondAsync($":white_check_mark: Your time zone has been set to **{parsedzone}**.");
} }
[RequireGuildContext]
[SlashCommand("set-for", HelpSetFor)]
public async Task CmdSetFor([Summary(description: "The user whose time zone to modify.")] SocketGuildUser user,
[Summary(description: "The new time zone to set.")] string zone) {
if (!IsUserAdmin((SocketGuildUser)Context.User)) {
await RespondAsync(ErrNotAllowed, ephemeral: true).ConfigureAwait(false);
return;
}
// Extract parameters
var newtz = ParseTimeZone(zone);
if (newtz == null) {
await RespondAsync(ErrInvalidZone);
return;
}
using var db = DbContext;
db.UpdateUser(user, newtz);
await RespondAsync($":white_check_mark: Time zone for **{user}** set to **{newtz}**.");
}
[RequireGuildContext]
[SlashCommand("remove", HelpRemove)] [SlashCommand("remove", HelpRemove)]
[EnabledInDm(false)]
public async Task CmdRemove() { public async Task CmdRemove() {
using var db = DbContext; using var db = DbContext;
var success = db.DeleteUser((SocketGuildUser)Context.User); var success = db.DeleteUser((SocketGuildUser)Context.User);
if (success) await RespondAsync(":white_check_mark: Your zone has been removed."); if (success) await RespondAsync(":white_check_mark: Your zone has been removed.");
else await RespondAsync(":x: You don't have a time zone set."); else await RespondAsync(":x: You don't have a time zone set.");
} }
[RequireGuildContext]
[SlashCommand("remove-for", HelpRemoveFor)]
public async Task CmdRemoveFor([Summary(description: "The user whose time zone to remove.")] SocketGuildUser user) {
if (!IsUserAdmin((SocketGuildUser)Context.User)) {
await RespondAsync(ErrNotAllowed, ephemeral: true).ConfigureAwait(false);
return;
}
using var db = DbContext;
if (db.DeleteUser(user))
await RespondAsync($":white_check_mark: Removed zone information for {user}.");
else
await RespondAsync($":white_check_mark: No time zone is set for {user}.");
}
} }

View file

@ -199,21 +199,12 @@ internal class WorldTime : IDisposable {
// Additional log information with error detail // Additional log information with error detail
logresult += " " + Enum.GetName(typeof(InteractionCommandError), result.Error) + ": " + result.ErrorReason; logresult += " " + Enum.GetName(typeof(InteractionCommandError), result.Error) + ": " + result.ErrorReason;
// Specific responses to errors, if necessary
if (result.Error == InteractionCommandError.UnmetPrecondition) {
string errReply = result.ErrorReason switch {
Commands.RequireGuildContextAttribute.Error => Commands.RequireGuildContextAttribute.Reply,
_ => result.ErrorReason
};
await context.Interaction.RespondAsync(errReply, ephemeral: true);
} else {
// Generic error response // Generic error response
// TODO when implementing proper application error logging, see here // TODO when implementing proper application error logging, see here
var ia = context.Interaction; var ia = context.Interaction;
if (ia.HasResponded) await ia.ModifyOriginalResponseAsync(p => p.Content = InternalError); if (ia.HasResponded) await ia.ModifyOriginalResponseAsync(p => p.Content = InternalError);
else await ia.RespondAsync(InternalError); else await ia.RespondAsync(InternalError);
} }
}
Program.Log("Command", logresult); Program.Log("Command", logresult);
} }