[Feature] Parameter precondition attribute for simplifying performing hierarchical operations within a guild (#2906)
* Support interaction framework and update bundled preconditions docs * Support text commands and update bundled preconditions docs * Fix example * Move hierarchy util to `PermissionUtils` * Refactoring
This commit is contained in:
@@ -30,6 +30,7 @@ to use.
|
|||||||
* @Discord.Interactions.RequireNsfwAttribute
|
* @Discord.Interactions.RequireNsfwAttribute
|
||||||
* @Discord.Interactions.RequireRoleAttribute
|
* @Discord.Interactions.RequireRoleAttribute
|
||||||
* @Discord.Interactions.RequireTeamAttribute
|
* @Discord.Interactions.RequireTeamAttribute
|
||||||
|
* @Discord.Interactions.DoHierarchyCheckAttribute
|
||||||
|
|
||||||
## Using Preconditions
|
## Using Preconditions
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ to use.
|
|||||||
* @Discord.Commands.RequireBotPermissionAttribute
|
* @Discord.Commands.RequireBotPermissionAttribute
|
||||||
* @Discord.Commands.RequireUserPermissionAttribute
|
* @Discord.Commands.RequireUserPermissionAttribute
|
||||||
* @Discord.Commands.RequireNsfwAttribute
|
* @Discord.Commands.RequireNsfwAttribute
|
||||||
|
* @Discord.Commands.DoHierarchyCheckAttribute
|
||||||
|
|
||||||
## Using Preconditions
|
## Using Preconditions
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Discord.Commands
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Ensures that command parameters are passed within a correct hierarchical context.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Useful for performing hierarchical operations within a guild, such as managing roles or users.
|
||||||
|
/// <note type="warning">
|
||||||
|
/// This supports <see cref="IRole"/>, <see cref="IGuildUser"/>, and <see cref="IUser"/> parameter types.
|
||||||
|
/// </note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||||
|
/// Thrown when the parameter type is not supported by this precondition attribute.
|
||||||
|
/// </exception>
|
||||||
|
/// <seealso cref="RequireBotPermissionAttribute"/>
|
||||||
|
/// <seealso cref="RequireUserPermissionAttribute"/>
|
||||||
|
public class DoHierarchyCheckAttribute : ParameterPreconditionAttribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the error message displayed when the command is used outside of a guild.
|
||||||
|
/// </summary>
|
||||||
|
public string NotAGuildErrorMessage { get; set; } = "This command cannot be used outside of a guild.";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the error message to be returned if execution context doesn't pass the precondition check.
|
||||||
|
/// </summary>
|
||||||
|
public string ErrorMessage { get; set; } = "You cannot target anyone who is higher or equal in the hierarchy to you or the bot.";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||||
|
/// Thrown when the parameter type is not supported by this precondition attribute.
|
||||||
|
/// </exception>
|
||||||
|
public override async Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, ParameterInfo parameterInfo, object value, IServiceProvider services)
|
||||||
|
{
|
||||||
|
if (context.User is not IGuildUser guildUser)
|
||||||
|
return PreconditionResult.FromError(NotAGuildErrorMessage);
|
||||||
|
|
||||||
|
var hieararchy = PermissionUtils.GetHieararchy(value);
|
||||||
|
if (hieararchy >= guildUser.Hierarchy ||
|
||||||
|
hieararchy >= (await context.Guild.GetCurrentUserAsync().ConfigureAwait(false)).Hierarchy)
|
||||||
|
return PreconditionResult.FromError(ErrorMessage);
|
||||||
|
|
||||||
|
return PreconditionResult.FromSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/Discord.Net.Core/Utils/PermissionUtils.cs
Normal file
31
src/Discord.Net.Core/Utils/PermissionUtils.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Discord
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a series of helper methods for permissions.
|
||||||
|
/// </summary>
|
||||||
|
public static class PermissionUtils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Determines the hierarchy of a target object based on its type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">
|
||||||
|
/// The target object: <see cref="IRole"/>, <see cref="IGuildUser"/>, or <see cref="IUser"/>.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// An integer representing the hierarchy of the target.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||||
|
/// Thrown when the parameter type is not supported by this precondition attribute.
|
||||||
|
/// </exception>
|
||||||
|
public static int GetHieararchy(object target) => target switch
|
||||||
|
{
|
||||||
|
// The order of cases here is important to determine the correct hierarchy value.
|
||||||
|
IRole role => role.Position,
|
||||||
|
IGuildUser guildUser => guildUser.Hierarchy,
|
||||||
|
IUser => int.MinValue,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(target), "Cannot determine hierarchy for the provided target.")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Discord.Interactions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Ensures that command parameters are passed within a correct hierarchical context.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Useful for performing hierarchical operations within a guild, such as managing roles or users.
|
||||||
|
/// <note type="warning">
|
||||||
|
/// This supports <see cref="IRole"/>, <see cref="IGuildUser"/>, and <see cref="IUser"/> parameter types.
|
||||||
|
/// </note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||||
|
/// Thrown when the parameter type is not supported by this precondition attribute.
|
||||||
|
/// </exception>
|
||||||
|
/// <seealso cref="RequireRoleAttribute"/>
|
||||||
|
/// <seealso cref="RequireBotPermissionAttribute"/>
|
||||||
|
/// <seealso cref="RequireUserPermissionAttribute"/>
|
||||||
|
public class DoHierarchyCheckAttribute : ParameterPreconditionAttribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the error message displayed when the command is used outside of a guild.
|
||||||
|
/// </summary>
|
||||||
|
public string NotAGuildErrorMessage { get; set; } = "This command cannot be used outside of a guild.";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ErrorMessage => "You cannot target anyone who is higher or equal in the hierarchy to you or the bot.";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||||
|
/// Thrown when the parameter type is not supported by this precondition attribute.
|
||||||
|
/// </exception>
|
||||||
|
public override async Task<PreconditionResult> CheckRequirementsAsync(IInteractionContext context, IParameterInfo parameterInfo, object value, IServiceProvider services)
|
||||||
|
{
|
||||||
|
if (context.User is not IGuildUser guildUser)
|
||||||
|
return PreconditionResult.FromError(NotAGuildErrorMessage);
|
||||||
|
|
||||||
|
var hieararchy = PermissionUtils.GetHieararchy(value);
|
||||||
|
if (hieararchy >= guildUser.Hierarchy ||
|
||||||
|
hieararchy >= (await context.Guild.GetCurrentUserAsync().ConfigureAwait(false)).Hierarchy)
|
||||||
|
return PreconditionResult.FromError(ErrorMessage);
|
||||||
|
|
||||||
|
return PreconditionResult.FromSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user