Skip to content

Commit

Permalink
Update the documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
KubaZ2 committed Nov 18, 2024
1 parent 30188b6 commit f20b0d2
Show file tree
Hide file tree
Showing 15 changed files with 143 additions and 100 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using NetCord;
using NetCord.Rest;
using NetCord.Services.ApplicationCommands;

namespace MyBot;

public class ExampleModule : ApplicationCommandModule<ApplicationCommandContext>
{
[SlashCommand("pong", "Pong!")]
public static string Pong() => "Ping!";

[UserCommand("ID")]
public static string Id(User user) => user.Id.ToString();

[MessageCommand("Timestamp")]
public static string Timestamp(RestMessage message) => message.CreatedAt.ToString();
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,32 @@
Intents = default,
});

ApplicationCommandService<SlashCommandContext> applicationCommandService = new();
// Create the application command service
ApplicationCommandService<ApplicationCommandContext> applicationCommandService = new();

// Add commands using minimal APIs
applicationCommandService.AddSlashCommand("ping", "Ping!", () => "Pong!");
applicationCommandService.AddUserCommand("Username", (User user) => user.Username);
applicationCommandService.AddMessageCommand("Length", (RestMessage message) => message.Content.Length.ToString());

// Add commands from modules
applicationCommandService.AddModules(typeof(Program).Assembly);

// Add the handler to handle interactions
client.InteractionCreate += async interaction =>
{
if (interaction is not SlashCommandInteraction slashCommandInteraction)
// Check if the interaction is an application command interaction
if (interaction is not ApplicationCommandInteraction applicationCommandInteraction)
return;

var result = await applicationCommandService.ExecuteAsync(new SlashCommandContext(slashCommandInteraction, client));
// Execute the command
var result = await applicationCommandService.ExecuteAsync(new ApplicationCommandContext(applicationCommandInteraction, client));

// Check if the execution failed
if (result is not IFailResult failResult)
return;

// Return the error message to the user if the execution failed
try
{
await interaction.SendResponseAsync(InteractionCallback.Message(failResult.Message));
Expand All @@ -32,6 +44,7 @@
}
};

// Create the commands so that you can use them in the Discord client
await applicationCommandService.CreateCommandsAsync(client.Rest, client.Id);

client.Log += message =>
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,26 @@
using NetCord.Hosting.Gateway;
using NetCord.Hosting.Services;
using NetCord.Hosting.Services.ApplicationCommands;
using NetCord.Rest;
using NetCord.Services.ApplicationCommands;

var builder = Host.CreateApplicationBuilder(args);

builder.Services
.AddDiscordGateway()
.AddApplicationCommands<SlashCommandInteraction, SlashCommandContext>()
.AddApplicationCommands<UserCommandInteraction, UserCommandContext>()
.AddApplicationCommands<MessageCommandInteraction, MessageCommandContext>();

var host = builder.Build()
.AddSlashCommand<SlashCommandContext>("ping", "Ping!", () => "Pong!")
.AddUserCommand<UserCommandContext>("Username", (UserCommandContext context) => context.Target.Username)
.AddMessageCommand<MessageCommandContext>("Length", (MessageCommandContext context) => context.Target.Content.Length.ToString())
.AddModules(typeof(Program).Assembly)
.UseGatewayEventHandlers();
.AddApplicationCommands<ApplicationCommandInteraction, ApplicationCommandContext>();

var host = builder.Build();

// Add commands using minimal APIs
host.AddSlashCommand("ping", "Ping!", () => "Pong!")
.AddUserCommand("Username", (User user) => user.Username)
.AddMessageCommand("Length", (RestMessage message) => message.Content.Length.ToString());

// Add commands from modules
host.AddModules(typeof(Program).Assembly);

// Add handlers to handle the commands
host.UseGatewayEventHandlers();

await host.RunAsync();
37 changes: 12 additions & 25 deletions Documentation/guides/services/application-commands/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ uid: application-commands

## [.NET Generic Host](#tab/generic-host)

Adding application commands with the .NET Generic Host is very easy. Use @NetCord.Hosting.Services.ApplicationCommands.ApplicationCommandServiceServiceCollectionExtensions.AddApplicationCommands``2(Microsoft.Extensions.DependencyInjection.IServiceCollection) to add an application command service to your host builder. Then, use @NetCord.Hosting.Services.ApplicationCommands.ApplicationCommandServiceHostExtensions.AddSlashCommand*, @NetCord.Hosting.Services.ApplicationCommands.ApplicationCommandServiceHostExtensions.AddUserCommand* or @NetCord.Hosting.Services.ApplicationCommands.ApplicationCommandServiceHostExtensions.AddMessageCommand* to add an application command using the minimal APIs way and/or use @NetCord.Hosting.Services.ServicesHostExtensions.AddModules(Microsoft.Extensions.Hosting.IHost,System.Reflection.Assembly) to add modules from an assembly. You also need to use @NetCord.Hosting.Gateway.GatewayEventHandlerHostExtensions.UseGatewayEventHandlers(Microsoft.Extensions.Hosting.IHost) to bind the service event handlers.
[!code-cs[Program.cs](IntroductionHosting/Program.cs?highlight=13-15,18-22)]
Adding application commands with the .NET Generic Host is very easy. Use @NetCord.Hosting.Services.ApplicationCommands.ApplicationCommandServiceServiceCollectionExtensions.AddApplicationCommands``2(Microsoft.Extensions.DependencyInjection.IServiceCollection) to add the application command service to your host builder. Then, use @NetCord.Hosting.Services.ApplicationCommands.ApplicationCommandServiceHostExtensions.AddSlashCommand*, @NetCord.Hosting.Services.ApplicationCommands.ApplicationCommandServiceHostExtensions.AddUserCommand* or @NetCord.Hosting.Services.ApplicationCommands.ApplicationCommandServiceHostExtensions.AddMessageCommand* to add an application command using the minimal APIs way and/or use @NetCord.Hosting.Services.ServicesHostExtensions.AddModules(Microsoft.Extensions.Hosting.IHost,System.Reflection.Assembly) to add application command modules from an assembly. You also need to use @NetCord.Hosting.Gateway.GatewayEventHandlerHostExtensions.UseGatewayEventHandlers(Microsoft.Extensions.Hosting.IHost) to bind the service event handlers.
[!code-cs[Program.cs](IntroductionHosting/Program.cs?highlight=14,19-21,24,27)]

## [Bare Bones](#tab/bare-bones)

First, add the following lines to using the section.
[!code-cs[Program.cs](Introduction/Program.cs#L4-L5)]
First, add the following lines to the using section.
[!code-cs[Program.cs](Introduction/Program.cs#L3-L5)]

Now, it's time to create @NetCord.Services.ApplicationCommands.ApplicationCommandService`1 instance and add application commands to it. You can do it by using @NetCord.Services.ApplicationCommands.ApplicationCommandService`1.AddSlashCommand*, @NetCord.Services.ApplicationCommands.ApplicationCommandService`1.AddUserCommand* or @NetCord.Services.ApplicationCommands.ApplicationCommandService`1.AddMessageCommand* to add an application command using the minimal APIs way and/or by using @NetCord.Services.ApplicationCommands.ApplicationCommandService`1.AddModules(System.Reflection.Assembly) to add modules from an assembly. You can use a context of your choice, it can be for example @NetCord.Services.ApplicationCommands.SlashCommandContext, @NetCord.Services.ApplicationCommands.UserCommandContext or @NetCord.Services.ApplicationCommands.MessageCommandContext. In this example, we will use @NetCord.Services.ApplicationCommands.SlashCommandContext.
[!code-cs[Program.cs](Introduction/Program.cs#L12-L14)]
Now, it's time to create @NetCord.Services.ApplicationCommands.ApplicationCommandService`1 instance and add application commands to it. You can do it by using @NetCord.Services.ApplicationCommands.ApplicationCommandService`1.AddSlashCommand*, @NetCord.Services.ApplicationCommands.ApplicationCommandService`1.AddUserCommand* or @NetCord.Services.ApplicationCommands.ApplicationCommandService`1.AddMessageCommand* to add an application command using the minimal APIs way and/or by using @NetCord.Services.ApplicationCommands.ApplicationCommandService`1.AddModules(System.Reflection.Assembly) to add application command modules from an assembly.
[!code-cs[Program.cs](Introduction/Program.cs#L12-L21)]

We can add a command handler now. If you used other context than @NetCord.Services.ApplicationCommands.SlashCommandContext, you should change the interaction type of the handler to the appropriate one.
[!code-cs[Program.cs](Introduction/Program.cs#L16-L33)]
[!code-cs[Program.cs](Introduction/Program.cs#L23-L45)]

Now, we should send the commands to Discord, to make them usable. Add the following line under the handler:
[!code-cs[Program.cs](Introduction/Program.cs#L35)]
[!code-cs[Program.cs](Introduction/Program.cs#L47-L48)]

### The Final Product

Expand All @@ -34,22 +34,9 @@ Now, we should send the commands to Discord, to make them usable. Add the follow
> If you don't see the commands in Discord, try refreshing the Discord client using `Ctrl + R` on PC or `⌘ + R` on Mac.
> [!IMPORTANT]
> Please note that names of:
> - slash commands
> - sub slash commands
> - slash command parameters
>
> **must** be lowercase.
> Please note that names of slash commands must be lowercase.
### Example Modules
### Example Module

Here you can see example modules for each type of application command.

#### Slash Command Module
[!code-cs[SlashCommandModule.cs](Introduction/SlashCommandModule.cs)]

#### User Command Module
[!code-cs[UserCommandModule.cs](Introduction/UserCommandModule.cs)]

#### Message Command Module
[!code-cs[MessageCommandModule.cs](Introduction/MessageCommandModule.cs)]
Here you can see an example module showing how to use modules with application commands.
[!code-cs[ExampleModule.cs](Introduction/ExampleModule.cs)]
36 changes: 24 additions & 12 deletions Documentation/guides/services/application-commands/parameters.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,47 @@
# Parameters

> [!WARNING]
> Parameters are supported only by slash commands.
## Slash Commands

Slash commands support up to 25 parameters.

### Optional parameters

## Optional parameters
To mark parameters as optional, give them a default value, example:
[!code-cs[ExampleModule.cs](Parameters/ExampleModule.cs#L8-L13)]

## Parameter name and description

> [!IMPORTANT]
> Parameter names **must** be lowercase.
### Parameter name and description

You can change parameter name and parameter description using @NetCord.Services.ApplicationCommands.SlashCommandParameterAttribute, example:
[!code-cs[ExampleModule.cs](Parameters/ExampleModule.cs#L15-L21)]

## Min and Max Values
### Min and Max Values

You can specify min and max parameter values by setting @NetCord.Services.ApplicationCommands.SlashCommandParameterAttribute.MinValue and @NetCord.Services.ApplicationCommands.SlashCommandParameterAttribute.MaxValue properties in @NetCord.Services.ApplicationCommands.SlashCommandParameterAttribute. It's only possible for numeric types.

## Min and Max Length
### Min and Max Length

You can specify min and max parameter length by setting @NetCord.Services.ApplicationCommands.SlashCommandParameterAttribute.MinLength and @NetCord.Services.ApplicationCommands.SlashCommandParameterAttribute.MaxLength properties in @NetCord.Services.ApplicationCommands.SlashCommandParameterAttribute. It's only possible for text types.

## Choices and Autocomplete
### Choices and Autocomplete

Choices are constants for a given parameter, autocomplete may depend on a text entered by a user.

### Choices
#### Choices

Choices are automatically generated when you set `enum` as a parameter type, you can override choices' names using @NetCord.Services.ApplicationCommands.SlashCommandChoiceAttribute on enum fields, example:
[!code-cs[ExampleModule.cs](Parameters/ExampleModule.cs#L23-L24)]
[!code-cs[Animal.cs](Parameters/Animal.cs#l5-L12)]

You can also define own choices in the Type Reader by overriding @NetCord.Services.ApplicationCommands.SlashCommandTypeReader`1.ChoicesProvider property or in @NetCord.Services.ApplicationCommands.SlashCommandParameterAttribute by setting @NetCord.Services.ApplicationCommands.SlashCommandParameterAttribute.ChoicesProviderType property.

### Autocomplete
#### Autocomplete

You can turn on autocomplete in Type Reader by overriding @NetCord.Services.ApplicationCommands.SlashCommandTypeReader`1.AutocompleteProviderType property or in @NetCord.Services.ApplicationCommands.SlashCommandParameterAttribute by setting @NetCord.Services.ApplicationCommands.SlashCommandParameterAttribute.AutocompleteProviderType property. You run it using @NetCord.Services.ApplicationCommands.ApplicationCommandService`2.ExecuteAutocompleteAsync(`1,System.IServiceProvider).

## User Commands

User commands only support a single parameter of type @NetCord.User. It's is not required, but allows you to access the target user of the user command easily.

## Message Commands

Message commands only support a single parameter of type @NetCord.Rest.RestMessage. It's is not required, but allows you to access the target message of the message command easily.
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,30 @@
Intents = default,
});

// Create the component interaction service with the button interaction context
ComponentInteractionService<ButtonInteractionContext> interactionService = new();

// Add a component interaction using minimal APIs
interactionService.AddInteraction("ping", () => "Pong!");

// Add component interactions from modules
interactionService.AddModules(typeof(Program).Assembly);

// Add the handler to handle interactions
client.InteractionCreate += async interaction =>
{
// Check if the interaction is a button interaction
if (interaction is not ButtonInteraction buttonInteraction)
return;

// Execute the interaction
var result = await interactionService.ExecuteAsync(new ButtonInteractionContext(buttonInteraction, client));

// Check if the execution failed
if (result is not IFailResult failResult)
return;

// Return the error message to the user if the execution failed
try
{
await interaction.SendResponseAsync(InteractionCallback.Message(failResult.Message));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,21 @@
.AddComponentInteractions<ChannelMenuInteraction, ChannelMenuInteractionContext>()
.AddComponentInteractions<ModalInteraction, ModalInteractionContext>();

var host = builder.Build()
.AddComponentInteraction<ButtonInteractionContext>("ping", () => "Pong!")
var host = builder.Build();

// Add component interactions using minimal APIs
host.AddComponentInteraction<ButtonInteractionContext>("ping", () => "Pong!")
.AddComponentInteraction<StringMenuInteractionContext>("string", (StringMenuInteractionContext context) => string.Join("\n", context.SelectedValues))
.AddComponentInteraction<UserMenuInteractionContext>("user", (UserMenuInteractionContext context) => string.Join("\n", context.SelectedUsers))
.AddComponentInteraction<RoleMenuInteractionContext>("role", (RoleMenuInteractionContext context) => string.Join("\n", context.SelectedRoles))
.AddComponentInteraction<MentionableMenuInteractionContext>("mentionable", (MentionableMenuInteractionContext context) => string.Join("\n", context.SelectedMentionables))
.AddComponentInteraction<ChannelMenuInteractionContext>("channel", (ChannelMenuInteractionContext context) => string.Join("\n", context.SelectedChannels))
.AddComponentInteraction<ModalInteractionContext>("modal", (ModalInteractionContext context) => context.Components[0].Value)
.AddModules(typeof(Program).Assembly)
.UseGatewayEventHandlers();
.AddComponentInteraction<ModalInteractionContext>("modal", (ModalInteractionContext context) => context.Components[0].Value);

// Add component interactions from modules
host.AddModules(typeof(Program).Assembly);

// Add handlers to handle the component interactions
host.UseGatewayEventHandlers();

await host.RunAsync();
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@ uid: component-interactions

## [.NET Generic Host](#tab/generic-host)

Adding component interactions with the .NET Generic Host is very easy. Use @NetCord.Hosting.Services.ComponentInteractions.ComponentInteractionServiceServiceCollectionExtensions.AddComponentInteractions``2(Microsoft.Extensions.DependencyInjection.IServiceCollection) to add a component interaction service to your host builder. Then, use @NetCord.Hosting.Services.ComponentInteractions.ComponentInteractionServiceHostExtensions.AddComponentInteraction* to add a component interaction using the minimal APIs way and/or use @NetCord.Hosting.Services.ServicesHostExtensions.AddModules(Microsoft.Extensions.Hosting.IHost,System.Reflection.Assembly) to add modules from an assembly. You also need to use @NetCord.Hosting.Gateway.GatewayEventHandlerHostExtensions.UseGatewayEventHandlers(Microsoft.Extensions.Hosting.IHost) to bind the service event handlers.
[!code-cs[Program.cs](IntroductionHosting/Program.cs?highlight=13-19,22-30)]
Adding component interactions with the .NET Generic Host is very easy. Use @NetCord.Hosting.Services.ComponentInteractions.ComponentInteractionServiceServiceCollectionExtensions.AddComponentInteractions``2(Microsoft.Extensions.DependencyInjection.IServiceCollection) to add a component interaction service to your host builder. Then, use @NetCord.Hosting.Services.ComponentInteractions.ComponentInteractionServiceHostExtensions.AddComponentInteraction* to add a component interaction using the minimal APIs way and/or use @NetCord.Hosting.Services.ServicesHostExtensions.AddModules(Microsoft.Extensions.Hosting.IHost,System.Reflection.Assembly) to add component interaction modules from an assembly. You also need to use @NetCord.Hosting.Gateway.GatewayEventHandlerHostExtensions.UseGatewayEventHandlers(Microsoft.Extensions.Hosting.IHost) to bind the service event handlers.

Unlike application commands, component interactions require maintaining context for each interaction, as the data between component interaction types can vary significantly. While it's possible to use a single context for all component interactions and cast them as needed, it's generally recommended to use distinct contexts for different types of component interactions. This is why multiple services are added to the service collection here - each one handles a specific type of component interaction. However, you likely won't need all of them, so feel free to remove the ones that aren't relevant to your use case.
[!code-cs[Program.cs](IntroductionHosting/Program.cs?highlight=13-19,24-30,33,36)]

## [Bare Bones](#tab/bare-bones)

First, add the following lines to the using section.
[!code-cs[Program.cs](Introduction/Program.cs#L4-L5)]
[!code-cs[Program.cs](Introduction/Program.cs#L3-L5)]

Now, it's time to create @NetCord.Services.ComponentInteractions.ComponentInteractionService`1 instance and add modules to it. In this example, we will use @NetCord.Services.ComponentInteractions.ButtonInteractionContext.
[!code-cs[Program.cs](Introduction/Program.cs#L12-L13)]
Now, it's time to create @NetCord.Services.ComponentInteractions.ComponentInteractionService`1 instance and add component interactions to it. In this example, we will use @NetCord.Services.ComponentInteractions.ButtonInteractionContext.
[!code-cs[Program.cs](Introduction/Program.cs#L12-L19)]

We can add an interaction handler now.
[!code-cs[Program.cs](Introduction/Program.cs#L15-L32)]
[!code-cs[Program.cs](Introduction/Program.cs#L21-L43)]

### The Final Product

Expand Down
Loading

0 comments on commit f20b0d2

Please sign in to comment.