Browse Source

Initial proofread of the articles

pull/1161/head
Still Hsu 7 years ago
parent
commit
ea82c2537e
No known key found for this signature in database GPG Key ID: 8601A145FDA95209
14 changed files with 105 additions and 98 deletions
  1. +4
    -4
      docs/faq/basics/basic-operations.md
  2. +4
    -4
      docs/faq/basics/client-basics.md
  3. +15
    -13
      docs/faq/basics/getting-started.md
  4. +45
    -40
      docs/faq/commands/commands.md
  5. +1
    -1
      docs/faq/commands/samples/Remainder.cs
  6. +2
    -2
      docs/faq/misc/legacy.md
  7. +1
    -1
      docs/guides/commands/intro.md
  8. +18
    -18
      docs/guides/commands/post-execution.md
  9. +7
    -7
      docs/guides/concepts/connections.md
  10. +2
    -2
      docs/guides/concepts/deployment.md
  11. +1
    -1
      docs/guides/concepts/entities.md
  12. +1
    -1
      docs/guides/concepts/events.md
  13. +1
    -1
      docs/guides/concepts/logging.md
  14. +3
    -3
      docs/guides/getting_started/terminology.md

+ 4
- 4
docs/faq/basics/basic-operations.md View File

@@ -8,7 +8,7 @@ title: Questions about Basic Operations
## How should I safely check a type?

> [!WARNING]
> Direct casting (e.g. `(Type)type`) is **the least recommended**
> 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.
>
@@ -28,9 +28,9 @@ A good and safe casting example:
## How do I send a message?

> [!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
> The [GetChannel] method by default returns an [IChannel], allowing
> channel types such as [IVoiceChannel], [ICategoryChannel]
> to be returned; consequently, you cannot send a message
> to channels like those.

Any implementation of [IMessageChannel] has a [SendMessageAsync]


+ 4
- 4
docs/faq/basics/client-basics.md View File

@@ -21,7 +21,7 @@ There are few possible reasons why this may occur.
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 is **different** from a *client secret*.
mind that a token is **different** from a *client secret*.

[TokenType]: xref:Discord.TokenType
[827]: https://github.com/RogueException/Discord.Net/issues/827
@@ -33,11 +33,11 @@ There are few possible reasons why this may occur.
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
Discord 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
particular guild has downloaded; however, it is 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.

@@ -46,7 +46,7 @@ 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,
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](xref:Guides.Concepts.Events#cacheable).


+ 15
- 13
docs/faq/basics/getting-started.md View File

@@ -8,25 +8,27 @@ title: Beginner Questions / How to Get Started
## 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 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
users can be assigned to.

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

## What is a token?

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.
token can log into your account. This risk applies to both user
and bot accounts. That also means that you should **never** 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.

## What is a client/user/object ID?



+ 45
- 40
docs/faq/commands/commands.md View File

@@ -5,37 +5,35 @@ title: Questions about Commands

# Command-related Questions

## How can I restrict some of my commands so only certain 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
restrict the command based on the user's current permissions in the
guild or channel (*e.g. `GuildPermission.Administrator`,
`ChannelPermission.ManageMessages` etc.*).
guild or channel (*e.g., `GuildPermission.Administrator`,
`ChannelPermission.ManageMessages`*).

If, however, you wish to restrict the commands based on the user's
role, you can either create your own custom precondition or use
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 own
Its source can also be used as an example for creating your
custom preconditions.

[RequireUserPermission]: xref:Discord.Commands.RequireUserPermissionAttribute
[Preconditions Addons]: https://github.com/Joe4evr/Discord.Addons/tree/master/src/Discord.Addons.Preconditions

## I'm getting an error about `Assembly#GetEntryAssembly`.
## I am getting an error about `Assembly.GetEntryAssembly`.

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*
[CommandService#AddModuleAsync]: xref:Discord.Commands.CommandService.AddModuleAsync*
You may be confusing @Discord.Commands.CommandService.AddModulesAsync*
with @Discord.Commands.CommandService.AddModuleAsync*. The former
is used to add modules 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
do not 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.
@@ -47,13 +45,14 @@ 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
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,
@@ -68,15 +67,23 @@ 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. 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, the library warns the user about any long-running event
handler that persists for **more than 3 seconds**. Any event
handlers that are run on the same thread as the gateway task, the task
in charge of keeping the connection alive, may block the processing of
heartbeat, and thus terminating the connection.

In this case, the library detects that a `MessageReceived`
event handler is blocking the gateway thread. This warning is
typically associated with the command handler as it listens for that
particular event. If the command handler is blocking the thread, then
this **might** mean that you have a long-running command (in rare
cases, runtime errors can also cause blockage, usually associated
with Mono, which is not supported by this library).

To resolve this, the library has designed a flag called [RunMode].
To prevent a long-running command from blocking the gateway
thread, a flag called [RunMode] is explicitly designed to resolve
this issue.

There are 2 main `RunMode`s.

@@ -84,7 +91,7 @@ There are 2 main `RunMode`s.
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)
@@ -101,10 +108,9 @@ the [DefaultRunMode] flag under `CommandServiceConfig`.

> [!IMPORTANT]
> 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
> consider whether it is necessary to do so.
> to a different thread, keep in mind that by doing so, there will be
> **potentially unwanted consequences**. Before applying this flag,
> please consider whether it is necessary to do so.
>
> Further details regarding `RunMode.Async` can be found below.

@@ -115,16 +121,15 @@ 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
different thread. This means that [ExecuteAsync] will be forced to
return a successful [ExecuteResult] regardless of the actual
execution result.
[Task.Run], essentially making the task that is used to invoke the
command task to be finished on a different thread. This design means
that [ExecuteAsync] will be forced to return a successful
[ExecuteResult] regardless of the actual execution result.

The following are the known caveats with `RunMode.Async`,

1. You can potentially introduce race condition.
2. Unnecessary overhead caused by [async state machine].
1. You can potentially introduce a race condition.
2. Unnecessary overhead caused by the [async state machine].
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).


+ 1
- 1
docs/faq/commands/samples/Remainder.cs View File

@@ -16,5 +16,5 @@ public Task EchoAsync(string text) => ReplyAsync(text);
// Wrapping the message in quotes solves this.
// This way, the system knows the entire message is to be parsed as a
// single String.
// e.g.
// e.g.,
// !echo "Coffee Cake"

+ 2
- 2
docs/faq/misc/legacy.md View File

@@ -7,8 +7,8 @@ title: Questions about Legacy Versions

## 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
If you are currently using an older version of the 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.


+ 1
- 1
docs/guides/commands/intro.md View File

@@ -107,7 +107,7 @@ be found in @Guides.Commands.TypeReaders.
#### Optional Parameters

Parameters, by default, are always required. To make a parameter
optional, give it a default value (i.e. `int num = 0`).
optional, give it a default value (i.e., `int num = 0`).

#### Parameters with Spaces



+ 18
- 18
docs/guides/commands/post-execution.md View File

@@ -6,18 +6,18 @@ title: Post-command Execution Handling
# Preface

When developing commands, you may want to consider building a
post-execution handling system so you can have a finer control
post-execution handling system so you can have finer control
over commands. Discord.Net offers several post-execution workflows
for you to work with.

If you recall, in the [Command Guide], we've shown the following
If you recall, in the [Command Guide], we have shown the following
example for executing and handling commands,

[!code[Command Handler](samples/command_handler.cs)]

You may notice that after we perform [ExecuteAsync], we store the
result and print it to the chat. This is essentially the most
basic post-execution handling.
result and print it to the chat, essentially creating the most
fundamental form of a post-execution handler.

With this in mind, we could start doing things like the following,

@@ -25,8 +25,8 @@ With this in mind, we could start doing things like the following,

However, this may not always be preferred, because you are
creating your post-execution logic *with* the essential command
handler. This could lead to messy code and could potentially be a
violation of the SRP (Single Responsibility Principle).
handler. This design could lead to messy code and could potentially
be a violation of the SRP (Single Responsibility Principle).

Another major issue is if your command is marked with
`RunMode.Async`, [ExecuteAsync] will **always** return a successful
@@ -37,8 +37,8 @@ about the impact in the [FAQ](xref:FAQ.Commands).

Enter [CommandExecuted], an event that was introduced in
Discord.Net 2.0. This event is raised whenever a command is
successfully executed **without any run-time exceptions** or **without
any parsing or precondition failure**. This means this event can be
successfully executed **without any run-time exceptions** or **any
parsing or precondition failure**. This means this event can be
used to streamline your post-execution design, and the best thing
about this event is that it is not prone to `RunMode.Async`'s
[ExecuteAsync] drawbacks.
@@ -52,7 +52,7 @@ next? We can take this further by using [RuntimeResult].

### RuntimeResult

`RuntimeResult` was originally introduced in 1.0 to allow
`RuntimeResult` was initially introduced in 1.0 to allow
developers to centralize their command result logic.
In other words, it is a result type that is designed to be
returned when the command has finished its execution.
@@ -62,7 +62,7 @@ However, it wasn't widely adopted due to the aforementioned
result-handler via the [CommandExecuted] event, we can start
making use of this class.

The best way to make use of it is to create your own version of
The best way to make use of it is to create your version of
`RuntimeResult`. You can achieve this by inheriting the `RuntimeResult`
class.

@@ -71,16 +71,16 @@ of `RuntimeResult`,

[!code[Base Use](samples/customresult_base.cs)]

The sky's the limit from here. You can add any additional information
you'd like regarding the execution result.
The sky is the limit from here. You can add any additional information
you would like regarding the execution result.

For example, you may want to add your own result type or other
For example, you may want to add your result type or other
helpful information regarding the execution, or something
simple like static methods to help you create return types easily.

[!code[Extended Use](samples/customresult_extended.cs)]

After you're done creating your own [RuntimeResult], you can
After you're done creating your [RuntimeResult], you can
implement it in your command by marking the command return type to
`Task<RuntimeResult>`.

@@ -100,12 +100,12 @@ And now we can check for it in our [CommandExecuted] handler:
## CommandService.Log Event

We have so far covered the handling of various result types, but we
haven't talked about what to do if the command enters a catastrophic
failure (i.e. exceptions). To resolve this, we can make use of the
have not talked about what to do if the command enters a catastrophic
failure (i.e., exceptions). To resolve this, we can make use of the
[CommandService.Log] event.

All exceptions thrown during a command execution will be caught and
be sent to the Log event under the [LogMessage.Exception] property
All exceptions thrown during a command execution are caught and sent
to the Log event under the [LogMessage.Exception] property
as a [CommandException] type. The [CommandException] class allows
us to access the exception thrown, as well as the context
of the command.


+ 7
- 7
docs/guides/concepts/connections.md View File

@@ -11,14 +11,14 @@ stopped.

To start a connection, invoke the `StartAsync` method on a client that
supports a WebSocket connection; to end a connection, invoke the
`StopAsync` method. This will gracefully close any open WebSocket or
`StopAsync` method, which gracefully closes any open WebSocket or
UdpSocket connections.

Since the Start/Stop methods only signal to an underlying connection
manager that a connection needs to be started, **they return before a
connection is actually made.**
connection is made.**

As a result, you will need to hook into one of the connection-state
As a result, you need to hook into one of the connection-state
based events to have an accurate representation of when a client is
ready for use.

@@ -29,7 +29,7 @@ ready to be used.

A separate event, `Ready`, is provided on [DiscordSocketClient], which
is raised only when the client has finished guild stream or guild
sync, and has a complete guild cache.
sync and has a completed guild cache.

[DiscordSocketClient]: xref:Discord.WebSocket.DiscordSocketClient

@@ -41,8 +41,8 @@ sync, and has a complete guild cache.

> [!TIP]
> Avoid running long-running code on the gateway! If you deadlock the
> gateway (as explained in [events]), the connection manager will be
> unable to recover and reconnect.
> gateway (as explained in [events]), the connection manager will
> **NOT** be able to recover and reconnect.

Assuming the client disconnected because of a fault on Discord's end,
and not a deadlock on your end, we will always attempt to reconnect
@@ -50,6 +50,6 @@ and resume a connection.

Don't worry about trying to maintain your own connections, the
connection manager is designed to be bulletproof and never fail - if
your client doesn't manage to reconnect, you've found a bug!
your client does not manage to reconnect, you have found a bug!

[events]: xref:Guides.Concepts.Events

+ 2
- 2
docs/guides/concepts/deployment.md View File

@@ -68,7 +68,7 @@ for use on another machine without installing the dependencies first.
This can be achieved by using the dotnet CLI too on the development
machine:

`dotnet publish -c Release`
* `dotnet publish -c Release`

Additionally, you may want to target a specific platform when
publishing the application so you may use the application without
@@ -80,7 +80,7 @@ For example, when targeting a Windows 10 machine, you may want to use
the following to create the application in Windows executable
format (.exe):

`dotnet publish -c Release -r win10-x64`
* `dotnet publish -c Release -r win10-x64`

[.NET Core application deployment]: https://docs.microsoft.com/en-us/dotnet/core/deploying/
[Runtime ID]: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog

+ 1
- 1
docs/guides/concepts/entities.md View File

@@ -56,7 +56,7 @@ DiscordSocketClient.
> [FAQ](xref:FAQ.Basics.GetStarted) page.

More detailed versions of entities can be pulled from the basic
entities, e.g. `SocketGuild.GetUser`, which returns a
entities, e.g., `SocketGuild.GetUser`, which returns a
`SocketGuildUser`, or `SocketGuild.GetChannel`, which returns a
`SocketGuildChannel`. Again, you may need to cast these objects to get
a variant of the type that you need.


+ 1
- 1
docs/guides/concepts/events.md View File

@@ -74,7 +74,7 @@ object.
[Cacheable]: xref:Discord.Cacheable`2

> [!NOTE]
> Many events relating to a Message entity (i.e. `MessageUpdated` and
> Many events relating to a Message entity (i.e., `MessageUpdated` and
> `ReactionAdded`) rely on the client's message cache, which is
> **not** enabled by default. Set the `MessageCacheSize` flag in
> @Discord.WebSocket.DiscordSocketConfig to enable it.


+ 1
- 1
docs/guides/concepts/logging.md View File

@@ -16,7 +16,7 @@ section.
> [!WARNING]
> Due to the nature of Discord.Net's event system, all log event
> handlers will be executed synchronously on the gateway thread. If your
> log output will be dumped to a Web API (e.g. Sentry), you are advised
> log output will be dumped to a Web API (e.g., Sentry), you are advised
> to wrap your output in a `Task.Run` so the gateway thread does not
> become blocked while waiting for logging data to be written.



+ 3
- 3
docs/guides/getting_started/terminology.md View File

@@ -28,13 +28,13 @@ addon will run on all platforms.

`Discord.Net.Rest` provides a set of concrete classes to be used
**strictly** with the REST portion of Discord's API. Entities in this
implementation are prefixed with `Rest` (e.g. `RestChannel`).
implementation are prefixed with `Rest` (e.g., `RestChannel`).

`Discord.Net.Rpc` provides a set of concrete classes that are used
with Discord's RPC API. Entities in this implementation are prefixed
with `Rpc` (e.g. `RpcChannel`).
with `Rpc` (e.g., `RpcChannel`).

`Discord.Net.WebSocket` provides a set of concrete classes that are
used primarily with Discord's WebSocket API or entities that are kept
in cache. When developing bots, you will be using this implementation.
All entities are prefixed with `Socket` (e.g. `SocketChannel`).
All entities are prefixed with `Socket` (e.g., `SocketChannel`).

Loading…
Cancel
Save