FAQ rework, replacing outdated info, better interaction FAQ (#2106)
* FAQ rework, replacing outdated info, better interaction faq * Update docs/faq/basics/getting-started.md Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Update docs/faq/basics/getting-started.md Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Update docs/faq/int_framework/general.md Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * fix TOC reference Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> Co-authored-by: Quin Lynch <lynchquin@gmail.com>
This commit is contained in:
46
docs/faq/basics/dependency-injection.md
Normal file
46
docs/faq/basics/dependency-injection.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
uid: FAQ.Basics.DI
|
||||
title: Questions about Dependency Injection.
|
||||
---
|
||||
|
||||
# Dependency-injection-related Questions
|
||||
|
||||
In the following section, you will find common questions and answers
|
||||
to utilizing dependency injection with @Discord.Commands and @Discord.Interactions, as well as
|
||||
common troubleshooting steps regarding DI.
|
||||
|
||||
## What is a service? Why does my module not hold any data after execution?
|
||||
|
||||
In Discord.Net, modules are created similarly to ASP.NET, meaning
|
||||
that they have a transient nature; modules are spawned whenever a
|
||||
request is received, and are killed from memory when the execution
|
||||
finishes. In other words, you cannot store persistent
|
||||
data inside a module. Consider using a service if you wish to
|
||||
workaround this.
|
||||
|
||||
Service is often used to hold data externally so that they persist
|
||||
throughout execution. Think of it like a chest that holds
|
||||
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
|
||||
implementation of [Dependency Injection] \([video]) before proceeding.
|
||||
|
||||
A brief example of service and dependency injection can be seen below.
|
||||
|
||||
[!code-csharp[DI](samples/DI.cs)]
|
||||
|
||||
[Dependency Injection]: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection
|
||||
[video]: https://www.youtube.com/watch?v=QtDTfn8YxXg
|
||||
|
||||
## Why is my Command/Interaction Service complaining about a missing dependency?
|
||||
|
||||
If you encounter an error similar to `Failed to create MyModule,
|
||||
dependency MyExternalDependency was not found.`, you may have
|
||||
forgotten to add the external dependency to the dependency container.
|
||||
|
||||
For example, if your module, `MyModule`, requests a `DatabaseService`
|
||||
in its constructor, the `DatabaseService` must be present in the
|
||||
[IServiceProvider] when registering `MyModule`.
|
||||
|
||||
[!code-csharp[Missing Dependencies](samples/missing-dep.cs)]
|
||||
|
||||
[IServiceProvider]: xref:System.IServiceProvider
|
||||
@@ -11,18 +11,32 @@ introduction to the Discord API ecosystem.
|
||||
|
||||
## 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.
|
||||
Inviting your bot can be done by using the OAuth2 url generator provided by the [Discord Developer Portal].
|
||||
|
||||
[FiniteReality]: https://github.com/FiniteReality/permissions-calculator
|
||||
[permission calculator]: https://finitereality.github.io/permissions-calculator
|
||||
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 where you have the `Manage Server` permission.
|
||||
|
||||

|
||||
|
||||
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?
|
||||
|
||||
|
||||
BIN
docs/faq/basics/images/link.png
Normal file
BIN
docs/faq/basics/images/link.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
BIN
docs/faq/basics/images/permissions.png
Normal file
BIN
docs/faq/basics/images/permissions.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 59 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
BIN
docs/faq/basics/images/scopes.png
Normal file
BIN
docs/faq/basics/images/scopes.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
@@ -1,88 +0,0 @@
|
||||
---
|
||||
uid: FAQ.Basics.InteractionBasics
|
||||
title: Basics of interactions, common practice
|
||||
---
|
||||
|
||||
# Interactions basics, where to get started
|
||||
|
||||
This section answers basic questions and common mistakes in handling application commands, and responding to them.
|
||||
|
||||
## What's the difference between RespondAsync, DeferAsync and FollowupAsync?
|
||||
|
||||
The difference between these 3 functions is in how you handle the command response.
|
||||
[RespondAsync] and
|
||||
[DeferAsync] let the API know you have succesfully received the command. This is also called 'acknowledging' a command.
|
||||
DeferAsync will not send out a response, RespondAsync will.
|
||||
[FollowupAsync] follows up on succesful acknowledgement.
|
||||
|
||||
> [!WARNING]
|
||||
> If you have not acknowledged the command FollowupAsync will not work! the interaction has not been resonded to, so you cannot follow it up!
|
||||
|
||||
[RespondAsync]: xref:Discord.IDiscordInteraction
|
||||
[DeferAsync]: xref:Discord.IDiscordInteraction
|
||||
[FollowUpAsync]: xref:Discord.IDiscordInteraction
|
||||
|
||||
## 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.
|
||||
|
||||
## 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
|
||||
|
||||
## My interaction commands are not showing up?
|
||||
|
||||
If you registered your commands globally, it can take up to 1 hour for them to register.
|
||||
Did you register a guild command (should be instant), or waited more than an hour and still don't have them show up?
|
||||
|
||||
- Try to check for any errors in the console, there is a good chance something might have been thrown.
|
||||
|
||||
- Register your commands after the Ready event in the client. The client is not configured to register commands before this moment.
|
||||
|
||||
- Check if no bad form exception is thrown; If so, refer to the above question.
|
||||
|
||||
- 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?
|
||||
|
||||
If you are registering your commands for the first time, it is required to create them once.
|
||||
After this, commands will exist indefinitely until you overwrite them.
|
||||
Overwriting is only required if you make changes to existing commands, or add new ones.
|
||||
|
||||
## I can't see all of my user/message commands, why?
|
||||
|
||||
Message and user commands have a limit of 5 per guild, and another 5 globally.
|
||||
If you have more than 5 guild-only message commands being registered, no more than 5 will actually show up.
|
||||
You can get up to 10 entries to show if you register 5 per guild, and another 5 globally.
|
||||
28
docs/faq/basics/samples/DI.cs
Normal file
28
docs/faq/basics/samples/DI.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
public class MyService
|
||||
{
|
||||
public string MyCoolString { get; set; }
|
||||
}
|
||||
public class Setup
|
||||
{
|
||||
public IServiceProvider BuildProvider() =>
|
||||
new ServiceCollection()
|
||||
.AddSingleton<MyService>()
|
||||
.BuildServiceProvider();
|
||||
}
|
||||
public class MyModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
// Inject via public settable prop
|
||||
public MyService MyService { get; set; }
|
||||
|
||||
// ...or via the module's constructor
|
||||
|
||||
// private readonly MyService _myService;
|
||||
// public MyModule (MyService myService) => _myService = myService;
|
||||
|
||||
[Command("string")]
|
||||
public Task GetOrSetStringAsync(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_myService.MyCoolString)) _myService.MyCoolString = input;
|
||||
return ReplyAsync(_myService.MyCoolString);
|
||||
}
|
||||
}
|
||||
32
docs/faq/basics/samples/missing-dep.cs
Normal file
32
docs/faq/basics/samples/missing-dep.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
public class MyModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
private readonly DatabaseService _dbService;
|
||||
public MyModule(DatabaseService dbService)
|
||||
=> _dbService = dbService;
|
||||
}
|
||||
public class CommandHandler
|
||||
{
|
||||
private readonly CommandService _commands;
|
||||
private readonly IServiceProvider _services;
|
||||
public CommandHandler(DiscordSocketClient client)
|
||||
{
|
||||
_services = new ServiceCollection()
|
||||
.AddSingleton<CommandService>()
|
||||
.AddSingleton(client)
|
||||
// We are missing DatabaseService!
|
||||
.BuildServiceProvider();
|
||||
}
|
||||
public async Task RegisterCommandsAsync()
|
||||
{
|
||||
// ...
|
||||
// The method fails here because DatabaseService is a required
|
||||
// dependency and cannot be resolved by the dependency
|
||||
// injection service at runtime since the service is not
|
||||
// registered in this instance of _services.
|
||||
await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
|
||||
// ...
|
||||
|
||||
// The same approach applies to the interaction service.
|
||||
// Make sure to resolve these issues!
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
private async Task ReadyAsync()
|
||||
{
|
||||
// pull your commands from some array, everyone has a different approach for this.
|
||||
var commands = _builders.ToArray();
|
||||
|
||||
// write your list of commands globally in one go.
|
||||
await _client.Rest.BulkOverwriteGlobalCommands(commands);
|
||||
|
||||
// write your array of commands to one guild in one go.
|
||||
// You can do a foreach (... in _client.Guilds) approach to write to all guilds.
|
||||
await _client.Rest.BulkOverwriteGuildCommands(commands, /* some guild ID */);
|
||||
|
||||
foreach (var c in commands)
|
||||
{
|
||||
// Create a global command, repeating usage for multiple commands.
|
||||
await _client.Rest.CreateGlobalCommand(c);
|
||||
|
||||
// Create a guild command, repeating usage for multiple commands.
|
||||
await _client.Rest.CreateGuildCommand(c, guildId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user