Browse Source

Add/migrate code examples

pull/1304/head
Still Hsu 6 years ago
parent
commit
456ee4b150
18 changed files with 432 additions and 212 deletions
  1. +18
    -1
      Discord.Net.sln
  2. +4
    -6
      src/Discord.Net.Core/Entities/Channels/IGuildChannel.cs
  3. +25
    -38
      src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs
  4. +1
    -1
      src/Discord.Net.Core/Entities/Channels/ITextChannel.cs
  5. +2
    -10
      src/Discord.Net.Core/Entities/Guilds/IGuild.cs
  6. +4
    -3
      src/Discord.Net.Core/Entities/Users/IUser.cs
  7. +4
    -4
      src/Discord.Net.Core/IDiscordClient.cs
  8. +39
    -24
      src/Discord.Net.Examples/Core/Entities/Channels/IGuildChannel.Examples.cs
  9. +114
    -0
      src/Discord.Net.Examples/Core/Entities/Channels/IMessageChannel.Examples.cs
  10. +25
    -0
      src/Discord.Net.Examples/Core/Entities/Guilds/IGuild.Examples.cs
  11. +33
    -17
      src/Discord.Net.Examples/Core/Entities/Users/IUser.Examples.cs
  12. +21
    -0
      src/Discord.Net.Examples/Discord.Net.Examples.csproj
  13. +110
    -83
      src/Discord.Net.Examples/WebSocket/BaseSocketClient.Events.Examples.cs
  14. +1
    -1
      src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
  15. +13
    -7
      src/Discord.Net.WebSocket/BaseSocketClient.Events.cs
  16. +14
    -14
      src/Discord.Net.WebSocket/BaseSocketClient.cs
  17. +3
    -2
      src/Discord.Net.WebSocket/DiscordSocketConfig.cs
  18. +1
    -1
      src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs

+ 18
- 1
Discord.Net.sln View File

@@ -30,7 +30,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01_basic_ping_bot", "sample
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02_commands_framework", "samples\02_commands_framework\02_commands_framework.csproj", "{4E1F1F40-B1DD-40C9-A4B1-A2046A4C9C76}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "03_sharded_client", "samples\03_sharded_client\03_sharded_client.csproj", "{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03_sharded_client", "samples\03_sharded_client\03_sharded_client.csproj", "{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{D1F0271E-0EE2-4B66-AC3D-9871B7E1C4CF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Examples", "src\Discord.Net.Examples\Discord.Net.Examples.csproj", "{7EA96B2B-4D71-458D-9423-839362DC38BE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -174,6 +178,18 @@ Global
{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}.Release|x64.Build.0 = Release|Any CPU
{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}.Release|x86.ActiveCfg = Release|Any CPU
{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}.Release|x86.Build.0 = Release|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Debug|x64.ActiveCfg = Debug|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Debug|x64.Build.0 = Debug|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Debug|x86.ActiveCfg = Debug|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Debug|x86.Build.0 = Debug|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Release|Any CPU.Build.0 = Release|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Release|x64.ActiveCfg = Release|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Release|x64.Build.0 = Release|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Release|x86.ActiveCfg = Release|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -188,6 +204,7 @@ Global
{F2FF84FB-F6AD-47E5-9EE5-18206CAE136E} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
{4E1F1F40-B1DD-40C9-A4B1-A2046A4C9C76} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
{7EA96B2B-4D71-458D-9423-839362DC38BE} = {D1F0271E-0EE2-4B66-AC3D-9871B7E1C4CF}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D2404771-EEC8-45F2-9D71-F3373F6C1495}


+ 4
- 6
src/Discord.Net.Core/Entities/Channels/IGuildChannel.cs View File

@@ -101,9 +101,8 @@ namespace Discord
/// <see cref="IGuild.GetChannelAsync"/>. Next, it checks if an overwrite had already been set via
/// <see cref="GetPermissionOverwrite(Discord.IRole)"/>; if not, it denies the role from sending any
/// messages to the channel.
/// <code lang="cs"
/// source="../Discord.Net.Examples/Core/Entities/Channels/IGuildChannel.Examples.cs"
/// region="AddPermissionOverwriteAsyncRole"/>
/// <code language="cs" region="AddPermissionOverwriteAsyncRole"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Channels\IGuildChannel.Examples.cs"/>
/// </example>
/// <param name="role">The role to add the overwrite to.</param>
/// <param name="permissions">The overwrite to add to the role.</param>
@@ -121,9 +120,8 @@ namespace Discord
/// <see cref="IGuild.GetChannelAsync"/>. Next, it checks if an overwrite had already been set via
/// <see cref="GetPermissionOverwrite(Discord.IUser)"/>; if not, it denies the user from sending any
/// messages to the channel.
/// <code lang="cs"
/// source="../Discord.Net.Examples/Core/Entities/Channels/IGuildChannel.Examples.cs"
/// region="AddPermissionOverwriteAsyncUser"/>
/// <code language="cs" region="AddPermissionOverwriteAsyncUser"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Channels\IGuildChannel.Examples.cs"/>
/// </example>
/// <param name="user">The user to add the overwrite to.</param>
/// <param name="permissions">The overwrite to add to the user.</param>


+ 25
- 38
src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs View File

@@ -16,11 +16,8 @@ namespace Discord
/// <example>
/// The following example sends a message with the current system time in RFC 1123 format to the channel and
/// deletes itself after 5 seconds.
/// <code language="cs">
/// var message = await channel.SendMessageAsync(DateTimeOffset.UtcNow.ToString("R"));
/// await Task.Delay(TimeSpan.FromSeconds(5))
/// .ContinueWith(x => message.DeleteAsync());
/// </code>
/// <code language="cs" region="SendMessageAsync"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Channels\IMessageChannel.Examples.cs" />
/// </example>
/// <param name="text">The message to be sent.</param>
/// <param name="isTTS">Determines whether the message should be read aloud by Discord or not.</param>
@@ -35,18 +32,14 @@ namespace Discord
/// Sends a file to this message channel with an optional caption.
/// </summary>
/// <example>
/// The following example uploads a local file called <c>wumpus.txt</c> along with the text
/// <c>good discord boi</c> to the channel.
/// <code language="cs">
/// await channel.SendFileAsync("wumpus.txt", "good discord boi");
/// </code>
///
/// The following example uploads a local image called <c>b1nzy.jpg</c> embedded inside a rich embed to the
/// channel.
/// <code language="cs">
/// await channel.SendFileAsync("b1nzy.jpg",
/// embed: new EmbedBuilder {ImageUrl = "attachment://b1nzy.jpg"}.Build());
/// </code>
/// <para>The following example uploads a local file called <c>wumpus.txt</c> along with the text
/// <c>good discord boi</c> to the channel.</para>
/// <code language="cs" region="SendFileAsync.FilePath"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Channels\IMessageChannel.Examples.cs" />
/// <para>The following example uploads a local image called <c>b1nzy.jpg</c> embedded inside a rich embed to the
/// channel.</para>
/// <code language="cs" region="SendFileAsync.FilePath.EmbeddedImage"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Channels\IMessageChannel.Examples.cs" />
/// </example>
/// <remarks>
/// This method sends a file as if you are uploading an attachment directly from your Discord client.
@@ -72,10 +65,8 @@ namespace Discord
/// <example>
/// The following example uploads a streamed image that will be called <c>b1nzy.jpg</c> embedded inside a
/// rich embed to the channel.
/// <code language="cs">
/// await channel.SendFileAsync(b1nzyStream, "b1nzy.jpg",
/// embed: new EmbedBuilder {ImageUrl = "attachment://b1nzy.jpg"}.Build());
/// </code>
/// <code language="cs" region="SendFileAsync.FileStream.EmbeddedImage"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Channels\IMessageChannel.Examples.cs" />
/// </example>
/// <remarks>
/// This method sends a file as if you are uploading an attachment directly from your Discord client.
@@ -132,10 +123,8 @@ namespace Discord
/// <example>
/// The following example downloads 300 messages and gets messages that belong to the user
/// <c>53905483156684800</c>.
/// <code lang="cs">
/// var messages = await messageChannel.GetMessagesAsync(300).FlattenAsync();
/// var userMessages = messages.Where(x =&gt; x.Author.Id == 53905483156684800);
/// </code>
/// <code language="cs" region="GetMessagesAsync.FromLimit.Standard"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Channels\IMessageChannel.Examples.cs" />
/// </example>
/// <param name="limit">The numbers of message to be gotten from.</param>
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from
@@ -168,10 +157,13 @@ namespace Discord
/// of flattening.
/// </remarks>
/// <example>
/// The following example gets 5 message prior to the message identifier <c>442012544660537354</c>.
/// <code lang="cs">
/// var messages = await channel.GetMessagesAsync(442012544660537354, Direction.Before, 5).FlattenAsync();
/// </code>
/// <para>The following example gets 5 message prior to the message identifier <c>442012544660537354</c>.</para>
/// <code language="cs" region="GetMessagesAsync.FromId.FromMessage"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Channels\IMessageChannel.Examples.cs" />
/// <para>The following example attempts to retrieve <c>messageCount</c> number of messages from the
/// beginning of the channel and prints them to the console.</para>
/// <code language="cs" region="GetMessagesAsync.FromId.BeginningMessages"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Channels\IMessageChannel.Examples.cs" />
/// </example>
/// <param name="fromMessageId">The ID of the starting message to get the messages from.</param>
/// <param name="dir">The direction of the messages to be gotten from.</param>
@@ -207,9 +199,8 @@ namespace Discord
/// </remarks>
/// <example>
/// The following example gets 5 message prior to a specific message, <c>oldMessage</c>.
/// <code lang="cs">
/// var messages = await channel.GetMessagesAsync(oldMessage, Direction.Before, 5).FlattenAsync();
/// </code>
/// <code language="cs" region="GetMessagesAsync.FromMessage"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Channels\IMessageChannel.Examples.cs" />
/// </example>
/// <param name="fromMessage">The starting message to get the messages from.</param>
/// <param name="dir">The direction of the messages to be gotten from.</param>
@@ -263,12 +254,8 @@ namespace Discord
/// </summary>
/// <example>
/// The following example keeps the client in the typing state until <c>LongRunningAsync</c> has finished.
/// <code lang="cs">
/// using (messageChannel.EnterTypingState())
/// {
/// await LongRunningAsync();
/// }
/// </code>
/// <code language="cs" region="EnterTypingState"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Channels\IMessageChannel.Examples.cs" />
/// </example>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>


+ 1
- 1
src/Discord.Net.Core/Entities/Channels/ITextChannel.cs View File

@@ -40,7 +40,7 @@ namespace Discord
/// </summary>
/// <example>
/// The following example gets 250 messages from the channel and deletes them.
/// <code lang="cs">
/// <code language="cs">
/// var messages = await textChannel.GetMessagesAsync(250).FlattenAsync();
/// await textChannel.DeleteMessagesAsync(messages);
/// </code>


+ 2
- 10
src/Discord.Net.Core/Entities/Guilds/IGuild.cs View File

@@ -440,16 +440,8 @@ namespace Discord
/// </summary>
/// <example>
/// The following example creates a new text channel under an existing category named <c>Wumpus</c> with a set topic.
/// <code lang="cs">
/// var categories = await guild.GetCategoriesAsync();
/// var targetCategory = categories.FirstOrDefault(x => x.Name == "wumpus");
/// if (targetCategory == null) return;
/// await Context.Guild.CreateTextChannelAsync(name, x =>
/// {
/// x.CategoryId = targetCategory.Id;
/// x.Topic = $"This channel was created at {DateTimeOffset.UtcNow} by {user}.";
/// });
/// </code>
/// <code language="cs" region="CreateTextChannelAsync"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Guilds\IGuild.Examples.cs"/>
/// </example>
/// <param name="name">The new name for the text channel.</param>
/// <param name="func">The delegate containing the properties to be applied to the channel upon its creation.</param>


+ 4
- 3
src/Discord.Net.Core/Entities/Users/IUser.cs View File

@@ -23,7 +23,8 @@ namespace Discord
/// <example>
/// The following example attempts to retrieve the user's current avatar and send it to a channel; if one is
/// not set, a default avatar for this user will be returned instead.
/// <code source="../Discord.Net.Examples/Core/Entities/Users/IUser.Examples.cs" region="GetAvatarUrl"/>
/// <code language="cs" region="GetAvatarUrl"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Users\IUser.Examples.cs"/>
/// </example>
/// <param name="format">The format to return.</param>
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.
@@ -91,8 +92,8 @@ namespace Discord
/// <example>
/// The following example attempts to send a direct message to the target user and logs the incident should
/// it fail.
/// <code source="../Discord.Net.Examples/Core/Entities/Users/IUser.Examples.cs"
/// region="GetOrCreateDMChannelAsync"/>
/// <code region="GetOrCreateDMChannelAsync" language="cs"
/// source="../../../Discord.Net.Examples/Core/Entities/Users/IUser.Examples.cs"/>
/// </example>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>


+ 4
- 4
src/Discord.Net.Core/IDiscordClient.cs View File

@@ -63,7 +63,7 @@ namespace Discord
/// Gets a generic channel.
/// </summary>
/// <example>
/// <code lang="cs" title="Example method">
/// <code language="cs" title="Example method">
/// var channel = await _client.GetChannelAsync(381889909113225237);
/// if (channel != null &amp;&amp; channel is IMessageChannel msgChannel)
/// {
@@ -194,7 +194,7 @@ namespace Discord
/// Gets a user.
/// </summary>
/// <example>
/// <code lang="cs" title="Example method">
/// <code language="cs" title="Example method">
/// var user = await _client.GetUserAsync(168693960628371456);
/// if (user != null)
/// Console.WriteLine($"{user} is created at {user.CreatedAt}.";
@@ -212,7 +212,7 @@ namespace Discord
/// Gets a user.
/// </summary>
/// <example>
/// <code lang="cs" title="Example method">
/// <code language="cs" title="Example method">
/// var user = await _client.GetUserAsync("Still", "2876");
/// if (user != null)
/// Console.WriteLine($"{user} is created at {user.CreatedAt}.";
@@ -232,7 +232,7 @@ namespace Discord
/// </summary>
/// <example>
/// The following example gets the most optimal voice region from the collection.
/// <code lang="cs">
/// <code language="cs">
/// var regions = await client.GetVoiceRegionsAsync();
/// var optimalRegion = regions.FirstOrDefault(x =&gt; x.IsOptimal);
/// </code>


+ 39
- 24
src/Discord.Net.Examples/Core/Entities/Channels/IGuildChannel.Examples.cs View File

@@ -1,31 +1,46 @@
#region AddPermissionOverwriteAsyncRole
public async Task MuteRoleAsync(IRole role, IGuildChannel channel)
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;

namespace Discord.Net.Examples.Core.Entities.Channels
{
if (role == null) throw new ArgumentNullException(nameof(role));
if (channel == null) throw new ArgumentNullException(nameof(channel));
[PublicAPI]
internal class GuildChannelExamples
{
#region AddPermissionOverwriteAsyncRole

// Fetches the previous overwrite and bail if one is found
var previousOverwrite = channel.GetPermissionOverwrite(role);
if (previousOverwrite.HasValue && previousOverwrite.Value.SendMessages == PermValue.Deny)
throw new InvalidOperationException($"Role {role.Name} had already been muted in this channel.");
public async Task MuteRoleAsync(IRole role, IGuildChannel channel)
{
if (role == null) throw new ArgumentNullException(nameof(role));
if (channel == null) throw new ArgumentNullException(nameof(channel));

// Creates a new OverwritePermissions with send message set to deny and pass it into the method
await channel.AddPermissionOverwriteAsync(role, new OverwritePermissions(sendMessages: PermValue.Deny));
}
#endregion
// Fetches the previous overwrite and bail if one is found
var previousOverwrite = channel.GetPermissionOverwrite(role);
if (previousOverwrite.HasValue && previousOverwrite.Value.SendMessages == PermValue.Deny)
throw new InvalidOperationException($"Role {role.Name} had already been muted in this channel.");

#region AddPermissionOverwriteAsyncUser
public async Task MuteUserAsync(IGuildUser user, IGuildChannel channel)
{
if (role == null) throw new ArgumentNullException(nameof(user));
if (channel == null) throw new ArgumentNullException(nameof(channel));
// Creates a new OverwritePermissions with send message set to deny and pass it into the method
await channel.AddPermissionOverwriteAsync(role, new OverwritePermissions(sendMessages: PermValue.Deny));
}

#endregion

#region AddPermissionOverwriteAsyncUser

public async Task MuteUserAsync(IGuildUser user, IGuildChannel channel)
{
if (user == null) throw new ArgumentNullException(nameof(user));
if (channel == null) throw new ArgumentNullException(nameof(channel));

// Fetches the previous overwrite and bail if one is found
var previousOverwrite = channel.GetPermissionOverwrite(user);
if (previousOverwrite.HasValue && previousOverwrite.Value.SendMessages == PermValue.Deny)
throw new InvalidOperationException($"User {user.Username} had already been muted in this channel.");

// Fetches the previous overwrite and bail if one is found
var previousOverwrite = channel.GetPermissionOverwrite(user);
if (previousOverwrite.HasValue && previousOverwrite.Value.SendMessages == PermValue.Deny)
throw new InvalidOperationException($"User {user.Name} had already been muted in this channel.");
// Creates a new OverwritePermissions with send message set to deny and pass it into the method
await channel.AddPermissionOverwriteAsync(user, new OverwritePermissions(sendMessages: PermValue.Deny));
}

// Creates a new OverwritePermissions with send message set to deny and pass it into the method
await channel.AddPermissionOverwriteAsync(user, new OverwritePermissions(sendMessages: PermValue.Deny));
#endregion
}
}
#endregion

+ 114
- 0
src/Discord.Net.Examples/Core/Entities/Channels/IMessageChannel.Examples.cs View File

@@ -0,0 +1,114 @@
using System;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using JetBrains.Annotations;

namespace Discord.Net.Examples.Core.Entities.Channels
{
[PublicAPI]
internal class MessageChannelExamples
{
#region GetMessagesAsync.FromId.BeginningMessages

public async Task PrintFirstMessages(IMessageChannel channel, int messageCount)
{
// Although the library does attempt to divide the messageCount by 100
// to comply to Discord's maximum message limit per request, sending
// too many could still cause the queue to clog up.
// The purpose of this exception is to discourage users from sending
// too many requests at once.
if (messageCount > 1000)
throw new InvalidOperationException("Too many messages requested.");

// Setting fromMessageId to 0 will make Discord
// default to the first message in channel.
var messages = await channel.GetMessagesAsync(
0, Direction.After, messageCount)
.FlattenAsync();

// Print message content
foreach (var message in messages)
Console.WriteLine($"{message.Author} posted '{message.Content}' at {message.CreatedAt}.");
}

#endregion

public async Task GetMessagesExampleBody(IMessageChannel channel)
{
#pragma warning disable IDISP001
#pragma warning disable IDISP014
// We're just declaring this for the sample below.
// Ideally, you want to get or create your HttpClient
// from IHttpClientFactory.
// You get a bonus for reading the example source though!
var httpClient = new HttpClient();
#pragma warning restore IDISP014
#pragma warning restore IDISP001

// Another dummy method
Task LongRunningAsync()
{
return Task.Delay(0);
}

#region GetMessagesAsync.FromLimit.Standard

var messages = await channel.GetMessagesAsync(300).FlattenAsync();
var userMessages = messages.Where(x => x.Author.Id == 53905483156684800);

#endregion

#region GetMessagesAsync.FromMessage

var oldMessage = await channel.SendMessageAsync("boi");
var messagesFromMsg = await channel.GetMessagesAsync(oldMessage, Direction.Before, 5).FlattenAsync();

#endregion


#region GetMessagesAsync.FromId.FromMessage

await channel.GetMessagesAsync(442012544660537354, Direction.Before, 5).FlattenAsync();

#endregion

#region SendMessageAsync

var message = await channel.SendMessageAsync(DateTimeOffset.UtcNow.ToString("R"));
await Task.Delay(TimeSpan.FromSeconds(5))
.ContinueWith(x => message.DeleteAsync());

#endregion

#region SendFileAsync.FilePath

await channel.SendFileAsync("wumpus.txt", "good discord boi");

#endregion

#region SendFileAsync.FilePath.EmbeddedImage

await channel.SendFileAsync("b1nzy.jpg",
embed: new EmbedBuilder {ImageUrl = "attachment://b1nzy.jpg"}.Build());

#endregion


#region SendFileAsync.FileStream.EmbeddedImage

using (var b1nzyStream = await httpClient.GetStreamAsync("https://example.com/b1nzy"))
await channel.SendFileAsync(b1nzyStream, "b1nzy.jpg",
embed: new EmbedBuilder {ImageUrl = "attachment://b1nzy.jpg"}.Build());

#endregion

#region EnterTypingState

using (channel.EnterTypingState()) await LongRunningAsync();

#endregion

}
}
}

+ 25
- 0
src/Discord.Net.Examples/Core/Entities/Guilds/IGuild.Examples.cs View File

@@ -0,0 +1,25 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;

namespace Discord.Net.Examples.Core.Entities.Guilds
{
[PublicAPI]
internal class GuildExamples
{
#region CreateTextChannelAsync
public async Task CreateTextChannelUnderWumpus(IGuild guild, string name)
{
var categories = await guild.GetCategoriesAsync();
var targetCategory = categories.FirstOrDefault(x => x.Name == "wumpus");
if (targetCategory == null) return;
await guild.CreateTextChannelAsync(name, x =>
{
x.CategoryId = targetCategory.Id;
x.Topic = $"This channel was created at {DateTimeOffset.UtcNow}.";
});
}
#endregion
}
}

+ 33
- 17
src/Discord.Net.Examples/Core/Entities/Users/IUser.Examples.cs View File

@@ -1,22 +1,38 @@
#region GetAvatarUrl
public async Task GetAvatarAsync(IUser user)
{
var userAvatarUrl = user.GetAvatarUrl() ?? user.GetDefaultAvatarUrl();
await textChannel.SendMessageAsync(userAvatarUrl);
}
#endregion
using System;
using System.Net;
using System.Threading.Tasks;
using JetBrains.Annotations;

#region GetOrCreateDMChannelAsync
public async Task MessageUserAsync(IUser user)
namespace Discord.Net.Examples.Core.Entities.Users
{
var channel = await user.GetOrCreateDMChannelAsync();
try
[PublicAPI]
internal class UserExamples
{
await channel.SendMessageAsync("Awesome stuff!");
}
catch (Discord.Net.HttpException ex) when (ex.HttpCode == 403)
{
Console.WriteLine($"Boo, I cannot message {user}");
#region GetAvatarUrl

public async Task GetAvatarAsync(IUser user, ITextChannel textChannel)
{
var userAvatarUrl = user.GetAvatarUrl() ?? user.GetDefaultAvatarUrl();
await textChannel.SendMessageAsync(userAvatarUrl);
}

#endregion

#region GetOrCreateDMChannelAsync

public async Task MessageUserAsync(IUser user)
{
var channel = await user.GetOrCreateDMChannelAsync();
try
{
await channel.SendMessageAsync("Awesome stuff!");
}
catch (Discord.Net.HttpException ex) when (ex.HttpCode == HttpStatusCode.Forbidden)
{
Console.WriteLine($"Boo, I cannot message {user}.");
}
}

#endregion
}
}
#endregion

+ 21
- 0
src/Discord.Net.Examples/Discord.Net.Examples.csproj View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Remove="Core\Entities\Guilds\IGuild.Examples.cs" />
</ItemGroup>

<ItemGroup>
<None Include="Core\Entities\Guilds\IGuild.Examples.cs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" />
<ProjectReference Include="..\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj" />
<PackageReference Include="JetBrains.Annotations" Version="2018.3.0" />
</ItemGroup>

</Project>

+ 110
- 83
src/Discord.Net.Examples/WebSocket/BaseSocketClient.Events.Examples.cs View File

@@ -1,90 +1,117 @@
#region ReactionAdded
public void HookReactionAdded(BaseSocketClient client)
{
client.ReactionAdded += HandleReactionAddedAsync;
}
public async Task HandleReactionAddedAsync(Cacheable<IUserMessage, ulong> cachedMessage,
ISocketMessageChannel originChannel, SocketReaction reaction)
{
var message = await cachedMessage.GetOrDownloadAsync();
if (message != null && reaction.User.IsSpecified)
Console.WriteLine($"{message.User.Value} just added a reaction '{reaction.Emote}' " +
$"to {message.Author}'s message ({message.Id}).");
}
#endregion
using System;
using System.Linq;
using System.Threading.Tasks;
using Discord.WebSocket;
using JetBrains.Annotations;

#region ChannelCreated
public void HookChannelCreated(BaseSocketClient client)
{
client.ChannelCreated += HandleChannelCreated;
}
public Task HandleChannelCreated(SocketChannel channel)
namespace Discord.Net.Examples.WebSocket
{
Console.WriteLine($"A new channel '{channel.Name}'({channel.Id}, {channel.GetType()})"
+ $"has been created at {channel.CreatedAt}.");
return Task.CompletedTask;
}
#endregion
[PublicAPI]
internal class BaseSocketClientExamples
{
#region ReactionAdded

#region ChannelDestroyed
public void HookChannelDestroyed(BaseSocketClient client)
{
client.ChannelDestroyed += HandleChannelDestroyed;
}
public Task HandleChannelDestroyed(SocketChannel channel)
{
Console.WriteLine($"A new channel '{channel.Name}'({channel.Id}, {channel.GetType()}) has been deleted.");
return Task.CompletedTask;
}
#endregion
public void HookReactionAdded(BaseSocketClient client)
=> client.ReactionAdded += HandleReactionAddedAsync;

#region ChannelUpdated
public void HookChannelUpdated(BaseSocketClient client)
{
client.ChannelUpdated += HandleChannelRename;
}
public Task HandleChannelRename(SocketChannel beforeChannel, SocketChannel afterChannel)
{
if (beforeChannel.Name != afterChannel.Name)
Console.WriteLine($"A channel ({beforeChannel.Id}) is renamed from {beforeChannel.Name} to {afterChannel.Name}.");
return Task.CompletedTask;
}
#endregion
public async Task HandleReactionAddedAsync(Cacheable<IUserMessage, ulong> cachedMessage,
ISocketMessageChannel originChannel, SocketReaction reaction)
{
var message = await cachedMessage.GetOrDownloadAsync();
if (message != null && reaction.User.IsSpecified)
Console.WriteLine($"{reaction.User.Value} just added a reaction '{reaction.Emote}' " +
$"to {message.Author}'s message ({message.Id}).");
}

#region MessageReceived
private readonly ulong[] _targetUserIds = new {168693960628371456, 53905483156684800};
public void HookMessageReceived(BaseSocketClient client)
{
client.MessageReceived += HandleMessageReceived;
}
public Task HandleMessageReceived(SocketMessage message)
{
// check if the message is a user message as opposed to a system message (e.g. Clyde, pins, etc.)
if (!(message is SocketUserMessage userMessage)) return;
// check if the message origin is a guild message channel
if (!(userMessage.Channel is SocketTextChannel textChannel)) return;
// check if the target user was mentioned
var targetUsers = userMessage.MentionedUsers.Where(x => _targetUserIds.Contains(x));
if (targetUsers == null) return;
foreach (var targetUser in targetUsers)
Console.WriteLine($"{targetUser} was mentioned in the message '{message.Content}' by {message.Author}.");
return Task.CompletedTask;
}
#endregion
#endregion

#region MessageDeleted
public void HookMessageDeleted(BaseSocketClient client)
{
client.MessageDeleted += HandleMessageDelete;
}
public Task HandleMessageDelete(Cacheable<IMessage, ulong> cachedMessage, ISocketMessageChannel channel)
{
// check if the message exists in cache; if not, we cannot report what was removed
if (!cachedMessage.HasValue) return;
var message = cachedMessage.Value;
Console.WriteLine($"A message ({message.Id}) from {message.Author} was removed from the channel {channel.Name} ({channel.Id}):"
+ Environment.NewLine
+ message.Content);
return Task.CompletedTask;
#region ChannelCreated

public void HookChannelCreated(BaseSocketClient client)
=> client.ChannelCreated += HandleChannelCreated;

public Task HandleChannelCreated(SocketChannel channel)
{
if (channel is SocketGuildChannel guildChannel)
Console.WriteLine($"A new channel '{guildChannel.Name}'({guildChannel.Id}, {guildChannel.GetType()})"
+ $"has been created at {guildChannel.CreatedAt}.");
return Task.CompletedTask;
}

#endregion

#region ChannelDestroyed

public void HookChannelDestroyed(BaseSocketClient client)
=> client.ChannelDestroyed += HandleChannelDestroyed;

public Task HandleChannelDestroyed(SocketChannel channel)
{
if (channel is SocketGuildChannel guildChannel)
Console.WriteLine(
$"A new channel '{guildChannel.Name}'({guildChannel.Id}, {guildChannel.GetType()}) has been deleted.");
return Task.CompletedTask;
}

#endregion

#region ChannelUpdated

public void HookChannelUpdated(BaseSocketClient client)
=> client.ChannelUpdated += HandleChannelRename;

public Task HandleChannelRename(SocketChannel beforeChannel, SocketChannel afterChannel)
{
if (beforeChannel is SocketGuildChannel beforeGuildChannel &&
afterChannel is SocketGuildChannel afterGuildChannel)
if (beforeGuildChannel.Name != afterGuildChannel.Name)
Console.WriteLine(
$"A channel ({beforeChannel.Id}) is renamed from {beforeGuildChannel.Name} to {afterGuildChannel.Name}.");
return Task.CompletedTask;
}

#endregion

#region MessageReceived

private readonly ulong[] _targetUserIds = {168693960628371456, 53905483156684800};

public void HookMessageReceived(BaseSocketClient client)
=> client.MessageReceived += HandleMessageReceived;

public Task HandleMessageReceived(SocketMessage message)
{
// check if the message is a user message as opposed to a system message (e.g. Clyde, pins, etc.)
if (!(message is SocketUserMessage userMessage)) return Task.CompletedTask;
// check if the message origin is a guild message channel
if (!(userMessage.Channel is SocketTextChannel textChannel)) return Task.CompletedTask;
// check if the target user was mentioned
var targetUsers = userMessage.MentionedUsers.Where(x => _targetUserIds.Contains(x.Id));
foreach (var targetUser in targetUsers)
Console.WriteLine(
$"{targetUser} was mentioned in the message '{message.Content}' by {message.Author} in {textChannel.Name}.");
return Task.CompletedTask;
}

#endregion

#region MessageDeleted

public void HookMessageDeleted(BaseSocketClient client)
=> client.MessageDeleted += HandleMessageDelete;

public Task HandleMessageDelete(Cacheable<IMessage, ulong> cachedMessage, ISocketMessageChannel channel)
{
// check if the message exists in cache; if not, we cannot report what was removed
if (!cachedMessage.HasValue) return Task.CompletedTask;
var message = cachedMessage.Value;
Console.WriteLine(
$"A message ({message.Id}) from {message.Author} was removed from the channel {channel.Name} ({channel.Id}):"
+ Environment.NewLine
+ message.Content);
return Task.CompletedTask;
}

#endregion
}
}
#endregion

+ 1
- 1
src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs View File

@@ -405,7 +405,7 @@ namespace Discord.Rest
/// </summary>
/// <example>
/// The following example creates a new text channel under an existing category named <c>Wumpus</c> with a set topic.
/// <code lang="cs">
/// <code language="cs">
/// var categories = await guild.GetCategoriesAsync();
/// var targetCategory = categories.FirstOrDefault(x => x.Name == "wumpus");
/// if (targetCategory == null) return;


+ 13
- 7
src/Discord.Net.WebSocket/BaseSocketClient.Events.cs View File

@@ -19,7 +19,8 @@ namespace Discord.WebSocket
/// </para>
/// </remarks>
/// <example>
/// <code source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs" region="ChannelCreated"></code>
/// <code language="cs" region="ChannelCreated"
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/>
/// </example>
public event Func<SocketChannel, Task> ChannelCreated
{
@@ -40,7 +41,8 @@ namespace Discord.WebSocket
/// </para>
/// </remarks>
/// <example>
/// <code source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs" region="ChannelDestroyed"></code>
/// <code language="cs" region="ChannelDestroyed"
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/>
/// </example>
public event Func<SocketChannel, Task> ChannelDestroyed {
add { _channelDestroyedEvent.Add(value); }
@@ -61,7 +63,8 @@ namespace Discord.WebSocket
/// </para>
/// </remarks>
/// <example>
/// <code source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs" region="ChannelUpdated"></code>
/// <code language="cs" region="ChannelUpdated"
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/>
/// </example>
public event Func<SocketChannel, SocketChannel, Task> ChannelUpdated {
add { _channelUpdatedEvent.Add(value); }
@@ -84,8 +87,9 @@ namespace Discord.WebSocket
/// </para>
/// </remarks>
/// <example>
/// The example below checks if the newly received message contains the target user.
/// <code source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs" region="MessageReceived"></code>
/// <para>The example below checks if the newly received message contains the target user.</para>
/// <code language="cs" region="MessageReceived"
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/>
/// </example>
public event Func<SocketMessage, Task> MessageReceived {
add { _messageReceivedEvent.Add(value); }
@@ -116,7 +120,8 @@ namespace Discord.WebSocket
/// </para>
/// </remarks>
/// <example>
/// <code source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs" region="MessageDeleted"></code>
/// <code language="cs" region="MessageDeleted"
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs" />
/// </example>
public event Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task> MessageDeleted {
add { _messageDeletedEvent.Add(value); }
@@ -176,7 +181,8 @@ namespace Discord.WebSocket
/// </note>
/// </remarks>
/// <example>
/// <code source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs" region="ReactionAdded"></code>
/// <code language="cs" region="ReactionAdded"
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/>
/// </example>
public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task> ReactionAdded {
add { _reactionAddedEvent.Add(value); }


+ 14
- 14
src/Discord.Net.WebSocket/BaseSocketClient.cs View File

@@ -97,15 +97,15 @@ namespace Discord.WebSocket
/// <remarks>
/// This method gets the user present in the WebSocket cache with the given condition.
/// <note type="warning">
/// Sometimes a user may return <c>null</c> due to Discord not sending offline users in large
/// guilds (i.e. guild with 100+ members) actively. To download users on startup and to see
/// more information about this subject, see <see cref="DiscordSocketConfig.AlwaysDownloadUsers"/>.
/// Sometimes a user may return <c>null</c> due to Discord not sending offline users in large guilds
/// (i.e. guild with 100+ members) actively. To download users on startup and to see more information
/// about this subject, see <see cref="Discord.WebSocket.DiscordSocketConfig.AlwaysDownloadUsers" />.
/// </note>
/// <note>
/// This method does not attempt to fetch users that the logged-in user does not have access to (i.e.
/// users who don't share mutual guild(s) with the current user). If you wish to get a user that
/// you do not have access to, consider using the REST implementation of
/// <see cref="DiscordSocketRestClient.GetUserAsync"/>.
/// users who don't share mutual guild(s) with the current user). If you wish to get a user that you do
/// not have access to, consider using the REST implementation of
/// <see cref="DiscordRestClient.GetUserAsync(System.UInt64,Discord.RequestOptions)" />.
/// </note>
/// </remarks>
/// <returns>
@@ -116,22 +116,22 @@ namespace Discord.WebSocket
/// <summary>
/// Gets a user.
/// </summary>
/// <param name="username">The name of the user.</param>
/// <param name="discriminator">The discriminator value of the user.</param>
/// <remarks>
/// This method gets the user present in the WebSocket cache with the given condition.
/// <note type="warning">
/// Sometimes a user may return <c>null</c> due to Discord not sending offline users in large
/// guilds (i.e. guild with 100+ members) actively. To download users on startup and to see
/// more information about this subject, see <see cref="DiscordSocketConfig.AlwaysDownloadUsers"/>.
/// Sometimes a user may return <c>null</c> due to Discord not sending offline users in large guilds
/// (i.e. guild with 100+ members) actively. To download users on startup and to see more information
/// about this subject, see <see cref="Discord.WebSocket.DiscordSocketConfig.AlwaysDownloadUsers" />.
/// </note>
/// <note>
/// This method does not attempt to fetch users that the logged-in user does not have access to (i.e.
/// users who don't share mutual guild(s) with the current user). If you wish to get a user that
/// you do not have access to, consider using the REST implementation of
/// <see cref="DiscordSocketRestClient.GetUserAsync"/>.
/// users who don't share mutual guild(s) with the current user). If you wish to get a user that you do
/// not have access to, consider using the REST implementation of
/// <see cref="DiscordRestClient.GetUserAsync(System.UInt64,Discord.RequestOptions)" />.
/// </note>
/// </remarks>
/// <param name="username">The name of the user.</param>
/// <param name="discriminator">The discriminator value of the user.</param>
/// <returns>
/// A generic WebSocket-based user; <c>null</c> when the user cannot be found.
/// </returns>


+ 3
- 2
src/Discord.Net.WebSocket/DiscordSocketConfig.cs View File

@@ -94,8 +94,9 @@ namespace Discord.WebSocket
/// Please note that it can be difficult to fill the cache completely on large guilds depending on the
/// traffic. If you are using the command system, the default user TypeReader may fail to find the user
/// due to this issue. This may be resolved at v3 of the library. Until then, you may want to consider
/// overriding the TypeReader and use <see cref="DiscordSocketRestClient.GetUserAsync"/>
/// or <see cref="DiscordSocketRestClient.GetGuildUserAsync"/> as a backup.
/// overriding the TypeReader and use
/// <see cref="DiscordRestClient.GetUserAsync(System.UInt64,Discord.RequestOptions)"/>
/// or <see cref="DiscordSocketRestClient.GetGuildUserAsync(ulong, ulong, RequestOptions)"/> as a backup.
/// </note>
/// </remarks>
public bool AlwaysDownloadUsers { get; set; } = false;


+ 1
- 1
src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs View File

@@ -535,7 +535,7 @@ namespace Discord.WebSocket
/// </summary>
/// <example>
/// The following example creates a new text channel under an existing category named <c>Wumpus</c> with a set topic.
/// <code lang="cs">
/// <code language="cs">
/// var categories = await guild.GetCategoriesAsync();
/// var targetCategory = categories.FirstOrDefault(x => x.Name == "wumpus");
/// if (targetCategory == null) return;


Loading…
Cancel
Save