diff --git a/src/Discord.Net.Commands/Attributes/AliasAttribute.cs b/src/Discord.Net.Commands/Attributes/AliasAttribute.cs index acdb600ce..16eb3ba73 100644 --- a/src/Discord.Net.Commands/Attributes/AliasAttribute.cs +++ b/src/Discord.Net.Commands/Attributes/AliasAttribute.cs @@ -2,14 +2,37 @@ using System; namespace Discord.Commands { - /// Marks the aliases for a command. + /// + /// Marks the aliases for a command. + /// + /// + /// This attribute allows a command to have one or multiple aliases. In other words, the base command can have + /// multiple aliases when triggering the command itself, giving the end-user more freedom of choices when giving + /// hot-words to trigger the desired command. See the example for a better illustration. + /// + /// + /// In the following example, the command can be triggered with the base name, "stats", or either "stat" or + /// "info". + /// + /// [Command("stats")] + /// [Alias("stat", "info")] + /// public async Task GetStatsAsync(IUser user) + /// { + /// // ...pull stats + /// } + /// + /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public class AliasAttribute : Attribute { - /// Gets the aliases which have been defined for the command. + /// + /// Gets the aliases which have been defined for the command. + /// public string[] Aliases { get; } - /// Creates a new with the given aliases. + /// + /// Creates a new with the given aliases. + /// public AliasAttribute(params string[] aliases) { Aliases = aliases; diff --git a/src/Discord.Net.Commands/Attributes/CommandAttribute.cs b/src/Discord.Net.Commands/Attributes/CommandAttribute.cs index 372c9c2e9..d4d9ee3bb 100644 --- a/src/Discord.Net.Commands/Attributes/CommandAttribute.cs +++ b/src/Discord.Net.Commands/Attributes/CommandAttribute.cs @@ -2,7 +2,9 @@ using System; namespace Discord.Commands { - /// Marks the execution information for a command. + /// + /// Marks the execution information for a command. + /// [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public class CommandAttribute : Attribute { diff --git a/src/Discord.Net.Commands/Attributes/DontAutoLoadAttribute.cs b/src/Discord.Net.Commands/Attributes/DontAutoLoadAttribute.cs index 451b87f5e..7dbe1a495 100644 --- a/src/Discord.Net.Commands/Attributes/DontAutoLoadAttribute.cs +++ b/src/Discord.Net.Commands/Attributes/DontAutoLoadAttribute.cs @@ -2,7 +2,14 @@ using System; namespace Discord.Commands { - /// Prevents the marked module from being loaded automatically. + /// + /// Prevents the marked module from being loaded automatically. + /// + /// + /// This attribute tells to ignore the marked module from being loaded + /// automatically (e.g. the method). If a non-public module marked + /// with this attribute is attempted to be loaded manually, the loading process will also fail. + /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public class DontAutoLoadAttribute : Attribute { diff --git a/src/Discord.Net.Commands/Attributes/DontInjectAttribute.cs b/src/Discord.Net.Commands/Attributes/DontInjectAttribute.cs index 19d946afd..72ca92fdf 100644 --- a/src/Discord.Net.Commands/Attributes/DontInjectAttribute.cs +++ b/src/Discord.Net.Commands/Attributes/DontInjectAttribute.cs @@ -5,6 +5,25 @@ namespace Discord.Commands /// /// Prevents the marked property from being injected into a module. /// + /// + /// This attribute prevents the marked member from being injected into its parent module. Useful when you have a + /// public property that you do not wish to invoke the library's dependency injection service. + /// + /// + /// In the following example, DatabaseService will not be automatically injected into the module and will + /// not throw an error message if the dependency fails to be resolved. + /// + /// public class MyModule : ModuleBase + /// { + /// [DontInject] + /// public DatabaseService DatabaseService; + /// public MyModule() + /// { + /// DatabaseService = DatabaseFactory.Generate(); + /// } + /// } + /// + /// [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public class DontInjectAttribute : Attribute { diff --git a/src/Discord.Net.Commands/Attributes/OverrideTypeReaderAttribute.cs b/src/Discord.Net.Commands/Attributes/OverrideTypeReaderAttribute.cs index ec110ab1a..85f5df10e 100644 --- a/src/Discord.Net.Commands/Attributes/OverrideTypeReaderAttribute.cs +++ b/src/Discord.Net.Commands/Attributes/OverrideTypeReaderAttribute.cs @@ -5,8 +5,28 @@ using System.Reflection; namespace Discord.Commands { /// - /// Marks the to be read by the specified . + /// Marks the to be read by the specified . /// + /// + /// This attribute will override the to be used when parsing for the + /// desired type in the command. This is useful when one wishes to use a particular + /// without affecting other commands that are using the same target + /// type. + /// + /// If the given type reader does not inherit from , an + /// will be thrown. + /// + /// + /// + /// In this example, the will be read by a custom + /// , FriendlyTimeSpanTypeReader, instead of the + /// shipped by Discord.Net. + /// + /// [Command("time")] + /// public Task GetTimeAsync([OverrideTypeReader(typeof(FriendlyTimeSpanTypeReader))]TimeSpan time) + /// => ReplyAsync(time); + /// + /// [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] public class OverrideTypeReaderAttribute : Attribute { diff --git a/src/Discord.Net.Commands/Attributes/Preconditions/RequireNsfwAttribute.cs b/src/Discord.Net.Commands/Attributes/Preconditions/RequireNsfwAttribute.cs index 6a6f7eb6d..930511da1 100644 --- a/src/Discord.Net.Commands/Attributes/Preconditions/RequireNsfwAttribute.cs +++ b/src/Discord.Net.Commands/Attributes/Preconditions/RequireNsfwAttribute.cs @@ -11,6 +11,22 @@ namespace Discord.Commands /// that has been marked as mature or NSFW. If the channel is not of type or the /// channel is not marked as NSFW, the precondition will fail with an erroneous . /// + /// + /// The following example restricts the command too-cool to an NSFW-enabled channel only. + /// + /// public class DankModule : ModuleBase + /// { + /// [Command("cool")] + /// public Task CoolAsync() + /// => ReplyAsync("I'm cool for everyone."); + /// + /// [RequireNsfw] + /// [Command("too-cool")] + /// public Task TooCoolAsync() + /// => ReplyAsync("You can only see this if you're cool enough."); + /// } + /// + /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public class RequireNsfwAttribute : PreconditionAttribute { diff --git a/src/Discord.Net.Commands/Attributes/Preconditions/RequireOwnerAttribute.cs b/src/Discord.Net.Commands/Attributes/Preconditions/RequireOwnerAttribute.cs index 0b9571a2a..53021ad10 100644 --- a/src/Discord.Net.Commands/Attributes/Preconditions/RequireOwnerAttribute.cs +++ b/src/Discord.Net.Commands/Attributes/Preconditions/RequireOwnerAttribute.cs @@ -15,6 +15,22 @@ namespace Discord.Commands /// ;otherwise, this precondition will always fail. /// /// + /// + /// The following example restricts the command to a set of sensitive commands that only the owner of the bot + /// application should be able to access. + /// + /// [RequireOwner] + /// [Group("admin")] + /// public class AdminModule : ModuleBase + /// { + /// [Command("exit")] + /// public async Task ExitAsync() + /// { + /// Environment.Exit(0); + /// } + /// } + /// + /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public class RequireOwnerAttribute : PreconditionAttribute { diff --git a/src/Discord.Net.Commands/Readers/ChannelTypeReader.cs b/src/Discord.Net.Commands/Readers/ChannelTypeReader.cs index 6cb9ca6e6..cdbc59cef 100644 --- a/src/Discord.Net.Commands/Readers/ChannelTypeReader.cs +++ b/src/Discord.Net.Commands/Readers/ChannelTypeReader.cs @@ -9,6 +9,12 @@ namespace Discord.Commands /// /// A for parsing objects implementing . /// + /// + /// This is shipped with Discord.Net and is used by default to parse any + /// implemented object within a command. The TypeReader will attempt to first parse the + /// input by mention, then the snowflake identifier, then by name; the highest candidate will be chosen as the + /// final output; otherwise, an erroneous is returned. + /// /// The type to be checked; must implement . public class ChannelTypeReader : TypeReader where T : class, IChannel diff --git a/src/Discord.Net.Commands/Readers/EnumTypeReader.cs b/src/Discord.Net.Commands/Readers/EnumTypeReader.cs index d0f93aed7..356d704c9 100644 --- a/src/Discord.Net.Commands/Readers/EnumTypeReader.cs +++ b/src/Discord.Net.Commands/Readers/EnumTypeReader.cs @@ -44,6 +44,7 @@ namespace Discord.Commands _enumsByValue = byValueBuilder.ToImmutable(); } + /// public override Task ReadAsync(ICommandContext context, string input, IServiceProvider services) { object enumValue; diff --git a/src/Discord.Net.Commands/Readers/NullableTypeReader.cs b/src/Discord.Net.Commands/Readers/NullableTypeReader.cs index 1a64dc198..f68bf6e2c 100644 --- a/src/Discord.Net.Commands/Readers/NullableTypeReader.cs +++ b/src/Discord.Net.Commands/Readers/NullableTypeReader.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Reflection; using System.Threading.Tasks; @@ -24,6 +24,7 @@ namespace Discord.Commands _baseTypeReader = baseTypeReader; } + /// public override async Task ReadAsync(ICommandContext context, string input, IServiceProvider services) { if (string.Equals(input, "null", StringComparison.OrdinalIgnoreCase) || string.Equals(input, "nothing", StringComparison.OrdinalIgnoreCase)) diff --git a/src/Discord.Net.Commands/Readers/TimeSpanTypeReader.cs b/src/Discord.Net.Commands/Readers/TimeSpanTypeReader.cs index 314fbb322..b4a27cb5b 100644 --- a/src/Discord.Net.Commands/Readers/TimeSpanTypeReader.cs +++ b/src/Discord.Net.Commands/Readers/TimeSpanTypeReader.cs @@ -24,6 +24,7 @@ namespace Discord.Commands "%s's'", // 1s }; + /// public override Task ReadAsync(ICommandContext context, string input, IServiceProvider services) { return (TimeSpan.TryParseExact(input.ToLowerInvariant(), Formats, CultureInfo.InvariantCulture, out var timeSpan))