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))