Browse Source

Rewrite all concepts documentation

hello RC documentation
tags/1.0.0-rc2
Christopher F 8 years ago
parent
commit
3a60c58697
11 changed files with 284 additions and 18 deletions
  1. +4
    -0
      docs/guides/commands/commands.md
  2. +58
    -0
      docs/guides/concepts/connections.md
  3. +71
    -0
      docs/guides/concepts/entities.md
  4. +71
    -15
      docs/guides/concepts/events.md
  5. +23
    -0
      docs/guides/concepts/samples/connections.cs
  6. +13
    -0
      docs/guides/concepts/samples/entities.cs
  7. +31
    -0
      docs/guides/concepts/samples/events.cs
  8. +1
    -1
      docs/guides/getting_started/intro.md
  9. +9
    -0
      docs/guides/toc.yml
  10. +2
    -1
      docs/guides/voice/sending-voice.md
  11. +1
    -1
      docs/index.md

+ 4
- 0
docs/guides/commands/commands.md View File

@@ -1,5 +1,9 @@
# The Command Service # The Command Service


>[!WARNING]
>This article is out of date, and has not been rewritten yet.
Information is not guaranteed to be accurate.

[Discord.Commands](xref:Discord.Commands) provides an Attribute-based [Discord.Commands](xref:Discord.Commands) provides an Attribute-based
Command Parser. Command Parser.




+ 58
- 0
docs/guides/concepts/connections.md View File

@@ -0,0 +1,58 @@
---
title: Managing Connections
---

In Discord.Net, once a client has been started, it will automatically
maintain a connection to Discord's gateway, until it is manually
stopped.

### Usage

To start a connection, invoke the `StartAsync` method on a client that
supports a WebSocket connection.

These clients include the [DiscordSocketClient] and
[DiscordRpcClient], as well as Audio clients.

To end a connection, invoke the `StopAsync` method. This will
gracefully close 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.**

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

All clients provide a `Connected` and `Disconnected` event, which is
raised respectively when a connection opens or closes. In the case of
the DiscordSocketClient, this does **not** mean that the client is
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.

[DiscordSocketClient]: xref:Discord.WebSocket.DiscordSocketClient
[DiscordRpcClient]: xref:Discord.Rpc.DiscordRpcClient

### Samples

[!code-csharp[Connection Sample](samples/events.cs)]

### Tips

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.

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
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!

[events]: events.md

+ 71
- 0
docs/guides/concepts/entities.md View File

@@ -0,0 +1,71 @@
---
title: Entities
---

>[!NOTE]
This article is written with the Socket variants of entities in mind,
not the general interfaces or Rest/Rpc entities.

Discord.Net provides a versatile entity system for navigating the
Discord API.

### Inheritance

Due to the nature of the Discord API, some entities are designed with
multiple variants, for example, `SocketUser` and `SocketGuildUser`.

All models will contain the most detailed version of an entity
possible, even if the type is less detailed.

For example, in the case of the `MessageReceived` event, a
`SocketMessage` is passed in with a channel property of type
`SocketMessageChannel`. All messages come from channels capable of
messaging, so this is the only variant of a channel that can cover
every single case.

But that doesn't mean a message _can't_ come from a
`SocketTextChannel`, which is a message channel in a guild. To
retrieve information about a guild from a message entity, you will
need to cast its channel object to a `SocketTextChannel`.

### Navigation

All socket entities have navigation properties on them, which allow
you to easily navigate to an entity's parent or children. As explained
above, you will sometimes need to cast to a more detailed version of
an entity to navigate to its parent.

All socket entities have a `Discord` property, which will allow you
to access the parent `DiscordSocketClient`.

### Accessing Entities

The most basic forms of entities, `SocketGuild`, `SocketUser`, and
`SocketChannel` can be pulled from the DiscordSocketClient's global
cache, and can be retrieved using the respective `GetXXX` method on
DiscordSocketClient.

>[!TIP]
It is **vital** that you use the proper IDs for an entity when using
a GetXXX method. It is recommended that you enable Discord's
_developer mode_ to allow easy access to entity IDs, found in
Settings > Appearance > Advanced

More detailed versions of entities can be pulled from the basic
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.

### Samples

[!code-csharp[Entity Sample](samples/entities.cs)]

### Tips

Avoid using boxing-casts to coerce entities into a variant, use the
`as` keyword, and a null-conditional operator.

This allows you to write safer code, and avoid InvalidCastExceptions.

For example, `(message.Author as SocketGuildUser)?.Nickname`.

+ 71
- 15
docs/guides/concepts/events.md View File

@@ -1,28 +1,84 @@
--- ---
title: Events
title: Working with Events
--- ---


# Events
Events in Discord.Net are consumed in a similar manner to the standard
convention, with the exception that every event must be of the type
`System.Threading.Tasks.Task`, and instead of using EventArgs, the
event's parameters are passed directly into the handler.


Messages from Discord are exposed via events, and follow a pattern of `Func<[event params], Task>`, which allows you to easily create either async or sync event handlers.
This allows for events to be handled in an async context directly,
instead of relying on async void.


To hook into events, you must be using the @Discord.WebSocket.DiscordSocketClient, which provides WebSocket capabilities, necessary for receiving events.
### Usage


>[!NOTE]
>The gateway will wait for all registered handlers of an event to finish before raising the next event. As a result of this, it is reccomended that if you need to perform any heavy work in an event handler, it is done on its own thread or Task.
To receive data from an event, hook into it using C#'s delegate
event pattern.


**For further documentation of all events**, it is reccomended to look at the [Events Section](xref:Discord.WebSocket.DiscordSocketClient#events) on the API documentation of @Discord.WebSocket.DiscordSocketClient
You may opt either to hook an event to an anonymous function (lambda)
or a named function.


## Connection State
### Safety


Connection Events will be raised when the Connection State of your client changes.
All events are designed to be thread-safe, in that events are executed
synchronously off the gateway task, in the same context as the gateway
task.


[DiscordSocketClient.Connected](xref:Discord.WebSocket.DiscordSocketClient#Discord_WebSocket_DiscordSocketClient_Connected) and [Disconnected](xref:Discord.WebSocket.DiscordSocketClient#Discord_WebSocket_DiscordSocketClient_Disconnected) are raised when the Gateway Socket connects or disconnects, respectively.
As a side effect, this makes it possible to deadlock the gateway task,
and kill a connection. As a general rule of thumb, any task that takes
longer than three seconds should **not** be awaited directly in the
context of an event, but should be wrapped in a `Task.Run` or
offloaded to another task.


>[!WARNING]
>You should not use DiscordClient.Connected to run code when your client first connects to Discord. The client has not received and parsed the READY event and guild stream yet, and will have an incomplete or empty cache.
This also means that you should not await a task that requests data
from Discord's gateway in the same context of an event. Since the
gateway will wait on all invoked event handlers to finish before
processing any additional data from the gateway, this will create
a deadlock that will be impossible to recover from.


[DiscordSocketClient.Ready](xref:Discord.WebSocket.DiscordSocketClient#Discord_WebSocket_DiscordSocketClient_Ready) is raised when the `READY` packet is parsed and received from Discord.
Exceptions in commands will be swallowed by the gateway and logged out
through the client's log method.


>[!NOTE]
>The [DiscordSocketClient.ConnectAsync](xref:Discord.WebSocket.DiscordSocketClient#Discord_WebSocket_DiscordSocketClient_ConnectAsync_System_Boolean_) method will not return until the READY packet has been processed. By default, it also will not return until the guild stream has finished. This means it is safe to run bot code directly after awaiting the ConnectAsync method.
### Common Patterns

As you may know, events in Discord.Net are only given a signature of
`Func<T1, ..., Task>`. There is no room for predefined argument names,
so you must either consult IntelliSense, or view the API documentation
directly.

That being said, there are a variety of common patterns that allow you
to infer what the parameters in an event mean.

#### Entity, Entity

An event handler with a signature of `Func<Entity, Entity, Task>`
typically means that the first object will be a clone of the entity
_before_ a change was made, and the latter object will be an attached
model of the entity _after_ the change was made.

This pattern is typically only found on `EntityUpdated` events.

#### Cacheable

An event handler with a signature of `Func<Cacheable, Entity, Task>`
means that the `before` state of the entity was not provided by the
API, so it can either be pulled from the client's cache, or
downloaded from the API.

See the documentation for [Cacheable] for more information on this
object.

[Cacheable]: xref:Discord.Cacheable`2

### Samples

[!code-csharp[Event Sample](samples/events.cs)]

### Tips

Many events relating to a Message entity, e.g. `MessageUpdated`
and `ReactionAdded` rely on the client's message cache, which is
**not** enabled by default. Set the `MessageCacheSize` flag in
[DiscordSocketConfig] to enable it.

[DiscordSocketConfig]: xref:Discord.WebSocket.DiscordSocketConfig

+ 23
- 0
docs/guides/concepts/samples/connections.cs View File

@@ -0,0 +1,23 @@
using Discord;
using Discord.WebSocket;

public class Program
{
private DiscordSocketClient _client;
static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult();
public async Task MainAsync()
{
_client = new DiscordSocketClient();

await _client.LoginAsync(TokenType.Bot, "bot token");
await _client.StartAsync();

Console.WriteLine("Press any key to exit...");
Console.ReadKey();

await _client.StopAsync();
// Wait a little for the client to finish disconnecting before allowing the program to return
await Task.Delay(500);
}
}

+ 13
- 0
docs/guides/concepts/samples/entities.cs View File

@@ -0,0 +1,13 @@
public string GetChannelTopic(ulong id)
{
var channel = client.GetChannel(81384956881809408) as SocketTextChannel;
if (channel == null) return "";
return channel.Topic;
}

public string GuildOwner(SocketChannel channel)
{
var guild = (channel as SocketGuildChannel)?.Guild;
if (guild == null) return "";
return Context.Guild.Owner.Username;
}

+ 31
- 0
docs/guides/concepts/samples/events.cs View File

@@ -0,0 +1,31 @@
using Discord;
using Discord.WebSocket;

public class Program
{
private DiscordSocketClient _client;
static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult();
public async Task MainAsync()
{
_client = new DiscordSocketClient();

await _client.LoginAsync(TokenType.Bot, "bot token");
await _client.StartAsync();

_client.MessageUpdated += MessageUpdated;
_client.Ready += () =>
{
Console.WriteLine("Bot is connected!");
return Task.CompletedTask;
}
await Task.Delay(-1);
}

private async Task MessageUpdated(Cacheable<IMessage, ulong> before, SocketMessage after, ISocketMessageChannel channel)
{
var message = await before.GetOrDownloadAsync();
Console.WriteLine($"{message} -> {after}");
}
}

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

@@ -205,7 +205,7 @@ For your reference, you may view the [completed program].


[MessageReceived]: xref:Discord.WebSocket.DiscordSocketClient#Discord_WebSocket_DiscordSocketClient_MessageReceived [MessageReceived]: xref:Discord.WebSocket.DiscordSocketClient#Discord_WebSocket_DiscordSocketClient_MessageReceived
[SocketMessage]: xref:Discord.WebSocket.SocketMessage [SocketMessage]: xref:Discord.WebSocket.SocketMessage
[SocketMessageChannel]: xref:Discord.WebSocket.SocketMessageChannel
[SocketMessageChannel]: xref:Discord.WebSocket.ISocketMessageChannel
[completed program]: samples/intro/complete.cs [completed program]: samples/intro/complete.cs


# Building a bot with commands # Building a bot with commands


+ 9
- 0
docs/guides/toc.yml View File

@@ -12,7 +12,16 @@
href: concepts/logging.md href: concepts/logging.md
- name: Working with Events - name: Working with Events
href: concepts/events.md href: concepts/events.md
- name: Managing Connections
href: concepts/connections.md
- name: Entities - name: Entities
href: concepts/entities.md
- name: The Command Service - name: The Command Service
items:
- name: Command Guide
href: commands/commands.md
- name: Voice - name: Voice
items:
- name: Voice Guide
href: voice/sending-voice.md
- name: Migrating from 0.9 - name: Migrating from 0.9

+ 2
- 1
docs/guides/voice/sending-voice.md View File

@@ -5,7 +5,8 @@ title: Sending Voice
**Information on this page is subject to change!** **Information on this page is subject to change!**


>[!WARNING] >[!WARNING]
>Audio in 1.0 is in progress
>This article is out of date, and has not been rewritten yet.
Information is not guaranteed to be accurate.


## Installing ## Installing




+ 1
- 1
docs/index.md View File

@@ -3,7 +3,7 @@


Discord.Net is an asynchronous, multiplatform .NET Library used to interface with the [Discord API](https://discordapp.com/). Discord.Net is an asynchronous, multiplatform .NET Library used to interface with the [Discord API](https://discordapp.com/).


If this is your first time using Discord.Net, you should refer to the [Intro](guides/intro.md) for tutorials.
If this is your first time using Discord.Net, you should refer to the [Intro](guides/getting_started/intro.md) for tutorials.
More experienced users might refer to the [API Documentation](api/index.md) for a breakdown of the individuals objects in the library. More experienced users might refer to the [API Documentation](api/index.md) for a breakdown of the individuals objects in the library.


For additional resources: For additional resources:


Loading…
Cancel
Save