| @@ -1,12 +1,12 @@ | |||||
| --- | --- | ||||
| uid: FAQ.Commands.DI | |||||
| title: Questions about Dependency Injection with Commands | |||||
| uid: FAQ.Basics.DI | |||||
| title: Questions about Dependency Injection. | |||||
| --- | --- | ||||
| # Dependency-injection-related Questions | # Dependency-injection-related Questions | ||||
| In the following section, you will find common questions and answers | In the following section, you will find common questions and answers | ||||
| to utilizing dependency injection with @Discord.Commands, as well as | |||||
| to utilizing dependency injection with @Discord.Commands and @Discord.Interactions, as well as | |||||
| common troubleshooting steps regarding DI. | common troubleshooting steps regarding DI. | ||||
| ## What is a service? Why does my module not hold any data after execution? | ## What is a service? Why does my module not hold any data after execution? | ||||
| @@ -22,8 +22,7 @@ Service is often used to hold data externally so that they persist | |||||
| throughout execution. Think of it like a chest that holds | throughout execution. Think of it like a chest that holds | ||||
| whatever you throw at it that won't be affected by anything unless | whatever you throw at it that won't be affected by anything unless | ||||
| you want it to. Note that you should also learn Microsoft's | you want it to. Note that you should also learn Microsoft's | ||||
| implementation of [Dependency Injection] \([video]) before proceeding, | |||||
| as well as how it works in [Discord.Net](xref:Guides.TextCommands.DI#usage-in-modules). | |||||
| implementation of [Dependency Injection] \([video]) before proceeding. | |||||
| A brief example of service and dependency injection can be seen below. | A brief example of service and dependency injection can be seen below. | ||||
| @@ -32,18 +31,12 @@ A brief example of service and dependency injection can be seen below. | |||||
| [Dependency Injection]: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection | [Dependency Injection]: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection | ||||
| [video]: https://www.youtube.com/watch?v=QtDTfn8YxXg | [video]: https://www.youtube.com/watch?v=QtDTfn8YxXg | ||||
| ## Why is my `CommandService` complaining about a missing dependency? | |||||
| ## Why is my Command/Interaction Service complaining about a missing dependency? | |||||
| If you encounter an error similar to `Failed to create MyModule, | If you encounter an error similar to `Failed to create MyModule, | ||||
| dependency MyExternalDependency was not found.`, you may have | dependency MyExternalDependency was not found.`, you may have | ||||
| forgotten to add the external dependency to the dependency container. | forgotten to add the external dependency to the dependency container. | ||||
| Starting from Discord.Net 2.0, all dependencies required by each | |||||
| module must be present when the module is loaded into the | |||||
| [CommandService]. This means when loading the module, you must pass a | |||||
| valid [IServiceProvider] with the dependency loaded before the module | |||||
| can be successfully registered. | |||||
| For example, if your module, `MyModule`, requests a `DatabaseService` | For example, if your module, `MyModule`, requests a `DatabaseService` | ||||
| in its constructor, the `DatabaseService` must be present in the | in its constructor, the `DatabaseService` must be present in the | ||||
| [IServiceProvider] when registering `MyModule`. | [IServiceProvider] when registering `MyModule`. | ||||
| @@ -51,4 +44,3 @@ in its constructor, the `DatabaseService` must be present in the | |||||
| [!code-csharp[Missing Dependencies](samples/missing-dep.cs)] | [!code-csharp[Missing Dependencies](samples/missing-dep.cs)] | ||||
| [IServiceProvider]: xref:System.IServiceProvider | [IServiceProvider]: xref:System.IServiceProvider | ||||
| [CommandService]: xref:Discord.Commands.CommandService | |||||
| @@ -11,18 +11,32 @@ introduction to the Discord API ecosystem. | |||||
| ## How do I add my bot to my server/guild? | ## How do I add my bot to my server/guild? | ||||
| You can do so by using the [permission calculator] provided | |||||
| by [FiniteReality]. | |||||
| This tool allows you to set permissions that the bot will be assigned | |||||
| with, and invite the bot into your guild. With this method, bots will | |||||
| also be assigned a unique role that a regular user cannot use; this | |||||
| is what we call a `Managed` role. Because you cannot assign this | |||||
| role to any other users, it is much safer than creating a single | |||||
| role which, intentionally or not, can be applied to other users | |||||
| to escalate their privilege. | |||||
| [FiniteReality]: https://github.com/FiniteReality/permissions-calculator | |||||
| [permission calculator]: https://finitereality.github.io/permissions-calculator | |||||
| Inviting your bot can be done by using the O2Auth url generator provided by the [Discord Developer Portal]. | |||||
| Permissions can be granted by selecting the `bot` scope in the scopes section. | |||||
|  | |||||
| A permissions tab will appear below the scope selection, | |||||
| from which you can pick any permissions your bot may require to function. | |||||
| When invited, the role this bot is granted will include these permissions. | |||||
| If you grant no permissions, no role will be created for your bot upon invitation as there is no need for one. | |||||
|  | |||||
| When done selecting permissions, you can use the link below in your browser to invite the bot | |||||
| to servers you have `Manage Server` permission of. | |||||
|  | |||||
| If you are planning to play around with slash/context commands, | |||||
| make sure to check the `application commands` scope before inviting your bot! | |||||
| > [!NOTE] | |||||
| > You do not have to kick and reinvite your bot to update permissions/scopes later on. | |||||
| > Simply reusing the invite link with provided scopes/perms will update it accordingly. | |||||
| [Discord Developer Portal]: https://discord.com/developers/applications/ | |||||
| ## What is a token? | ## What is a token? | ||||
| @@ -11,8 +11,8 @@ public class CommandHandler | |||||
| public CommandHandler(DiscordSocketClient client) | public CommandHandler(DiscordSocketClient client) | ||||
| { | { | ||||
| _services = new ServiceCollection() | _services = new ServiceCollection() | ||||
| .AddService<CommandService>() | |||||
| .AddService(client) | |||||
| .AddSingleton<CommandService>() | |||||
| .AddSingleton(client) | |||||
| // We are missing DatabaseService! | // We are missing DatabaseService! | ||||
| .BuildServiceProvider(); | .BuildServiceProvider(); | ||||
| } | } | ||||
| @@ -25,5 +25,8 @@ public class CommandHandler | |||||
| // registered in this instance of _services. | // registered in this instance of _services. | ||||
| await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services); | await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services); | ||||
| // ... | // ... | ||||
| // The same approach applies to the interaction service. | |||||
| // Make sure to resolve these issues! | |||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -1,34 +1,54 @@ | |||||
| --- | --- | ||||
| uid: FAQ.Commands.Interactions | |||||
| title: Interaction service | |||||
| uid: FAQ.Interactions.Framework | |||||
| title: Interaction Framework | |||||
| --- | --- | ||||
| # Interaction commands in services | |||||
| # The Interaction Framework | |||||
| A chapter talking about the interaction service framework. | |||||
| For questions about interactions in general, refer to the [Interactions FAQ] | |||||
| Common misconceptions and questions about the Interaction Framework. | |||||
| ## How can I restrict some of my commands so only specific users can execute them? | |||||
| Based on how you want to implement the restrictions, you can use the | |||||
| built-in `RequireUserPermission` precondition, which allows you to | |||||
| restrict the command based on the user's current permissions in the | |||||
| guild or channel (*e.g., `GuildPermission.Administrator`, | |||||
| `ChannelPermission.ManageMessages`*). | |||||
| [RequireUserPermission]: xref:Discord.Commands.RequireUserPermissionAttribute | |||||
| > [!NOTE] | |||||
| > There are many more preconditions to use, including being able to make some yourself. | |||||
| > Examples on self-made preconditions can be found | |||||
| > [here](https://github.com/discord-net/Discord.Net/blob/dev/samples/InteractionFramework/Attributes/RequireOwnerAttribute.cs) | |||||
| ## Why do preconditions not hide my commands? | |||||
| In the current permission design by Discord, | |||||
| it is not very straight forward to limit vision of slash/context commands to users. | |||||
| If you want to hide commands, you should take a look at the commands' `DefaultPermissions` parameter. | |||||
| ## Module dependencies aren't getting populated by Property Injection? | ## Module dependencies aren't getting populated by Property Injection? | ||||
| Make sure the properties are publicly accessible and publicly settable. | Make sure the properties are publicly accessible and publicly settable. | ||||
| ## How do I use this * interaction specific method/property? | |||||
| If your interaction context holds a down-casted version of the interaction object, you need to up-cast it. | |||||
| Ideally, use pattern matching to make sure its the type of interaction you are expecting it to be. | |||||
| [!code-csharp[Property Injection](samples/propertyinjection.cs)] | |||||
| ## `InteractionService.ExecuteAsync()` always returns a successful result, how do i access the failed command execution results? | ## `InteractionService.ExecuteAsync()` always returns a successful result, how do i access the failed command execution results? | ||||
| If you are using `RunMode.Async` you need to setup your post-execution pipeline around `CommandExecuted` events. | |||||
| If you are using `RunMode.Async` you need to setup your post-execution pipeline around | |||||
| `..Executed` events exposed by the Interaction Service. | |||||
| ## How do I check if the executing user has * permission? | ## How do I check if the executing user has * permission? | ||||
| Refer to the [documentation about preconditions] | Refer to the [documentation about preconditions] | ||||
| [documentation about preconditions]: xref:Guides.ChatCommands.Preconditions | |||||
| ## How do I send the HTTP Response from inside the command modules. | ## How do I send the HTTP Response from inside the command modules. | ||||
| Set the `RestResponseCallback` property of [InteractionServiceConfig] with a delegate for handling HTTP Responses and use | Set the `RestResponseCallback` property of [InteractionServiceConfig] with a delegate for handling HTTP Responses and use | ||||
| `RestInteractionModuleBase` to create your command modules. `RespondAsync()` and `DeferAsync()` methods of this module base will use the | |||||
| `RestInteractionModuleBase` to create your command modules. `RespondWithModalAsync()`, `RespondAsync()` and `DeferAsync()` methods of this module base will use the | |||||
| `RestResponseCallback` to create interaction responses. | `RestResponseCallback` to create interaction responses. | ||||
| ## Is there a cleaner way of creating parameter choices other than using `[Choice]`? | ## Is there a cleaner way of creating parameter choices other than using `[Choice]`? | ||||
| @@ -49,4 +69,3 @@ It compares the _target base type_ key of the | |||||
| [TypeConverter]: xref:Discord.Interactions.TypeConverter | [TypeConverter]: xref:Discord.Interactions.TypeConverter | ||||
| [Interactions FAQ]: xref: FAQ.Basics.Interactions | [Interactions FAQ]: xref: FAQ.Basics.Interactions | ||||
| [InteractionServiceConfig]: xref:Discord.Interactions.InteractionServiceConfig | [InteractionServiceConfig]: xref:Discord.Interactions.InteractionServiceConfig | ||||
| [documentation about preconditions]: xref: Guides.ChatCommands.Preconditions | |||||
| @@ -1,11 +1,13 @@ | |||||
| --- | --- | ||||
| uid: FAQ.Basics.InteractionBasics | |||||
| title: Basics of interactions, common practice | |||||
| uid: FAQ.Interactions.General | |||||
| title: Interactions | |||||
| --- | --- | ||||
| # Interactions basics, where to get started | |||||
| # Interaction basics | |||||
| This section answers basic questions and common mistakes in handling application commands, and responding to them. | |||||
| This chapter mostly refers to interactions in general, | |||||
| and will include questions that are common among users of the Interaction Framework | |||||
| as well as users that register and handle commands manually. | |||||
| ## What's the difference between RespondAsync, DeferAsync and FollowupAsync? | ## What's the difference between RespondAsync, DeferAsync and FollowupAsync? | ||||
| @@ -24,33 +26,20 @@ DeferAsync will not send out a response, RespondAsync will. | |||||
| ## Im getting System.TimeoutException: 'Cannot respond to an interaction after 3 seconds!' | ## Im getting System.TimeoutException: 'Cannot respond to an interaction after 3 seconds!' | ||||
| This happens because your computers clock is out of sync or your trying to respond after 3 seconds. If your clock is out of sync and you cant fix it, you can set the `UseInteractionSnowflakeDate` to false in the config. | |||||
| This happens because your computers clock is out of sync or your trying to respond after 3 seconds. | |||||
| If your clock is out of sync and you can't fix it, you can set the `UseInteractionSnowflakeDate` to false in the [DiscordSocketConfig]. | |||||
| ## Bad form Exception when I try to create my commands, why do I get this? | |||||
| [!code-csharp[Interaction Sync](samples/interactionsyncing.cs)] | |||||
| Bad form exceptions are thrown if the slash, user or message command builder has invalid values. | |||||
| The following options could resolve your error. | |||||
| [DiscordClientConfig]: xref:Discord.WebSocket.DiscordSocketConfig | |||||
| #### Is your command name lowercase? | |||||
| ## How do I use this * interaction specific method/property? | |||||
| If your command name is not lowercase, it is not seen as a valid command entry. | |||||
| `Avatar` is invalid; `avatar` is valid. | |||||
| #### Are your values below or above the required amount? (This also applies to message components) | |||||
| Discord expects all values to be below maximum allowed. | |||||
| Going over this maximum amount of characters causes an exception. | |||||
| If your interaction context holds a down-casted version of the interaction object, you need to up-cast it. | |||||
| Ideally, use pattern matching to make sure its the type of interaction you are expecting it to be. | |||||
| > [!NOTE] | > [!NOTE] | ||||
| > All maximum and minimum value requirements can be found in the [Discord Developer Docs]. | |||||
| > For components, structure documentation is found [here]. | |||||
| [Discord Developer Docs]: https://discord.com/developers/docs/interactions/application-commands#application-commands | |||||
| [here]: https://discord.com/developers/docs/interactions/message-components#message-components | |||||
| #### Is your subcommand branching correct? | |||||
| Branching structure is covered properly here: xref:Guides.SlashCommands.SubCommand | |||||
| > Further documentation on pattern matching can be found [here](xref:Guides.Entities.Casting). | |||||
| ## My interaction commands are not showing up? | ## My interaction commands are not showing up? | ||||
| @@ -65,16 +54,6 @@ Did you register a guild command (should be instant), or waited more than an hou | |||||
| - Do you have the application commands scope checked when adding your bot to guilds? | - Do you have the application commands scope checked when adding your bot to guilds? | ||||
|  | |||||
| ## There are many options for creating commands, which do I use? | |||||
| [!code-csharp[Register examples](samples/registerint.cs)] | |||||
| > [!NOTE] | |||||
| > You can use bulkoverwrite even if there are no commands in guild, nor globally. | |||||
| > The bulkoverwrite method disposes the old set of commands and replaces it with the new. | |||||
| ## Do I need to create commands on startup? | ## Do I need to create commands on startup? | ||||
| If you are registering your commands for the first time, it is required to create them once. | If you are registering your commands for the first time, it is required to create them once. | ||||
| @@ -0,0 +1,45 @@ | |||||
| --- | |||||
| uid: FAQ.Interactions.Basics | |||||
| title: Interaction Basics | |||||
| --- | |||||
| # Manually handing interactions. | |||||
| This section talks about the manual building and responding to interactions. | |||||
| If you are using the interaction framework (highly recommended) this section does not apply to you. | |||||
| ## Bad form Exception when I try to create my commands, why do I get this? | |||||
| Bad form exceptions are thrown if the slash, user or message command builder has invalid values. | |||||
| The following options could resolve your error. | |||||
| #### Is your command name lowercase? | |||||
| If your command name is not lowercase, it is not seen as a valid command entry. | |||||
| `Avatar` is invalid; `avatar` is valid. | |||||
| #### Are your values below or above the required amount? (This also applies to message components) | |||||
| Discord expects all values to be below maximum allowed. | |||||
| Going over this maximum amount of characters causes an exception. | |||||
| > [!NOTE] | |||||
| > All maximum and minimum value requirements can be found in the [Discord Developer Docs]. | |||||
| > For components, structure documentation is found [here]. | |||||
| [Discord Developer Docs]: https://discord.com/developers/docs/interactions/application-commands#application-commands | |||||
| [here]: https://discord.com/developers/docs/interactions/message-components#message-components | |||||
| #### Is your subcommand branching correct? | |||||
| Branching structure is covered properly here: xref:Guides.SlashCommands.SubCommand | |||||
|  | |||||
| ## There are many options for creating commands, which do I use? | |||||
| [!code-csharp[Register examples](samples/registerint.cs)] | |||||
| > [!NOTE] | |||||
| > You can use bulkoverwrite even if there are no commands in guild, nor globally. | |||||
| > The bulkoverwrite method disposes the old set of commands and replaces it with the new. | |||||
| @@ -0,0 +1,6 @@ | |||||
| DiscordSocketConfig config = new() | |||||
| { | |||||
| UseInteractionSnowflakeDate = false | |||||
| }; | |||||
| DiscordSocketclient client = new(config); | |||||
| @@ -0,0 +1,8 @@ | |||||
| public class MyModule | |||||
| { | |||||
| // Intended. | |||||
| public InteractionService Service { get; set; } | |||||
| // Will not work. A private setter cannot be accessed by the serviceprovider. | |||||
| private InteractionService Service { get; private set; } | |||||
| } | |||||
| @@ -8,15 +8,32 @@ title: Questions about Legacy Versions | |||||
| This section refers to legacy library-related questions that do not | This section refers to legacy library-related questions that do not | ||||
| apply to the latest or recent version of the Discord.Net library. | apply to the latest or recent version of the Discord.Net library. | ||||
| ## Migrating your commands to application commands. | |||||
| The new interaction service was designed to act like the previous service for text-based commands. | |||||
| Your pre-existing code will continue to work, but you will need to migrate your modules and response functions to use the new | |||||
| interaction service methods. Documentation on this can be found in the [Guides](xref:Guides.IntFw.Intro). | |||||
| ## Gateway event parameters changed, why? | |||||
| With 3.0, a higher focus on [Cacheable]'s was introduced. | |||||
| [Cacheable]'s get an entity from cache, rather than making an API call to retrieve it's data. | |||||
| The entity can be retrieved from cache by calling `GetOrDownloadAsync()` on the [Cacheable] type. | |||||
| > [!NOTE] | |||||
| > GetOrDownloadAsync will download the entity if its not available directly from the cache. | |||||
| [Cacheable]: xref:Discord.Cacheable | |||||
| ## X, Y, Z does not work! It doesn't return a valid value anymore. | ## X, Y, Z does not work! It doesn't return a valid value anymore. | ||||
| If you are currently using an older version of the stable branch, | If you are currently using an older version of the stable branch, | ||||
| please upgrade to the latest pre-release version to ensure maximum | |||||
| please upgrade to the latest release version to ensure maximum | |||||
| compatibility. Several features may be broken in older | compatibility. Several features may be broken in older | ||||
| versions and will likely not be fixed in the version branch due to | versions and will likely not be fixed in the version branch due to | ||||
| their breaking nature. | their breaking nature. | ||||
| Visit the repo's [release tag] to see the latest public pre-release. | |||||
| Visit the repo's [release tag] to see the latest public release. | |||||
| [release tag]: https://github.com/discord-net/Discord.Net/releases | [release tag]: https://github.com/discord-net/Discord.Net/releases | ||||
| @@ -1,6 +1,6 @@ | |||||
| --- | --- | ||||
| uid: FAQ.Commands.General | |||||
| title: General Questions about chat Commands | |||||
| uid: FAQ.TextCommands.General | |||||
| title: General Questions about Text Commands | |||||
| --- | --- | ||||
| # Chat Command-related Questions | # Chat Command-related Questions | ||||
| @@ -10,21 +10,16 @@ answered regarding general command usage when using @Discord.Commands. | |||||
| ## How can I restrict some of my commands so only specific users can execute them? | ## How can I restrict some of my commands so only specific users can execute them? | ||||
| Based on how you want to implement the restrictions, you can use the | |||||
| built-in [RequireUserPermission] precondition, which allows you to | |||||
| You can use the built-in `RequireUserPermission` precondition, which allows you to | |||||
| restrict the command based on the user's current permissions in the | restrict the command based on the user's current permissions in the | ||||
| guild or channel (*e.g., `GuildPermission.Administrator`, | guild or channel (*e.g., `GuildPermission.Administrator`, | ||||
| `ChannelPermission.ManageMessages`*). | `ChannelPermission.ManageMessages`*). | ||||
| If, however, you wish to restrict the commands based on the user's | |||||
| role, you can either create your custom precondition or use | |||||
| Joe4evr's [Preconditions Addons] that provides a few custom | |||||
| preconditions that aren't provided in the stock library. | |||||
| Its source can also be used as an example for creating your | |||||
| custom preconditions. | |||||
| > [!NOTE] | |||||
| > There are many more preconditions to use, including being able to make some yourself. | |||||
| > Precondition documentation is covered [here](xref:Guides.TextCommands.Preconditions) | |||||
| [RequireUserPermission]: xref:Discord.Commands.RequireUserPermissionAttribute | [RequireUserPermission]: xref:Discord.Commands.RequireUserPermissionAttribute | ||||
| [Preconditions Addons]: https://github.com/Joe4evr/Discord.Addons/tree/master/src/Discord.Addons.Preconditions | |||||
| ## Why am I getting an error about `Assembly.GetEntryAssembly`? | ## Why am I getting an error about `Assembly.GetEntryAssembly`? | ||||
| @@ -6,15 +6,19 @@ | |||||
| topicUid: FAQ.Basics.BasicOp | topicUid: FAQ.Basics.BasicOp | ||||
| - name: Client Basics | - name: Client Basics | ||||
| topicUid: FAQ.Basics.ClientBasics | topicUid: FAQ.Basics.ClientBasics | ||||
| - name: Interactions | |||||
| topicUid: FAQ.Basics.InteractionBasics | |||||
| - name: Commands | |||||
| items: | |||||
| - name: String commands | |||||
| topicUid: FAQ.Commands.General | |||||
| - name: Interaction commands | |||||
| topicUid: FAQ.Commands.Interactions | |||||
| - name: Dependency Injection | - name: Dependency Injection | ||||
| topicUid: FAQ.Commands.DI | |||||
| topicUid: FAQ.Basics.DI | |||||
| - name: Interactions | |||||
| items: | |||||
| - name: Starting out | |||||
| topicUid: FAQ.Interactions.General | |||||
| - name: Interaction Service/Framework | |||||
| topicUid: FAQ.Interactions.Framework | |||||
| - name: Manual handling | |||||
| topicUid: FAQ.Interactions.Manual | |||||
| - name: Text Commands | |||||
| items: | |||||
| - name: Text Command basics | |||||
| topicUid: FAQ.TextCommands.General | |||||
| - name: Legacy or Upgrade | - name: Legacy or Upgrade | ||||
| topicUid: FAQ.Legacy | topicUid: FAQ.Legacy | ||||