Files
Discord.Net/docs/guides/getting_started/intro.md
Hsu Still 22d79c1004 Improve library documentation (#826)
* Improve the Command Service documentation

The following changes have been added to this PR:
•	Fix minor grammatical errors.
•	Capitalize terms such as Commands, Modules and such, as the context is specific to the lib.
•	Wrap methods and properties in code blocks.

The docs page currently has several issues that remains to be fixed.

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

The docs doesn't necessarily seem "out of date" as the warning claims. The basics seem pretty relevant to the latest version of the lib.

2.
>“To manually load a module, invoke [CommandService.AddModuleAsync], by passing in the generic type of your module and optionally, a dependency map.”

The latter part of the sentence seems off. Where should the user pass the dependency map to? It seems to suggest that `AddModuleAsync` has an argument to pass the dependency to. If it is referring to `AddModuleAsync(Type type)`, then I feel like it should be clarified here - or perhaps change the wording of the sentence.

3.
>“First, you need to create an @System.IServiceProvider You may create your own IServiceProvider if you wish.” 

Any mention of @System.IServiceProvider is currently broken on the docs.

4.
>“Submodules are Modules that reside within another one. Typically, submodules are used to create nested groups (although not required to create nested groups).”

Clarification on the part after "although?"

5.
>“Finally, pass the map into the LoadAssembly method. Your modules will automatically be loaded with this dependency map.”

Where is this `LoadAssembly` method?

6.
```md
>[!NOTE]
>Preconditions can be applied to Modules, Groups, or Commands.
```

The docs should mention `ParameterPreconditionAttribute`'s existence.

* Update line breaks to comply with docs standard

* Change "you should..." to "instead, ..."

* Trim trailing spaces

* Change "inherits" to "inherit"

* Fix Context warning note and add ReplyAsync xref

* Fix broken xrefs

* Fix [Command Service] xref

* Fix consistency between TypeReaders and Preconditions returns

* Add missing semi-colons in ServiceProvider sample

* Change CommandContext to SocketCommandContext & change variable naming

* Cleanup TypeReader section

* Wrap [DontInject] in code block

* Fix commands docs linking in intro

* Improve Getting Started - Installation

- Fix character misalignment to comply with docs standard.
- Fix image numbering issues by moving the tooltips above some of the steps.
- Add codeblocks to search terms like `Discord.Net`.
- Remove broken `addons` reference.
- Specify `.NET 4.6.1` as `.NET Framework 4.6.1`.
- Minor cross-reference cleanup.

* Fix Getting Started - Intro

- Minor grammartical fixes.
- Wrap mentions of the methods, properties, and events in code block.
- Replace `Discord.Net` to `Discord.NET`.
- Fix steps numbering under `Creating a Discord Bot` and `Adding your bot to a server`.
- Change `Task-based Asynchronous Pattern ([TAP])` linking to mark the entire term instead.
- Change code block of `Pong!` to quotation mark instead.

* Fix cross references in Sending Voice

* Mention parameter precondition attribute

* Change `Discord.NET` to `Discord.Net` for consistency

* Wrap project names in code blocks & minor fixes in Terminology

* Change `add-ons` to `addons` for consistency

* Fix cross references in Logging

* Fix minor grammatical issues in "Working with Events"

* Missed a tilda

* Remove out-of-date warning in Commands

* Minor grammatical fixes for Entities

* Fix broken xref in Logging

* Adjust service collection sample

...according to f89aecb7bf (r141530227)

* Update Command Handler sample

- Update Main for C# 7.1.
- Inject CommandService and DiscordSocketClient into the service collection.
- Add Async suffix to asynchronous methods.

* Minor grammatical fixes in Events

* Revert 2 incorrect grammar corrections

* Revert async Main sample

* Add hardcode token notice in sample

* Fix missing method for Command Handler

* Modify module samples to use SocketCommandContext instead

* Emphasize CommandContext and SocketCommandContext

* Fix formatting for module sample

* Add SocketCommandContext for Groups sample

* Remove comma

* Fix DepMap sample formatting

* Replace [DontInject] with DontInjectAttribute with cross reference

* Remove connection logic note

There is no reason that this note should still be here since Ready event exists.

* Add a new warning message informing the users the existence of CommandService

* Make command handler private

excellent change
2017-10-03 16:48:05 -04:00

8.4 KiB

title
title
Getting Started

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.

Creating a Discord Bot

Before you can begin writing your bot, it is necessary to create a bot account on Discord.

  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.

    Step 4

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

    Step 5

  6. Confirm the popup.

  7. If this bot will be public, check "Public Bot." Do not tick any other options!

Adding your bot to a server

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.

    Step 2

  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.

  6. Click on authorize.

    Note

    Only servers where you have the MANAGE_SERVER permission will be present in this list.

    Step 6

Connecting to Discord

If you have not already created a project and installed Discord.Net, do that now. (see the Installing 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 are 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-csharpAsync Context]

As a result of this, your program will now start and immidiately 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 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-csharpAsync Context]

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 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).

Token

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

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-csharpCreate client]

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 installation guide for how to fix this.

Handling a 'ping'

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.

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 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 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 comes from - "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-csharpMessage]

Now 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.

Building a bot with commands

This section will show you how to write a program that is ready for Commands. Note that we 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.

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