From 5dadcb2e30729292a769adc701634843d946d85c Mon Sep 17 00:00:00 2001
From: ImNoOSRS <69985903+ImNoOSRS@users.noreply.github.com>
Date: Sat, 11 May 2024 22:27:59 +0200
Subject: [PATCH] RequireRole permission for commands. (#2923)
* Create RequireRoleAttribute.cs
* Apply suggestions from code review
---------
Co-authored-by: Mihail Gribkov <61027276+Misha-133@users.noreply.github.com>
---
.../Preconditions/RequireRoleAttribute.cs | 74 +++++++++++++++++++
1 file changed, 74 insertions(+)
create mode 100644 src/Discord.Net.Commands/Attributes/Preconditions/RequireRoleAttribute.cs
diff --git a/src/Discord.Net.Commands/Attributes/Preconditions/RequireRoleAttribute.cs b/src/Discord.Net.Commands/Attributes/Preconditions/RequireRoleAttribute.cs
new file mode 100644
index 00000000..112f5697
--- /dev/null
+++ b/src/Discord.Net.Commands/Attributes/Preconditions/RequireRoleAttribute.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Discord.Commands
+{
+ ///
+ /// Requires the user invoking the command to have a specified role.
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
+ public class RequireRoleAttribute : PreconditionAttribute
+ {
+ ///
+ /// Gets the specified Role name of the precondition.
+ ///
+ public string RoleName { get; }
+
+ ///
+ /// Gets the specified Role ID of the precondition.
+ ///
+ public ulong? RoleId { get; }
+
+ ///
+ /// Gets or sets the error message if the precondition
+ /// fails due to being run outside of a Guild channel.
+ ///
+ public string NotAGuildErrorMessage { get; set; }
+
+ ///
+ /// Requires that the user invoking the command to have a specific Role.
+ ///
+ /// Id of the role that the user must have.
+ public RequireRoleAttribute(ulong roleId)
+ {
+ RoleId = roleId;
+ }
+
+ ///
+ /// Requires that the user invoking the command to have a specific Role.
+ ///
+ /// Name of the role that the user must have.
+ public RequireRoleAttribute(string roleName)
+ {
+ RoleName = roleName;
+ }
+
+
+ public override Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services)
+ {
+ if (context.User is not IGuildUser guildUser)
+ return Task.FromResult(PreconditionResult.FromError(NotAGuildErrorMessage ?? "Command must be used in a guild channel."));
+
+ if (RoleId.HasValue)
+ {
+ if (guildUser.RoleIds.Contains(RoleId.Value))
+ return Task.FromResult(PreconditionResult.FromSuccess());
+ else
+ return Task.FromResult(PreconditionResult.FromError(ErrorMessage ?? $"User requires guild role {context.Guild.GetRole(RoleId.Value).Name}."));
+ }
+
+ if (!string.IsNullOrEmpty(RoleName))
+ {
+ var roleNames = guildUser.RoleIds.Select(x => guildUser.Guild.GetRole(x).Name);
+
+ if (roleNames.Contains(RoleName))
+ return Task.FromResult(PreconditionResult.FromSuccess());
+ else
+ return Task.FromResult(PreconditionResult.FromError(ErrorMessage ?? $"User requires guild role {RoleName}."));
+ }
+
+ return Task.FromResult(PreconditionResult.FromSuccess());
+ }
+ }
+}