Browse Source

Merge remote-tracking branch 'upstream/docs/pre-release' into docs/Casino-Docs

pull/1161/head
Casino Boyale 7 years ago
parent
commit
6e41692261
58 changed files with 939 additions and 416 deletions
  1. +5
    -2
      src/Discord.Net.Core/Entities/Channels/GuildChannelProperties.cs
  2. +13
    -1
      src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs
  3. +4
    -3
      src/Discord.Net.Core/Entities/Channels/IChannel.cs
  4. +6
    -0
      src/Discord.Net.Core/Entities/Channels/IDMChannel.cs
  5. +3
    -0
      src/Discord.Net.Core/Entities/Channels/IGroupChannel.cs
  6. +23
    -33
      src/Discord.Net.Core/Entities/Channels/IGuildChannel.cs
  7. +53
    -24
      src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs
  8. +3
    -2
      src/Discord.Net.Core/Entities/Channels/INestedChannel.cs
  9. +1
    -1
      src/Discord.Net.Core/Entities/Channels/IPrivateChannel.cs
  10. +28
    -13
      src/Discord.Net.Core/Entities/Channels/ITextChannel.cs
  11. +14
    -3
      src/Discord.Net.Core/Entities/Channels/IVoiceChannel.cs
  12. +2
    -2
      src/Discord.Net.Core/Entities/Channels/ReorderChannelProperties.cs
  13. +2
    -4
      src/Discord.Net.Core/Entities/Channels/TextChannelProperties.cs
  14. +1
    -1
      src/Discord.Net.Core/Entities/Channels/VoiceChannelProperties.cs
  15. +4
    -1
      src/Discord.Net.Core/Entities/Emotes/Emoji.cs
  16. +11
    -4
      src/Discord.Net.Core/Entities/Emotes/Emote.cs
  17. +1
    -1
      src/Discord.Net.Core/Entities/Emotes/EmoteProperties.cs
  18. +11
    -2
      src/Discord.Net.Core/Entities/Emotes/GuildEmote.cs
  19. +3
    -0
      src/Discord.Net.Core/Entities/Emotes/IEmote.cs
  20. +1
    -1
      src/Discord.Net.Core/Entities/Guilds/GuildEmbedProperties.cs
  21. +1
    -1
      src/Discord.Net.Core/Entities/Guilds/GuildIntegrationProperties.cs
  22. +1
    -1
      src/Discord.Net.Core/Entities/Guilds/GuildProperties.cs
  23. +170
    -145
      src/Discord.Net.Core/Entities/Guilds/IGuild.cs
  24. +1
    -1
      src/Discord.Net.Core/Entities/IApplication.cs
  25. +6
    -1
      src/Discord.Net.Core/Entities/ISnowflakeEntity.cs
  26. +27
    -6
      src/Discord.Net.Core/Entities/Messages/EmbedFooter.cs
  27. +33
    -5
      src/Discord.Net.Core/Entities/Messages/EmbedImage.cs
  28. +18
    -2
      src/Discord.Net.Core/Entities/Messages/EmbedProvider.cs
  29. +33
    -5
      src/Discord.Net.Core/Entities/Messages/EmbedThumbnail.cs
  30. +49
    -1
      src/Discord.Net.Core/Entities/Messages/IUserMessage.cs
  31. +1
    -1
      src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs
  32. +19
    -20
      src/Discord.Net.Core/Entities/Roles/Color.cs
  33. +2
    -2
      src/Discord.Net.Core/Entities/Roles/IRole.cs
  34. +1
    -1
      src/Discord.Net.Core/Entities/Roles/ReorderRoleProperties.cs
  35. +51
    -8
      src/Discord.Net.Core/Entities/Users/IGuildUser.cs
  36. +1
    -1
      src/Discord.Net.Core/Entities/Users/IPresence.cs
  37. +8
    -2
      src/Discord.Net.Core/Entities/Users/ISelfUser.cs
  38. +18
    -6
      src/Discord.Net.Core/Logging/LogMessage.cs
  39. +1
    -1
      src/Discord.Net.Core/Net/RateLimitedException.cs
  40. +15
    -3
      src/Discord.Net.Core/RequestOptions.cs
  41. +1
    -2
      src/Discord.Net.Core/Utils/DateTimeUtils.cs
  42. +1
    -1
      src/Discord.Net.Core/Utils/MentionUtils.cs
  43. +17
    -0
      src/Discord.Net.Core/Utils/SnowflakeUtils.cs
  44. +4
    -4
      src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs
  45. +1
    -0
      src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs
  46. +1
    -1
      src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
  47. +2
    -1
      src/Discord.Net.Rest/Entities/Messages/RestSystemMessage.cs
  48. +1
    -0
      src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs
  49. +38
    -11
      src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs
  50. +14
    -0
      src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs
  51. +148
    -81
      src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
  52. +21
    -0
      src/Discord.Net.WebSocket/Entities/Roles/SocketRole.cs
  53. +2
    -1
      src/Discord.Net.WebSocket/Entities/SocketEntity.cs
  54. +8
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketGroupUser.cs
  55. +9
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketPresence.cs
  56. +3
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs
  57. +14
    -1
      src/Discord.Net.WebSocket/Entities/Users/SocketUnknownUser.cs
  58. +9
    -2
      src/Discord.Net.WebSocket/Entities/Users/SocketVoiceState.cs

+ 5
- 2
src/Discord.Net.Core/Entities/Channels/GuildChannelProperties.cs View File

@@ -10,8 +10,11 @@ namespace Discord
/// Gets or sets the channel to this name. /// Gets or sets the channel to this name.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// When modifying an <see cref="ITextChannel" />, the <see cref="Name" />
/// MUST be alphanumeric with dashes. It must match the following RegEx: [a-z0-9-_]{2,100}
/// This property defines the new name for this channel.
/// <note type="warning">
/// When modifying an <see cref="ITextChannel"/>, the <see cref="Name"/> must be alphanumeric with
/// dashes. It must match the RegEx <c>[a-z0-9-_]{2,100}</c>.
/// </note>
/// </remarks> /// </remarks>
public Optional<string> Name { get; set; } public Optional<string> Name { get; set; }
/// <summary> /// <summary>


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

@@ -12,9 +12,21 @@ namespace Discord
/// <summary> /// <summary>
/// Connects to this audio channel. /// Connects to this audio channel.
/// </summary> /// </summary>
/// <param name="selfDeaf">Determines whether the client should deaf itself upon connection.</param>
/// <param name="selfMute">Determines whether the client should mute itself upon connection.</param>
/// <param name="external">Determines whether the audio client is an external one or not.</param>
/// <returns>
/// A task representing the asynchronous connection operation. The task result contains the
/// <see cref="IAudioClient"/> responsible for the connection.
/// </returns>
Task<IAudioClient> ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false); Task<IAudioClient> ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false);


/// <summary> Disconnects from this audio channel. </summary>
/// <summary>
/// Disconnects from this audio channel.
/// </summary>
/// <returns>
/// A task representing the asynchronous disconnection operation.
/// </returns>
Task DisconnectAsync(); Task DisconnectAsync();
} }
} }

+ 4
- 3
src/Discord.Net.Core/Entities/Channels/IChannel.cs View File

@@ -31,11 +31,12 @@ namespace Discord
/// <summary> /// <summary>
/// Gets a user in this channel. /// Gets a user in this channel.
/// </summary> /// </summary>
/// <param name="id">The snowflake identifier of the user (e.g. 168693960628371456).</param>
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="id">The snowflake identifier of the user (e.g. <c>168693960628371456</c>).</param>
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a user object that represents the user.
/// A task that represents the asynchronous get operation. The task result contains a user object that
/// represents the found user; <c>null</c> if none is found.
/// </returns> /// </returns>
Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
} }


+ 6
- 0
src/Discord.Net.Core/Entities/Channels/IDMChannel.cs View File

@@ -10,12 +10,18 @@ namespace Discord
/// <summary> /// <summary>
/// Gets the recipient of all messages in this channel. /// Gets the recipient of all messages in this channel.
/// </summary> /// </summary>
/// <returns>
/// A user object that represents the other user in this channel.
/// </returns>
IUser Recipient { get; } IUser Recipient { get; }


/// <summary> /// <summary>
/// Closes this private channel, removing it from your channel list. /// Closes this private channel, removing it from your channel list.
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous close operation.
/// </returns>
Task CloseAsync(RequestOptions options = null); Task CloseAsync(RequestOptions options = null);
} }
} }

+ 3
- 0
src/Discord.Net.Core/Entities/Channels/IGroupChannel.cs View File

@@ -11,6 +11,9 @@ namespace Discord
/// Leaves this group. /// Leaves this group.
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous leave operation.
/// </returns>
Task LeaveAsync(RequestOptions options = null); Task LeaveAsync(RequestOptions options = null);
} }
} }

+ 23
- 33
src/Discord.Net.Core/Entities/Channels/IGuildChannel.cs View File

@@ -16,7 +16,8 @@ namespace Discord
/// Gets the position of this channel. /// Gets the position of this channel.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// The position of this channel in the guild's channel list, relative to others of the same type.
/// An <see cref="int"/> representing the position of this channel in the guild's channel list relative to
/// others of the same type.
/// </returns> /// </returns>
int Position { get; } int Position { get; }


@@ -24,14 +25,15 @@ namespace Discord
/// Gets the guild associated with this channel. /// Gets the guild associated with this channel.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A guild that this channel belongs to.
/// A guild object that this channel belongs to.
/// </returns> /// </returns>
IGuild Guild { get; } IGuild Guild { get; }
/// <summary> /// <summary>
/// Gets the guild ID associated with this channel. /// Gets the guild ID associated with this channel.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A guild snowflake identifier for the guild that this channel belongs to.
/// An <see cref="ulong"/> representing the guild snowflake identifier for the guild that this channel
/// belongs to.
/// </returns> /// </returns>
ulong GuildId { get; } ulong GuildId { get; }
/// <summary> /// <summary>
@@ -45,25 +47,14 @@ namespace Discord
/// <summary> /// <summary>
/// Creates a new invite to this channel. /// Creates a new invite to this channel.
/// </summary> /// </summary>
/// <param name="maxAge">
/// The time (in seconds) until the invite expires. Set to <c>null</c> to never expire.
/// </param>
/// <param name="maxUses">
/// The max amount of times this invite may be used. Set to <c>null</c> to have unlimited uses.
/// </param>
/// <param name="isTemporary">
/// If <c>true</c>, a user accepting this invite will be kicked from the guild after closing their client.
/// </param>
/// <param name="isUnique">
/// If <c>true</c>, don't try to reuse a similar invite (useful for creating many unique one time use
/// invites).
/// </param>
/// <param name="options">
/// The options to be used when sending the request.
/// </param>
/// <param name="maxAge">The time (in seconds) until the invite expires. Set to <c>null</c> to never expire.</param>
/// <param name="maxUses">The max amount of times this invite may be used. Set to <c>null</c> to have unlimited uses.</param>
/// <param name="isTemporary">If <c>true</c>, the user accepting this invite will be kicked from the guild after closing their client.</param>
/// <param name="isUnique">If <c>true</c>, don't try to reuse a similar invite (useful for creating many unique one time use invites).</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing an invite metadata object containing information for the
/// created invite.
/// A task that represents the asynchronous invite creation operation. The task result contains an invite
/// metadata object containing information for the created invite.
/// </returns> /// </returns>
Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null); Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null);
/// <summary> /// <summary>
@@ -71,18 +62,18 @@ namespace Discord
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a read-only collection of invite metadata that are created
/// for this channel.
/// A task that represents the asynchronous get operation. The task result contains a read-only collection
/// of invite metadata that are created for this channel.
/// </returns> /// </returns>
Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null); Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null);


/// <summary> /// <summary>
/// Modifies this guild channel. /// Modifies this guild channel.
/// </summary> /// </summary>
/// <param name="func">The properties to modify the channel with.</param>
/// <param name="func">The delegate containing the properties to modify the channel with.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task that represents the asynchronous modification operation.
/// </returns> /// </returns>
Task ModifyAsync(Action<GuildChannelProperties> func, RequestOptions options = null); Task ModifyAsync(Action<GuildChannelProperties> func, RequestOptions options = null);


@@ -108,7 +99,7 @@ namespace Discord
/// <param name="role">The role to remove the overwrite from.</param> /// <param name="role">The role to remove the overwrite from.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task representing the asynchronous removal operation.
/// </returns> /// </returns>
Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null); Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null);
/// <summary> /// <summary>
@@ -117,7 +108,7 @@ namespace Discord
/// <param name="user">The user to remove the overwrite from.</param> /// <param name="user">The user to remove the overwrite from.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task representing the asynchronous removal operation.
/// </returns> /// </returns>
Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null); Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null);


@@ -128,7 +119,7 @@ namespace Discord
/// <param name="permissions">The overwrite to add to the role.</param> /// <param name="permissions">The overwrite to add to the role.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task representing the asynchronous permission addition operation.
/// </returns> /// </returns>
Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options = null); Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options = null);
/// <summary> /// <summary>
@@ -138,7 +129,7 @@ namespace Discord
/// <param name="permissions">The overwrite to add to the user.</param> /// <param name="permissions">The overwrite to add to the user.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task representing the asynchronous permission addition operation.
/// </returns> /// </returns>
Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options = null); Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options = null);


@@ -159,12 +150,11 @@ namespace Discord
/// Gets a user in this channel with the provided ID. /// Gets a user in this channel with the provided ID.
/// </summary> /// </summary>
/// <param name="id">The ID of the user.</param> /// <param name="id">The ID of the user.</param>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a guild user object that represents the user.
/// A task representing the asynchrnous get operation. The task result contains a guild user object that
/// represents the user; <c>null</c> if none is found.
/// </returns> /// </returns>
new Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); new Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
} }


+ 53
- 24
src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs View File

@@ -14,57 +14,67 @@ namespace Discord
/// Sends a message to this message channel. /// Sends a message to this message channel.
/// </summary> /// </summary>
/// <param name="text">The message to be sent.</param> /// <param name="text">The message to be sent.</param>
/// <param name="isTTS">Whether the message should be read aloud by Discord or not.</param>
/// <param name="embed">The <see cref="EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param>
/// <param name="isTTS">Determines whether the message should be read aloud by Discord or not.</param>
/// <param name="embed">The <see cref="Discord.EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable Task containing the message sent to the channel.
/// A task that represents an asynchrnous send operation for delievering the message. The task result
/// contains the sent message.
/// </returns> /// </returns>
Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null);
/// <summary> /// <summary>
/// Sends a file to this message channel with an optional caption. /// Sends a file to this message channel with an optional caption.
/// </summary> /// </summary>
/// <remarks>
/// This method sends a file as if you are uploading an attachment directly from your Discord client.
/// <note>
/// If you wish to upload an image and have it embedded in a <see cref="Discord.EmbedType.Rich"/>embed,
/// you may upload the file and refer to the file with "attachment://filename.ext" in the
/// <see cref="Discord.EmbedBuilder.ImageUrl"/>.
/// </note>
/// </remarks>
/// <param name="filePath">The file path of the file.</param> /// <param name="filePath">The file path of the file.</param>
/// <param name="text">The message to be sent.</param> /// <param name="text">The message to be sent.</param>
/// <param name="isTTS">Whether the message should be read aloud by Discord or not.</param> /// <param name="isTTS">Whether the message should be read aloud by Discord or not.</param>
/// <param name="embed">The <see cref="EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param>
/// <param name="embed">The <see cref="Discord.EmbedType.Rich" /> <see cref="Embed" /> to be sent.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <remarks>
/// If you wish to upload an image and have it embedded in a <see cref="EmbedType.Rich"/> embed, you may
/// upload the file and refer to the file with "attachment://filename.ext" in the
/// <see cref="Discord.EmbedBuilder.ImageUrl"/>.
/// </remarks>
/// <returns> /// <returns>
/// An awaitable Task containing the message sent to the channel.
/// A task that represents an asynchrnous send operation for delievering the message. The task result
/// contains the sent message.
/// </returns> /// </returns>
Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null);
/// <summary> /// <summary>
/// Sends a file to this message channel with an optional caption. /// Sends a file to this message channel with an optional caption.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> of the file to be sent.</param>
/// <remarks>
/// This method sends a file as if you are uploading an attachment directly from your Discord client.
/// <note>
/// If you wish to upload an image and have it embedded in a <see cref="Discord.EmbedType.Rich"/>embed,
/// you may upload the file and refer to the file with "attachment://filename.ext" in the
/// <see cref="Discord.EmbedBuilder.ImageUrl"/>.
/// </note>
/// </remarks>
/// <param name="stream">The <see cref="Stream" /> of the file to be sent.</param>
/// <param name="filename">The name of the attachment.</param> /// <param name="filename">The name of the attachment.</param>
/// <param name="text">The message to be sent.</param> /// <param name="text">The message to be sent.</param>
/// <param name="isTTS">Whether the message should be read aloud by Discord or not.</param> /// <param name="isTTS">Whether the message should be read aloud by Discord or not.</param>
/// <param name="embed">The <see cref="EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param>
/// <param name="embed">The <see cref="Discord.EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <remarks>
/// If you wish to upload an image and have it embedded in a <see cref="EmbedType.Rich"/> embed, you may
/// upload the file and refer to the file with "attachment://filename.ext" in the
/// <see cref="Discord.EmbedBuilder.ImageUrl"/>.
/// </remarks>
/// <returns> /// <returns>
/// An awaitable Task containing the message sent to the channel.
/// A task that represents an asynchrnous send operation for delievering the message. The task result
/// contains the sent message.
/// </returns> /// </returns>
Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null);


/// <summary> /// <summary>
/// Gets a message from this message channel with the given id, or <c>null</c> if not found.
/// Gets a message from this message channel.
/// </summary> /// </summary>
/// <param name="id">The ID of the message.</param>
/// <param name="id">The snowflake identifier of the message.</param>
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param> /// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// The message gotten from either the cache or the download, or <c>null</c> if none is found.
/// A task that represents an asynchrnous get operation for retrieving the message. The task result contains
/// the retrieved message; <c>null</c> if no message is found with the specified identifier.
/// </returns> /// </returns>
Task<IMessage> GetMessageAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IMessage> GetMessageAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);


@@ -94,7 +104,6 @@ namespace Discord
/// </returns> /// </returns>
IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch,
CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);

/// <summary> /// <summary>
/// Gets a collection of messages in this channel. /// Gets a collection of messages in this channel.
/// </summary> /// </summary>
@@ -115,25 +124,45 @@ namespace Discord
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable Task containing a collection of messages.
/// A task that represents the asynchronous get operation for retrieving pinned messages in this channel.
/// The task result contains a collection of messages found in the pinned messages.
/// </returns> /// </returns>
Task<IReadOnlyCollection<IMessage>> GetPinnedMessagesAsync(RequestOptions options = null); Task<IReadOnlyCollection<IMessage>> GetPinnedMessagesAsync(RequestOptions options = null);


/// <summary> Deletes a message based on the message ID in this channel. </summary>
/// <summary>
/// Deletes a message.
/// </summary>
/// <param name="messageId">The snowflake identifier of the message that would be removed.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous removal operation.
/// </returns>
Task DeleteMessageAsync(ulong messageId, RequestOptions options = null); Task DeleteMessageAsync(ulong messageId, RequestOptions options = null);
/// <summary> Deletes a message based on the provided message in this channel. </summary> /// <summary> Deletes a message based on the provided message in this channel. </summary>
/// <param name="message">The message that would be removed.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous removal operation.
/// </returns>
Task DeleteMessageAsync(IMessage message, RequestOptions options = null); Task DeleteMessageAsync(IMessage message, RequestOptions options = null);


/// <summary> /// <summary>
/// Broadcasts the "user is typing" message to all users in this channel, lasting 10 seconds. /// Broadcasts the "user is typing" message to all users in this channel, lasting 10 seconds.
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous operation that triggers the broadcast.
/// </returns>
Task TriggerTypingAsync(RequestOptions options = null); Task TriggerTypingAsync(RequestOptions options = null);
/// <summary> /// <summary>
/// Continuously broadcasts the "user is typing" message to all users in this channel until the returned /// Continuously broadcasts the "user is typing" message to all users in this channel until the returned
/// object is disposed. /// object is disposed.
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A disposable object that, upon its disposal, will stop the client from broadcasting its typing state in
/// this channel.
/// </returns>
IDisposable EnterTypingState(RequestOptions options = null); IDisposable EnterTypingState(RequestOptions options = null);
} }
} }

+ 3
- 2
src/Discord.Net.Core/Entities/Channels/INestedChannel.cs View File

@@ -11,7 +11,7 @@ namespace Discord
/// Gets the parent (category) ID of this channel in the guild's channel list. /// Gets the parent (category) ID of this channel in the guild's channel list.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// An <see cref="System.UInt64"/> representing the snowflake identifier of the parent of this channel;
/// A <see cref="ulong"/> representing the snowflake identifier of the parent of this channel;
/// <c>null</c> if none is set. /// <c>null</c> if none is set.
/// </returns> /// </returns>
ulong? CategoryId { get; } ulong? CategoryId { get; }
@@ -21,7 +21,8 @@ namespace Discord
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param> /// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// A category channel representing the parent of this channel; <c>null</c> if none is set.
/// A task that represents the asynchrnous get operation. The task result contains the category channel
/// representing the parent of this channel; <c>null</c> if none is set.
/// </returns> /// </returns>
Task<ICategoryChannel> GetCategoryAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<ICategoryChannel> GetCategoryAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
} }


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

@@ -11,7 +11,7 @@ namespace Discord
/// Gets the users that can access this channel. /// Gets the users that can access this channel.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A collection of users that can access this channel.
/// A read-only collection of users that can access this channel.
/// </returns> /// </returns>
IReadOnlyCollection<IUser> Recipients { get; } IReadOnlyCollection<IUser> Recipients { get; }
} }


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

@@ -14,7 +14,7 @@ namespace Discord
/// Determines whether the channel is NSFW. /// Determines whether the channel is NSFW.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// <c>true</c> if the channel has the NSFW flag enabled; otherwise, <c>false</c>.
/// <c>true</c> if the channel has the NSFW flag enabled; otherwise <c>false</c>.
/// </returns> /// </returns>
bool IsNsfw { get; } bool IsNsfw { get; }


@@ -22,7 +22,7 @@ namespace Discord
/// Gets the current topic for this text channel. /// Gets the current topic for this text channel.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// The topic set in the channel, or <c>null</c> if none is set.
/// A string representing the topic set in the channel; <c>null</c> if none is set.
/// </returns> /// </returns>
string Topic { get; } string Topic { get; }


@@ -30,32 +30,44 @@ namespace Discord
/// Bulk-deletes multiple messages. /// Bulk-deletes multiple messages.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This method attempts to remove the messages specified in bulk.
/// <note type="important"> /// <note type="important">
/// This method can only remove messages that are posted within 14 days!
/// Due to the limitation set by Discord, this method can only remove messages that are posted within 14 days!
/// </note> /// </note>
/// </remarks> /// </remarks>
/// <param name="messages">The messages to be bulk-deleted.</param> /// <param name="messages">The messages to be bulk-deleted.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous bulk-removal operation.
/// </returns>
Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null); Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null);
/// <summary> /// <summary>
/// Bulk-deletes multiple messages. /// Bulk-deletes multiple messages.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This method attempts to remove the messages specified in bulk.
/// <note type="important"> /// <note type="important">
/// This method can only remove messages that are posted within 14 days!
/// Due to the limitation set by Discord, this method can only remove messages that are posted within 14 days!
/// </note> /// </note>
/// </remarks> /// </remarks>
/// <param name="messageIds">The IDs of the messages to be bulk-deleted.</param>
/// <param name="messageIds">The snowflake identifier of the messages to be bulk-deleted.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous bulk-removal operation.
/// </returns>
Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null); Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null);


/// <summary> /// <summary>
/// Modifies this text channel. /// Modifies this text channel.
/// </summary> /// </summary>
/// <param name="func">The properties to modify the channel with.</param>
/// <param name="func">The delegate containing the properties to modify the channel with.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous modification operation.
/// </returns>
/// <seealso cref="TextChannelProperties"/>
Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null); Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null);

/// <summary> /// <summary>
/// Creates a webhook in this text channel. /// Creates a webhook in this text channel.
/// </summary> /// </summary>
@@ -63,24 +75,27 @@ namespace Discord
/// <param name="avatar">The avatar of the webhook.</param> /// <param name="avatar">The avatar of the webhook.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// The created webhook.
/// A task that represents the asynchronous creation operation. The task result contains the newly created
/// webhook.
/// </returns> /// </returns>
Task<IWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null); Task<IWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets the webhook in this text channel with the provided ID.
/// Gets a webhook available in this text channel.
/// </summary> /// </summary>
/// <param name="id">The ID of the webhook.</param>
/// <param name="id">The identifier of the webhook.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// A webhook associated with the <paramref name="id"/>, or <c>null</c> if not found.
/// A task that represents the asynchronous get operation. The task result contains a webhook associated
/// with the identifier; <c>null</c> if the webhook is not found.
/// </returns> /// </returns>
Task<IWebhook> GetWebhookAsync(ulong id, RequestOptions options = null); Task<IWebhook> GetWebhookAsync(ulong id, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets the webhooks for this text channel.
/// Gets the webhooks available in this text channel.
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a collection of webhooks.
/// A task that represents the asynchronous get operation. The task result contains a read-only collection
/// of webhooks that is available in this channel.
/// </returns> /// </returns>
Task<IReadOnlyCollection<IWebhook>> GetWebhooksAsync(RequestOptions options = null); Task<IReadOnlyCollection<IWebhook>> GetWebhooksAsync(RequestOptions options = null);
} }


+ 14
- 3
src/Discord.Net.Core/Entities/Channels/IVoiceChannel.cs View File

@@ -9,13 +9,20 @@ namespace Discord
public interface IVoiceChannel : INestedChannel, IAudioChannel public interface IVoiceChannel : INestedChannel, IAudioChannel
{ {
/// <summary> /// <summary>
/// Gets the bitrate, in bits per second, clients in this voice channel are requested to use.
/// Gets the bitrate that the clients in this voice channel are requested to use.
/// </summary> /// </summary>
/// <returns>
/// An <see cref="int"/> representing the bitrate (bps) that this voice channel defines and requests the
/// client(s) to use.
/// </returns>
int Bitrate { get; } int Bitrate { get; }
/// <summary> /// <summary>
/// Gets the max amount of users allowed to be connected to this channel at one time, or
/// <c>null</c> if none is set.
/// Gets the max number of users allowed to be connected to this channel at once.
/// </summary> /// </summary>
/// <returns>
/// An <see cref="int"/> representing the maxmimum number of users that are allowed to be connected to this
/// channel at once; <c>null</c> if a limit is not set.
/// </returns>
int? UserLimit { get; } int? UserLimit { get; }


/// <summary> /// <summary>
@@ -23,6 +30,10 @@ namespace Discord
/// </summary> /// </summary>
/// <param name="func">The properties to modify the channel with.</param> /// <param name="func">The properties to modify the channel with.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous modification operation.
/// </returns>
/// <seealso cref="VoiceChannelProperties"/>
Task ModifyAsync(Action<VoiceChannelProperties> func, RequestOptions options = null); Task ModifyAsync(Action<VoiceChannelProperties> func, RequestOptions options = null);
} }
} }

+ 2
- 2
src/Discord.Net.Core/Entities/Channels/ReorderChannelProperties.cs View File

@@ -1,7 +1,7 @@
namespace Discord namespace Discord
{ {
/// <summary> /// <summary>
/// Properties that are used to reorder an <see cref="IGuildChannel"/>.
/// Provides properties that are used to reorder an <see cref="IGuildChannel"/>.
/// </summary> /// </summary>
public class ReorderChannelProperties public class ReorderChannelProperties
{ {
@@ -20,7 +20,7 @@ namespace Discord
/// </returns> /// </returns>
public int Position { get; } public int Position { get; }


/// <summary> Creates a <see cref="ReorderChannelProperties"/> used to reorder a channel. </summary>
/// <summary> Initializes a new instance of the <see cref="ReorderChannelProperties"/> class used to reorder a channel. </summary>
/// <param name="id"> Sets the ID of the channel to apply this position to. </param> /// <param name="id"> Sets the ID of the channel to apply this position to. </param>
/// <param name="position"> Sets the new zero-based position of this channel. </param> /// <param name="position"> Sets the new zero-based position of this channel. </param>
public ReorderChannelProperties(ulong id, int position) public ReorderChannelProperties(ulong id, int position)


+ 2
- 4
src/Discord.Net.Core/Entities/Channels/TextChannelProperties.cs View File

@@ -1,11 +1,9 @@
using System;

namespace Discord namespace Discord
{ {
/// <summary> /// <summary>
/// Properties that are used to modify an <see cref="ITextChannel"/> with the specified changes.
/// Provides properties that are used to modify an <see cref="ITextChannel"/> with the specified changes.
/// </summary> /// </summary>
/// <seealso cref="ITextChannel.ModifyAsync(Action{TextChannelProperties}, RequestOptions)"/>
/// <seealso cref="ITextChannel.ModifyAsync(System.Action{TextChannelProperties}, RequestOptions)"/>
public class TextChannelProperties : GuildChannelProperties public class TextChannelProperties : GuildChannelProperties
{ {
/// <summary> /// <summary>


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

@@ -1,7 +1,7 @@
namespace Discord namespace Discord
{ {
/// <summary> /// <summary>
/// Properties that are used to modify an <see cref="IVoiceChannel" /> with the specified changes.
/// Provides properties that are used to modify an <see cref="IVoiceChannel" /> with the specified changes.
/// </summary> /// </summary>
public class VoiceChannelProperties : GuildChannelProperties public class VoiceChannelProperties : GuildChannelProperties
{ {


+ 4
- 1
src/Discord.Net.Core/Entities/Emotes/Emoji.cs View File

@@ -12,10 +12,13 @@ namespace Discord
/// <summary> /// <summary>
/// Gets the Unicode representation of this emote. /// Gets the Unicode representation of this emote.
/// </summary> /// </summary>
/// <returns>
/// A string that resolves to <see cref="Emoji.Name"/>.
/// </returns>
public override string ToString() => Name; public override string ToString() => Name;


/// <summary> /// <summary>
/// Creates a Unicode emoji.
/// Initializes a new <see cref="Emoji"/> class with the provided Unicode.
/// </summary> /// </summary>
/// <param name="unicode">The pure UTF-8 encoding of an emoji.</param> /// <param name="unicode">The pure UTF-8 encoding of an emoji.</param>
public Emoji(string unicode) public Emoji(string unicode)


+ 11
- 4
src/Discord.Net.Core/Entities/Emotes/Emote.cs View File

@@ -17,14 +17,18 @@ namespace Discord
/// <summary> /// <summary>
/// Gets whether this emote is animated. /// Gets whether this emote is animated.
/// </summary> /// </summary>
/// <returns>
/// A boolean that determines whether or not this emote is an animated one.
/// </returns>
public bool Animated { get; } public bool Animated { get; }
/// <summary>
/// Gets the date when this emote is created.
/// </summary>
/// <inheritdoc />
public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id);
/// <summary> /// <summary>
/// Gets the image URL of this emote. /// Gets the image URL of this emote.
/// </summary> /// </summary>
/// <returns>
/// A string that points to the URL of this emote.
/// </returns>
public string Url => CDN.GetEmojiUrl(Id, Animated); public string Url => CDN.GetEmojiUrl(Id, Animated);


internal Emote(ulong id, string name, bool animated) internal Emote(ulong id, string name, bool animated)
@@ -59,7 +63,7 @@ namespace Discord
} }


/// <summary> Parses an <see cref="Emote"/> from its raw format. </summary> /// <summary> Parses an <see cref="Emote"/> from its raw format. </summary>
/// <param name="text">The raw encoding of an emote; for example, &lt;:dab:277855270321782784&gt;.</param>
/// <param name="text">The raw encoding of an emote (e.g. <c>&lt;:dab:277855270321782784&gt;</c>).</param>
/// <returns>An emote.</returns> /// <returns>An emote.</returns>
/// <exception cref="ArgumentException">Invalid emote format.</exception> /// <exception cref="ArgumentException">Invalid emote format.</exception>
public static Emote Parse(string text) public static Emote Parse(string text)
@@ -99,6 +103,9 @@ namespace Discord
/// <summary> /// <summary>
/// Returns the raw representation of the emote. /// Returns the raw representation of the emote.
/// </summary> /// </summary>
/// <returns>
/// A string representing the raw presentation of the emote (e.g. <c>&lt;:thonkang:282745590985523200&gt;</c>).
/// </returns>
public override string ToString() => $"<{(Animated ? "a" : "")}:{Name}:{Id}>"; public override string ToString() => $"<{(Animated ? "a" : "")}:{Name}:{Id}>";
} }
} }

+ 1
- 1
src/Discord.Net.Core/Entities/Emotes/EmoteProperties.cs View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace Discord namespace Discord
{ {
/// <summary> /// <summary>
/// Properties that are used to modify an <see cref="Emote" /> with the specified changes.
/// Provides properties that are used to modify an <see cref="Emote" /> with the specified changes.
/// </summary> /// </summary>
/// <seealso cref="IGuild.ModifyEmoteAsync"/> /// <seealso cref="IGuild.ModifyEmoteAsync"/>
public class EmoteProperties public class EmoteProperties


+ 11
- 2
src/Discord.Net.Core/Entities/Emotes/GuildEmote.cs View File

@@ -10,16 +10,25 @@ namespace Discord
public class GuildEmote : Emote public class GuildEmote : Emote
{ {
/// <summary> /// <summary>
/// Gets whether this emoji is managed.
/// Gets whether this emoji is managed by an integration.
/// </summary> /// </summary>
/// <returns>
/// A boolean that determines whether or not this emote is managed by a Twitch integration.
/// </returns>
public bool IsManaged { get; } public bool IsManaged { get; }
/// <summary> /// <summary>
/// Gets whether this emoji must be wrapped in colons. /// Gets whether this emoji must be wrapped in colons.
/// </summary> /// </summary>
/// <returns>
/// A boolean that determines whether or not this emote requires the use of colons in chat to be used.
/// </returns>
public bool RequireColons { get; } public bool RequireColons { get; }
/// <summary> /// <summary>
/// Gets the roles this emoji is whitelisted to.
/// Gets the roles that are allowed to use this emoji.
/// </summary> /// </summary>
/// <returns>
/// A read-only list containing snowflake identifiers for roles that are allowed to use this emoji.
/// </returns>
public IReadOnlyList<ulong> RoleIds { get; } public IReadOnlyList<ulong> RoleIds { get; }


internal GuildEmote(ulong id, string name, bool animated, bool isManaged, bool requireColons, IReadOnlyList<ulong> roleIds) : base(id, name, animated) internal GuildEmote(ulong id, string name, bool animated, bool isManaged, bool requireColons, IReadOnlyList<ulong> roleIds) : base(id, name, animated)


+ 3
- 0
src/Discord.Net.Core/Entities/Emotes/IEmote.cs View File

@@ -8,6 +8,9 @@ namespace Discord
/// <summary> /// <summary>
/// Gets the display name or Unicode representation of this emote. /// Gets the display name or Unicode representation of this emote.
/// </summary> /// </summary>
/// <returns>
/// A string representing the display name or the Unicode representation (e.g. <c>🤔</c>) of this emote.
/// </returns>
string Name { get; } string Name { get; }
} }
} }

+ 1
- 1
src/Discord.Net.Core/Entities/Guilds/GuildEmbedProperties.cs View File

@@ -1,7 +1,7 @@
namespace Discord namespace Discord
{ {
/// <summary> /// <summary>
/// Properties that are used to modify the widget of an <see cref="IGuild" /> with the specified changes.
/// Provides properties that are used to modify the widget of an <see cref="IGuild" /> with the specified changes.
/// </summary> /// </summary>
public class GuildEmbedProperties public class GuildEmbedProperties
{ {


+ 1
- 1
src/Discord.Net.Core/Entities/Guilds/GuildIntegrationProperties.cs View File

@@ -1,7 +1,7 @@
namespace Discord namespace Discord
{ {
/// <summary> /// <summary>
/// Properties used to modify an <see cref="IGuildIntegration" /> with the specified changes.
/// Provides properties used to modify an <see cref="IGuildIntegration" /> with the specified changes.
/// </summary> /// </summary>
public class GuildIntegrationProperties public class GuildIntegrationProperties
{ {


+ 1
- 1
src/Discord.Net.Core/Entities/Guilds/GuildProperties.cs View File

@@ -1,7 +1,7 @@
namespace Discord namespace Discord
{ {
/// <summary> /// <summary>
/// Properties that are used to modify an <see cref="IGuild" /> with the specified changes.
/// Provides properties that are used to modify an <see cref="IGuild" /> with the specified changes.
/// </summary> /// </summary>
/// <see cref="IGuild.ModifyAsync"/> /// <see cref="IGuild.ModifyAsync"/>
public class GuildProperties public class GuildProperties


+ 170
- 145
src/Discord.Net.Core/Entities/Guilds/IGuild.cs View File

@@ -22,7 +22,7 @@ namespace Discord
/// automatically moved to the AFK voice channel. /// automatically moved to the AFK voice channel.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// An <see cref="Int32"/> representing the amount of time in seconds for a user to be marked as inactive
/// An <see cref="int"/> representing the amount of time in seconds for a user to be marked as inactive
/// and moved into the AFK voice channel. /// and moved into the AFK voice channel.
/// </returns> /// </returns>
int AFKTimeout { get; } int AFKTimeout { get; }
@@ -98,63 +98,88 @@ namespace Discord
/// Gets the ID of the AFK voice channel for this guild. /// Gets the ID of the AFK voice channel for this guild.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// An <see cref="UInt64" /> representing the snowflake identifier of the AFK voice channel; <c>null</c> if
/// A <see cref="ulong"/> representing the snowflake identifier of the AFK voice channel; <c>null</c> if
/// none is set. /// none is set.
/// </returns> /// </returns>
ulong? AFKChannelId { get; } ulong? AFKChannelId { get; }
/// <summary> /// <summary>
/// Gets the ID of the the default channel for this guild.
/// Gets the ID of the default channel for this guild.
/// </summary> /// </summary>
/// <remarks>
/// This property retrieves the snowflake identifier of the first viewable text channel for this guild.
/// <note type="warning">
/// This channel does not guarantee the user can send message to it, as it only looks for the first viewable
/// text channel.
/// </note>
/// </remarks>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the default text channel; <c>0</c> if
/// none can be found.
/// </returns>
ulong DefaultChannelId { get; } ulong DefaultChannelId { get; }
/// <summary> /// <summary>
/// Gets the ID of the embed channel set in the widget settings of this guild, or <c>null</c> if none is set.
/// Gets the ID of the widget embed channel of this guild.
/// </summary> /// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the embedded channel found within the
/// widget settings of this guild; <c>null</c> if none is set.
/// </returns>
ulong? EmbedChannelId { get; } ulong? EmbedChannelId { get; }
/// <summary> /// <summary>
/// Gets the ID of the channel where randomized welcome messages are sent, or <c>null</c> if none is set.
/// Gets the ID of the channel where randomized welcome messages are sent.
/// </summary> /// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the system channel where randomized
/// welcome messages are sent; <c>null</c> if none is set.
/// </returns>
ulong? SystemChannelId { get; } ulong? SystemChannelId { get; }
/// <summary> /// <summary>
/// Gets the ID of the user that created this guild.
/// Gets the ID of the user that owns this guild.
/// </summary> /// </summary>
/// <returns>
/// A <see cref="ulong"/> representing the snowflake identifier of the user that owns this guild.
/// </returns>
ulong OwnerId { get; } ulong OwnerId { get; }
/// <summary> /// <summary>
/// Gets the ID of the region hosting this guild's voice channels. /// Gets the ID of the region hosting this guild's voice channels.
/// </summary> /// </summary>
/// <returns>
/// A string containing the identifier for the voice region that this guild uses (e.g. <c>eu-central</c>).
/// </returns>
string VoiceRegionId { get; } string VoiceRegionId { get; }
/// <summary> /// <summary>
/// Gets the <see cref="IAudioClient" /> currently associated with this guild.
/// Gets the <see cref="IAudioClient"/> currently associated with this guild.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// <see cref="IAudioClient" /> currently associated with this guild.
/// An <see cref="IAudioClient"/> currently associated with this guild.
/// </returns> /// </returns>
IAudioClient AudioClient { get; } IAudioClient AudioClient { get; }
/// <summary> /// <summary>
/// Gets the built-in role containing all users in this guild. /// Gets the built-in role containing all users in this guild.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// Built-in role that represents an @everyone role in this guild.
/// A role object that represents an <c>@everyone</c> role in this guild.
/// </returns> /// </returns>
IRole EveryoneRole { get; } IRole EveryoneRole { get; }
/// <summary> /// <summary>
/// Gets a collection of all custom emotes for this guild. /// Gets a collection of all custom emotes for this guild.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A collection of all custom emotes for this guild.
/// A read-only collection of all custom emotes for this guild.
/// </returns> /// </returns>
IReadOnlyCollection<GuildEmote> Emotes { get; } IReadOnlyCollection<GuildEmote> Emotes { get; }
/// <summary> /// <summary>
/// Gets a collection of all extra features added to this guild. /// Gets a collection of all extra features added to this guild.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A collection of enabled features in this guild.
/// A read-only collection of enabled features in this guild.
/// </returns> /// </returns>
IReadOnlyCollection<string> Features { get; } IReadOnlyCollection<string> Features { get; }
/// <summary> /// <summary>
/// Gets a collection of all roles in this guild. /// Gets a collection of all roles in this guild.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A collection of roles found within this guild.
/// A read-only collection of roles found within this guild.
/// </returns> /// </returns>
IReadOnlyCollection<IRole> Roles { get; } IReadOnlyCollection<IRole> Roles { get; }


@@ -164,7 +189,7 @@ namespace Discord
/// <param name="func">The delegate containing the properties to modify the guild with.</param> /// <param name="func">The delegate containing the properties to modify the guild with.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task that represents the asynchronous modification operation.
/// </returns> /// </returns>
Task ModifyAsync(Action<GuildProperties> func, RequestOptions options = null); Task ModifyAsync(Action<GuildProperties> func, RequestOptions options = null);
/// <summary> /// <summary>
@@ -173,7 +198,7 @@ namespace Discord
/// <param name="func">The delegate containing the properties to modify the guild widget with.</param> /// <param name="func">The delegate containing the properties to modify the guild widget with.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task that represents the asynchronous modification operation.
/// </returns> /// </returns>
Task ModifyEmbedAsync(Action<GuildEmbedProperties> func, RequestOptions options = null); Task ModifyEmbedAsync(Action<GuildEmbedProperties> func, RequestOptions options = null);
/// <summary> /// <summary>
@@ -182,7 +207,7 @@ namespace Discord
/// <param name="args">The properties used to modify the channel positions with.</param> /// <param name="args">The properties used to modify the channel positions with.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task that represents the asynchronous reorder operation.
/// </returns> /// </returns>
Task ReorderChannelsAsync(IEnumerable<ReorderChannelProperties> args, RequestOptions options = null); Task ReorderChannelsAsync(IEnumerable<ReorderChannelProperties> args, RequestOptions options = null);
/// <summary> /// <summary>
@@ -191,28 +216,32 @@ namespace Discord
/// <param name="args">The properties used to modify the role positions with.</param> /// <param name="args">The properties used to modify the role positions with.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task that represents the asynchronous reorder operation.
/// </returns> /// </returns>
Task ReorderRolesAsync(IEnumerable<ReorderRoleProperties> args, RequestOptions options = null); Task ReorderRolesAsync(IEnumerable<ReorderRoleProperties> args, RequestOptions options = null);
/// <summary> /// <summary>
/// Leaves this guild. /// Leaves this guild.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This method will make the currently logged-in user leave the guild. If the user is the owner, use
/// <see cref="IDeletable.DeleteAsync" /> instead.
/// This method will make the currently logged-in user leave the guild.
/// <note>
/// If the user is the owner of this guild, use <see cref="IDeletable.DeleteAsync"/> instead.
/// </note>
/// </remarks> /// </remarks>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task that represents the asynchronous leave operation.
/// </returns> /// </returns>
Task LeaveAsync(RequestOptions options = null); Task LeaveAsync(RequestOptions options = null);


/// <summary> /// <summary>
/// Gets a collection of all users banned on this guild.
/// Gets a collection of all users banned in this guild.
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a collection of banned users with reasons.
/// A task that represents the asynchronous get operation. The task result contains a read-only collection of
/// ban objects that this guild currently possesses, with each object containing the user banned and reason
/// behind the ban.
/// </returns> /// </returns>
Task<IReadOnlyCollection<IBan>> GetBansAsync(RequestOptions options = null); Task<IReadOnlyCollection<IBan>> GetBansAsync(RequestOptions options = null);
/// <summary> /// <summary>
@@ -221,8 +250,8 @@ namespace Discord
/// <param name="user">The banned user.</param> /// <param name="user">The banned user.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the ban object, which contains the user information and the
/// reason for the ban; <c>null</c> if the ban entry cannot be found.
/// A task that represents the asynchronous get operation. The task result contains a ban object, which
/// contains the user information and the reason for the ban; <c>null</c> if the ban entry cannot be found.
/// </returns> /// </returns>
Task<IBan> GetBanAsync(IUser user, RequestOptions options = null); Task<IBan> GetBanAsync(IUser user, RequestOptions options = null);
/// <summary> /// <summary>
@@ -231,216 +260,197 @@ namespace Discord
/// <param name="userId">The snowflake identifier for the banned user.</param> /// <param name="userId">The snowflake identifier for the banned user.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the ban object, which contains the user information and the
/// reason for the ban; <c>null</c> if the ban entry cannot be found.
/// A task that represents the asynchronous get operation. The task result contains a ban object, which
/// contains the user information and the reason for the ban; <c>null</c> if the ban entry cannot be found.
/// </returns> /// </returns>
Task<IBan> GetBanAsync(ulong userId, RequestOptions options = null); Task<IBan> GetBanAsync(ulong userId, RequestOptions options = null);
/// <summary> /// <summary>
/// Bans the user from this guild and optionally prunes their recent messages. /// Bans the user from this guild and optionally prunes their recent messages.
/// </summary> /// </summary>
/// <param name="user">The user to ban.</param> /// <param name="user">The user to ban.</param>
/// <param name="pruneDays">
/// The number of days to remove messages from this <paramref name="user" /> for - must be between [0, 7].
/// </param>
/// <param name="pruneDays">The number of days to remove messages from this user for, and this number must be between [0, 7].</param>
/// <param name="reason">The reason of the ban to be written in the audit log.</param> /// <param name="reason">The reason of the ban to be written in the audit log.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <exception cref="ArgumentException"><paramref name="pruneDays" /> is not between 0 to 7.</exception>
/// <exception cref="ArgumentException"><paramref name="pruneDays"/> is not between 0 to 7.</exception>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task that represents the asynchronous add operation for the ban.
/// </returns> /// </returns>
Task AddBanAsync(IUser user, int pruneDays = 0, string reason = null, RequestOptions options = null); Task AddBanAsync(IUser user, int pruneDays = 0, string reason = null, RequestOptions options = null);
/// <summary> /// <summary>
/// Bans the user from this guild and optionally prunes their recent messages. /// Bans the user from this guild and optionally prunes their recent messages.
/// </summary> /// </summary>
/// <param name="userId">The snowflake ID of the user to ban.</param> /// <param name="userId">The snowflake ID of the user to ban.</param>
/// <param name="pruneDays">
/// The number of days to remove messages from this user for - must be between [0, 7].
/// </param>
/// <param name="pruneDays">The number of days to remove messages from this user for, and this number must be between [0, 7].</param>
/// <param name="reason">The reason of the ban to be written in the audit log.</param> /// <param name="reason">The reason of the ban to be written in the audit log.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <exception cref="ArgumentException"><paramref name="pruneDays" /> is not between 0 to 7.</exception>
/// <exception cref="ArgumentException"><paramref name="pruneDays"/> is not between 0 to 7.</exception>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task that represents the asynchronous add operation for the ban.
/// </returns> /// </returns>
Task AddBanAsync(ulong userId, int pruneDays = 0, string reason = null, RequestOptions options = null); Task AddBanAsync(ulong userId, int pruneDays = 0, string reason = null, RequestOptions options = null);
/// <summary> /// <summary>
/// Unbans the provided user if they are currently banned.
/// Unbans the user if they are currently banned.
/// </summary> /// </summary>
/// <param name="user">The user to be unbanned.</param> /// <param name="user">The user to be unbanned.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task that represents the asynchronous removal operation for the ban.
/// </returns> /// </returns>
Task RemoveBanAsync(IUser user, RequestOptions options = null); Task RemoveBanAsync(IUser user, RequestOptions options = null);
/// <summary> /// <summary>
/// Unbans the provided user ID if it is currently banned.
/// Unbans the user if they are currently banned.
/// </summary> /// </summary>
/// <param name="userId">The snowflake ID of the user to be unbanned.</param>
/// <param name="userId">The snowflake identifier of the user to be unbanned.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task that represents the asynchronous removal operation for the ban.
/// </returns> /// </returns>
Task RemoveBanAsync(ulong userId, RequestOptions options = null); Task RemoveBanAsync(ulong userId, RequestOptions options = null);


/// <summary> /// <summary>
/// Gets a collection of all channels in this guild. /// Gets a collection of all channels in this guild.
/// </summary> /// </summary>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a collection of generic channels found within this guild.
/// A task that represents the asynchronous get operation. The task result contains a read-only collection of
/// generic channels found within this guild.
/// </returns> /// </returns>
Task<IReadOnlyCollection<IGuildChannel>> GetChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IReadOnlyCollection<IGuildChannel>> GetChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets the channel in this guild with the provided ID.
/// Gets a channel in this guild.
/// </summary> /// </summary>
/// <param name="id">The channel ID.</param>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="id">The snowflake identifier for the channel.</param>
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the generic channel with the specified ID, or
/// <c>null</c> if none is found.
/// A task that represents the asynchronous get operation. The task result contains the generic channel
/// associated with the specified <paramref name="id"/>; <c>null</c> if none is found.
/// </returns> /// </returns>
Task<IGuildChannel> GetChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IGuildChannel> GetChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets a collection of all text channels in this guild. /// Gets a collection of all text channels in this guild.
/// </summary> /// </summary>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a collection of text channels found within this guild.
/// A task that represents the asynchronous get operation. The task result contains a read-only collection of
/// message channels found within this guild.
/// </returns> /// </returns>
Task<IReadOnlyCollection<ITextChannel>> GetTextChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IReadOnlyCollection<ITextChannel>> GetTextChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets a text channel in this guild with the provided ID, or <c>null</c> if not found.
/// Gets a text channel in this guild.
/// </summary> /// </summary>
/// <param name="id">The text channel ID.</param>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="id">The snowflake identifier for the text channel.</param>
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the text channel with the specified ID, or
/// <c>null</c> if none is found.
/// A task that represents the asynchronous get operation. The task result contains the text channel
/// associated with the specified <paramref name="id"/>; <c>null</c> if none is found.
/// </returns> /// </returns>
Task<ITextChannel> GetTextChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<ITextChannel> GetTextChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets a collection of all voice channels in this guild. /// Gets a collection of all voice channels in this guild.
/// </summary> /// </summary>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a collection of voice channels found within this guild.
/// A task that represents the asynchronous get operation. The task result contains a read-only collection of
/// voice channels found within this guild.
/// </returns> /// </returns>
Task<IReadOnlyCollection<IVoiceChannel>> GetVoiceChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IReadOnlyCollection<IVoiceChannel>> GetVoiceChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets a collection of all category channels in this guild. /// Gets a collection of all category channels in this guild.
/// </summary> /// </summary>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a collection of category channels found within this guild.
/// A task that represents the asynchronous get operation. The task result contains a read-only collection of
/// category channels found within this guild.
/// </returns> /// </returns>
Task<IReadOnlyCollection<ICategoryChannel>> GetCategoriesAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IReadOnlyCollection<ICategoryChannel>> GetCategoriesAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets the voice channel in this guild with the provided ID.
/// Gets a voice channel in this guild.
/// </summary> /// </summary>
/// <param name="id">The text channel ID.</param>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="id">The snowflake identifier for the voice channel.</param>
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the voice channel with the specified ID, or
/// <c>null</c> if none is found.
/// A task that represents the asynchronous get operation. The task result contains the voice channel associated
/// with the specified <paramref name="id"/>; <c>null</c> if none is found.
/// </returns> /// </returns>
Task<IVoiceChannel> GetVoiceChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IVoiceChannel> GetVoiceChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets the AFK voice channel in this guild. /// Gets the AFK voice channel in this guild.
/// </summary> /// </summary>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the AFK voice channel set within this guild, or
/// <c>null</c> if none is set.
/// A task that represents the asynchronous get operation. The task result contains the voice channel that the
/// AFK users will be moved to after they have idled for too long; <c>null</c> if none is set.
/// </returns> /// </returns>
Task<IVoiceChannel> GetAFKChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IVoiceChannel> GetAFKChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets the default system text channel in this guild with the provided ID.
/// Gets the system channel where randomized welcome messages are sent in this guild.
/// </summary> /// </summary>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the system channel within this guild, or
/// <c>null</c> if none is set.
/// A task that represents the asynchronous get operation. The task result contains the text channel where
/// randomized welcome messages will be sent to; <c>null</c> if none is set.
/// </returns> /// </returns>
Task<ITextChannel> GetSystemChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<ITextChannel> GetSystemChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets the top viewable text channel in this guild with the provided ID.
/// Gets the first viewable text channel in this guild.
/// </summary> /// </summary>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the first viewable text channel in this guild, or
/// <c>null</c> if none is found.
/// A task that represents the asynchronous get operation. The task result contains the first viewable text
/// channel in this guild; <c>null</c> if none is found.
/// </returns> /// </returns>
Task<ITextChannel> GetDefaultChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<ITextChannel> GetDefaultChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets the embed channel (i.e. the channel set in the guild's widget settings) in this guild. /// Gets the embed channel (i.e. the channel set in the guild's widget settings) in this guild.
/// </summary> /// </summary>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the embed channel set within the server's widget settings, or
/// <c>null</c> if none is set.
/// A task that represents the asynchronous get operation. The task result contains the embed channel set
/// within the server's widget settings; <c>null</c> if none is set.
/// </returns> /// </returns>
Task<IGuildChannel> GetEmbedChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IGuildChannel> GetEmbedChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);


/// <summary> /// <summary>
/// Creates a new text channel.
/// Creates a new text channel in this guild.
/// </summary> /// </summary>
/// <param name="name">The new name for the text channel.</param> /// <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> /// <param name="func">The delegate containing the properties to be applied to the channel upon its creation.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the newly created text channel.
/// A task that represents the asynchronous creation operation. The task result contains the newly created
/// text channel.
/// </returns> /// </returns>
Task<ITextChannel> CreateTextChannelAsync(string name, Action<TextChannelProperties> func = null, RequestOptions options = null); Task<ITextChannel> CreateTextChannelAsync(string name, Action<TextChannelProperties> func = null, RequestOptions options = null);
/// <summary> /// <summary>
/// Creates a new voice channel.
/// Creates a new voice channel in this guild.
/// </summary> /// </summary>
/// <param name="name">The new name for the voice channel.</param> /// <param name="name">The new name for the voice channel.</param>
/// <param name="func">The delegate containing the properties to be applied to the channel upon its creation.</param> /// <param name="func">The delegate containing the properties to be applied to the channel upon its creation.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the newly created voice channel.
/// A task that represents the asynchronous creation operation. The task result contains the newly created
/// voice channel.
/// </returns> /// </returns>
Task<IVoiceChannel> CreateVoiceChannelAsync(string name, Action<VoiceChannelProperties> func = null, RequestOptions options = null); Task<IVoiceChannel> CreateVoiceChannelAsync(string name, Action<VoiceChannelProperties> func = null, RequestOptions options = null);
/// <summary> /// <summary>
/// Creates a new channel category.
/// Creates a new channel category in this guild.
/// </summary> /// </summary>
/// <param name="name">The new name for the category.</param> /// <param name="name">The new name for the category.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the newly created category channel.
/// A task that represents the asynchronous creation operation. The task result contains the newly created
/// category channel.
/// </returns> /// </returns>
Task<ICategoryChannel> CreateCategoryAsync(string name, RequestOptions options = null); Task<ICategoryChannel> CreateCategoryAsync(string name, RequestOptions options = null);


@@ -448,11 +458,12 @@ namespace Discord
Task<IGuildIntegration> CreateIntegrationAsync(ulong id, string type, RequestOptions options = null); Task<IGuildIntegration> CreateIntegrationAsync(ulong id, string type, RequestOptions options = null);


/// <summary> /// <summary>
/// Gets a collection of all invites to this guild.
/// Gets a collection of all invites in this guild.
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a collection of invites found within this guild.
/// A task that represents the asynchronous get operation. The task result contains a read-only collection of
/// invite metadata, each representing information for an invite found within this guild.
/// </returns> /// </returns>
Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null); Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null);
/// <summary> /// <summary>
@@ -460,17 +471,17 @@ namespace Discord
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the partial metadata of the vanity invite found within
/// this guild.
/// A task that represents the asynchronous get operation. The task result contains the partial metadata of
/// the vanity invite found within this guild; <c>null</c> if none is found.
/// </returns> /// </returns>
Task<IInviteMetadata> GetVanityInviteAsync(RequestOptions options = null); Task<IInviteMetadata> GetVanityInviteAsync(RequestOptions options = null);


/// <summary> /// <summary>
/// Gets a role in this guild. /// Gets a role in this guild.
/// </summary> /// </summary>
/// <param name="id">The role ID.</param>
/// <param name="id">The snowflake identifier for the role.</param>
/// <returns> /// <returns>
/// A role that matches the provided snowflake identifier; <c>null</c> if none is found.
/// A role that is associated with the specified <paramref name="id"/>; <c>null</c> if none is found.
/// </returns> /// </returns>
IRole GetRole(ulong id); IRole GetRole(ulong id);
/// <summary> /// <summary>
@@ -482,7 +493,8 @@ namespace Discord
/// <param name="isHoisted">Whether the role is separated from others on the sidebar.</param> /// <param name="isHoisted">Whether the role is separated from others on the sidebar.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the newly crated role.
/// A task that represents the asynchronous creation operation. The task result contains the newly created
/// role.
/// </returns> /// </returns>
Task<IRole> CreateRoleAsync(string name, GuildPermissions? permissions = null, Color? color = null, bool isHoisted = false, RequestOptions options = null); Task<IRole> CreateRoleAsync(string name, GuildPermissions? permissions = null, Color? color = null, bool isHoisted = false, RequestOptions options = null);


@@ -492,27 +504,33 @@ namespace Discord
/// <remarks> /// <remarks>
/// This method retrieves all users found within this guild. /// This method retrieves all users found within this guild.
/// <note> /// <note>
/// This may return an incomplete list on the WebSocket implementation.
/// This may return an incomplete collection in the WebSocket implementation due to how Discord does not
/// send a complete user list for large guilds.
/// </note> /// </note>
/// </remarks> /// </remarks>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a collection of users found within this guild.
/// A task that represents the asynchronous get operation. The task result contains a collection of guild
/// users found within this guild.
/// </returns> /// </returns>
Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
/// Gets a user found in this guild.
/// Gets a user from this guild.
/// </summary> /// </summary>
/// <param name="id">The user ID to search for.</param>
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from
/// cache.</param>
/// <remarks>
/// This method retrieves a user found within this guild.
/// <note>
/// This may return <c>null</c> in the WebSocket implementation due to incomplete user collection in
/// large guilds.
/// </note>
/// </remarks>
/// <param name="id">The snowflake identifier of the user.</param>
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the guild user with the specified ID; <c>null</c> if none is
/// found.
/// A task that represents the asynchronous get operation. The task result contains the guild user
/// associated with the specified <paramref name="id"/>; <c>null</c> if none is found.
/// </returns> /// </returns>
Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
@@ -521,7 +539,8 @@ namespace Discord
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param> /// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the currently logged-in user within this guild.
/// A task that represents the asynchronous get operation. The task result contains the currently logged-in
/// user within this guild.
/// </returns> /// </returns>
Task<IGuildUser> GetCurrentUserAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IGuildUser> GetCurrentUserAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
@@ -530,29 +549,34 @@ namespace Discord
/// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param> /// <param name="mode">The <see cref="CacheMode"/> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the owner of this guild.
/// A task that represents the asynchronous get operation. The task result contains the owner of this guild.
/// </returns> /// </returns>
Task<IGuildUser> GetOwnerAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IGuildUser> GetOwnerAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
/// <summary> /// <summary>
/// Downloads all users for this guild if the current list is incomplete. /// Downloads all users for this guild if the current list is incomplete.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task that represents the asynchronous download operation.
/// </returns> /// </returns>
Task DownloadUsersAsync(); Task DownloadUsersAsync();
/// <summary> /// <summary>
/// Prunes inactive users. /// Prunes inactive users.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This method removes all users that have not logged on in the provided number of days or, if
/// <paramref name="simulate"/> is <c>true</c>, returns the number of users that would be removed.
/// <para>
/// This method removes all users that have not logged on in the provided number of <paramref name="days"/>.
/// </para>
/// <para>
/// If <paramref name="simulate" /> is <c>true</c>, this method will only return the number of users that
/// would be removed without kicking the users.
/// </para>
/// </remarks> /// </remarks>
/// <param name="days">The number of days required for the users to be kicked.</param> /// <param name="days">The number of days required for the users to be kicked.</param>
/// <param name="simulate">Whether this prune action is a simulation.</param> /// <param name="simulate">Whether this prune action is a simulation.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task" /> containing the number of users to be or has been removed from this
/// guild.
/// A task that represents the asynchronous prune operation. The task result contains the number of users to
/// be or has been removed from this guild.
/// </returns> /// </returns>
Task<int> PruneUsersAsync(int days = 30, bool simulate = false, RequestOptions options = null); Task<int> PruneUsersAsync(int days = 30, bool simulate = false, RequestOptions options = null);


@@ -560,24 +584,23 @@ namespace Discord
/// Gets the specified number of audit log entries for this guild. /// Gets the specified number of audit log entries for this guild.
/// </summary> /// </summary>
/// <param name="limit">The number of audit log entries to fetch.</param> /// <param name="limit">The number of audit log entries to fetch.</param>
/// <param name="mode">
/// The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.
/// </param>
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a collection of requested audit log entries.
/// A task that represents the asynchronous get operation. The task result contains a read-only collection
/// of the requested audit log entries.
/// </returns> /// </returns>
Task<IReadOnlyCollection<IAuditLogEntry>> GetAuditLogAsync(int limit = DiscordConfig.MaxAuditLogEntriesPerBatch,
Task<IReadOnlyCollection<IAuditLogEntry>> GetAuditLogsAsync(int limit = DiscordConfig.MaxAuditLogEntriesPerBatch,
CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);


/// <summary> /// <summary>
/// Gets a webhook found within this guild. /// Gets a webhook found within this guild.
/// </summary> /// </summary>
/// <param name="id">The webhook ID.</param>
/// <param name="id">The identifier for the webhook.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the webhook with the specified ID; <c>null</c> if none is
/// found.
/// A task that represents the asynchronous get operation. The task result contains the webhook with the
/// specified <paramref name="id"/>; <c>null</c> if none is found.
/// </returns> /// </returns>
Task<IWebhook> GetWebhookAsync(ulong id, RequestOptions options = null); Task<IWebhook> GetWebhookAsync(ulong id, RequestOptions options = null);
/// <summary> /// <summary>
@@ -585,18 +608,19 @@ namespace Discord
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a collection of webhooks found within the guild.
/// A task that represents the asynchronous get operation. The task result contains a read-only collection
/// of webhooks found within the guild.
/// </returns> /// </returns>
Task<IReadOnlyCollection<IWebhook>> GetWebhooksAsync(RequestOptions options = null); Task<IReadOnlyCollection<IWebhook>> GetWebhooksAsync(RequestOptions options = null);


/// <summary> /// <summary>
/// Gets a specific emote from this guild. /// Gets a specific emote from this guild.
/// </summary> /// </summary>
/// <param name="id">The guild emote ID.</param>
/// <param name="id">The snowflake identifier for the guild emote.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the emote found with the specified ID; <c>null</c> if none is
/// found.
/// A task that represents the asynchronous get operation. The task result contains the emote found with the
/// specified <paramref name="id"/>; <c>null</c> if none is found.
/// </returns> /// </returns>
Task<GuildEmote> GetEmoteAsync(ulong id, RequestOptions options = null); Task<GuildEmote> GetEmoteAsync(ulong id, RequestOptions options = null);
/// <summary> /// <summary>
@@ -607,7 +631,7 @@ namespace Discord
/// <param name="roles">The roles to limit the emote usage to.</param> /// <param name="roles">The roles to limit the emote usage to.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the created emote.
/// A task that represents the asynchronous creation operation. The task result contains the created emote.
/// </returns> /// </returns>
Task<GuildEmote> CreateEmoteAsync(string name, Image image, Optional<IEnumerable<IRole>> roles = default(Optional<IEnumerable<IRole>>), RequestOptions options = null); Task<GuildEmote> CreateEmoteAsync(string name, Image image, Optional<IEnumerable<IRole>> roles = default(Optional<IEnumerable<IRole>>), RequestOptions options = null);


@@ -618,7 +642,8 @@ namespace Discord
/// <param name="func">The delegate containing the properties to modify the emote with.</param> /// <param name="func">The delegate containing the properties to modify the emote with.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing the newly modified emote.
/// A task that represents the asynchronous modification operation. The task result contains the modified
/// emote.
/// </returns> /// </returns>
Task<GuildEmote> ModifyEmoteAsync(GuildEmote emote, Action<EmoteProperties> func, RequestOptions options = null); Task<GuildEmote> ModifyEmoteAsync(GuildEmote emote, Action<EmoteProperties> func, RequestOptions options = null);
/// <summary> /// <summary>
@@ -627,7 +652,7 @@ namespace Discord
/// <param name="emote">The emote to delete.</param> /// <param name="emote">The emote to delete.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/>.
/// A task that represents the asynchronous removal operation.
/// </returns> /// </returns>
Task DeleteEmoteAsync(GuildEmote emote, RequestOptions options = null); Task DeleteEmoteAsync(GuildEmote emote, RequestOptions options = null);
} }


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

@@ -19,7 +19,7 @@ namespace Discord
string[] RPCOrigins { get; } string[] RPCOrigins { get; }
ulong Flags { get; } ulong Flags { get; }
/// <summary> /// <summary>
/// Gets the icon URL of the application.
/// Gets the icon URL of the application.
/// </summary> /// </summary>
string IconUrl { get; } string IconUrl { get; }




+ 6
- 1
src/Discord.Net.Core/Entities/ISnowflakeEntity.cs View File

@@ -5,7 +5,12 @@ namespace Discord
/// <summary> Represents a Discord snowflake entity. </summary> /// <summary> Represents a Discord snowflake entity. </summary>
public interface ISnowflakeEntity : IEntity<ulong> public interface ISnowflakeEntity : IEntity<ulong>
{ {
/// <summary> Gets when the snowflake is created. </summary>
/// <summary>
/// Gets when the snowflake is created.
/// </summary>
/// <returns>
/// A <see cref="DateTimeOffset"/> representing when the entity was first created.
/// </returns>
DateTimeOffset CreatedAt { get; } DateTimeOffset CreatedAt { get; }
} }
} }

+ 27
- 6
src/Discord.Net.Core/Entities/Messages/EmbedFooter.cs View File

@@ -6,12 +6,27 @@ namespace Discord
[DebuggerDisplay("{DebuggerDisplay,nq}")] [DebuggerDisplay("{DebuggerDisplay,nq}")]
public struct EmbedFooter public struct EmbedFooter
{ {
/// <summary> Gets the text of the footer.</summary>
public string Text { get; internal set; }
/// <summary> Gets the icon URL of the footer.</summary>
public string IconUrl { get; internal set; }
/// <summary> Gets the proxified icon URL of the footer.</summary>
public string ProxyUrl { get; internal set; }
/// <summary>
/// Gets the text of the footer field.
/// </summary>
/// <returns>
/// A string containing the text of the footer field.
/// </returns>
public string Text { get; }
/// <summary>
/// Gets the URL of the footer icon.
/// </summary>
/// <returns>
/// A string containing the URL of the footer icon.
/// </returns>
public string IconUrl { get; }
/// <summary>
/// Gets the proxied URL of the footer icon link.
/// </summary>
/// <returns>
/// A string containing the proxied URL of the footer icon.
/// </returns>
public string ProxyUrl { get; }


internal EmbedFooter(string text, string iconUrl, string proxyUrl) internal EmbedFooter(string text, string iconUrl, string proxyUrl)
{ {
@@ -21,6 +36,12 @@ namespace Discord
} }


private string DebuggerDisplay => $"{Text} ({IconUrl})"; private string DebuggerDisplay => $"{Text} ({IconUrl})";
/// <summary>
/// Gets the text of the footer field.
/// </summary>
/// <returns>
/// A string that resolves to <see cref="Discord.EmbedFooter.Text"/>.
/// </returns>
public override string ToString() => Text; public override string ToString() => Text;
} }
} }

+ 33
- 5
src/Discord.Net.Core/Entities/Messages/EmbedImage.cs View File

@@ -6,13 +6,35 @@ namespace Discord
[DebuggerDisplay("{DebuggerDisplay,nq}")] [DebuggerDisplay("{DebuggerDisplay,nq}")]
public struct EmbedImage public struct EmbedImage
{ {
/// <summary> Gets the URL of the image.</summary>
/// <summary>
/// Gets the URL of the image.
/// </summary>
/// <returns>
/// A string containing the URL of the image.
/// </returns>
public string Url { get; } public string Url { get; }
/// <summary> Gets the proxified URL of the image.</summary>
/// <summary>
/// Gets a proxied URL of this image.
/// </summary>
/// <returns>
/// A string containing the proxied URL of this image.
/// </returns>
public string ProxyUrl { get; } public string ProxyUrl { get; }
/// <summary> Gets the height of the image if any is set. </summary>
/// <summary>
/// Gets the height of this image.
/// </summary>
/// <returns>
/// A <see cref="int"/> representing the height of this image if it can be retrieved; otherwise
/// <c>null</c>.
/// </returns>
public int? Height { get; } public int? Height { get; }
/// <summary> Gets the width of the image if any is set. </summary>
/// <summary>
/// Gets the width of this image.
/// </summary>
/// <returns>
/// A <see cref="int"/> representing the width of this image if it can be retrieved; otherwise
/// <c>null</c>.
/// </returns>
public int? Width { get; } public int? Width { get; }


internal EmbedImage(string url, string proxyUrl, int? height, int? width) internal EmbedImage(string url, string proxyUrl, int? height, int? width)
@@ -24,6 +46,12 @@ namespace Discord
} }


private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})"; private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})";
public override string ToString() => Url.ToString();
/// <summary>
/// Gets the URL of the thumbnail.
/// </summary>
/// <returns>
/// A string that resolves to <see cref="Discord.EmbedImage.Url"/> .
/// </returns>
public override string ToString() => Url;
} }
} }

+ 18
- 2
src/Discord.Net.Core/Entities/Messages/EmbedProvider.cs View File

@@ -6,9 +6,19 @@ namespace Discord
[DebuggerDisplay("{DebuggerDisplay,nq}")] [DebuggerDisplay("{DebuggerDisplay,nq}")]
public struct EmbedProvider public struct EmbedProvider
{ {
/// <summary> Gets the name of the provider.</summary>
/// <summary>
/// Gets the name of the provider.
/// </summary>
/// <returns>
/// A string representing the name of the provider.
/// </returns>
public string Name { get; } public string Name { get; }
/// <summary> Gets the URL of the provider.</summary>
/// <summary>
/// Gets the URL of the provider.
/// </summary>
/// <returns>
/// A string representing the link to the provider.
/// </returns>
public string Url { get; } public string Url { get; }


internal EmbedProvider(string name, string url) internal EmbedProvider(string name, string url)
@@ -18,6 +28,12 @@ namespace Discord
} }


private string DebuggerDisplay => $"{Name} ({Url})"; private string DebuggerDisplay => $"{Name} ({Url})";
/// <summary>
/// Gets the name of the provider.
/// </summary>
/// <returns>
/// A string that resolves to <see cref="Discord.EmbedProvider.Name" />.
/// </returns>
public override string ToString() => Name; public override string ToString() => Name;
} }
} }

+ 33
- 5
src/Discord.Net.Core/Entities/Messages/EmbedThumbnail.cs View File

@@ -6,13 +6,35 @@ namespace Discord
[DebuggerDisplay("{DebuggerDisplay,nq}")] [DebuggerDisplay("{DebuggerDisplay,nq}")]
public struct EmbedThumbnail public struct EmbedThumbnail
{ {
/// <summary> Gets the URL of the thumbnail.</summary>
/// <summary>
/// Gets the URL of the thumbnail.
/// </summary>
/// <returns>
/// A string containing the URL of the thumbnail.
/// </returns>
public string Url { get; } public string Url { get; }
/// <summary> Gets the proxified URL of the thumbnail.</summary>
/// <summary>
/// Gets a proxied URL of this thumbnail.
/// </summary>
/// <returns>
/// A string containing the proxied URL of this thumbnail.
/// </returns>
public string ProxyUrl { get; } public string ProxyUrl { get; }
/// <summary> Gets the height of the thumbnail if any is set. </summary>
/// <summary>
/// Gets the height of this thumbnail.
/// </summary>
/// <returns>
/// A <see cref="int"/> representing the height of this thumbnail if it can be retrieved; otherwise
/// <c>null</c>.
/// </returns>
public int? Height { get; } public int? Height { get; }
/// <summary> Gets the width of the thumbnail if any is set. </summary>
/// <summary>
/// Gets the width of this thumbnail.
/// </summary>
/// <returns>
/// A <see cref="int"/> representing the width of this thumbnail if it can be retrieved; otherwise
/// <c>null</c>.
/// </returns>
public int? Width { get; } public int? Width { get; }


internal EmbedThumbnail(string url, string proxyUrl, int? height, int? width) internal EmbedThumbnail(string url, string proxyUrl, int? height, int? width)
@@ -24,6 +46,12 @@ namespace Discord
} }


private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})"; private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})";
public override string ToString() => Url.ToString();
/// <summary>
/// Gets the URL of the thumbnail.
/// </summary>
/// <returns>
/// A string that resolves to <see cref="Discord.EmbedThumbnail.Url" />.
/// </returns>
public override string ToString() => Url;
} }
} }

+ 49
- 1
src/Discord.Net.Core/Entities/Messages/IUserMessage.cs View File

@@ -12,32 +12,75 @@ namespace Discord
/// <summary> /// <summary>
/// Modifies this message. /// Modifies this message.
/// </summary> /// </summary>
/// <example>
/// <code language="cs">
/// await msg.ModifyAsync(x =&gt; x.Content = "Hello World!");
/// </code>
/// </example>
/// <param name="func">A delegate containing the properties to modify the message with.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// An awaitable <see cref="Task"/>.
/// </returns>
Task ModifyAsync(Action<MessageProperties> func, RequestOptions options = null); Task ModifyAsync(Action<MessageProperties> func, RequestOptions options = null);
/// <summary> /// <summary>
/// Adds this message to its channel's pinned messages. /// Adds this message to its channel's pinned messages.
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// An awaitable <see cref="Task"/>.
/// </returns>
Task PinAsync(RequestOptions options = null); Task PinAsync(RequestOptions options = null);
/// <summary> /// <summary>
/// Removes this message from its channel's pinned messages. /// Removes this message from its channel's pinned messages.
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// An awaitable <see cref="Task"/>.
/// </returns>
Task UnpinAsync(RequestOptions options = null); Task UnpinAsync(RequestOptions options = null);


/// <summary> /// <summary>
/// Returns all reactions included in this message.
/// Gets all reactions included in this message.
/// </summary> /// </summary>
IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions { get; } IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions { get; }


/// <summary> /// <summary>
/// Adds a reaction to this message. /// Adds a reaction to this message.
/// </summary> /// </summary>
/// <example>
/// <code language="cs">
/// await msg.AddReactionAsync(new Emoji("\U0001f495"));
/// </code>
/// </example>
/// <param name="emote">The emoji used to react to this message.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// An awaitable <see cref="Task"/>.
/// </returns>
Task AddReactionAsync(IEmote emote, RequestOptions options = null); Task AddReactionAsync(IEmote emote, RequestOptions options = null);
/// <summary> /// <summary>
/// Removes a reaction from message. /// Removes a reaction from message.
/// </summary> /// </summary>
/// <example>
/// <code language="cs">
/// await msg.RemoveReactionAsync(new Emoji("\U0001f495"), msg.Author);
/// </code>
/// </example>
/// <param name="emote">The emoji used to react to this message.</param>
/// <param name="user">The user that added the emoji.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// An awaitable <see cref="Task"/>.
/// </returns>
Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null); Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null);
/// <summary> /// <summary>
/// Removes all reactions from this message. /// Removes all reactions from this message.
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// An awaitable <see cref="Task"/>.
/// </returns>
Task RemoveAllReactionsAsync(RequestOptions options = null); Task RemoveAllReactionsAsync(RequestOptions options = null);
/// <summary> /// <summary>
/// Gets all users that reacted to a message with a given emote. /// Gets all users that reacted to a message with a given emote.
@@ -47,6 +90,11 @@ namespace Discord
/// <summary> /// <summary>
/// Transforms this message's text into a human-readable form by resolving its tags. /// Transforms this message's text into a human-readable form by resolving its tags.
/// </summary> /// </summary>
/// <param name="userHandling">Determines how the user tag should be handled.</param>
/// <param name="channelHandling">Determines how the channel tag should be handled.</param>
/// <param name="roleHandling">Determines how the role tag should be handled.</param>
/// <param name="everyoneHandling">Determines how the @everyone tag should be handled.</param>
/// <param name="emojiHandling">Determines how the emoji tag should be handled.</param>
string Resolve( string Resolve(
TagHandling userHandling = TagHandling.Name, TagHandling userHandling = TagHandling.Name,
TagHandling channelHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name,


+ 1
- 1
src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs View File

@@ -148,7 +148,7 @@ namespace Discord
RawValue = value; RawValue = value;
} }


/// <summary> Creates a new <see cref="GuildPermissions"/> with the provided permissions. </summary>
/// <summary> Creates a new <see cref="GuildPermissions"/> structure with the provided permissions. </summary>
public GuildPermissions( public GuildPermissions(
bool createInstantInvite = false, bool createInstantInvite = false,
bool kickMembers = false, bool kickMembers = false,


+ 19
- 20
src/Discord.Net.Core/Entities/Roles/Color.cs View File

@@ -18,61 +18,60 @@ namespace Discord
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/1ABC9C">1ABC9C</see>.</returns> /// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/1ABC9C">1ABC9C</see>.</returns>
public static readonly Color Teal = new Color(0x1ABC9C); public static readonly Color Teal = new Color(0x1ABC9C);
/// <summary> Gets the dark teal color value. </summary> /// <summary> Gets the dark teal color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/11806A">11806A</see>.</returns>
public static readonly Color DarkTeal = new Color(0x11806A); public static readonly Color DarkTeal = new Color(0x11806A);
/// <summary> Gets the green color value. </summary> /// <summary> Gets the green color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/2ECC71">2ECC71</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/11806A">11806A</see>.</returns>
public static readonly Color Green = new Color(0x2ECC71); public static readonly Color Green = new Color(0x2ECC71);
/// <summary> Gets the dark green color value. </summary> /// <summary> Gets the dark green color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/1F8B4C">1F8B4C</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/2ECC71">2ECC71</see>.</returns>
public static readonly Color DarkGreen = new Color(0x1F8B4C); public static readonly Color DarkGreen = new Color(0x1F8B4C);
/// <summary> Gets the blue color value. </summary> /// <summary> Gets the blue color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/3498DB">3498DB</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/1F8B4C">1F8B4C</see>.</returns>
public static readonly Color Blue = new Color(0x3498DB); public static readonly Color Blue = new Color(0x3498DB);
/// <summary> Gets the dark blue color value. </summary> /// <summary> Gets the dark blue color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/206694">206694</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/3498DB">3498DB</see>.</returns>
public static readonly Color DarkBlue = new Color(0x206694); public static readonly Color DarkBlue = new Color(0x206694);
/// <summary> Gets the purple color value. </summary> /// <summary> Gets the purple color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/9B59B6">9B59B6</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/206694">206694</see>.</returns>
public static readonly Color Purple = new Color(0x9B59B6); public static readonly Color Purple = new Color(0x9B59B6);
/// <summary> Gets the dark purple color value. </summary> /// <summary> Gets the dark purple color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/71368A">71368A</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/9B59B6">9B59B6</see>.</returns>
public static readonly Color DarkPurple = new Color(0x71368A); public static readonly Color DarkPurple = new Color(0x71368A);
/// <summary> Gets the magenta color value. </summary> /// <summary> Gets the magenta color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/E91E63">E91E63</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/71368A">71368A</see>.</returns>
public static readonly Color Magenta = new Color(0xE91E63); public static readonly Color Magenta = new Color(0xE91E63);
/// <summary> Gets the dark magenta color value. </summary> /// <summary> Gets the dark magenta color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/AD1457">AD1457</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/E91E63">E91E63</see>.</returns>
public static readonly Color DarkMagenta = new Color(0xAD1457); public static readonly Color DarkMagenta = new Color(0xAD1457);
/// <summary> Gets the gold color value. </summary> /// <summary> Gets the gold color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/F1C40F">F1C40F</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/AD1457">AD1457</see>.</returns>
public static readonly Color Gold = new Color(0xF1C40F); public static readonly Color Gold = new Color(0xF1C40F);
/// <summary> Gets the light orange color value. </summary> /// <summary> Gets the light orange color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/C27C0E">C27C0E</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/F1C40F">F1C40F</see>.</returns>
public static readonly Color LightOrange = new Color(0xC27C0E); public static readonly Color LightOrange = new Color(0xC27C0E);
/// <summary> Gets the orange color value. </summary> /// <summary> Gets the orange color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/E67E22">E67E22</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/C27C0E">C27C0E</see>.</returns>
public static readonly Color Orange = new Color(0xE67E22); public static readonly Color Orange = new Color(0xE67E22);
/// <summary> Gets the dark orange color value. </summary> /// <summary> Gets the dark orange color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/A84300">A84300</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/E67E22">E67E22</see>.</returns>
public static readonly Color DarkOrange = new Color(0xA84300); public static readonly Color DarkOrange = new Color(0xA84300);
/// <summary> Gets the red color value. </summary> /// <summary> Gets the red color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/E74C3C">E74C3C</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/A84300">A84300</see>.</returns>
public static readonly Color Red = new Color(0xE74C3C); public static readonly Color Red = new Color(0xE74C3C);
/// <summary> Gets the dark red color value. </summary> /// <summary> Gets the dark red color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/992D22">992D22</see>.</returns>
public static readonly Color DarkRed = new Color(0x992D22);
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/E74C3C">E74C3C</see>.</returns>
public static readonly Color DarkRed = new Color(0x992D22);
/// <summary> Gets the light grey color value. </summary> /// <summary> Gets the light grey color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/979C9F">979C9F</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/992D22">992D22</see>.</returns>
public static readonly Color LightGrey = new Color(0x979C9F); public static readonly Color LightGrey = new Color(0x979C9F);
/// <summary> Gets the lighter grey color value. </summary> /// <summary> Gets the lighter grey color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/95A5A6">95A5A6</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/979C9F">979C9F</see>.</returns>
public static readonly Color LighterGrey = new Color(0x95A5A6); public static readonly Color LighterGrey = new Color(0x95A5A6);
/// <summary> Gets the dark grey color value. </summary> /// <summary> Gets the dark grey color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/607D8B">607D8B</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/95A5A6">95A5A6</see>.</returns>
public static readonly Color DarkGrey = new Color(0x607D8B); public static readonly Color DarkGrey = new Color(0x607D8B);
/// <summary> Gets the darker grey color value. </summary> /// <summary> Gets the darker grey color value. </summary>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/546E7A">546E7A</see>.</returns>
/// <returns> A color class with the hex value of <see href="http://www.color-hex.com/color/607D8B">607D8B</see>.</returns>
public static readonly Color DarkerGrey = new Color(0x546E7A); public static readonly Color DarkerGrey = new Color(0x546E7A);


/// <summary> Gets the encoded value for this color. </summary> /// <summary> Gets the encoded value for this color. </summary>


+ 2
- 2
src/Discord.Net.Core/Entities/Roles/IRole.cs View File

@@ -4,12 +4,12 @@ using System.Threading.Tasks;
namespace Discord namespace Discord
{ {
/// <summary> /// <summary>
/// Represents a generic role object.
/// Represents a generic role object to be given to a guild user.
/// </summary> /// </summary>
public interface IRole : ISnowflakeEntity, IDeletable, IMentionable, IComparable<IRole> public interface IRole : ISnowflakeEntity, IDeletable, IMentionable, IComparable<IRole>
{ {
/// <summary> /// <summary>
/// Gets the guild owning this role.
/// Gets the guild that owns this role.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A guild representing the parent guild of this role. /// A guild representing the parent guild of this role.


+ 1
- 1
src/Discord.Net.Core/Entities/Roles/ReorderRoleProperties.cs View File

@@ -16,7 +16,7 @@ namespace Discord
/// Gets the new zero-based position of the role. /// Gets the new zero-based position of the role.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A <see cref="int"/> representing the new zero-based position of the role.
/// An <see cref="int"/> representing the new zero-based position of the role.
/// </returns> /// </returns>
public int Position { get; } public int Position { get; }




+ 51
- 8
src/Discord.Net.Core/Entities/Users/IGuildUser.cs View File

@@ -10,36 +10,60 @@ namespace Discord
public interface IGuildUser : IUser, IVoiceState public interface IGuildUser : IUser, IVoiceState
{ {
/// <summary> /// <summary>
/// Gets when this user joined this guild.
/// Gets when this user joined the guild.
/// </summary> /// </summary>
/// <returns>
/// A <see cref="DateTimeOffset"/> representing the time of which the user has joined the guild;
/// <c>null</c> when it cannot be obtained.
/// </returns>
DateTimeOffset? JoinedAt { get; } DateTimeOffset? JoinedAt { get; }
/// <summary> /// <summary>
/// Gets the nickname for this user. /// Gets the nickname for this user.
/// </summary> /// </summary>
/// <returns>
/// A string representing the nickname of the user; <c>null</c> if none is set.
/// </returns>
string Nickname { get; } string Nickname { get; }
/// <summary> /// <summary>
/// Gets the guild-level permissions for this user. /// Gets the guild-level permissions for this user.
/// </summary> /// </summary>
/// <returns>
/// A <see cref="Discord.GuildPermissions"/> structure for this user, representing what
/// permissions this user has in the guild.
/// </returns>
GuildPermissions GuildPermissions { get; } GuildPermissions GuildPermissions { get; }


/// <summary> /// <summary>
/// Gets the guild for this user. /// Gets the guild for this user.
/// </summary> /// </summary>
/// <returns>
/// A guild object that this user belongs to.
/// </returns>
IGuild Guild { get; } IGuild Guild { get; }
/// <summary> /// <summary>
/// Gets the ID of the guild for this user. /// Gets the ID of the guild for this user.
/// </summary> /// </summary>
/// <returns>
/// An <see cref="ulong"/> representing the snowflake identifier of the guild that this user belongs to.
/// </returns>
ulong GuildId { get; } ulong GuildId { get; }
/// <summary> /// <summary>
/// Returns a collection of the ids of the roles this user is a member of in this guild, including the
/// guild's @everyone role.
/// Gets a collection of IDs for the roles that this user currently possesses in the guild.
/// </summary> /// </summary>
/// <returns>
/// A read-only collection of <see cref="ulong"/>, each representing a snowflake identifier for a role that
/// this user posesses.
/// </returns>
IReadOnlyCollection<ulong> RoleIds { get; } IReadOnlyCollection<ulong> RoleIds { get; }


/// <summary> /// <summary>
/// Gets the level permissions granted to this user to a given channel. /// Gets the level permissions granted to this user to a given channel.
/// </summary> /// </summary>
/// <param name="channel">The channel to get the permission from.</param> /// <param name="channel">The channel to get the permission from.</param>
/// <returns>
/// A <see cref="Discord.ChannelPermissions"/> structure representing the permissions that a user has in the
/// specified channel.
/// </returns>
ChannelPermissions GetPermissions(IGuildChannel channel); ChannelPermissions GetPermissions(IGuildChannel channel);


/// <summary> /// <summary>
@@ -47,37 +71,56 @@ namespace Discord
/// </summary> /// </summary>
/// <param name="reason">The reason for the kick which will be recorded in the audit log.</param> /// <param name="reason">The reason for the kick which will be recorded in the audit log.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous kick operation.
/// </returns>
Task KickAsync(string reason = null, RequestOptions options = null); Task KickAsync(string reason = null, RequestOptions options = null);
/// <summary> /// <summary>
/// Modifies this user's properties in this guild. /// Modifies this user's properties in this guild.
/// </summary> /// </summary>
/// <param name="func">The properties to modify the user with.</param>
/// <param name="func">The delegate containing the properties to modify the user with.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous modification operation.
/// </returns>
/// <seealso cref="Discord.GuildUserProperties"/>
Task ModifyAsync(Action<GuildUserProperties> func, RequestOptions options = null); Task ModifyAsync(Action<GuildUserProperties> func, RequestOptions options = null);


/// <summary> /// <summary>
/// Adds a <paramref name="role"/> to this user in this guild.
/// Adds the specified <paramref name="role"/> to this user in this guild.
/// </summary> /// </summary>
/// <param name="role">The role to be added to the user.</param> /// <param name="role">The role to be added to the user.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous role addition operation.
/// </returns>
Task AddRoleAsync(IRole role, RequestOptions options = null); Task AddRoleAsync(IRole role, RequestOptions options = null);
/// <summary> /// <summary>
/// Adds <paramref name="roles"/> to this user in this guild.
/// Adds the specified <paramref name="roles"/> to this user in this guild.
/// </summary> /// </summary>
/// <param name="roles">The roles to be added to the user.</param> /// <param name="roles">The roles to be added to the user.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous role addition operation.
/// </returns>
Task AddRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null); Task AddRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null);
/// <summary> /// <summary>
/// Removes a <paramref name="role"/> from this user in this guild.
/// Removes the specified <paramref name="role"/> from this user in this guild.
/// </summary> /// </summary>
/// <param name="role">The role to be removed from the user.</param> /// <param name="role">The role to be removed from the user.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous role removal operation.
/// </returns>
Task RemoveRoleAsync(IRole role, RequestOptions options = null); Task RemoveRoleAsync(IRole role, RequestOptions options = null);
/// <summary> /// <summary>
/// Removes <paramref name="roles"/> from this user in this guild.
/// Removes the specified <paramref name="roles"/> from this user in this guild.
/// </summary> /// </summary>
/// <param name="roles">The roles to be removed from the user.</param> /// <param name="roles">The roles to be removed from the user.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous role removal operation.
/// </returns>
Task RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null); Task RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options = null);
} }
} }

+ 1
- 1
src/Discord.Net.Core/Entities/Users/IPresence.cs View File

@@ -1,7 +1,7 @@
namespace Discord namespace Discord
{ {
/// <summary> /// <summary>
/// Represents a Discord user's presence status.
/// Represents the user's presence status. This may include their online status and their activity.
/// </summary> /// </summary>
public interface IPresence public interface IPresence
{ {


+ 8
- 2
src/Discord.Net.Core/Entities/Users/ISelfUser.cs View File

@@ -13,12 +13,18 @@ namespace Discord
/// </summary> /// </summary>
string Email { get; } string Email { get; }
/// <summary> /// <summary>
/// Returns <c>true</c> if this user's email has been verified.
/// Indicates whether or not this user has their email verified.
/// </summary> /// </summary>
/// <returns>
/// <c>true</c> if this user's email has been verified; <c>false</c> if not.
/// </returns>
bool IsVerified { get; } bool IsVerified { get; }
/// <summary> /// <summary>
/// Returns <c>true</c> if this user has enabled MFA on their account.
/// Indicates whether or not this user has MFA enabled on their account.
/// </summary> /// </summary>
/// <returns>
/// <c>true</c> if this user has enabled multi-factor authentication on their account; <c>false</c> if not.
/// </returns>
bool IsMfaEnabled { get; } bool IsMfaEnabled { get; }


/// <summary> /// <summary>


+ 18
- 6
src/Discord.Net.Core/Logging/LogMessage.cs View File

@@ -4,29 +4,41 @@ using System.Text;
namespace Discord namespace Discord
{ {
/// <summary> /// <summary>
/// Represents a message used for logging purposes.
/// Provides a message object used for logging purposes.
/// </summary> /// </summary>
public struct LogMessage public struct LogMessage
{ {
/// <summary> /// <summary>
/// Gets the severity of the log message.
/// Gets the severity of the log entry.
/// </summary> /// </summary>
/// <returns>
/// A <see cref="LogSeverity"/> enum to indicate the severeness of the incident or event.
/// </returns>
public LogSeverity Severity { get; } public LogSeverity Severity { get; }
/// <summary> /// <summary>
/// Gets the source of the log message.
/// Gets the source of the log entry.
/// </summary> /// </summary>
/// <returns>
/// A string representing the source of the log entry.
/// </returns>
public string Source { get; } public string Source { get; }
/// <summary> /// <summary>
/// Gets the message of the log message.
/// Gets the message of this log entry.
/// </summary> /// </summary>
/// <returns>
/// A string containing the message of this log entry.
/// </returns>
public string Message { get; } public string Message { get; }
/// <summary> /// <summary>
/// Gets the exception of the log message.
/// Gets the exception of this log entry.
/// </summary> /// </summary>
/// <returns>
/// An <see cref="Discord.LogMessage.Exception" /> object associated with an incident; otherwise <c>null</c>.
/// </returns>
public Exception Exception { get; } public Exception Exception { get; }


/// <summary> /// <summary>
/// Initializes a new <see cref="LogMessage" /> struct with the severity, source, message of the event, and
/// Initializes a new <see cref="LogMessage"/> struct with the severity, source, message of the event, and
/// optionally, an exception. /// optionally, an exception.
/// </summary> /// </summary>
/// <param name="severity">The severity of the event.</param> /// <param name="severity">The severity of the event.</param>


+ 1
- 1
src/Discord.Net.Core/Net/RateLimitedException.cs View File

@@ -3,7 +3,7 @@ using System;
namespace Discord.Net namespace Discord.Net
{ {
/// <summary> /// <summary>
/// Describes an exception that indicates the user is being rate limited by Discord.
/// The exception that is thrown when the user is being rate limited by Discord.
/// </summary> /// </summary>
public class RateLimitedException : TimeoutException public class RateLimitedException : TimeoutException
{ {


+ 15
- 3
src/Discord.Net.Core/RequestOptions.cs View File

@@ -13,11 +13,23 @@ namespace Discord
public static RequestOptions Default => new RequestOptions(); public static RequestOptions Default => new RequestOptions();


/// <summary> /// <summary>
/// Gets or set the max time, in milliseconds, to wait for this request to complete. If
/// <c>null</c>, a request will not time out. If a rate limit has been triggered for this
/// request's bucket and will not be unpaused in time, this request will fail immediately.
/// Gets or sets the maximum time to wait for for this request to complete.
/// </summary> /// </summary>
/// <remarks>
/// Gets or set the max time, in milliseconds, to wait for for this request to complete. If
/// <c>null</c>, a request will not time out. If a rate limit has been triggered for this request's bucket
/// and will not be unpaused in time, this request will fail immediately.
/// </remarks>
/// <returns>
/// A <see cref="int"/> in milliseconds for when the request times out.
/// </returns>
public int? Timeout { get; set; } public int? Timeout { get; set; }
/// <summary>
/// Gets or sets the cancellation token for this request.
/// </summary>
/// <returns>
/// A <see cref="CancellationToken"/> for this request.
/// </returns>
public CancellationToken CancelToken { get; set; } = CancellationToken.None; public CancellationToken CancelToken { get; set; } = CancellationToken.None;
/// <summary> /// <summary>
/// Gets or sets the retry behavior when the request fails. /// Gets or sets the retry behavior when the request fails.


+ 1
- 2
src/Discord.Net.Core/Utils/DateTimeUtils.cs View File

@@ -2,13 +2,12 @@ using System;


namespace Discord namespace Discord
{ {
//Source: https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/DateTimeOffset.cs
/// <see href="https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/DateTimeOffset.cs"/>
internal static class DateTimeUtils internal static class DateTimeUtils
{ {
public static DateTimeOffset FromTicks(long ticks) public static DateTimeOffset FromTicks(long ticks)
=> new DateTimeOffset(ticks, TimeSpan.Zero); => new DateTimeOffset(ticks, TimeSpan.Zero);
public static DateTimeOffset? FromTicks(long? ticks) public static DateTimeOffset? FromTicks(long? ticks)
=> ticks != null ? new DateTimeOffset(ticks.Value, TimeSpan.Zero) : (DateTimeOffset?)null; => ticks != null ? new DateTimeOffset(ticks.Value, TimeSpan.Zero) : (DateTimeOffset?)null;
} }
} }

+ 1
- 1
src/Discord.Net.Core/Utils/MentionUtils.cs View File

@@ -5,7 +5,7 @@ using System.Text;
namespace Discord namespace Discord
{ {
/// <summary> /// <summary>
/// Represents a helper class for mention-related parsing.
/// Provides a series of helper methods for parsing mentions.
/// </summary> /// </summary>
public static class MentionUtils public static class MentionUtils
{ {


+ 17
- 0
src/Discord.Net.Core/Utils/SnowflakeUtils.cs View File

@@ -2,10 +2,27 @@ using System;


namespace Discord namespace Discord
{ {
/// <summary>
/// Provides a series of helper methods for handling snowflake identifiers.
/// </summary>
public static class SnowflakeUtils public static class SnowflakeUtils
{ {
/// <summary>
/// Resolves the time of which the snowflake is generated.
/// </summary>
/// <param name="value">The snowflake identifier to resolve.</param>
/// <returns>
/// A <see cref="DateTimeOffset" /> representing the time for when the object is geenrated.
/// </returns>
public static DateTimeOffset FromSnowflake(ulong value) public static DateTimeOffset FromSnowflake(ulong value)
=> DateTimeOffset.FromUnixTimeMilliseconds((long)((value >> 22) + 1420070400000UL)); => DateTimeOffset.FromUnixTimeMilliseconds((long)((value >> 22) + 1420070400000UL));
/// <summary>
/// Generates a pseudo-snowflake identifier with a <see cref="DateTimeOffset"/>.
/// </summary>
/// <param name="value">The time to be used in the new snowflake.</param>
/// <returns>
/// A <see cref="UInt64" /> representing the newly generated snowflake identifier.
/// </returns>
public static ulong ToSnowflake(DateTimeOffset value) public static ulong ToSnowflake(DateTimeOffset value)
=> ((ulong)value.ToUnixTimeMilliseconds() - 1420070400000UL) << 22; => ((ulong)value.ToUnixTimeMilliseconds() - 1420070400000UL) << 22;
} }


+ 4
- 4
src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs View File

@@ -16,14 +16,13 @@ namespace Discord.Rest
{ {
/// <inheritdoc /> /// <inheritdoc />
public string Topic { get; private set; } public string Topic { get; private set; }
/// <inheritdoc />
public ulong? CategoryId { get; private set; } public ulong? CategoryId { get; private set; }


/// <inheritdoc /> /// <inheritdoc />
public string Mention => MentionUtils.MentionChannel(Id); public string Mention => MentionUtils.MentionChannel(Id);

private bool _nsfw;
/// <inheritdoc /> /// <inheritdoc />
public bool IsNsfw => _nsfw;
public bool IsNsfw { get; private set; }


internal RestTextChannel(BaseDiscordClient discord, IGuild guild, ulong id) internal RestTextChannel(BaseDiscordClient discord, IGuild guild, ulong id)
: base(discord, guild, id) : base(discord, guild, id)
@@ -40,7 +39,7 @@ namespace Discord.Rest
base.Update(model); base.Update(model);
CategoryId = model.CategoryId; CategoryId = model.CategoryId;
Topic = model.Topic.Value; Topic = model.Topic.Value;
_nsfw = model.Nsfw.GetValueOrDefault();
IsNsfw = model.Nsfw.GetValueOrDefault();
} }


/// <inheritdoc /> /// <inheritdoc />
@@ -239,6 +238,7 @@ namespace Discord.Rest
} }


// INestedChannel // INestedChannel
/// <inheritdoc />
async Task<ICategoryChannel> INestedChannel.GetCategoryAsync(CacheMode mode, RequestOptions options) async Task<ICategoryChannel> INestedChannel.GetCategoryAsync(CacheMode mode, RequestOptions options)
{ {
if (CategoryId.HasValue && mode == CacheMode.AllowDownload) if (CategoryId.HasValue && mode == CacheMode.AllowDownload)


+ 1
- 0
src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs View File

@@ -18,6 +18,7 @@ namespace Discord.Rest
public int Bitrate { get; private set; } public int Bitrate { get; private set; }
/// <inheritdoc /> /// <inheritdoc />
public int? UserLimit { get; private set; } public int? UserLimit { get; private set; }
/// <inheritdoc />
public ulong? CategoryId { get; private set; } public ulong? CategoryId { get; private set; }


internal RestVoiceChannel(BaseDiscordClient discord, IGuild guild, ulong id) internal RestVoiceChannel(BaseDiscordClient discord, IGuild guild, ulong id)


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

@@ -553,7 +553,7 @@ namespace Discord.Rest
Task IGuild.DownloadUsersAsync() => Task IGuild.DownloadUsersAsync() =>
throw new NotSupportedException(); throw new NotSupportedException();


async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogAsync(int limit, CacheMode cacheMode, RequestOptions options)
async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options)
{ {
if (cacheMode == CacheMode.AllowDownload) if (cacheMode == CacheMode.AllowDownload)
return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray(); return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();


+ 2
- 1
src/Discord.Net.Rest/Entities/Messages/RestSystemMessage.cs View File

@@ -1,4 +1,4 @@
using System.Diagnostics;
using System.Diagnostics;
using Model = Discord.API.Message; using Model = Discord.API.Message;


namespace Discord.Rest namespace Discord.Rest
@@ -6,6 +6,7 @@ namespace Discord.Rest
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestSystemMessage : RestMessage, ISystemMessage public class RestSystemMessage : RestMessage, ISystemMessage
{ {
/// <inheritdoc />
public MessageType Type { get; private set; } public MessageType Type { get; private set; }


internal RestSystemMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, IUser author) internal RestSystemMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, IUser author)


+ 1
- 0
src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs View File

@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;


+ 38
- 11
src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs View File

@@ -23,10 +23,10 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
public ulong? CategoryId { get; private set; } public ulong? CategoryId { get; private set; }
/// <summary> /// <summary>
/// Gets the Category this channel belongs to.
/// Gets the parent (category) of this channel in the guild's channel list.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// An <see cref="ICategoryChannel"/> that this channel belongs to; otherwise <c>null</c>.
/// An <see cref="ICategoryChannel"/> representing the parent of this channel; <c>null</c> if none is set.
/// </returns> /// </returns>
public ICategoryChannel Category public ICategoryChannel Category
=> CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null; => CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null;
@@ -73,14 +73,14 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
public SocketMessage GetCachedMessage(ulong id) public SocketMessage GetCachedMessage(ulong id)
=> _messages?.Get(id); => _messages?.Get(id);

/// <summary> /// <summary>
/// Gets the message associated with the passed <paramref name="id"/>.
/// Gets a message from this message channel.
/// </summary> /// </summary>
/// <param name="id">The snowflake identifier of the message you want to retrieve.</param>
/// <param name="id">The ID of the message.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing an <see cref="IMessage"/>.
/// An awaitable <see cref="Task"/> containing the downloaded message; <c>null</c> if none is found or if
/// the message fails to be retrieved.
/// </returns> /// </returns>
public async Task<IMessage> GetMessageAsync(ulong id, RequestOptions options = null) public async Task<IMessage> GetMessageAsync(ulong id, RequestOptions options = null)
{ {
@@ -89,11 +89,10 @@ namespace Discord.WebSocket
msg = await ChannelHelper.GetMessageAsync(this, Discord, id, options).ConfigureAwait(false); msg = await ChannelHelper.GetMessageAsync(this, Discord, id, options).ConfigureAwait(false);
return msg; return msg;
} }

/// <summary> /// <summary>
/// Gets the last N messages from this message channel. /// Gets the last N messages from this message channel.
/// </summary> /// </summary>
/// <param name="limit">The number of messages you want to get.</param>
/// <param name="limit">The numbers of message to be gotten from.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// Paged collection of messages. Flattening the paginated response into a collection of messages with /// Paged collection of messages. Flattening the paginated response into a collection of messages with
@@ -101,8 +100,30 @@ namespace Discord.WebSocket
/// </returns> /// </returns>
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, null, Direction.Before, limit, CacheMode.AllowDownload, options); => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, null, Direction.Before, limit, CacheMode.AllowDownload, options);
/// <summary>
/// Gets a collection of messages in this channel.
/// </summary>
/// <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>
/// <param name="limit">The numbers of message to be gotten from.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// Paged collection of messages. Flattening the paginated response into a collection of messages with
/// <see cref="AsyncEnumerableExtensions.FlattenAsync{T}"/> is required if you wish to access the messages.
/// </returns>
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessageId, dir, limit, CacheMode.AllowDownload, options); => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessageId, dir, limit, CacheMode.AllowDownload, options);
/// <summary>
/// Gets a collection of messages in this channel.
/// </summary>
/// <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>
/// <param name="limit">The numbers of message to be gotten from.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// Paged collection of messages. Flattening the paginated response into a collection of messages with
/// <see cref="AsyncEnumerableExtensions.FlattenAsync{T}"/> is required if you wish to access the messages.
/// </returns>
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, CacheMode.AllowDownload, options); => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, CacheMode.AllowDownload, options);
/// <inheritdoc /> /// <inheritdoc />
@@ -119,13 +140,16 @@ namespace Discord.WebSocket
=> ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options);


/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options); => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options);


/// <inheritdoc /> /// <inheritdoc />
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options);

/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options);


@@ -135,6 +159,7 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
public Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null) public Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null)
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messageIds, options); => ChannelHelper.DeleteMessagesAsync(this, Discord, messageIds, options);

/// <inheritdoc /> /// <inheritdoc />
public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
=> ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options); => ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options);
@@ -177,7 +202,7 @@ namespace Discord.WebSocket
/// <param name="avatar">The avatar of the webhook.</param> /// <param name="avatar">The avatar of the webhook.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// The created webhook.
/// An awaitable <see cref="Task"/> containing the created webhook.
/// </returns> /// </returns>
public Task<RestWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null) public Task<RestWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null)
=> ChannelHelper.CreateWebhookAsync(this, Discord, name, avatar, options); => ChannelHelper.CreateWebhookAsync(this, Discord, name, avatar, options);
@@ -187,7 +212,8 @@ namespace Discord.WebSocket
/// <param name="id">The identifier of the webhook.</param> /// <param name="id">The identifier of the webhook.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> webhook associated with the identifier, or <c>null</c> if not found.
/// An awaitable <see cref="Task"/> containing a webhook associated with the identifier; <c>null</c> if not
/// found.
/// </returns> /// </returns>
public Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null) public Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null)
=> ChannelHelper.GetWebhookAsync(this, Discord, id, options); => ChannelHelper.GetWebhookAsync(this, Discord, id, options);
@@ -196,7 +222,7 @@ namespace Discord.WebSocket
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> collection of webhooks.
/// An awaitable <see cref="Task"/> containing a collection of found webhooks.
/// </returns> /// </returns>
public Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) public Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null)
=> ChannelHelper.GetWebhooksAsync(this, Discord, options); => ChannelHelper.GetWebhooksAsync(this, Discord, options);
@@ -256,6 +282,7 @@ namespace Discord.WebSocket
=> await SendMessageAsync(text, isTTS, embed, options).ConfigureAwait(false); => await SendMessageAsync(text, isTTS, embed, options).ConfigureAwait(false);


// INestedChannel // INestedChannel
/// <inheritdoc />
Task<ICategoryChannel> INestedChannel.GetCategoryAsync(CacheMode mode, RequestOptions options) Task<ICategoryChannel> INestedChannel.GetCategoryAsync(CacheMode mode, RequestOptions options)
=> Task.FromResult(Category); => Task.FromResult(Category);
} }


+ 14
- 0
src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs View File

@@ -20,7 +20,14 @@ namespace Discord.WebSocket
public int Bitrate { get; private set; } public int Bitrate { get; private set; }
/// <inheritdoc /> /// <inheritdoc />
public int? UserLimit { get; private set; } public int? UserLimit { get; private set; }
/// <inheritdoc />
public ulong? CategoryId { get; private set; } public ulong? CategoryId { get; private set; }
/// <summary>
/// Gets the parent (category) of this channel in the guild's channel list.
/// </summary>
/// <returns>
/// An <see cref="ICategoryChannel"/> representing the parent of this channel; <c>null</c> if none is set.
/// </returns>
public ICategoryChannel Category public ICategoryChannel Category
=> CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null; => CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null;


@@ -56,6 +63,12 @@ namespace Discord.WebSocket
return await Guild.ConnectAudioAsync(Id, selfDeaf, selfMute, external).ConfigureAwait(false); return await Guild.ConnectAudioAsync(Id, selfDeaf, selfMute, external).ConfigureAwait(false);
} }


/// <summary>
/// Disconnects from this voice channel if the client is in an active voice connection.
/// </summary>
/// <returns>
/// An awaitable <see cref="Task" /> .
/// </returns>
public async Task DisconnectAsync() public async Task DisconnectAsync()
=> await Guild.DisconnectAudioAsync(); => await Guild.DisconnectAudioAsync();


@@ -80,6 +93,7 @@ namespace Discord.WebSocket
=> ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>(Users).ToAsyncEnumerable(); => ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>(Users).ToAsyncEnumerable();


// INestedChannel // INestedChannel
/// <inheritdoc />
Task<ICategoryChannel> INestedChannel.GetCategoryAsync(CacheMode mode, RequestOptions options) Task<ICategoryChannel> INestedChannel.GetCategoryAsync(CacheMode mode, RequestOptions options)
=> Task.FromResult(Category); => Task.FromResult(Category);
} }


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

@@ -54,8 +54,18 @@ namespace Discord.WebSocket
/// Gets the number of members. /// Gets the number of members.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This property retrieves the number of members returned by Discord and is the most accurate. You may see
/// discrepancy between the <see cref="Users"/> collection and this property.
/// This property retrieves the number of members returned by Discord.
/// <note type="tip">
/// <para>
/// Due to how this property is returned by Discord instead of relying on the WebSocket cache, the
/// number here is the most accurate in terms of counting the number of users within this guild.
/// </para>
/// <para>
/// Use this instead of enumerating the count of the
/// <see cref="Discord.WebSocket.SocketGuild.Users" /> collection, as you may see discrepancy
/// between that and this property.
/// </para>
/// </note>
/// </remarks> /// </remarks>
public int MemberCount { get; internal set; } public int MemberCount { get; internal set; }
/// <summary> Gets the number of members downloaded to the local guild cache. </summary> /// <summary> Gets the number of members downloaded to the local guild cache. </summary>
@@ -95,12 +105,18 @@ namespace Discord.WebSocket
/// </summary> /// </summary>
public IAudioClient AudioClient => _audioClient; public IAudioClient AudioClient => _audioClient;
/// <summary> /// <summary>
/// Gets the first viewable text channel.
/// Gets the default channel in this guild.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This method gets the first viewable text channel for the logged-in user. This property does not
/// guarantee the user can send message to it.
/// This property retrieves the first viewable text channel for this guild.
/// <note type="warning">
/// This channel does not guarantee the user can send message to it, as it only looks for the first viewable
/// text channel.
/// </note>
/// </remarks> /// </remarks>
/// <returns>
/// A <see cref="SocketTextChannel"/> representing the first viewable channel that the user has access to.
/// </returns>
public SocketTextChannel DefaultChannel => TextChannels public SocketTextChannel DefaultChannel => TextChannels
.Where(c => CurrentUser.GetPermissions(c).ViewChannel) .Where(c => CurrentUser.GetPermissions(c).ViewChannel)
.OrderBy(c => c.Position) .OrderBy(c => c.Position)
@@ -109,7 +125,8 @@ namespace Discord.WebSocket
/// Gets the AFK voice channel in this guild. /// Gets the AFK voice channel in this guild.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A voice channel set within this guild that AFK users get moved to; otherwise <c>null</c> if none is set.
/// A <see cref="SocketVoiceChannel" /> that the AFK users will be moved to after they have idled for too
/// long; <c>null</c> if none is set.
/// </returns> /// </returns>
public SocketVoiceChannel AFKChannel public SocketVoiceChannel AFKChannel
{ {
@@ -120,10 +137,10 @@ namespace Discord.WebSocket
} }
} }
/// <summary> /// <summary>
/// Gets the embed channel set in the widget settings of this guild.
/// Gets the embed channel (i.e. the channel set in the guild's widget settings) in this guild.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A channel set in the widget settings of this guild; otherwise <c>null</c> if none is set.
/// A channel set within the server's widget settings; <c>null</c> if none is set.
/// </returns> /// </returns>
public SocketGuildChannel EmbedChannel public SocketGuildChannel EmbedChannel
{ {
@@ -134,11 +151,10 @@ namespace Discord.WebSocket
} }
} }
/// <summary> /// <summary>
/// Gets the channel where randomized welcome messages are sent.
/// Gets the system channel where randomized welcome messages are sent in this guild.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A channel where randomized welcome messages are sent in this guild; otherwise <c>null</c> if none is
/// set.
/// A text channel where randomized welcome messages will be sent to; <c>null</c> if none is set.
/// </returns> /// </returns>
public SocketTextChannel SystemChannel public SocketTextChannel SystemChannel
{ {
@@ -149,21 +165,27 @@ namespace Discord.WebSocket
} }
} }
/// <summary> /// <summary>
/// Gets a collection of text channels present in this guild.
/// Gets a collection of all text channels in this guild.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A collection of text channels in this guild.
/// A read-only collection of message channels found within this guild.
/// </returns> /// </returns>
public IReadOnlyCollection<SocketTextChannel> TextChannels public IReadOnlyCollection<SocketTextChannel> TextChannels
=> Channels.Select(x => x as SocketTextChannel).Where(x => x != null).ToImmutableArray(); => Channels.Select(x => x as SocketTextChannel).Where(x => x != null).ToImmutableArray();
/// <summary> /// <summary>
/// Gets a collection of voice channels present in this guild.
/// Gets a collection of all voice channels in this guild.
/// </summary> /// </summary>
/// <returns>
/// A read-only collection of voice channels found within this guild.
/// </returns>
public IReadOnlyCollection<SocketVoiceChannel> VoiceChannels public IReadOnlyCollection<SocketVoiceChannel> VoiceChannels
=> Channels.Select(x => x as SocketVoiceChannel).Where(x => x != null).ToImmutableArray(); => Channels.Select(x => x as SocketVoiceChannel).Where(x => x != null).ToImmutableArray();
/// <summary> /// <summary>
/// Gets a collection of category channels present in this guild.
/// Gets a collection of all category channels in this guild.
/// </summary> /// </summary>
/// <returns>
/// A read-only collection of category channels found within this guild.
/// </returns>
public IReadOnlyCollection<SocketCategoryChannel> CategoryChannels public IReadOnlyCollection<SocketCategoryChannel> CategoryChannels
=> Channels.Select(x => x as SocketCategoryChannel).Where(x => x != null).ToImmutableArray(); => Channels.Select(x => x as SocketCategoryChannel).Where(x => x != null).ToImmutableArray();
/// <summary> /// <summary>
@@ -171,14 +193,17 @@ namespace Discord.WebSocket
/// </summary> /// </summary>
public SocketGuildUser CurrentUser => _members.TryGetValue(Discord.CurrentUser.Id, out SocketGuildUser member) ? member : null; public SocketGuildUser CurrentUser => _members.TryGetValue(Discord.CurrentUser.Id, out SocketGuildUser member) ? member : null;
/// <summary> /// <summary>
/// Gets the @everyone role in this guild.
/// Gets the built-in role containing all users in this guild.
/// </summary> /// </summary>
/// <returns>
/// A role object that represents an <c>@everyone</c> role in this guild.
/// </returns>
public SocketRole EveryoneRole => GetRole(Id); public SocketRole EveryoneRole => GetRole(Id);
/// <summary> /// <summary>
/// Gets a collection of channels present in this guild.
/// Gets a collection of all channels in this guild.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// Collection of channels.
/// A read-only collection of generic channels found within this guild.
/// </returns> /// </returns>
public IReadOnlyCollection<SocketGuildChannel> Channels public IReadOnlyCollection<SocketGuildChannel> Channels
{ {
@@ -189,37 +214,37 @@ namespace Discord.WebSocket
return channels.Select(x => state.GetChannel(x) as SocketGuildChannel).Where(x => x != null).ToReadOnlyCollection(channels); return channels.Select(x => state.GetChannel(x) as SocketGuildChannel).Where(x => x != null).ToReadOnlyCollection(channels);
} }
} }
/// <summary>
/// Gets a collection of emotes created in this guild.
/// </summary>
/// <returns>
/// Collection of emotes.
/// </returns>
/// <inheritdoc />
public IReadOnlyCollection<GuildEmote> Emotes => _emotes; public IReadOnlyCollection<GuildEmote> Emotes => _emotes;
/// <summary>
/// Gets a collection of features enabled in this guild.
/// </summary>
/// <returns>
/// Collection of features in string.
/// </returns>
/// <inheritdoc />
public IReadOnlyCollection<string> Features => _features; public IReadOnlyCollection<string> Features => _features;
/// <summary> /// <summary>
/// Gets a collection of users in this guild. /// Gets a collection of users in this guild.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This property may not always return all the members for large guilds (i.e. guilds containing 100+ users).
/// You may need to enable <see cref="DiscordSocketConfig.AlwaysDownloadUsers"/> to fetch the full user list
/// upon startup, or use <see cref="DownloadUsersAsync"/> to manually download the users.
/// This property retrieves all users found within this guild.
/// <note type="warning">
/// <para>
/// This property may not always return all the members for large guilds (i.e. guilds containing
/// 100+ users). If you are simply looking to get the number of users present in this guild,
/// consider using <see cref="MemberCount"/> instead.
/// </para>
/// <para>
/// Otherwise, you may need to enable <see cref="DiscordSocketConfig.AlwaysDownloadUsers"/> to fetch
/// the full user list upon startup, or use <see cref="DownloadUsersAsync"/> to manually download
/// the users.
/// </para>
/// </note>
/// </remarks> /// </remarks>
/// <returns> /// <returns>
/// Collection of users.
/// A collection of guild users found within this guild.
/// </returns> /// </returns>
public IReadOnlyCollection<SocketGuildUser> Users => _members.ToReadOnlyCollection(); public IReadOnlyCollection<SocketGuildUser> Users => _members.ToReadOnlyCollection();
/// <summary> /// <summary>
/// Gets a collection of roles in this guild.
/// Gets a collection of all roles in this guild.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// Collection of roles.
/// A read-only collection of roles found within this guild.
/// </returns> /// </returns>
public IReadOnlyCollection<SocketRole> Roles => _roles.ToReadOnlyCollection(); public IReadOnlyCollection<SocketRole> Roles => _roles.ToReadOnlyCollection();


@@ -407,16 +432,36 @@ namespace Discord.WebSocket


//Bans //Bans
/// <summary> /// <summary>
/// Returns a collection of the banned users in this guild.
/// Gets a collection of all users banned in this guild.
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// A collection of bans.
/// A task that represents the asynchronous get operation. The task result contains a read-only collection of
/// ban objects that this guild currently possesses, with each object containing the user banned and reason
/// behind the ban.
/// </returns> /// </returns>
public Task<IReadOnlyCollection<RestBan>> GetBansAsync(RequestOptions options = null) public Task<IReadOnlyCollection<RestBan>> GetBansAsync(RequestOptions options = null)
=> GuildHelper.GetBansAsync(this, Discord, options); => GuildHelper.GetBansAsync(this, Discord, options);
/// <summary>
/// Gets a ban object for a banned user.
/// </summary>
/// <param name="user">The banned user.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous get operation. The task result contains a ban object, which
/// contains the user information and the reason for the ban; <c>null</c> if the ban entry cannot be found.
/// </returns>
public Task<RestBan> GetBanAsync(IUser user, RequestOptions options = null) public Task<RestBan> GetBanAsync(IUser user, RequestOptions options = null)
=> GuildHelper.GetBanAsync(this, Discord, user.Id, options); => GuildHelper.GetBanAsync(this, Discord, user.Id, options);
/// <summary>
/// Gets a ban object for a banned user.
/// </summary>
/// <param name="userId">The snowflake identifier for the banned user.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous get operation. The task result contains a ban object, which
/// contains the user information and the reason for the ban; <c>null</c> if the ban entry cannot be found.
/// </returns>
public Task<RestBan> GetBanAsync(ulong userId, RequestOptions options = null) public Task<RestBan> GetBanAsync(ulong userId, RequestOptions options = null)
=> GuildHelper.GetBanAsync(this, Discord, userId, options); => GuildHelper.GetBanAsync(this, Discord, userId, options);


@@ -436,11 +481,11 @@ namespace Discord.WebSocket


//Channels //Channels
/// <summary> /// <summary>
/// Returns a guild channel with the provided ID.
/// Gets a channel in this guild.
/// </summary> /// </summary>
/// <param name="id">The channel ID.</param>
/// <param name="id">The snowflake identifier for the channel.</param>
/// <returns> /// <returns>
/// The guild channel associated with the ID.
/// A generic channel associated with the specified <paramref name="id" />; <c>null</c> if none is found.
/// </returns> /// </returns>
public SocketGuildChannel GetChannel(ulong id) public SocketGuildChannel GetChannel(ulong id)
{ {
@@ -450,56 +495,59 @@ namespace Discord.WebSocket
return null; return null;
} }
/// <summary> /// <summary>
/// Returns a text channel with the provided ID.
/// Gets a text channel in this guild.
/// </summary> /// </summary>
/// <param name="id">The channel ID.</param>
/// <param name="id">The snowflake identifier for the text channel.</param>
/// <returns> /// <returns>
/// The text channel associated with the ID.
/// A text channel associated with the specified <paramref name="id" />; <c>null</c> if none is found.
/// </returns> /// </returns>
public SocketTextChannel GetTextChannel(ulong id) public SocketTextChannel GetTextChannel(ulong id)
=> GetChannel(id) as SocketTextChannel; => GetChannel(id) as SocketTextChannel;
/// <summary> /// <summary>
/// Returns a voice channel with the provided ID.
/// Gets a voice channel in this guild.
/// </summary> /// </summary>
/// <param name="id">The channel ID.</param>
/// <param name="id">The snowflake identifier for the voice channel.</param>
/// <returns> /// <returns>
/// The voice channel associated with the ID.
/// A voice channel associated with the specified <paramref name="id" />; <c>null</c> if none is found.
/// </returns> /// </returns>
public SocketVoiceChannel GetVoiceChannel(ulong id) public SocketVoiceChannel GetVoiceChannel(ulong id)
=> GetChannel(id) as SocketVoiceChannel; => GetChannel(id) as SocketVoiceChannel;


/// <summary> /// <summary>
/// Creates a text channel with the provided name.
/// Creates a new text channel in this guild.
/// </summary> /// </summary>
/// <param name="name">The name of the new channel.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <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> /// <param name="func">The delegate containing the properties to be applied to the channel upon its creation.</param>
/// <exception cref="ArgumentNullException"><paramref name="name" /> is <c>null</c>.</exception>
/// <param name="options">The options to be used when sending the request.</param>
/// <exception cref="ArgumentNullException"><paramref name="name"/> is <c>null</c>.</exception>
/// <returns> /// <returns>
/// The created text channel.
/// A task that represents the asynchronous creation operation. The task result contains the newly created
/// text channel.
/// </returns> /// </returns>
public Task<RestTextChannel> CreateTextChannelAsync(string name, Action<TextChannelProperties> func = null, RequestOptions options = null) public Task<RestTextChannel> CreateTextChannelAsync(string name, Action<TextChannelProperties> func = null, RequestOptions options = null)
=> GuildHelper.CreateTextChannelAsync(this, Discord, name, options, func); => GuildHelper.CreateTextChannelAsync(this, Discord, name, options, func);
/// <summary> /// <summary>
/// Creates a voice channel with the provided name.
/// Creates a new voice channel in this guild.
/// </summary> /// </summary>
/// <param name="name">The name of the new channel.</param>
/// <param name="name">The new name for the voice channel.</param>
/// <param name="func">The delegate containing the properties to be applied to the channel upon its creation.</param> /// <param name="func">The delegate containing the properties to be applied to the channel upon its creation.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <exception cref="ArgumentNullException"><paramref name="name" /> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="name"/> is <c>null</c>.</exception>
/// <returns> /// <returns>
/// The created voice channel.
/// A task that represents the asynchronous creation operation. The task result contains the newly created
/// voice channel.
/// </returns> /// </returns>
public Task<RestVoiceChannel> CreateVoiceChannelAsync(string name, Action<VoiceChannelProperties> func = null, RequestOptions options = null) public Task<RestVoiceChannel> CreateVoiceChannelAsync(string name, Action<VoiceChannelProperties> func = null, RequestOptions options = null)
=> GuildHelper.CreateVoiceChannelAsync(this, Discord, name, options, func); => GuildHelper.CreateVoiceChannelAsync(this, Discord, name, options, func);
/// <summary> /// <summary>
/// Creates a category channel with the provided name.
/// Creates a new channel category in this guild.
/// </summary> /// </summary>
/// <param name="name">The name of the new channel.</param>
/// <param name="name">The new name for the category.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <exception cref="ArgumentNullException"><paramref name="name" /> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="name"/> is <c>null</c>.</exception>
/// <returns> /// <returns>
/// The created category channel.
/// A task that represents the asynchronous creation operation. The task result contains the newly created
/// category channel.
/// </returns> /// </returns>
public Task<RestCategoryChannel> CreateCategoryChannelAsync(string name, RequestOptions options = null) public Task<RestCategoryChannel> CreateCategoryChannelAsync(string name, RequestOptions options = null)
=> GuildHelper.CreateCategoryChannelAsync(this, Discord, name, options); => GuildHelper.CreateCategoryChannelAsync(this, Discord, name, options);
@@ -526,11 +574,12 @@ namespace Discord.WebSocket


//Invites //Invites
/// <summary> /// <summary>
/// Returns a collection of invites associated with this channel.
/// Gets a collection of all invites in this guild.
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// An awaitable <see cref="Task"/> containing a collection of invites.
/// A task that represents the asynchronous get operation. The task result contains a read-only collection of
/// invite metadata, each representing information for an invite found within this guild.
/// </returns> /// </returns>
public Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(RequestOptions options = null) public Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(RequestOptions options = null)
=> GuildHelper.GetInvitesAsync(this, Discord, options); => GuildHelper.GetInvitesAsync(this, Discord, options);
@@ -539,18 +588,19 @@ namespace Discord.WebSocket
/// </summary> /// </summary>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <returns> /// <returns>
/// A partial metadata of the vanity invite found within this guild.
/// A task that represents the asynchronous get operation. The task result contains the partial metadata of
/// the vanity invite found within this guild; <c>null</c> if none is found.
/// </returns> /// </returns>
public Task<RestInviteMetadata> GetVanityInviteAsync(RequestOptions options = null) public Task<RestInviteMetadata> GetVanityInviteAsync(RequestOptions options = null)
=> GuildHelper.GetVanityInviteAsync(this, Discord, options); => GuildHelper.GetVanityInviteAsync(this, Discord, options);


//Roles //Roles
/// <summary> /// <summary>
/// Gets a role.
/// Gets a role in this guild.
/// </summary> /// </summary>
/// <param name="id">The snowflake identifier of the role.</param>
/// <param name="id">The snowflake identifier for the role.</param>
/// <returns> /// <returns>
/// The role associated with the snowflake identifier.
/// A role that is associated with the specified <paramref name="id"/>; <c>null</c> if none is found.
/// </returns> /// </returns>
public SocketRole GetRole(ulong id) public SocketRole GetRole(ulong id)
{ {
@@ -560,18 +610,17 @@ namespace Discord.WebSocket
} }


/// <summary> /// <summary>
/// Creates a role.
/// Creates a new role with the provided name.
/// </summary> /// </summary>
/// <param name="name">The name of the new role.</param>
/// <param name="permissions">
/// The permissions that the new role possesses. Set to <c>null</c> to use the default permissions.
/// </param>
/// <param name="color">The color of the role. Set to <c>null</c> to use the default color.</param>
/// <param name="isHoisted">Used to determine if users of this role are separated in the user list.</param>
/// <param name="name">The new name for the role.</param>
/// <param name="permissions">The guild permission that the role should possess.</param>
/// <param name="color">The color of the role.</param>
/// <param name="isHoisted">Whether the role is separated from others on the sidebar.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <exception cref="ArgumentNullException"><paramref name="name" /> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="name"/> is <c>null</c>.</exception>
/// <returns> /// <returns>
/// The created role.
/// A task that represents the asynchronous creation operation. The task result contains the newly created
/// role.
/// </returns> /// </returns>
public Task<RestRole> CreateRoleAsync(string name, GuildPermissions? permissions = default(GuildPermissions?), Color? color = default(Color?), public Task<RestRole> CreateRoleAsync(string name, GuildPermissions? permissions = default(GuildPermissions?), Color? color = default(Color?),
bool isHoisted = false, RequestOptions options = null) bool isHoisted = false, RequestOptions options = null)
@@ -593,9 +642,16 @@ namespace Discord.WebSocket
/// <summary> /// <summary>
/// Gets a user from this guild. /// Gets a user from this guild.
/// </summary> /// </summary>
/// <param name="id">The snowflake identifier of the user (e.g. `168693960628371456`).</param>
/// <remarks>
/// This method retrieves a user found within this guild.
/// <note>
/// This may return <c>null</c> in the WebSocket implementation due to incomplete user collection in
/// large guilds.
/// </note>
/// </remarks>
/// <param name="id">The snowflake identifier of the user.</param>
/// <returns> /// <returns>
/// A WebSocket-based guild user associated with the snowflake identifier.
/// A guild user associated with the specified <paramref name="id"/>; <c>null</c> if none is found.
/// </returns> /// </returns>
public SocketGuildUser GetUser(ulong id) public SocketGuildUser GetUser(ulong id)
{ {
@@ -657,9 +713,7 @@ namespace Discord.WebSocket
return null; return null;
} }


/// <summary>
/// Downloads the users of this guild to the WebSocket cache.
/// </summary>
/// <inheritdoc />
public async Task DownloadUsersAsync() public async Task DownloadUsersAsync()
{ {
await Discord.DownloadUsersAsync(new[] { this }).ConfigureAwait(false); await Discord.DownloadUsersAsync(new[] { this }).ConfigureAwait(false);
@@ -670,6 +724,15 @@ namespace Discord.WebSocket
} }


//Audit logs //Audit logs
/// <summary>
/// Gets the specified number of audit log entries for this guild.
/// </summary>
/// <param name="limit">The number of audit log entries to fetch.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous get operation. The task result contains a read-only collection
/// of the requested audit log entries.
/// </returns>
public IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(int limit, RequestOptions options = null) public IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(int limit, RequestOptions options = null)
=> GuildHelper.GetAuditLogsAsync(this, Discord, null, limit, options); => GuildHelper.GetAuditLogsAsync(this, Discord, null, limit, options);


@@ -895,6 +958,9 @@ namespace Discord.WebSocket
/// <summary> /// <summary>
/// Gets the name of the guild. /// Gets the name of the guild.
/// </summary> /// </summary>
/// <returns>
/// A string that resolves to <see cref="Discord.WebSocket.SocketGuild.Name"/>.
/// </returns>
public override string ToString() => Name; public override string ToString() => Name;
private string DebuggerDisplay => $"{Name} ({Id})"; private string DebuggerDisplay => $"{Name} ({Id})";
internal SocketGuild Clone() => MemberwiseClone() as SocketGuild; internal SocketGuild Clone() => MemberwiseClone() as SocketGuild;
@@ -1004,7 +1070,8 @@ namespace Discord.WebSocket
Task<IGuildUser> IGuild.GetOwnerAsync(CacheMode mode, RequestOptions options) Task<IGuildUser> IGuild.GetOwnerAsync(CacheMode mode, RequestOptions options)
=> Task.FromResult<IGuildUser>(Owner); => Task.FromResult<IGuildUser>(Owner);


async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogAsync(int limit, CacheMode cacheMode, RequestOptions options)
/// <inheritdoc />
async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options)
{ {
if (cacheMode == CacheMode.AllowDownload) if (cacheMode == CacheMode.AllowDownload)
return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray(); return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();


+ 21
- 0
src/Discord.Net.WebSocket/Entities/Roles/SocketRole.cs View File

@@ -8,9 +8,18 @@ using Model = Discord.API.Role;


namespace Discord.WebSocket namespace Discord.WebSocket
{ {
/// <summary>
/// Represents a WebSocket-based role to be given to a guild user.
/// </summary>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class SocketRole : SocketEntity<ulong>, IRole public class SocketRole : SocketEntity<ulong>, IRole
{ {
/// <summary>
/// Gets the guild that owns this role.
/// </summary>
/// <returns>
/// A <see cref="SocketGuild"/> representing the parent guild of this role.
/// </returns>
public SocketGuild Guild { get; } public SocketGuild Guild { get; }


/// <inheritdoc /> /// <inheritdoc />
@@ -30,6 +39,12 @@ namespace Discord.WebSocket


/// <inheritdoc /> /// <inheritdoc />
public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id);
/// <summary>
/// Returns a value that determines if the role is an @everyone role.
/// </summary>
/// <returns>
/// <c>true</c> if the role is @everyone; otherwise <c>false</c>.
/// </returns>
public bool IsEveryone => Id == Guild.Id; public bool IsEveryone => Id == Guild.Id;
/// <inheritdoc /> /// <inheritdoc />
public string Mention => IsEveryone ? "@everyone" : MentionUtils.MentionRole(Id); public string Mention => IsEveryone ? "@everyone" : MentionUtils.MentionRole(Id);
@@ -65,6 +80,12 @@ namespace Discord.WebSocket
public Task DeleteAsync(RequestOptions options = null) public Task DeleteAsync(RequestOptions options = null)
=> RoleHelper.DeleteAsync(this, Discord, options); => RoleHelper.DeleteAsync(this, Discord, options);


/// <summary>
/// Gets the name of the role.
/// </summary>
/// <returns>
/// A string that resolves to <see cref="Discord.WebSocket.SocketRole.Name" />.
/// </returns>
public override string ToString() => Name; public override string ToString() => Name;
private string DebuggerDisplay => $"{Name} ({Id})"; private string DebuggerDisplay => $"{Name} ({Id})";
internal SocketRole Clone() => MemberwiseClone() as SocketRole; internal SocketRole Clone() => MemberwiseClone() as SocketRole;


+ 2
- 1
src/Discord.Net.WebSocket/Entities/SocketEntity.cs View File

@@ -1,4 +1,4 @@
using System;
using System;


namespace Discord.WebSocket namespace Discord.WebSocket
{ {
@@ -6,6 +6,7 @@ namespace Discord.WebSocket
where T : IEquatable<T> where T : IEquatable<T>
{ {
internal DiscordSocketClient Discord { get; } internal DiscordSocketClient Discord { get; }
/// <inheritdoc />
public T Id { get; } public T Id { get; }


internal SocketEntity(DiscordSocketClient discord, T id) internal SocketEntity(DiscordSocketClient discord, T id)


+ 8
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketGroupUser.cs View File

@@ -6,7 +6,14 @@ namespace Discord.WebSocket
[DebuggerDisplay("{DebuggerDisplay,nq}")] [DebuggerDisplay("{DebuggerDisplay,nq}")]
public class SocketGroupUser : SocketUser, IGroupUser public class SocketGroupUser : SocketUser, IGroupUser
{ {
/// <summary>
/// Gets the group channel of the user.
/// </summary>
/// <returns>
/// A <see cref="SocketGroupChannel" /> representing the channel of which the user belongs to.
/// </returns>
public SocketGroupChannel Channel { get; } public SocketGroupChannel Channel { get; }
/// <inheritdoc />
internal override SocketGlobalUser GlobalUser { get; } internal override SocketGlobalUser GlobalUser { get; }


/// <inheritdoc /> /// <inheritdoc />
@@ -17,6 +24,7 @@ namespace Discord.WebSocket
public override ushort DiscriminatorValue { get { return GlobalUser.DiscriminatorValue; } internal set { GlobalUser.DiscriminatorValue = value; } } public override ushort DiscriminatorValue { get { return GlobalUser.DiscriminatorValue; } internal set { GlobalUser.DiscriminatorValue = value; } }
/// <inheritdoc /> /// <inheritdoc />
public override string AvatarId { get { return GlobalUser.AvatarId; } internal set { GlobalUser.AvatarId = value; } } public override string AvatarId { get { return GlobalUser.AvatarId; } internal set { GlobalUser.AvatarId = value; } }
/// <inheritdoc />
internal override SocketPresence Presence { get { return GlobalUser.Presence; } set { GlobalUser.Presence = value; } } internal override SocketPresence Presence { get { return GlobalUser.Presence; } set { GlobalUser.Presence = value; } }


/// <inheritdoc /> /// <inheritdoc />


+ 9
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketPresence.cs View File

@@ -3,6 +3,9 @@ using Model = Discord.API.Presence;


namespace Discord.WebSocket namespace Discord.WebSocket
{ {
/// <summary>
/// Represents the WebSocket user's presence status. This may include their online status and their activity.
/// </summary>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public struct SocketPresence : IPresence public struct SocketPresence : IPresence
{ {
@@ -21,6 +24,12 @@ namespace Discord.WebSocket
return new SocketPresence(model.Status, model.Game?.ToEntity()); return new SocketPresence(model.Status, model.Game?.ToEntity());
} }


/// <summary>
/// Gets the status of the user.
/// </summary>
/// <returns>
/// A string that resolves to <see cref="Discord.WebSocket.SocketPresence.Status" />.
/// </returns>
public override string ToString() => Status.ToString(); public override string ToString() => Status.ToString();
private string DebuggerDisplay => $"{Status}{(Activity != null ? $", {Activity.Name}": "")}"; private string DebuggerDisplay => $"{Status}{(Activity != null ? $", {Activity.Name}": "")}";




+ 3
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs View File

@@ -6,6 +6,9 @@ using Model = Discord.API.User;


namespace Discord.WebSocket namespace Discord.WebSocket
{ {
/// <summary>
/// Represents the logged-in WebSocker-based user.
/// </summary>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class SocketSelfUser : SocketUser, ISelfUser public class SocketSelfUser : SocketUser, ISelfUser
{ {


+ 14
- 1
src/Discord.Net.WebSocket/Entities/Users/SocketUnknownUser.cs View File

@@ -4,17 +4,30 @@ using Model = Discord.API.User;


namespace Discord.WebSocket namespace Discord.WebSocket
{ {
/// <summary>
/// Represents a WebSocket-based user that is yet to be recognized by the client.
/// </summary>
/// <remarks>
/// A user may not be recognized due to the user missing from the cache or failed to be recognized properly.
/// </remarks>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class SocketUnknownUser : SocketUser public class SocketUnknownUser : SocketUser
{ {
/// <inheritdoc />
public override string Username { get; internal set; } public override string Username { get; internal set; }
/// <inheritdoc />
public override ushort DiscriminatorValue { get; internal set; } public override ushort DiscriminatorValue { get; internal set; }
/// <inheritdoc />
public override string AvatarId { get; internal set; } public override string AvatarId { get; internal set; }
/// <inheritdoc />
public override bool IsBot { get; internal set; } public override bool IsBot { get; internal set; }

/// <inheritdoc />
public override bool IsWebhook => false; public override bool IsWebhook => false;


internal override SocketPresence Presence { get { return new SocketPresence(UserStatus.Offline, null); } set { } } internal override SocketPresence Presence { get { return new SocketPresence(UserStatus.Offline, null); } set { } }
/// <inheritdoc />
/// <exception cref="NotSupportedException">This field is not supported for an unknown user.</exception>
internal override SocketGlobalUser GlobalUser => internal override SocketGlobalUser GlobalUser =>
throw new NotSupportedException(); throw new NotSupportedException();




+ 9
- 2
src/Discord.Net.WebSocket/Entities/Users/SocketVoiceState.cs View File

@@ -4,9 +4,15 @@ using Model = Discord.API.VoiceState;


namespace Discord.WebSocket namespace Discord.WebSocket
{ {
/// <summary>
/// Represents a WebSocket user's voice connection status.
/// </summary>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public struct SocketVoiceState : IVoiceState public struct SocketVoiceState : IVoiceState
{ {
/// <summary>
/// Initializes a default <see cref="SocketVoiceState"/> with everything set to <c>null</c> or <c>false</c>.
/// </summary>
public static readonly SocketVoiceState Default = new SocketVoiceState(null, null, false, false, false, false, false); public static readonly SocketVoiceState Default = new SocketVoiceState(null, null, false, false, false, false, false);


[Flags] [Flags]
@@ -64,15 +70,16 @@ namespace Discord.WebSocket
} }


/// <summary> /// <summary>
/// Gets the name of the voice channel.
/// Gets the name of this voice channel.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// The name of the voice channel.
/// A string that resolves to name of this voice channel; otherwise "Unknown".
/// </returns> /// </returns>
public override string ToString() => VoiceChannel?.Name ?? "Unknown"; public override string ToString() => VoiceChannel?.Name ?? "Unknown";
private string DebuggerDisplay => $"{VoiceChannel?.Name ?? "Unknown"} ({_voiceStates})"; private string DebuggerDisplay => $"{VoiceChannel?.Name ?? "Unknown"} ({_voiceStates})";
internal SocketVoiceState Clone() => this; internal SocketVoiceState Clone() => this;


/// <inheritdoc />
IVoiceChannel IVoiceState.VoiceChannel => VoiceChannel; IVoiceChannel IVoiceState.VoiceChannel => VoiceChannel;
} }
} }

Loading…
Cancel
Save