Parameter preconditions and typereader overriding
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace Discord.Commands
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public class OverrideTypeReaderAttribute : Attribute
|
||||
{
|
||||
private readonly TypeInfo _typeReaderTypeInfo = typeof(TypeReader).GetTypeInfo();
|
||||
|
||||
public Type TypeReader { get; }
|
||||
|
||||
public OverrideTypeReaderAttribute(Type overridenType)
|
||||
{
|
||||
if (!_typeReaderTypeInfo.IsAssignableFrom(overridenType.GetTypeInfo()))
|
||||
throw new ArgumentException($"{nameof(overridenType)} must inherit from {nameof(TypeReader)}");
|
||||
|
||||
TypeReader = overridenType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Commands
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)]
|
||||
public abstract class ParameterPreconditionAttribute : Attribute
|
||||
{
|
||||
public abstract Task<PreconditionResult> CheckPermissions(CommandContext context, ParameterInfo parameter, object value);
|
||||
}
|
||||
}
|
||||
@@ -182,6 +182,10 @@ namespace Discord.Commands
|
||||
// TODO: C#7 type switch
|
||||
if (attribute is SummaryAttribute)
|
||||
builder.Summary = (attribute as SummaryAttribute).Text;
|
||||
else if (attribute is OverrideTypeReaderAttribute)
|
||||
builder.TypeReader = service.GetTypeReader((attribute as OverrideTypeReaderAttribute).TypeReader);
|
||||
else if (attribute is ParameterPreconditionAttribute)
|
||||
builder.AddPrecondition(attribute as ParameterPreconditionAttribute);
|
||||
else if (attribute is ParamArrayAttribute)
|
||||
{
|
||||
builder.IsMultiple = true;
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord.Commands.Builders
|
||||
{
|
||||
public class ParameterBuilder
|
||||
{
|
||||
private readonly List<ParameterPreconditionAttribute> _preconditions;
|
||||
|
||||
public CommandBuilder Command { get; }
|
||||
public string Name { get; internal set; }
|
||||
public Type ParameterType { get; internal set; }
|
||||
@@ -16,16 +20,20 @@ namespace Discord.Commands.Builders
|
||||
public object DefaultValue { get; set; }
|
||||
public string Summary { get; set; }
|
||||
|
||||
public IReadOnlyList<ParameterPreconditionAttribute> Preconditions => _preconditions;
|
||||
|
||||
//Automatic
|
||||
internal ParameterBuilder(CommandBuilder command)
|
||||
{
|
||||
_preconditions = new List<ParameterPreconditionAttribute>();
|
||||
|
||||
Command = command;
|
||||
}
|
||||
//User-defined
|
||||
internal ParameterBuilder(CommandBuilder command, string name, Type type)
|
||||
: this(command)
|
||||
{
|
||||
Preconditions.NotNull(name, nameof(name));
|
||||
Discord.Preconditions.NotNull(name, nameof(name));
|
||||
|
||||
Name = name;
|
||||
SetType(type);
|
||||
@@ -49,7 +57,7 @@ namespace Discord.Commands.Builders
|
||||
}
|
||||
public ParameterBuilder WithDefault(object defaultValue)
|
||||
{
|
||||
DefaultValue = defaultValue;
|
||||
DefaultValue = defaultValue;
|
||||
return this;
|
||||
}
|
||||
public ParameterBuilder WithIsOptional(bool isOptional)
|
||||
@@ -68,6 +76,12 @@ namespace Discord.Commands.Builders
|
||||
return this;
|
||||
}
|
||||
|
||||
public ParameterBuilder AddPrecondition(ParameterPreconditionAttribute precondition)
|
||||
{
|
||||
_preconditions.Add(precondition);
|
||||
return this;
|
||||
}
|
||||
|
||||
internal ParameterInfo Build(CommandInfo info)
|
||||
{
|
||||
if (TypeReader == null)
|
||||
|
||||
@@ -135,9 +135,26 @@ namespace Discord.Commands
|
||||
if (map == null)
|
||||
map = DependencyMap.Empty;
|
||||
|
||||
object[] args = null;
|
||||
|
||||
try
|
||||
{
|
||||
args = GenerateArgs(argList, paramList);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ExecuteResult.FromError(ex);
|
||||
}
|
||||
|
||||
foreach (var parameter in Parameters)
|
||||
{
|
||||
var result = await parameter.CheckPreconditionsAsync(context, args, map).ConfigureAwait(false);
|
||||
if (!result.IsSuccess)
|
||||
return ExecuteResult.FromError(result);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var args = GenerateArgs(argList, paramList);
|
||||
switch (RunMode)
|
||||
{
|
||||
case RunMode.Sync: //Always sync
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Discord.Commands.Builders;
|
||||
@@ -10,6 +12,17 @@ namespace Discord.Commands
|
||||
{
|
||||
private readonly TypeReader _reader;
|
||||
|
||||
public CommandInfo Command { get; }
|
||||
public string Name { get; }
|
||||
public string Summary { get; }
|
||||
public bool IsOptional { get; }
|
||||
public bool IsRemainder { get; }
|
||||
public bool IsMultiple { get; }
|
||||
public Type Type { get; }
|
||||
public object DefaultValue { get; }
|
||||
|
||||
public IReadOnlyList<ParameterPreconditionAttribute> Preconditions { get; }
|
||||
|
||||
internal ParameterInfo(ParameterBuilder builder, CommandInfo command, CommandService service)
|
||||
{
|
||||
Command = command;
|
||||
@@ -23,17 +36,30 @@ namespace Discord.Commands
|
||||
Type = builder.ParameterType;
|
||||
DefaultValue = builder.DefaultValue;
|
||||
|
||||
Preconditions = builder.Preconditions.ToImmutableArray();
|
||||
|
||||
_reader = builder.TypeReader;
|
||||
}
|
||||
|
||||
public CommandInfo Command { get; }
|
||||
public string Name { get; }
|
||||
public string Summary { get; }
|
||||
public bool IsOptional { get; }
|
||||
public bool IsRemainder { get; }
|
||||
public bool IsMultiple { get; }
|
||||
public Type Type { get; }
|
||||
public object DefaultValue { get; }
|
||||
public async Task<PreconditionResult> CheckPreconditionsAsync(CommandContext context, object[] args, IDependencyMap map = null)
|
||||
{
|
||||
if (map == null)
|
||||
map = DependencyMap.Empty;
|
||||
|
||||
int position = 0;
|
||||
for(position = 0; position < Command.Parameters.Count; position++)
|
||||
if (Command.Parameters[position] == this)
|
||||
break;
|
||||
|
||||
foreach (var precondition in Preconditions)
|
||||
{
|
||||
var result = await precondition.CheckPermissions(context, this, args[position]).ConfigureAwait(false);
|
||||
if (!result.IsSuccess)
|
||||
return result;
|
||||
}
|
||||
|
||||
return PreconditionResult.FromSuccess();
|
||||
}
|
||||
|
||||
public async Task<TypeReaderResult> Parse(CommandContext context, string input)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user