| @@ -7,6 +7,7 @@ namespace Discord.Commands | |||||
| { | { | ||||
| public string Text { get; } | public string Text { get; } | ||||
| public RunMode RunMode { get; set; } = RunMode.Default; | public RunMode RunMode { get; set; } = RunMode.Default; | ||||
| public PreconditionsMode PreconditionsMode { get; set; } = PreconditionsMode.Default; | |||||
| public CommandAttribute() | public CommandAttribute() | ||||
| { | { | ||||
| @@ -20,6 +20,7 @@ namespace Discord.Commands.Builders | |||||
| public string Remarks { get; set; } | public string Remarks { get; set; } | ||||
| public string PrimaryAlias { get; set; } | public string PrimaryAlias { get; set; } | ||||
| public RunMode RunMode { get; set; } | public RunMode RunMode { get; set; } | ||||
| public PreconditionsMode PreconditionsMode { get; set; } | |||||
| public int Priority { get; set; } | public int Priority { get; set; } | ||||
| public IReadOnlyList<PreconditionAttribute> Preconditions => _preconditions; | public IReadOnlyList<PreconditionAttribute> Preconditions => _preconditions; | ||||
| @@ -67,6 +68,11 @@ namespace Discord.Commands.Builders | |||||
| RunMode = runMode; | RunMode = runMode; | ||||
| return this; | return this; | ||||
| } | } | ||||
| public CommandBuilder WithPreconditionsMode(PreconditionsMode preconditionsMode) | |||||
| { | |||||
| PreconditionsMode = preconditionsMode; | |||||
| return this; | |||||
| } | |||||
| public CommandBuilder WithPriority(int priority) | public CommandBuilder WithPriority(int priority) | ||||
| { | { | ||||
| Priority = priority; | Priority = priority; | ||||
| @@ -128,26 +128,33 @@ namespace Discord.Commands | |||||
| foreach (var attribute in attributes) | 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) | if (builder.Name == null) | ||||
| @@ -195,24 +202,27 @@ namespace Discord.Commands | |||||
| foreach (var attribute in attributes) | 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 bool _caseSensitive, _throwOnError; | ||||
| internal readonly char _separatorChar; | internal readonly char _separatorChar; | ||||
| internal readonly RunMode _defaultRunMode; | internal readonly RunMode _defaultRunMode; | ||||
| internal readonly PreconditionsMode _defaultPreconditionsMode; | |||||
| internal readonly Logger _cmdLogger; | internal readonly Logger _cmdLogger; | ||||
| internal readonly LogManager _logManager; | internal readonly LogManager _logManager; | ||||
| @@ -44,6 +45,9 @@ namespace Discord.Commands | |||||
| _defaultRunMode = config.DefaultRunMode; | _defaultRunMode = config.DefaultRunMode; | ||||
| if (_defaultRunMode == RunMode.Default) | if (_defaultRunMode == RunMode.Default) | ||||
| throw new InvalidOperationException("The default run mode cannot be set to 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 = new LogManager(config.LogLevel); | ||||
| _logManager.Message += async msg => await _logEvent.InvokeAsync(msg).ConfigureAwait(false); | _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> | /// <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; | 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; } = ' '; | public char SeparatorChar { get; set; } = ' '; | ||||
| /// <summary> Should commands be case-sensitive? </summary> | /// <summary> Should commands be case-sensitive? </summary> | ||||
| public bool CaseSensitiveCommands { get; set; } = false; | public bool CaseSensitiveCommands { get; set; } = false; | ||||
| @@ -27,6 +27,7 @@ namespace Discord.Commands | |||||
| public int Priority { get; } | public int Priority { get; } | ||||
| public bool HasVarArgs { get; } | public bool HasVarArgs { get; } | ||||
| public RunMode RunMode { get; } | public RunMode RunMode { get; } | ||||
| public PreconditionsMode PreconditionsMode { get; } | |||||
| public IReadOnlyList<string> Aliases { get; } | public IReadOnlyList<string> Aliases { get; } | ||||
| public IReadOnlyList<ParameterInfo> Parameters { get; } | public IReadOnlyList<ParameterInfo> Parameters { get; } | ||||
| @@ -41,6 +42,7 @@ namespace Discord.Commands | |||||
| Remarks = builder.Remarks; | Remarks = builder.Remarks; | ||||
| RunMode = (builder.RunMode == RunMode.Default ? service._defaultRunMode : builder.RunMode); | RunMode = (builder.RunMode == RunMode.Default ? service._defaultRunMode : builder.RunMode); | ||||
| PreconditionsMode = (builder.PreconditionsMode == PreconditionsMode.Default ? service._defaultPreconditionsMode : builder.PreconditionsMode); | |||||
| Priority = builder.Priority; | Priority = builder.Priority; | ||||
| Aliases = module.Aliases | Aliases = module.Aliases | ||||
| @@ -75,11 +77,23 @@ namespace Discord.Commands | |||||
| return result; | 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(); | return PreconditionResult.FromSuccess(); | ||||
| @@ -0,0 +1,9 @@ | |||||
| namespace Discord.Commands | |||||
| { | |||||
| public enum PreconditionsMode | |||||
| { | |||||
| Default, | |||||
| RequireAny, | |||||
| RequireAll | |||||
| } | |||||
| } | |||||