| @@ -5,6 +5,7 @@ using System.Threading.Tasks; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = true)] | |||||
| public abstract class PreconditionAttribute : Attribute | public abstract class PreconditionAttribute : Attribute | ||||
| { | { | ||||
| public abstract Task<PreconditionResult> CheckPermissions(IMessage context); | public abstract Task<PreconditionResult> CheckPermissions(IMessage context); | ||||
| @@ -5,6 +5,7 @@ using System.Threading.Tasks; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | |||||
| public class RequireDMAttribute : PreconditionAttribute | public class RequireDMAttribute : PreconditionAttribute | ||||
| { | { | ||||
| public override Task<PreconditionResult> CheckPermissions(IMessage context) | public override Task<PreconditionResult> CheckPermissions(IMessage context) | ||||
| @@ -5,6 +5,7 @@ using System.Threading.Tasks; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | |||||
| public class RequireGuildAttribute : PreconditionAttribute | public class RequireGuildAttribute : PreconditionAttribute | ||||
| { | { | ||||
| public override Task<PreconditionResult> CheckPermissions(IMessage context) | public override Task<PreconditionResult> CheckPermissions(IMessage context) | ||||
| @@ -0,0 +1,54 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Threading.Tasks; | |||||
| namespace Discord.Commands.Attributes.Preconditions | |||||
| { | |||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | |||||
| public class RequirePermission : RequireGuildAttribute | |||||
| { | |||||
| public GuildPermission? GuildPermission { get; set; } | |||||
| public ChannelPermission? ChannelPermission { get; set; } | |||||
| public RequirePermission(GuildPermission permission) | |||||
| { | |||||
| GuildPermission = permission; | |||||
| ChannelPermission = null; | |||||
| } | |||||
| public RequirePermission(ChannelPermission permission) | |||||
| { | |||||
| ChannelPermission = permission; | |||||
| GuildPermission = null; | |||||
| } | |||||
| public override async Task<PreconditionResult> CheckPermissions(IMessage context) | |||||
| { | |||||
| var result = await base.CheckPermissions(context).ConfigureAwait(false); | |||||
| if (!result.IsSuccess) | |||||
| return result; | |||||
| var author = context.Author as IGuildUser; | |||||
| if (GuildPermission.HasValue) | |||||
| { | |||||
| var guildPerms = author.GuildPermissions.ToList(); | |||||
| if (!guildPerms.Contains(GuildPermission.Value)) | |||||
| return PreconditionResult.FromError($"User is missing guild permission {GuildPermission.Value}"); | |||||
| } | |||||
| if (ChannelPermission.HasValue) | |||||
| { | |||||
| var channel = context.Channel as IGuildChannel; | |||||
| var channelPerms = author.GetPermissions(channel).ToList(); | |||||
| if (!channelPerms.Contains(ChannelPermission.Value)) | |||||
| return PreconditionResult.FromError($"User is missing channel permission {ChannelPermission.Value}"); | |||||
| } | |||||
| return PreconditionResult.FromSuccess(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -5,6 +5,7 @@ using System.Threading.Tasks; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] | |||||
| public class RequireRoleAttribute : RequireGuildAttribute | public class RequireRoleAttribute : RequireGuildAttribute | ||||
| { | { | ||||
| public string Role { get; set; } | public string Role { get; set; } | ||||
| @@ -44,9 +44,16 @@ namespace Discord.Commands | |||||
| public async Task<PreconditionResult> CheckPreconditions(IMessage context) | public async Task<PreconditionResult> CheckPreconditions(IMessage context) | ||||
| { | { | ||||
| foreach (PreconditionAttribute permission in Preconditions) | |||||
| foreach (PreconditionAttribute precondition in Module.Preconditions) | |||||
| { | { | ||||
| var result = await permission.CheckPermissions(context).ConfigureAwait(false); | |||||
| var result = await precondition.CheckPermissions(context).ConfigureAwait(false); | |||||
| if (!result.IsSuccess) | |||||
| return result; | |||||
| } | |||||
| foreach (PreconditionAttribute precondition in Preconditions) | |||||
| { | |||||
| var result = await precondition.CheckPermissions(context).ConfigureAwait(false); | |||||
| if (!result.IsSuccess) | if (!result.IsSuccess) | ||||
| return result; | return result; | ||||
| } | } | ||||
| @@ -1,4 +1,5 @@ | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | |||||
| using System.Diagnostics; | using System.Diagnostics; | ||||
| using System.Reflection; | using System.Reflection; | ||||
| @@ -12,6 +13,8 @@ namespace Discord.Commands | |||||
| public IEnumerable<Command> Commands { get; } | public IEnumerable<Command> Commands { get; } | ||||
| internal object Instance { get; } | internal object Instance { get; } | ||||
| public IReadOnlyList<PreconditionAttribute> Preconditions { get; } | |||||
| internal Module(CommandService service, object instance, ModuleAttribute moduleAttr, TypeInfo typeInfo) | internal Module(CommandService service, object instance, ModuleAttribute moduleAttr, TypeInfo typeInfo) | ||||
| { | { | ||||
| Service = service; | Service = service; | ||||
| @@ -21,6 +24,8 @@ namespace Discord.Commands | |||||
| List<Command> commands = new List<Command>(); | List<Command> commands = new List<Command>(); | ||||
| SearchClass(instance, commands, typeInfo, moduleAttr.Prefix ?? ""); | SearchClass(instance, commands, typeInfo, moduleAttr.Prefix ?? ""); | ||||
| Commands = commands; | Commands = commands; | ||||
| Preconditions = BuildPreconditions(typeInfo); | |||||
| } | } | ||||
| private void SearchClass(object instance, List<Command> commands, TypeInfo typeInfo, string groupPrefix) | private void SearchClass(object instance, List<Command> commands, TypeInfo typeInfo, string groupPrefix) | ||||
| @@ -48,6 +53,11 @@ namespace Discord.Commands | |||||
| } | } | ||||
| } | } | ||||
| private IReadOnlyList<PreconditionAttribute> BuildPreconditions(TypeInfo typeInfo) | |||||
| { | |||||
| return typeInfo.GetCustomAttributes<PreconditionAttribute>().ToImmutableArray(); | |||||
| } | |||||
| public override string ToString() => Name; | public override string ToString() => Name; | ||||
| private string DebuggerDisplay => Name; | private string DebuggerDisplay => Name; | ||||
| } | } | ||||