| @@ -18,7 +18,7 @@ namespace Discord.Commands | |||||
| public OverrideTypeReaderAttribute(Type overridenTypeReader) | public OverrideTypeReaderAttribute(Type overridenTypeReader) | ||||
| { | { | ||||
| if (!_typeReaderTypeInfo.IsAssignableFrom(overridenTypeReader.GetTypeInfo())) | if (!_typeReaderTypeInfo.IsAssignableFrom(overridenTypeReader.GetTypeInfo())) | ||||
| throw new ArgumentException($"{nameof(overridenTypeReader)} must inherit from {nameof(TypeReader)}"); | |||||
| throw new ArgumentException($"{nameof(overridenTypeReader)} must inherit from {nameof(TypeReader)}."); | |||||
| TypeReader = overridenTypeReader; | TypeReader = overridenTypeReader; | ||||
| } | } | ||||
| @@ -9,7 +9,7 @@ namespace Discord.Commands | |||||
| { | { | ||||
| /// <summary> Specify a group that this precondition belongs to. </summary> | /// <summary> Specify a group that this precondition belongs to. </summary> | ||||
| /// <remarks> | /// <remarks> | ||||
| /// Preconditions of the same group require only one | |||||
| /// <see cref="Preconditions"/> of the same group require only one | |||||
| /// of the preconditions to pass in order to be successful (A || B). | /// of the preconditions to pass in order to be successful (A || B). | ||||
| /// Specifying <see cref="Group"/> = <see langword="null"/> | /// Specifying <see cref="Group"/> = <see langword="null"/> | ||||
| /// or not at all will require *all* preconditions to pass, just like normal (A && B). | /// or not at all will require *all* preconditions to pass, just like normal (A && B). | ||||
| @@ -50,9 +50,9 @@ namespace Discord.Commands | |||||
| if (GuildPermission.HasValue) | if (GuildPermission.HasValue) | ||||
| { | { | ||||
| if (guildUser == null) | if (guildUser == null) | ||||
| return PreconditionResult.FromError("Command must be used in a guild channel"); | |||||
| return PreconditionResult.FromError("Command must be used in a guild channel."); | |||||
| if (!guildUser.GuildPermissions.Has(GuildPermission.Value)) | if (!guildUser.GuildPermissions.Has(GuildPermission.Value)) | ||||
| return PreconditionResult.FromError($"Bot requires guild permission {GuildPermission.Value}"); | |||||
| return PreconditionResult.FromError($"Bot requires guild permission {GuildPermission.Value}."); | |||||
| } | } | ||||
| if (ChannelPermission.HasValue) | if (ChannelPermission.HasValue) | ||||
| @@ -64,7 +64,7 @@ namespace Discord.Commands | |||||
| perms = ChannelPermissions.All(context.Channel); | perms = ChannelPermissions.All(context.Channel); | ||||
| if (!perms.Has(ChannelPermission.Value)) | if (!perms.Has(ChannelPermission.Value)) | ||||
| return PreconditionResult.FromError($"Bot requires channel permission {ChannelPermission.Value}"); | |||||
| return PreconditionResult.FromError($"Bot requires channel permission {ChannelPermission.Value}."); | |||||
| } | } | ||||
| return PreconditionResult.FromSuccess(); | return PreconditionResult.FromSuccess(); | ||||
| @@ -1,6 +1,5 @@ | |||||
| using System; | using System; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using Microsoft.Extensions.DependencyInjection; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| @@ -17,7 +17,7 @@ namespace Discord.Commands | |||||
| case TokenType.Bot: | case TokenType.Bot: | ||||
| var application = await context.Client.GetApplicationInfoAsync(); | var application = await context.Client.GetApplicationInfoAsync(); | ||||
| if (context.User.Id != application.Owner.Id) | if (context.User.Id != application.Owner.Id) | ||||
| return PreconditionResult.FromError("Command can only be run by the owner of the bot"); | |||||
| return PreconditionResult.FromError("Command can only be run by the owner of the bot."); | |||||
| return PreconditionResult.FromSuccess(); | return PreconditionResult.FromSuccess(); | ||||
| default: | default: | ||||
| return PreconditionResult.FromError($"{nameof(RequireOwnerAttribute)} is not supported by this {nameof(TokenType)}."); | return PreconditionResult.FromError($"{nameof(RequireOwnerAttribute)} is not supported by this {nameof(TokenType)}."); | ||||
| @@ -1,5 +1,6 @@ | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| /// <summary> The type of error the command throws. </summary> | |||||
| public enum CommandError | public enum CommandError | ||||
| { | { | ||||
| //Search | //Search | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| using System.Text; | using System.Text; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| @@ -148,7 +148,7 @@ namespace Discord.Commands | |||||
| if (isEscaping) | if (isEscaping) | ||||
| return ParseResult.FromError(CommandError.ParseFailed, "Input text may not end on an incomplete escape."); | return ParseResult.FromError(CommandError.ParseFailed, "Input text may not end on an incomplete escape."); | ||||
| if (curPart == ParserPart.QuotedParameter) | if (curPart == ParserPart.QuotedParameter) | ||||
| return ParseResult.FromError(CommandError.ParseFailed, "A quoted parameter is incomplete"); | |||||
| return ParseResult.FromError(CommandError.ParseFailed, "A quoted parameter is incomplete."); | |||||
| //Add missing optionals | //Add missing optionals | ||||
| for (int i = argList.Count; i < command.Parameters.Count; i++) | for (int i = argList.Count; i < command.Parameters.Count; i++) | ||||
| @@ -111,11 +111,11 @@ namespace Discord.Commands | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// Add a command module from a type | |||||
| /// Add a command module from a <see cref="Type"/>. | |||||
| /// </summary> | /// </summary> | ||||
| /// <typeparam name="T">The type of module</typeparam> | |||||
| /// <param name="services">An IServiceProvider for your dependency injection solution, if using one - otherwise, pass null</param> | |||||
| /// <returns>A built module</returns> | |||||
| /// <typeparam name="T">The type of module.</typeparam> | |||||
| /// <param name="services">An <see cref="IServiceProvider"/> for your dependency injection solution, if using one - otherwise, pass <see langword="null"/>. </param> | |||||
| /// <returns>A built module.</returns> | |||||
| public Task<ModuleInfo> AddModuleAsync<T>(IServiceProvider services) => AddModuleAsync(typeof(T), services); | public Task<ModuleInfo> AddModuleAsync<T>(IServiceProvider services) => AddModuleAsync(typeof(T), services); | ||||
| public async Task<ModuleInfo> AddModuleAsync(Type type, IServiceProvider services) | public async Task<ModuleInfo> AddModuleAsync(Type type, IServiceProvider services) | ||||
| { | { | ||||
| @@ -127,7 +127,7 @@ namespace Discord.Commands | |||||
| var typeInfo = type.GetTypeInfo(); | var typeInfo = type.GetTypeInfo(); | ||||
| if (_typedModuleDefs.ContainsKey(type)) | if (_typedModuleDefs.ContainsKey(type)) | ||||
| throw new ArgumentException($"This module has already been added."); | |||||
| throw new ArgumentException("This module has already been added."); | |||||
| var module = (await ModuleClassBuilder.BuildAsync(this, services, typeInfo).ConfigureAwait(false)).FirstOrDefault(); | var module = (await ModuleClassBuilder.BuildAsync(this, services, typeInfo).ConfigureAwait(false)).FirstOrDefault(); | ||||
| @@ -144,11 +144,11 @@ namespace Discord.Commands | |||||
| } | } | ||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// Add command modules from an assembly | |||||
| /// Add command modules from an <see cref="Assembly"/>. | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="assembly">The assembly containing command modules</param> | |||||
| /// <param name="services">An IServiceProvider for your dependency injection solution, if using one - otherwise, pass null</param> | |||||
| /// <returns>A collection of built modules</returns> | |||||
| /// <param name="assembly">The <see cref="Assembly"/> containing command modules.</param> | |||||
| /// <param name="services">An <see cref="IServiceProvider"/> for your dependency injection solution, if using one - otherwise, pass <see langword="null"/>.</param> | |||||
| /// <returns>A collection of built modules.</returns> | |||||
| public async Task<IEnumerable<ModuleInfo>> AddModulesAsync(Assembly assembly, IServiceProvider services) | public async Task<IEnumerable<ModuleInfo>> AddModulesAsync(Assembly assembly, IServiceProvider services) | ||||
| { | { | ||||
| services = services ?? EmptyServiceProvider.Instance; | services = services ?? EmptyServiceProvider.Instance; | ||||
| @@ -231,18 +231,26 @@ namespace Discord.Commands | |||||
| //Type Readers | //Type Readers | ||||
| /// <summary> | /// <summary> | ||||
| /// Adds a custom <see cref="TypeReader"/> to this <see cref="CommandService"/> for the supplied object type. | |||||
| /// If <typeparamref name="T"/> is a <see cref="ValueType"/>, a <see cref="NullableTypeReader{T}"/> will also be added. | |||||
| /// If a default <see cref="TypeReader"/> exists for <typeparamref name="T"/>, a warning will be logged and the default <see cref="TypeReader"/> will be replaced. | |||||
| /// Adds a custom <see cref="TypeReader"/> to this <see cref="CommandService"/> for the supplied object type. | |||||
| /// <para> | |||||
| /// If <typeparamref name="T"/> is a <see cref="ValueType"/>, a <see cref="NullableTypeReader{T}"/> will also be added. | |||||
| /// </para> | |||||
| /// <para> | |||||
| /// If a default <see cref="TypeReader"/> exists for <typeparamref name="T"/>, a warning will be logged and the default <see cref="TypeReader"/> will be replaced. | |||||
| /// </para> | |||||
| /// </summary> | /// </summary> | ||||
| /// <typeparam name="T">The object type to be read by the <see cref="TypeReader"/>.</typeparam> | /// <typeparam name="T">The object type to be read by the <see cref="TypeReader"/>.</typeparam> | ||||
| /// <param name="reader">An instance of the <see cref="TypeReader"/> to be added.</param> | /// <param name="reader">An instance of the <see cref="TypeReader"/> to be added.</param> | ||||
| public void AddTypeReader<T>(TypeReader reader) | public void AddTypeReader<T>(TypeReader reader) | ||||
| => AddTypeReader(typeof(T), reader); | => AddTypeReader(typeof(T), reader); | ||||
| /// <summary> | /// <summary> | ||||
| /// Adds a custom <see cref="TypeReader"/> to this <see cref="CommandService"/> for the supplied object type. | |||||
| /// If <paramref name="type"/> is a <see cref="ValueType"/>, a <see cref="NullableTypeReader{T}"/> for the value type will also be added. | |||||
| /// If a default <see cref="TypeReader"/> exists for <paramref name="type"/>, a warning will be logged and the default <see cref="TypeReader"/> will be replaced. | |||||
| /// Adds a custom <see cref="TypeReader"/> to this <see cref="CommandService"/> for the supplied object type. | |||||
| /// <para> | |||||
| /// If <paramref name="type"/> is a <see cref="ValueType"/>, a <see cref="NullableTypeReader{T}"/> for the value type will also be added. | |||||
| /// </para> | |||||
| /// <para> | |||||
| /// If a default <see cref="TypeReader"/> exists for <paramref name="type"/>, a warning will be logged and the default <see cref="TypeReader"/> will be replaced. | |||||
| /// </para> | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="type">A <see cref="Type"/> instance for the type to be read.</param> | /// <param name="type">A <see cref="Type"/> instance for the type to be read.</param> | ||||
| /// <param name="reader">An instance of the <see cref="TypeReader"/> to be added.</param> | /// <param name="reader">An instance of the <see cref="TypeReader"/> to be added.</param> | ||||
| @@ -250,12 +258,14 @@ namespace Discord.Commands | |||||
| { | { | ||||
| if (_defaultTypeReaders.ContainsKey(type)) | if (_defaultTypeReaders.ContainsKey(type)) | ||||
| _ = _cmdLogger.WarningAsync($"The default TypeReader for {type.FullName} was replaced by {reader.GetType().FullName}." + | _ = _cmdLogger.WarningAsync($"The default TypeReader for {type.FullName} was replaced by {reader.GetType().FullName}." + | ||||
| $"To suppress this message, use AddTypeReader<T>(reader, true)."); | |||||
| "To suppress this message, use AddTypeReader<T>(reader, true)."); | |||||
| AddTypeReader(type, reader, true); | AddTypeReader(type, reader, true); | ||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// Adds a custom <see cref="TypeReader"/> to this <see cref="CommandService"/> for the supplied object type. | /// Adds a custom <see cref="TypeReader"/> to this <see cref="CommandService"/> for the supplied object type. | ||||
| /// If <typeparamref name="T"/> is a <see cref="ValueType"/>, a <see cref="NullableTypeReader{T}"/> will also be added. | |||||
| /// <para> | |||||
| /// If <typeparamref name="T"/> is a <see cref="ValueType"/>, a <see cref="NullableTypeReader{T}"/> will also be added. | |||||
| /// </para> | |||||
| /// </summary> | /// </summary> | ||||
| /// <typeparam name="T">The object type to be read by the <see cref="TypeReader"/>.</typeparam> | /// <typeparam name="T">The object type to be read by the <see cref="TypeReader"/>.</typeparam> | ||||
| /// <param name="reader">An instance of the <see cref="TypeReader"/> to be added.</param> | /// <param name="reader">An instance of the <see cref="TypeReader"/> to be added.</param> | ||||
| @@ -264,7 +274,9 @@ namespace Discord.Commands | |||||
| => AddTypeReader(typeof(T), reader, replaceDefault); | => AddTypeReader(typeof(T), reader, replaceDefault); | ||||
| /// <summary> | /// <summary> | ||||
| /// Adds a custom <see cref="TypeReader"/> to this <see cref="CommandService"/> for the supplied object type. | /// Adds a custom <see cref="TypeReader"/> to this <see cref="CommandService"/> for the supplied object type. | ||||
| /// If <paramref name="type"/> is a <see cref="ValueType"/>, a <see cref="NullableTypeReader{T}"/> for the value type will also be added. | |||||
| /// <para> | |||||
| /// If <paramref name="type"/> is a <see cref="ValueType"/>, a <see cref="NullableTypeReader{T}"/> for the value type will also be added. | |||||
| /// </para> | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="type">A <see cref="Type"/> instance for the type to be read.</param> | /// <param name="type">A <see cref="Type"/> instance for the type to be read.</param> | ||||
| /// <param name="reader">An instance of the <see cref="TypeReader"/> to be added.</param> | /// <param name="reader">An instance of the <see cref="TypeReader"/> to be added.</param> | ||||
| @@ -271,11 +271,11 @@ namespace Discord.Commands | |||||
| foreach (object arg in argList) | foreach (object arg in argList) | ||||
| { | { | ||||
| if (i == argCount) | if (i == argCount) | ||||
| throw new InvalidOperationException("Command was invoked with too many parameters"); | |||||
| throw new InvalidOperationException("Command was invoked with too many parameters."); | |||||
| array[i++] = arg; | array[i++] = arg; | ||||
| } | } | ||||
| if (i < argCount) | if (i < argCount) | ||||
| throw new InvalidOperationException("Command was invoked with too few parameters"); | |||||
| throw new InvalidOperationException("Command was invoked with too few parameters."); | |||||
| if (HasVarArgs) | if (HasVarArgs) | ||||
| { | { | ||||
| @@ -2,11 +2,13 @@ using Discord.Commands.Builders; | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| using System.Diagnostics; | |||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using Microsoft.Extensions.DependencyInjection; | using Microsoft.Extensions.DependencyInjection; | ||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||||
| public class ParameterInfo | public class ParameterInfo | ||||
| { | { | ||||
| private readonly TypeReader _reader; | private readonly TypeReader _reader; | ||||
| @@ -65,4 +67,4 @@ namespace Discord.Commands | |||||
| public override string ToString() => Name; | public override string ToString() => Name; | ||||
| private string DebuggerDisplay => $"{Name}{(IsOptional ? " (Optional)" : "")}{(IsRemainder ? " (Remainder)" : "")}"; | private string DebuggerDisplay => $"{Name}{(IsOptional ? " (Optional)" : "")}{(IsRemainder ? " (Remainder)" : "")}"; | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -43,7 +43,7 @@ namespace Discord.Commands | |||||
| void IModuleBase.SetContext(ICommandContext context) | void IModuleBase.SetContext(ICommandContext context) | ||||
| { | { | ||||
| var newValue = context as T; | var newValue = context as T; | ||||
| Context = newValue ?? throw new InvalidOperationException($"Invalid context type. Expected {typeof(T).Name}, got {context.GetType().Name}"); | |||||
| Context = newValue ?? throw new InvalidOperationException($"Invalid context type. Expected {typeof(T).Name}, got {context.GetType().Name}."); | |||||
| } | } | ||||
| void IModuleBase.BeforeExecute(CommandInfo command) => BeforeExecute(command); | void IModuleBase.BeforeExecute(CommandInfo command) => BeforeExecute(command); | ||||
| void IModuleBase.AfterExecute(CommandInfo command) => AfterExecute(command); | void IModuleBase.AfterExecute(CommandInfo command) => AfterExecute(command); | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| using System.Linq; | using System.Linq; | ||||
| @@ -53,14 +53,14 @@ namespace Discord.Commands | |||||
| if (_enumsByValue.TryGetValue(baseValue, out enumValue)) | if (_enumsByValue.TryGetValue(baseValue, out enumValue)) | ||||
| return Task.FromResult(TypeReaderResult.FromSuccess(enumValue)); | return Task.FromResult(TypeReaderResult.FromSuccess(enumValue)); | ||||
| else | else | ||||
| return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, $"Value is not a {_enumType.Name}")); | |||||
| return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, $"Value is not a {_enumType.Name}.")); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| if (_enumsByName.TryGetValue(input.ToLower(), out enumValue)) | if (_enumsByName.TryGetValue(input.ToLower(), out enumValue)) | ||||
| return Task.FromResult(TypeReaderResult.FromSuccess(enumValue)); | return Task.FromResult(TypeReaderResult.FromSuccess(enumValue)); | ||||
| else | else | ||||
| return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, $"Value is not a {_enumType.Name}")); | |||||
| return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, $"Value is not a {_enumType.Name}.")); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| @@ -24,7 +24,7 @@ namespace Discord.Commands | |||||
| public PrimitiveTypeReader(TryParseDelegate<T> tryParse, float score) | public PrimitiveTypeReader(TryParseDelegate<T> tryParse, float score) | ||||
| { | { | ||||
| if (score < 0 || score > 1) | if (score < 0 || score > 1) | ||||
| throw new ArgumentOutOfRangeException(nameof(score), score, "Scores must be within the range [0, 1]"); | |||||
| throw new ArgumentOutOfRangeException(nameof(score), score, "Scores must be within the range [0, 1]."); | |||||
| _tryParse = tryParse; | _tryParse = tryParse; | ||||
| _score = score; | _score = score; | ||||
| @@ -34,7 +34,7 @@ namespace Discord.Commands | |||||
| { | { | ||||
| if (_tryParse(input, out T value)) | if (_tryParse(input, out T value)) | ||||
| return Task.FromResult(TypeReaderResult.FromSuccess(new TypeReaderValue(value, _score))); | return Task.FromResult(TypeReaderResult.FromSuccess(new TypeReaderValue(value, _score))); | ||||
| return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, $"Failed to parse {typeof(T).Name}")); | |||||
| return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, $"Failed to parse {typeof(T).Name}.")); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Globalization; | using System.Globalization; | ||||
| using System.Linq; | using System.Linq; | ||||
| @@ -11,15 +11,13 @@ namespace Discord.Commands | |||||
| { | { | ||||
| public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) | public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) | ||||
| { | { | ||||
| ulong id; | |||||
| if (context.Guild != null) | if (context.Guild != null) | ||||
| { | { | ||||
| var results = new Dictionary<ulong, TypeReaderValue>(); | var results = new Dictionary<ulong, TypeReaderValue>(); | ||||
| var roles = context.Guild.Roles; | var roles = context.Guild.Roles; | ||||
| //By Mention (1.0) | //By Mention (1.0) | ||||
| if (MentionUtils.TryParseRole(input, out id)) | |||||
| if (MentionUtils.TryParseRole(input, out var id)) | |||||
| AddResult(results, context.Guild.GetRole(id) as T, 1.00f); | AddResult(results, context.Guild.GetRole(id) as T, 1.00f); | ||||
| //By Id (0.9) | //By Id (0.9) | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| using System.Globalization; | using System.Globalization; | ||||
| @@ -15,13 +15,12 @@ namespace Discord.Commands | |||||
| var results = new Dictionary<ulong, TypeReaderValue>(); | var results = new Dictionary<ulong, TypeReaderValue>(); | ||||
| IAsyncEnumerable<IUser> channelUsers = context.Channel.GetUsersAsync(CacheMode.CacheOnly).Flatten(); // it's better | IAsyncEnumerable<IUser> channelUsers = context.Channel.GetUsersAsync(CacheMode.CacheOnly).Flatten(); // it's better | ||||
| IReadOnlyCollection<IGuildUser> guildUsers = ImmutableArray.Create<IGuildUser>(); | IReadOnlyCollection<IGuildUser> guildUsers = ImmutableArray.Create<IGuildUser>(); | ||||
| ulong id; | |||||
| if (context.Guild != null) | if (context.Guild != null) | ||||
| guildUsers = await context.Guild.GetUsersAsync(CacheMode.CacheOnly).ConfigureAwait(false); | guildUsers = await context.Guild.GetUsersAsync(CacheMode.CacheOnly).ConfigureAwait(false); | ||||
| //By Mention (1.0) | //By Mention (1.0) | ||||
| if (MentionUtils.TryParseUser(input, out id)) | |||||
| if (MentionUtils.TryParseUser(input, out var id)) | |||||
| { | { | ||||
| if (context.Guild != null) | if (context.Guild != null) | ||||
| AddResult(results, await context.Guild.GetUserAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T, 1.00f); | AddResult(results, await context.Guild.GetUserAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T, 1.00f); | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System.Collections.Generic; | |||||
| using System.Collections.Generic; | |||||
| using System.Diagnostics; | using System.Diagnostics; | ||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| @@ -14,11 +14,11 @@ namespace Discord.Commands | |||||
| PreconditionResults = (preconditions ?? new List<PreconditionResult>(0)).ToReadOnlyCollection(); | PreconditionResults = (preconditions ?? new List<PreconditionResult>(0)).ToReadOnlyCollection(); | ||||
| } | } | ||||
| public static new PreconditionGroupResult FromSuccess() | |||||
| public new static PreconditionGroupResult FromSuccess() | |||||
| => new PreconditionGroupResult(null, null, null); | => new PreconditionGroupResult(null, null, null); | ||||
| public static PreconditionGroupResult FromError(string reason, ICollection<PreconditionResult> preconditions) | public static PreconditionGroupResult FromError(string reason, ICollection<PreconditionResult> preconditions) | ||||
| => new PreconditionGroupResult(CommandError.UnmetPrecondition, reason, preconditions); | => new PreconditionGroupResult(CommandError.UnmetPrecondition, reason, preconditions); | ||||
| public static new PreconditionGroupResult FromError(IResult result) //needed? | |||||
| public new static PreconditionGroupResult FromError(IResult result) //needed? | |||||
| => new PreconditionGroupResult(result.Error, result.ErrorReason, null); | => new PreconditionGroupResult(result.Error, result.ErrorReason, null); | ||||
| public override string ToString() => IsSuccess ? "Success" : $"{Error}: {ErrorReason}"; | public override string ToString() => IsSuccess ? "Success" : $"{Error}: {ErrorReason}"; | ||||
| @@ -1,7 +1,4 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Diagnostics; | using System.Diagnostics; | ||||
| using System.Text; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| @@ -2,7 +2,6 @@ using System; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Linq; | using System.Linq; | ||||
| using System.Reflection; | using System.Reflection; | ||||
| using Microsoft.Extensions.DependencyInjection; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| @@ -38,7 +37,7 @@ namespace Discord.Commands | |||||
| } | } | ||||
| catch (Exception ex) | catch (Exception ex) | ||||
| { | { | ||||
| throw new Exception($"Failed to create \"{ownerType.FullName}\"", ex); | |||||
| throw new Exception($"Failed to create \"{ownerType.FullName}\".", ex); | |||||
| } | } | ||||
| } | } | ||||
| @@ -46,14 +45,14 @@ namespace Discord.Commands | |||||
| { | { | ||||
| var constructors = ownerType.DeclaredConstructors.Where(x => !x.IsStatic).ToArray(); | var constructors = ownerType.DeclaredConstructors.Where(x => !x.IsStatic).ToArray(); | ||||
| if (constructors.Length == 0) | if (constructors.Length == 0) | ||||
| throw new InvalidOperationException($"No constructor found for \"{ownerType.FullName}\""); | |||||
| throw new InvalidOperationException($"No constructor found for \"{ownerType.FullName}\"."); | |||||
| else if (constructors.Length > 1) | else if (constructors.Length > 1) | ||||
| throw new InvalidOperationException($"Multiple constructors found for \"{ownerType.FullName}\""); | |||||
| throw new InvalidOperationException($"Multiple constructors found for \"{ownerType.FullName}\"."); | |||||
| return constructors[0]; | return constructors[0]; | ||||
| } | } | ||||
| private static System.Reflection.PropertyInfo[] GetProperties(TypeInfo ownerType) | |||||
| private static PropertyInfo[] GetProperties(TypeInfo ownerType) | |||||
| { | { | ||||
| var result = new List<System.Reflection.PropertyInfo>(); | |||||
| var result = new List<PropertyInfo>(); | |||||
| while (ownerType != _objectTypeInfo) | while (ownerType != _objectTypeInfo) | ||||
| { | { | ||||
| foreach (var prop in ownerType.DeclaredProperties) | foreach (var prop in ownerType.DeclaredProperties) | ||||
| @@ -71,7 +70,7 @@ namespace Discord.Commands | |||||
| return commands; | return commands; | ||||
| if (memberType == typeof(IServiceProvider) || memberType == services.GetType()) | if (memberType == typeof(IServiceProvider) || memberType == services.GetType()) | ||||
| return services; | return services; | ||||
| var service = services?.GetService(memberType); | |||||
| var service = services.GetService(memberType); | |||||
| if (service != null) | if (service != null) | ||||
| return service; | return service; | ||||
| throw new InvalidOperationException($"Failed to create \"{ownerType.FullName}\", dependency \"{memberType.Name}\" was not found."); | throw new InvalidOperationException($"Failed to create \"{ownerType.FullName}\", dependency \"{memberType.Name}\" was not found."); | ||||
| @@ -2,7 +2,7 @@ using System; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <summary> Contains the strings related to various Content Delievery Networks (CDNs). </summary> | |||||
| /// <summary> A class containing the strings related to various Content Delivery Networks (CDNs). </summary> | |||||
| public static class CDN | public static class CDN | ||||
| { | { | ||||
| /// <summary> Returns the Discord developer application icon. </summary> | /// <summary> Returns the Discord developer application icon. </summary> | ||||
| @@ -4,15 +4,15 @@ namespace Discord | |||||
| { | { | ||||
| public class DiscordConfig | public class DiscordConfig | ||||
| { | { | ||||
| /// <summary> Returns the gateway version Discord.NET uses. </summary> | |||||
| /// <summary> Returns the gateway version Discord.Net uses. </summary> | |||||
| public const int APIVersion = 6; | public const int APIVersion = 6; | ||||
| /// <summary> Returns the Discord.NET verion, including the build number. </summary> | |||||
| /// <summary> Returns the Discord.Net version, including the build number. </summary> | |||||
| public static string Version { get; } = | public static string Version { get; } = | ||||
| typeof(DiscordConfig).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? | typeof(DiscordConfig).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? | ||||
| typeof(DiscordConfig).GetTypeInfo().Assembly.GetName().Version.ToString(3) ?? | typeof(DiscordConfig).GetTypeInfo().Assembly.GetName().Version.ToString(3) ?? | ||||
| "Unknown"; | "Unknown"; | ||||
| /// <summary> Returns the user agent that Discord.NET uses in its clients. </summary> | |||||
| /// <summary> Returns the user agent that Discord.Net uses in its clients. </summary> | |||||
| public static string UserAgent { get; } = $"DiscordBot (https://github.com/RogueException/Discord.Net, v{Version})"; | public static string UserAgent { get; } = $"DiscordBot (https://github.com/RogueException/Discord.Net, v{Version})"; | ||||
| /// <summary> Returns the base Discord API URL. </summary> | /// <summary> Returns the base Discord API URL. </summary> | ||||
| public static readonly string APIUrl = $"https://discordapp.com/api/v{APIVersion}/"; | public static readonly string APIUrl = $"https://discordapp.com/api/v{APIVersion}/"; | ||||
| @@ -57,7 +57,7 @@ namespace Discord | |||||
| get => _url; | get => _url; | ||||
| set | set | ||||
| { | { | ||||
| if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(Url)); | |||||
| if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI.", nameof(Url)); | |||||
| _url = value; | _url = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -67,7 +67,7 @@ namespace Discord | |||||
| get => _thumbnail?.Url; | get => _thumbnail?.Url; | ||||
| set | set | ||||
| { | { | ||||
| if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(ThumbnailUrl)); | |||||
| if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI.", nameof(ThumbnailUrl)); | |||||
| _thumbnail = new EmbedThumbnail(value, null, null, null); | _thumbnail = new EmbedThumbnail(value, null, null, null); | ||||
| } | } | ||||
| } | } | ||||
| @@ -77,7 +77,7 @@ namespace Discord | |||||
| get => _image?.Url; | get => _image?.Url; | ||||
| set | set | ||||
| { | { | ||||
| if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(ImageUrl)); | |||||
| if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI.", nameof(ImageUrl)); | |||||
| _image = new EmbedImage(value, null, null, null); | _image = new EmbedImage(value, null, null, null); | ||||
| } | } | ||||
| } | } | ||||
| @@ -87,7 +87,7 @@ namespace Discord | |||||
| get => _fields; | get => _fields; | ||||
| set | set | ||||
| { | { | ||||
| if (value == null) throw new ArgumentNullException("Cannot set an embed builder's fields collection to null", nameof(Fields)); | |||||
| if (value == null) throw new ArgumentNullException(nameof(Fields), "Cannot set an embed builder's fields collection to null."); | |||||
| if (value.Count > MaxFieldCount) throw new ArgumentException($"Field count must be less than or equal to {MaxFieldCount}.", nameof(Fields)); | if (value.Count > MaxFieldCount) throw new ArgumentException($"Field count must be less than or equal to {MaxFieldCount}.", nameof(Fields)); | ||||
| _fields = value; | _fields = value; | ||||
| } | } | ||||
| @@ -271,7 +271,7 @@ namespace Discord | |||||
| public Embed Build() | public Embed Build() | ||||
| { | { | ||||
| if (Length > MaxEmbedLength) | if (Length > MaxEmbedLength) | ||||
| throw new InvalidOperationException($"Total embed length must be less than or equal to {MaxEmbedLength}"); | |||||
| throw new InvalidOperationException($"Total embed length must be less than or equal to {MaxEmbedLength}."); | |||||
| var fields = ImmutableArray.CreateBuilder<EmbedField>(Fields.Count); | var fields = ImmutableArray.CreateBuilder<EmbedField>(Fields.Count); | ||||
| for (int i = 0; i < Fields.Count; i++) | for (int i = 0; i < Fields.Count; i++) | ||||
| @@ -294,7 +294,7 @@ namespace Discord | |||||
| get => _name; | get => _name; | ||||
| set | set | ||||
| { | { | ||||
| if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException($"Field name must not be null, empty or entirely whitespace.", nameof(Name)); | |||||
| if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Field name must not be null, empty or entirely whitespace.", nameof(Name)); | |||||
| if (value.Length > MaxFieldNameLength) throw new ArgumentException($"Field name length must be less than or equal to {MaxFieldNameLength}.", nameof(Name)); | if (value.Length > MaxFieldNameLength) throw new ArgumentException($"Field name length must be less than or equal to {MaxFieldNameLength}.", nameof(Name)); | ||||
| _name = value; | _name = value; | ||||
| } | } | ||||
| @@ -354,7 +354,7 @@ namespace Discord | |||||
| get => _url; | get => _url; | ||||
| set | set | ||||
| { | { | ||||
| if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(Url)); | |||||
| if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI.", nameof(Url)); | |||||
| _url = value; | _url = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -363,7 +363,7 @@ namespace Discord | |||||
| get => _iconUrl; | get => _iconUrl; | ||||
| set | set | ||||
| { | { | ||||
| if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(IconUrl)); | |||||
| if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI.", nameof(IconUrl)); | |||||
| _iconUrl = value; | _iconUrl = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -409,7 +409,7 @@ namespace Discord | |||||
| get => _iconUrl; | get => _iconUrl; | ||||
| set | set | ||||
| { | { | ||||
| if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(IconUrl)); | |||||
| if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI.", nameof(IconUrl)); | |||||
| _iconUrl = value; | _iconUrl = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -3,7 +3,7 @@ using System; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <summary> Defines the available permissions for a channel. </summary> | /// <summary> Defines the available permissions for a channel. </summary> | ||||
| [FlagsAttribute] | |||||
| [Flags] | |||||
| public enum ChannelPermission : ulong | public enum ChannelPermission : ulong | ||||
| { | { | ||||
| // General | // General | ||||
| @@ -29,7 +29,7 @@ namespace Discord | |||||
| case ICategoryChannel _: return Category; | case ICategoryChannel _: return Category; | ||||
| case IDMChannel _: return DM; | case IDMChannel _: return DM; | ||||
| case IGroupChannel _: return Group; | case IGroupChannel _: return Group; | ||||
| default: throw new ArgumentException("Unknown channel type", nameof(channel)); | |||||
| default: throw new ArgumentException("Unknown channel type.", nameof(channel)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -74,11 +74,11 @@ namespace Discord | |||||
| public Color(int r, int g, int b) | public Color(int r, int g, int b) | ||||
| { | { | ||||
| if (r < 0 || r > 255) | if (r < 0 || r > 255) | ||||
| throw new ArgumentOutOfRangeException(nameof(r), "Value must be within [0,255]"); | |||||
| throw new ArgumentOutOfRangeException(nameof(r), "Value must be within [0,255]."); | |||||
| if (g < 0 || g > 255) | if (g < 0 || g > 255) | ||||
| throw new ArgumentOutOfRangeException(nameof(g), "Value must be within [0,255]"); | |||||
| throw new ArgumentOutOfRangeException(nameof(g), "Value must be within [0,255]."); | |||||
| if (b < 0 || b > 255) | if (b < 0 || b > 255) | ||||
| throw new ArgumentOutOfRangeException(nameof(b), "Value must be within [0,255]"); | |||||
| throw new ArgumentOutOfRangeException(nameof(b), "Value must be within [0,255]."); | |||||
| RawValue = | RawValue = | ||||
| ((uint)r << 16) | | ((uint)r << 16) | | ||||
| ((uint)g << 8) | | ((uint)g << 8) | | ||||
| @@ -87,11 +87,11 @@ namespace Discord | |||||
| public Color(float r, float g, float b) | public Color(float r, float g, float b) | ||||
| { | { | ||||
| if (r < 0.0f || r > 1.0f) | if (r < 0.0f || r > 1.0f) | ||||
| throw new ArgumentOutOfRangeException(nameof(r), "Value must be within [0,1]"); | |||||
| throw new ArgumentOutOfRangeException(nameof(r), "Value must be within [0,1]."); | |||||
| if (g < 0.0f || g > 1.0f) | if (g < 0.0f || g > 1.0f) | ||||
| throw new ArgumentOutOfRangeException(nameof(g), "Value must be within [0,1]"); | |||||
| throw new ArgumentOutOfRangeException(nameof(g), "Value must be within [0,1]."); | |||||
| if (b < 0.0f || b > 1.0f) | if (b < 0.0f || b > 1.0f) | ||||
| throw new ArgumentOutOfRangeException(nameof(b), "Value must be within [0,1]"); | |||||
| throw new ArgumentOutOfRangeException(nameof(b), "Value must be within [0,1]."); | |||||
| RawValue = | RawValue = | ||||
| ((uint)(r * 255.0f) << 16) | | ((uint)(r * 255.0f) << 16) | | ||||
| ((uint)(g * 255.0f) << 8) | | ((uint)(g * 255.0f) << 8) | | ||||