diff --git a/samples/02_commands_framework/Modules/PublicModule.cs b/samples/02_commands_framework/Modules/PublicModule.cs index 8d55d8ba84..b9263649f8 100644 --- a/samples/02_commands_framework/Modules/PublicModule.cs +++ b/samples/02_commands_framework/Modules/PublicModule.cs @@ -60,6 +60,7 @@ public Task EchoAsync([Remainder] string text) public Task ListAsync(params string[] objects) => ReplyAsync("You listed: " + string.Join("; ", objects)); + // Setting a custom ErrorMessage property will help clarify the precondition error [Command("guild_only")] [RequireContext(ContextType.Guild, ErrorMessage = "Sorry, this command must be ran from within a server, not a DM!")] public Task GuildOnlyCommand() diff --git a/samples/02_commands_framework/Program.cs b/samples/02_commands_framework/Program.cs index 76c11f9f08..ccbc8e1657 100644 --- a/samples/02_commands_framework/Program.cs +++ b/samples/02_commands_framework/Program.cs @@ -37,10 +37,12 @@ public async Task MainAsync() client.Log += LogAsync; services.GetRequiredService().Log += LogAsync; - // Tokens should be considered secret data, and never hard-coded. + // Tokens should be considered secret data and never hard-coded. + // We can read from the environment variable to avoid hardcoding. await client.LoginAsync(TokenType.Bot, Environment.GetEnvironmentVariable("token")); await client.StartAsync(); + // Here we initialize the logic required to register our commands. await services.GetRequiredService().InitializeAsync(); await Task.Delay(-1); diff --git a/samples/02_commands_framework/Services/CommandHandlingService.cs b/samples/02_commands_framework/Services/CommandHandlingService.cs index d29be9201a..5ec496f788 100644 --- a/samples/02_commands_framework/Services/CommandHandlingService.cs +++ b/samples/02_commands_framework/Services/CommandHandlingService.cs @@ -20,12 +20,16 @@ public CommandHandlingService(IServiceProvider services) _discord = services.GetRequiredService(); _services = services; + // Hook CommandExecuted to handle post-command-execution logic. _commands.CommandExecuted += CommandExecutedAsync; + // Hook MessageReceived so we can process each message to see + // if it qualifies as a command. _discord.MessageReceived += MessageReceivedAsync; } public async Task InitializeAsync() { + // Register modules that are public and inherit ModuleBase. await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services); } @@ -37,10 +41,18 @@ public async Task MessageReceivedAsync(SocketMessage rawMessage) // This value holds the offset where the prefix ends var argPos = 0; + // Perform prefix check. You may want to replace this with + // (!message.HasCharPrefix('!', ref argPos)) + // for a more traditional command format like !help. if (!message.HasMentionPrefix(_discord.CurrentUser, ref argPos)) return; var context = new SocketCommandContext(_discord, message); - await _commands.ExecuteAsync(context, argPos, _services); // we will handle the result in CommandExecutedAsync + // Perform the execution of the command. In this method, + // the command service will perform precondition and parsing check + // then execute the command if one is matched. + await _commands.ExecuteAsync(context, argPos, _services); + // Note that normally a result will be returned by this format, but here + // we will handle the result in CommandExecutedAsync, } public async Task CommandExecutedAsync(Optional command, ICommandContext context, IResult result) @@ -49,12 +61,12 @@ public async Task CommandExecutedAsync(Optional command, ICommandCo if (!command.IsSpecified) return; - // the command was succesful, we don't care about this result, unless we want to log that a command succeeded. + // the command was successful, we don't care about this result, unless we want to log that a command succeeded. if (result.IsSuccess) return; // the command failed, let's notify the user that something happened. - await context.Channel.SendMessageAsync($"error: {result.ToString()}"); + await context.Channel.SendMessageAsync($"error: {result}"); } } }