diff --git a/docs/faq/Commands.md b/docs/faq/Commands.md index 7e8b23d7a..bc902811b 100644 --- a/docs/faq/Commands.md +++ b/docs/faq/Commands.md @@ -2,17 +2,17 @@ ## How can I restrict some of my commands so only certain 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` etc.*). - -If, however, you wish to restrict the commands based on the user's -role, you can either create your own 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 own +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` etc.*). + +If, however, you wish to restrict the commands based on the user's +role, you can either create your own 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 own custom preconditions. [RequireUserPermission]: xref:Discord.Commands.RequireUserPermissionAttribute @@ -20,8 +20,8 @@ custom preconditions. ## I'm getting an error about `Assembly#GetEntryAssembly`. -You may be confusing [CommandService#AddModulesAsync] with -[CommandService#AddModuleAsync]. The former is used to add modules +You may be confusing [CommandService#AddModulesAsync] with +[CommandService#AddModuleAsync]. The former is used to add modules via the assembly, while the latter is used to add a single module. [CommandService#AddModulesAsync]: xref:Discord.Commands.CommandService.AddModulesAsync* @@ -29,10 +29,10 @@ via the assembly, while the latter is used to add a single module. ## What does [Remainder] do in the command signature? -The [RemainderAttribute] leaves the string unparsed, meaning you -don't have to add quotes around the text for the text to be -recognized as a single object. Please note that if your method has -multiple parameters, the remainder attribute can only be applied to +The [RemainderAttribute] leaves the string unparsed, meaning you +don't have to add quotes around the text for the text to be +recognized as a single object. Please note that if your method has +multiple parameters, the remainder attribute can only be applied to the last parameter. [!code-csharp[Remainder](samples/commands/Remainder.cs)] @@ -41,17 +41,17 @@ the last parameter. ## 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. This means that they are spawned -every time when a request is received, and are killed from memory -when the execution finishes. This is why you cannot store persistent -data inside a module. To workaround this, consider using a service. - -Service is often used to hold data externally, so that they will -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, as well +In Discord.NET, modules are created similarly to ASP.NET, meaning +that they have a transient nature. This means that they are spawned +every time when a request is received, and are killed from memory +when the execution finishes. This is why you cannot store persistent +data inside a module. To workaround this, consider using a service. + +Service is often used to hold data externally, so that they will +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, as well as how it works in [Discord.NET](../guides/commands/commands.md#usage-in-modules). A brief example of service and dependency injection can be seen below. @@ -63,22 +63,22 @@ A brief example of service and dependency injection can be seen below. ## I have a long-running Task in my command, and Discord.NET keeps saying that a `MessageReceived` handler is blocking the gateway. What gives? -By default, all commands are executed on the same thread as the -gateway task, which is responsible for keeping the connection from -your client to Discord alive. By default, when you execute a command, -this blocks the gateway from communicating for as long as the command -task is being executed. The library will warn you about any long -running event handler (in this case, the command handler) that -persists for **more than 3 seconds**. +By default, all commands are executed on the same thread as the +gateway task, which is responsible for keeping the connection from +your client to Discord alive. By default, when you execute a command, +this blocks the gateway from communicating for as long as the command +task is being executed. The library will warn you about any long +running event handler (in this case, the command handler) that +persists for **more than 3 seconds**. -To resolve this, the library has designed a flag called [RunMode]. +To resolve this, the library has designed a flag called [RunMode]. There are 2 main `RunMode`s. - 1. `RunMode.Sync` (default) + 1. `RunMode.Sync` (default) 2. `RunMode.Async` You can set the `RunMode` either by specifying it individually via -the `CommandAttribute`, or by setting the global default with +the `CommandAttribute`, or by setting the global default with the [DefaultRunMode] flag under `CommandServiceConfig`. # [CommandAttribute](#tab/cmdattrib) @@ -94,10 +94,10 @@ the [DefaultRunMode] flag under `CommandServiceConfig`. *** > [!IMPORTANT] -> While specifying `RunMode.Async` allows the command to be spun off +> While specifying `RunMode.Async` allows the command to be spun off > to a different thread instead of the gateway thread, -> keep in mind that there will be **potential consequences** -> by doing so. Before applying this flag, please +> keep in mind that there will be **potential consequences** +> by doing so. Before applying this flag, please > consider whether it is necessary to do so. > > Further details regarding `RunMode.Async` can be found below. @@ -108,28 +108,28 @@ the [DefaultRunMode] flag under `CommandServiceConfig`. ## How does `RunMode.Async` work, and why is Discord.NET *not* using it by default? -`RunMode.Async` works by spawning a new `Task` with an unawaited -[Task.Run], essentially making `ExecuteAsyncInternalAsync`, the task -that is used to invoke the command task, to be finished on a +`RunMode.Async` works by spawning a new `Task` with an unawaited +[Task.Run], essentially making `ExecuteAsyncInternalAsync`, the task +that is used to invoke the command task, to be finished on a different thread. This means that [ExecuteAsync] will be forced to return a successful [ExecuteResult] regardless of the execution. The following are the known caveats with `RunMode.Async`, 1. You can potentially introduce race condition. 2. Unnecessary overhead caused by [async state machine]. - 3. [ExecuteAsync] will immediately return [ExecuteResult] instead of - other result types (this is particularly important for those who wish + 3. [ExecuteAsync] will immediately return [ExecuteResult] instead of + other result types (this is particularly important for those who wish to utilize [RuntimeResult] in 2.0). 4. Exceptions are swallowed. However, there are ways to remedy some of these. -For #3, in Discord.NET 2.0, the library introduces a new event called -[CommandExecuted], which is raised whenever the command is -**successfully executed**. This event will be raised regardless of +For #3, in Discord.NET 2.0, the library introduces a new event called +[CommandExecuted], which is raised whenever the command is +**successfully executed**. This event will be raised regardless of the `RunMode` type and will return the appropriate execution result. -For #4, exceptions are caught in [CommandService#Log] event under +For #4, exceptions are caught in [CommandService#Log] event under [LogMessage.Exception] as [CommandException]. [Task.Run]: https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run diff --git a/docs/faq/Glossary.md b/docs/faq/Glossary.md index 3a5198bb1..096bcc0ab 100644 --- a/docs/faq/Glossary.md +++ b/docs/faq/Glossary.md @@ -2,7 +2,7 @@ ## Common Types -* A **Guild** ([IGuild]) is an isolated collection of users and +* A **Guild** ([IGuild]) is an isolated collection of users and channels, and are often referred to as "servers". - Example: [Discord API](https://discord.gg/jkrBmQR) * A **Channel** ([IChannel]) represents either a voice or text channel. @@ -14,11 +14,11 @@ channels, and are often referred to as "servers". ## Channel Types ### Message Channels -* A **Text channel** ([ITextChannel]) is a message channel from a +* A **Text channel** ([ITextChannel]) is a message channel from a Guild. * A **DM channel** ([IDMChannel]) is a message channel from a DM. -* A **Group channel** ([IGroupChannel]) is a message channel from a -Group. +* A **Group channel** ([IGroupChannel]) is a message channel from a +Group. - This is rarely used due to the bot's inability to join groups. * A **Private channel** ([IPrivateChannel]) is a DM or a Group. * A **Message channel** ([IMessageChannel]) can be any of the above. @@ -27,7 +27,7 @@ Group. * A **Guild channel** ([IGuildChannel]) is a guild channel in a guild. - This can be any channels that may exist in a guild. * A **Voice channel** ([IVoiceChannel]) is a voice channel in a guild. -* A **Category channel** ([ICategoryChannel]) (2.0+) is a category that +* A **Category channel** ([ICategoryChannel]) (2.0+) is a category that holds one or more sub-channels. [IGuildChannel]: xref:Discord.IGuildChannel @@ -52,12 +52,12 @@ holds one or more sub-channels. ## Activity Types * A **Game** ([Game]) refers to a user's game activity. -* A **Rich Presence** ([RichGame]) refers to a user's detailed -gameplay status. +* A **Rich Presence** ([RichGame]) refers to a user's detailed +gameplay status. - Visit [Rich Presence Intro] on Discord docs for more info. -* A **Streaming Status** ([StreamingGame]) refers to user's activity +* A **Streaming Status** ([StreamingGame]) refers to user's activity for streaming on services such as Twitch. -* A **Spotify Status** ([SpotifyGame]) (2.0+) refers to a user's +* A **Spotify Status** ([SpotifyGame]) (2.0+) refers to a user's activity for listening to a song on Spotify. [Game]: xref:Discord.Game diff --git a/docs/faq/Legacy.md b/docs/faq/Legacy.md index 61d1b3d5a..925ee45b4 100644 --- a/docs/faq/Legacy.md +++ b/docs/faq/Legacy.md @@ -1,10 +1,10 @@ # Legacy Questions ## X, Y, Z does not work! It doesn't return a valid value anymore. -If you're currently using an older version in stable branch, please -upgrade to the latest pre-release version to ensure maximum -compatibility. Several features may be broken in older -versions and will likely not be fixed in the version branch due to +If you're currently using an older version in stable branch, please +upgrade to the latest pre-release version to ensure maximum +compatibility. Several features may be broken in older +versions and will likely not be fixed in the version branch due to their breaking nature. Visit the repo's [release tag] to see the latest public pre-release. @@ -12,8 +12,8 @@ Visit the repo's [release tag] to see the latest public pre-release. [release tag]: https://github.com/RogueException/Discord.Net/releases ## I came from an earlier version of Discord.NET 1.0, and DependencyMap doesn't seem to exist anymore in the later revision? What happened to it? -The `DependencyMap` has been replaced with Microsoft's -[DependencyInjection] Abstractions. An example usage can be seen +The `DependencyMap` has been replaced with Microsoft's +[DependencyInjection] Abstractions. An example usage can be seen [here](https://github.com/foxbot/DiscordBotBase/blob/csharp/src/DiscordBot/Program.cs#L36). [DependencyInjection]: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection \ No newline at end of file diff --git a/docs/faq/basic-operations.md b/docs/faq/basic-operations.md index e7490c8bb..c91f155e6 100644 --- a/docs/faq/basic-operations.md +++ b/docs/faq/basic-operations.md @@ -3,15 +3,15 @@ ## How should I safely check a type? > [!WARNING] -> Direct casting (e.g. `(Type)type`) is **the least recommended** -> way of casting, as it *can* throw an [InvalidCastException] +> Direct casting (e.g. `(Type)type`) is **the least recommended** +> way of casting, as it *can* throw an [InvalidCastException] > when the object isn't the desired type. > > Please refer to [this post] for more details. -In Discord.NET, the idea of polymorphism is used throughout. You may -need to cast the object as a certain type before you can perform any -action. +In Discord.NET, the idea of polymorphism is used throughout. You may +need to cast the object as a certain type before you can perform any +action. A good and safe casting example: @@ -25,15 +25,15 @@ A good and safe casting example: > [!TIP] > The [GetChannel] method by default returns an [IChannel]. > This means channels such as [IVoiceChannel], [ICategoryChannel] -> can be returned. This is why that you cannot send message +> can be returned. This is why that you cannot send message > to channels like those. Any implementation of [IMessageChannel] has a [SendMessageAsync] method. You can get the channel via [GetChannel] under the client. -Remember, when using Discord.NET, polymorphism is a common recurring -theme. This means an object may take in many shapes or form, which -means casting is your friend. You should attempt to cast the channel -as an [IMessageChannel] or any other entity that implements it to be +Remember, when using Discord.NET, polymorphism is a common recurring +theme. This means an object may take in many shapes or form, which +means casting is your friend. You should attempt to cast the channel +as an [IMessageChannel] or any other entity that implements it to be able to message. [SendMessageAsync]: xref:Discord.IMessageChannel.SendMessageAsync* @@ -41,7 +41,7 @@ able to message. ## How can I tell if a message is from X, Y, Z channel? -You may check the message channel type. Visit [Glossary] to see the +You may check the message channel type. Visit [Glossary] to see the various types of channels. [Glossary]: Glossary.md#message-channels @@ -50,13 +50,13 @@ various types of channels. There are 2 ways to do this. You can do either of the following, 1. Cast the user as an [IGuildUser] and use its [IGuild] property. - 2. Cast the channel as an [IGuildChannel] and use + 2. Cast the channel as an [IGuildChannel] and use its [IGuild] property. ## How do I add hyperlink text to an embed? -Embeds can use standard [markdown] in the description field as well -as in field values. With that in mind, links can be added with +Embeds can use standard [markdown] in the description field as well +as in field values. With that in mind, links can be added with `[text](link)`. [markdown]: https://support.discordapp.com/hc/en-us/articles/210298617-Markdown-Text-101-Chat-Formatting-Bold-Italic-Underline- @@ -64,26 +64,26 @@ as in field values. With that in mind, links can be added with ## How do I add reactions to a message? Any entities that implement [IUserMessage] has an [AddReactionAsync] -method. This method expects an [IEmote] as a parameter. -In Discord.Net, an Emote represents a server custom emote, while an -Emoji is a Unicode emoji (standard emoji). Both [Emoji] and [Emote] -implement [IEmote] and are valid options. +method. This method expects an [IEmote] as a parameter. +In Discord.Net, an Emote represents a server custom emote, while an +Emoji is a Unicode emoji (standard emoji). Both [Emoji] and [Emote] +implement [IEmote] and are valid options. [!code-csharp[Emoji](samples/basics/emoji.cs)] [AddReactionAsync]: xref:Discord.IUserMessage.AddReactionAsync* - + ## Why am I getting so many preemptive rate limits when I try to add more than one reactions? -This is due to how HTML header works, mistreating -0.25sec/action to 1sec. This casues the lib to throw preemptive rate -limit more frequently than it should for methods such as adding +This is due to how HTML header works, mistreating +0.25sec/action to 1sec. This casues the lib to throw preemptive rate +limit more frequently than it should for methods such as adding reactions. ## Can I opt-out of preemptive rate limits? - + Unfortunately, not at the moment. See [#401](https://github.com/RogueException/Discord.Net/issues/401). - + [IChannel]: xref:Discord.IChannel [ICategoryChannel]: xref:Discord.ICategoryChannel diff --git a/docs/faq/client-basics.md b/docs/faq/client-basics.md index a8de2a552..8c56e86fd 100644 --- a/docs/faq/client-basics.md +++ b/docs/faq/client-basics.md @@ -3,35 +3,35 @@ ## My client keeps returning 401 upon logging in! > [!WARNING] -> Userbot/selfbot (logging in with a user token) is not +> Userbot/selfbot (logging in with a user token) is not > officially supported with this library. > -> Logging in under a user account may result in account +> Logging in under a user account may result in account > termination! There are few possible reasons why this may occur. - 1. You are not using the appropriate [TokenType]. - If you are using a bot account created from the Discord Developer - portal, you should be using `TokenType.Bot`. - 2. You are not using the correct login credentials. - Please keep in mind that tokens start with `Mj*`. - If it starts with any other characters, chances are, you might be - using the *client secret*, which has nothing to do with the login + 1. You are not using the appropriate [TokenType]. + If you are using a bot account created from the Discord Developer + portal, you should be using `TokenType.Bot`. + 2. You are not using the correct login credentials. + Please keep in mind that tokens start with `Mj*`. + If it starts with any other characters, chances are, you might be + using the *client secret*, which has nothing to do with the login token. [TokenType]: xref:Discord.TokenType ## How do I do X, Y, Z when my bot connects/logs on? Why do I get a `NullReferenceException` upon calling any client methods after connect? -Your bot should **not** attempt to interact in any way with -guilds/servers until the [Ready] event fires. When the bot -connects, it first has to download guild information from -Discord in order for you to get access to any server -information; the client is not ready at this point. - -Technically, the [GuildAvailable] event fires once the data for a -particular guild has downloaded; however, it's best to wait for all -guilds to be downloaded. Once all downloads are complete, the [Ready] +Your bot should **not** attempt to interact in any way with +guilds/servers until the [Ready] event fires. When the bot +connects, it first has to download guild information from +Discord in order for you to get access to any server +information; the client is not ready at this point. + +Technically, the [GuildAvailable] event fires once the data for a +particular guild has downloaded; however, it's best to wait for all +guilds to be downloaded. Once all downloads are complete, the [Ready] event is triggered, then you can proceed to do whatever you like. [Ready]: xref:Discord.WebSocket.DiscordSocketClient.Ready @@ -39,14 +39,15 @@ event is triggered, then you can proceed to do whatever you like. ## How do I get a message's previous content when that message is edited? -If you need to do anything with messages (e.g. checking Reactions, -checking the content of edited/deleted messages), you must set the -[MessageCacheSize] in your [DiscordSocketConfig] settings in order to +If you need to do anything with messages (e.g. checking Reactions, +checking the content of edited/deleted messages), you must set the +[MessageCacheSize] in your [DiscordSocketConfig] settings in order to use the cached message entity. Read more about it [here](../guides/concepts/events.md#cacheable). + 1. Message Cache must be enabled. -2. Hook the MessageUpdated event. This event provides a *before* and +2. Hook the MessageUpdated event. This event provides a *before* and *after* object. -3. Only messages received *after* the bot comes online will be +3. Only messages received *after* the bot comes online will be available in the cache. [MessageCacheSize]: xref:Discord.WebSocket.DiscordSocketConfig.MessageCacheSize diff --git a/docs/faq/getting-started.md b/docs/faq/getting-started.md index c9fd7a738..1b1057bcf 100644 --- a/docs/faq/getting-started.md +++ b/docs/faq/getting-started.md @@ -1,81 +1,84 @@ # Basic Concepts / Getting Started ## How do I get started? -First of all, welcome! You may visit us on our Discord should you -have any questions. Before you delve into using the library, -however, you should have some decent understanding of the language -you are about to use. This library touches on -[Task-based Asynchronous Pattern] \(TAP), [polymorphism], [interface] -and many more advanced topics extensively. Please make sure that you + +First of all, welcome! You may visit us on our Discord should you +have any questions. Before you delve into using the library, +however, you should have some decent understanding of the language +you are about to use. This library touches on +[Task-based Asynchronous Pattern] \(TAP), [polymorphism], [interface] +and many more advanced topics extensively. Please make sure that you understand these topics to some extent before proceeding. - + Here are some examples: 1. [Official quick start guide](https://github.com/RogueException/Discord.Net/blob/dev/docs/guides/getting_started/samples/intro/structure.cs) 2. [Official template](https://github.com/foxbot/DiscordBotBase/tree/csharp/src/DiscordBot) -> [!TIP] -> Please note that you should *not* try to blindly copy paste -> the code. The examples are meant to be a template or a guide. +> [!TIP] +> Please note that you should *not* try to blindly copy paste +> the code. The examples are meant to be a template or a guide. > It is not meant to be something that will work out of the box. - + [Task-based Asynchronous Pattern]: https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap [polymorphism]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/polymorphism [interface]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/ - + ## How do I add my bot to my server/guild? -You can do so by using the [permission calculator] provided +You can do so by using the [permission calculator] provided by FiniteReality. -This tool allows you to set the permissions that the bot will be -added with, and invite the bot into your guild. With this method, -bots will also be assigned their own special roles that normal users +This tool allows you to set the permissions that the bot will be +added with, and invite the bot into your guild. With this method, +bots will also be assigned their own special roles that normal users cannot use; this is what we call a `Managed` role, and this is a much -safer method of permission management than to create a role that any +safer method of permission management than to create a role that any users can be assigned to. [permission calculator]: https://finitereality.github.io/permissions-calculator ## What is a Client/User/Object ID? Is it the token? -Each user and object on Discord has its own snowflake ID generated +Each user and object on Discord has its own snowflake ID generated based on various conditions. ![Snowflake Generation](images/snowflake.png) -The ID can be seen by anyone; it is public. It is merely used to -identify an object in the Discord ecosystem. Many things in the -library require an ID to retrieve the said object. - -There are 2 ways to obtain the said ID. - 1. Enable Discord's developer mode. With developer mode enabled, - you can - as an example - right click on a guild and copy the guild - id (please note that this does not apply to all objects, such as +The ID can be seen by anyone; it is public. It is merely used to +identify an object in the Discord ecosystem. Many things in the +library require an ID to retrieve the said object. + +There are 2 ways to obtain the said ID. + + 1. Enable Discord's developer mode. With developer mode enabled, + you can - as an example - right click on a guild and copy the guild + id (please note that this does not apply to all objects, such as Role IDs \[see below], or DM channel IDs). ![Developer Mode](images/dev-mode.png) - 2. Escape the object using `\` in front the object. For example, - when you do `\@Example#1234` in chat, it will return the user ID of + 2. Escape the object using `\` in front the object. For example, + when you do `\@Example#1234` in chat, it will return the user ID of the aforementioned user. - -A token is a credential used to log into an account. This information -should be kept **private** and for your eyes only. Anyone with your -token can log into your account. This applies to both user and bot -accounts. That also means that you should never ever hardcode your -token or add it into source control, as your identity may be stolen -by scrape bots on the internet that scours through constantly to + +A token is a credential used to log into an account. This information +should be kept **private** and for your eyes only. Anyone with your +token can log into your account. This applies to both user and bot +accounts. That also means that you should never ever hardcode your +token or add it into source control, as your identity may be stolen +by scrape bots on the internet that scours through constantly to obtain a token. ## How do I get the role ID? Several common ways to do this: - 1. Make the role mentionable and mention the role, and escape it + + 1. Make the role mentionable and mention the role, and escape it using the `\` character in front. 2. Inspect the roles collection within the guild via your debugger. - -Please note that right-clicking on the role and copying the ID will + +Please note that right-clicking on the role and copying the ID will **not** work. It will only copy the message ID. -## I have more questions! +## I have more questions! -Please visit us at #dotnet_discord-net at [Discord API]. -Describe the problem in details to us, and preferably with the +Please visit us at #dotnet_discord-net at [Discord API]. +Describe the problem in details to us, and preferably with the problematic code uploaded onto [Hastebin](https://hastebin.com). [Discord API]: https://discord.gg/jkrBmQR \ No newline at end of file