Add module-level preconditions and precondition for individual permissions
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user