diff --git a/Discord.Net.sln b/Discord.Net.sln
index c11739aef..9f888cd12 100644
--- a/Discord.Net.sln
+++ b/Discord.Net.sln
@@ -42,8 +42,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Examples", "src
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "idn", "samples\idn\idn.csproj", "{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FeatureTesting", "..\FeatureTesting\FeatureTesting\FeatureTesting.csproj", "{0CC57A32-3AC7-489D-8DF5-C431925E4675}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
diff --git a/docs/guides/application-commands/context-menu-commands/creating-context-menu-commands.md b/docs/guides/application-commands/context-menu-commands/creating-context-menu-commands.md
index 4e1a42987..9100c3b42 100644
--- a/docs/guides/application-commands/context-menu-commands/creating-context-menu-commands.md
+++ b/docs/guides/application-commands/context-menu-commands/creating-context-menu-commands.md
@@ -15,14 +15,23 @@ Guild commands are specific to the guild you specify when making them. Guild com
If you don't have the code for a bot ready yet please follow [this guide](https://docs.stillu.cc/guides/getting_started/first-bot.html).
-## SlashCommandBuilder
+## UserCommandBuilder
-The slash command builder will help you create slash commands. The builder has these available fields and methods:
+The context menu user command builder will help you create user commands. The builder has these available fields and methods:
+
+| Name | Type | Description |
+| --------------------- | -------------------------------- | -------------------------------------------------------------------------------------------- |
+| Name | string | The name of this context menu command. |
+| WithName | Function | Sets the field name. |
+| Build | Function | Builds the builder into the appropriate `CommandCreationProperties` class used to make Menu commands |
+
+## MessageCommandBuilder
+
+The context menu message command builder will help you create message commands. The builder has these available fields and methods:
| Name | Type | Description |
| --------------------- | -------------------------------- | -------------------------------------------------------------------------------------------- |
| Name | string | The name of this context menu command. |
-| Description | string | A 0 length string. Left in place for possible future use. |
| WithName | Function | Sets the field name. |
| Build | Function | Builds the builder into the appropriate `CommandCreationProperties` class used to make Menu commands |
diff --git a/docs/guides/application-commands/context-menu-commands/receiving-context-menu-command-events.md b/docs/guides/application-commands/context-menu-commands/receiving-context-menu-command-events.md
index a1492fc50..52bc303e7 100644
--- a/docs/guides/application-commands/context-menu-commands/receiving-context-menu-command-events.md
+++ b/docs/guides/application-commands/context-menu-commands/receiving-context-menu-command-events.md
@@ -15,24 +15,21 @@ public async Task InteractionCreatedHandler(SocketInteraction arg)
public async Task ApplicationCommandHandler(SocketInteraction arg)
{
- var slashCommand = arg as SocketSlashCommand;
- if(slashCommand != null)
- Console.Writeline("Slash command received!")
-
- var userCommand = arg as SocketApplicationUserCommand;
- if(userCommand != null)
+ switch (arg)
{
- Console.Writeline("User command received!")
- // userCommand.User = User who ran command.
- // userCommand.Data.Member = User who was clicked.
- }
-
- var messageCommand = arg as SocketApplicationMessageCommand;
- if(messageCommand != null)
- {
- Console.Writeline("Message command received!")
- // messageCommand.User = User who ran command.
- // messageCommand.Data.Message = Message that was clicked.
+ case SocketSlashCommand slashCommand:
+ Console.Writeline("Slash command received!");
+ break;
+ case SocketUserCommand userCommand:
+ Console.Writeline("User command received!")
+ // userCommand.User = User who ran command.
+ // userCommand.Data.Member = User who was clicked.
+ break;
+ case SocketMessageCommand messageCommand:
+ Console.Writeline("Message command received!")
+ // messageCommand.User = User who ran command.
+ // messageCommand.Data.Message = Message that was clicked.
+ break;
}
}
```
diff --git a/src/Discord.Net.Core/CDN.cs b/src/Discord.Net.Core/CDN.cs
index e1e8e5e1a..b1879eebc 100644
--- a/src/Discord.Net.Core/CDN.cs
+++ b/src/Discord.Net.Core/CDN.cs
@@ -46,6 +46,24 @@ namespace Discord
string extension = FormatToExtension(format, avatarId);
return $"{DiscordConfig.CDNUrl}avatars/{userId}/{avatarId}.{extension}?size={size}";
}
+
+ ///
+ /// Returns a user banner URL.
+ ///
+ /// The user snowflake identifier.
+ /// The banner identifier.
+ /// The size of the image to return in horizontal pixels. This can be any power of two between 16 and 2048.
+ /// The format to return.
+ ///
+ /// A URL pointing to the user's banner in the specified size.
+ ///
+ public static string GetUserBannerUrl(ulong userId, string bannerId, ushort size, ImageFormat format)
+ {
+ if (bannerId == null)
+ return null;
+ string extension = FormatToExtension(format, bannerId);
+ return $"{DiscordConfig.CDNUrl}banners/{userId}/{bannerId}.{extension}?size={size}";
+ }
///
/// Returns the default user avatar URL.
///
diff --git a/src/Discord.Net.Core/Discord.Net.Core.csproj b/src/Discord.Net.Core/Discord.Net.Core.csproj
index f0be10059..ac54b259c 100644
--- a/src/Discord.Net.Core/Discord.Net.Core.csproj
+++ b/src/Discord.Net.Core/Discord.Net.Core.csproj
@@ -1,4 +1,4 @@
-
+
@@ -8,12 +8,12 @@
net461;netstandard2.0;netstandard2.1
netstandard2.0;netstandard2.1
Discord.Net.Labs.Core
- 3.0.0-pre
+ 3.0.1-pre
Discord.Net.Labs.Core
https://github.com/Discord-Net-Labs/Discord.Net-Labs
Temporary.png
- 2.3.8
- 2.3.8
+ 3.3.1
+ 3.0.1
false
diff --git a/src/Discord.Net.Core/Discord.Net.Core.xml b/src/Discord.Net.Core/Discord.Net.Core.xml
index d1e4770e3..8be13e6bd 100644
--- a/src/Discord.Net.Core/Discord.Net.Core.xml
+++ b/src/Discord.Net.Core/Discord.Net.Core.xml
@@ -100,6 +100,18 @@
A URL pointing to the user's avatar in the specified size.
+
+
+ Returns a user banner URL.
+
+ The user snowflake identifier.
+ The banner identifier.
+ The size of the image to return in horizontal pixels. This can be any power of two between 16 and 2048.
+ The format to return.
+
+ A URL pointing to the user's banner in the specified size.
+
+
Returns the default user avatar URL.
@@ -3902,6 +3914,16 @@
A task that represents the asynchronous removal operation.
+
+
+ Gets this guilds slash commands commands
+
+ The options to be used when sending the request.
+
+ A task that represents the asynchronous get operation. The task result contains a read-only collection
+ of application commands found within the guild.
+
+
Holds information for a guild integration feature.
@@ -4467,6 +4489,41 @@
Whether the command is enabled by default when the app is added to a guild. Default is
+
+
+ ApplicationCommandType is enum of current valid Application Command Types: Slash, User, Message
+
+
+
+
+ ApplicationCommandType.Slash is Slash command type
+
+
+
+
+ ApplicationCommandType.User is Context Menu User command type
+
+
+
+
+ ApplicationCommandType.Message is Context Menu Message command type
+
+
+
+
+ A class used to create Message commands.
+
+
+
+
+ The name of this command.
+
+
+
+
+ Gets or sets the type for this command.
+
+
The base command model that belongs to an application. see
@@ -4502,13 +4559,6 @@
If the option is a subcommand or subcommand group type, this nested options will be the parameters.
-
-
- Deletes this command
-
- The options to be used when sending the request.
- A task that represents the asynchronous delete operation.
-
Represents data of an Interaction Command, see .
@@ -4642,6 +4692,58 @@
read-only property, always 1.
+
+
+ Responds to an Interaction with type .
+
+ The text of the message to be sent.
+ A array of embeds to send with this response. Max 10
+ if the message should be read out by a text-to-speech reader, otherwise .
+ if the response should be hidden to everyone besides the invoker of the command, otherwise .
+ The allowed mentions for this response.
+ The request options for this response.
+ A to be sent with this response
+ A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored.
+
+
+
+ Sends a followup message for this interaction.
+
+ The text of the message to be sent
+ A array of embeds to send with this response. Max 10
+ if the message should be read out by a text-to-speech reader, otherwise .
+ if the response should be hidden to everyone besides the invoker of the command, otherwise .
+ The allowed mentions for this response.
+ The request options for this response.
+ A to be sent with this response
+ A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored.
+
+ The sent message.
+
+
+
+
+ Gets the original response for this interaction.
+
+ The request options for this async request.
+ A that represents the initial response.
+
+
+
+ Edits original response for this interaction.
+
+ A delegate containing the properties to modify the message with.
+ The request options for this async request.
+ A that represents the initial response.
+
+
+
+ Acknowledges this interaction.
+
+
+ A task that represents the asynchronous operation of acknowledging the interaction.
+
+
Represents an interface used to specify classes that they are a vaild dataype of a class.
@@ -4792,7 +4894,7 @@
Represents a builder for creating a .
-
+
The max length of a .
@@ -4915,11 +5017,16 @@
Represents a class used to build 's.
+
+
+ The max length of a .
+
+
Gets or sets the label of the current button.
- length exceeds .
+ length exceeds .
@@ -5239,16 +5346,26 @@
Represents a class used to build 's.
+
+
+ The maximum length of a .
+
+
The maximum length of a .
+
+
+ The maximum length of a .
+
+
Gets or sets the label of the current select menu.
- length exceeds
+ length exceeds
@@ -5456,7 +5573,7 @@
- A class used to build slash commands.
+ A class used to build Message commands.
@@ -5464,26 +5581,16 @@
Returns the maximun length a commands name allowed by Discord
-
-
- Returns the maximum length of a commands description allowed by Discord.
-
-
- The name of this slash command.
-
-
-
-
- A 1-100 length description of this slash command
+ The name of this Message command.
- Build the current builder into a class.
+ Build the current builder into a class.
- A that can be used to create user commands over rest.
+ A that can be used to create message commands over rest.
@@ -5494,33 +5601,6 @@
The current builder.
-
-
- Sets the description of the current command.
-
- The description of this command.
- The current builder.
-
-
-
- A class used to create Message commands.
-
-
-
-
- The name of this command.
-
-
-
-
- The discription of this command.
-
-
-
-
- Gets or sets the type for this command.
-
-
A class used to build slash commands.
@@ -5785,7 +5865,7 @@
- A class used to build slash commands.
+ A class used to build user commands.
@@ -5793,26 +5873,16 @@
Returns the maximun length a commands name allowed by Discord
-
-
- Returns the maximum length of a commands description allowed by Discord.
-
-
- The name of this slash command.
-
-
-
-
- A 1-100 length description of this slash command
+ The name of this User command.
- Build the current builder into a class.
+ Build the current builder into a class.
- A that can be used to create user commands over rest.
+ A that can be used to create user commands over rest.
@@ -5823,13 +5893,6 @@
The current builder.
-
-
- Sets the description of the current command.
-
- The description of this command.
- The current builder.
-
A class used to create User commands.
@@ -7751,7 +7814,7 @@
Gets or sets a single embed for this message.
- This property will be added to the array, in the future please use the array rather then this property.
+ This property will be added to the array, in the future please use the array rather than this property.
@@ -8794,7 +8857,25 @@
If true, a user may edit the webhooks for this guild.
- If true, a user may edit the emojis for this guild.
+ If true, a user may edit the emojis and stickers for this guild.
+
+
+ If true, a user may use slash commands in this guild.
+
+
+ If true, a user may request to speak in stage channels.
+
+
+ If true, a user may manage threads in this guild.
+
+
+ If true, a user may create public threads in this guild.
+
+
+ If true, a user may create private threads in this guild.
+
+
+ If true, a user may use external stickers in this guild.
Creates a new with the provided packed value.
@@ -8802,10 +8883,10 @@
Creates a new with the provided packed value after converting to ulong.
-
+
Creates a new structure with the provided permissions.
-
+
Creates a new from this one, changing the provided non-null permissions.
@@ -8992,6 +9073,9 @@
Represents a color used in Discord.
+
+ Gets the max decimal value of color.
+
Gets the default user color value.
@@ -9096,20 +9180,21 @@
Initializes a struct with the given raw value.
- The following will create a color that has a hex value of
+ The following will create a color that has a hex value of
#607D8B.
Color darkGrey = new Color(0x607D8B);
The raw value of the color (e.g. 0x607D8B).
+ Value exceeds .
Initializes a struct with the given RGB bytes.
- The following will create a color that has a value of
+ The following will create a color that has a value of
#607D8B.
Color darkGrey = new Color((byte)0b_01100000, (byte)0b_01111101, (byte)0b_10001011);
@@ -9118,13 +9203,14 @@
The byte that represents the red color.
The byte that represents the green color.
The byte that represents the blue color.
+ Value exceeds .
Initializes a struct with the given RGB value.
- The following will create a color that has a value of
+ The following will create a color that has a value of
#607D8B.
Color darkGrey = new Color(96, 125, 139);
@@ -9140,7 +9226,7 @@
Initializes a struct with the given RGB float value.
- The following will create a color that has a value of
+ The following will create a color that has a value of
#607c8c.
Color darkGrey = new Color(0.38f, 0.49f, 0.55f);
@@ -9908,19 +9994,33 @@
Gets the identifier of this user's avatar.
+
+
+ Gets the identifier of this user's banner.
+
+
+
+
+ Gets the user's banner color.
+
+
+ A struct representing the accent color of this user's banner.
+
+
Gets the avatar URL for this user.
This property retrieves a URL for this user's avatar. In event that the user does not have a valid avatar
- (i.e. their avatar identifier is not set), this property will return null. If you wish to
+ (i.e. their avatar identifier is not set), this method will return null. If you wish to
retrieve the default avatar for this user, consider using (see
example).
- The following example attempts to retrieve the user's current avatar and send it to a channel; if one is
- not set, a default avatar for this user will be returned instead.
+ The following example attempts to retrieve the user's current avatar and send it to a channel; if one is
+ not set, a default avatar for this user will be returned instead.
@@ -9931,6 +10031,17 @@
A string representing the user's avatar URL; null if the user does not have an avatar in place.
+
+
+ Gets the banner URL for this user.
+
+ The format to return.
+ The size of the image to return in. This can be any power of two between 16 and 2048.
+
+
+ A string representing the user's avatar URL; null if the user does not have an banner in place.
+
+
Gets the default avatar URL for this user.
@@ -9998,8 +10109,8 @@
This method is used to obtain or create a channel used to send a direct message.
In event that the current user cannot send a message to the target user, a channel can and will
- still be created by Discord. However, attempting to send a message will yield a
- with a 403 as its
+ still be created by Discord. However, attempting to send a message will yield a
+ with a 403 as its
. There are currently no official workarounds by
Discord.
@@ -10293,6 +10404,11 @@
Gets the user that created this webhook.
+
+
+ Gets the ID of the application owning this webhook.
+
+
Modifies this webhook.
diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
index ad2e0317d..414b6fe73 100644
--- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
+++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
@@ -941,5 +941,15 @@ namespace Discord
/// A task that represents the asynchronous removal operation.
///
Task DeleteEmoteAsync(GuildEmote emote, RequestOptions options = null);
+
+ ///
+ /// Gets this guilds slash commands commands
+ ///
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation. The task result contains a read-only collection
+ /// of application commands found within the guild.
+ ///
+ Task> GetApplicationCommandsAsync (RequestOptions options = null);
}
}
diff --git a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandTypes.cs b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandTypes.cs
index 23b00f2a2..de9c1a263 100644
--- a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandTypes.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandTypes.cs
@@ -6,10 +6,22 @@ using System.Threading.Tasks;
namespace Discord
{
+ ///
+ /// ApplicationCommandType is enum of current valid Application Command Types: Slash, User, Message
+ ///
public enum ApplicationCommandType : byte
{
+ ///
+ /// ApplicationCommandType.Slash is Slash command type
+ ///
Slash = 1,
+ ///
+ /// ApplicationCommandType.User is Context Menu User command type
+ ///
User = 2,
+ ///
+ /// ApplicationCommandType.Message is Context Menu Message command type
+ ///
Message = 3
}
}
diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageCommandCreationProperties.cs b/src/Discord.Net.Core/Entities/Interactions/ContextMenuCommandCreationProperties.cs
similarity index 73%
rename from src/Discord.Net.Core/Entities/Interactions/MessageCommandCreationProperties.cs
rename to src/Discord.Net.Core/Entities/Interactions/ContextMenuCommandCreationProperties.cs
index 7c7dac593..4ddc0a7b1 100644
--- a/src/Discord.Net.Core/Entities/Interactions/MessageCommandCreationProperties.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/ContextMenuCommandCreationProperties.cs
@@ -9,19 +9,13 @@ namespace Discord
///
/// A class used to create Message commands.
///
- public class MessageCommandCreationProperties
+ public class ContextMenuCommandCreationProperties
{
///
/// The name of this command.
///
public string Name { get; set; }
- ///
- /// The discription of this command.
- ///
- public string Description { get; set; }
-
-
///
/// Gets or sets the type for this command.
///
diff --git a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs
index ab4b3eac0..e15843d98 100644
--- a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs
@@ -9,7 +9,7 @@ namespace Discord
///
/// The base command model that belongs to an application. see
///
- public interface IApplicationCommand : ISnowflakeEntity
+ public interface IApplicationCommand : ISnowflakeEntity, IDeletable
{
///
/// Gets the unique id of the parent application.
@@ -40,12 +40,5 @@ namespace Discord
/// If the option is a subcommand or subcommand group type, this nested options will be the parameters.
///
IReadOnlyCollection Options { get; }
-
- ///
- /// Deletes this command
- ///
- /// The options to be used when sending the request.
- /// A task that represents the asynchronous delete operation.
- Task DeleteAsync(RequestOptions options = null);
}
}
diff --git a/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs b/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs
index 466bf3e91..ae015c2a6 100644
--- a/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs
@@ -39,5 +39,59 @@ namespace Discord
/// read-only property, always 1.
///
int Version { get; }
+
+ ///
+ /// Responds to an Interaction with type .
+ ///
+ /// The text of the message to be sent.
+ /// A array of embeds to send with this response. Max 10
+ /// if the message should be read out by a text-to-speech reader, otherwise .
+ /// if the response should be hidden to everyone besides the invoker of the command, otherwise .
+ /// The allowed mentions for this response.
+ /// The request options for this response.
+ /// A to be sent with this response
+ /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored.
+ Task RespondAsync (string text = null, Embed[] embeds = null, bool isTTS = false,
+ bool ephemeral = false, AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent component = null, Embed embed = null);
+
+ ///
+ /// Sends a followup message for this interaction.
+ ///
+ /// The text of the message to be sent
+ /// A array of embeds to send with this response. Max 10
+ /// if the message should be read out by a text-to-speech reader, otherwise .
+ /// if the response should be hidden to everyone besides the invoker of the command, otherwise .
+ /// The allowed mentions for this response.
+ /// The request options for this response.
+ /// A to be sent with this response
+ /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored.
+ ///
+ /// The sent message.
+ ///
+ Task FollowupAsync (string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false,
+ AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent component = null, Embed embed = null);
+
+ ///
+ /// Gets the original response for this interaction.
+ ///
+ /// The request options for this async request.
+ /// A that represents the initial response.
+ Task GetOriginalResponseAsync (RequestOptions options = null);
+
+ ///
+ /// Edits original response for this interaction.
+ ///
+ /// A delegate containing the properties to modify the message with.
+ /// The request options for this async request.
+ /// A that represents the initial response.
+ Task ModifyOriginalResponseAsync (Action func, RequestOptions options = null);
+
+ ///
+ /// Acknowledges this interaction.
+ ///
+ ///
+ /// A task that represents the asynchronous operation of acknowledging the interaction.
+ ///
+ Task DeferAsync (bool ephemeral = false, RequestOptions options = null);
}
}
diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs
index bb2f80a81..085c62cef 100644
--- a/src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs
@@ -13,7 +13,7 @@ namespace Discord
///
/// The max length of a .
///
- public const int MaxLabelLength = 80;
+ public const int MaxButtonLabelLength = 80;
///
/// The max length of a .
@@ -307,17 +307,22 @@ namespace Discord
///
public class ButtonBuilder
{
+ ///
+ /// The max length of a .
+ ///
+ public const int MaxLabelLength = 80;
+
///
/// Gets or sets the label of the current button.
///
- /// length exceeds .
+ /// length exceeds .
public string Label
{
get => _label;
set
{
- if (value != null && value.Length > ComponentBuilder.MaxLabelLength)
- throw new ArgumentException(message: $"Button label must be {ComponentBuilder.MaxLabelLength} characters or less!", paramName: nameof(Label));
+ if (value != null && value.Length > ComponentBuilder.MaxButtonLabelLength)
+ throw new ArgumentException(message: $"Button label must be {ComponentBuilder.MaxButtonLabelLength} characters or less!", paramName: nameof(Label));
_label = value;
}
@@ -539,8 +544,8 @@ namespace Discord
if (string.IsNullOrEmpty(this.Url))
throw new InvalidOperationException("Link buttons must have a link associated with them");
else
- UrlValidation.Validate(this.Url);
- }
+ UrlValidation.Validate(this.Url);
+ }
else if (string.IsNullOrEmpty(this.CustomId))
throw new InvalidOperationException("Non-link buttons must have a custom id associated with them");
@@ -831,23 +836,33 @@ namespace Discord
///
public class SelectMenuOptionBuilder
{
+ ///
+ /// The maximum length of a .
+ ///
+ public const int MaxLabelLength = 100;
+
///
/// The maximum length of a .
///
- public const int MaxDescriptionLength = 50;
+ public const int MaxDescriptionLength = 100;
+
+ ///
+ /// The maximum length of a .
+ ///
+ public const int MaxSelectLabelLength = 100;
///
/// Gets or sets the label of the current select menu.
///
- /// length exceeds
+ /// length exceeds
public string Label
{
get => _label;
set
{
if (value != null)
- if (value.Length > ComponentBuilder.MaxLabelLength)
- throw new ArgumentException(message: $"Button label must be {ComponentBuilder.MaxLabelLength} characters or less!", paramName: nameof(Label));
+ if (value.Length > MaxSelectLabelLength)
+ throw new ArgumentException(message: $"Button label must be {MaxSelectLabelLength} characters or less!", paramName: nameof(Label));
_label = value;
}
diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageCommandBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageCommandBuilder.cs
index 792d7d19f..b658a181b 100644
--- a/src/Discord.Net.Core/Entities/Interactions/MessageCommandBuilder.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/MessageCommandBuilder.cs
@@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace Discord
{
///
- /// A class used to build slash commands.
+ /// A class used to build Message commands.
///
public class MessageCommandBuilder
{
@@ -16,13 +16,9 @@ namespace Discord
/// Returns the maximun length a commands name allowed by Discord
///
public const int MaxNameLength = 32;
- ///
- /// Returns the maximum length of a commands description allowed by Discord.
- ///
- public const int MaxDescriptionLength = 0;
///
- /// The name of this slash command.
+ /// The name of this Message command.
///
public string Name
{
@@ -45,36 +41,17 @@ namespace Discord
}
}
- ///
- /// A 1-100 length description of this slash command
- ///
- public string Description
- {
- get
- {
- return _description;
- }
- set
- {
- Preconditions.Equals(value, "");
-
- _description = value;
- }
- }
-
private string _name { get; set; }
- private string _description { get; set; }
///
- /// Build the current builder into a class.
+ /// Build the current builder into a class.
///
- /// A that can be used to create user commands over rest.
- public MessageCommandCreationProperties Build()
+ /// A that can be used to create message commands over rest.
+ public ContextMenuCommandCreationProperties Build()
{
- MessageCommandCreationProperties props = new MessageCommandCreationProperties()
+ ContextMenuCommandCreationProperties props = new ContextMenuCommandCreationProperties()
{
Name = this.Name,
- Description = this.Description,
Type=ApplicationCommandType.Message
};
@@ -93,17 +70,6 @@ namespace Discord
{
this.Name = name;
return this;
- }
-
- ///
- /// Sets the description of the current command.
- ///
- /// The description of this command.
- /// The current builder.
- public MessageCommandBuilder WithDescription(string description)
- {
- this.Description = description;
- return this;
- }
+ }
}
}
diff --git a/src/Discord.Net.Core/Entities/Interactions/UserCommandBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/UserCommandBuilder.cs
index 0dc6526ba..f10b6b123 100644
--- a/src/Discord.Net.Core/Entities/Interactions/UserCommandBuilder.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/UserCommandBuilder.cs
@@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace Discord
{
///
- /// A class used to build slash commands.
+ /// A class used to build user commands.
///
public class UserCommandBuilder
{
@@ -16,13 +16,9 @@ namespace Discord
/// Returns the maximun length a commands name allowed by Discord
///
public const int MaxNameLength = 32;
- ///
- /// Returns the maximum length of a commands description allowed by Discord.
- ///
- public const int MaxDescriptionLength = 0;
///
- /// The name of this slash command.
+ /// The name of this User command.
///
public string Name
{
@@ -45,36 +41,17 @@ namespace Discord
}
}
- ///
- /// A 1-100 length description of this slash command
- ///
- public string Description
- {
- get
- {
- return _description;
- }
- set
- {
- Preconditions.Equals(value, "");
-
- _description = value;
- }
- }
-
private string _name { get; set; }
- private string _description { get; set; }
///
- /// Build the current builder into a class.
+ /// Build the current builder into a class.
///
- /// A that can be used to create user commands over rest.
- public UserCommandCreationProperties Build()
+ /// A that can be used to create user commands over rest.
+ public ContextMenuCommandCreationProperties Build()
{
- UserCommandCreationProperties props = new UserCommandCreationProperties()
+ ContextMenuCommandCreationProperties props = new ContextMenuCommandCreationProperties()
{
Name = this.Name,
- Description = this.Description,
Type=ApplicationCommandType.User
};
@@ -93,17 +70,6 @@ namespace Discord
{
this.Name = name;
return this;
- }
-
- ///
- /// Sets the description of the current command.
- ///
- /// The description of this command.
- /// The current builder.
- public UserCommandBuilder WithDescription(string description)
- {
- this.Description = description;
- return this;
- }
+ }
}
}
diff --git a/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs b/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs
index 2ab2699a6..5b92e02a5 100644
--- a/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs
+++ b/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs
@@ -411,7 +411,7 @@ namespace Discord
UrlValidation.Validate(Url);
if (!string.IsNullOrEmpty(ThumbnailUrl))
UrlValidation.Validate(ThumbnailUrl);
- if (!string.IsNullOrEmpty(ImageUrl))
+ if (!string.IsNullOrEmpty(ImageUrl) && !ImageUrl.StartsWith("attachment://", StringComparison.Ordinal))
UrlValidation.Validate(ImageUrl);
if (Author != null)
{
diff --git a/src/Discord.Net.Core/Entities/Messages/MessageProperties.cs b/src/Discord.Net.Core/Entities/Messages/MessageProperties.cs
index 19cfacebe..abd09d856 100644
--- a/src/Discord.Net.Core/Entities/Messages/MessageProperties.cs
+++ b/src/Discord.Net.Core/Entities/Messages/MessageProperties.cs
@@ -22,7 +22,7 @@ namespace Discord
/// Gets or sets a single embed for this message.
///
///
- /// This property will be added to the array, in the future please use the array rather then this property.
+ /// This property will be added to the array, in the future please use the array rather than this property.
///
public Optional
..\Discord.Net.Rest\Discord.Net.Rest.xml
diff --git a/src/Discord.Net.Rest/Discord.Net.Rest.xml b/src/Discord.Net.Rest/Discord.Net.Rest.xml
index c6c81ee75..0fc188b2e 100644
--- a/src/Discord.Net.Rest/Discord.Net.Rest.xml
+++ b/src/Discord.Net.Rest/Discord.Net.Rest.xml
@@ -3493,6 +3493,16 @@
of webhooks found within the guild.
+
+
+ Gets this guilds slash commands commands
+
+ The options to be used when sending the request.
+
+ A task that represents the asynchronous get operation. The task result contains a read-only collection
+ of application commands found within the guild.
+
+
Returns the name of the guild.
@@ -3650,6 +3660,9 @@
+
+
+
@@ -4667,7 +4680,7 @@
- Represents a thread user recieved over the REST api.
+ Represents a thread user received over the REST api.
@@ -4690,7 +4703,7 @@
Gets the guild user for this thread user.
- A task representing the asyncronous get operation. The task returns a
+ A task representing the asynchronous get operation. The task returns a
that represents the current thread user.
@@ -4711,6 +4724,12 @@
+
+
+
+
+
+
@@ -4753,6 +4772,9 @@
+
+
+
@@ -4875,6 +4897,9 @@
+
+
+
diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs
index 42cde4cfc..8bf7f6e43 100644
--- a/src/Discord.Net.Rest/DiscordRestApiClient.cs
+++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs
@@ -55,7 +55,7 @@ namespace Discord.API
_restClientProvider = restClientProvider;
UserAgent = userAgent;
DefaultRetryMode = defaultRetryMode;
- _serializer = serializer ?? new JsonSerializer { ContractResolver = new DiscordContractResolver(), NullValueHandling = NullValueHandling.Ignore };
+ _serializer = serializer ?? new JsonSerializer { ContractResolver = new DiscordContractResolver(), NullValueHandling = NullValueHandling.Include };
UseSystemClock = useSystemClock;
RequestQueue = new RequestQueue();
@@ -1113,11 +1113,8 @@ namespace Discord.API
Preconditions.NotNull(command, nameof(command));
Preconditions.AtMost(command.Name.Length, 32, nameof(command.Name));
Preconditions.AtLeast(command.Name.Length, 3, nameof(command.Name));
- Preconditions.Equals(command.Description, "");
- options = RequestOptions.CreateOrClone(options);
-
-
+ options = RequestOptions.CreateOrClone(options);
return await TrySendApplicationCommand(SendJsonAsync("POST", () => $"applications/{this.CurrentUserId}/commands", command, new BucketIds(), options: options)).ConfigureAwait(false);
}
@@ -1126,12 +1123,9 @@ namespace Discord.API
Preconditions.NotNull(command, nameof(command));
Preconditions.AtMost(command.Name.Length, 32, nameof(command.Name));
Preconditions.AtLeast(command.Name.Length, 3, nameof(command.Name));
- Preconditions.Equals(command.Description, "");
options = RequestOptions.CreateOrClone(options);
-
-
return await TrySendApplicationCommand(SendJsonAsync("POST", () => $"applications/{this.CurrentUserId}/commands", command, new BucketIds(), options: options)).ConfigureAwait(false);
}
@@ -1174,7 +1168,6 @@ namespace Discord.API
var bucket = new BucketIds(guildId: guildId);
return await TrySendApplicationCommand(SendJsonAsync("POST", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", command, bucket, options: options)).ConfigureAwait(false);
-
}
public async Task ModifyGuildApplicationCommandAsync(ModifyApplicationCommandParams command, ulong guildId, ulong commandId, RequestOptions options = null)
{
@@ -1182,21 +1175,7 @@ namespace Discord.API
var bucket = new BucketIds(guildId: guildId);
- try
- {
- return await SendJsonAsync("PATCH", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", command, bucket, options: options).ConfigureAwait(false);
- }
- catch (HttpException x)
- {
- if (x.HttpCode == HttpStatusCode.BadRequest)
- {
- var json = (x.Request as JsonRestRequest).Json;
- throw new ApplicationCommandException(json, x);
- }
-
- // Re-throw the http exception
- throw;
- }
+ return await TrySendApplicationCommand(SendJsonAsync("PATCH", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", command, bucket, options: options)).ConfigureAwait(false);
}
public async Task DeleteGuildApplicationCommandAsync(ulong guildId, ulong commandId, RequestOptions options = null)
{
@@ -1223,29 +1202,15 @@ namespace Discord.API
var bucket = new BucketIds(guildId: guildId);
return await TrySendApplicationCommand(SendJsonAsync("POST", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", command, bucket, options: options)).ConfigureAwait(false);
-
}
+
public async Task ModifyGuildApplicationUserCommandAsync(ModifyApplicationCommandParams command, ulong guildId, ulong commandId, RequestOptions options = null)
{
options = RequestOptions.CreateOrClone(options);
var bucket = new BucketIds(guildId: guildId);
- try
- {
- return await SendJsonAsync("PATCH", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", command, bucket, options: options).ConfigureAwait(false);
- }
- catch (HttpException x)
- {
- if (x.HttpCode == HttpStatusCode.BadRequest)
- {
- var json = (x.Request as JsonRestRequest).Json;
- throw new ApplicationCommandException(json, x);
- }
-
- // Re-throw the http exception
- throw;
- }
+ return await TrySendApplicationCommand(SendJsonAsync("PATCH", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", command, bucket, options: options)).ConfigureAwait(false);
}
public async Task BulkOverwriteGuildApplicationUserCommands(ulong guildId, CreateApplicationCommandParams[] commands, RequestOptions options = null)
{
@@ -1263,7 +1228,6 @@ namespace Discord.API
var bucket = new BucketIds(guildId: guildId);
return await TrySendApplicationCommand(SendJsonAsync("POST", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", command, bucket, options: options)).ConfigureAwait(false);
-
}
public async Task ModifyGuildApplicationMessageCommandAsync(ModifyApplicationCommandParams command, ulong guildId, ulong commandId, RequestOptions options = null)
{
@@ -1271,21 +1235,7 @@ namespace Discord.API
var bucket = new BucketIds(guildId: guildId);
- try
- {
- return await SendJsonAsync("PATCH", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", command, bucket, options: options).ConfigureAwait(false);
- }
- catch (HttpException x)
- {
- if (x.HttpCode == HttpStatusCode.BadRequest)
- {
- var json = (x.Request as JsonRestRequest).Json;
- throw new ApplicationCommandException(json, x);
- }
-
- // Re-throw the http exception
- throw;
- }
+ return await TrySendApplicationCommand(SendJsonAsync("PATCH", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", command, bucket, options: options)).ConfigureAwait(false);
}
public async Task BulkOverwriteGuildApplicationMessageCommands(ulong guildId, CreateApplicationCommandParams[] commands, RequestOptions options = null)
diff --git a/src/Discord.Net.Rest/DiscordRestClient.cs b/src/Discord.Net.Rest/DiscordRestClient.cs
index cb28d19b6..c204a2d1c 100644
--- a/src/Discord.Net.Rest/DiscordRestClient.cs
+++ b/src/Discord.Net.Rest/DiscordRestClient.cs
@@ -112,25 +112,25 @@ namespace Discord.Rest
=> InteractionHelper.CreateGlobalCommand(this, properties, options);
public Task CreateGlobalCommand(Action func, RequestOptions options = null)
=> InteractionHelper.CreateGlobalCommand(this, func, options);
- public Task CreateGlobalUserCommand(UserCommandCreationProperties properties, RequestOptions options = null)
+ public Task CreateGlobalUserCommand(ContextMenuCommandCreationProperties properties, RequestOptions options = null)
=> InteractionHelper.CreateGlobalUserCommand(this, properties, options);
- public Task CreateGlobalUserCommand(Action func, RequestOptions options = null)
+ public Task CreateGlobalUserCommand(Action func, RequestOptions options = null)
=> InteractionHelper.CreateGlobalUserCommand(this, func, options);
- public Task CreateGlobalMessageCommand(MessageCommandCreationProperties properties, RequestOptions options = null)
+ public Task CreateGlobalMessageCommand(ContextMenuCommandCreationProperties properties, RequestOptions options = null)
=> InteractionHelper.CreateGlobalMessageCommand(this, properties, options);
- public Task CreateGlobalMessageCommand(Action func, RequestOptions options = null)
+ public Task CreateGlobalMessageCommand(Action func, RequestOptions options = null)
=> InteractionHelper.CreateGlobalMessageCommand(this, func, options);
public Task CreateGuildCommand(SlashCommandCreationProperties properties, ulong guildId, RequestOptions options = null)
=> InteractionHelper.CreateGuildCommand(this, guildId, properties, options);
public Task CreateGuildCommand(Action func, ulong guildId, RequestOptions options = null)
=> InteractionHelper.CreateGuildCommand(this, guildId, func, options);
- public Task CreateGuildUserCommand(UserCommandCreationProperties properties, ulong guildId, RequestOptions options = null)
+ public Task CreateGuildUserCommand(ContextMenuCommandCreationProperties properties, ulong guildId, RequestOptions options = null)
=> InteractionHelper.CreateGuildUserCommand(this, guildId, properties, options);
- public Task CreateGuildUserCommand(Action func, ulong guildId, RequestOptions options = null)
+ public Task CreateGuildUserCommand(Action func, ulong guildId, RequestOptions options = null)
=> InteractionHelper.CreateGuildUserCommand(this, guildId, func, options);
- public Task CreateGuildMessageCommand(MessageCommandCreationProperties properties, ulong guildId, RequestOptions options = null)
+ public Task CreateGuildMessageCommand(ContextMenuCommandCreationProperties properties, ulong guildId, RequestOptions options = null)
=> InteractionHelper.CreateGuildMessageCommand(this, guildId, properties, options);
- public Task CreateGuildMessageCommand(Action func, ulong guildId, RequestOptions options = null)
+ public Task CreateGuildMessageCommand(Action func, ulong guildId, RequestOptions options = null)
=> InteractionHelper.CreateGuildMessageCommand(this, guildId, func, options);
public Task> GetGlobalApplicationCommands(RequestOptions options = null)
=> ClientHelper.GetGlobalApplicationCommands(this, options);
diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
index 2fab63347..126a211c8 100644
--- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
+++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
@@ -869,6 +869,18 @@ namespace Discord.Rest
public Task> GetWebhooksAsync(RequestOptions options = null)
=> GuildHelper.GetWebhooksAsync(this, Discord, options);
+ //Interactions
+ ///
+ /// Gets this guilds slash commands commands
+ ///
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation. The task result contains a read-only collection
+ /// of application commands found within the guild.
+ ///
+ public async Task> GetApplicationCommandsAsync (RequestOptions options = null)
+ => await ClientHelper.GetGuildApplicationCommands(Discord, Id, options).ConfigureAwait(false);
+
///
/// Returns the name of the guild.
///
@@ -1154,6 +1166,8 @@ namespace Discord.Rest
///
async Task> IGuild.GetWebhooksAsync(RequestOptions options)
=> await GetWebhooksAsync(options).ConfigureAwait(false);
-
+ ///
+ async Task> IGuild.GetApplicationCommandsAsync (RequestOptions options)
+ => await GetApplicationCommandsAsync(options).ConfigureAwait(false);
}
}
diff --git a/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs b/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs
index d5006a6a9..b5c354047 100644
--- a/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs
+++ b/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs
@@ -200,22 +200,20 @@ namespace Discord.Rest
await client.ApiClient.DeleteGlobalApplicationCommandAsync(command.Id, options).ConfigureAwait(false);
}
- public static async Task CreateGlobalUserCommand(BaseDiscordClient client, Action func, RequestOptions options = null)
+ public static async Task CreateGlobalUserCommand(BaseDiscordClient client, Action func, RequestOptions options = null)
{
- var args = new UserCommandCreationProperties();
+ var args = new ContextMenuCommandCreationProperties();
func(args);
return await CreateGlobalUserCommand(client, args, options).ConfigureAwait(false);
}
- public static async Task CreateGlobalUserCommand(BaseDiscordClient client, UserCommandCreationProperties arg, RequestOptions options = null)
+ public static async Task CreateGlobalUserCommand(BaseDiscordClient client, ContextMenuCommandCreationProperties arg, RequestOptions options = null)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
- Preconditions.Equals(arg.Description, "");
var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
- Description = arg.Description,
Type = arg.Type
};
@@ -223,22 +221,20 @@ namespace Discord.Rest
return RestGlobalUserCommand.Create(client, cmd);
}
- public static async Task CreateGlobalMessageCommand(BaseDiscordClient client, Action func, RequestOptions options = null)
+ public static async Task CreateGlobalMessageCommand(BaseDiscordClient client, Action func, RequestOptions options = null)
{
- var args = new MessageCommandCreationProperties();
+ var args = new ContextMenuCommandCreationProperties();
func(args);
return await CreateGlobalMessageCommand(client, args, options).ConfigureAwait(false);
}
- public static async Task CreateGlobalMessageCommand(BaseDiscordClient client, MessageCommandCreationProperties arg, RequestOptions options = null)
+ public static async Task CreateGlobalMessageCommand(BaseDiscordClient client, ContextMenuCommandCreationProperties arg, RequestOptions options = null)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
- Preconditions.Equals(arg.Description, "");
var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
- Description = arg.Description,
Type = arg.Type
};
@@ -246,7 +242,7 @@ namespace Discord.Rest
return RestGlobalMessageCommand.Create(client, cmd);
}
- public static async Task> BulkOverwriteGlobalUserCommands(BaseDiscordClient client, UserCommandCreationProperties[] args, RequestOptions options = null)
+ public static async Task> BulkOverwriteGlobalUserCommands(BaseDiscordClient client, ContextMenuCommandCreationProperties[] args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));
@@ -255,13 +251,11 @@ namespace Discord.Rest
foreach (var arg in args)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
- Preconditions.NotNullOrEmpty(arg.Description, nameof(arg.Description));
Preconditions.Equals(arg.Type, ApplicationCommandType.User);
var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
- Description = arg.Description,
Type = arg.Type
};
@@ -307,7 +301,7 @@ namespace Discord.Rest
await client.ApiClient.DeleteGlobalApplicationCommandAsync(command.Id, options).ConfigureAwait(false);
}
- public static async Task> BulkOverwriteGlobalMessageCommands(BaseDiscordClient client, MessageCommandCreationProperties[] args, RequestOptions options = null)
+ public static async Task> BulkOverwriteGlobalMessageCommands(BaseDiscordClient client, ContextMenuCommandCreationProperties[] args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));
@@ -316,13 +310,11 @@ namespace Discord.Rest
foreach (var arg in args)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
- Preconditions.NotNullOrEmpty(arg.Description, nameof(arg.Description));
Preconditions.Equals(arg.Type, ApplicationCommandType.Message);
var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
- Description = arg.Description,
Type = arg.Type
};
@@ -465,22 +457,20 @@ namespace Discord.Rest
await client.ApiClient.DeleteGuildApplicationCommandAsync(guildId, command.Id, options).ConfigureAwait(false);
}
- public static async Task CreateGuildUserCommand(BaseDiscordClient client, ulong guildId, Action func, RequestOptions options = null)
+ public static async Task CreateGuildUserCommand(BaseDiscordClient client, ulong guildId, Action func, RequestOptions options = null)
{
- var args = new UserCommandCreationProperties();
+ var args = new ContextMenuCommandCreationProperties();
func(args);
return await CreateGuildUserCommand(client, guildId, args, options).ConfigureAwait(false);
}
- public static async Task CreateGuildUserCommand(BaseDiscordClient client, ulong guildId, UserCommandCreationProperties arg, RequestOptions options = null)
+ public static async Task CreateGuildUserCommand(BaseDiscordClient client, ulong guildId, ContextMenuCommandCreationProperties arg, RequestOptions options = null)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
- Preconditions.Equals(arg.Description, "");
var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
- Description = arg.Description,
Type = arg.Type
};
@@ -488,22 +478,20 @@ namespace Discord.Rest
return RestGuildUserCommand.Create(client, cmd, guildId);
}
- public static async Task CreateGuildMessageCommand(BaseDiscordClient client, ulong guildId, Action func, RequestOptions options = null)
+ public static async Task CreateGuildMessageCommand(BaseDiscordClient client, ulong guildId, Action func, RequestOptions options = null)
{
- var args = new MessageCommandCreationProperties();
+ var args = new ContextMenuCommandCreationProperties();
func(args);
return await CreateGuildMessageCommand(client, guildId, args, options).ConfigureAwait(false);
}
- public static async Task CreateGuildMessageCommand(BaseDiscordClient client, ulong guildId, MessageCommandCreationProperties arg, RequestOptions options = null)
+ public static async Task CreateGuildMessageCommand(BaseDiscordClient client, ulong guildId, ContextMenuCommandCreationProperties arg, RequestOptions options = null)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
- Preconditions.Equals(arg.Description, "");
var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
- Description = arg.Description,
Type = arg.Type
};
@@ -511,7 +499,7 @@ namespace Discord.Rest
return RestGuildMessageCommand.Create(client, cmd, guildId);
}
- public static async Task> BulkOverwriteGuildUserCommands(BaseDiscordClient client, ulong guildId, UserCommandCreationProperties[] args, RequestOptions options = null)
+ public static async Task> BulkOverwriteGuildUserCommands(BaseDiscordClient client, ulong guildId, ContextMenuCommandCreationProperties[] args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));
@@ -520,13 +508,11 @@ namespace Discord.Rest
foreach (var arg in args)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
- Preconditions.NotNullOrEmpty(arg.Description, nameof(arg.Description));
Preconditions.Equals(arg.Type, ApplicationCommandType.User);
var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
- Description = arg.Description,
Type = arg.Type
};
@@ -573,7 +559,7 @@ namespace Discord.Rest
await client.ApiClient.DeleteGuildApplicationCommandAsync(guildId, command.Id, options).ConfigureAwait(false);
}
- public static async Task> BulkOverwriteGuildMessageCommands(BaseDiscordClient client, ulong guildId, MessageCommandCreationProperties[] args, RequestOptions options = null)
+ public static async Task> BulkOverwriteGuildMessageCommands(BaseDiscordClient client, ulong guildId, ContextMenuCommandCreationProperties[] args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));
@@ -582,13 +568,11 @@ namespace Discord.Rest
foreach (var arg in args)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
- Preconditions.NotNullOrEmpty(arg.Description, nameof(arg.Description));
Preconditions.Equals(arg.Type, ApplicationCommandType.Message);
var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
- Description = arg.Description,
Type = arg.Type
};
@@ -642,15 +626,33 @@ namespace Discord.Rest
var args = new MessageProperties();
func(args);
+ var embed = args.Embed;
+ var embeds = args.Embeds;
+
bool hasText = args.Content.IsSpecified ? !string.IsNullOrEmpty(args.Content.Value) : !string.IsNullOrEmpty(message.Content);
- bool hasEmbed = args.Embeds.IsSpecified ? args.Embeds.Value != null : message.Embeds.Any();
- if (!hasText && !hasEmbed)
+ bool hasEmbeds = (embed.IsSpecified && embed.Value != null) || (embeds.IsSpecified && embeds.Value?.Length > 0) || message.Embeds.Any();
+
+ if (!hasText && !hasEmbeds)
Preconditions.NotNullOrEmpty(args.Content.IsSpecified ? args.Content.Value : string.Empty, nameof(args.Content));
+ var apiEmbeds = embed.IsSpecified || embeds.IsSpecified ? new List() : null;
+
+ if (embed.IsSpecified && embed.Value != null)
+ {
+ apiEmbeds.Add(embed.Value.ToModel());
+ }
+
+ if (embeds.IsSpecified && embeds.Value != null)
+ {
+ apiEmbeds.AddRange(embeds.Value.Select(x => x.ToModel()));
+ }
+
+ Preconditions.AtMost(apiEmbeds?.Count ?? 0, 10, nameof(args.Embeds), "A max of 10 embeds are allowed.");
+
var apiArgs = new API.Rest.ModifyInteractionResponseParams
{
Content = args.Content,
- Embeds = args.Embeds.IsSpecified ? args.Embeds.Value.Select(x => x.ToModel()).ToArray() : Optional.Create(),
+ Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified,
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value.ToModel() : Optional.Unspecified,
Components = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional.Unspecified,
};
@@ -667,10 +669,33 @@ namespace Discord.Rest
var args = new MessageProperties();
func(args);
+ var embed = args.Embed;
+ var embeds = args.Embeds;
+
+ bool hasText = !string.IsNullOrEmpty(args.Content.GetValueOrDefault());
+ bool hasEmbeds = (embed.IsSpecified && embed.Value != null) || (embeds.IsSpecified && embeds.Value?.Length > 0);
+
+ if (!hasText && !hasEmbeds)
+ Preconditions.NotNullOrEmpty(args.Content.IsSpecified ? args.Content.Value : string.Empty, nameof(args.Content));
+
+ var apiEmbeds = embed.IsSpecified || embeds.IsSpecified ? new List() : null;
+
+ if (embed.IsSpecified && embed.Value != null)
+ {
+ apiEmbeds.Add(embed.Value.ToModel());
+ }
+
+ if (embeds.IsSpecified && embeds.Value != null)
+ {
+ apiEmbeds.AddRange(embeds.Value.Select(x => x.ToModel()));
+ }
+
+ Preconditions.AtMost(apiEmbeds?.Count ?? 0, 10, nameof(args.Embeds), "A max of 10 embeds are allowed.");
+
var apiArgs = new ModifyInteractionResponseParams
{
Content = args.Content,
- Embeds = args.Embeds.IsSpecified ? args.Embeds.Value?.Select(x => x.ToModel()).ToArray() : Optional.Unspecified,
+ Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified,
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional.Unspecified,
Components = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional.Unspecified,
Flags = args.Flags
diff --git a/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs b/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs
index 83ad2777e..9546025b0 100644
--- a/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs
+++ b/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs
@@ -1,3 +1,4 @@
+using Discord.API;
using Discord.API.Rest;
using System;
using System.Collections.Generic;
@@ -33,9 +34,13 @@ namespace Discord.Rest
if (msg.Author.Id != client.CurrentUser.Id && (args.Content.IsSpecified || args.Embeds.IsSpecified || args.AllowedMentions.IsSpecified))
throw new InvalidOperationException("Only the author of a message may modify the message content, embed, or allowed mentions.");
+ var embed = args.Embed;
+ var embeds = args.Embeds;
+
bool hasText = args.Content.IsSpecified ? !string.IsNullOrEmpty(args.Content.Value) : !string.IsNullOrEmpty(msg.Content);
- bool hasEmbed = args.Embeds.IsSpecified ? args.Embeds.Value != null : msg.Embeds.Any();
- if (!hasText && !hasEmbed)
+ bool hasEmbeds = (embed.IsSpecified && embed.Value != null) || (embeds.IsSpecified && embeds.Value?.Length > 0) || msg.Embeds.Any();
+
+ if (!hasText && !hasEmbeds)
Preconditions.NotNullOrEmpty(args.Content.IsSpecified ? args.Content.Value : string.Empty, nameof(args.Content));
if (args.AllowedMentions.IsSpecified)
@@ -61,22 +66,24 @@ namespace Discord.Rest
}
}
- var embeds = new List();
+ var apiEmbeds = embed.IsSpecified || embeds.IsSpecified ? new List() : null;
- if (args.Embed.IsSpecified)
+ if (embed.IsSpecified && embed.Value != null)
{
- embeds.Add(args.Embed.Value.ToModel());
+ apiEmbeds.Add(embed.Value.ToModel());
}
- if (args.Embeds.IsSpecified)
+ if (embeds.IsSpecified && embeds.Value != null)
{
- embeds.AddRange(args.Embeds.Value.Select(x => x.ToModel()));
+ apiEmbeds.AddRange(embeds.Value.Select(x => x.ToModel()));
}
+ Preconditions.AtMost(apiEmbeds?.Count ?? 0, 10, nameof(args.Embeds), "A max of 10 embeds are allowed.");
+
var apiArgs = new ModifyMessageParams
{
Content = args.Content,
- Embeds = embeds.ToArray(),
+ Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified,
Components = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional.Unspecified,
Flags = args.Flags,
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value.ToModel() : Optional.Unspecified,
@@ -90,7 +97,13 @@ namespace Discord.Rest
var args = new MessageProperties();
func(args);
- if (args.Content.IsSpecified && string.IsNullOrEmpty(args.Content.Value) && args.Embeds.IsSpecified && args.Embeds.Value == null)
+ var embed = args.Embed;
+ var embeds = args.Embeds;
+
+ bool hasText = args.Content.IsSpecified && string.IsNullOrEmpty(args.Content.Value);
+ bool hasEmbeds = (embed.IsSpecified && embed.Value != null) || (embeds.IsSpecified && embeds.Value?.Length > 0);
+
+ if (!hasText && !hasEmbeds)
Preconditions.NotNullOrEmpty(args.Content.IsSpecified ? args.Content.Value : string.Empty, nameof(args.Content));
if (args.AllowedMentions.IsSpecified)
@@ -117,22 +130,24 @@ namespace Discord.Rest
}
}
- var embeds = new List();
+ var apiEmbeds = embed.IsSpecified || embeds.IsSpecified ? new List() : null;
- if (args.Embed.IsSpecified)
+ if (embed.IsSpecified && embed.Value != null)
{
- embeds.Add(args.Embed.Value.ToModel());
+ apiEmbeds.Add(embed.Value.ToModel());
}
- if (args.Embeds.IsSpecified)
+ if (embeds.IsSpecified && embeds.Value != null)
{
- embeds.AddRange(args.Embeds.Value.Select(x => x.ToModel()));
+ apiEmbeds.AddRange(embeds.Value.Select(x => x.ToModel()));
}
+ Preconditions.AtMost(apiEmbeds?.Count ?? 0, 10, nameof(args.Embeds), "A max of 10 embeds are allowed.");
+
var apiArgs = new API.Rest.ModifyMessageParams
{
Content = args.Content,
- Embeds = embeds.ToArray(),
+ Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified,
Flags = args.Flags.IsSpecified ? args.Flags.Value : Optional.Create(),
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value.ToModel() : Optional.Create(),
Components = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional.Unspecified,
diff --git a/src/Discord.Net.Rest/Entities/Users/RestThreadUser.cs b/src/Discord.Net.Rest/Entities/Users/RestThreadUser.cs
index d74591e75..bb981bfdb 100644
--- a/src/Discord.Net.Rest/Entities/Users/RestThreadUser.cs
+++ b/src/Discord.Net.Rest/Entities/Users/RestThreadUser.cs
@@ -9,7 +9,7 @@ using Model = Discord.API.ThreadMember;
namespace Discord.Rest
{
///
- /// Represents a thread user recieved over the REST api.
+ /// Represents a thread user received over the REST api.
///
public class RestThreadUser : RestEntity
{
@@ -51,7 +51,7 @@ namespace Discord.Rest
/// Gets the guild user for this thread user.
///
///
- /// A task representing the asyncronous get operation. The task returns a
+ /// A task representing the asynchronous get operation. The task returns a
/// that represents the current thread user.
///
public Task GetGuildUser()
diff --git a/src/Discord.Net.Rest/Entities/Users/RestUser.cs b/src/Discord.Net.Rest/Entities/Users/RestUser.cs
index 7bc1447fe..618804fef 100644
--- a/src/Discord.Net.Rest/Entities/Users/RestUser.cs
+++ b/src/Discord.Net.Rest/Entities/Users/RestUser.cs
@@ -22,6 +22,10 @@ namespace Discord.Rest
///
public string AvatarId { get; private set; }
///
+ public string BannerId { get; private set; }
+ ///
+ public Color? AccentColor { get; private set; }
+ ///
public UserProperties? PublicFlags { get; private set; }
///
@@ -61,6 +65,10 @@ namespace Discord.Rest
{
if (model.Avatar.IsSpecified)
AvatarId = model.Avatar.Value;
+ if (model.Banner.IsSpecified)
+ BannerId = model.Banner.Value;
+ if (model.AccentColor.IsSpecified)
+ AccentColor = model.AccentColor.Value;
if (model.Discriminator.IsSpecified)
DiscriminatorValue = ushort.Parse(model.Discriminator.Value, NumberStyles.None, CultureInfo.InvariantCulture);
if (model.Bot.IsSpecified)
@@ -92,6 +100,10 @@ namespace Discord.Rest
public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128)
=> CDN.GetUserAvatarUrl(Id, AvatarId, size, format);
+ ///
+ public string GetBannerUrl(ImageFormat format = ImageFormat.Auto, ushort size = 256)
+ => CDN.GetUserBannerUrl(Id, BannerId, size, format);
+
///
public string GetDefaultAvatarUrl()
=> CDN.GetDefaultUserAvatarUrl(DiscriminatorValue);
diff --git a/src/Discord.Net.Rest/Entities/Webhooks/RestWebhook.cs b/src/Discord.Net.Rest/Entities/Webhooks/RestWebhook.cs
index 9baddf003..5ae09fde0 100644
--- a/src/Discord.Net.Rest/Entities/Webhooks/RestWebhook.cs
+++ b/src/Discord.Net.Rest/Entities/Webhooks/RestWebhook.cs
@@ -24,6 +24,8 @@ namespace Discord.Rest
public ulong? GuildId { get; private set; }
///
public IUser Creator { get; private set; }
+ ///
+ public ulong? ApplicationId { get; private set; }
///
public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id);
@@ -66,6 +68,8 @@ namespace Discord.Rest
GuildId = model.GuildId.Value;
if (model.Name.IsSpecified)
Name = model.Name.Value;
+
+ ApplicationId = model.ApplicationId;
}
///
diff --git a/src/Discord.Net.Rest/Extensions/EntityExtensions.cs b/src/Discord.Net.Rest/Extensions/EntityExtensions.cs
index f8676c783..0c2e0f8c2 100644
--- a/src/Discord.Net.Rest/Extensions/EntityExtensions.cs
+++ b/src/Discord.Net.Rest/Extensions/EntityExtensions.cs
@@ -68,6 +68,7 @@ namespace Discord.Rest
model.Video = entity.Video.Value.ToModel();
return model;
}
+
public static API.AllowedMentions ToModel(this AllowedMentions entity)
{
return new API.AllowedMentions()
diff --git a/src/Discord.Net.WebSocket/Discord.Net.WebSocket.csproj b/src/Discord.Net.WebSocket/Discord.Net.WebSocket.csproj
index af17578fb..167ccebb0 100644
--- a/src/Discord.Net.WebSocket/Discord.Net.WebSocket.csproj
+++ b/src/Discord.Net.WebSocket/Discord.Net.WebSocket.csproj
@@ -8,7 +8,7 @@
net461;netstandard2.0;netstandard2.1
netstandard2.0;netstandard2.1
true
- 3.0.0-pre
+ 3.0.1-pre
https://github.com/Discord-Net-Labs/Discord.Net-Labs
https://github.com/Discord-Net-Labs/Discord.Net-Labs
Temporary.png
@@ -16,6 +16,8 @@
..\Discord.Net.WebSocket\Discord.Net.WebSocket.xml
+ 3.0.1
+ 3.0.1
TRACE;
diff --git a/src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml b/src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml
index 742bebac0..485a83a61 100644
--- a/src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml
+++ b/src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml
@@ -3599,40 +3599,43 @@
-
+
+
+
+
Represents a Websocket-based slash command received over the gateway.
-
+
The data associated with this interaction.
-
+
- Represents the data tied with the interaction.
+ Represents the data tied with the interaction.
-
+
-
+
Represents a Websocket-based slash command received over the gateway.
-
+
The data associated with this interaction.
-
+
- Represents the data tied with the interaction.
+ Represents the data tied with the interaction.
-
+
@@ -3664,15 +3667,19 @@
-
+
- Acknowledges this interaction with the .
+ Defers an interaction and responds with type 5 ()
+ to send this message ephemerally, otherwise .
The request options for this async request.
A task that represents the asynchronous operation of acknowledging the interaction.
+
+
+
Represents the data sent with a .
@@ -3812,6 +3819,11 @@
If the option is a subcommand or subcommand group type, this nested options will be the parameters.
+
+
+ Base class for User, Message, and Slash command interactions
+
+
The data associated with this interaction.
@@ -3823,7 +3835,7 @@
-
+
Acknowledges this interaction with the .
@@ -3831,6 +3843,27 @@
A task that represents the asynchronous operation of acknowledging the interaction.
+
+
+ Represents the base data tied with the interaction.
+
+
+
+
+
+
+
+ The 's received with this interaction.
+
+
+
+
+ Represents the base Websocket-based recieved by the gateway
+
+
+
+
+
@@ -3943,14 +3976,25 @@
A task that represents the asynchronous operation of acknowledging the interaction.
-
+
Acknowledges this interaction.
+ to send this message ephemerally, otherwise .
+ The request options for this async request.
A task that represents the asynchronous operation of acknowledging the interaction.
+
+
+
+
+
+
+
+
+
Represents a WebSocket-based invite to a guild.
@@ -4487,6 +4531,12 @@
+
+
+
+
+
+
@@ -4545,6 +4595,12 @@
+
+
+
+
+
+
@@ -4608,7 +4664,7 @@
Returns the position of the user within the role hierarchy.
- The returned value equal to the position of the highest role the user has, or
+ The returned value equal to the position of the highest role the user has, or
if user is the server owner.
@@ -4730,6 +4786,12 @@
+
+
+
+
+
+
@@ -4783,6 +4845,12 @@
+
+
+
+
+
+
@@ -4890,6 +4958,12 @@
+
+
+
+
+
+
@@ -4920,6 +4994,12 @@
+
+
+
+
+
+
@@ -4958,6 +5038,9 @@
+
+
+
@@ -5039,6 +5122,14 @@
+
+
+ Webhook users does not support banners.
+
+
+
+ Webhook users does not support accent colors.
+
diff --git a/src/Discord.Net.WebSocket/DiscordShardedClient.cs b/src/Discord.Net.WebSocket/DiscordShardedClient.cs
index 6847d8580..450145f1c 100644
--- a/src/Discord.Net.WebSocket/DiscordShardedClient.cs
+++ b/src/Discord.Net.WebSocket/DiscordShardedClient.cs
@@ -30,7 +30,16 @@ namespace Discord.WebSocket
///
public override IActivity Activity { get => _shards[0].Activity; protected set { } }
- internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient;
+ internal new DiscordSocketApiClient ApiClient
+ {
+ get
+ {
+ if (base.ApiClient.CurrentUserId == null)
+ base.ApiClient.CurrentUserId = CurrentUser?.Id;
+
+ return base.ApiClient;
+ }
+ }
///
public override IReadOnlyCollection Guilds => GetGuilds().ToReadOnlyCollection(GetGuildCount);
///
diff --git a/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs b/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs
index 9221a3faa..e19cedb33 100644
--- a/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs
+++ b/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs
@@ -79,7 +79,7 @@ namespace Discord.API
if (msg != null)
{
#if DEBUG_PACKETS
- Console.WriteLine($"<- {msg.Operation} [{msg.Type ?? "none"}] : {(msg.Payload as Newtonsoft.Json.Linq.JToken)?.ToString().Length}");
+ Console.WriteLine($"<- {(GatewayOpCode)msg.Operation} [{msg.Type ?? "none"}] : {(msg.Payload as Newtonsoft.Json.Linq.JToken)?.ToString().Length}");
#endif
await _receivedGatewayEvent.InvokeAsync((GatewayOpCode)msg.Operation, msg.Sequence, msg.Type, msg.Payload).ConfigureAwait(false);
@@ -96,7 +96,7 @@ namespace Discord.API
if (msg != null)
{
#if DEBUG_PACKETS
- Console.WriteLine($"<- {msg.Operation} [{msg.Type ?? "none"}] : {(msg.Payload as Newtonsoft.Json.Linq.JToken)?.ToString().Length}");
+ Console.WriteLine($"<- {(GatewayOpCode)msg.Operation} [{msg.Type ?? "none"}] : {(msg.Payload as Newtonsoft.Json.Linq.JToken)?.ToString().Length}");
#endif
await _receivedGatewayEvent.InvokeAsync((GatewayOpCode)msg.Operation, msg.Sequence, msg.Type, msg.Payload).ConfigureAwait(false);
@@ -105,6 +105,10 @@ namespace Discord.API
};
WebSocketClient.Closed += async ex =>
{
+#if DEBUG_PACKETS
+ Console.WriteLine(ex);
+#endif
+
await DisconnectAsync().ConfigureAwait(false);
await _disconnectedEvent.InvokeAsync(ex).ConfigureAwait(false);
};
@@ -166,6 +170,11 @@ namespace Discord.API
var gatewayResponse = await GetGatewayAsync().ConfigureAwait(false);
_gatewayUrl = $"{gatewayResponse.Url}?v={DiscordConfig.APIVersion}&encoding={DiscordSocketConfig.GatewayEncoding}&compress=zlib-stream";
}
+
+#if DEBUG_PACKETS
+ Console.WriteLine("Connecting to gateway: " + _gatewayUrl);
+#endif
+
await WebSocketClient.ConnectAsync(_gatewayUrl).ConfigureAwait(false);
ConnectionState = ConnectionState.Connected;
@@ -237,7 +246,9 @@ namespace Discord.API
options = RequestOptions.CreateOrClone(options);
var props = new Dictionary
{
- ["$device"] = "Discord.Net"
+ ["$device"] = "Discord.Net Labs",
+ ["$os"] = Environment.OSVersion.Platform.ToString(),
+ [$"browser"] = "Discord.Net Labs"
};
var msg = new IdentifyParams()
{
diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
index c32bb3f49..5c385fe01 100644
--- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
+++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
@@ -1478,6 +1478,9 @@ namespace Discord.WebSocket
///
async Task> IGuild.GetWebhooksAsync(RequestOptions options)
=> await GetWebhooksAsync(options).ConfigureAwait(false);
+ ///
+ async Task> IGuild.GetApplicationCommandsAsync (RequestOptions options)
+ => await GetApplicationCommandsAsync(options).ConfigureAwait(false);
void IDisposable.Dispose()
{
diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketApplicationMessageCommand.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketMessageCommand.cs
similarity index 69%
rename from src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketApplicationMessageCommand.cs
rename to src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketMessageCommand.cs
index 828ed14bb..5d8b0af43 100644
--- a/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketApplicationMessageCommand.cs
+++ b/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketMessageCommand.cs
@@ -10,14 +10,14 @@ namespace Discord.WebSocket
///
/// Represents a Websocket-based slash command received over the gateway.
///
- public class SocketApplicationMessageCommand : SocketCommandBase
+ public class SocketMessageCommand : SocketCommandBase
{
///
/// The data associated with this interaction.
///
- new public SocketApplicationMessageCommandData Data { get; }
+ new public SocketMessageCommandData Data { get; }
- internal SocketApplicationMessageCommand(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
+ internal SocketMessageCommand(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
: base(client, model, channel)
{
var dataModel = model.Data.IsSpecified ?
@@ -28,12 +28,12 @@ namespace Discord.WebSocket
if (this.Channel is SocketGuildChannel guildChannel)
guildId = guildChannel.Guild.Id;
- Data = SocketApplicationMessageCommandData.Create(client, dataModel, model.Id, guildId);
+ Data = SocketMessageCommandData.Create(client, dataModel, model.Id, guildId);
}
new internal static SocketInteraction Create(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
{
- var entity = new SocketApplicationMessageCommand(client, model, channel);
+ var entity = new SocketMessageCommand(client, model, channel);
entity.Update(model);
return entity;
}
diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketApplicationMessageCommandData.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketMessageCommandData.cs
similarity index 89%
rename from src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketApplicationMessageCommandData.cs
rename to src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketMessageCommandData.cs
index ead330ef6..9c925c4ce 100644
--- a/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketApplicationMessageCommandData.cs
+++ b/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketMessageCommandData.cs
@@ -6,12 +6,15 @@ using Model = Discord.API.ApplicationCommandInteractionData;
namespace Discord.WebSocket
{
///
- /// Represents the data tied with the interaction.
+ /// Represents the data tied with the interaction.
///
- public class SocketApplicationMessageCommandData : SocketEntity, IApplicationCommandInteractionData
+ public class SocketMessageCommandData : SocketEntity, IApplicationCommandInteractionData
{
///
public string Name { get; private set; }
+ ///
+ /// The message selected to run the command
+ ///
public SocketMessage Message { get; private set; }
internal Dictionary guildMembers { get; private set; }
@@ -27,15 +30,11 @@ namespace Discord.WebSocket
private ulong? guildId;
- private ApplicationCommandType Type;
-
- internal SocketApplicationMessageCommandData(DiscordSocketClient client, Model model, ulong? guildId)
+ internal SocketMessageCommandData(DiscordSocketClient client, Model model, ulong? guildId)
: base(client, model.Id)
{
this.guildId = guildId;
- this.Type = (ApplicationCommandType)model.Type;
-
if (model.Resolved.IsSpecified)
{
var guild = this.guildId.HasValue ? Discord.GetGuild(this.guildId.Value) : null;
@@ -126,9 +125,9 @@ namespace Discord.WebSocket
}
}
- internal static SocketApplicationMessageCommandData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId)
+ internal static SocketMessageCommandData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId)
{
- var entity = new SocketApplicationMessageCommandData(client, model, guildId);
+ var entity = new SocketMessageCommandData(client, model, guildId);
entity.Update(model);
return entity;
}
diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketApplicationUserCommand.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketUserCommand.cs
similarity index 70%
rename from src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketApplicationUserCommand.cs
rename to src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketUserCommand.cs
index 603a11397..f4c3a8b7b 100644
--- a/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketApplicationUserCommand.cs
+++ b/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketUserCommand.cs
@@ -10,14 +10,14 @@ namespace Discord.WebSocket
///
/// Represents a Websocket-based slash command received over the gateway.
///
- public class SocketApplicationUserCommand : SocketCommandBase
+ public class SocketUserCommand : SocketCommandBase
{
///
/// The data associated with this interaction.
///
- new public SocketApplicationUserCommandData Data { get; }
+ new public SocketUserCommandData Data { get; }
- internal SocketApplicationUserCommand(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
+ internal SocketUserCommand(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
: base(client, model, channel)
{
var dataModel = model.Data.IsSpecified ?
@@ -28,12 +28,12 @@ namespace Discord.WebSocket
if (this.Channel is SocketGuildChannel guildChannel)
guildId = guildChannel.Guild.Id;
- Data = SocketApplicationUserCommandData.Create(client, dataModel, model.Id, guildId);
+ Data = SocketUserCommandData.Create(client, dataModel, model.Id, guildId);
}
new internal static SocketInteraction Create(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
{
- var entity = new SocketApplicationUserCommand(client, model, channel);
+ var entity = new SocketUserCommand(client, model, channel);
entity.Update(model);
return entity;
}
diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketApplicationUserCommandData.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketUserCommandData.cs
similarity index 86%
rename from src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketApplicationUserCommandData.cs
rename to src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketUserCommandData.cs
index a6eb24ca5..1cdfed097 100644
--- a/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketApplicationUserCommandData.cs
+++ b/src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketUserCommandData.cs
@@ -6,13 +6,15 @@ using Model = Discord.API.ApplicationCommandInteractionData;
namespace Discord.WebSocket
{
///
- /// Represents the data tied with the interaction.
+ /// Represents the data tied with the interaction.
///
- public class SocketApplicationUserCommandData : SocketEntity, IApplicationCommandInteractionData
+ public class SocketUserCommandData : SocketEntity, IApplicationCommandInteractionData
{
///
public string Name { get; private set; }
-
+ ///
+ /// The user used to run the command
+ ///
public SocketUser Member { get; private set; }
internal Dictionary guildMembers { get; private set; }
@@ -28,15 +30,11 @@ namespace Discord.WebSocket
private ulong? guildId;
- private ApplicationCommandType Type;
-
- internal SocketApplicationUserCommandData(DiscordSocketClient client, Model model, ulong? guildId)
+ internal SocketUserCommandData(DiscordSocketClient client, Model model, ulong? guildId)
: base(client, model.Id)
{
this.guildId = guildId;
- this.Type = (ApplicationCommandType)model.Type;
-
if (model.Resolved.IsSpecified)
{
var guild = this.guildId.HasValue ? Discord.GetGuild(this.guildId.Value) : null;
@@ -99,9 +97,9 @@ namespace Discord.WebSocket
}
}
- internal static SocketApplicationUserCommandData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId)
+ internal static SocketUserCommandData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId)
{
- var entity = new SocketApplicationUserCommandData(client, model, guildId);
+ var entity = new SocketUserCommandData(client, model, guildId);
entity.Update(model);
return entity;
}
diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Message Components/SocketMessageComponent.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Message Components/SocketMessageComponent.cs
index 921f81de4..cc91b098f 100644
--- a/src/Discord.Net.WebSocket/Entities/Interaction/Message Components/SocketMessageComponent.cs
+++ b/src/Discord.Net.WebSocket/Entities/Interaction/Message Components/SocketMessageComponent.cs
@@ -4,12 +4,13 @@ using System.Threading.Tasks;
using Model = Discord.API.Interaction;
using DataModel = Discord.API.MessageComponentInteractionData;
using Discord.Rest;
+using System.Collections.Generic;
namespace Discord.WebSocket
{
- ///
- /// Represents a Websocket-based interaction type for Message Components.
- ///
+///
+/// Represents a Websocket-based interaction type for Message Components.
+///
public class SocketMessageComponent : SocketInteraction
{
///
@@ -123,7 +124,7 @@ namespace Discord.WebSocket
};
if (ephemeral)
- response.Data.Value.Flags = 64;
+ response.Data.Value.Flags = MessageFlags.Ephemeral;
await InteractionHelper.SendInteractionResponse(this.Discord, response, this.Id, Token, options);
}
@@ -149,8 +150,28 @@ namespace Discord.WebSocket
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions), "A max of 100 user Ids are allowed.");
}
- if (args.Embeds.IsSpecified)
- Preconditions.AtMost(args.Embeds.Value?.Length ?? 0, 10, nameof(args.Embeds), "A max of 10 embeds are allowed.");
+ var embed = args.Embed;
+ var embeds = args.Embeds;
+
+ bool hasText = args.Content.IsSpecified ? !string.IsNullOrEmpty(args.Content.Value) : !string.IsNullOrEmpty(Message.Content);
+ bool hasEmbeds = (embed.IsSpecified && embed.Value != null) || (embeds.IsSpecified && embeds.Value?.Length > 0) || Message.Embeds.Any();
+
+ if (!hasText && !hasEmbeds)
+ Preconditions.NotNullOrEmpty(args.Content.IsSpecified ? args.Content.Value : string.Empty, nameof(args.Content));
+
+ var apiEmbeds = embed.IsSpecified || embeds.IsSpecified ? new List() : null;
+
+ if (embed.IsSpecified && embed.Value != null)
+ {
+ apiEmbeds.Add(embed.Value.ToModel());
+ }
+
+ if (embeds.IsSpecified && embeds.Value != null)
+ {
+ apiEmbeds.AddRange(embeds.Value.Select(x => x.ToModel()));
+ }
+
+ Preconditions.AtMost(apiEmbeds?.Count ?? 0, 10, nameof(args.Embeds), "A max of 10 embeds are allowed.");
// check that user flag and user Id list are exclusive, same with role flag and role Id list
if (args.AllowedMentions.IsSpecified && args.AllowedMentions.Value != null && args.AllowedMentions.Value.AllowedTypes.HasValue)
@@ -176,11 +197,11 @@ namespace Discord.WebSocket
{
Content = args.Content,
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional.Unspecified,
- Embeds = args.Embeds.IsSpecified ? args.Embeds.Value?.Select(x => x.ToModel()).ToArray() : Optional.Unspecified,
+ Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified,
Components = args.Components.IsSpecified
? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray()
: Optional.Unspecified,
- Flags = args.Flags.IsSpecified ? (int?)args.Flags.Value ?? Optional.Unspecified : Optional.Unspecified
+ Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional.Unspecified : Optional.Unspecified
}
};
@@ -213,27 +234,43 @@ namespace Discord.WebSocket
AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified,
IsTTS = isTTS,
Embeds = embeds?.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified,
- Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified
+ Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified,
};
if (ephemeral)
- args.Flags = 64;
+ args.Flags = MessageFlags.Ephemeral;
return await InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options);
}
///
- /// Acknowledges this interaction with the .
+ /// Defers an interaction and responds with type 5 ()
///
+ /// to send this message ephemerally, otherwise .
/// The request options for this async request.
///
/// A task that represents the asynchronous operation of acknowledging the interaction.
///
- public override Task DeferAsync(RequestOptions options = null)
+ public Task DeferLoadingAsync(bool ephemeral = false, RequestOptions options = null)
+ {
+ var response = new API.InteractionResponse()
+ {
+ Type = InteractionResponseType.DeferredChannelMessageWithSource,
+ Data = ephemeral ? new API.InteractionCallbackData() { Flags = MessageFlags.Ephemeral } : Optional.Unspecified
+
+ };
+
+ return Discord.Rest.ApiClient.CreateInteractionResponse(response, this.Id, this.Token, options);
+ }
+
+ ///
+ public override Task DeferAsync(bool ephemeral = false, RequestOptions options = null)
{
var response = new API.InteractionResponse()
{
Type = InteractionResponseType.DeferredUpdateMessage,
+ Data = ephemeral ? new API.InteractionCallbackData() { Flags = MessageFlags.Ephemeral } : Optional.Unspecified
+
};
return Discord.Rest.ApiClient.CreateInteractionResponse(response, this.Id, this.Token, options);
diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommand.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommand.cs
index 3013099c7..36542f15a 100644
--- a/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommand.cs
+++ b/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommand.cs
@@ -36,6 +36,6 @@ namespace Discord.WebSocket
var entity = new SocketSlashCommand(client, model, channel);
entity.Update(model);
return entity;
- }
+ }
}
}
diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandDataOption.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandDataOption.cs
index f33008cf3..f9c12257e 100644
--- a/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandDataOption.cs
+++ b/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandDataOption.cs
@@ -86,9 +86,9 @@ namespace Discord.WebSocket
break;
case ApplicationCommandOptionType.Integer:
{
- if (model.Value.Value is int val)
+ if (model.Value.Value is long val)
this.Value = val;
- else if (int.TryParse(model.Value.Value.ToString(), out int res))
+ else if (long.TryParse(model.Value.Value.ToString(), out long res))
this.Value = res;
}
break;
@@ -109,7 +109,7 @@ namespace Discord.WebSocket
}
break;
}
-
+
}
this.Options = model.Options.IsSpecified
diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs b/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs
index 4dbadc552..6ba9ba05a 100644
--- a/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs
+++ b/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs
@@ -9,6 +9,9 @@ using Model = Discord.API.Interaction;
namespace Discord.WebSocket
{
+ ///
+ /// Base class for User, Message, and Slash command interactions
+ ///
public class SocketCommandBase : SocketInteraction
{
///
@@ -105,7 +108,7 @@ namespace Discord.WebSocket
};
if (ephemeral)
- response.Data.Value.Flags = 64;
+ response.Data.Value.Flags = MessageFlags.Ephemeral;
await InteractionHelper.SendInteractionResponse(this.Discord, response, this.Id, Token, options);
}
@@ -140,7 +143,7 @@ namespace Discord.WebSocket
};
if (ephemeral)
- args.Flags = 64;
+ args.Flags = MessageFlags.Ephemeral;
return await InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options);
}
@@ -151,7 +154,7 @@ namespace Discord.WebSocket
///
/// A task that represents the asynchronous operation of acknowledging the interaction.
///
- public override Task DeferAsync(RequestOptions options = null)
+ public override Task DeferAsync(bool ephemeral = false, RequestOptions options = null)
{
var response = new API.InteractionResponse
{
diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBaseData.cs b/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBaseData.cs
index 7d7dbbce7..dde981eb9 100644
--- a/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBaseData.cs
+++ b/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBaseData.cs
@@ -5,13 +5,17 @@ using Model = Discord.API.ApplicationCommandInteractionData;
namespace Discord.WebSocket
{
+ ///
+ /// Represents the base data tied with the interaction.
+ ///
public class SocketCommandBaseData : SocketEntity, IApplicationCommandInteractionData
{
+ ///
public string Name { get; private set; }
-
+ ///
+ /// The 's received with this interaction.
+ ///
public IReadOnlyCollection Options { get; private set; }
- // id
- // type
internal Dictionary guildMembers { get; private set; }
= new Dictionary();
internal Dictionary users { get; private set; }
diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBaseDataOption.cs b/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBaseDataOption.cs
index 369f1f868..6aa15978e 100644
--- a/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBaseDataOption.cs
+++ b/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBaseDataOption.cs
@@ -9,8 +9,12 @@ using Model = Discord.API.ApplicationCommandInteractionDataOption;
namespace Discord.WebSocket
{
+ ///
+ /// Represents the base Websocket-based recieved by the gateway
+ ///
public class SocketCommandBaseDataOption : IApplicationCommandInteractionDataOption
{
+ ///
public string Name { get; private set; }
///
diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs b/src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs
index 59bae6f08..9b42ed0e2 100644
--- a/src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs
+++ b/src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs
@@ -71,9 +71,9 @@ namespace Discord.WebSocket
if (dataModel != null)
{
if (dataModel.Type.Equals(ApplicationCommandType.User))
- return SocketApplicationUserCommand.Create(client, model, channel);
+ return SocketUserCommand.Create(client, model, channel);
if (dataModel.Type.Equals(ApplicationCommandType.Message))
- return SocketApplicationMessageCommand.Create(client, model, channel);
+ return SocketMessageCommand.Create(client, model, channel);
}
}
return SocketSlashCommand.Create(client, model, channel);
@@ -172,20 +172,37 @@ namespace Discord.WebSocket
/// A task that represents the asynchronous operation of acknowledging the interaction.
///
[Obsolete("This method deprecated, please use DeferAsync instead")]
- public Task AcknowledgeAsync(RequestOptions options = null) => DeferAsync(options);
+ public Task AcknowledgeAsync(RequestOptions options = null) => DeferAsync(options: options);
///
/// Acknowledges this interaction.
///
+ /// to send this message ephemerally, otherwise .
+ /// The request options for this async request.
///
/// A task that represents the asynchronous operation of acknowledging the interaction.
///
- public abstract Task DeferAsync(RequestOptions options = null);
+ public abstract Task DeferAsync(bool ephemeral = false, RequestOptions options = null);
private bool CheckToken()
{
// Tokens last for 15 minutes according to https://discord.com/developers/docs/interactions/slash-commands#responding-to-an-interaction
return (DateTime.UtcNow - this.CreatedAt.UtcDateTime).TotalMinutes <= 15d;
}
+
+ // IDiscordInteraction
+
+ ///
+ async Task IDiscordInteraction.FollowupAsync (string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions,
+ RequestOptions options, MessageComponent component, Embed embed)
+ => await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, options, component, embed).ConfigureAwait(false);
+
+ ///
+ async Task IDiscordInteraction.GetOriginalResponseAsync (RequestOptions options)
+ => await GetOriginalResponseAsync(options).ConfigureAwait(false);
+
+ ///
+ async Task IDiscordInteraction.ModifyOriginalResponseAsync (Action func, RequestOptions options)
+ => await ModifyOriginalResponseAsync(func, options).ConfigureAwait(false);
}
}
diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs
index 82c656486..1b62d14dd 100644
--- a/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs
+++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs
@@ -122,7 +122,10 @@ namespace Discord.WebSocket
}
internal static SocketMessage Create(DiscordSocketClient discord, ClientState state, SocketUser author, ISocketMessageChannel channel, Model model)
{
- if (model.Type == MessageType.Default || model.Type == MessageType.Reply)
+ if (model.Type == MessageType.Default ||
+ model.Type == MessageType.Reply ||
+ model.Type == MessageType.ApplicationCommand ||
+ model.Type == MessageType.ThreadStarterMessage)
return SocketUserMessage.Create(discord, state, author, channel, model);
else
return SocketSystemMessage.Create(discord, state, author, channel, model);
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketGlobalUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketGlobalUser.cs
index 15c5182fc..b1bce5934 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketGlobalUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketGlobalUser.cs
@@ -12,6 +12,8 @@ namespace Discord.WebSocket
public override string Username { get; internal set; }
public override ushort DiscriminatorValue { get; internal set; }
public override string AvatarId { get; internal set; }
+ public override string BannerId { get; internal set; }
+ public override Color? AccentColor { get; internal set; }
internal override SocketPresence Presence { get; set; }
public override bool IsWebhook => false;
@@ -47,7 +49,7 @@ namespace Discord.WebSocket
discord.RemoveUser(Id);
}
}
-
+
internal void Update(ClientState state, PresenceModel model)
{
Presence = SocketPresence.Create(model);
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketGroupUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketGroupUser.cs
index 805a88110..d99310540 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketGroupUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketGroupUser.cs
@@ -29,6 +29,10 @@ namespace Discord.WebSocket
///
public override string AvatarId { get { return GlobalUser.AvatarId; } internal set { GlobalUser.AvatarId = value; } }
///
+ public override string BannerId { get { return GlobalUser.BannerId; } internal set { GlobalUser.BannerId = value; } }
+ ///
+ public override Color? AccentColor { get { return GlobalUser.AccentColor; } internal set { GlobalUser.AccentColor = value; } }
+ ///
internal override SocketPresence Presence { get { return GlobalUser.Presence; } set { GlobalUser.Presence = value; } }
///
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs
index f79fc7afe..ac8409a32 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs
@@ -38,6 +38,11 @@ namespace Discord.WebSocket
public override ushort DiscriminatorValue { get { return GlobalUser.DiscriminatorValue; } internal set { GlobalUser.DiscriminatorValue = value; } }
///
public override string AvatarId { get { return GlobalUser.AvatarId; } internal set { GlobalUser.AvatarId = value; } }
+ ///
+ public override string BannerId { get { return GlobalUser.BannerId; } internal set { GlobalUser.BannerId = value; } }
+ ///
+ public override Color? AccentColor { get { return GlobalUser.AccentColor; } internal set { GlobalUser.AccentColor = value; } }
+
///
public GuildPermissions GuildPermissions => new GuildPermissions(Permissions.ResolveGuild(Guild, this));
internal override SocketPresence Presence { get; set; }
@@ -91,7 +96,7 @@ namespace Discord.WebSocket
/// Returns the position of the user within the role hierarchy.
///
///
- /// The returned value equal to the position of the highest role the user has, or
+ /// The returned value equal to the position of the highest role the user has, or
/// if user is the server owner.
///
public int Hierarchy
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs
index 7b11257a3..e821238ee 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs
@@ -29,6 +29,10 @@ namespace Discord.WebSocket
///
public override string AvatarId { get { return GlobalUser.AvatarId; } internal set { GlobalUser.AvatarId = value; } }
///
+ public override string BannerId { get { return GlobalUser.BannerId; } internal set { GlobalUser.BannerId = value; } }
+ ///
+ public override Color? AccentColor { get { return GlobalUser.AccentColor; } internal set { GlobalUser.AccentColor = value; } }
+ ///
internal override SocketPresence Presence { get { return GlobalUser.Presence; } set { GlobalUser.Presence = value; } }
///
public UserProperties Flags { get; internal set; }
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketThreadUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketThreadUser.cs
index d1237d598..5fb1f56e5 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketThreadUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketThreadUser.cs
@@ -36,7 +36,7 @@ namespace Discord.WebSocket
///
public string Nickname
- => GuildUser.Nickname;
+ => GuildUser.Nickname;
///
public DateTimeOffset? PremiumSince
@@ -53,6 +53,20 @@ namespace Discord.WebSocket
internal set => GuildUser.AvatarId = value;
}
+ ///
+ public override string BannerId
+ {
+ get => GuildUser.BannerId;
+ internal set => GuildUser.BannerId = value;
+ }
+
+ ///
+ public override Color? AccentColor
+ {
+ get => GuildUser.AccentColor;
+ internal set => GuildUser.AccentColor = value;
+ }
+
///
public override ushort DiscriminatorValue
{
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketUnknownUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketUnknownUser.cs
index 840a1c30b..180e60a3b 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketUnknownUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketUnknownUser.cs
@@ -19,9 +19,16 @@ namespace Discord.WebSocket
public override ushort DiscriminatorValue { get; internal set; }
///
public override string AvatarId { get; internal set; }
+
+ ///
+ public override string BannerId { get; internal set; }
+
+ ///
+ public override Color? AccentColor { get; internal set; }
+
///
public override bool IsBot { get; internal set; }
-
+
///
public override bool IsWebhook => false;
///
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs
index 025daf29a..c50fbee4f 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs
@@ -25,6 +25,10 @@ namespace Discord.WebSocket
///
public abstract string AvatarId { get; internal set; }
///
+ public abstract string BannerId { get; internal set; }
+ ///
+ public abstract Color? AccentColor { get; internal set; }
+ ///
public abstract bool IsWebhook { get; }
///
public UserProperties? PublicFlags { get; private set; }
@@ -64,6 +68,16 @@ namespace Discord.WebSocket
AvatarId = model.Avatar.Value;
hasChanges = true;
}
+ if (model.Banner.IsSpecified && model.Banner.Value != BannerId)
+ {
+ BannerId = model.Banner.Value;
+ hasChanges = true;
+ }
+ if (model.AccentColor.IsSpecified && model.AccentColor.Value != AccentColor?.RawValue)
+ {
+ AccentColor = model.AccentColor.Value;
+ hasChanges = true;
+ }
if (model.Discriminator.IsSpecified)
{
var newVal = ushort.Parse(model.Discriminator.Value, NumberStyles.None, CultureInfo.InvariantCulture);
@@ -99,6 +113,10 @@ namespace Discord.WebSocket
public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128)
=> CDN.GetUserAvatarUrl(Id, AvatarId, size, format);
+ ///
+ public string GetBannerUrl(ImageFormat format = ImageFormat.Auto, ushort size = 256)
+ => CDN.GetUserBannerUrl(Id, BannerId, size, format);
+
///
public string GetDefaultAvatarUrl()
=> CDN.GetDefaultUserAvatarUrl(DiscriminatorValue);
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs
index 2b0ecbb19..f1269e649 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs
@@ -24,6 +24,23 @@ namespace Discord.WebSocket
public override ushort DiscriminatorValue { get; internal set; }
///
public override string AvatarId { get; internal set; }
+
+ ///
+ /// Webhook users does not support banners.
+ public override string BannerId
+ {
+ get => throw new NotSupportedException("Webhook users does not support banners.");
+ internal set => throw new NotSupportedException("Webhook users does not support banners.");
+ }
+
+ ///
+ /// Webhook users does not support accent colors.
+ public override Color? AccentColor
+ {
+ get => throw new NotSupportedException("Webhook users does not support accent colors.");
+ internal set => throw new NotSupportedException("Webhook users does not support accent colors.");
+ }
+
///
public override bool IsBot { get; internal set; }
diff --git a/src/Discord.Net.Webhook/Discord.Net.Webhook.csproj b/src/Discord.Net.Webhook/Discord.Net.Webhook.csproj
index 13e5cf111..f04dedf43 100644
--- a/src/Discord.Net.Webhook/Discord.Net.Webhook.csproj
+++ b/src/Discord.Net.Webhook/Discord.Net.Webhook.csproj
@@ -6,7 +6,7 @@
Discord.Webhook
A core Discord.Net Labs library containing the Webhook client and models.
netstandard2.0;netstandard2.1
- 2.3.4
+ 3.0.0-pre
Discord.Net.Labs.Webhook
https://github.com/Discord-Net-Labs/Discord.Net-Labs
https://github.com/Discord-Net-Labs/Discord.Net-Labs
diff --git a/src/Discord.Net.Webhook/Discord.Net.Webhook.xml b/src/Discord.Net.Webhook/Discord.Net.Webhook.xml
index f629c2c29..d1bafb9a3 100644
--- a/src/Discord.Net.Webhook/Discord.Net.Webhook.xml
+++ b/src/Discord.Net.Webhook/Discord.Net.Webhook.xml
@@ -31,7 +31,7 @@
Thrown if the is an invalid format.
Thrown if the is null or whitespace.
-
+
Sends a message to the channel for this webhook.
Returns the ID of the created message.
@@ -99,6 +99,11 @@
Gets or sets the allowed mentions of the message.
+
+
+ Gets or sets the components that the message should display.
+
+
Could not find a webhook with the supplied credentials.
diff --git a/src/Discord.Net.Webhook/DiscordWebhookClient.cs b/src/Discord.Net.Webhook/DiscordWebhookClient.cs
index 91d077411..d4affb08b 100644
--- a/src/Discord.Net.Webhook/DiscordWebhookClient.cs
+++ b/src/Discord.Net.Webhook/DiscordWebhookClient.cs
@@ -88,8 +88,8 @@ namespace Discord.Webhook
/// Sends a message to the channel for this webhook.
/// Returns the ID of the created message.
public Task SendMessageAsync(string text = null, bool isTTS = false, IEnumerable embeds = null,
- string username = null, string avatarUrl = null, RequestOptions options = null, AllowedMentions allowedMentions = null)
- => WebhookClientHelper.SendMessageAsync(this, text, isTTS, embeds, username, avatarUrl, allowedMentions, options);
+ string username = null, string avatarUrl = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageComponent component = null)
+ => WebhookClientHelper.SendMessageAsync(this, text, isTTS, embeds, username, avatarUrl, allowedMentions, options, component);
///
/// Modifies a message posted using this webhook.
diff --git a/src/Discord.Net.Webhook/Entities/Messages/WebhookMessageProperties.cs b/src/Discord.Net.Webhook/Entities/Messages/WebhookMessageProperties.cs
index dec7b6e3b..ca2ff10a0 100644
--- a/src/Discord.Net.Webhook/Entities/Messages/WebhookMessageProperties.cs
+++ b/src/Discord.Net.Webhook/Entities/Messages/WebhookMessageProperties.cs
@@ -22,5 +22,9 @@ namespace Discord.Webhook
/// Gets or sets the allowed mentions of the message.
///
public Optional AllowedMentions { get; set; }
+ ///
+ /// Gets or sets the components that the message should display.
+ ///
+ public Optional Components { get; set; }
}
}
diff --git a/src/Discord.Net.Webhook/Entities/Webhooks/RestInternalWebhook.cs b/src/Discord.Net.Webhook/Entities/Webhooks/RestInternalWebhook.cs
index bbb160fcd..2a5c4786e 100644
--- a/src/Discord.Net.Webhook/Entities/Webhooks/RestInternalWebhook.cs
+++ b/src/Discord.Net.Webhook/Entities/Webhooks/RestInternalWebhook.cs
@@ -17,6 +17,7 @@ namespace Discord.Webhook
public string Name { get; private set; }
public string AvatarId { get; private set; }
public ulong? GuildId { get; private set; }
+ public ulong? ApplicationId { get; private set; }
public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id);
@@ -44,6 +45,8 @@ namespace Discord.Webhook
GuildId = model.GuildId.Value;
if (model.Name.IsSpecified)
Name = model.Name.Value;
+
+ ApplicationId = model.ApplicationId;
}
public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128)
diff --git a/src/Discord.Net.Webhook/WebhookClientHelper.cs b/src/Discord.Net.Webhook/WebhookClientHelper.cs
index 528848f7f..6e3651323 100644
--- a/src/Discord.Net.Webhook/WebhookClientHelper.cs
+++ b/src/Discord.Net.Webhook/WebhookClientHelper.cs
@@ -21,7 +21,7 @@ namespace Discord.Webhook
return RestInternalWebhook.Create(client, model);
}
public static async Task SendMessageAsync(DiscordWebhookClient client,
- string text, bool isTTS, IEnumerable embeds, string username, string avatarUrl, AllowedMentions allowedMentions, RequestOptions options)
+ string text, bool isTTS, IEnumerable embeds, string username, string avatarUrl, AllowedMentions allowedMentions, RequestOptions options, MessageComponent component)
{
var args = new CreateWebhookMessageParams
{
@@ -37,6 +37,8 @@ namespace Discord.Webhook
args.AvatarUrl = avatarUrl;
if (allowedMentions != null)
args.AllowedMentions = allowedMentions.ToModel();
+ if (component != null)
+ args.Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray();
var model = await client.ApiClient.CreateWebhookMessageAsync(client.Webhook.Id, args, options: options).ConfigureAwait(false);
return model.Id;
@@ -83,7 +85,8 @@ namespace Discord.Webhook
: Optional.Create(),
AllowedMentions = args.AllowedMentions.IsSpecified
? args.AllowedMentions.Value.ToModel()
- : Optional.Create()
+ : Optional.Create(),
+ Components = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional.Unspecified,
};
await client.ApiClient.ModifyWebhookMessageAsync(client.Webhook.Id, messageId, apiArgs, options)
diff --git a/src/Discord.Net/Discord.Net.nuspec b/src/Discord.Net/Discord.Net.nuspec
index 595203eba..eb3bd9b6d 100644
--- a/src/Discord.Net/Discord.Net.nuspec
+++ b/src/Discord.Net/Discord.Net.nuspec
@@ -2,7 +2,7 @@
Discord.Net.Labs
- 3.0.1-pre$suffix$
+ 3.0.2-pre$suffix$
Discord.Net Labs
Discord.Net Contributors
quinchs
@@ -14,23 +14,23 @@
https://avatars.githubusercontent.com/u/84047264
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
diff --git a/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs b/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs
index 137dc5575..9be109c6e 100644
--- a/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs
+++ b/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs
@@ -91,7 +91,13 @@ namespace Discord
AssertFlag(() => new GuildPermissions(manageNicknames: true), GuildPermission.ManageNicknames);
AssertFlag(() => new GuildPermissions(manageRoles: true), GuildPermission.ManageRoles);
AssertFlag(() => new GuildPermissions(manageWebhooks: true), GuildPermission.ManageWebhooks);
- AssertFlag(() => new GuildPermissions(manageEmojis: true), GuildPermission.ManageEmojis);
+ AssertFlag(() => new GuildPermissions(manageEmojisAndStickers: true), GuildPermission.ManageEmojisAndStickers);
+ AssertFlag(() => new GuildPermissions(useSlashCommands: true), GuildPermission.UseSlashCommands);
+ AssertFlag(() => new GuildPermissions(requestToSpeak: true), GuildPermission.RequestToSpeak);
+ AssertFlag(() => new GuildPermissions(manageThreads: true), GuildPermission.ManageThreads);
+ AssertFlag(() => new GuildPermissions(usePublicThreads: true), GuildPermission.UsePublicThreads);
+ AssertFlag(() => new GuildPermissions(usePrivateThreads: true), GuildPermission.UsePrivateThreads);
+ AssertFlag(() => new GuildPermissions(useExternalStickers: true), GuildPermission.UseExternalStickers);
}
///
@@ -161,7 +167,13 @@ namespace Discord
AssertUtil(GuildPermission.ManageNicknames, x => x.ManageNicknames, (p, enable) => p.Modify(manageNicknames: enable));
AssertUtil(GuildPermission.ManageRoles, x => x.ManageRoles, (p, enable) => p.Modify(manageRoles: enable));
AssertUtil(GuildPermission.ManageWebhooks, x => x.ManageWebhooks, (p, enable) => p.Modify(manageWebhooks: enable));
- AssertUtil(GuildPermission.ManageEmojis, x => x.ManageEmojisAndStickers, (p, enable) => p.Modify(manageEmojis: enable));
+ AssertUtil(GuildPermission.ManageEmojisAndStickers, x => x.ManageEmojisAndStickers, (p, enable) => p.Modify(manageEmojisAndStickers: enable));
+ AssertUtil(GuildPermission.UseSlashCommands, x => x.UseSlashCommands, (p, enable) => p.Modify(useSlashCommands: enable));
+ AssertUtil(GuildPermission.RequestToSpeak, x => x.RequestToSpeak, (p, enable) => p.Modify(requestToSpeak: enable));
+ AssertUtil(GuildPermission.ManageThreads, x => x.ManageThreads, (p, enable) => p.Modify(manageThreads: enable));
+ AssertUtil(GuildPermission.UsePublicThreads, x => x.UsePublicThreads, (p, enable) => p.Modify(usePublicThreads: enable));
+ AssertUtil(GuildPermission.UsePrivateThreads, x => x.UsePrivateThreads, (p, enable) => p.Modify(usePrivateThreads: enable));
+ AssertUtil(GuildPermission.UseExternalStickers, x => x.UseExternalStickers, (p, enable) => p.Modify(useExternalStickers: enable));
}
}
}