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