Update Documentation to be compatible with Beta2
this one took a while
This commit is contained in:
@@ -3,4 +3,10 @@
|
|||||||
|
|
||||||
This is where you will find documentation for all members and objects in Discord.Net
|
This is where you will find documentation for all members and objects in Discord.Net
|
||||||
|
|
||||||
**TODO:** Think of something useful to put on this page.
|
__Commonly Used Entities__
|
||||||
|
@Discord.WebSocket
|
||||||
|
@Discord.WebSocket.DiscordSocketClient
|
||||||
|
@Discord.WebSocket.SocketGuildChannel
|
||||||
|
@Discord.WebSocket.SocketGuildUser
|
||||||
|
@Discord.WebSocket.SocketMessage
|
||||||
|
@Discord.WebSocket.SocketRole
|
||||||
@@ -1,37 +1,60 @@
|
|||||||
# The Command Service
|
# The Command Service
|
||||||
|
|
||||||
[Discord.Commands](xref:Discord.Commands) provides an Attribute-based Command Parser.
|
[Discord.Commands](xref:Discord.Commands) provides an Attribute-based
|
||||||
|
Command Parser.
|
||||||
|
|
||||||
### Setup
|
### Setup
|
||||||
|
|
||||||
To use Commands, you must create a [Commands Service](xref:Discord.Commands.CommandService) and a Command Handler.
|
To use Commands, you must create a
|
||||||
|
[Commands Service](xref:Discord.Commands.CommandService)
|
||||||
|
and a Command Handler.
|
||||||
|
|
||||||
Included below is a very bare-bones Command Handler. You can extend your Command Handler as much as you like, however the below is the bare minimum.
|
Included below is a very bare-bones Command Handler. You can extend
|
||||||
|
your Command Handler as much as you like, however the below is the
|
||||||
|
bare minimum.
|
||||||
|
|
||||||
[!code-csharp[Barebones Command Handler](samples/command_handler.cs)]
|
[!code-csharp[Barebones Command Handler](samples/command_handler.cs)]
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
In 1.0, Commands are no longer implemented at runtime with a builder pattern.
|
In 1.0, Commands are no longer implemented at runtime with a builder
|
||||||
While a builder pattern may be provided later, commands are created primarily with
|
pattern. While a builder pattern may be provided later, commands are
|
||||||
attributes.
|
created primarily with attributes.
|
||||||
|
|
||||||
### Basic Structure
|
### Basic Structure
|
||||||
|
|
||||||
All commands belong to a Module. (See the below section for creating modules.)
|
All commands belong to a Module. (See the below section for creating
|
||||||
|
modules).
|
||||||
|
|
||||||
All commands in a module must be defined as an `Task`, with at least one argument,
|
All commands in a module must be defined as a `Task`.
|
||||||
being the @Discord.IUserMessage representing the context of the command.
|
|
||||||
|
|
||||||
To add parameters to your command, add additional arguments to the `Task` of the command.
|
To add parameters to your command, you simply need to add parameters
|
||||||
You are _not_ required to accept all arguments as `String`, they will be automatically parsed
|
to the Task that represents the command. You are _not_ required to
|
||||||
into the type you specify for the arument. See the Example Module for an example of command parameters.
|
accept all arguments as `String`, they will be automatically parsed
|
||||||
|
into the type you specify for the arument. See the Example Module
|
||||||
|
for an example of command parameters.
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
Modules serve as a host for commands you create.
|
Modules are an organizational pattern that allow you to write your
|
||||||
|
commands in different classes, and have them automatically loaded.
|
||||||
|
|
||||||
To create a module, create a class that you will place commands in. Flag this class with the `[Module]` attribute. You may optionally pass in a string to the `Module` attribute to set a prefix for all of the commands inside the module.
|
Discord.Net's implementation of Modules is influenced heavily from
|
||||||
|
ASP.Net Core's Controller pattern. This means that the lifetime of a
|
||||||
|
module instance is only as long as the command being ran in it.
|
||||||
|
|
||||||
|
**Avoid using long-running code** in your modules whereever possible.
|
||||||
|
You should **not** be implementing very much logic into your modules;
|
||||||
|
outsource to a service for that.
|
||||||
|
|
||||||
|
If you are unfamiliar with Inversion of Control, it is recommended to
|
||||||
|
read the MSDN article on [IoC] and [Dependency Injection].
|
||||||
|
|
||||||
|
To create a module, create a class that inherits from
|
||||||
|
@Discord.Commands.ModuleBase.
|
||||||
|
|
||||||
|
[IoC]: https://msdn.microsoft.com/en-us/library/ff921087.aspx
|
||||||
|
[Dependency Injection]: https://msdn.microsoft.com/en-us/library/ff921152.aspx
|
||||||
|
|
||||||
### Example Module
|
### Example Module
|
||||||
|
|
||||||
@@ -39,68 +62,95 @@ To create a module, create a class that you will place commands in. Flag this cl
|
|||||||
|
|
||||||
#### Loading Modules Automatically
|
#### Loading Modules Automatically
|
||||||
|
|
||||||
The Command Service can automatically discover all classes in an Assembly that are flagged with the `Module` attribute, and load them.
|
The Command Service can automatically discover all classes in an
|
||||||
|
Assembly that inherit @Discord.Commands.ModuleBase, and load them.
|
||||||
|
|
||||||
To have a module opt-out of auto-loading, pass `autoload: false` in the Module attribute.
|
To have a module opt-out of auto-loading, pass `autoload: false` in
|
||||||
|
the Module attribute.
|
||||||
|
|
||||||
Invoke [CommandService.LoadAssembly](xref:Discord.Commands.CommandService#Discord_Commands_CommandService_LoadAssembly) to discover modules and install them.
|
Invoke [CommandService.AddModules] to discover modules and install them.
|
||||||
|
|
||||||
|
[CommandService.AddModules]: xref:Discord.Commands.CommandService#Discord_Commands_CommandService_AddModules
|
||||||
|
|
||||||
#### Loading Modules Manually
|
#### Loading Modules Manually
|
||||||
|
|
||||||
To manually load a module, invoke [CommandService.Load](xref:Discord.Commands.CommandService#Discord_Commands_CommandService_Load), and pass in an instance of your module.
|
To manually load a module, invoke [CommandService.AddModule],
|
||||||
|
by passing in the generic type of your module, and optionally
|
||||||
|
a dependency map.
|
||||||
|
|
||||||
|
[CommandService.AddModule]: xref:Discord.Commands.CommandService#Discord_Commands_CommandService_AddModule__1_Discord_Commands_IDependencyMap_
|
||||||
|
|
||||||
### Module Constructors
|
### Module Constructors
|
||||||
|
|
||||||
When automatically loading modules, you are limited in your constructor. Using a constructor that accepts _no arguments_, or a constructor that accepts a @Discord.Commands.CommandService will always work.
|
Modules are constructed using Dependency Injection. Any parameters
|
||||||
|
that are placed in the constructor must be injected into an
|
||||||
Alternatively, you can use an @Discord.Commands.IDependencyMap, as shown below.
|
@Discord.Commands.IDependencyMap. Alternatively, you may accept an
|
||||||
|
IDependencyMap as an argument and extract services yourself.
|
||||||
|
|
||||||
### Command Groups
|
### Command Groups
|
||||||
|
|
||||||
Command groups function similarly to Modules, but they must be contained inside a module. Simply create a **public** class inside a module, and flag it with the @Discord.Commands.GroupAttribute
|
Command Groups allow you to create a module where commands are prefixed.
|
||||||
|
To create a group, create a new module and flag it with the
|
||||||
|
@Discord.Commands.GroupAttribute.
|
||||||
|
|
||||||
|
>![NOTE]
|
||||||
|
>Groups do not _need_ to be modules. Only classes with commands should
|
||||||
|
>inherit from ModuleBase. If you plan on using a group for strictly
|
||||||
|
>organizational purposes, there is no reason to make it a module.
|
||||||
|
|
||||||
[!code-csharp[Groups Sample](samples/groups.cs)]
|
[!code-csharp[Groups Sample](samples/groups.cs)]
|
||||||
|
|
||||||
## Dependency Injection
|
## Dependency Injection
|
||||||
|
|
||||||
The Commands Service includes a very basic implementation of Dependency Injection that allows you to have completely custom constructors, within certain limitations.
|
The commands service is bundled with a very barebones Dependency
|
||||||
|
Injection service for your convienence. It is recommended that
|
||||||
|
you use DI when writing your modules.
|
||||||
|
|
||||||
### Setup
|
### Setup
|
||||||
|
|
||||||
First, you need to create an @Discord.Commands.IDependencyMap . The library includes @Discord.Commands.DependencyMap to help with this, however you may create your own IDependencyMap if you wish.
|
First, you need to create an @Discord.Commands.IDependencyMap.
|
||||||
|
The library includes @Discord.Commands.DependencyMap to help with
|
||||||
|
this, however you may create your own IDependencyMap if you wish.
|
||||||
|
|
||||||
Next, add the dependencies your modules will use to the map.
|
Next, add the dependencies your modules will use to the map.
|
||||||
|
|
||||||
Finally, pass the map into the `LoadAssembly` method. Your modules will automatically be loaded with this dependency map.
|
Finally, pass the map into the `LoadAssembly` method.
|
||||||
|
Your modules will automatically be loaded with this dependency map.
|
||||||
|
|
||||||
[!code-csharp[DependencyMap Setup](samples/dependency_map_setup.cs)]
|
[!code-csharp[DependencyMap Setup](samples/dependency_map_setup.cs)]
|
||||||
|
|
||||||
### Usage in Modules
|
### Usage in Modules
|
||||||
|
|
||||||
In the constructor of your module, any parameters will be filled in by the @Discord.Commands.IDependencyMap you pass into `LoadAssembly`.
|
In the constructor of your module, any parameters will be filled in by
|
||||||
|
the @Discord.Commands.IDependencyMap you pass into `LoadAssembly`.
|
||||||
|
|
||||||
>[!NOTE]
|
>[!NOTE]
|
||||||
>If you accept `CommandService` or `IDependencyMap` as a parameter in your constructor, these parameters will be filled by the CommandService the module was loaded from, and the DependencyMap passed into it, respectively.
|
>If you accept `CommandService` or `IDependencyMap` as a parameter in
|
||||||
|
your constructor, these parameters will be filled by the
|
||||||
|
CommandService the module was loaded from, and the DependencyMap passed
|
||||||
|
into it, respectively.
|
||||||
|
|
||||||
[!code-csharp[DependencyMap in Modules](samples/dependency_module.cs)]
|
[!code-csharp[DependencyMap in Modules](samples/dependency_module.cs)]
|
||||||
|
|
||||||
# Preconditions
|
# Preconditions
|
||||||
|
|
||||||
Preconditions serve as a permissions system for your commands. Keep in mind, however, that they are
|
Preconditions serve as a permissions system for your commands. Keep in
|
||||||
not limited to _just_ permissions, and can be as complex as you want them to be.
|
mind, however, that they are not limited to _just_ permissions, and
|
||||||
|
can be as complex as you want them to be.
|
||||||
|
|
||||||
>[!NOTE]
|
>[!NOTE]
|
||||||
>Preconditions can be applied to Modules, Groups, or Commands.
|
>Preconditions can be applied to Modules, Groups, or Commands.
|
||||||
|
|
||||||
## Bundled Preconditions
|
## Bundled Preconditions
|
||||||
|
|
||||||
@Discord.Commands ships with two built-in preconditions, @Discord.Commands.RequireContextAttribute
|
@Discord.Commands ships with two built-in preconditions,
|
||||||
and @Discord.Commands.RequirePermissionAttribute.
|
@Discord.Commands.RequireContextAttribute and
|
||||||
|
@Discord.Commands.RequirePermissionAttribute.
|
||||||
|
|
||||||
### RequireContext
|
### RequireContext
|
||||||
|
|
||||||
@Discord.Commands.RequireContextAttribute is a precondition that requires your command to be
|
@Discord.Commands.RequireContextAttribute is a precondition that
|
||||||
executed in the specified context.
|
requires your command to be executed in the specified context.
|
||||||
|
|
||||||
You may require three different types of context:
|
You may require three different types of context:
|
||||||
* Guild
|
* Guild
|
||||||
@@ -113,29 +163,34 @@ Since these are `Flags`, you may OR them together.
|
|||||||
|
|
||||||
### RequirePermission
|
### RequirePermission
|
||||||
|
|
||||||
@Discord.Commands.RequirePermissionAttribute is a precondition that allows you to quickly
|
@Discord.Commands.RequirePermissionAttribute is a precondition that
|
||||||
specfiy that a user must poesess a permission to execute a command.
|
allows you to quickly specfiy that a user must poesess a permission
|
||||||
|
to execute a command.
|
||||||
|
|
||||||
You may require either a @Discord.GuildPermission or @Discord.ChannelPermission
|
You may require either a @Discord.GuildPermission or
|
||||||
|
@Discord.ChannelPermission
|
||||||
|
|
||||||
[!code-csharp[RequireContext](samples/require_permission.cs)]
|
[!code-csharp[RequireContext](samples/require_permission.cs)]
|
||||||
|
|
||||||
## Custom Preconditions
|
## Custom Preconditions
|
||||||
|
|
||||||
To write your own preconditions, create a new class that inherits from @Discord.Commands.PreconditionAttribute
|
To write your own preconditions, create a new class that inherits from
|
||||||
|
@Discord.Commands.PreconditionAttribute
|
||||||
|
|
||||||
In order for your precondition to function, you will need to override `CheckPermissions`,
|
In order for your precondition to function, you will need to override
|
||||||
which is a `Task<PreconditionResult>`.
|
`CheckPermissions`, which is a `Task<PreconditionResult>`.
|
||||||
Your IDE should provide an option to fill this in for you.
|
Your IDE should provide an option to fill this in for you.
|
||||||
|
|
||||||
Return `PreconditionResult.FromSuccess()` if the context met the required parameters, otherwise
|
Return `PreconditionResult.FromSuccess()` if the context met the
|
||||||
return `PreconditionResult.FromError()`, optionally including an error message.
|
required parameters, otherwise return `PreconditionResult.FromError()`,
|
||||||
|
optionally including an error message.
|
||||||
|
|
||||||
[!code-csharp[Custom Precondition](samples/require_owner.cs)]
|
[!code-csharp[Custom Precondition](samples/require_owner.cs)]
|
||||||
|
|
||||||
# Type Readers
|
# Type Readers
|
||||||
|
|
||||||
Type Readers allow you to parse different types of arguments in your commands.
|
Type Readers allow you to parse different types of arguments in
|
||||||
|
your commands.
|
||||||
|
|
||||||
By default, the following Types are supported arguments:
|
By default, the following Types are supported arguments:
|
||||||
|
|
||||||
@@ -153,16 +208,20 @@ By default, the following Types are supported arguments:
|
|||||||
|
|
||||||
### Creating a Type Readers
|
### Creating a Type Readers
|
||||||
|
|
||||||
To create a TypeReader, create a new class that imports @Discord and @Discord.Commands . Ensure your class inherits from @Discord.Commands.TypeReader
|
To create a TypeReader, create a new class that imports @Discord and
|
||||||
|
@Discord.Commands. Ensure your class inherits from @Discord.Commands.TypeReader
|
||||||
|
|
||||||
Next, satisfy the `TypeReader` class by overriding `Task<TypeReaderResult> Read(IUserMessage context, string input)`.
|
Next, satisfy the `TypeReader` class by overriding `Task<TypeReaderResult> Read(CommandContext context, string input)`.
|
||||||
|
|
||||||
>[!NOTE]
|
>[!NOTE]
|
||||||
>In many cases, Visual Studio can fill this in for you, using the "Implement Abstract Class" IntelliSense hint.
|
>In many cases, Visual Studio can fill this in for you, using the
|
||||||
|
>"Implement Abstract Class" IntelliSense hint.
|
||||||
|
|
||||||
Inside this task, add whatever logic you need to parse the input string.
|
Inside this task, add whatever logic you need to parse the input string.
|
||||||
|
|
||||||
Finally, return a `TypeReaderResult`. If you were able to successfully parse the input, return `TypeReaderResult.FromSuccess(parsedInput)`. Otherwise, return `TypeReaderResult.FromError`.
|
Finally, return a `TypeReaderResult`. If you were able to successfully
|
||||||
|
parse the input, return `TypeReaderResult.FromSuccess(parsedInput)`.
|
||||||
|
Otherwise, return `TypeReaderResult.FromError`.
|
||||||
|
|
||||||
#### Sample
|
#### Sample
|
||||||
|
|
||||||
@@ -170,4 +229,5 @@ Finally, return a `TypeReaderResult`. If you were able to successfully parse the
|
|||||||
|
|
||||||
### Installing TypeReaders
|
### Installing TypeReaders
|
||||||
|
|
||||||
TypeReaders are not automatically discovered by the Command Service, and must be explicitly added. To install a TypeReader, invoke [CommandService.AddTypeReader](xref:Discord.Commands.CommandService#Discord_Commands_CommandService_AddTypeReader__1_Discord_Commands_TypeReader_).
|
TypeReaders are not automatically discovered by the Command Service,
|
||||||
|
and must be explicitly added. To install a TypeReader, invoke [CommandService.AddTypeReader](xref:Discord.Commands.CommandService#Discord_Commands_CommandService_AddTypeReader__1_Discord_Commands_TypeReader_).
|
||||||
@@ -16,6 +16,8 @@ Bot accounts must be added to a server, you must use the [OAuth 2 Flow](https://
|
|||||||
|
|
||||||
You can install Discord.Net 1.0 from our [MyGet Feed](https://www.myget.org/feed/Packages/discord-net).
|
You can install Discord.Net 1.0 from our [MyGet Feed](https://www.myget.org/feed/Packages/discord-net).
|
||||||
|
|
||||||
|
**For most users writing bots, install only `Discord.Net.WebSocket`.**
|
||||||
|
|
||||||
You may add the MyGet feed to Visual Studio directly from `https://www.myget.org/F/discord-net/api/v3/index.json`.
|
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).
|
You can also pull the latest source from [GitHub](https://github.com/RogueException/Discord.Net).
|
||||||
|
|||||||
@@ -17,8 +17,4 @@ title: Samples
|
|||||||
|
|
||||||
#### Sending a message to a channel
|
#### Sending a message to a channel
|
||||||
|
|
||||||
[!code-csharp[Message to Channel](samples/faq/send_message.cs)]
|
[!code-csharp[Message to Channel](samples/faq/send_message.cs)]
|
||||||
|
|
||||||
#### Retrieving an IGuild from an IUserMessage
|
|
||||||
|
|
||||||
[!code-csharp[Message to Guild](samples/faq/guild_from_message.cs)]
|
|
||||||
@@ -33,21 +33,21 @@ public class Program
|
|||||||
// Discover all of the commands in this assembly and load them.
|
// Discover all of the commands in this assembly and load them.
|
||||||
await commands.LoadAssembly(Assembly.GetEntryAssembly());
|
await commands.LoadAssembly(Assembly.GetEntryAssembly());
|
||||||
}
|
}
|
||||||
public async Task HandleCommand(IMessage paramMessage)
|
public async Task HandleCommand(SocketMessage messageParam)
|
||||||
{
|
{
|
||||||
// Cast paramMessage to an IUserMessage, return if the message was a System message.
|
// Don't process the command if it was a System Message
|
||||||
var msg = paramMessage as IUserMessage;
|
var message = messageParam as SocketUserMessage;
|
||||||
if (msg == null) return;
|
if (message == null) return;
|
||||||
// Internal integer, marks where the command begins
|
// Create a number to track where the prefix ends and the command begins
|
||||||
int argPos = 0;
|
int argPos = 0;
|
||||||
// Get the current user (used for Mention parsing)
|
|
||||||
var currentUser = await client.GetCurrentUserAsync();
|
|
||||||
// Determine if the message is a command, based on if it starts with '!' or a mention prefix
|
// Determine if the message is a command, based on if it starts with '!' or a mention prefix
|
||||||
if (msg.HasCharPrefix('!', ref argPos) || msg.HasMentionPrefix(currentUser, ref argPos))
|
if (message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(client.CurrentUser, ref argPos))
|
||||||
{
|
{
|
||||||
// Execute the command. (result does not indicate a return value,
|
// Create a Command Context
|
||||||
|
var context = new CommandContext(client, message);
|
||||||
|
// Execute the command. (result does not indicate a return value,
|
||||||
// rather an object stating if the command executed succesfully)
|
// rather an object stating if the command executed succesfully)
|
||||||
var result = await _commands.Execute(msg, argPos);
|
var result = await _commands.Execute(context, argPos);
|
||||||
if (!result.IsSuccess)
|
if (!result.IsSuccess)
|
||||||
await msg.Channel.SendMessageAsync(result.ErrorReason);
|
await msg.Channel.SendMessageAsync(result.ErrorReason);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using foxboat.Services;
|
||||||
|
|
||||||
public class Commands
|
public class Commands
|
||||||
{
|
{
|
||||||
@@ -8,10 +9,16 @@ public class Commands
|
|||||||
{
|
{
|
||||||
var commands = new CommandService();
|
var commands = new CommandService();
|
||||||
var map = new DependencyMap();
|
var map = new DependencyMap();
|
||||||
map.Add<IDiscordClient>(client);
|
map.Add(client);
|
||||||
var self = await client.GetCurrentUserAsync();
|
map.Add(commands);
|
||||||
map.Add<ISelfUser>(self);
|
|
||||||
await commands.LoadAssembly(Assembly.GetCurrentAssembly(), map);
|
await commands.LoadAssembly(Assembly.GetCurrentAssembly(), map);
|
||||||
}
|
}
|
||||||
|
// In ConfigureServices, we will inject the Dependency Map with
|
||||||
|
// all of the services our client will use.
|
||||||
|
public Task ConfigureServices(IDependencyMap map)
|
||||||
|
{
|
||||||
|
map.Add(new NotificationService(map));
|
||||||
|
map.Add(new DatabaseService(map));
|
||||||
|
}
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
public async Task ChangeAvatar()
|
public async Task ChangeAvatar()
|
||||||
{
|
{
|
||||||
var fileStream = new FileStream("./newAvatar.png", FileMode.Open);
|
var fileStream = new FileStream("./newAvatar.png", FileMode.Open);
|
||||||
await (await _client.GetCurrentUserAsync()).ModifyAsync(x => x.Avatar = fileStream);
|
await _client.CurrentUser.ModifyAsync(x => x.Avatar = fileStream);
|
||||||
}
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
public async Task MessageReceived(IMessage msg)
|
|
||||||
{
|
|
||||||
var guild = (msg.Channel as IGuildChannel)?.Guild;
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
public async Task SendMessageToChannel(ulong ChannelId)
|
public async Task SendMessageToChannel(ulong ChannelId)
|
||||||
{
|
{
|
||||||
var channel = await _client.GetChannelAsync(ChannelId) as IMessageChannel;
|
var channel = _client.GetChannel(ChannelId) as ISocketMessageChannel;
|
||||||
await channel?.SendMessageAsync("aaaaaaaaahhh!!!")
|
await channel?.SendMessageAsync("aaaaaaaaahhh!!!")
|
||||||
/* ^ This question mark is used to indicate that 'channel' may sometimes be null, and in cases that it is null, we will do nothing here. */
|
/* ^ This question mark is used to indicate that 'channel' may sometimes be null, and in cases that it is null, we will do nothing here. */
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
[Module("admin")]
|
[Group("admin")]
|
||||||
public class AdminModule
|
public class AdminModule : ModuleBase
|
||||||
{
|
{
|
||||||
[Group("mod")]
|
[Group("mod")]
|
||||||
public class ModerationGroup
|
public class ModerationGroup : ModuleBase
|
||||||
{
|
{
|
||||||
// ~admin mod ban foxbot#0282
|
// ~admin mod ban foxbot#0282
|
||||||
[Command("ban")]
|
[Command("ban")]
|
||||||
public async Task Ban(IUserMessage msg, IGuildUser user) { }
|
public async Task Ban(IGuildUser user) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~admin clean 100
|
// ~admin clean 100
|
||||||
[Command("clean")]
|
[Command("clean")]
|
||||||
public async Task Clean(IUserMessage msg, int count = 100) { }
|
public async Task Clean(int count = 100) { }
|
||||||
}
|
}
|
||||||
@@ -1,29 +1,29 @@
|
|||||||
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
|
||||||
// Create a module with no prefix
|
// Create a module with no prefix
|
||||||
[Module]
|
public class Info : ModuleBase
|
||||||
public class Info
|
|
||||||
{
|
{
|
||||||
// ~say hello -> hello
|
// ~say hello -> hello
|
||||||
[Command("say"), Summary("Echos a message.")]
|
[Command("say"), Summary("Echos a message.")]
|
||||||
public async Task Say(IUserMessage msg,
|
public async Task Say([Unparsed, Summary("The text to echo")] string echo)
|
||||||
[Unparsed, Summary("The text to echo")] string echo)
|
|
||||||
{
|
{
|
||||||
await msg.Channel.SendMessageAsync(echo);
|
// ReplyAsync is a method on ModuleBase
|
||||||
|
await ReplyAsync(echo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a module with the 'sample' prefix
|
// Create a module with the 'sample' prefix
|
||||||
[Module("sample")]
|
[Group("sample")]
|
||||||
public class Sample
|
public class Sample : ModuleBase
|
||||||
{
|
{
|
||||||
// ~sample square 20 ->
|
// ~sample square 20 -> 400
|
||||||
[Command("square"), Summary("Squares a number.")]
|
[Command("square"), Summary("Squares a number.")]
|
||||||
public async Task Square(IUserMessage msg,
|
public async Task Square([Summary("The number to square.")] int num)
|
||||||
[Summary("The number to square.")] int num)
|
|
||||||
{
|
{
|
||||||
await msg.Channel.SendMessageAsync($"{num}^2 = {Math.Pow(num, 2)}");
|
// We can also access the channel from the Command Context.
|
||||||
|
await Context.Channel.SendMessageAsync($"{num}^2 = {Math.Pow(num, 2)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~sample userinfo --> foxbot#0282
|
// ~sample userinfo --> foxbot#0282
|
||||||
@@ -34,10 +34,9 @@ public class Sample
|
|||||||
// ~sample whois 96642168176807936 --> Khionu#8708
|
// ~sample whois 96642168176807936 --> Khionu#8708
|
||||||
[Command("userinfo"), Summary("Returns info about the current user, or the user parameter, if one passed.")]
|
[Command("userinfo"), Summary("Returns info about the current user, or the user parameter, if one passed.")]
|
||||||
[Alias("user", "whois")]
|
[Alias("user", "whois")]
|
||||||
public async Task UserInfo(IUserMessage msg,
|
public async Task UserInfo([Summary("The (optional) user to get info for")] IUser user = null)
|
||||||
[Summary("The (optional) user to get info for")] IUser user = null)
|
|
||||||
{
|
{
|
||||||
var userInfo = user ?? await Program.Client.GetCurrentUserAsync();
|
var userInfo = user ?? Context.Client.CurrentUser;
|
||||||
await msg.Channel.SendMessageAsync($"{userInfo.Username}#{userInfo.Discriminator}");
|
await ReplyAsync($"{userInfo.Username}#{userInfo.Discriminator}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
[Module]
|
public class InfoModule : ModuleBase
|
||||||
public class InfoModule
|
|
||||||
{
|
{
|
||||||
// Constrain this command to Guilds
|
// Constrain this command to Guilds
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Whois(IUserMessage msg, IGuildUser user) { }
|
public async Task Whois(IGuildUser user) { }
|
||||||
|
|
||||||
// Constrain this command to either Guilds or DMs
|
// Constrain this command to either Guilds or DMs
|
||||||
[RequireContext(ContextType.Guild | ContextType.DM)]
|
[RequireContext(ContextType.Guild | ContextType.DM)]
|
||||||
public async Task Info(IUserMessage msg) { }
|
public async Task Info() { }
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,18 @@
|
|||||||
// Defining the Precondition
|
// Defining the Precondition
|
||||||
|
|
||||||
// Specify that this precondition can target a Class (Module/Group) or Method (Command)
|
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
|
||||||
// Inherit from PreconditionAttribute
|
// Inherit from PreconditionAttribute
|
||||||
public class RequireOwnerAttribute : PreconditionAttribute
|
public class RequireOwnerAttribute : PreconditionAttribute
|
||||||
{
|
{
|
||||||
public readonly ulong OwnerId = 66078337084162048;
|
|
||||||
|
|
||||||
// Override the CheckPermissions method
|
// Override the CheckPermissions method
|
||||||
public override Task<PreconditionResult> CheckPermissions(IUserMessage context, Command executingCommand, object moduleInstance)
|
public override Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map)
|
||||||
{
|
{
|
||||||
// If the author of the message is '66078337084162048', return success; otherwise fail.
|
// Get the ID of the bot's owner
|
||||||
return Task.FromResult(context.Author.Id == OwnerId ? PreconditionResult.FromSuccess() : PreconditionResult.FromError("You must be the owner of the bot."));
|
var ownerId = (await map.Get<DiscordSocketClient>().GetApplicationInfoAsync()).Owner.Id;
|
||||||
|
// If this command was executed by that user, return a success
|
||||||
|
if (context.User.Id == ownerId)
|
||||||
|
return PreconditionResult.FromSuccess();
|
||||||
|
// Since it wasn't, fail
|
||||||
|
else
|
||||||
|
return PreconditionResult.FromError("You must be the owner of the bot to run this command.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
[Module]
|
public class AdminModule : ModuleBase
|
||||||
public class AdminModule
|
|
||||||
{
|
{
|
||||||
[Command("ban")]
|
[Command("ban")]
|
||||||
[RequirePermission(GuildPermission.BanMembers)]
|
[RequirePermission(GuildPermission.BanMembers)]
|
||||||
public async Task Ban(IUserMessage msg) { }
|
public async Task Ban(IGuildUser target) { }
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@ using Discord.Commands;
|
|||||||
|
|
||||||
public class BooleanTypeReader : TypeReader
|
public class BooleanTypeReader : TypeReader
|
||||||
{
|
{
|
||||||
public override Task<TypeReaderResult> Read(IUserMessage context, string input)
|
public override Task<TypeReaderResult> Read(CommandContext context, string input)
|
||||||
{
|
{
|
||||||
bool result;
|
bool result;
|
||||||
if (bool.TryParse(input, out result))
|
if (bool.TryParse(input, out result))
|
||||||
|
|||||||
@@ -9,17 +9,30 @@ title: Terminology
|
|||||||
|
|
||||||
Most terms for objects remain the same between 0.9 and 1.0. The major difference is that the ``Server`` is now called ``Guild``, to stay in line with Discord internally
|
Most terms for objects remain the same between 0.9 and 1.0. The major difference is that the ``Server`` is now called ``Guild``, to stay in line with Discord internally
|
||||||
|
|
||||||
## Introduction to Interfaces
|
## Implementation Specific Entities
|
||||||
|
|
||||||
Discord.Net 1.0 is built strictly around Interfaces. There are no methods that return a concrete object, only an interface.
|
Discord.Net 1.0 is split into a core library, and three different
|
||||||
|
implementations - Discord.Net.Core, Discord.Net.Rest, Discord.Net.Rpc,
|
||||||
|
and Discord.Net.WebSockets.
|
||||||
|
|
||||||
Many of the interfaces in Discord.Net are linked through inheritance. For example, @Discord.IChannel represents any channel in Discord. @Discord.IGuildChannel inherits from IChannel, and represents all channels belonging to a Guild. As a result, @Discord.IChannel can sometimes be cast to @Discord.IGuildChannel, and you may find yourself doing this frequently in order to properly utilize the library.
|
As a bot developer, you will only need to use Discord.Net.WebSockets,
|
||||||
|
but you should be aware of the differences between them.
|
||||||
|
|
||||||
### The Inheritance Tree
|
`Discord.Net.Core` provides a set of interfaces that model Discord's
|
||||||
|
API. These interfaces are consistent throughout all implementations of
|
||||||
|
Discord.Net, and if you are writing an implementation-agnostic library
|
||||||
|
or addon, you can rely on the core interfaces to ensure that your
|
||||||
|
addon will run on all platforms.
|
||||||
|
|
||||||
You may want to familiarize yourself with the inheritance in Discord.Net. An inheritance tree is provided below.
|
`Discord.Net.Rest` provides a set of concrete classes to be used
|
||||||
|
**strictly** with the REST portion of Discord's API. Entities in
|
||||||
|
this implementation are prefixed with `Rest`, e.g. `RestChannel`.
|
||||||
|
|
||||||

|
`Discord.Net.Rpc` provides a set of concrete classes that are used with
|
||||||

|
Discord's RPC API. Entities in this implementation are prefixed with
|
||||||

|
`Rpc`, e.g. `RpcChannel`.
|
||||||

|
|
||||||
|
`Discord.Net.WebSocket` provides a set of concrete classes that are used
|
||||||
|
primarily with Discord's WebSocket API, or entities that are kept in
|
||||||
|
cache. When developing bots, you will be using this implementation. All
|
||||||
|
entities are prefixed with `Socket`, e.g. `SocketChannel`.
|
||||||
@@ -5,11 +5,6 @@ changes in the design of the library.**
|
|||||||
|
|
||||||
>A medium to advanced understanding is recommended when working with this library.
|
>A medium to advanced understanding is recommended when working with this library.
|
||||||
|
|
||||||
One of the biggest major changes from `0.9.x` is the exclusive use of interfaces.
|
|
||||||
For the most part, your usability will be very similar to the 0.9 approach of concrete
|
|
||||||
classes. You **will** be required to cast some entities; this is outlined in a later
|
|
||||||
section.
|
|
||||||
|
|
||||||
It is recommended to familiarize yourself with the entities in 1.0 before continuing.
|
It is recommended to familiarize yourself with the entities in 1.0 before continuing.
|
||||||
Feel free to look through the library's source directly, look through IntelliSense, or
|
Feel free to look through the library's source directly, look through IntelliSense, or
|
||||||
look through our hosted [API Documentation](xref:Discord).
|
look through our hosted [API Documentation](xref:Discord).
|
||||||
@@ -19,8 +14,7 @@ look through our hosted [API Documentation](xref:Discord).
|
|||||||
Most API models function _similarly_ to 0.9, however their names have been changed.
|
Most API models function _similarly_ to 0.9, however their names have been changed.
|
||||||
You should also keep in mind that we now separate different types of Channels and Users.
|
You should also keep in mind that we now separate different types of Channels and Users.
|
||||||
|
|
||||||
Take a look at inheritance section of @Terminology for an example of how inheritance and interfaces
|
Before proceeding, please read over @Terminology to understand the naming behind some objects.
|
||||||
work in 1.0
|
|
||||||
|
|
||||||
Below is a table that compares most common 0.9 entities to their 1.0 counterparts.
|
Below is a table that compares most common 0.9 entities to their 1.0 counterparts.
|
||||||
|
|
||||||
@@ -29,18 +23,16 @@ Below is a table that compares most common 0.9 entities to their 1.0 counterpart
|
|||||||
|
|
||||||
| 0.9 | 1.0 | Notice |
|
| 0.9 | 1.0 | Notice |
|
||||||
| --- | --- | ------ |
|
| --- | --- | ------ |
|
||||||
| Server | @Discord.IGuild |
|
| Server | @Discord.WebSocket.SocketGuild |
|
||||||
| Channel | @Discord.IGuildChannel | Applies only to channels that are members of a Guild |
|
| Channel | @Discord.WebSocket.SocketGuildChannel | Applies only to channels that are members of a Guild |
|
||||||
| Channel.IsPrivate | @Discord.IDMChannel
|
| Channel.IsPrivate | @Discord.WebSocket.SocketDMChannel
|
||||||
| ChannelType.Text | @Discord.ITextChannel | This applies only to Text Channels in Guilds
|
| ChannelType.Text | @Discord.WebSocket.SocketTextChannel | This applies only to Text Channels in Guilds
|
||||||
| ChannelType.Voice | @Discord.IVoiceChannel | This applies only to Voice Channels in Guilds
|
| ChannelType.Voice | @Discord.WebSocket.SocketVoiceChannel | This applies only to Voice Channels in Guilds
|
||||||
| User | @Discord.IGuildUser | This applies only to users belonging to a Guild*
|
| User | @Discord.WebSocket.SocketGuildUser | This applies only to users belonging to a Guild*
|
||||||
| Profile | @Discord.ISelfUser
|
| Profile | @Discord.WebSocket.SocketGuildUser
|
||||||
| Message | @Discord.IUserMessage
|
| Message | @Discord.WebSocket.SocketUserMessage
|
||||||
|
|
||||||
\* To retrieve an @Discord.IGuildUser, you must retrieve the user from an @Discord.IGuild.
|
\* To retrieve an @Discord.WebSocket.SocketGuildUser, you must retrieve the user from an @Discord.WebSocket.SocketGuild.
|
||||||
[IDiscordClient.GetUserAsync](xref:Discord.IDiscordClient#Discord_IDiscordClient_GetUserAsync_System_UInt64_)
|
|
||||||
returns a @Discord.IUser, which only contains the information that Discord exposes for public users.
|
|
||||||
|
|
||||||
## Event Registration
|
## Event Registration
|
||||||
|
|
||||||
@@ -67,15 +59,3 @@ API docs before implementing it.
|
|||||||
## Async
|
## Async
|
||||||
|
|
||||||
Nearly everything in 1.0 is an async Task. You should always await any tasks you invoke.
|
Nearly everything in 1.0 is an async Task. You should always await any tasks you invoke.
|
||||||
|
|
||||||
However, when using WebSockets, you may find this both inconvienent, and unnecessary, as many of the
|
|
||||||
WebSocket implementations of the interfaces keep their own local cache of objects, rendering the use
|
|
||||||
of async redundant.
|
|
||||||
|
|
||||||
**As of right now,** there are extension methods you can use, located in `Discord.WebSocket` that will
|
|
||||||
provide java-esque, synchronus `GetXXX` methods to replace the asynchronus methods on WebSocket entities.
|
|
||||||
|
|
||||||
This functionality may be changed at a later date, we are currently reviewing this implementation and
|
|
||||||
alternative methods.
|
|
||||||
|
|
||||||
For your reference, you may want to look through the extension classes located in @Discord.WebSocket
|
|
||||||
|
|||||||
Reference in New Issue
Block a user