Bleeding edge builds are available using our MyGet feed (`https://www.myget.org/F/discord-net/api/v3/index.json`). These builds may break at any time - use with caution.
Nightly builds are available through our MyGet feed (`https://www.myget.org/F/discord-net/api/v3/index.json`).
## Compiling
## Compiling
In order to compile Discord.Net, you require the following:
In order to compile Discord.Net, you require the following:
### Using Visual Studio
### Using Visual Studio
- [Visual Studio 2017 RC](https://www.microsoft.com/net/core#windowsvs2017)
- [Visual Studio 2017 RC](https://www.microsoft.com/net/core#windowsvs2017)
.Net Core 1.1 does not support WebSockets on Win7 and earlier. Track the issue [here](https://github.com/dotnet/corefx/issues/9503).
.NET Core 1.1 does not support WebSockets on Win7 and earlier. It's recommended to use the Discord.Net.Providers.WS4Net package until this is resolved.
Track the issue [here](https://github.com/dotnet/corefx/issues/9503).
@@ -10,6 +10,6 @@ I don't really have any strict conditions for writing documentation, but just ke
### Compiling
### Compiling
Documentation is compiled into a static site using [DocFx](dotnet.github.io/docfx/). You **must** install a version of DocFx that supports .NET Core. The latest build of that is [2.1.0-cli-alpha](https://github.com/dotnet/docfx/releases/tag/v2.1.0-cli-alpha).
Documentation is compiled into a static site using [DocFx](https://dotnet.github.io/docfx/). We currently use version 2.8
After making changes, compile your changes into the static site with `docfx`. You can also view your changes live with `docfx --serve`.
After making changes, compile your changes into the static site with `docfx`. You can also view your changes live with `docfx --serve`.
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_).
@@ -17,7 +17,7 @@ To hook into events, you must be using the @Discord.WebSocket.DiscordSocketClien
Connection Events will be raised when the Connection State of your client changes.
Connection Events will be raised when the Connection State of your client changes.
[DiscordSocketClient.Connected](xref:Discord.WebSocket.DiscordSocketClient#Discord_WebSocket_DiscordSocketClient_Connected) and [Disconnected](Discord_WebSocket_DiscordSocketClient_Disconnected) are raised when the Gateway Socket connects or disconnects, respectively.
[DiscordSocketClient.Connected](xref:Discord.WebSocket.DiscordSocketClient#Discord_WebSocket_DiscordSocketClient_Connected) and [Disconnected](xref:Discord.WebSocket.DiscordSocketClient#Discord_WebSocket_DiscordSocketClient_Disconnected) are raised when the Gateway Socket connects or disconnects, respectively.
>[!WARNING]
>[!WARNING]
>You should not use DiscordClient.Connected to run code when your client first connects to Discord. The client has not received and parsed the READY event and guild stream yet, and will have an incomplete or empty cache.
>You should not use DiscordClient.Connected to run code when your client first connects to Discord. The client has not received and parsed the READY event and guild stream yet, and will have an incomplete or empty cache.
@@ -23,11 +23,19 @@ You may add the MyGet feed to Visual Studio directly from `https://www.myget.org
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).
>[!WARNING]
>[!WARNING]
>The versions of Discord.Net on NuGet are behind the versions this documentation is written for.
>The versions of Discord.Net on NuGet are behind the versions this
>documentation is written for.
>You MUST install from MyGet or Source!
## Async
## Async
Discord.Net uses C# tasks extensiely - nearly all operations return one. It is highly reccomended these tasks be awaited whenever possible. To do so requires the calling method to be marked as async, which can be problematic in a console application. An example of how to get around this is provided below.
Discord.Net uses C# tasks extensiely - nearly all operations return
one.
It is highly reccomended these tasks be awaited whenever possible.
To do so requires the calling method to be marked as async, which
can be problematic in a console application. An example of how to
get around this is provided below.
For more information, go to [MSDN's Async-Await section.](https://msdn.microsoft.com/en-us/library/hh191443.aspx)
For more information, go to [MSDN's Async-Await section.](https://msdn.microsoft.com/en-us/library/hh191443.aspx)
@@ -37,4 +45,6 @@ For more information, go to [MSDN's Async-Await section.](https://msdn.microsoft
>[!NOTE]
>[!NOTE]
>In previous versions of Discord.Net, you had to hook into the `Ready` and `GuildAvailable` events to determine when your client was ready for use.
>In previous versions of Discord.Net, you had to hook into the `Ready` and `GuildAvailable` events to determine when your client was ready for use.
>In 1.0, the [ConnectAsync](xref:Discord.DiscordSocketClient#ConnectAsync) method will automatically wait for the Ready event, and for all guilds to stream. To avoid this, pass `false` into `ConnectAsync`.
>In 1.0, the [ConnectAsync] method will automatically wait for the Ready event, and for all guilds to stream. To avoid this, pass `false` into `ConnectAsync`.
// Create an IAudioClient, and store it for later use
private IAudioClient _audio;
// Create a Join command, that will join the parameter or the user's current voice channel
[Command("join")]
[Command("join")]
public async Task JoinChannel(IUserMessage msg,
IVoiceChannel channel = null)
public async Task JoinChannel(IVoiceChannel channel = null)
{
{
// Get the audio channel
// Get the audio channel
channel = channel ?? (msg.Author as IGuildUser)?.VoiceChannel;
channel = channel ?? (msg.Author as IGuildUser)?.VoiceChannel;
if (channel == null) { await msg.Channel.SendMessageAsync("User must be in a voice channel, or a voice channel must be passed as an argument."); return; }
if (channel == null) { await msg.Channel.SendMessageAsync("User must be in a voice channel, or a voice channel must be passed as an argument."); return; }
// Get the IAudioClient by calling the JoinAsync method
_audio = await channel.JoinAsync();
// For the next step with transmitting audio, you would want to pass this Audio Client in to a service.
To use Audio, you must first configure your `DiscordSocketClient` with Audio support.
To use Audio, you must first configure your [DiscordSocketClient]
with Audio support.
In your @Discord.DiscordSocketConfig, set `AudioMode` to the appropriate @Discord.Audio.AudioMode for your bot. For most bots, you will only need to use `AudioMode.Outgoing`.
In your [DiscordSocketConfig], set `AudioMode` to the appropriate
[AudioMode] for your bot. For most bots, you will only need to use
Audio requires two native libraries, `libsodium` and `opus`. Both of these libraries must be placed in the runtime directory of your bot (for .NET 4.6, the directory where your exe is located; for .NET core, directory where your project.json is located)
Audio requires two native libraries, `libsodium` and `opus`.
Both of these libraries must be placed in the runtime directory of your
bot. (When developing on .NET Framework, this would be `bin/debug`,
when developing on .NET Core, this is where you execute `dotnet run`
from; typically the same directory as your csproj).
For Windows Users, precompiled binaries are available for your
For Windows Users, precompiled binaries are available for your convienence [here](https://discord.foxbot.me/binaries/)
For Linux Users, you will need to compile [Sodium] and [Opus] from
source, or install them from your package manager.
For Linux Users, you will need to compile from source. [Sodium Source Code](https://download.libsodium.org/libsodium/releases/), [Opus Source Code](http://downloads.xiph.org/releases/opus/).
Joining Voice Channels is relatively straight-forward, and is a requirement for sending or receiving audio. This will also allow us to create an @Discord.Audio.IAudioClient, which will be used later to send or receive audio.
Joining a channel is the first step to sending audio, and will return
an [IAudioClient] to send data with.
To join a channel, simply await [ConnectAsync] on any instance of an
@Discord.IVoiceChannel.
[!code-csharp[Joining a Channel](samples/joining_audio.cs)]
[!code-csharp[Joining a Channel](samples/joining_audio.cs)]
The client will sustain a connection to this channel until it is kicked, disconnected from Discord, or told to disconnect.
The client will sustain a connection to this channel until it is
kicked, disconnected from Discord, or told to disconnect.
It should be noted that voice connections are created on a per-guild
basis; only one audio connection may be open by the bot in a single
guild. To switch channels within a guild, invoke [ConnectAsync] on
Refer to [Guides](guides/intro.md) for tutorials on using Discord.Net, or the [API documentation](api/index.md) to review individual objects in the library.
Discord.Net is an asynchronous, multiplatform .NET Library used to interface with the [Discord API](https://discordapp.com/).
**Todo:** Put something meaningful here.
If this is your first time using Discord.Net, you should refer to the [Intro](guides/intro.md) for tutorials.
More experienced users might refer to the [API Documentation](api/index.md) for a breakdown of the individuals objects in the library.
For additional resources:
- [Discord API Guild](https://discord.gg/discord-api) - Look for `#dotnet_discord-net`
public class RequireBotPermissionAttribute : PreconditionAttribute
{
public GuildPermission? GuildPermission { get; }
public ChannelPermission? ChannelPermission { get; }
/// <summary>
/// Require that the bot account has a specified GuildPermission
/// </summary>
/// <remarks>This precondition will always fail if the command is being invoked in a private channel.</remarks>
/// <param name="permission">The GuildPermission that the bot must have. Multiple permissions can be specified by ORing the permissions together.</param>
public RequireBotPermissionAttribute(GuildPermission permission)
{
GuildPermission = permission;
ChannelPermission = null;
}
/// <summary>
/// Require that the bot account has a specified ChannelPermission.
/// </summary>
/// <param name="permission">The ChannelPermission that the bot must have. Multiple permissions can be specified by ORing the permissions together.</param>
public class RequireContextAttribute : PreconditionAttribute
public class RequireContextAttribute : PreconditionAttribute
{
{
public ContextType Contexts { get; }
public ContextType Contexts { get; }
/// <summary>
/// Require that the command be invoked in a specified context.
/// </summary>
/// <param name="contexts">The type of context the command can be invoked in. Multiple contexts can be specified by ORing the contexts together.</param>
public class RequirePermissionAttribute : PreconditionAttribute
public class RequireUserPermissionAttribute : PreconditionAttribute
{
{
public GuildPermission? GuildPermission { get; }
public GuildPermission? GuildPermission { get; }
public ChannelPermission? ChannelPermission { get; }
public ChannelPermission? ChannelPermission { get; }
public RequirePermissionAttribute(GuildPermission permission)
/// <summary>
/// Require that the user invoking the command has a specified GuildPermission
/// </summary>
/// <remarks>This precondition will always fail if the command is being invoked in a private channel.</remarks>
/// <param name="permission">The GuildPermission that the user must have. Multiple permissions can be specified by ORing the permissions together.</param>
public RequireUserPermissionAttribute(GuildPermission permission)
{
{
GuildPermission = permission;
GuildPermission = permission;
ChannelPermission = null;
ChannelPermission = null;
}
}
public RequirePermissionAttribute(ChannelPermission permission)
/// <summary>
/// Require that the user invoking the command has a specified ChannelPermission.
/// </summary>
/// <param name="permission">The ChannelPermission that the user must have. Multiple permissions can be specified by ORing the permissions together.</param>
public override async Task<TypeReaderResult> Read(CommandContext context, string input)
public override async Task<TypeReaderResult> Read(ICommandContext context, string input)
{
{
var results = new Dictionary<ulong, TypeReaderValue>();
var results = new Dictionary<ulong, TypeReaderValue>();
IReadOnlyCollection<IUser> channelUsers = (await context.Channel.GetUsersAsync(CacheMode.CacheOnly).Flatten().ConfigureAwait(false)).ToArray(); //TODO: must be a better way?
IReadOnlyCollection<IUser> channelUsers = (await context.Channel.GetUsersAsync(CacheMode.CacheOnly).Flatten().ConfigureAwait(false)).ToArray(); //TODO: must be a better way?
@@ -46,13 +46,13 @@ namespace Discord.Commands
ushort discriminator;
ushort discriminator;
if (ushort.TryParse(input.Substring(index + 1), out discriminator))
if (ushort.TryParse(input.Substring(index + 1), out discriminator))
{
{
var channelUser = channelUsers.Where(x => x.DiscriminatorValue == discriminator &&
/// Creates a new outgoing stream accepting Opus-encoded data.
/// </summary>
/// <param name="samplesPerFrame">Samples per frame. Must be 120, 240, 480, 960, 1920 or 2880, representing 2.5, 5, 10, 20, 40 or 60 milliseconds respectively.</param>
/// <returns></returns>
AudioOutStream CreateOpusStream(int samplesPerFrame, int bufferMillis = 1000);
/// <summary>
/// Creates a new outgoing stream accepting Opus-encoded data. This is a direct stream with no internal timer.
/// </summary>
/// <param name="samplesPerFrame">Samples per frame. Must be 120, 240, 480, 960, 1920 or 2880, representing 2.5, 5, 10, 20, 40 or 60 milliseconds respectively.</param>
/// Creates a new outgoing stream accepting PCM (raw) data.
/// </summary>
/// <param name="samplesPerFrame">Samples per frame. Must be 120, 240, 480, 960, 1920 or 2880, representing 2.5, 5, 10, 20, 40 or 60 milliseconds respectively.</param>
/// <param name="bitrate"></param>
/// <returns></returns>
AudioOutStream CreatePCMStream(AudioApplication application, int samplesPerFrame, int channels = 2, int? bitrate = null, int bufferMillis = 1000);
/// <summary>
/// Creates a new direct outgoing stream accepting PCM (raw) data. This is a direct stream with no internal timer.
/// </summary>
/// <param name="samplesPerFrame">Samples per frame. Must be 120, 240, 480, 960, 1920 or 2880, representing 2.5, 5, 10, 20, 40 or 60 milliseconds respectively.</param>
/// <param name="bitrate"></param>
/// <returns></returns>
AudioOutStream CreateDirectPCMStream(AudioApplication application, int samplesPerFrame, int channels = 2, int? bitrate = null);
Thank you for your continuous support to the Openl Qizhi Community AI Collaboration Platform. In order to protect your usage rights and ensure network security, we updated the Openl Qizhi Community AI Collaboration Platform Usage Agreement in January 2024. The updated agreement specifies that users are prohibited from using intranet penetration tools. After you click "Agree and continue", you can continue to use our services. Thank you for your cooperation and understanding.