docs: Main docs update (#1304)
* Remove template in favor of official samples * Fixed a variable name copy pasta mistake line 35 was _database.GetData() instead of DBService.GetData() * Experimental theme change * Change paragraph, code, heading fonts * Widen viewport * Update DocFX.Plugins.LastModified v1.2.3 * Exclude Discord.API in docs * Add remarks for SocketReaction properties * Add examples for BaseSocketClient.Events * Add additional clarification for some methods * Move IUser and IGuildChannel examples * Clarify several guides samples with notes - Reword TypeReader comment to avoid giving the idea that the sample itself is "obsolete" - Remove CommandException logging comment regarding C#7.0 as the version is now the standard across VS2017 and up - Remove suggestion about handling result in command handler since it is now advised to use CommandExecuted instead + Add additional comment to clarify ctor for DI setup * Add/migrate code examples * Incorporate material design theme License @ https://github.com/ovasquez * Update installation and nightly guide * Fix improper indentations made obvious by the widen viewport * Fix minor grammar issues + Add installation for nightly build using dotnet CLI * Fix nav level indentation * Revise "Your First Bot" article * Merge some paragraphs to avoid clutter while keeping readability * Reword the use of command framework + Add additional warning/note about environment variable * Add additional indent level * Fix indentation text warping * Remove connections sample * Update logging sample Remove redundant part of the sample * Remove mention of RPC * Remove misleading section about commands - Remove command sample from complete snippet * Revise "Your First Bot" command paragraphs * Change wording to hint devs that additional command parser packages may be available, as more and more begin to crop up * Update themes * Add XML docs contribution guidelines Update guidelines * Update CommandExecuted remarks * Fix precondition remarks typo no one saw that ok * Fix permission sample in docfx * Fix IMessageChannel samples * Update docs/_template/light-dark-theme/styles/docfx.vendor.minify.css Co-Authored-By: Still34 <341464@gmail.com> * Update docs/_template/light-dark-theme/styles/material.css Co-Authored-By: Still34 <341464@gmail.com> * Update docs/_template/light-dark-theme/styles/material.css Co-Authored-By: Still34 <341464@gmail.com>
This commit is contained in:
@@ -1,23 +1,46 @@
|
||||
# Contributing to Docs
|
||||
|
||||
First of all, thank you for your interest in contributing to our
|
||||
documentation work. We really appreciate it! That being said,
|
||||
there are several guidelines you should attempt to follow when adding
|
||||
to/changing the documentation.
|
||||
|
||||
## General Guidelines
|
||||
|
||||
We do not have any strict conditions for writing documentation,
|
||||
but keep these guidelines in mind:
|
||||
|
||||
* Keep code samples in the `guides/samples` folder
|
||||
* Keep code samples in each section's `samples` folder
|
||||
* When referencing an object in the API, link to its page in the
|
||||
API documentation
|
||||
* Documentation should be written in an FAQ/Wiki-style format
|
||||
* Documentation should be written in clear and proper English*
|
||||
|
||||
\* If anyone is interested in translating documentation into other
|
||||
languages, please open an issue or contact me on
|
||||
Discord (`foxbot#0282`).
|
||||
languages, please open an issue or contact `foxbot#0282` on
|
||||
Discord.
|
||||
|
||||
## Style Consistencies
|
||||
## XML Docstrings Guidelines
|
||||
|
||||
* Use a ruler set at 70 characters
|
||||
* When using the `<summary>` tag, use concise verbs. For example:
|
||||
|
||||
```cs
|
||||
/// <summary> Gets or sets the guild user in this object. </summary>
|
||||
public IGuildUser GuildUser { get; set; }
|
||||
```
|
||||
|
||||
* The `<summary>` tag should not be more than 3 lines long. Consider
|
||||
simplifying the terms or using the `<remarks>` tag instead.
|
||||
* When using the `<code>` tag, put the code sample within the
|
||||
`src/Discord.Net.Examples` project under the corresponding path of
|
||||
the object and surround the code with a `#region` tag.
|
||||
* If the remarks you are looking to write are too long, consider
|
||||
writing a shorter version in the XML docs while keeping the longer
|
||||
version in the `overwrites` folder using the DocFX overwrites syntax.
|
||||
* You may find an example of this in the samples provided within
|
||||
the folder.
|
||||
|
||||
## Docs Guide Guidelines
|
||||
|
||||
* Use a ruler set at 70 characters (use the docs workspace provided
|
||||
if you are using Visual Studio Code)
|
||||
* Links should use long syntax
|
||||
* Pages should be short and concise, not broad and long
|
||||
|
||||
@@ -31,5 +54,7 @@ Please consult the [API Documentation] for more information.
|
||||
|
||||
## Recommended Reads
|
||||
|
||||
* http://docs.microsoft.com
|
||||
* http://flask.pocoo.org/docs/0.12/
|
||||
* [Microsoft Docs](https://docs.microsoft.com)
|
||||
* [Flask Docs](https://flask.pocoo.org/docs/1.0/)
|
||||
* [DocFX Manual](https://dotnet.github.io/docfx/)
|
||||
* [Sandcastle XML Guide](http://ewsoftware.github.io/XMLCommentsGuide)
|
||||
@@ -1,6 +1,6 @@
|
||||
A "precondidtion" in the command system is used to determine if a
|
||||
A "precondition" in the command system is used to determine if a
|
||||
condition is met before entering the command task. Using a
|
||||
precondidtion may aid in keeping a well-organized command logic.
|
||||
precondition may aid in keeping a well-organized command logic.
|
||||
|
||||
The most common use case being whether a user has sufficient
|
||||
permission to execute the command.
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
<configuration>
|
||||
<dllmap os="linux" cpu="x86-64" wordsize="64" dll="git2-8e0b172" target="lib/linux-x64/libgit2-8e0b172.so" />
|
||||
<dllmap os="osx" cpu="x86,x86-64" dll="git2-8e0b172" target="lib/osx/libgit2-8e0b172.dylib" />
|
||||
<dllmap os="linux" cpu="x86-64" wordsize="64" dll="git2-a904fc6" target="lib/linux-x64/libgit2-a904fc6.so" />
|
||||
<dllmap os="osx" cpu="x86,x86-64" dll="git2-a904fc6" target="lib/osx/libgit2-a904fc6.dylib" />
|
||||
</configuration>
|
||||
|
||||
Binary file not shown.
BIN
docs/_template/last-modified/plugins/lib/alpine-x64/libgit2-a904fc6.so
vendored
Normal file
BIN
docs/_template/last-modified/plugins/lib/alpine-x64/libgit2-a904fc6.so
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
docs/_template/last-modified/plugins/lib/debian.9-x64/libgit2-a904fc6.so
vendored
Normal file
BIN
docs/_template/last-modified/plugins/lib/debian.9-x64/libgit2-a904fc6.so
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
docs/_template/last-modified/plugins/lib/fedora-x64/libgit2-a904fc6.so
vendored
Normal file
BIN
docs/_template/last-modified/plugins/lib/fedora-x64/libgit2-a904fc6.so
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
docs/_template/last-modified/plugins/lib/linux-x64/libgit2-a904fc6.so
vendored
Normal file
BIN
docs/_template/last-modified/plugins/lib/linux-x64/libgit2-a904fc6.so
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
docs/_template/last-modified/plugins/lib/osx/libgit2-a904fc6.dylib
vendored
Normal file
BIN
docs/_template/last-modified/plugins/lib/osx/libgit2-a904fc6.dylib
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
docs/_template/last-modified/plugins/lib/rhel-x64/libgit2-a904fc6.so
vendored
Normal file
BIN
docs/_template/last-modified/plugins/lib/rhel-x64/libgit2-a904fc6.so
vendored
Normal file
Binary file not shown.
BIN
docs/_template/last-modified/plugins/lib/ubuntu.18.04-x64/libgit2-a904fc6.so
vendored
Normal file
BIN
docs/_template/last-modified/plugins/lib/ubuntu.18.04-x64/libgit2-a904fc6.so
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
docs/_template/last-modified/plugins/lib/win32/x64/git2-a904fc6.dll
vendored
Normal file
BIN
docs/_template/last-modified/plugins/lib/win32/x64/git2-a904fc6.dll
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
docs/_template/last-modified/plugins/lib/win32/x86/git2-a904fc6.dll
vendored
Normal file
BIN
docs/_template/last-modified/plugins/lib/win32/x86/git2-a904fc6.dll
vendored
Normal file
Binary file not shown.
21
docs/_template/light-dark-theme/docfx-material-license.md
vendored
Normal file
21
docs/_template/light-dark-theme/docfx-material-license.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Oscar Vásquez
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -15,6 +15,7 @@
|
||||
<link rel="stylesheet" href="{{_rel}}styles/docfx.css">
|
||||
<link rel="stylesheet" href="{{_rel}}styles/master.css">
|
||||
<link rel="stylesheet" href="{{_rel}}styles/main.css">
|
||||
<link rel="stylesheet" href="{{_rel}}styles/material.css">
|
||||
<link rel="stylesheet" href="{{_rel}}styles/theme-switcher.css">
|
||||
<link href="https://cdn.rawgit.com/noelboss/featherlight/1.7.6/release/featherlight.min.css" type="text/css" rel="stylesheet" />
|
||||
<meta name="theme-color" content="#99AAB5"/>
|
||||
|
||||
14
docs/_template/light-dark-theme/styles/dark.css
vendored
14
docs/_template/light-dark-theme/styles/dark.css
vendored
@@ -7,6 +7,15 @@ body {
|
||||
color: #C0C0C0;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
color: #E0E0E0;
|
||||
}
|
||||
|
||||
button,
|
||||
a {
|
||||
color: #64B5F6;
|
||||
@@ -258,6 +267,11 @@ tbody>tr {
|
||||
border-top: 2px solid rgb(173, 173, 173)
|
||||
}
|
||||
|
||||
/* top navbar */
|
||||
.navbar-inverse[role="navigation"] {
|
||||
background-color: #2C2F33;
|
||||
}
|
||||
|
||||
/* select */
|
||||
|
||||
select {
|
||||
|
||||
@@ -361,7 +361,6 @@ pre {
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
color: #333;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
|
||||
15
docs/_template/light-dark-theme/styles/gray.css
vendored
15
docs/_template/light-dark-theme/styles/gray.css
vendored
@@ -7,6 +7,15 @@ body {
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
color: #EEEEEE;
|
||||
}
|
||||
|
||||
button,
|
||||
a {
|
||||
color: #64B5F6;
|
||||
@@ -39,13 +48,13 @@ hr {
|
||||
}
|
||||
|
||||
/* top navbar */
|
||||
.navbar-inverse[role="navigation"] {
|
||||
/*.navbar-inverse[role="navigation"] {
|
||||
background-color: #2C2F33;
|
||||
}
|
||||
}*/
|
||||
|
||||
/* sub navbar (below top) */
|
||||
.subnav {
|
||||
background: #282B2F
|
||||
background: rgb(69, 75, 82)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +1,37 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Titillium+Web|Noto+Sans');
|
||||
@import url('https://fonts.googleapis.com/css?family=Roboto|Muli|Fira+Mono');
|
||||
|
||||
html,
|
||||
body {
|
||||
font-family: 'Titillium Web', 'Segoe UI', Tahoma, Helvetica, sans-serif;
|
||||
font-family: 'Roboto', 'Segoe UI', Tahoma, Helvetica, sans-serif;
|
||||
font-display: optional;
|
||||
height: 100%;
|
||||
font-size: 15px;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
code{
|
||||
font-family: 'Fira Mono', 'Courier New', Courier, monospace
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: 'Muli', Verdana, Geneva, Tahoma, sans-serif;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
h1,
|
||||
.h1,
|
||||
h2,
|
||||
.h2,
|
||||
h3,
|
||||
.h3 {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#logo
|
||||
{
|
||||
max-width: 100px;
|
||||
@@ -25,6 +48,14 @@ li,
|
||||
line-height: 160%;
|
||||
}
|
||||
|
||||
.toc-filter{
|
||||
background: inherit !important;
|
||||
}
|
||||
|
||||
.affix ul>li.active>ul, .affix ul>li.active>a:before, .affix ul>li>a:hover:before{
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
img {
|
||||
box-shadow: 0px 0px 3px 0px rgb(66, 66, 66);
|
||||
max-width: 95% !important;
|
||||
@@ -57,16 +88,6 @@ article.content h6{
|
||||
transition: all .25s ease-in-out;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: 'Noto Sans', Verdana, Geneva, Tahoma, sans-serif;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
.sideaffix {
|
||||
line-height: 140%;
|
||||
}
|
||||
@@ -173,3 +194,38 @@ span.arrow-d{
|
||||
span.arrow-r{
|
||||
top: 6px; position: relative;
|
||||
}
|
||||
|
||||
/* widen viewport */
|
||||
|
||||
@media (min-width: 1085px) {
|
||||
.container {
|
||||
width: calc(100% - 15vw);
|
||||
max-width: calc(100% - 15vw);
|
||||
}
|
||||
}
|
||||
|
||||
/* fix level indentation */
|
||||
|
||||
.level2 {
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.level3 {
|
||||
padding: 0 5px;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.level4 {
|
||||
padding: 0 5px;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
.level5 {
|
||||
padding: 0 5px;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.level6 {
|
||||
padding: 0 5px;
|
||||
font-size: 75%;
|
||||
}
|
||||
199
docs/_template/light-dark-theme/styles/material.css
vendored
Normal file
199
docs/_template/light-dark-theme/styles/material.css
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
body {
|
||||
color: #34393e;
|
||||
line-height: 1.5;
|
||||
/*font-size: 16px;*/
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
word-wrap: break-word
|
||||
}
|
||||
|
||||
/* HEADINGS */
|
||||
|
||||
h1 {
|
||||
font-weight: 600;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: 600;
|
||||
font-size: 24px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 14px;
|
||||
padding: 10px 0px;
|
||||
}
|
||||
|
||||
article h1,
|
||||
article h2,
|
||||
article h3,
|
||||
article h4 {
|
||||
margin-top: 35px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
article h4 {
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 2px solid #ddd;
|
||||
}
|
||||
|
||||
/* NAVBAR */
|
||||
|
||||
.navbar-brand>img {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
border: none;
|
||||
/* Both navbars use box-shadow */
|
||||
-webkit-box-shadow: 0px 1px 3px 0px rgba(100, 100, 100, 0.5);
|
||||
-moz-box-shadow: 0px 1px 3px 0px rgba(100, 100, 100, 0.5);
|
||||
box-shadow: 0px 1px 3px 0px rgba(100, 100, 100, 0.5);
|
||||
}
|
||||
|
||||
.subnav {
|
||||
border-top: 1px solid #ddd;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.navbar-inverse {
|
||||
background-color: #0d47a1;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-nav>li>a,
|
||||
.navbar-inverse .navbar-text {
|
||||
color: #fff;
|
||||
/*background-color: #0d47a1;*/
|
||||
border-bottom: 3px solid transparent;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-nav>li>a:focus,
|
||||
.navbar-inverse .navbar-nav>li>a:hover {
|
||||
color: #fff;
|
||||
background-color: #1157c0;
|
||||
border-bottom: 3px solid white;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-nav>.active>a,
|
||||
.navbar-inverse .navbar-nav>.active>a:focus,
|
||||
.navbar-inverse .navbar-nav>.active>a:hover {
|
||||
color: #fff;
|
||||
background-color: #1157c0;
|
||||
border-bottom: 3px solid white;
|
||||
}
|
||||
|
||||
.navbar-form .form-control {
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
/* SIDEBAR */
|
||||
|
||||
/*.toc .level1>li {
|
||||
font-weight: 400;
|
||||
}*/
|
||||
|
||||
.toc .nav>li>a {
|
||||
color: #34393e;
|
||||
}
|
||||
|
||||
.sidefilter {
|
||||
background-color: #fff;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.sidefilter {
|
||||
background-color: #fff;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.toc-filter {
|
||||
padding: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.toc-filter>input {
|
||||
border: 2px solid #ddd;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.toc-filter>.filter-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidetoc>.toc {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.sidetoc {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* ALERTS */
|
||||
|
||||
.alert {
|
||||
padding: 0px 0px 5px 0px;
|
||||
color: inherit;
|
||||
background-color: inherit;
|
||||
border: none;
|
||||
box-shadow: 0px 2px 2px 0px rgba(100, 100, 100, 0.4);
|
||||
}
|
||||
|
||||
.alert>p {
|
||||
margin-bottom: 0;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.alert>ul {
|
||||
margin-bottom: 0;
|
||||
padding: 5px 40px;
|
||||
}
|
||||
|
||||
.alert>h5 {
|
||||
padding: 10px 15px;
|
||||
margin-top: 0;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.alert-info>h5 {
|
||||
color: #1976d2;
|
||||
border-bottom: 4px solid #1976d2;
|
||||
background-color: #e3f2fd;
|
||||
}
|
||||
|
||||
.alert-warning>h5 {
|
||||
color: #f57f17;
|
||||
border-bottom: 4px solid #f57f17;
|
||||
background-color: #fff3e0;
|
||||
}
|
||||
|
||||
.alert-danger>h5 {
|
||||
color: #d32f2f;
|
||||
border-bottom: 4px solid #d32f2f;
|
||||
background-color: #ffebee;
|
||||
}
|
||||
|
||||
/* CODE HIGHLIGHT */
|
||||
pre {
|
||||
padding: 9.5px;
|
||||
margin: 10px 10px 10px;
|
||||
font-size: 13px;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
/*background-color: #fffaef;*/
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 1px 4px 1px rgba(100, 100, 100, 0.4);
|
||||
}
|
||||
@@ -4,4 +4,7 @@ apiRules:
|
||||
type: Namespace
|
||||
- exclude:
|
||||
uidRegex: ^Discord\.Analyzers$
|
||||
type: Namespace
|
||||
- exclude:
|
||||
uidRegex: ^Discord\.API$
|
||||
type: Namespace
|
||||
@@ -3,6 +3,9 @@ public class Initialize
|
||||
private readonly CommandService _commands;
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
// Ask if there are existing CommandService and DiscordSocketClient
|
||||
// instance. If there are, we retrieve them and add them to the
|
||||
// DI container; if not, we create our own.
|
||||
public Initialize(CommandService commands = null, DiscordSocketClient client = null)
|
||||
{
|
||||
_commands = commands ?? new CommandService();
|
||||
|
||||
@@ -32,6 +32,6 @@ public class DatabaseModule : ModuleBase<SocketCommandContext>
|
||||
[Command("read")]
|
||||
public async Task ReadFromDbAsync()
|
||||
{
|
||||
await ReplyAsync(_database.GetData());
|
||||
await ReplyAsync(DbService.GetData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ public class CommandHandler
|
||||
private readonly DiscordSocketClient _client;
|
||||
private readonly CommandService _commands;
|
||||
|
||||
// Retrieve client and CommandService instance via ctor
|
||||
public CommandHandler(DiscordSocketClient client, CommandService commands)
|
||||
{
|
||||
_commands = commands;
|
||||
@@ -46,19 +47,9 @@ public class CommandHandler
|
||||
|
||||
// Execute the command with the command context we just
|
||||
// created, along with the service provider for precondition checks.
|
||||
|
||||
// Keep in mind that result does not indicate a return value
|
||||
// rather an object stating if the command executed successfully.
|
||||
var result = await _commands.ExecuteAsync(
|
||||
await _commands.ExecuteAsync(
|
||||
context: context,
|
||||
argPos: argPos,
|
||||
services: null);
|
||||
|
||||
// Optionally, we may inform the user if the command fails
|
||||
// to be executed; however, this may not always be desired,
|
||||
// as it may clog up the request queue should a user spam a
|
||||
// command.
|
||||
// if (!result.IsSuccess)
|
||||
// await context.Channel.SendMessageAsync(result.ErrorReason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
public async Task LogAsync(LogMessage logMessage)
|
||||
{
|
||||
// This casting type requries C#7
|
||||
if (logMessage.Exception is CommandException cmdException)
|
||||
{
|
||||
// We can tell the user that something unexpected has happened
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Note: This example is obsolete, a boolean type reader is bundled
|
||||
// with Discord.Commands
|
||||
// Please note that the library already supports type reading
|
||||
// primitive types such as bool. This example is merely used
|
||||
// to demonstrate how one could write a simple TypeReader.
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
|
||||
|
||||
@@ -35,10 +35,6 @@ sync and has a completed guild cache.
|
||||
|
||||
[DiscordSocketClient]: xref:Discord.WebSocket.DiscordSocketClient
|
||||
|
||||
### Samples
|
||||
|
||||
[!code-csharp[Connection Sample](samples/events.cs)]
|
||||
|
||||
## Reconnection
|
||||
|
||||
> [!TIP]
|
||||
|
||||
@@ -7,7 +7,7 @@ title: Entities
|
||||
|
||||
> [!NOTE]
|
||||
> This article is written with the Socket variants of entities in mind,
|
||||
> not the general interfaces or Rest/Rpc entities.
|
||||
> not the general interfaces or Rest entities.
|
||||
|
||||
Discord.Net provides a versatile entity system for navigating the
|
||||
Discord API.
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
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, Environment.GetEnvironmentVariable("DiscordToken"));
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,24 @@
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
|
||||
public class Program
|
||||
public class LoggingService
|
||||
{
|
||||
private DiscordSocketClient _client;
|
||||
static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult();
|
||||
|
||||
public async Task MainAsync()
|
||||
public LoggingService(DiscordSocketClient client, CommandService command)
|
||||
{
|
||||
_client = new DiscordSocketClient(new DiscordSocketConfig
|
||||
{
|
||||
LogLevel = LogSeverity.Info
|
||||
});
|
||||
|
||||
_client.Log += Log;
|
||||
|
||||
await _client.LoginAsync(TokenType.Bot, Environment.GetEnvironmentVariable("DiscordToken"));
|
||||
await _client.StartAsync();
|
||||
|
||||
await Task.Delay(-1);
|
||||
client.Log += LogAsync;
|
||||
command.Log += LogAsync;
|
||||
}
|
||||
|
||||
private Task Log(LogMessage message)
|
||||
private Task LogAsync(LogMessage message)
|
||||
{
|
||||
Console.WriteLine(message.ToString());
|
||||
if (message.Exception is CommandException cmdException)
|
||||
{
|
||||
Console.WriteLine($"[Command/{message.Severity}] {cmdException.Command.Aliases.First()}"
|
||||
+ $" failed to execute in {cmdException.Context.Channel}.");
|
||||
Console.WriteLine(cmdException);
|
||||
}
|
||||
else
|
||||
Console.WriteLine($"[General/{message.Severity}] {message}");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -128,12 +128,10 @@ 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 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.
|
||||
if you are unsure of the differences. 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 we had just created. Events in Discord.Net work
|
||||
@@ -142,22 +140,33 @@ similarly to any other events in C#.
|
||||
Next, you will need to "log in to Discord" with the [LoginAsync]
|
||||
method with the application's "token."
|
||||
|
||||

|
||||
|
||||
> [!NOTE]
|
||||
> Pay attention to what you are copying from the developer portal!
|
||||
> A token is not the same as the application's "client secret."
|
||||
|
||||

|
||||
|
||||
> [!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 source if you plan on distributing
|
||||
> **do not** share this token with anyone else! You should store this
|
||||
> token in an external source if you plan on distributing
|
||||
> the source code for your bot.
|
||||
>
|
||||
> In the following example, we retrieve the token from the environment
|
||||
> variable `DiscordToken`. Please note that this is *not* designed to
|
||||
> be used in a production environment, as the secrets are stored in
|
||||
> plain-text.
|
||||
>
|
||||
> For information on how to set an environment variable, please see
|
||||
> instructions below,
|
||||
>
|
||||
> * Windows: [How to Create Environment Variables Shortcut in Windows](https://www.tenforums.com/tutorials/121742-create-environment-variables-shortcut-windows.html)
|
||||
> * Linux: [How To Read and Set Environmental and Shell Variables on a Linux VPS](https://www.digitalocean.com/community/tutorials/how-to-read-and-set-environmental-and-shell-variables-on-a-linux-vps)
|
||||
> * macOS: [How do I set environment variables on OS X?](https://apple.stackexchange.com/questions/106778/how-do-i-set-environment-variables-on-os-x)
|
||||
|
||||
We may now invoke the client's [StartAsync] method, which will
|
||||
start connection/reconnection logic. It is important to note that
|
||||
**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. This means that you should **not** directly be interacting with
|
||||
the client before it is fully ready.
|
||||
@@ -173,81 +182,34 @@ The following lines can now be added:
|
||||
At this point, feel free to start your program and see your bot come
|
||||
online in Discord.
|
||||
|
||||
> [!TIP]
|
||||
> [!WARNING]
|
||||
> Getting a warning about `A supplied token was invalid.` and/or
|
||||
> having trouble logging in? Double-check whether you have put in
|
||||
> the correct credentials and make sure that it is _not_ a client
|
||||
> secret, which is different from a token.
|
||||
|
||||
> [!TIP]
|
||||
> [!WARNING]
|
||||
> 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.
|
||||
|
||||
> [!NOTE]
|
||||
> For your reference, you may view the [completed program].
|
||||
|
||||
[DiscordSocketClient]: xref:Discord.WebSocket.DiscordSocketClient
|
||||
[LoginAsync]: xref:Discord.Rest.BaseDiscordClient.LoginAsync*
|
||||
[StartAsync]: xref:Discord.WebSocket.DiscordSocketClient.StartAsync*
|
||||
[installation guide]: xref:Guides.GettingStarted.Installation
|
||||
|
||||
### 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](xref:Guides.Commands.Intro) section.
|
||||
|
||||
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
|
||||
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,
|
||||
`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 [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/first-bot/message.cs)]
|
||||
|
||||
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.
|
||||
|
||||
> [!NOTE]
|
||||
> For your reference, you may view the [completed program].
|
||||
|
||||
[MessageReceived]: xref:Discord.WebSocket.BaseSocketClient.MessageReceived
|
||||
[SocketMessage]: xref:Discord.WebSocket.SocketMessage
|
||||
[ISocketMessageChannel]: xref:Discord.WebSocket.ISocketMessageChannel
|
||||
[SendMessageAsync]: xref:Discord.WebSocket.ISocketMessageChannel.SendMessageAsync*
|
||||
[completed program]: samples/first-bot/complete.cs
|
||||
|
||||
# Building a bot with commands
|
||||
|
||||
@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.
|
||||
To create commands for your bot, you may choose from a variety of
|
||||
command processors available. Throughout the guides, we will be using
|
||||
the one that Discord.Net ships with. @Guides.Commands.Intro will
|
||||
guide you through how to setup a program that is ready for
|
||||
[CommandService].
|
||||
|
||||
For reference, view an [annotated example] of this structure.
|
||||
|
||||
|
||||
@@ -42,37 +42,45 @@ published to our [MyGet feed]. See
|
||||
|
||||
### [Using Visual Studio](#tab/vs-install)
|
||||
|
||||
1. Create a new solution for your bot.
|
||||
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."
|
||||

|
||||
4. In the "Browse" tab, search for `Discord.Net`.
|
||||
5. Install the `Discord.Net` package.
|
||||

|
||||
bot's project
|
||||
3. Right click on "Dependencies", and select "Manage NuGet packages"
|
||||
|
||||

|
||||
|
||||
4. In the "Browse" tab, search for `Discord.Net`
|
||||
5. Install the `Discord.Net` package
|
||||
|
||||

|
||||
|
||||
### [Using JetBrains Rider](#tab/rider-install)
|
||||
|
||||
1. Create a new solution for your bot.
|
||||
2. Open the NuGet window (Tools > NuGet > Manage NuGet packages for
|
||||
Solution).
|
||||

|
||||
3. In the "Packages" tab, search for `Discord.Net`.
|
||||

|
||||
4. Install by adding the package to your project.
|
||||

|
||||
1. Create a new solution for your bot
|
||||
2. Open the NuGet window (Tools > NuGet > Manage NuGet packages for Solution)
|
||||
|
||||

|
||||
|
||||
3. In the "Packages" tab, search for `Discord.Net`
|
||||
|
||||

|
||||
|
||||
4. Install by adding the package to your project
|
||||
|
||||

|
||||
|
||||
### [Using Visual Studio Code](#tab/vs-code)
|
||||
|
||||
1. Create a new project for your bot.
|
||||
2. Add `Discord.Net` to your .csproj.
|
||||
1. Create a new project for your bot
|
||||
2. Add `Discord.Net` to your `*.csproj`
|
||||
|
||||
[!code[Sample .csproj](samples/project.xml)]
|
||||
|
||||
### [Using dotnet CLI](#tab/dotnet-cli)
|
||||
|
||||
1. Open command-line and navigate to where your .csproj is located.
|
||||
2. Enter `dotnet add package Discord.Net`.
|
||||
1. Launch your terminal
|
||||
2. Navigate to where your `*.csproj` is located
|
||||
3. Enter `dotnet add package Discord.Net`
|
||||
|
||||
***
|
||||
|
||||
@@ -115,16 +123,16 @@ by installing one or more custom packages as listed below.
|
||||
|
||||
1. Install or compile the following packages:
|
||||
|
||||
* `Discord.Net.Providers.WS4Net`
|
||||
* `Discord.Net.Providers.UDPClient` (Optional)
|
||||
* This is _only_ required if your bot will be utilizing voice chat.
|
||||
* `Discord.Net.Providers.WS4Net`
|
||||
* `Discord.Net.Providers.UDPClient` (Optional)
|
||||
* This is _only_ required if your bot will be utilizing voice chat.
|
||||
|
||||
2. Configure your [DiscordSocketClient] to use these custom providers
|
||||
over the default ones.
|
||||
|
||||
* To do this, set the `WebSocketProvider` and the optional
|
||||
`UdpSocketProvider` properties on the [DiscordSocketConfig] that you
|
||||
are passing into your client.
|
||||
* To do this, set the `WebSocketProvider` and the optional
|
||||
`UdpSocketProvider` properties on the [DiscordSocketConfig] that you
|
||||
are passing into your client.
|
||||
|
||||
[!code-csharp[Example](samples/netstd11.cs)]
|
||||
|
||||
|
||||
@@ -31,22 +31,33 @@ The following is the feed link of Discord.Net,
|
||||
Depending on which IDE you use, there are many different ways of
|
||||
adding the feed to your package source.
|
||||
|
||||
### [Visual Studio](#tab/vs)
|
||||
### [Using Visual Studio](#tab/vs)
|
||||
|
||||
1. Go to `Tools` > `NuGet Package Manager` > `Package Manager Settings`
|
||||
|
||||

|
||||
|
||||
2. Go to `Package Sources`
|
||||
|
||||

|
||||
|
||||
3. Click on the add icon
|
||||
4. Fill in the desired name and source as shown below and hit `Update`
|
||||
|
||||

|
||||
|
||||
> [!NOTE]
|
||||
> Remember to tick the `Include prerelease` checkbox to see the
|
||||
> Remember to tick the `Include pre-release` checkbox to see the
|
||||
> nightly builds!
|
||||
> 
|
||||
|
||||
### [Local NuGet.Config](#tab/local-nuget-config)
|
||||
### [Using dotnet CLI](#tab/cli)
|
||||
|
||||
1. Launch your terminal
|
||||
2. Navigate to where your `*.csproj` is located
|
||||
3. Type `dotnet add package Discord.Net --source https://www.myget.org/F/discord-net/api/v3/index.json`
|
||||
|
||||
### [Using Local NuGet.Config](#tab/local-nuget-config)
|
||||
|
||||
If you plan on deploying your bot or developing outside of Visual
|
||||
Studio, you will need to create a local NuGet configuration file for
|
||||
|
||||
@@ -9,7 +9,6 @@ public class Program
|
||||
{
|
||||
_client = new DiscordSocketClient();
|
||||
_client.Log += Log;
|
||||
_client.MessageReceived += MessageReceivedAsync;
|
||||
await _client.LoginAsync(TokenType.Bot,
|
||||
Environment.GetEnvironmentVariable("DiscordToken"));
|
||||
await _client.StartAsync();
|
||||
@@ -17,15 +16,6 @@ public class Program
|
||||
// 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());
|
||||
|
||||
@@ -16,17 +16,14 @@ understand these topics to some extent before proceeding. With all
|
||||
that being said, feel free to visit us on Discord at the link below
|
||||
if you have any questions!
|
||||
|
||||
Here are some examples:
|
||||
|
||||
1. [Official samples]
|
||||
2. [Official template]
|
||||
An official collection of samples can be found
|
||||
in [our GitHub repository].
|
||||
|
||||
> [!NOTE]
|
||||
> Please note that you should *not* try to blindly copy paste
|
||||
> the code. The examples are meant to be a template or a guide.
|
||||
|
||||
[Official template]: https://github.com/foxbot/DiscordBotBase/tree/csharp/src/DiscordBot
|
||||
[Official samples]: https://github.com/RogueException/Discord.Net/tree/dev/samples
|
||||
[our GitHub repository]: https://github.com/RogueException/Discord.Net/tree/dev/samples
|
||||
[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/
|
||||
|
||||
Reference in New Issue
Block a user