@@ -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} | |||
@@ -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> | |||
@@ -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 => 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> | |||
@@ -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> | |||
@@ -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> | |||
@@ -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> | |||
@@ -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 && 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 => x.IsOptimal); | |||
/// </code> | |||
@@ -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 |
@@ -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 | |||
} | |||
} | |||
} |
@@ -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 | |||
} | |||
} |
@@ -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 |
@@ -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> |
@@ -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 |
@@ -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; | |||
@@ -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); } | |||
@@ -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> | |||
@@ -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; | |||
@@ -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; | |||