| @@ -3,15 +3,24 @@ using System; | |||
| namespace Discord.Commands | |||
| { | |||
| /// <summary> Provides aliases for a command. </summary> | |||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] | |||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple=true)] | |||
| public class AliasAttribute : Attribute | |||
| { | |||
| /// <summary> The type to be applied to this alias group <summary> | |||
| public AliasType Type { get; } | |||
| /// <summary> The aliases which have been defined for the command. </summary> | |||
| public string[] Aliases { get; } | |||
| /// <summary> Creates a new <see cref="AliasAttribute"/> with the given aliases. </summary> | |||
| public AliasAttribute(params string[] aliases) | |||
| { | |||
| Type = AliasType.Relative; | |||
| Aliases = aliases; | |||
| } | |||
| /// <summary> Creates a new <see cref="AliasAttribute"/> with the given aliases. </summary> | |||
| public AliasAttribute(AliasType type, params string[] aliases) | |||
| { | |||
| Type = type; | |||
| Aliases = aliases; | |||
| } | |||
| } | |||
| @@ -0,0 +1,8 @@ | |||
| namespace Discord.Commands | |||
| { | |||
| public enum AliasType | |||
| { | |||
| Relative, | |||
| Absolute | |||
| } | |||
| } | |||
| @@ -1,9 +1,9 @@ | |||
| using System; | |||
| namespace Discord.Commands { | |||
| [AttributeUsage(AttributeTargets.Property)] | |||
| public class DontInjectAttribute : Attribute { | |||
| } | |||
| namespace Discord.Commands | |||
| { | |||
| [AttributeUsage(AttributeTargets.Property)] | |||
| public class DontInjectAttribute : Attribute | |||
| { | |||
| } | |||
| } | |||
| @@ -9,7 +9,7 @@ namespace Discord.Commands.Builders | |||
| { | |||
| private readonly List<PreconditionAttribute> _preconditions; | |||
| private readonly List<ParameterBuilder> _parameters; | |||
| private readonly List<string> _aliases; | |||
| private readonly List<string> _relativeAliases, _absoluteAliases; | |||
| public ModuleBuilder Module { get; } | |||
| internal Func<ICommandContext, object[], IDependencyMap, Task> Callback { get; set; } | |||
| @@ -22,7 +22,8 @@ namespace Discord.Commands.Builders | |||
| public IReadOnlyList<PreconditionAttribute> Preconditions => _preconditions; | |||
| public IReadOnlyList<ParameterBuilder> Parameters => _parameters; | |||
| public IReadOnlyList<string> Aliases => _aliases; | |||
| public IReadOnlyList<string> RelativeAliases => _relativeAliases; | |||
| public IReadOnlyList<string> AbsoluteAliases => _absoluteAliases; | |||
| //Automatic | |||
| internal CommandBuilder(ModuleBuilder module) | |||
| @@ -31,7 +32,8 @@ namespace Discord.Commands.Builders | |||
| _preconditions = new List<PreconditionAttribute>(); | |||
| _parameters = new List<ParameterBuilder>(); | |||
| _aliases = new List<string>(); | |||
| _relativeAliases = new List<string>(); | |||
| _absoluteAliases = new List<string>(); | |||
| } | |||
| //User-defined | |||
| internal CommandBuilder(ModuleBuilder module, string primaryAlias, Func<ICommandContext, object[], IDependencyMap, Task> callback) | |||
| @@ -41,7 +43,7 @@ namespace Discord.Commands.Builders | |||
| Discord.Preconditions.NotNull(callback, nameof(callback)); | |||
| Callback = callback; | |||
| _aliases.Add(primaryAlias); | |||
| _relativeAliases.Add(primaryAlias); | |||
| } | |||
| public CommandBuilder WithName(string name) | |||
| @@ -70,13 +72,22 @@ namespace Discord.Commands.Builders | |||
| return this; | |||
| } | |||
| public CommandBuilder AddAliases(params string[] aliases) | |||
| public CommandBuilder AddAliases(AliasType type, params string[] aliases) | |||
| { | |||
| for (int i = 0; i < aliases.Length; i++) | |||
| { | |||
| var alias = aliases[i] ?? ""; | |||
| if (!_aliases.Contains(alias)) | |||
| _aliases.Add(alias); | |||
| switch (type) | |||
| { | |||
| case AliasType.Relative: | |||
| if (!_relativeAliases.Contains(alias)) | |||
| _relativeAliases.Add(alias); | |||
| break; | |||
| case AliasType.Absolute: | |||
| if (!_absoluteAliases.Contains(alias)) | |||
| _absoluteAliases.Add(alias); | |||
| break; | |||
| } | |||
| } | |||
| return this; | |||
| } | |||
| @@ -111,7 +122,7 @@ namespace Discord.Commands.Builders | |||
| { | |||
| //Default name to first alias | |||
| if (Name == null) | |||
| Name = _aliases[0]; | |||
| Name = _relativeAliases[0]; | |||
| if (_parameters.Count > 0) | |||
| { | |||
| @@ -9,7 +9,7 @@ namespace Discord.Commands.Builders | |||
| private readonly List<CommandBuilder> _commands; | |||
| private readonly List<ModuleBuilder> _submodules; | |||
| private readonly List<PreconditionAttribute> _preconditions; | |||
| private readonly List<string> _aliases; | |||
| private readonly List<string> _relativeAliases, _absoluteAliases; | |||
| public CommandService Service { get; } | |||
| public ModuleBuilder Parent { get; } | |||
| @@ -20,7 +20,8 @@ namespace Discord.Commands.Builders | |||
| public IReadOnlyList<CommandBuilder> Commands => _commands; | |||
| public IReadOnlyList<ModuleBuilder> Modules => _submodules; | |||
| public IReadOnlyList<PreconditionAttribute> Preconditions => _preconditions; | |||
| public IReadOnlyList<string> Aliases => _aliases; | |||
| public IReadOnlyList<string> RelativeAliases => _relativeAliases; | |||
| public IReadOnlyList<string> AbsoluteAliases => _absoluteAliases; | |||
| //Automatic | |||
| internal ModuleBuilder(CommandService service, ModuleBuilder parent) | |||
| @@ -31,7 +32,8 @@ namespace Discord.Commands.Builders | |||
| _commands = new List<CommandBuilder>(); | |||
| _submodules = new List<ModuleBuilder>(); | |||
| _preconditions = new List<PreconditionAttribute>(); | |||
| _aliases = new List<string>(); | |||
| _relativeAliases = new List<string>(); | |||
| _absoluteAliases = new List<string>(); | |||
| } | |||
| //User-defined | |||
| internal ModuleBuilder(CommandService service, ModuleBuilder parent, string primaryAlias) | |||
| @@ -39,7 +41,7 @@ namespace Discord.Commands.Builders | |||
| { | |||
| Discord.Preconditions.NotNull(primaryAlias, nameof(primaryAlias)); | |||
| _aliases = new List<string> { primaryAlias }; | |||
| _relativeAliases = new List<string> { primaryAlias }; | |||
| } | |||
| public ModuleBuilder WithName(string name) | |||
| @@ -58,13 +60,22 @@ namespace Discord.Commands.Builders | |||
| return this; | |||
| } | |||
| public ModuleBuilder AddAliases(params string[] aliases) | |||
| public ModuleBuilder AddAliases(AliasType type, params string[] aliases) | |||
| { | |||
| for (int i = 0; i < aliases.Length; i++) | |||
| { | |||
| var alias = aliases[i] ?? ""; | |||
| if (!_aliases.Contains(alias)) | |||
| _aliases.Add(alias); | |||
| switch (type) | |||
| { | |||
| case AliasType.Relative: | |||
| if (!_relativeAliases.Contains(alias)) | |||
| _relativeAliases.Add(alias); | |||
| break; | |||
| case AliasType.Absolute: | |||
| if (!_absoluteAliases.Contains(alias)) | |||
| _absoluteAliases.Add(alias); | |||
| break; | |||
| } | |||
| } | |||
| return this; | |||
| } | |||
| @@ -106,7 +117,7 @@ namespace Discord.Commands.Builders | |||
| { | |||
| //Default name to first alias | |||
| if (Name == null) | |||
| Name = _aliases[0]; | |||
| Name = _relativeAliases[0]; | |||
| return new ModuleInfo(this, service, parent); | |||
| } | |||
| @@ -89,20 +89,23 @@ namespace Discord.Commands | |||
| else if (attribute is RemarksAttribute) | |||
| builder.Remarks = (attribute as RemarksAttribute).Text; | |||
| else if (attribute is AliasAttribute) | |||
| builder.AddAliases((attribute as AliasAttribute).Aliases); | |||
| { | |||
| var aliasAttr = attribute as AliasAttribute; | |||
| builder.AddAliases(aliasAttr.Type, aliasAttr.Aliases); | |||
| } | |||
| else if (attribute is GroupAttribute) | |||
| { | |||
| var groupAttr = attribute as GroupAttribute; | |||
| builder.Name = builder.Name ?? groupAttr.Prefix; | |||
| builder.AddAliases(groupAttr.Prefix); | |||
| builder.AddAliases(AliasType.Relative, groupAttr.Prefix); | |||
| } | |||
| else if (attribute is PreconditionAttribute) | |||
| builder.AddPrecondition(attribute as PreconditionAttribute); | |||
| } | |||
| //Check for unspecified info | |||
| if (builder.Aliases.Count == 0) | |||
| builder.AddAliases(""); | |||
| if (builder.RelativeAliases.Count == 0) | |||
| builder.AddAliases(AliasType.Relative, ""); | |||
| if (builder.Name == null) | |||
| builder.Name = typeInfo.Name; | |||
| @@ -127,7 +130,7 @@ namespace Discord.Commands | |||
| if (attribute is CommandAttribute) | |||
| { | |||
| var cmdAttr = attribute as CommandAttribute; | |||
| builder.AddAliases(cmdAttr.Text); | |||
| builder.AddAliases(AliasType.Relative, cmdAttr.Text); | |||
| builder.RunMode = cmdAttr.RunMode; | |||
| builder.Name = builder.Name ?? cmdAttr.Text; | |||
| } | |||
| @@ -140,7 +143,10 @@ namespace Discord.Commands | |||
| else if (attribute is RemarksAttribute) | |||
| builder.Remarks = (attribute as RemarksAttribute).Text; | |||
| else if (attribute is AliasAttribute) | |||
| builder.AddAliases((attribute as AliasAttribute).Aliases); | |||
| { | |||
| var aliasAttr = attribute as AliasAttribute; | |||
| builder.AddAliases(aliasAttr.Type, aliasAttr.Aliases); | |||
| } | |||
| else if (attribute is PreconditionAttribute) | |||
| builder.AddPrecondition(attribute as PreconditionAttribute); | |||
| } | |||
| @@ -43,7 +43,7 @@ namespace Discord.Commands | |||
| Priority = builder.Priority; | |||
| Aliases = module.Aliases | |||
| .Permutate(builder.Aliases, (first, second) => | |||
| .Permutate(builder.RelativeAliases, (first, second) => | |||
| { | |||
| if (first == "") | |||
| return second; | |||
| @@ -52,6 +52,7 @@ namespace Discord.Commands | |||
| else | |||
| return first + service._separatorChar + second; | |||
| }) | |||
| .Concat(builder.AbsoluteAliases) | |||
| .Select(x => service._caseSensitive ? x : x.ToLowerInvariant()) | |||
| .ToImmutableArray(); | |||
| @@ -38,28 +38,33 @@ namespace Discord.Commands | |||
| private static IEnumerable<string> BuildAliases(ModuleBuilder builder, CommandService service) | |||
| { | |||
| var result = builder.Aliases.ToList(); | |||
| var builderQueue = new Queue<ModuleBuilder>(); | |||
| var result = builder.RelativeAliases.ToList(); | |||
| var builderQueue = new Stack<ModuleBuilder>(); | |||
| var parent = builder; | |||
| while ((parent = parent.Parent) != null) | |||
| builderQueue.Enqueue(parent); | |||
| builderQueue.Push(parent); | |||
| while (builderQueue.Count > 0) | |||
| { | |||
| var level = builderQueue.Dequeue(); | |||
| var level = builderQueue.Pop(); | |||
| // permute in reverse because we want to *prefix* our aliases | |||
| result = level.Aliases.Permutate(result, (first, second) => | |||
| { | |||
| if (first == "") | |||
| return second; | |||
| else if (second == "") | |||
| return first; | |||
| else | |||
| return first + service._separatorChar + second; | |||
| }).ToList(); | |||
| result = result | |||
| .Permutate(level.RelativeAliases, (first, second) => | |||
| { | |||
| if (first == "") | |||
| return second; | |||
| else if (second == "") | |||
| return first; | |||
| else | |||
| return first + service._separatorChar + second; | |||
| }) | |||
| .Concat(level.AbsoluteAliases) | |||
| .ToList(); | |||
| } | |||
| result = result.Concat(builder.AbsoluteAliases).ToList(); | |||
| return result; | |||
| } | |||
| @@ -13,7 +13,6 @@ namespace Discord.WebSocket | |||
| public override ushort DiscriminatorValue { get; internal set; } | |||
| public override string AvatarId { get; internal set; } | |||
| internal override SocketPresence Presence { get { return new SocketPresence(UserStatus.Offline, null); } set { } } | |||
| internal override SocketGlobalUser GlobalUser { get { throw new NotSupportedException(); } } | |||
| internal SocketSimpleUser(DiscordSocketClient discord, ulong id) | |||