You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

intro.md 8.3 KiB

8 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. ---
  2. title: Getting Started
  3. ---
  4. # Making a Ping-Pong bot
  5. One of the first steps to getting started with the Discord API is to
  6. write a basic ping-pong bot. We will expand on this to create more
  7. diverse commands later, but for now, it is a good starting point.
  8. ## Creating a Discord Bot
  9. Before you can begin writing your bot, it is necessary to create a bot
  10. account on Discord.
  11. 1. Visit the [Discord Applications Portal]
  12. 2. Create a New Application
  13. 3. Give the application a name (this will be the bot's initial
  14. username).
  15. 4. Create the Application
  16. ![Step 4](images/intro-create-app.png)
  17. 5. In the application review page, click **Create a Bot User**
  18. ![Step 5](images/intro-create-bot.png)
  19. 6. Confirm the popup
  20. 7. If this bot will be public, check 'Public Bot'.
  21. **Do not tick any other options!**
  22. [Discord Applications Portal]: https://discordapp.com/developers/applications/me
  23. ## Adding your bot to a server
  24. Bots **can not** use invite links, they must be explicitly invited
  25. through the OAuth2 flow.
  26. 1. Open your bot's application on the [Discord Applications Portal]
  27. 2. Retrieve the app's **Client ID**.
  28. ![Step 2](images/intro-client-id.png)
  29. 3. Create an OAuth2 authorization URL
  30. `https://discordapp.com/oauth2/authorize?client_id=<CLIENT ID>&scope=bot`
  31. 4. Open the authorization URL in your browser
  32. 5. Select a server
  33. >[!NOTE]
  34. Only servers where you have the `MANAGE_SERVER` permission will be
  35. present in this list.
  36. 6. Click authorize
  37. ![Step 6](images/intro-add-bot.png)
  38. ## Connecting to Discord
  39. If you have not already created a project and installed Discord.Net,
  40. do that now. (see the [Installing](installing.md) section)
  41. ### Async
  42. Discord.Net uses .NET's Task-based Asynchronous Pattern ([TAP])
  43. extensively - nearly every operation is asynchronous.
  44. It is highly recommended that these operations be awaited in a
  45. properly established async context whenever possible. Establishing an
  46. async context can be problematic, but not hard.
  47. To do so, we will be creating an async main in your console
  48. application, and rewriting the static main method to invoke the new
  49. async main.
  50. [!code-csharp[Async Context](samples/intro/async-context.cs)]
  51. As a result of this, your program will now start, and immidiately
  52. jump into an async context. This will allow us later on to create a
  53. connection to Discord, without needing to worry about setting up the
  54. correct async implementation.
  55. >[!TIP]
  56. If your application throws any exceptions within an async context,
  57. they will be thrown all the way back up to the first non-async method.
  58. Since our first non-async method is the program's Main method, this
  59. means that **all** unhandled exceptions will be thrown up there, which
  60. will crash your application. Discord.Net will prevent exceptions in
  61. event handlers from crashing your program, but any exceptions in your
  62. async main **will** cause the application to crash.
  63. ### Creating a logging method
  64. Before we create and configure a Discord client, we will add a method
  65. to handle Discord.Net's log events.
  66. To allow agnostic support of as many log providers as possible, we
  67. log information through a Log event, with a proprietary LogMessage
  68. parameter. See the [API Documentation] for this event.
  69. If you are using your own logging framework, this is where you would
  70. invoke it. For the sake of simplicity, we will only be logging to
  71. the Console.
  72. [!code-csharp[Async Context](samples/intro/logging.cs)]
  73. ### Creating a Discord Client
  74. Finally, we can create a connection to Discord. Since we are writing
  75. a bot, we will be using a [DiscordSocketClient], along with socket
  76. entities. See the [terminology](terminology.md) if you're unsure of
  77. the differences.
  78. To do so, create an instance of [DiscordSocketClient] in your async
  79. main, passing in a configuration object only if necessary. For most
  80. users, the default will work fine.
  81. Before connecting, we should hook the client's log event to the
  82. log handler that was just created. Events in Discord.Net work
  83. similarly to other events in C#, so hook this event the way that
  84. you typically would.
  85. Next, you will need to 'login to Discord' with the `LoginAsync` method.
  86. You may create a variable to hold your bot's token (this can be found
  87. on your bot's application page on the [Discord Applications Portal]).
  88. ![Token](images/intro-token.png)
  89. >[!IMPORTANT]
  90. Your bot's token can be used to gain total access to your bot, so
  91. **do __NOT__ share this token with anyone!**. It may behoove you to
  92. store this token in an external file if you plan on distributing the
  93. source code for your bot.
  94. We may now invoke the client's `StartAsync` method, which will
  95. start connection/reconnection logic. It is important to note that
  96. **this method returns as soon as connection logic has been started!**
  97. Any methods that rely on the client's state should go in an event
  98. handler.
  99. >[!NOTE]
  100. Connection logic is incomplete as of the current build. Events will
  101. soon be added to indicate when the client's state is ready for use;
  102. (rewrite this section when possible)
  103. Finally, we will want to block the async main method from returning
  104. until after the application is exited. To do this, we can await an
  105. infinite delay, or any other blocking method, such as reading from
  106. the console.
  107. The following lines can now be added:
  108. [!code-csharp[Create client](samples/intro/client.cs)]
  109. At this point, feel free to start your program and see your bot come
  110. online in Discord.
  111. >[!TIP]
  112. Encountering a `PlatformNotSupportedException` when starting your bot?
  113. This means that you are targeting a platform where .NET's default
  114. WebSocket client is not supported. Refer to the [installing guide]
  115. for how to fix this.
  116. [TAP]: https://docs.microsoft.com/en-us/dotnet/articles/csharp/async
  117. [API Documentation]: xref:Discord.Rest.BaseDiscordClient#Discord_Rest_BaseDiscordClient_Log
  118. [DiscordSocketClient]: xref:Discord.WebSocket.DiscordSocketClient
  119. [installing guide]: installing.md#installing-on-.net-standard-11
  120. ### Handling a 'ping'
  121. Now that we have learned how to open a connection to Discord, we can
  122. begin handling messages that users are sending.
  123. To start out, our bot will listen for any message where the content
  124. is equal to `!ping`, and respond back with `Pong!`.
  125. Since we want to listen for new messages, the event to hook in to
  126. is [MessageReceived].
  127. In your program, add a method that matches the signature of the
  128. MessageReceived event - it must be a method (`Func`) that returns the
  129. type `Task`, and takes a single parameter, a [SocketMessage]. Also,
  130. since we will be sending data to Discord in this method, we will flag
  131. it as `async`.
  132. In this method, we will add an `if` block, to determine if the message
  133. content fits the rules of our scenario - recall that it must be equal
  134. to `!ping`.
  135. Inside the branch of this condition, we will want to send a message
  136. back to the channel from which the message came - `Pong!`. To find the
  137. channel, look for the `Channel` property on the message parameter.
  138. Next, we will want to send a message to this channel. Since the
  139. channel object is of type [SocketMessageChannel], we can invoke the
  140. `SendMessageAsync` instance method. For the message content, send back
  141. a string containing 'Pong!'.
  142. You should have now added the following lines:
  143. [!code-csharp[Message](samples/intro/message.cs)]
  144. Now, your first bot is complete. You may continue to add on to this
  145. if you desire, but for any bot that will be carrying out multiple
  146. commands, it is strongly encouraged to use the command framework, as
  147. shown below.
  148. For your reference, you may view the [completed program].
  149. [MessageReceived]: xref:Discord.WebSocket.DiscordSocketClient#Discord_WebSocket_DiscordSocketClient_MessageReceived
  150. [SocketMessage]: xref:Discord.WebSocket.SocketMessage
  151. [SocketMessageChannel]: xref:Discord.WebSocket.SocketMessageChannel
  152. [completed program]: samples/intro/complete.cs
  153. # Building a bot with commands
  154. This section will show you how to write a program that is ready for
  155. [commands](commands.md). Note that this will not be explaining _how_
  156. to write commands or services, it will only be covering the general
  157. structure.
  158. For reference, view an [annotated example] of this structure.
  159. [annotated example]: samples/intro/structure.cs
  160. It is important to know that the recommended design pattern of bots
  161. should be to separate the program (initialization and command handler),
  162. the modules (handle commands), and the services (persistent storage,
  163. pure functions, data manipulation).
  164. **todo:** diagram of bot structure