@@ -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; | ||||
} | } | ||||