@@ -2,14 +2,37 @@ using System; | |||||
namespace Discord.Commands | namespace Discord.Commands | ||||
{ | { | ||||
/// <summary> Marks the aliases for a command. </summary> | |||||
/// <summary> | |||||
/// Marks the aliases for a command. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// 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. | |||||
/// </remarks> | |||||
/// <example> | |||||
/// In the following example, the command can be triggered with the base name, "stats", or either "stat" or | |||||
/// "info". | |||||
/// <code language="cs"> | |||||
/// [Command("stats")] | |||||
/// [Alias("stat", "info")] | |||||
/// public async Task GetStatsAsync(IUser user) | |||||
/// { | |||||
/// // ...pull stats | |||||
/// } | |||||
/// </code> | |||||
/// </example> | |||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | ||||
public class AliasAttribute : Attribute | public class AliasAttribute : Attribute | ||||
{ | { | ||||
/// <summary> Gets the aliases which have been defined for the command. </summary> | |||||
/// <summary> | |||||
/// Gets the aliases which have been defined for the command. | |||||
/// </summary> | |||||
public string[] Aliases { get; } | public string[] Aliases { get; } | ||||
/// <summary> Creates a new <see cref="AliasAttribute"/> with the given aliases. </summary> | |||||
/// <summary> | |||||
/// Creates a new <see cref="AliasAttribute" /> with the given aliases. | |||||
/// </summary> | |||||
public AliasAttribute(params string[] aliases) | public AliasAttribute(params string[] aliases) | ||||
{ | { | ||||
Aliases = aliases; | Aliases = aliases; | ||||
@@ -2,7 +2,9 @@ using System; | |||||
namespace Discord.Commands | namespace Discord.Commands | ||||
{ | { | ||||
/// <summary> Marks the execution information for a command. </summary> | |||||
/// <summary> | |||||
/// Marks the execution information for a command. | |||||
/// </summary> | |||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | ||||
public class CommandAttribute : Attribute | public class CommandAttribute : Attribute | ||||
{ | { | ||||
@@ -2,7 +2,14 @@ using System; | |||||
namespace Discord.Commands | namespace Discord.Commands | ||||
{ | { | ||||
/// <summary> Prevents the marked module from being loaded automatically. </summary> | |||||
/// <summary> | |||||
/// Prevents the marked module from being loaded automatically. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// This attribute tells <see cref="CommandService" /> to ignore the marked module from being loaded | |||||
/// automatically (e.g. the <see cref="CommandService.AddModulesAsync" /> method). If a non-public module marked | |||||
/// with this attribute is attempted to be loaded manually, the loading process will also fail. | |||||
/// </remarks> | |||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] | ||||
public class DontAutoLoadAttribute : Attribute | public class DontAutoLoadAttribute : Attribute | ||||
{ | { | ||||
@@ -5,6 +5,25 @@ namespace Discord.Commands | |||||
/// <summary> | /// <summary> | ||||
/// Prevents the marked property from being injected into a module. | /// Prevents the marked property from being injected into a module. | ||||
/// </summary> | /// </summary> | ||||
/// <remarks> | |||||
/// 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. | |||||
/// </remarks> | |||||
/// <example> | |||||
/// In the following example, <c>DatabaseService</c> will not be automatically injected into the module and will | |||||
/// not throw an error message if the dependency fails to be resolved. | |||||
/// <code language="cs"> | |||||
/// public class MyModule : ModuleBase | |||||
/// { | |||||
/// [DontInject] | |||||
/// public DatabaseService DatabaseService; | |||||
/// public MyModule() | |||||
/// { | |||||
/// DatabaseService = DatabaseFactory.Generate(); | |||||
/// } | |||||
/// } | |||||
/// </code> | |||||
/// </example> | |||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] | ||||
public class DontInjectAttribute : Attribute | public class DontInjectAttribute : Attribute | ||||
{ | { | ||||
@@ -5,8 +5,28 @@ using System.Reflection; | |||||
namespace Discord.Commands | namespace Discord.Commands | ||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// Marks the <see cref="Type"/> to be read by the specified <see cref="TypeReader"/>. | |||||
/// Marks the <see cref="Type"/> to be read by the specified <see cref="Discord.Commands.TypeReader"/>. | |||||
/// </summary> | /// </summary> | ||||
/// <remarks> | |||||
/// This attribute will override the <see cref="Discord.Commands.TypeReader"/> to be used when parsing for the | |||||
/// desired type in the command. This is useful when one wishes to use a particular | |||||
/// <see cref="Discord.Commands.TypeReader"/> without affecting other commands that are using the same target | |||||
/// type. | |||||
/// <note type="warning"> | |||||
/// If the given type reader does not inherit from <see cref="Discord.Commands.TypeReader"/>, an | |||||
/// <see cref="ArgumentException"/> will be thrown. | |||||
/// </note> | |||||
/// </remarks> | |||||
/// <example> | |||||
/// In this example, the <see cref="TimeSpan"/> will be read by a custom | |||||
/// <see cref="Discord.Commands.TypeReader"/>, <c>FriendlyTimeSpanTypeReader</c>, instead of the | |||||
/// <see cref="TimeSpanTypeReader"/> shipped by Discord.Net. | |||||
/// <code language="cs"> | |||||
/// [Command("time")] | |||||
/// public Task GetTimeAsync([OverrideTypeReader(typeof(FriendlyTimeSpanTypeReader))]TimeSpan time) | |||||
/// => ReplyAsync(time); | |||||
/// </code> | |||||
/// </example> | |||||
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] | ||||
public class OverrideTypeReaderAttribute : Attribute | public class OverrideTypeReaderAttribute : Attribute | ||||
{ | { | ||||
@@ -11,6 +11,22 @@ namespace Discord.Commands | |||||
/// that has been marked as mature or NSFW. If the channel is not of type <see cref="ITextChannel"/> or the | /// that has been marked as mature or NSFW. If the channel is not of type <see cref="ITextChannel"/> or the | ||||
/// channel is not marked as NSFW, the precondition will fail with an erroneous <see cref="PreconditionResult"/>. | /// channel is not marked as NSFW, the precondition will fail with an erroneous <see cref="PreconditionResult"/>. | ||||
/// </remarks> | /// </remarks> | ||||
/// <example> | |||||
/// The following example restricts the command <c>too-cool</c> to an NSFW-enabled channel only. | |||||
/// <code language="cs"> | |||||
/// 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."); | |||||
/// } | |||||
/// </code> | |||||
/// </example> | |||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | ||||
public class RequireNsfwAttribute : PreconditionAttribute | public class RequireNsfwAttribute : PreconditionAttribute | ||||
{ | { | ||||
@@ -15,6 +15,22 @@ namespace Discord.Commands | |||||
/// ;otherwise, this precondition will always fail. | /// ;otherwise, this precondition will always fail. | ||||
/// </note> | /// </note> | ||||
/// </remarks> | /// </remarks> | ||||
/// <example> | |||||
/// 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. | |||||
/// <code language="cs"> | |||||
/// [RequireOwner] | |||||
/// [Group("admin")] | |||||
/// public class AdminModule : ModuleBase | |||||
/// { | |||||
/// [Command("exit")] | |||||
/// public async Task ExitAsync() | |||||
/// { | |||||
/// Environment.Exit(0); | |||||
/// } | |||||
/// } | |||||
/// </code> | |||||
/// </example> | |||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | ||||
public class RequireOwnerAttribute : PreconditionAttribute | public class RequireOwnerAttribute : PreconditionAttribute | ||||
{ | { | ||||
@@ -9,6 +9,12 @@ namespace Discord.Commands | |||||
/// <summary> | /// <summary> | ||||
/// A <see cref="TypeReader"/> for parsing objects implementing <see cref="IChannel"/>. | /// A <see cref="TypeReader"/> for parsing objects implementing <see cref="IChannel"/>. | ||||
/// </summary> | /// </summary> | ||||
/// <remarks> | |||||
/// This <see cref="TypeReader"/> is shipped with Discord.Net and is used by default to parse any | |||||
/// <see cref="IChannel"/> 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 <see cref="TypeReaderResult"/> is returned. | |||||
/// </remarks> | |||||
/// <typeparam name="T">The type to be checked; must implement <see cref="IChannel"/>.</typeparam> | /// <typeparam name="T">The type to be checked; must implement <see cref="IChannel"/>.</typeparam> | ||||
public class ChannelTypeReader<T> : TypeReader | public class ChannelTypeReader<T> : TypeReader | ||||
where T : class, IChannel | where T : class, IChannel | ||||
@@ -44,6 +44,7 @@ namespace Discord.Commands | |||||
_enumsByValue = byValueBuilder.ToImmutable(); | _enumsByValue = byValueBuilder.ToImmutable(); | ||||
} | } | ||||
/// <inheritdoc /> | |||||
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) | public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) | ||||
{ | { | ||||
object enumValue; | object enumValue; | ||||
@@ -1,4 +1,4 @@ | |||||
using System; | |||||
using System; | |||||
using System.Linq; | using System.Linq; | ||||
using System.Reflection; | using System.Reflection; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
@@ -24,6 +24,7 @@ namespace Discord.Commands | |||||
_baseTypeReader = baseTypeReader; | _baseTypeReader = baseTypeReader; | ||||
} | } | ||||
/// <inheritdoc /> | |||||
public override async Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) | public override async Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) | ||||
{ | { | ||||
if (string.Equals(input, "null", StringComparison.OrdinalIgnoreCase) || string.Equals(input, "nothing", StringComparison.OrdinalIgnoreCase)) | if (string.Equals(input, "null", StringComparison.OrdinalIgnoreCase) || string.Equals(input, "nothing", StringComparison.OrdinalIgnoreCase)) | ||||
@@ -24,6 +24,7 @@ namespace Discord.Commands | |||||
"%s's'", // 1s | "%s's'", // 1s | ||||
}; | }; | ||||
/// <inheritdoc /> | |||||
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) | public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) | ||||
{ | { | ||||
return (TimeSpan.TryParseExact(input.ToLowerInvariant(), Formats, CultureInfo.InvariantCulture, out var timeSpan)) | return (TimeSpan.TryParseExact(input.ToLowerInvariant(), Formats, CultureInfo.InvariantCulture, out var timeSpan)) | ||||