Browse Source

Improve various articles

+ Rename Guides.Concepts.Logging title from 'Logging' to 'Logging Events/Data'.
+ Rewrite various sections of Guides.GettingStarted.FirstBot and Guides.GettingStarted.Installing based on suggested changes from #1027.
+ Rename project.csproj example to project.xml to avoid auto-compilation from Visual Studio Code.
+ Rename 'samples\intro' to 'samples\first-bot' to reflect on the article name change.
+ Clean first-bot samples.
pull/988/head
Hsu Still 7 years ago
parent
commit
4bb6263abd
No known key found for this signature in database GPG Key ID: 8601A145FDA95209
14 changed files with 182 additions and 191 deletions
  1. +1
    -1
      docs/guides/concepts/logging.md
  2. +84
    -69
      docs/guides/getting_started/first-bot.md
  3. +37
    -33
      docs/guides/getting_started/installing.md
  4. +9
    -0
      docs/guides/getting_started/samples/first-bot/async-context.cs
  5. +5
    -5
      docs/guides/getting_started/samples/first-bot/client.cs
  6. +38
    -0
      docs/guides/getting_started/samples/first-bot/complete.cs
  7. +5
    -0
      docs/guides/getting_started/samples/first-bot/logging.cs
  8. +1
    -1
      docs/guides/getting_started/samples/first-bot/message.cs
  9. +0
    -0
      docs/guides/getting_started/samples/first-bot/structure.cs
  10. +0
    -15
      docs/guides/getting_started/samples/intro/async-context.cs
  11. +0
    -44
      docs/guides/getting_started/samples/intro/complete.cs
  12. +0
    -22
      docs/guides/getting_started/samples/intro/logging.cs
  13. +1
    -0
      docs/guides/getting_started/samples/project.xml
  14. +1
    -1
      docs/guides/introduction/intro.md

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

@@ -1,6 +1,6 @@
---
uid: Guides.Concepts.Logging
title: Logging
title: Logging Events/Data
---

# Logging in Discord.Net


+ 84
- 69
docs/guides/getting_started/first-bot.md View File

@@ -5,14 +5,15 @@ title: Start making a bot

# Making a Ping-Pong bot

One of the first steps to getting started with the Discord API is to
write a basic ping-pong bot. We will expand on this to create more
diverse commands later, but for now, it is a good starting point.
One of ways to get started with the Discord API is to write a basic
ping-pong bot. This bot will respond to a simple command "ping."
We will expand on this to create more diverse commands later, but for
now, it is a good starting point.

## Creating a Discord Bot

Before you can begin writing your bot, it is necessary to create a bot
account on Discord.
Before writing your bot, it is necessary to create a bot account via the
Discord Applications Portal first.

1. Visit the [Discord Applications Portal].
2. Create a New Application.
@@ -37,12 +38,14 @@ Bots **cannot** use invite links; they must be explicitly invited
through the OAuth2 flow.

1. Open your bot's application on the [Discord Applications Portal].
2. Retrieve the app's **Client ID**.
2. Retrieve the application's **Client ID**.

![Step 2](images/intro-client-id.png)

3. Create an OAuth2 authorization URL
`https://discordapp.com/oauth2/authorize?client_id=<CLIENT ID>&scope=bot`

- `https://discordapp.com/oauth2/authorize?client_id=<CLIENT ID>&scope=bot`

4. Open the authorization URL in your browser.
5. Select a server.
6. Click on authorize.
@@ -56,26 +59,26 @@ through the OAuth2 flow.
## Connecting to Discord

If you have not already created a project and installed Discord.Net,
do that now. (see the [Installing](xref:Guides.GettingStarted.Installation) section)
do that now.

For more information, see @Guides.GettingStarted.Installation.

### Async

Discord.Net uses .NET's [Task-based Asynchronous Pattern (TAP)]
extensively - nearly every operation is asynchronous.
extensively - nearly every operation is asynchronous. It is highly
recommended that these operations are awaited in a
properly established async context whenever possible.

It is highly recommended that these operations are awaited in a
properly established async context whenever possible. Establishing an
async context can be problematic, but not hard.
To establish an async context, we will be creating an async main method
in your console application, and rewriting the static main method to
invoke the new async main.

To do so, we will be creating an async main in your console
application, and rewriting the static main method to invoke the new
async main.

[!code-csharp[Async Context](samples/intro/async-context.cs)]
[!code-csharp[Async Context](samples/first-bot/async-context.cs)]

As a result of this, your program will now start and immediately
jump into an async context. This will allow us to create a connection
to Discord later on without needing to worry about setting up the
to Discord later on without having to worry about setting up the
correct async implementation.

> [!TIP]
@@ -83,9 +86,11 @@ correct async implementation.
> they will be thrown all the way back up to the first non-async method;
> since our first non-async method is the program's `Main` method, this
> means that **all** unhandled exceptions will be thrown up there, which
> will crash your application. Discord.Net will prevent exceptions in
> event handlers from crashing your program, but any exceptions in your
> async main **will** cause the application to crash.
> will crash your application.
>
> Discord.Net will prevent exceptions in event handlers from crashing
> your program, but any exceptions in your async main **will** cause
> the application to crash.

[Task-based Asynchronous Pattern (TAP)]: https://docs.microsoft.com/en-us/dotnet/articles/csharp/async

@@ -100,57 +105,61 @@ parameter. See the [API Documentation] for this event.

If you are using your own logging framework, this is where you would
invoke it. For the sake of simplicity, we will only be logging to
the Console.
the console.

[!code-csharp[Async Context](samples/intro/logging.cs)]
You may learn more about this concept in @Guides.Concepts.Logging.

[!code-csharp[Async Context](samples/first-bot/logging.cs)]

[API Documentation]: xref:Discord.Rest.BaseDiscordClient.Log

### Creating a Discord Client

Finally, we can create a connection to Discord. Since we are writing
a bot, we will be using a [DiscordSocketClient] along with socket
entities. See the [terminology](xref:Guides.GettingStarted.Terminology) if you're unsure of
the differences.
Finally, we can create a new connection to Discord.

Since we are writing a bot, we will be using a [DiscordSocketClient]
along with socket entities. See @Guides.GettingStarted.Terminology
if you are unsure of the differences.

To do so, create an instance of [DiscordSocketClient] in your async
main, passing in a configuration object only if necessary. For most
To establish a new connection, we will create an instance of
[DiscordSocketClient] in the new async main. You may pass in an
optional @Discord.WebSocket.DiscordSocketConfig if necessary. For most
users, the default will work fine.

Before connecting, we should hook the client's `Log` event to the
log handler that was just created. Events in Discord.Net work
similarly to other events in C#, so hook this event the way that
you typically would.
log handler that we had just created. Events in Discord.Net work
similarly to any other events in C#.

Next, you will need to "login to Discord" with the `LoginAsync`
method.
Next, you will need to "login to Discord" with the [LoginAsync]
method with the application's "token."

You may create a variable to hold your bot's token (this can be found
on your bot's application page on the [Discord Applications Portal]).
> [!NOTE]
> Please note that this is not the same as the application's
> "client secret."

![Token](images/intro-token.png)

> [!IMPORTANT]
> Your bot's token can be used to gain total access to your bot, so
> **do __NOT__ share this token with anyone else!** It may behoove you
> to store this token in an external file if you plan on distributing
> to store this token in an external source if you plan on distributing
> the source code for your bot.

We may now invoke the client's `StartAsync` method, which will
We may now invoke the client's [StartAsync] method, which will
start connection/reconnection logic. It is important to note that
**this method returns as soon as connection logic has been started!**
**this method will return as soon as connection logic has been started!**

Any methods that rely on the client's state should go in an event
handler.
handler. This means that you should **not** directly be interacting with
the client before it is fully ready.

Finally, we will want to block the async main method from returning
until after the application is exited. To do this, we can await an
infinite delay or any other blocking method, such as reading from
the console.
when running the application. To do this, we can await an infinite delay
or any other blocking method, such as reading from the console.

The following lines can now be added:

[!code-csharp[Create client](samples/intro/client.cs)]
[!code-csharp[Create client](samples/first-bot/client.cs)]

At this point, feel free to start your program and see your bot come
online in Discord.
@@ -162,6 +171,8 @@ online in Discord.
> for how to fix this.

[DiscordSocketClient]: xref:Discord.WebSocket.DiscordSocketClient
[LoginAsync]: xref:Discord.Rest.BaseDiscordClient.LoginAsync*
[StartAsync]: xref:Discord.WebSocket.DiscordSocketClient.StartAsync*
[installation guide]: xref:Guides.GettingStarted.Installation#installing-on-net-standard-11

### Handling a 'ping'
@@ -169,18 +180,18 @@ online in Discord.
> [!WARNING]
> Please note that this is *not* a proper way to create a command.
> Use the `CommandService` provided by the library instead, as explained
> in the [Command Guide] section.
> in the [Command Guide](xref:Guides.Commands.Intro) section.

Now that we have learned how to open a connection to Discord, we can
begin handling messages that users are sending. To start out, our bot
will listen for any message where the content is equal to `!ping` and
respond back with "Pong!".
Now that we have learned to open a connection to Discord, we can
begin handling messages that the users are sending. To start out, our
bot will listen for any message whose content is equal to `!ping` and
will respond back with "Pong!".

Since we want to listen for new messages, the event to hook into
is [MessageReceived].

In your program, add a method that matches the signature of the
`MessageReceived` event - it must be a method (`Func`) that returns
`MessageReceived` event - it must be a method (`Func`) that returns
the type `Task` and takes a single parameter, a [SocketMessage]. Also,
since we will be sending data to Discord in this method, we will flag
it as `async`.
@@ -189,45 +200,49 @@ In this method, we will add an `if` block to determine if the message
content fits the rules of our scenario - recall that it must be equal
to `!ping`.

Inside the branch of this condition, we will want to send a message
back to the channel from which the message comes from - "Pong!". To
find the channel, look for the `Channel` property on the message
Inside the branch of this condition, we will want to send a message,
`Pong!`, back to the channel from which the message comes from. To
find the channel, look for the `Channel` property on the message
parameter.

Next, we will want to send a message to this channel. Since the
channel object is of type [SocketMessageChannel], we can invoke the
`SendMessageAsync` instance method. For the message content, send back
a string containing "Pong!".
channel object is of type [ISocketMessageChannel], we can invoke the
[SendMessageAsync] instance method. For the message content, send back
a string, "Pong!".

You should have now added the following lines,

[!code-csharp[Message](samples/intro/message.cs)]
[!code-csharp[Message](samples/first-bot/message.cs)]

Now your first bot is complete. You may continue to add on to this
Now that your first bot is complete. You may continue to add on to this
if you desire, but for any bots that will be carrying out multiple
commands, it is strongly recommended to use the command framework as
shown below.

For your reference, you may view the [completed program].
> [!NOTE]
> For your reference, you may view the [completed program].

[MessageReceived]: xref:Discord.WebSocket.BaseSocketClient.MessageReceived
[SocketMessage]: xref:Discord.WebSocket.SocketMessage
[SocketMessageChannel]: xref:Discord.WebSocket.ISocketMessageChannel
[completed program]: samples/intro/complete.cs
[Command Guide]: xref:Guides.Commands.Intro
[SendMessageAsync]: xref:Discord.WebSocket.ISocketMessageChannel.SendMessageAsync*
[completed program]: samples/first-bot/complete.cs

# Building a bot with commands

This section will show you how to write a program that is ready for
[Commands](xref:Guides.Commands.Intro). Note that we will not be
explaining _how_ to write Commands or Services, it will only be
covering the general structure.
@Guides.Commands.Intro will guide you through how to setup a program
that is ready for [CommandService], a service that is ready for
advanced command usage.

For reference, view an [annotated example] of this structure.

[annotated example]: samples/intro/structure.cs
[annotated example]: samples/first-bot/structure.cs

It is important to know that the recommended design pattern of bots
should be to separate the program (initialization and command handler),
the modules (handle commands), and the services (persistent storage,
pure functions, data manipulation).
should be to separate...

1. the program (initialization and command handler)
2. the modules (handle commands)
3. the services (persistent storage, pure functions, data manipulation)

[CommandService]: xref:Discord.Commands.CommandService

+ 37
- 33
docs/guides/getting_started/installing.md View File

@@ -3,19 +3,22 @@ uid: Guides.GettingStarted.Installation
title: Installing Discord.Net
---

Discord.Net is distributed through the NuGet package manager, and it
is recommended to use NuGet to get started.
# Discord.Net Installation

Optionally, you may compile from source and install yourself.
Discord.Net is distributed through the NuGet package manager, so it is
recommended for you to install the library that way.

# Supported Platforms
Alternatively, you may compile from the source and install the library
yourself.

## Supported Platforms

Currently, Discord.Net targets [.NET Standard] 1.3 and offers support
for .NET Standard 1.1. If your application will be targeting .NET
Standard 1.1, please see the [additional steps].

Since Discord.Net is built on the .NET Standard, it is also
recommended to create applications using [.NET Core], though not
Since Discord.Net is built on top of .NET Standard, it is also
recommended to create applications using [.NET Core], although it is not
required. When using .NET Framework, it is suggested to target
`.NET Framework 4.6.1` or higher.

@@ -23,13 +26,13 @@ required. When using .NET Framework, it is suggested to target
[.NET Core]: https://docs.microsoft.com/en-us/dotnet/articles/core/
[additional steps]: #installing-on-net-standard-11

# Installing with NuGet
## Installing with NuGet

Release builds of Discord.Net will be published to the
[official NuGet feed].

Development builds of Discord.Net, as well as add-ons are published to
our development [MyGet feed].
Development builds of Discord.Net, as well as add-ons, will be
published to our [MyGet feed].

Direct feed link: `https://www.myget.org/F/discord-net/api/v3/index.json`

@@ -41,7 +44,7 @@ Not sure how to add a direct feed? See how [with Visual Studio] or
[with Visual Studio]: https://docs.microsoft.com/en-us/nuget/tools/package-manager-ui#package-sources
[without Visual Studio]: #configuring-nuget-without-visual-studio

## [Using Visual Studio](#tab/vs-install)
### [Using Visual Studio](#tab/vs-install)

> [!TIP]
> Don't forget to change your package source if you're installing from
@@ -49,8 +52,8 @@ Not sure how to add a direct feed? See how [with Visual Studio] or
> Also make sure to check "Enable Prereleases" if installing a dev
> build!

1. Create a solution for your bot.
2. In Solution Explorer, find the "Dependencies" element under your
1. Create a new solution for your bot.
2. In the Solution Explorer, find the "Dependencies" element under your
bot's project.
3. Right click on "Dependencies", and select "Manage NuGet packages."
![Step 3](images/install-vs-deps.png)
@@ -58,7 +61,7 @@ Not sure how to add a direct feed? See how [with Visual Studio] or
5. Install the `Discord.Net` package.
![Step 5](images/install-vs-nuget.png)

## [Using JetBrains Rider](#tab/rider-install)
### [Using JetBrains Rider](#tab/rider-install)

> [!TIP]
> Make sure to check the "Prerelease" box if installing a dev build!
@@ -72,7 +75,7 @@ Not sure how to add a direct feed? See how [with Visual Studio] or
4. Install by adding the package to your project.
![Step 4](images/install-rider-add.png)

## [Using Visual Studio Code](#tab/vs-code)
### [Using Visual Studio Code](#tab/vs-code)

> [!TIP]
> Don't forget to add the package source to a [NuGet.Config file] if
@@ -81,11 +84,11 @@ Not sure how to add a direct feed? See how [with Visual Studio] or
1. Create a new project for your bot.
2. Add `Discord.Net` to your .csproj.

[!code[Sample .csproj](samples/project.csproj)]
[!code[Sample .csproj](samples/project.xml)]

[NuGet.Config file]: #configuring-nuget-without-visual-studio

## [Using dotnet CLI](#tab/dotnet-cli)
### [Using dotnet CLI](#tab/dotnet-cli)

> [!TIP]
> Don't forget to add the package source to a [NuGet.Config file] if
@@ -98,11 +101,11 @@ Not sure how to add a direct feed? See how [with Visual Studio] or

***

# Compiling from Source
## Compiling from Source

In order to compile Discord.Net, you require the following:
In order to compile Discord.Net, you will need the following:

## Using Visual Studio
### Using Visual Studio

- [Visual Studio 2017](https://www.visualstudio.com/)
- [.NET Core SDK]
@@ -110,31 +113,32 @@ In order to compile Discord.Net, you require the following:
The .NET Core and Docker (Preview) workload is required during Visual
Studio installation.

## Using Command Line
### Using Command Line

- [.NET Core SDK]

[.NET Core SDK]: https://www.microsoft.com/net/download/

# Additional Information
## Additional Information

## Installing on .NET Standard 1.1
### Installing on .NET Standard 1.1

For applications targeting a runtime corresponding with .NET Standard
1.1 or 1.2, the builtin WebSocket and UDP provider will not work. For
applications which utilize a WebSocket connection to Discord
(WebSocket or RPC), third-party provider packages will need to be
1.1 or 1.2, the built-in WebSocket and UDP provider will not work. For
applications which utilize a WebSocket connection to Discord, such as
WebSocket or RPC, third-party provider packages will need to be
installed and configured.

First, install the following packages through NuGet, or compile
> [!NOTE]
> `Discord.Net.Providers.UDPClient` is _only_ required if your
> bot will be utilizing voice chat.

First, install the following packages through NuGet, or compile them
yourself, if you prefer:

- Discord.Net.Providers.WS4Net
- Discord.Net.Providers.UDPClient

Note that `Discord.Net.Providers.UDPClient` is _only_ required if your
bot will be utilizing voice chat.

Next, you will need to configure your [DiscordSocketClient] to use
these custom providers over the default ones.

@@ -147,16 +151,16 @@ are passing into your client.
[DiscordSocketClient]: xref:Discord.WebSocket.DiscordSocketClient
[DiscordSocketConfig]: xref:Discord.WebSocket.DiscordSocketConfig

## Configuring NuGet without Visual Studio
### Configuring NuGet without Visual Studio

If you plan on deploying your bot or developing outside of Visual
Studio, you will need to create a local NuGet configuration file for
your project.

To do this, create a file named `nuget.config` alongside the root of
your application, where the project solution is located.
To do this, create a file named `NuGet.Config` alongside the root of
your application, where the project is located.

Paste the following snippets into this configuration file, adding any
additional feeds as necessary.
additional feeds if necessary.

[!code[NuGet Configuration](samples/nuget.config)]

+ 9
- 0
docs/guides/getting_started/samples/first-bot/async-context.cs View File

@@ -0,0 +1,9 @@
public class Program
{
public static void Main(string[] args)
=> new Program().MainAsync().GetAwaiter().GetResult();

public async Task MainAsync()
{
}
}

docs/guides/getting_started/samples/intro/client.cs → docs/guides/getting_started/samples/first-bot/client.cs View File

@@ -1,17 +1,17 @@
// Program.cs
using Discord.WebSocket;
// ...
private DiscordSocketClient _client;

public async Task MainAsync()
{
_client = new DiscordSocketClient();

_client.Log += Log;

string token = "abcdefg..."; // Remember to keep this private!
// Remember to keep this private or to read this
// from an external source!
string token = "abcdefg...";
await _client.LoginAsync(TokenType.Bot, token);
await _client.StartAsync();

// Block this task until the program is closed.
await Task.Delay(-1);
}
}

+ 38
- 0
docs/guides/getting_started/samples/first-bot/complete.cs View File

@@ -0,0 +1,38 @@
public class Program
{
private DiscordSocketClient _client;
public static void Main(string[] args)
=> new Program().MainAsync().GetAwaiter().GetResult();

public async Task MainAsync()
{
_client = new DiscordSocketClient();

_client.Log += Log;
_client.MessageReceived += MessageReceivedAsync;

// Remember to keep this private or to read this
// from an external source!
string token = "abcdefg...";
await _client.LoginAsync(TokenType.Bot, token);
await _client.StartAsync();

// Block this task until the program is closed.
await Task.Delay(-1);
}

private async Task MessageReceivedAsync(SocketMessage message)
{
if (message.Content == "!ping")
{
await message.Channel.SendMessageAsync("Pong!");
}
}

private Task Log(LogMessage msg)
{
Console.WriteLine(msg.ToString());
return Task.CompletedTask;
}
}

+ 5
- 0
docs/guides/getting_started/samples/first-bot/logging.cs View File

@@ -0,0 +1,5 @@
private Task Log(LogMessage msg)
{
Console.WriteLine(msg.ToString());
return Task.CompletedTask;
}

docs/guides/getting_started/samples/intro/message.cs → docs/guides/getting_started/samples/first-bot/message.cs View File

@@ -1,6 +1,6 @@
public async Task MainAsync()
{
// client.Log ...
// ...
_client.MessageReceived += MessageReceived;
// ...
}

docs/guides/getting_started/samples/intro/structure.cs → docs/guides/getting_started/samples/first-bot/structure.cs View File


+ 0
- 15
docs/guides/getting_started/samples/intro/async-context.cs View File

@@ -1,15 +0,0 @@
using System;
using System.Threading.Tasks;

namespace MyBot
{
public class Program
{
public static void Main(string[] args)
=> new Program().MainAsync().GetAwaiter().GetResult();

public async Task MainAsync()
{
}
}
}

+ 0
- 44
docs/guides/getting_started/samples/intro/complete.cs View File

@@ -1,44 +0,0 @@
using Discord;
using Discord.WebSocket;
using System;
using System.Threading.Tasks;

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

public async Task MainAsync()
{
_client = new DiscordSocketClient();

_client.Log += Log;
_client.MessageReceived += MessageReceived;

string token = "abcdefg..."; // Remember to keep this private!
await _client.LoginAsync(TokenType.Bot, token);
await _client.StartAsync();

// Block this task until the program is closed.
await Task.Delay(-1);
}

private async Task MessageReceived(SocketMessage message)
{
if (message.Content == "!ping")
{
await message.Channel.SendMessageAsync("Pong!");
}
}

private Task Log(LogMessage msg)
{
Console.WriteLine(msg.ToString());
return Task.CompletedTask;
}
}
}

+ 0
- 22
docs/guides/getting_started/samples/intro/logging.cs View File

@@ -1,22 +0,0 @@
using Discord;
using System;
using System.Threading.Tasks;

namespace MyBot
{
public class Program
{
public static void Main(string[] args)
=> new Program().MainAsync().GetAwaiter().GetResult();

public async Task MainAsync()
{
}

private Task Log(LogMessage msg)
{
Console.WriteLine(msg.ToString());
return Task.CompletedTask;
}
}
}

docs/guides/getting_started/samples/project.csproj → docs/guides/getting_started/samples/project.xml View File

@@ -1,4 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">

<!--
The following may differ depending on the latest version of
.NET Core Framework or Discord.Net.

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

@@ -26,7 +26,7 @@ Here are some examples:
> It is not meant to be something that will work out of the box.

[Official template]: https://github.com/foxbot/DiscordBotBase/tree/csharp/src/DiscordBot
[Official quick start guide]: https://github.com/RogueException/Discord.Net/blob/dev/docs/guides/getting_started/samples/intro/structure.cs
[Official quick start guide]: https://github.com/RogueException/Discord.Net/blob/dev/docs/guides/getting_started/samples/first-bot/structure.cs
[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/


Loading…
Cancel
Save