Added new getting started guide
Thanks @MinnDevelopment for his awesome work on the JDA guide that had no influence here at all.
This commit is contained in:
BIN
docs/guides/images/intro-add-bot.png
Normal file
BIN
docs/guides/images/intro-add-bot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
BIN
docs/guides/images/intro-client-id.png
Normal file
BIN
docs/guides/images/intro-client-id.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
BIN
docs/guides/images/intro-create-app.png
Normal file
BIN
docs/guides/images/intro-create-app.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
BIN
docs/guides/images/intro-create-bot.png
Normal file
BIN
docs/guides/images/intro-create-bot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
BIN
docs/guides/images/intro-token.png
Normal file
BIN
docs/guides/images/intro-token.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -11,7 +11,7 @@ Optionally, you may compile from source and install yourself.
|
||||
|
||||
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](#installing-on-.net-standard-1.1).
|
||||
please see the [additional steps](#installing-on-.net-standard-11).
|
||||
|
||||
Since Discord.Net is built on the .NET Standard, it is also recommended to
|
||||
create applications using [.NET Core], though you are not required to. When
|
||||
@@ -46,11 +46,13 @@ project
|
||||
3. Right click on 'Dependencies', and select 'Manage NuGet packages'
|
||||

|
||||
4. In the 'browse' tab, search for 'Discord.Net'
|
||||
|
||||
> [!TIP]
|
||||
> Don't forget to change your package source if you're installing from the
|
||||
> developer feed.
|
||||
> Also make sure to check 'Enable Prereleases' if installing a dev build!
|
||||
Don't forget to change your package source if you're installing from the
|
||||
developer feed.
|
||||
Also make sure to check 'Enable Prereleases' if installing a dev build!
|
||||
5. Install the 'Discord.Net' package
|
||||
|
||||

|
||||
|
||||
## Using JetBrains Rider
|
||||
|
||||
@@ -2,49 +2,223 @@
|
||||
title: Getting Started
|
||||
---
|
||||
|
||||
# Getting Started
|
||||
# Making a Ping-Pong bot
|
||||
|
||||
## Requirements
|
||||
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.
|
||||
|
||||
Discord.Net supports logging in with all variations of Discord Accounts, however the Discord API reccomends using a `Bot Account`.
|
||||
## Creating a Discord Bot
|
||||
|
||||
You may [register a bot account here](https://discordapp.com/developers/applications/me).
|
||||
Before you can begin writing your bot, it is necessary to create a bot
|
||||
account on Discord.
|
||||
|
||||
Bot accounts must be added to a server, you must use the [OAuth 2 Flow](https://discordapp.com/developers/docs/topics/oauth2#adding-bots-to-guilds) to add them to servers.
|
||||
1. Visit the [Discord Applications Portal]
|
||||
2. Create a New Application
|
||||
3. Give the application a name (this will be the bot's initial
|
||||
username).
|
||||
4. Create the Application
|
||||

|
||||
5. In the application review page, click **Create a Bot User**
|
||||

|
||||
6. Confirm the popup
|
||||
7. If this bot will be public, check 'Public Bot'.
|
||||
**Do not tick any other options!**
|
||||
|
||||
## Installation
|
||||
[Discord Applications Portal]: https://discordapp.com/developers/applications/me
|
||||
|
||||
You can install Discord.Net 1.0 from our [MyGet Feed](https://www.myget.org/feed/Packages/discord-net).
|
||||
## Adding your bot to a server
|
||||
|
||||
**For most users writing bots, install only `Discord.Net.WebSocket`.**
|
||||
Bots **can not** use invite links, they must be explicitly invited
|
||||
through the OAuth2 flow.
|
||||
|
||||
You may add the MyGet feed to Visual Studio directly from `https://www.myget.org/F/discord-net/api/v3/index.json`.
|
||||
|
||||
You can also pull the latest source from [GitHub](https://github.com/RogueException/Discord.Net).
|
||||
|
||||
>[!WARNING]
|
||||
>The versions of Discord.Net on NuGet are behind the versions this
|
||||
>documentation is written for.
|
||||
>You MUST install from MyGet or Source!
|
||||
|
||||
## Async
|
||||
|
||||
Discord.Net uses C# tasks extensiely - nearly all operations return
|
||||
one.
|
||||
|
||||
It is highly reccomended these tasks be awaited whenever possible.
|
||||
To do so requires the calling method to be marked as async, which
|
||||
can be problematic in a console application. An example of how to
|
||||
get around this is provided below.
|
||||
|
||||
For more information, go to [MSDN's Async-Await section.](https://msdn.microsoft.com/en-us/library/hh191443.aspx)
|
||||
|
||||
## First Steps
|
||||
|
||||
[!code-csharp[Main](samples/first-steps.cs)]
|
||||
1. Open your bot's application on the [Discord Applications Portal]
|
||||
2. Retrieve the app's **Client ID**.
|
||||

|
||||
3. Create an OAuth2 authorization URL
|
||||
`https://discordapp.com/oauth2/authorize?client_id=<CLIENT ID>&scope=bot`
|
||||
4. Open the authorization URL in your browser
|
||||
5. Select a server
|
||||
|
||||
>[!NOTE]
|
||||
>In previous versions of Discord.Net, you had to hook into the `Ready` and `GuildAvailable` events to determine when your client was ready for use.
|
||||
>In 1.0, the [ConnectAsync] method will automatically wait for the Ready event, and for all guilds to stream. To avoid this, pass `false` into `ConnectAsync`.
|
||||
Only servers where you have the `MANAGE_SERVER` permission will be
|
||||
present in this list.
|
||||
|
||||
[ConnectAsync]: xref:Discord.WebSocket.DiscordSocketClient#Discord_WebSocket_DiscordSocketClient_ConnectAsync_System_Boolean_
|
||||
6. Click authorize
|
||||

|
||||
|
||||
## Connecting to Discord
|
||||
|
||||
If you have not already created a project and installed Discord.Net,
|
||||
do that now. (see the [Installing](installing.md) section)
|
||||
|
||||
### Async
|
||||
|
||||
Discord.Net uses .NET's Task-based Asynchronous Pattern ([TAP])
|
||||
extensively - nearly every operation is asynchronous.
|
||||
|
||||
It is highly recommended that these operations be awaited in a
|
||||
properly established async context whenever possible. Establishing an
|
||||
async context can be problematic, but not hard.
|
||||
|
||||
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)]
|
||||
|
||||
As a result of this, your program will now start, and immidiately
|
||||
jump into an async context. This will allow us later on to create a
|
||||
connection to Discord, without needing to worry about setting up the
|
||||
correct async implementation.
|
||||
|
||||
>[!TIP]
|
||||
If your application throws any exceptions within an async context,
|
||||
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.
|
||||
|
||||
### Creating a logging method
|
||||
|
||||
Before we create and configure a Discord client, we will add a method
|
||||
to handle Discord.Net's log events.
|
||||
|
||||
To allow agnostic support of as many log providers as possible, we
|
||||
log information through a Log event, with a proprietary LogMessage
|
||||
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.
|
||||
|
||||
[!code-csharp[Async Context](samples/intro/logging.cs)]
|
||||
|
||||
### 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](terminology.md) if you're 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
|
||||
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.
|
||||
|
||||
Next, you will need to 'login to Discord' with the `LoginAsync` method.
|
||||
|
||||
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]).
|
||||

|
||||
|
||||
>[!IMPORTANT]
|
||||
Your bot's token can be used to gain total access to your bot, so
|
||||
**do __NOT__ share this token with anyone!**. It may behoove you to
|
||||
store this token in an external file if you plan on distributing the
|
||||
source code for your bot.
|
||||
|
||||
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!**
|
||||
|
||||
Any methods that rely on the client's state should go in an event
|
||||
handler.
|
||||
|
||||
>[!NOTE]
|
||||
Connection logic is incomplete as of the current build. Events will
|
||||
soon be added to indicate when the client's state is ready for use;
|
||||
(rewrite this section when possible)
|
||||
|
||||
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.
|
||||
|
||||
The following lines can now be added:
|
||||
|
||||
[!code-csharp[Create client](samples/intro/client.cs)]
|
||||
|
||||
At this point, feel free to start your program and see your bot come
|
||||
online in Discord.
|
||||
|
||||
>[!TIP]
|
||||
Encountering a `PlatformNotSupportedException` when starting your bot?
|
||||
This means that you are targeting a platform where .NET's default
|
||||
WebSocket client is not supported. Refer to the [installing guide]
|
||||
for how to fix this.
|
||||
|
||||
[TAP]: https://docs.microsoft.com/en-us/dotnet/articles/csharp/async
|
||||
[API Documentation]: xref:Discord.Rest.BaseDiscordClient#Discord_Rest_BaseDiscordClient_Log
|
||||
[DiscordSocketClient]: xref:Discord.WebSocket.DiscordSocketClient
|
||||
[installing guide]: installing.md#installing-on-.net-standard-11
|
||||
|
||||
### Handling a 'ping'
|
||||
|
||||
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!`.
|
||||
|
||||
Since we want to listen for new messages, the event to hook in to
|
||||
is [MessageReceived].
|
||||
|
||||
In your program, add a method that matches the signature of the
|
||||
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`.
|
||||
|
||||
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 came - `Pong!`. 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!'.
|
||||
|
||||
You should have now added the following lines:
|
||||
|
||||
[!code-csharp[Message](samples/intro/message.cs)]
|
||||
|
||||
Now, your first bot is complete. You may continue to add on to this
|
||||
if you desire, but for any bot that will be carrying out multiple
|
||||
commands, it is strongly encouraged to use the command framework, as
|
||||
shown below.
|
||||
|
||||
For your reference, you may view the [completed program].
|
||||
|
||||
[MessageReceived]: xref:Discord.WebSocket.DiscordSocketClient#Discord_WebSocket_DiscordSocketClient_MessageReceived
|
||||
[SocketMessage]: xref:Discord.WebSocket.SocketMessage
|
||||
[SocketMessageChannel]: xref:Discord.WebSocket.SocketMessageChannel
|
||||
[completed program]: samples/intro/complete.cs
|
||||
|
||||
# Building a bot with commands
|
||||
|
||||
This section will show you how to write a program that is ready for
|
||||
[commands](commands.md). Note that this will not be explaining _how_
|
||||
to write commands or services, it will only be covering the general
|
||||
structure.
|
||||
|
||||
For reference, view an [annotated example] of this structure.
|
||||
|
||||
[annotated example]: samples/intro/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).
|
||||
|
||||
**todo:** diagram of bot structure
|
||||
15
docs/guides/samples/intro/async-context.cs
Normal file
15
docs/guides/samples/intro/async-context.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
16
docs/guides/samples/intro/client.cs
Normal file
16
docs/guides/samples/intro/client.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// Program.cs
|
||||
using Discord.WebSocket;
|
||||
// ...
|
||||
public async Task MainAsync()
|
||||
{
|
||||
var client = new DiscordSocketClient();
|
||||
|
||||
client.Log += Log;
|
||||
|
||||
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);
|
||||
}
|
||||
42
docs/guides/samples/intro/complete.cs
Normal file
42
docs/guides/samples/intro/complete.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
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()
|
||||
{
|
||||
var 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
22
docs/guides/samples/intro/logging.cs
Normal file
22
docs/guides/samples/intro/logging.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
docs/guides/samples/intro/message.cs
Normal file
14
docs/guides/samples/intro/message.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
public async Task MainAsync()
|
||||
{
|
||||
// client.Log ...
|
||||
client.MessageReceived += MessageReceived;
|
||||
// ...
|
||||
}
|
||||
|
||||
private async Task MessageReceived(SocketMessage message)
|
||||
{
|
||||
if (message.Content == "!ping")
|
||||
{
|
||||
await message.Channel.SendMessageAsync("Pong!");
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,6 @@ class Program
|
||||
|
||||
// Login and connect.
|
||||
await _client.LoginAsync(TokenType.Bot, /* <DON'T HARDCODE YOUR TOKEN> */);
|
||||
// Prior to rc-00608 this was ConnectAsync();
|
||||
await _client.StartAsync();
|
||||
|
||||
// Wait infinitely so your bot actually stays connected.
|
||||
@@ -96,10 +95,10 @@ class Program
|
||||
await _commands.AddModuleAsync<SomeModule>();
|
||||
|
||||
// Subscribe a handler to see if a message invokes a command.
|
||||
_client.MessageReceived += CmdHandler;
|
||||
_client.MessageReceived += HandleCommandAsync;
|
||||
}
|
||||
|
||||
private async Task CmdHandler(SocketMessage arg)
|
||||
private async Task HandleCommandAsync(SocketMessage arg)
|
||||
{
|
||||
// Bail out if it's a System Message.
|
||||
var msg = arg as SocketUserMessage;
|
||||
Reference in New Issue
Block a user