@@ -7,6 +7,7 @@ namespace Discord.Commands | |||
{ | |||
public string Text { get; } | |||
public RunMode RunMode { get; set; } = RunMode.Default; | |||
public PreconditionsMode PreconditionsMode { get; set; } = PreconditionsMode.Default; | |||
public CommandAttribute() | |||
{ | |||
@@ -20,6 +20,7 @@ namespace Discord.Commands.Builders | |||
public string Remarks { get; set; } | |||
public string PrimaryAlias { get; set; } | |||
public RunMode RunMode { get; set; } | |||
public PreconditionsMode PreconditionsMode { get; set; } | |||
public int Priority { get; set; } | |||
public IReadOnlyList<PreconditionAttribute> Preconditions => _preconditions; | |||
@@ -67,6 +68,11 @@ namespace Discord.Commands.Builders | |||
RunMode = runMode; | |||
return this; | |||
} | |||
public CommandBuilder WithPreconditionsMode(PreconditionsMode preconditionsMode) | |||
{ | |||
PreconditionsMode = preconditionsMode; | |||
return this; | |||
} | |||
public CommandBuilder WithPriority(int priority) | |||
{ | |||
Priority = priority; | |||
@@ -128,26 +128,33 @@ namespace Discord.Commands | |||
foreach (var attribute in attributes) | |||
{ | |||
// TODO: C#7 type switch | |||
if (attribute is CommandAttribute) | |||
switch (attribute) | |||
{ | |||
var cmdAttr = attribute as CommandAttribute; | |||
builder.AddAliases(cmdAttr.Text); | |||
builder.RunMode = cmdAttr.RunMode; | |||
builder.Name = builder.Name ?? cmdAttr.Text; | |||
case CommandAttribute cmdAttr: | |||
builder.AddAliases(cmdAttr.Text); | |||
builder.RunMode = cmdAttr.RunMode; | |||
builder.PreconditionsMode = cmdAttr.PreconditionsMode; | |||
builder.Name = builder.Name ?? cmdAttr.Text; | |||
break; | |||
case NameAttribute nameAttr: | |||
builder.Name = nameAttr.Text; | |||
break; | |||
case PriorityAttribute priorityAttr: | |||
builder.Priority = priorityAttr.Priority; | |||
break; | |||
case SummaryAttribute summaryAttr: | |||
builder.Summary = summaryAttr.Text; | |||
break; | |||
case RemarksAttribute remarksAttr: | |||
builder.Remarks = remarksAttr.Text; | |||
break; | |||
case AliasAttribute aliasAttr: | |||
builder.AddAliases(aliasAttr.Aliases); | |||
break; | |||
case PreconditionAttribute preconditionAttr: | |||
builder.AddPrecondition(preconditionAttr); | |||
break; | |||
} | |||
else if (attribute is NameAttribute) | |||
builder.Name = (attribute as NameAttribute).Text; | |||
else if (attribute is PriorityAttribute) | |||
builder.Priority = (attribute as PriorityAttribute).Priority; | |||
else if (attribute is SummaryAttribute) | |||
builder.Summary = (attribute as SummaryAttribute).Text; | |||
else if (attribute is RemarksAttribute) | |||
builder.Remarks = (attribute as RemarksAttribute).Text; | |||
else if (attribute is AliasAttribute) | |||
builder.AddAliases((attribute as AliasAttribute).Aliases); | |||
else if (attribute is PreconditionAttribute) | |||
builder.AddPrecondition(attribute as PreconditionAttribute); | |||
} | |||
if (builder.Name == null) | |||
@@ -195,24 +202,27 @@ namespace Discord.Commands | |||
foreach (var attribute in attributes) | |||
{ | |||
// TODO: C#7 type switch | |||
if (attribute is SummaryAttribute) | |||
builder.Summary = (attribute as SummaryAttribute).Text; | |||
else if (attribute is OverrideTypeReaderAttribute) | |||
builder.TypeReader = GetTypeReader(service, paramType, (attribute as OverrideTypeReaderAttribute).TypeReader); | |||
else if (attribute is ParameterPreconditionAttribute) | |||
builder.AddPrecondition(attribute as ParameterPreconditionAttribute); | |||
else if (attribute is ParamArrayAttribute) | |||
{ | |||
builder.IsMultiple = true; | |||
paramType = paramType.GetElementType(); | |||
} | |||
else if (attribute is RemainderAttribute) | |||
switch (attribute) | |||
{ | |||
if (position != count-1) | |||
throw new InvalidOperationException("Remainder parameters must be the last parameter in a command."); | |||
builder.IsRemainder = true; | |||
case SummaryAttribute summaryAttr: | |||
builder.Summary = summaryAttr.Text; | |||
break; | |||
case OverrideTypeReaderAttribute overrideTypeReaderAttr: | |||
builder.TypeReader = GetTypeReader(service, paramType, | |||
overrideTypeReaderAttr.TypeReader); | |||
break; | |||
case ParameterPreconditionAttribute parameterPreconditionAttr: | |||
builder.AddPrecondition(parameterPreconditionAttr); | |||
break; | |||
case ParamArrayAttribute paramArrayAttr: | |||
builder.IsMultiple = true; | |||
paramType = paramType.GetElementType(); | |||
break; | |||
case RemainderAttribute remainderAttr: | |||
if (position != count - 1) | |||
throw new InvalidOperationException("Remainder parameters must be the last parameter in a command."); | |||
builder.IsRemainder = true; | |||
break; | |||
} | |||
} | |||
@@ -28,6 +28,7 @@ namespace Discord.Commands | |||
internal readonly bool _caseSensitive, _throwOnError; | |||
internal readonly char _separatorChar; | |||
internal readonly RunMode _defaultRunMode; | |||
internal readonly PreconditionsMode _defaultPreconditionsMode; | |||
internal readonly Logger _cmdLogger; | |||
internal readonly LogManager _logManager; | |||
@@ -44,6 +45,9 @@ namespace Discord.Commands | |||
_defaultRunMode = config.DefaultRunMode; | |||
if (_defaultRunMode == RunMode.Default) | |||
throw new InvalidOperationException("The default run mode cannot be set to Default."); | |||
_defaultPreconditionsMode = config.DefaultPreconditionsMode; | |||
if (_defaultPreconditionsMode == PreconditionsMode.Default) | |||
throw new InvalidOperationException("The default preconditions mode cannot be set to Default."); | |||
_logManager = new LogManager(config.LogLevel); | |||
_logManager.Message += async msg => await _logEvent.InvokeAsync(msg).ConfigureAwait(false); | |||
@@ -5,6 +5,9 @@ | |||
/// <summary> The default RunMode commands should have, if one is not specified on the Command attribute or builder. </summary> | |||
public RunMode DefaultRunMode { get; set; } = RunMode.Sync; | |||
/// <summary> The default PreconditionsMode commands should have, if one is not specified on the Command attribute or builder. </summary> | |||
public PreconditionsMode DefaultPreconditionsMode { get; set; } = PreconditionsMode.RequireAll; | |||
public char SeparatorChar { get; set; } = ' '; | |||
/// <summary> Should commands be case-sensitive? </summary> | |||
public bool CaseSensitiveCommands { get; set; } = false; | |||
@@ -27,6 +27,7 @@ namespace Discord.Commands | |||
public int Priority { get; } | |||
public bool HasVarArgs { get; } | |||
public RunMode RunMode { get; } | |||
public PreconditionsMode PreconditionsMode { get; } | |||
public IReadOnlyList<string> Aliases { get; } | |||
public IReadOnlyList<ParameterInfo> Parameters { get; } | |||
@@ -41,6 +42,7 @@ namespace Discord.Commands | |||
Remarks = builder.Remarks; | |||
RunMode = (builder.RunMode == RunMode.Default ? service._defaultRunMode : builder.RunMode); | |||
PreconditionsMode = (builder.PreconditionsMode == PreconditionsMode.Default ? service._defaultPreconditionsMode : builder.PreconditionsMode); | |||
Priority = builder.Priority; | |||
Aliases = module.Aliases | |||
@@ -75,11 +77,23 @@ namespace Discord.Commands | |||
return result; | |||
} | |||
foreach (PreconditionAttribute precondition in Preconditions) | |||
if (PreconditionsMode == PreconditionsMode.RequireAll) | |||
{ | |||
var result = await precondition.CheckPermissions(context, this, services).ConfigureAwait(false); | |||
if (!result.IsSuccess) | |||
return result; | |||
foreach (PreconditionAttribute precondition in Preconditions) | |||
{ | |||
var result = await precondition.CheckPermissions(context, this, services).ConfigureAwait(false); | |||
if (!result.IsSuccess) | |||
return result; | |||
} | |||
} | |||
else | |||
{ | |||
foreach (PreconditionAttribute precondition in Preconditions) | |||
{ | |||
var result = await precondition.CheckPermissions(context, this, services).ConfigureAwait(false); | |||
if (result.IsSuccess) | |||
return result; | |||
} | |||
} | |||
return PreconditionResult.FromSuccess(); | |||
@@ -0,0 +1,9 @@ | |||
namespace Discord.Commands | |||
{ | |||
public enum PreconditionsMode | |||
{ | |||
Default, | |||
RequireAny, | |||
RequireAll | |||
} | |||
} |