diff --git a/DisCatSharp.Docs/articles/application_commands/intro.md b/DisCatSharp.Docs/articles/application_commands/intro.md index 9ec5f9e4d..45c4d15a2 100644 --- a/DisCatSharp.Docs/articles/application_commands/intro.md +++ b/DisCatSharp.Docs/articles/application_commands/intro.md @@ -1,129 +1,133 @@ --- uid: appcommands_intro title: Application Commands Introduction --- >[!NOTE] > This article assumes you've recently read the article on *[writing your first bot](xref:basics_first_bot)*. # Introduction to App Commands Discord provides built-in commands called: *Application Commands*.
Be sure to install the `DisCatSharp.ApplicationCommands` package from NuGet before continuing. At the moment it is possible to create such commands: - Slash commands - User context menu commands - Message context menu commands ## Writing an Application Commands ### Creation of the first commands >[!NOTE] > In order for the bot to be able to create commands in the guild, it must be added to a guild with `applications.commands` scope. Each command is a method with the attribute [SlashCommand](xref:DisCatSharp.ApplicationCommands.SlashCommandAttribute) or [ContextMenu](xref:DisCatSharp.ApplicationCommands.ContextMenuAttribute). They must be in classes that inherit from [ApplicationCommandsModule](xref:DisCatSharp.ApplicationCommands.ApplicationCommandsModule). Also, the first argument to the method must be [InteractionContext](xref:DisCatSharp.ApplicationCommands.InteractionContext) or [ContextMenuContext](xref:DisCatSharp.ApplicationCommands.ContextMenuContext). Simple slash command: ```cs public class MyCommand : ApplicationCommandsModule { [SlashCommand("my_command", "This is decription of the command.")] - public static async Task MySlashCommand(InteractionContext context) + public async Task MySlashCommand(InteractionContext context) { } } ``` Simple context menu command: ```cs public class MySecondCommand : ApplicationCommandsModule { [ContextMenu(ApplicationCommandType.User, "My Command")] - public static async Task MyContextMenuCommand(ContextMenuContext context) + public async Task MyContextMenuCommand(ContextMenuContext context) { } } ``` Now let's add some actions to the commands, for example, send a reply: ```cs await context.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, new DiscordInteractionResponseBuilder() { Content = "Hello :3" }); ``` If the command will be executed for more than 3 seconds, we must response at the beginning of execution and edit it at the end. ```cs await context.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, new DiscordInteractionResponseBuilder()); await Task.Delay(5000); // Simulating a long command execution. await ctx.EditResponseAsync(new DiscordWebhookBuilder() { Content = "Hello :3" }); ``` +>[!NOTE] +> Note that you can make your commands static, but then you cannot use [Dependency Injection](xref:commands_dependency_injection) in them. + + ### Registration of commands After writing the commands, we must register them. For this we need a [DiscordClient](xref:DisCatSharp.DiscordClient). ```cs var appCommands = client.UseApplicationCommands(); appCommands.RegisterCommands(); appCommands.RegisterCommands(); ``` Simple, isn't it? You can register global and guild commands. Global commands will be available on all guilds of which the bot is a member. Guild commands will only appear in a specific guild. >[!NOTE] >Global commands are updated within an hour, so it is recommended to use guild commands for testing and development. To register guild commands, it is enough to specify the Id of the guild as the first argument of the registration method. ```cs var appCommands = client.UseApplicationCommands(); appCommands.RegisterCommands(); appCommands.RegisterCommands(); ``` ## Command Groups Sometimes we may need to combine slash commands into groups. In this case, we need to wrap our class with commands in another class and add the [SlashCommandGroup](xref:DisCatSharp.ApplicationCommands.SlashCommandGroupAttribute) attribute. ```cs public class MyCommand : ApplicationCommandsModule { [SlashCommandGroup("my_command", "This is decription of the command group.")] public class MyCommandGroup : ApplicationCommandsModule { [SlashCommand("first", "This is decription of the command.")] - public static async Task MySlashCommand(InteractionContext context) + public async Task MySlashCommand(InteractionContext context) { await context.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, new DiscordInteractionResponseBuilder() { Content = "This is first subcommand." }); } [SlashCommand("second", "This is decription of the command.")] - public static async Task MySecondCommand(InteractionContext context) + public async Task MySecondCommand(InteractionContext context) { await context.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, new DiscordInteractionResponseBuilder() { Content = "This is second subcommand." }); } } } ``` Commands will now be available via `/my_command first` and `/my_command second`. Also, note that both classes must inherit [ApplicationCommandsModule](xref:DisCatSharp.ApplicationCommands.ApplicationCommandsModule). diff --git a/DisCatSharp.Docs/articles/basics/web_app.md b/DisCatSharp.Docs/articles/basics/web_app.md index a5a5fed15..937946f3d 100644 --- a/DisCatSharp.Docs/articles/basics/web_app.md +++ b/DisCatSharp.Docs/articles/basics/web_app.md @@ -1,140 +1,148 @@ --- uid: basics_web_app title: Bot as Hosted Service --- # Prerequisites Install the following packages: - DisCatSharp - DisCatSharp.Hosting +>[!IMPORTANT] +> This requires .NET 5.0. +> +> But, unfortunately, in this version, exception handling does not work during the initialization of bots. In case, for example, an invalid token, the application will be shut down. +> If you need to customize specific actions on initialization exception, you need to use .NET 6.0. + # Bot.cs Create a new class called `Bot` which inherits from `DiscordHostedService`. ```cs public class Bot : DiscordHostedService { public Bot(IConfiguration config, ILogger logger, IServiceProvider provider) : base(config, logger, provider) { } } ``` # Startup.cs By using the `DisCatSharp.Hosting.DependencyInjection` module, this 1 line is enough to get your basic bot running... ```cs public void ConfigureServices(IServiceCollection services) { services.AddDiscordHostedService(); } ``` If you prefer another DI approach / the manual route -- the following two lines are all you need! ```cs public void ConfigureServices(IServiceCollection services) { services.AddSingleton(); services.AddHostedService(provider => provider.GetRequiredService()); } ``` Singleton - we only want 1 instance of Bot to ever run during runtime.
Then we take the registered singleton to run as a `HostedService`. # How to reference Within a DI environment, when you want to reference your `Bot` all you have to do is add `IDiscordHostedService` as a parameter in the constructor. # How to Configure You must provide a token in order for the bot to work. Add the following to `appsettings.json` ```json { "DisCatSharp": { "Discord": { "Token": "YOUR TOKEN HERE" } } } ``` ## Extensions If you wish to add additional modules/extensions you can do so one of two ways. 1. Use the full namespace name 2. Namespace without the `DisCatSharp` prefix - because we assume the extension starts with DisCatSharp. To add the extensions `Interactivity` and `CommandsNext`: ```json { "DisCatSharp": { "Using": [ "DisCatSharp.Interactivity", "CommandsNext" ], "Discord": { "Token": "YOUR TOKEN HERE" }, "Interactivity": { "PollBehaviour": "KeepEmojis" }, "CommandsNext": { "StringPrefixes": [ "!" ] } } } ``` Note: to configure an extension, you simply add a section for it under `DisCatSharp` in `appsettings.json`. You only have to include values you **WISH TO OVERRIDE**. There is no need to include all config options if you only need to change 1 value. For more info on which values are available checkout the following classes: - `ApplicationCommandsConfiguration` - `CommandsNextConfiguration` - `DiscordConfiguration` - `InteractivityConfiguration` - `LavalinkConfiguration` - `VoiceNextConfiguration` +For more information, you can also see the [example](https://github.com/Aiko-IT-Systems/DisCatSharp.Examples/tree/main/Hosting). + ____ ## Values It's worth mentioning the required formats for certain value types ### Enum - Single Flag/Value - "`Value`" - Multiple Flags - "`Flag1|Flag2|Flag3`" #### Example ```json { "DisCatSharp": { "Discord": { "Intents": "GuildMembers|GuildsBans" } } } ``` ### TimeSpan Hours:Minutes:Seconds "`HH:mm:ss`" #### Example HttpTimeout of 5 minutes ```json { "DisCatSharp": { "Discord": { "HttpTimeout": "00:05:00" } } } ``` diff --git a/DisCatSharp.Docs/articles/important_changes/9_8_3.md b/DisCatSharp.Docs/articles/important_changes/9_8_3.md index bfbc555cc..293d08423 100644 --- a/DisCatSharp.Docs/articles/important_changes/9_8_3.md +++ b/DisCatSharp.Docs/articles/important_changes/9_8_3.md @@ -1,74 +1,74 @@ --- uid: important_changes_9_8_3 title: Version 9.8.3 --- # What changed? We [changed](https://canary.discord.com/channels/858089281214087179/858099438580006913/890973133148926004) the option to restrict channel types in Slash Commands to an extra Attribute named `ChannelTypes` in favour of the application command autocompletion. You can read about it [here](https://github.com/discord/discord-api-docs/pull/3849). ## Upgrade from **9.8.2** to **9.8.3** In **DisCatSharp.ApplicationComands** you restricted channel types like this: ```cs [SlashCommand("openstage", "Opens a stage")] public static async Task OpenStageAsync(InteractionContext ctx, [Option("stage", "Stage Channel", ChannelType.Stage)] DiscordChannel stage, [Option("topic", "Topic of stage")] string topic, [Option("notify", "Whether to notify people")] bool notify = false, [Option("make_public", "Whether the stage channel will be public")] bool make_public = false) { try { await ctx.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, new DiscordInteractionResponseBuilder().WithContent("Opening stage").AsEphemeral(true)); await stage.OpenStageAsync(topic, notify, make_public ? StagePrivacyLevel.PUBLIC : StagePrivacyLevel.GUILD_ONLY); await ctx.EditResponseAsync(new() { Content = "Stage channel has been successfully opened." }); } catch (Exception ex) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent(ex.Message + " " + ex.StackTrace)); } } ``` In **DisCatSharp.ApplicationComands** you restrict channel types now like this: ```cs [SlashCommand("openstage", "Opens a stage")] public static async Task OpenStageAsync(InteractionContext ctx, [Option("stage", "Stage Channel"), ChannelTypes(ChannelType.Stage)] DiscordChannel stage, [Option("topic", "Topic of stage")] string topic, [Option("notify", "Whether to notify people")] bool notify = false, [Option("make_public", "Whether the stage channel will be public")] bool make_public = false) { try { await ctx.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, new DiscordInteractionResponseBuilder().WithContent("Opening stage").AsEphemeral(true)); await stage.OpenStageAsync(topic, notify, make_public ? StagePrivacyLevel.PUBLIC : StagePrivacyLevel.GUILD_ONLY); await ctx.EditResponseAsync(new() { Content = "Stage channel has been successfully opened." }); } catch (Exception ex) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent(ex.Message + " " + ex.StackTrace)); } } ``` ## New function: Application Command Autocompletion: Examples: -> Autocomplete Option: https://github.com/Aiko-IT-Systems/DisCatSharp.Support/blob/main/Commands/Tasks/ConduitTasks.cs#L169 +> Autocomplete Option: https://github.com/Aiko-IT-Systems/DisCatSharp.Examples/blob/main/ApplicationCommands/src/Commands/Tags.cs#L34 -> Autocomplete Provider: https://github.com/Aiko-IT-Systems/DisCatSharp.Support/blob/main/Providers/ConduitProvider.cs#L106 +> Autocomplete Provider: https://github.com/Aiko-IT-Systems/DisCatSharp.Examples/blob/main/ApplicationCommands/src/Commands/Tags.cs#L168 Docs: https://docs.dcs.aitsys.dev/api/DisCatSharp.ApplicationCommands.Attributes.AutocompleteAttribute.html https://docs.dcs.aitsys.dev/api/DisCatSharp.ApplicationCommands.Attributes.IAutocompleteProvider.html https://docs.dcs.aitsys.dev/api/DisCatSharp.Entities.DiscordApplicationCommandAutocompleteChoice.html https://docs.dcs.aitsys.dev/api/DisCatSharp.ApplicationCommands.OptionAttribute.html#DisCatSharp_ApplicationCommands_OptionAttribute__ctor_System_String_System_String_System_Boolean_