Browse Source

Simply internal usage of context menus

pull/1923/head
quin lynch 3 years ago
parent
commit
ae95d284fa
31 changed files with 429 additions and 1126 deletions
  1. +77
    -120
      src/Discord.Net.Core/Discord.Net.Core.xml
  2. +5
    -21
      src/Discord.Net.Core/Entities/Interactions/ApplicationCommandProperties.cs
  3. +6
    -4
      src/Discord.Net.Core/Entities/Interactions/ApplicationCommandTypes.cs
  4. +6
    -5
      src/Discord.Net.Core/Entities/Interactions/Context Menus/MessageCommandBuilder.cs
  5. +16
    -0
      src/Discord.Net.Core/Entities/Interactions/Context Menus/MessageCommandProperties.cs
  6. +4
    -5
      src/Discord.Net.Core/Entities/Interactions/Context Menus/UserCommandBuilder.cs
  7. +16
    -0
      src/Discord.Net.Core/Entities/Interactions/Context Menus/UserCommandProperties.cs
  8. +0
    -24
      src/Discord.Net.Core/Entities/Interactions/ContextMenuCommandCreationProperties.cs
  9. +11
    -1
      src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs
  10. +4
    -5
      src/Discord.Net.Core/Entities/Interactions/SlashCommandBuilder.cs
  11. +5
    -12
      src/Discord.Net.Core/Entities/Interactions/SlashCommandProperties.cs
  12. +0
    -30
      src/Discord.Net.Core/Entities/Interactions/UserCommandCreationProperties.cs
  13. +8
    -0
      src/Discord.Net.Rest/API/Common/ApplicationCommand.cs
  14. +0
    -1
      src/Discord.Net.Rest/API/Net/IResolvable.cs
  15. +0
    -3
      src/Discord.Net.Rest/API/Rest/ModifyApplicationCommandParams.cs
  16. +5
    -116
      src/Discord.Net.Rest/Discord.Net.Rest.xml
  17. +6
    -22
      src/Discord.Net.Rest/DiscordRestClient.cs
  18. +130
    -438
      src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs
  19. +10
    -29
      src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommand.cs
  20. +5
    -2
      src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandOption.cs
  21. +0
    -28
      src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandType.cs
  22. +7
    -4
      src/Discord.Net.Rest/Entities/Interactions/RestGlobalCommand.cs
  23. +0
    -41
      src/Discord.Net.Rest/Entities/Interactions/RestGlobalMessageCommand.cs
  24. +0
    -41
      src/Discord.Net.Rest/Entities/Interactions/RestGlobalUserCommand.cs
  25. +6
    -4
      src/Discord.Net.Rest/Entities/Interactions/RestGuildCommand.cs
  26. +0
    -61
      src/Discord.Net.Rest/Entities/Interactions/RestGuildMessageCommand.cs
  27. +0
    -61
      src/Discord.Net.Rest/Entities/Interactions/RestGuildUserCommand.cs
  28. +2
    -20
      src/Discord.Net.WebSocket/API/Gateway/ApplicationCommandCreatedUpdatedEvent.cs
  29. +22
    -3
      src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml
  30. +21
    -12
      src/Discord.Net.WebSocket/DiscordSocketClient.cs
  31. +57
    -13
      src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketApplicationCommand.cs

+ 77
- 120
src/Discord.Net.Core/Discord.Net.Core.xml View File

@@ -4461,7 +4461,7 @@
</member>
<member name="T:Discord.ApplicationCommandProperties">
<summary>
Provides properties that are used to modify a <see cref="T:Discord.IApplicationCommand" /> with the specified changes.
Represents the base class to create/modify application commands.
</summary>
</member>
<member name="P:Discord.ApplicationCommandProperties.Name">
@@ -4469,64 +4469,101 @@
Gets or sets the name of this command.
</summary>
</member>
<member name="P:Discord.ApplicationCommandProperties.Description">
<member name="T:Discord.ApplicationCommandType">
<summary>
Gets or sets the discription of this command.
ApplicationCommandType is enum of current valid Application Command Types: Slash, User, Message
</summary>
</member>
<member name="P:Discord.ApplicationCommandProperties.Type">
<member name="F:Discord.ApplicationCommandType.Slash">
<summary>
Gets or sets the type for this command.
ApplicationCommandType.Slash is Slash command type
</summary>
</member>
<member name="P:Discord.ApplicationCommandProperties.Options">
<member name="F:Discord.ApplicationCommandType.User">
<summary>
Gets or sets the options for this command.
ApplicationCommandType.User is Context Menu User command type
</summary>
</member>
<member name="P:Discord.ApplicationCommandProperties.DefaultPermission">
<member name="F:Discord.ApplicationCommandType.Message">
<summary>
Whether the command is enabled by default when the app is added to a guild. Default is <see langword="true"/>
ApplicationCommandType.Message is Context Menu Message command type
</summary>
</member>
<member name="T:Discord.ApplicationCommandType">
<member name="T:Discord.MessageCommandBuilder">
<summary>
ApplicationCommandType is enum of current valid Application Command Types: Slash, User, Message
A class used to build Message commands.
</summary>
</member>
<member name="F:Discord.ApplicationCommandType.Slash">
<member name="F:Discord.MessageCommandBuilder.MaxNameLength">
<summary>
Returns the maximun length a commands name allowed by Discord
</summary>
</member>
<member name="P:Discord.MessageCommandBuilder.Name">
<summary>
ApplicationCommandType.Slash is Slash command type
The name of this Message command.
</summary>
</member>
<member name="F:Discord.ApplicationCommandType.User">
<member name="M:Discord.MessageCommandBuilder.Build">
<summary>
ApplicationCommandType.User is Context Menu User command type
Build the current builder into a <see cref="T:Discord.MessageCommandProperties"/> class.
</summary>
<returns>
A <see cref="T:Discord.MessageCommandProperties"/> that can be used to create message commands.
</returns>
</member>
<member name="F:Discord.ApplicationCommandType.Message">
<member name="M:Discord.MessageCommandBuilder.WithName(System.String)">
<summary>
ApplicationCommandType.Message is Context Menu Message command type
Sets the field name.
</summary>
<param name="name">The value to set the field name to.</param>
<returns>
The current builder.
</returns>
</member>
<member name="T:Discord.ContextMenuCommandCreationProperties">
<member name="T:Discord.MessageCommandProperties">
<summary>
A class used to create Message commands.
A class used to create message commands.
</summary>
</member>
<member name="P:Discord.ContextMenuCommandCreationProperties.Name">
<member name="T:Discord.UserCommandBuilder">
<summary>
The name of this command.
A class used to build user commands.
</summary>
</member>
<member name="F:Discord.UserCommandBuilder.MaxNameLength">
<summary>
Returns the maximun length a commands name allowed by Discord
</summary>
</member>
<member name="P:Discord.UserCommandBuilder.Name">
<summary>
The name of this User command.
</summary>
</member>
<member name="M:Discord.UserCommandBuilder.Build">
<summary>
Build the current builder into a <see cref="T:Discord.UserCommandProperties"/> class.
</summary>
<returns>A <see cref="T:Discord.UserCommandProperties"/> that can be used to create user commands.</returns>
</member>
<member name="P:Discord.ContextMenuCommandCreationProperties.Type">
<member name="M:Discord.UserCommandBuilder.WithName(System.String)">
<summary>
Gets or sets the type for this command.
Sets the field name.
</summary>
<param name="name">The value to set the field name to.</param>
<returns>
The current builder.
</returns>
</member>
<member name="T:Discord.UserCommandProperties">
<summary>
A class used to create User commands.
</summary>
</member>
<member name="T:Discord.IApplicationCommand">
<summary>
The base command model that belongs to an application. see <see href="https://discord.com/developers/docs/interactions/slash-commands#applicationcommand"/>
The base command model that belongs to an application.
</summary>
</member>
<member name="P:Discord.IApplicationCommand.ApplicationId">
@@ -4559,6 +4596,16 @@
If the option is a subcommand or subcommand group type, this nested options will be the parameters.
</summary>
</member>
<member name="M:Discord.IApplicationCommand.ModifyAsync(System.Action{Discord.ApplicationCommandProperties},Discord.RequestOptions)">
<summary>
Modifies the current application command.
</summary>
<param name="func">The new properties to use when modifying the command.</param>
<param name="options">The options to be used when sending the request.</param>
<returns>
A task that represents the asynchronous modification operation.
</returns>
</member>
<member name="T:Discord.IApplicationCommandInteractionData">
<summary>
Represents data of an Interaction Command, see <see href="https://discord.com/developers/docs/interactions/slash-commands#interaction-applicationcommandinteractiondata"/>.
@@ -5571,36 +5618,6 @@
Will render this option as selected by default.
</summary>
</member>
<member name="T:Discord.MessageCommandBuilder">
<summary>
A class used to build Message commands.
</summary>
</member>
<member name="F:Discord.MessageCommandBuilder.MaxNameLength">
<summary>
Returns the maximun length a commands name allowed by Discord
</summary>
</member>
<member name="P:Discord.MessageCommandBuilder.Name">
<summary>
The name of this Message command.
</summary>
</member>
<member name="M:Discord.MessageCommandBuilder.Build">
<summary>
Build the current builder into a <see cref="T:Discord.ContextMenuCommandCreationProperties"/> class.
</summary>
<returns>A <see cref="T:Discord.ContextMenuCommandCreationProperties"/> that can be used to create message commands over rest.</returns>
</member>
<member name="M:Discord.MessageCommandBuilder.WithName(System.String)">
<summary>
Sets the field name.
</summary>
<param name="name">The value to set the field name to.</param>
<returns>
The current builder.
</returns>
</member>
<member name="T:Discord.SlashCommandBuilder">
<summary>
A class used to build slash commands.
@@ -5643,9 +5660,9 @@
</member>
<member name="M:Discord.SlashCommandBuilder.Build">
<summary>
Build the current builder into a <see cref="T:Discord.SlashCommandCreationProperties"/> class.
Build the current builder into a <see cref="T:Discord.SlashCommandProperties"/> class.
</summary>
<returns>A <see cref="T:Discord.SlashCommandCreationProperties"/> that can be used to create slash commands over rest.</returns>
<returns>A <see cref="T:Discord.SlashCommandProperties"/> that can be used to create slash commands over rest.</returns>
</member>
<member name="M:Discord.SlashCommandBuilder.WithName(System.String)">
<summary>
@@ -5833,86 +5850,26 @@
<param name="type">The type to set.</param>
<returns>The current builder.</returns>
</member>
<member name="T:Discord.SlashCommandCreationProperties">
<member name="T:Discord.SlashCommandProperties">
<summary>
A class used to create slash commands.
</summary>
</member>
<member name="P:Discord.SlashCommandCreationProperties.Name">
<summary>
The name of this command.
</summary>
</member>
<member name="P:Discord.SlashCommandCreationProperties.Description">
<member name="P:Discord.SlashCommandProperties.Description">
<summary>
The discription of this command.
</summary>
</member>
<member name="P:Discord.SlashCommandCreationProperties.Type">
<summary>
Gets or sets the type for this command.
</summary>
</member>
<member name="P:Discord.SlashCommandCreationProperties.Options">
<member name="P:Discord.SlashCommandProperties.Options">
<summary>
Gets or sets the options for this command.
</summary>
</member>
<member name="P:Discord.SlashCommandCreationProperties.DefaultPermission">
<member name="P:Discord.SlashCommandProperties.DefaultPermission">
<summary>
Whether the command is enabled by default when the app is added to a guild. Default is <see langword="true"/>
</summary>
</member>
<member name="T:Discord.UserCommandBuilder">
<summary>
A class used to build user commands.
</summary>
</member>
<member name="F:Discord.UserCommandBuilder.MaxNameLength">
<summary>
Returns the maximun length a commands name allowed by Discord
</summary>
</member>
<member name="P:Discord.UserCommandBuilder.Name">
<summary>
The name of this User command.
</summary>
</member>
<member name="M:Discord.UserCommandBuilder.Build">
<summary>
Build the current builder into a <see cref="T:Discord.ContextMenuCommandCreationProperties"/> class.
</summary>
<returns>A <see cref="T:Discord.ContextMenuCommandCreationProperties"/> that can be used to create user commands over rest.</returns>
</member>
<member name="M:Discord.UserCommandBuilder.WithName(System.String)">
<summary>
Sets the field name.
</summary>
<param name="name">The value to set the field name to.</param>
<returns>
The current builder.
</returns>
</member>
<member name="T:Discord.UserCommandCreationProperties">
<summary>
A class used to create User commands.
</summary>
</member>
<member name="P:Discord.UserCommandCreationProperties.Name">
<summary>
The name of this command.
</summary>
</member>
<member name="P:Discord.UserCommandCreationProperties.Description">
<summary>
The discription of this command.
</summary>
</member>
<member name="P:Discord.UserCommandCreationProperties.Type">
<summary>
Gets or sets the type for this command.
</summary>
</member>
<member name="T:Discord.IInvite">
<summary>
Represents a generic invite object.


+ 5
- 21
src/Discord.Net.Core/Entities/Interactions/ApplicationCommandProperties.cs View File

@@ -7,33 +7,17 @@ using System.Threading.Tasks;
namespace Discord
{
/// <summary>
/// Provides properties that are used to modify a <see cref="IApplicationCommand" /> with the specified changes.
/// Represents the base class to create/modify application commands.
/// </summary>
public class ApplicationCommandProperties
public abstract class ApplicationCommandProperties
{
internal abstract ApplicationCommandType Type { get; }

/// <summary>
/// Gets or sets the name of this command.
/// </summary>
public Optional<string> Name { get; set; }

/// <summary>
/// Gets or sets the discription of this command.
/// </summary>
public Optional<string> Description { get; set; }

/// <summary>
/// Gets or sets the type for this command.
/// </summary>
public Optional<ApplicationCommandType> Type { get; set; }

/// <summary>
/// Gets or sets the options for this command.
/// </summary>
public Optional<List<ApplicationCommandOptionProperties>> Options { get; set; }

/// <summary>
/// Whether the command is enabled by default when the app is added to a guild. Default is <see langword="true"/>
/// </summary>
public Optional<bool> DefaultPermission { get; set; }
internal ApplicationCommandProperties() { }
}
}

+ 6
- 4
src/Discord.Net.Core/Entities/Interactions/ApplicationCommandTypes.cs View File

@@ -7,20 +7,22 @@ using System.Threading.Tasks;
namespace Discord
{
/// <summary>
/// ApplicationCommandType is enum of current valid Application Command Types: Slash, User, Message
/// ApplicationCommandType is enum of current valid Application Command Types: Slash, User, Message
/// </summary>
public enum ApplicationCommandType : byte
{
/// <summary>
/// ApplicationCommandType.Slash is Slash command type
/// ApplicationCommandType.Slash is Slash command type
/// </summary>
Slash = 1,

/// <summary>
/// ApplicationCommandType.User is Context Menu User command type
/// ApplicationCommandType.User is Context Menu User command type
/// </summary>
User = 2,

/// <summary>
/// ApplicationCommandType.Message is Context Menu Message command type
/// ApplicationCommandType.Message is Context Menu Message command type
/// </summary>
Message = 3
}


src/Discord.Net.Core/Entities/Interactions/MessageCommandBuilder.cs → src/Discord.Net.Core/Entities/Interactions/Context Menus/MessageCommandBuilder.cs View File

@@ -44,15 +44,16 @@ namespace Discord
private string _name { get; set; }

/// <summary>
/// Build the current builder into a <see cref="ContextMenuCommandCreationProperties"/> class.
/// Build the current builder into a <see cref="MessageCommandProperties"/> class.
/// </summary>
/// <returns>A <see cref="ContextMenuCommandCreationProperties"/> that can be used to create message commands over rest.</returns>
public ContextMenuCommandCreationProperties Build()
/// <returns>
/// A <see cref="MessageCommandProperties"/> that can be used to create message commands.
/// </returns>
public MessageCommandProperties Build()
{
ContextMenuCommandCreationProperties props = new ContextMenuCommandCreationProperties()
MessageCommandProperties props = new MessageCommandProperties()
{
Name = this.Name,
Type=ApplicationCommandType.Message
};

return props;

+ 16
- 0
src/Discord.Net.Core/Entities/Interactions/Context Menus/MessageCommandProperties.cs View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord
{
/// <summary>
/// A class used to create message commands.
/// </summary>
public class MessageCommandProperties : ApplicationCommandProperties
{
internal override ApplicationCommandType Type => ApplicationCommandType.Message;
}
}

src/Discord.Net.Core/Entities/Interactions/UserCommandBuilder.cs → src/Discord.Net.Core/Entities/Interactions/Context Menus/UserCommandBuilder.cs View File

@@ -44,15 +44,14 @@ namespace Discord
private string _name { get; set; }

/// <summary>
/// Build the current builder into a <see cref="ContextMenuCommandCreationProperties"/> class.
/// Build the current builder into a <see cref="UserCommandProperties"/> class.
/// </summary>
/// <returns>A <see cref="ContextMenuCommandCreationProperties"/> that can be used to create user commands over rest.</returns>
public ContextMenuCommandCreationProperties Build()
/// <returns>A <see cref="UserCommandProperties"/> that can be used to create user commands.</returns>
public UserCommandProperties Build()
{
ContextMenuCommandCreationProperties props = new ContextMenuCommandCreationProperties()
UserCommandProperties props = new UserCommandProperties()
{
Name = this.Name,
Type=ApplicationCommandType.User
};

return props;

+ 16
- 0
src/Discord.Net.Core/Entities/Interactions/Context Menus/UserCommandProperties.cs View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord
{
/// <summary>
/// A class used to create User commands.
/// </summary>
public class UserCommandProperties : ApplicationCommandProperties
{
internal override ApplicationCommandType Type => ApplicationCommandType.User;
}
}

+ 0
- 24
src/Discord.Net.Core/Entities/Interactions/ContextMenuCommandCreationProperties.cs View File

@@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord
{
/// <summary>
/// A class used to create Message commands.
/// </summary>
public class ContextMenuCommandCreationProperties
{
/// <summary>
/// The name of this command.
/// </summary>
public string Name { get; set; }

/// <summary>
/// Gets or sets the type for this command.
/// </summary>
public ApplicationCommandType Type { get; set; }
}
}

+ 11
- 1
src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace Discord
{
/// <summary>
/// The base command model that belongs to an application. see <see href="https://discord.com/developers/docs/interactions/slash-commands#applicationcommand"/>
/// The base command model that belongs to an application.
/// </summary>
public interface IApplicationCommand : ISnowflakeEntity, IDeletable
{
@@ -40,5 +40,15 @@ namespace Discord
/// If the option is a subcommand or subcommand group type, this nested options will be the parameters.
/// </summary>
IReadOnlyCollection<IApplicationCommandOption> Options { get; }

/// <summary>
/// Modifies the current application command.
/// </summary>
/// <param name="func">The new properties to use when modifying the command.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous modification operation.
/// </returns>
Task ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null);
}
}

+ 4
- 5
src/Discord.Net.Core/Entities/Interactions/SlashCommandBuilder.cs View File

@@ -93,17 +93,16 @@ namespace Discord
private List<SlashCommandOptionBuilder> _options { get; set; }

/// <summary>
/// Build the current builder into a <see cref="SlashCommandCreationProperties"/> class.
/// Build the current builder into a <see cref="SlashCommandProperties"/> class.
/// </summary>
/// <returns>A <see cref="SlashCommandCreationProperties"/> that can be used to create slash commands over rest.</returns>
public SlashCommandCreationProperties Build()
/// <returns>A <see cref="SlashCommandProperties"/> that can be used to create slash commands over rest.</returns>
public SlashCommandProperties Build()
{
SlashCommandCreationProperties props = new SlashCommandCreationProperties()
SlashCommandProperties props = new SlashCommandProperties()
{
Name = this.Name,
Description = this.Description,
DefaultPermission = this.DefaultPermission,
Type = ApplicationCommandType.Slash
};

if (this.Options != null && this.Options.Any())


src/Discord.Net.Core/Entities/Interactions/SlashCommandCreationProperties.cs → src/Discord.Net.Core/Entities/Interactions/SlashCommandProperties.cs View File

@@ -9,22 +9,13 @@ namespace Discord
/// <summary>
/// A class used to create slash commands.
/// </summary>
public class SlashCommandCreationProperties
public class SlashCommandProperties : ApplicationCommandProperties
{
/// <summary>
/// The name of this command.
/// </summary>
public string Name { get; set; }

internal override ApplicationCommandType Type => ApplicationCommandType.Slash;
/// <summary>
/// The discription of this command.
/// </summary>
public string Description { get; set; }

/// <summary>
/// Gets or sets the type for this command.
/// </summary>
public ApplicationCommandType Type { get; set; }
public Optional<string> Description { get; set; }

/// <summary>
/// Gets or sets the options for this command.
@@ -35,5 +26,7 @@ namespace Discord
/// Whether the command is enabled by default when the app is added to a guild. Default is <see langword="true"/>
/// </summary>
public Optional<bool> DefaultPermission { get; set; }

internal SlashCommandProperties() { }
}
}

+ 0
- 30
src/Discord.Net.Core/Entities/Interactions/UserCommandCreationProperties.cs View File

@@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord
{
/// <summary>
/// A class used to create User commands.
/// </summary>
public class UserCommandCreationProperties
{
/// <summary>
/// The name of this command.
/// </summary>
public string Name { get; set; }

/// <summary>
/// The discription of this command.
/// </summary>
public string Description { get; set; }


/// <summary>
/// Gets or sets the type for this command.
/// </summary>
public ApplicationCommandType Type { get; set; }
}
}

+ 8
- 0
src/Discord.Net.Rest/API/Common/ApplicationCommand.cs View File

@@ -11,14 +11,22 @@ namespace Discord.API
{
[JsonProperty("id")]
public ulong Id { get; set; }

[JsonProperty("type")]
public ApplicationCommandType Type { get; set; } = ApplicationCommandType.Slash; // defaults to 1 which is slash.

[JsonProperty("application_id")]
public ulong ApplicationId { get; set; }

[JsonProperty("name")]
public string Name { get; set; }

[JsonProperty("description")]
public string Description { get; set; }

[JsonProperty("options")]
public Optional<ApplicationCommandOption[]> Options { get; set; }

[JsonProperty("default_permission")]
public Optional<bool> DefaultPermissions { get; set; }
}


+ 0
- 1
src/Discord.Net.Rest/API/Net/IResolvable.cs View File

@@ -9,6 +9,5 @@ namespace Discord.API
internal interface IResolvable
{
Optional<ApplicationCommandInteractionDataResolved> Resolved { get; }

}
}

+ 0
- 3
src/Discord.Net.Rest/API/Rest/ModifyApplicationCommandParams.cs View File

@@ -15,9 +15,6 @@ namespace Discord.API.Rest
[JsonProperty("description")]
public Optional<string> Description { get; set; }

[JsonProperty("type")]
public Optional<ApplicationCommandType> Type { get; set; }

[JsonProperty("options")]
public Optional<ApplicationCommandOption[]> Options { get; set; }



+ 5
- 116
src/Discord.Net.Rest/Discord.Net.Rest.xml View File

@@ -3762,17 +3762,15 @@
The options of this command.
</summary>
</member>
<member name="P:Discord.Rest.RestApplicationCommand.CommandType">
<summary>
The type of this rest application command.
</summary>
</member>
<member name="P:Discord.Rest.RestApplicationCommand.CreatedAt">
<inheritdoc/>
</member>
<member name="M:Discord.Rest.RestApplicationCommand.DeleteAsync(Discord.RequestOptions)">
<inheritdoc/>
</member>
<member name="M:Discord.Rest.RestApplicationCommand.ModifyAsync(System.Action{Discord.ApplicationCommandProperties},Discord.RequestOptions)">
<inheritdoc/>
</member>
<member name="T:Discord.Rest.RestApplicationCommandChoice">
<summary>
Represents a Rest-based implementation of <see cref="T:Discord.IApplicationCommandOptionChoice"/>.
@@ -3814,24 +3812,9 @@
A collection of <see cref="T:Discord.Rest.RestApplicationCommandOption"/>'s for this command.
</summary>
</member>
<member name="T:Discord.Rest.RestApplicationCommandType">
<summary>
Represents a type of Rest-based command.
</summary>
</member>
<member name="F:Discord.Rest.RestApplicationCommandType.GlobalCommand">
<summary>
Specifies that this command is a Global command.
</summary>
</member>
<member name="F:Discord.Rest.RestApplicationCommandType.GuildCommand">
<summary>
Specifies that this command is a Guild specific command.
</summary>
</member>
<member name="T:Discord.Rest.RestGlobalCommand">
<summary>
Represents a global Slash command.
Represents a Rest-based global application command.
</summary>
</member>
<member name="M:Discord.Rest.RestGlobalCommand.DeleteAsync(Discord.RequestOptions)">
@@ -3847,35 +3830,9 @@
The modified command.
</returns>
</member>
<member name="M:Discord.Rest.RestGlobalMessageCommand.DeleteAsync(Discord.RequestOptions)">
<inheritdoc/>
</member>
<member name="M:Discord.Rest.RestGlobalMessageCommand.ModifyAsync(System.Action{Discord.ApplicationCommandProperties},Discord.RequestOptions)">
<summary>
Modifies this <see cref="T:Discord.Rest.RestApplicationCommand"/>.
</summary>
<param name="func">The delegate containing the properties to modify the command with.</param>
<param name="options">The options to be used when sending the request.</param>
<returns>
The modified command.
</returns>
</member>
<member name="M:Discord.Rest.RestGlobalUserCommand.DeleteAsync(Discord.RequestOptions)">
<inheritdoc/>
</member>
<member name="M:Discord.Rest.RestGlobalUserCommand.ModifyAsync(System.Action{Discord.ApplicationCommandProperties},Discord.RequestOptions)">
<summary>
Modifies this <see cref="T:Discord.Rest.RestApplicationCommand"/>.
</summary>
<param name="func">The delegate containing the properties to modify the command with.</param>
<param name="options">The options to be used when sending the request.</param>
<returns>
The modified command.
</returns>
</member>
<member name="T:Discord.Rest.RestGuildCommand">
<summary>
Represents a Rest-based guild command.
Represents a Rest-based guild application command.
</summary>
</member>
<member name="P:Discord.Rest.RestGuildCommand.GuildId">
@@ -3928,74 +3885,6 @@
<see cref="T:Discord.Rest.RestGuild"/>.
</returns>
</member>
<member name="T:Discord.Rest.RestGuildMessageCommand">
<summary>
Represents a Rest-based guild command.
</summary>
</member>
<member name="P:Discord.Rest.RestGuildMessageCommand.GuildId">
<summary>
The guild Id where this command originates.
</summary>
</member>
<member name="M:Discord.Rest.RestGuildMessageCommand.DeleteAsync(Discord.RequestOptions)">
<inheritdoc/>
</member>
<member name="M:Discord.Rest.RestGuildMessageCommand.ModifyAsync(System.Action{Discord.ApplicationCommandProperties},Discord.RequestOptions)">
<summary>
Modifies this <see cref="T:Discord.Rest.RestApplicationCommand"/>.
</summary>
<param name="func">The delegate containing the properties to modify the command with.</param>
<param name="options">The options to be used when sending the request.</param>
<returns>
The modified command
</returns>
</member>
<member name="M:Discord.Rest.RestGuildMessageCommand.GetGuild(System.Boolean,Discord.RequestOptions)">
<summary>
Gets the guild that this slash command resides in.
</summary>
<param name="withCounts"><see langword="true"/> if you want the approximate member and presence counts for the guild, otherwise <see langword="false"/>.</param>
<param name="options">The options to be used when sending the request.</param>
<returns>
A task that represents the asynchronous get operation. The task result contains a
<see cref="T:Discord.Rest.RestGuild"/>.
</returns>
</member>
<member name="T:Discord.Rest.RestGuildUserCommand">
<summary>
Represents a Rest-based guild command.
</summary>
</member>
<member name="P:Discord.Rest.RestGuildUserCommand.GuildId">
<summary>
The guild Id where this command originates.
</summary>
</member>
<member name="M:Discord.Rest.RestGuildUserCommand.DeleteAsync(Discord.RequestOptions)">
<inheritdoc/>
</member>
<member name="M:Discord.Rest.RestGuildUserCommand.ModifyAsync(System.Action{Discord.ApplicationCommandProperties},Discord.RequestOptions)">
<summary>
Modifies this <see cref="T:Discord.Rest.RestApplicationCommand"/>.
</summary>
<param name="func">The delegate containing the properties to modify the command with.</param>
<param name="options">The options to be used when sending the request.</param>
<returns>
The modified command
</returns>
</member>
<member name="M:Discord.Rest.RestGuildUserCommand.GetGuild(System.Boolean,Discord.RequestOptions)">
<summary>
Gets the guild that this slash command resides in.
</summary>
<param name="withCounts"><see langword="true"/> if you want the approximate member and presence counts for the guild, otherwise <see langword="false"/>.</param>
<param name="options">The options to be used when sending the request.</param>
<returns>
A task that represents the asynchronous get operation. The task result contains a
<see cref="T:Discord.Rest.RestGuild"/>.
</returns>
</member>
<member name="P:Discord.Rest.RestInvite.ChannelName">
<inheritdoc />
</member>


+ 6
- 22
src/Discord.Net.Rest/DiscordRestClient.cs View File

@@ -108,37 +108,21 @@ namespace Discord.Rest
public Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null)
=> ClientHelper.GetWebhookAsync(this, id, options);

public Task<RestGlobalCommand> CreateGlobalCommand(SlashCommandCreationProperties properties, RequestOptions options = null)
public Task<RestGlobalCommand> CreateGlobalCommand(ApplicationCommandProperties properties, RequestOptions options = null)
=> InteractionHelper.CreateGlobalCommand(this, properties, options);
public Task<RestGlobalCommand> CreateGlobalCommand(Action<SlashCommandCreationProperties> func, RequestOptions options = null)
public Task<RestGlobalCommand> CreateGlobalCommand(Action<ApplicationCommandProperties> func, RequestOptions options = null)
=> InteractionHelper.CreateGlobalCommand(this, func, options);
public Task<RestGlobalUserCommand> CreateGlobalUserCommand(ContextMenuCommandCreationProperties properties, RequestOptions options = null)
=> InteractionHelper.CreateGlobalUserCommand(this, properties, options);
public Task<RestGlobalUserCommand> CreateGlobalUserCommand(Action<ContextMenuCommandCreationProperties> func, RequestOptions options = null)
=> InteractionHelper.CreateGlobalUserCommand(this, func, options);
public Task<RestGlobalMessageCommand> CreateGlobalMessageCommand(ContextMenuCommandCreationProperties properties, RequestOptions options = null)
=> InteractionHelper.CreateGlobalMessageCommand(this, properties, options);
public Task<RestGlobalMessageCommand> CreateGlobalMessageCommand(Action<ContextMenuCommandCreationProperties> func, RequestOptions options = null)
=> InteractionHelper.CreateGlobalMessageCommand(this, func, options);
public Task<RestGuildCommand> CreateGuildCommand(SlashCommandCreationProperties properties, ulong guildId, RequestOptions options = null)
public Task<RestGuildCommand> CreateGuildCommand(ApplicationCommandProperties properties, ulong guildId, RequestOptions options = null)
=> InteractionHelper.CreateGuildCommand(this, guildId, properties, options);
public Task<RestGuildCommand> CreateGuildCommand(Action<SlashCommandCreationProperties> func, ulong guildId, RequestOptions options = null)
public Task<RestGuildCommand> CreateGuildCommand(Action<ApplicationCommandProperties> func, ulong guildId, RequestOptions options = null)
=> InteractionHelper.CreateGuildCommand(this, guildId, func, options);
public Task<RestGuildUserCommand> CreateGuildUserCommand(ContextMenuCommandCreationProperties properties, ulong guildId, RequestOptions options = null)
=> InteractionHelper.CreateGuildUserCommand(this, guildId, properties, options);
public Task<RestGuildUserCommand> CreateGuildUserCommand(Action<ContextMenuCommandCreationProperties> func, ulong guildId, RequestOptions options = null)
=> InteractionHelper.CreateGuildUserCommand(this, guildId, func, options);
public Task<RestGuildMessageCommand> CreateGuildMessageCommand(ContextMenuCommandCreationProperties properties, ulong guildId, RequestOptions options = null)
=> InteractionHelper.CreateGuildMessageCommand(this, guildId, properties, options);
public Task<RestGuildMessageCommand> CreateGuildMessageCommand(Action<ContextMenuCommandCreationProperties> func, ulong guildId, RequestOptions options = null)
=> InteractionHelper.CreateGuildMessageCommand(this, guildId, func, options);
public Task<IReadOnlyCollection<RestGlobalCommand>> GetGlobalApplicationCommands(RequestOptions options = null)
=> ClientHelper.GetGlobalApplicationCommands(this, options);
public Task<IReadOnlyCollection<RestGuildCommand>> GetGuildApplicationCommands(ulong guildId, RequestOptions options = null)
=> ClientHelper.GetGuildApplicationCommands(this, guildId, options);
public Task<IReadOnlyCollection<RestGlobalCommand>> BulkOverwriteGlobalCommands(SlashCommandCreationProperties[] commandProperties, RequestOptions options = null)
public Task<IReadOnlyCollection<RestGlobalCommand>> BulkOverwriteGlobalCommands(ApplicationCommandProperties[] commandProperties, RequestOptions options = null)
=> InteractionHelper.BulkOverwriteGlobalCommands(this, commandProperties, options);
public Task<IReadOnlyCollection<RestGuildCommand>> BulkOverwriteGuildCommands(SlashCommandCreationProperties[] commandProperties, ulong guildId, RequestOptions options = null)
public Task<IReadOnlyCollection<RestGuildCommand>> BulkOverwriteGuildCommands(ApplicationCommandProperties[] commandProperties, ulong guildId, RequestOptions options = null)
=> InteractionHelper.BulkOverwriteGuildCommands(this, guildId, commandProperties, options);
public Task<IReadOnlyCollection<GuildApplicationCommandPermission>> BatchEditGuildCommandPermissions(ulong guildId, IDictionary<ulong, ApplicationCommandPermission[]> permissions, RequestOptions options = null)
=> InteractionHelper.BatchEditGuildCommandPermissionsAsync(this, guildId, permissions, options);


+ 130
- 438
src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs View File

@@ -44,41 +44,45 @@ namespace Discord.Rest
}

// Global commands
public static async Task<RestGlobalCommand> CreateGlobalCommand(BaseDiscordClient client,
Action<SlashCommandCreationProperties> func, RequestOptions options = null)
public static async Task<RestGlobalCommand> CreateGlobalCommand<TArg>(BaseDiscordClient client,
Action<TArg> func, RequestOptions options) where TArg : ApplicationCommandProperties
{
var args = new SlashCommandCreationProperties();
func(args);
return await CreateGlobalCommand(client, args, options).ConfigureAwait(false);
var args = Activator.CreateInstance(typeof(TArg));
func((TArg)args);
return await CreateGlobalCommand(client, (TArg)args, options);
}
public static async Task<RestGlobalCommand> CreateGlobalCommand(BaseDiscordClient client,
SlashCommandCreationProperties arg, RequestOptions options = null)
ApplicationCommandProperties arg, RequestOptions options = null)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
Preconditions.NotNullOrEmpty(arg.Description, nameof(arg.Description));

if (arg.Options.IsSpecified)
Preconditions.AtMost(arg.Options.Value.Count, 25, nameof(arg.Options));

var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
Description = arg.Description,
Type= arg.Type,
Options = arg.Options.IsSpecified
? arg.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified,
DefaultPermission = arg.DefaultPermission.IsSpecified
? arg.DefaultPermission.Value
: Optional<bool>.Unspecified
Name = arg.Name.Value,
Type = arg.Type,
};

if (arg is SlashCommandProperties slashProps)
{
Preconditions.NotNullOrEmpty(slashProps.Description, nameof(slashProps.Description));

model.Description = slashProps.Description.Value;

model.Options = slashProps.Options.IsSpecified
? slashProps.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified;

model.DefaultPermission = slashProps.DefaultPermission.IsSpecified
? slashProps.DefaultPermission.Value
: Optional<bool>.Unspecified;
}

var cmd = await client.ApiClient.CreateGlobalApplicationCommandAsync(model, options).ConfigureAwait(false);
return RestGlobalCommand.Create(client, cmd);
}

public static async Task<IReadOnlyCollection<RestGlobalCommand>> BulkOverwriteGlobalCommands(BaseDiscordClient client,
SlashCommandCreationProperties[] args, RequestOptions options = null)
ApplicationCommandProperties[] args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));

@@ -87,24 +91,28 @@ namespace Discord.Rest
foreach (var arg in args)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
Preconditions.NotNullOrEmpty(arg.Description, nameof(arg.Description));

if (arg.Options.IsSpecified)
Preconditions.AtMost(arg.Options.Value.Count, 25, nameof(arg.Options));

var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
Description = arg.Description,
Name = arg.Name.Value,
Type = arg.Type,
Options = arg.Options.IsSpecified
? arg.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified,
DefaultPermission = arg.DefaultPermission.IsSpecified
? arg.DefaultPermission.Value
: Optional<bool>.Unspecified
};

if (arg is SlashCommandProperties slashProps)
{
Preconditions.NotNullOrEmpty(slashProps.Description, nameof(slashProps.Description));

model.Description = slashProps.Description.Value;

model.Options = slashProps.Options.IsSpecified
? slashProps.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified;

model.DefaultPermission = slashProps.DefaultPermission.IsSpecified
? slashProps.DefaultPermission.Value
: Optional<bool>.Unspecified;
}

models.Add(model);
}

@@ -114,7 +122,7 @@ namespace Discord.Rest
}

public static async Task<IReadOnlyCollection<RestGuildCommand>> BulkOverwriteGuildCommands(BaseDiscordClient client, ulong guildId,
SlashCommandCreationProperties[] args, RequestOptions options = null)
ApplicationCommandProperties[] args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));

@@ -123,236 +131,88 @@ namespace Discord.Rest
foreach (var arg in args)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
Preconditions.NotNullOrEmpty(arg.Description, nameof(arg.Description));

if (arg.Options.IsSpecified)
Preconditions.AtMost(arg.Options.Value.Count, 25, nameof(arg.Options));

var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
Description = arg.Description,
Name = arg.Name.Value,
Type = arg.Type,
Options = arg.Options.IsSpecified
? arg.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified,
DefaultPermission = arg.DefaultPermission.IsSpecified
? arg.DefaultPermission.Value
: Optional<bool>.Unspecified
};

models.Add(model);
}

var apiModels = await client.ApiClient.BulkOverwriteGuildApplicationCommands(guildId, models.ToArray(), options);

return apiModels.Select(x => RestGuildCommand.Create(client, x, guildId)).ToArray();
}
if (arg is SlashCommandProperties slashProps)
{
Preconditions.NotNullOrEmpty(slashProps.Description, nameof(slashProps.Description));

public static async Task<RestGlobalCommand> ModifyGlobalCommand(BaseDiscordClient client, RestGlobalCommand command,
Action<ApplicationCommandProperties> func, RequestOptions options = null)
{
ApplicationCommandProperties args = new ApplicationCommandProperties();
func(args);
model.Description = slashProps.Description.Value;

if (args.Name.IsSpecified)
{
Preconditions.AtMost(args.Name.Value.Length, 32, nameof(args.Name));
Preconditions.AtLeast(args.Name.Value.Length, 3, nameof(args.Name));
}
if (args.Description.IsSpecified)
{
Preconditions.AtMost(args.Description.Value.Length, 100, nameof(args.Description));
Preconditions.AtLeast(args.Description.Value.Length, 1, nameof(args.Description));
}
model.Options = slashProps.Options.IsSpecified
? slashProps.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified;

model.DefaultPermission = slashProps.DefaultPermission.IsSpecified
? slashProps.DefaultPermission.Value
: Optional<bool>.Unspecified;
}

if (args.Options.IsSpecified)
{
if (args.Options.Value.Count > 10)
throw new ArgumentException("Option count must be 10 or less");
models.Add(model);
}

var model = new Discord.API.Rest.ModifyApplicationCommandParams()
{
Name = args.Name,
Description = args.Description,
Type = args.Type,
Options = args.Options.IsSpecified
? args.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified,
DefaultPermission = args.DefaultPermission.IsSpecified
? args.DefaultPermission.Value
: Optional<bool>.Unspecified
};

var msg = await client.ApiClient.ModifyGlobalApplicationCommandAsync(model, command.Id, options).ConfigureAwait(false);
command.Update(msg);
return command;
}


public static async Task DeleteGlobalCommand(BaseDiscordClient client, RestGlobalCommand command, RequestOptions options = null)
{
Preconditions.NotNull(command, nameof(command));
Preconditions.NotEqual(command.Id, 0, nameof(command.Id));

await client.ApiClient.DeleteGlobalApplicationCommandAsync(command.Id, options).ConfigureAwait(false);
}

public static async Task<RestGlobalUserCommand> CreateGlobalUserCommand(BaseDiscordClient client, Action<ContextMenuCommandCreationProperties> func, RequestOptions options = null)
{
var args = new ContextMenuCommandCreationProperties();
func(args);
return await CreateGlobalUserCommand(client, args, options).ConfigureAwait(false);
}

public static async Task<RestGlobalUserCommand> CreateGlobalUserCommand(BaseDiscordClient client, ContextMenuCommandCreationProperties arg, RequestOptions options = null)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));

var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
Type = arg.Type
};

var cmd = await client.ApiClient.CreateGlobalApplicationUserCommandAsync(model, options).ConfigureAwait(false);
return RestGlobalUserCommand.Create(client, cmd);
}
var apiModels = await client.ApiClient.BulkOverwriteGuildApplicationCommands(guildId, models.ToArray(), options);

public static async Task<RestGlobalMessageCommand> CreateGlobalMessageCommand(BaseDiscordClient client, Action<ContextMenuCommandCreationProperties> func, RequestOptions options = null)
{
var args = new ContextMenuCommandCreationProperties();
func(args);
return await CreateGlobalMessageCommand(client, args, options).ConfigureAwait(false);
return apiModels.Select(x => RestGuildCommand.Create(client, x, guildId)).ToArray();
}

public static async Task<RestGlobalMessageCommand> CreateGlobalMessageCommand(BaseDiscordClient client, ContextMenuCommandCreationProperties arg, RequestOptions options = null)
public static Task<ApplicationCommand> ModifyGlobalCommand<TArg>(BaseDiscordClient client, IApplicationCommand command,
Action<TArg> func, RequestOptions options = null) where TArg : ApplicationCommandProperties
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));

var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
Type = arg.Type
};

var cmd = await client.ApiClient.CreateGlobalApplicationMessageCommandAsync(model, options).ConfigureAwait(false);
return RestGlobalMessageCommand.Create(client, cmd);
var arg = (TArg)Activator.CreateInstance(typeof(TArg));
func(arg);
return ModifyGlobalCommand(client, command, arg, options);
}

public static async Task<IReadOnlyCollection<RestGlobalUserCommand>> BulkOverwriteGlobalUserCommands(BaseDiscordClient client, ContextMenuCommandCreationProperties[] args, RequestOptions options = null)
public static async Task<ApplicationCommand> ModifyGlobalCommand(BaseDiscordClient client, IApplicationCommand command,
ApplicationCommandProperties args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));

List<CreateApplicationCommandParams> models = new List<CreateApplicationCommandParams>();

foreach (var arg in args)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
Preconditions.Equals(arg.Type, ApplicationCommandType.User);

var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
Type = arg.Type
};

models.Add(model);
}

var apiModels = await client.ApiClient.BulkOverwriteGlobalApplicationUserCommands(models.ToArray(), options);

return apiModels.Select(x => RestGlobalUserCommand.Create(client, x)).ToArray();
}
public static async Task<RestGlobalUserCommand> ModifyGlobalUserCommand(BaseDiscordClient client, RestGlobalUserCommand command,
Action<ApplicationCommandProperties> func, RequestOptions options = null)
{
ApplicationCommandProperties args = new ApplicationCommandProperties();
func(args);

if (args.Name.IsSpecified)
{
Preconditions.AtMost(args.Name.Value.Length, 32, nameof(args.Name));
Preconditions.AtLeast(args.Name.Value.Length, 3, nameof(args.Name));
}
if (args.Description.IsSpecified)
{
Preconditions.Equals(args.Description.Value, "");
}

var model = new Discord.API.Rest.ModifyApplicationCommandParams()
{
Name = args.Name,
Description = args.Description
};

var msg = await client.ApiClient.ModifyGlobalApplicationUserCommandAsync(model, command.Id, options).ConfigureAwait(false);
command.Update(msg);
return command;
}

public static async Task DeleteGlobalUserCommand(BaseDiscordClient client, RestGlobalUserCommand command, RequestOptions options = null)
{
Preconditions.NotNull(command, nameof(command));
Preconditions.NotEqual(command.Id, 0, nameof(command.Id));

await client.ApiClient.DeleteGlobalApplicationCommandAsync(command.Id, options).ConfigureAwait(false);
}

public static async Task<IReadOnlyCollection<RestGlobalMessageCommand>> BulkOverwriteGlobalMessageCommands(BaseDiscordClient client, ContextMenuCommandCreationProperties[] args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));

List<CreateApplicationCommandParams> models = new List<CreateApplicationCommandParams>();

foreach (var arg in args)
if(args is SlashCommandProperties slashProps)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
Preconditions.Equals(arg.Type, ApplicationCommandType.Message);

var model = new CreateApplicationCommandParams()
if (slashProps.Description.IsSpecified)
{
Name = arg.Name,
Type = arg.Type
};
Preconditions.AtMost(slashProps.Description.Value.Length, 100, nameof(slashProps.Description));
Preconditions.AtLeast(slashProps.Description.Value.Length, 1, nameof(slashProps.Description));
}

models.Add(model);
}
if (slashProps.Options.IsSpecified)
{
if (slashProps.Options.Value.Count > 10)
throw new ArgumentException("Option count must be 10 or less");
}

var apiModels = await client.ApiClient.BulkOverwriteGlobalApplicationMessageCommands(models.ToArray(), options);
model.Description = slashProps.Description;

return apiModels.Select(x => RestGlobalMessageCommand.Create(client, x)).ToArray();
}
public static async Task<RestGlobalMessageCommand> ModifyGlobalMessageCommand(BaseDiscordClient client, RestGlobalMessageCommand command,
Action<ApplicationCommandProperties> func, RequestOptions options = null)
{
ApplicationCommandProperties args = new ApplicationCommandProperties();
func(args);
model.Options = slashProps.Options.IsSpecified
? slashProps.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified;

if (args.Name.IsSpecified)
{
Preconditions.AtMost(args.Name.Value.Length, 32, nameof(args.Name));
Preconditions.AtLeast(args.Name.Value.Length, 3, nameof(args.Name));
}
if (args.Description.IsSpecified)
{
Preconditions.Equals(args.Description.Value, "");
model.DefaultPermission = slashProps.DefaultPermission.IsSpecified
? slashProps.DefaultPermission.Value
: Optional<bool>.Unspecified;
}

var model = new Discord.API.Rest.ModifyApplicationCommandParams()
{
Name = args.Name,
Description = args.Description
};

var msg = await client.ApiClient.ModifyGlobalApplicationMessageCommandAsync(model, command.Id, options).ConfigureAwait(false);
command.Update(msg);
return command;
return await client.ApiClient.ModifyGlobalApplicationCommandAsync(model, command.Id, options).ConfigureAwait(false);
}

public static async Task DeleteGlobalMessageCommand(BaseDiscordClient client, RestGlobalMessageCommand command, RequestOptions options = null)

public static async Task DeleteGlobalCommand(BaseDiscordClient client, IApplicationCommand command, RequestOptions options = null)
{
Preconditions.NotNull(command, nameof(command));
Preconditions.NotEqual(command.Id, 0, nameof(command.Id));
@@ -361,197 +221,77 @@ namespace Discord.Rest
}

// Guild Commands
public static async Task<RestGuildCommand> CreateGuildCommand(BaseDiscordClient client, ulong guildId,
Action<SlashCommandCreationProperties> func, RequestOptions options = null)
public static async Task<RestGuildCommand> CreateGuildCommand<TArg>(BaseDiscordClient client, ulong guildId,
Action<TArg> func, RequestOptions options) where TArg : ApplicationCommandProperties
{
var args = new SlashCommandCreationProperties();
func(args);

return await CreateGuildCommand(client, guildId, args, options).ConfigureAwait(false);
var args = Activator.CreateInstance(typeof(TArg));
func((TArg)args);
return await CreateGuildCommand(client, guildId, (TArg)args, options);
}

public static async Task<RestGuildCommand> CreateGuildCommand(BaseDiscordClient client, ulong guildId,
SlashCommandCreationProperties args, RequestOptions options = null)
ApplicationCommandProperties arg, RequestOptions options = null)
{
Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name));
Preconditions.NotNullOrEmpty(args.Description, nameof(args.Description));

Preconditions.AtMost(args.Name.Length, 32, nameof(args.Name));
Preconditions.AtLeast(args.Name.Length, 3, nameof(args.Name));
Preconditions.AtMost(args.Description.Length, 100, nameof(args.Description));
Preconditions.AtLeast(args.Description.Length, 1, nameof(args.Description));

if (args.Options.IsSpecified)
{
if (args.Options.Value.Count > 10)
throw new ArgumentException("Option count must be 10 or less");

foreach (var item in args.Options.Value)
{
Preconditions.NotNullOrEmpty(item.Name, nameof(item.Name));
Preconditions.NotNullOrEmpty(item.Description, nameof(item.Description));
}
}

var model = new CreateApplicationCommandParams()
{
Name = args.Name,
Description = args.Description,
Type = args.Type,
Options = args.Options.IsSpecified
? args.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified,
DefaultPermission = args.DefaultPermission.IsSpecified
? args.DefaultPermission.Value
: Optional<bool>.Unspecified
Name = arg.Name.Value,
Type = arg.Type,
};

var cmd = await client.ApiClient.CreateGuildApplicationCommandAsync(model, guildId, options).ConfigureAwait(false);
return RestGuildCommand.Create(client, cmd, guildId);
}
public static async Task<RestGuildCommand> ModifyGuildCommand(BaseDiscordClient client, RestGuildCommand command,
Action<ApplicationCommandProperties> func, RequestOptions options = null)
{
ApplicationCommandProperties args = new ApplicationCommandProperties();
func(args);

if (args.Name.IsSpecified)
{
Preconditions.AtMost(args.Name.Value.Length, 32, nameof(args.Name));
Preconditions.AtLeast(args.Name.Value.Length, 3, nameof(args.Name));
}
if (args.Description.IsSpecified)
if (arg is SlashCommandProperties slashProps)
{
Preconditions.AtMost(args.Description.Value.Length, 100, nameof(args.Description));
Preconditions.AtLeast(args.Description.Value.Length, 1, nameof(args.Description));
}
Preconditions.NotNullOrEmpty(slashProps.Description, nameof(slashProps.Description));

if (args.Options.IsSpecified)
{
if (args.Options.Value.Count > 10)
throw new ArgumentException("Option count must be 10 or less");
}
model.Description = slashProps.Description.Value;

var model = new Discord.API.Rest.ModifyApplicationCommandParams()
{
Name = args.Name,
Description = args.Description,
Type = args.Type,
Options = args.Options.IsSpecified
? args.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified,
DefaultPermission = args.DefaultPermission.IsSpecified
? args.DefaultPermission.Value
: Optional<bool>.Unspecified
};

var msg = await client.ApiClient.ModifyGuildApplicationCommandAsync(model, command.GuildId, command.Id, options).ConfigureAwait(false);
command.Update(msg);
return command;
}

public static async Task DeleteGuildCommand(BaseDiscordClient client, ulong guildId, IApplicationCommand command, RequestOptions options = null)
{
Preconditions.NotNull(command, nameof(command));
Preconditions.NotEqual(command.Id, 0, nameof(command.Id));

await client.ApiClient.DeleteGuildApplicationCommandAsync(guildId, command.Id, options).ConfigureAwait(false);
}

public static async Task<RestGuildUserCommand> CreateGuildUserCommand(BaseDiscordClient client, ulong guildId, Action<ContextMenuCommandCreationProperties> func, RequestOptions options = null)
{
var args = new ContextMenuCommandCreationProperties();
func(args);
return await CreateGuildUserCommand(client, guildId, args, options).ConfigureAwait(false);
}
model.Options = slashProps.Options.IsSpecified
? slashProps.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified;

public static async Task<RestGuildUserCommand> CreateGuildUserCommand(BaseDiscordClient client, ulong guildId, ContextMenuCommandCreationProperties arg, RequestOptions options = null)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));

var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
Type = arg.Type
};
model.DefaultPermission = slashProps.DefaultPermission.IsSpecified
? slashProps.DefaultPermission.Value
: Optional<bool>.Unspecified;
}

var cmd = await client.ApiClient.CreateGuildApplicationUserCommandAsync(model, guildId, options).ConfigureAwait(false);
return RestGuildUserCommand.Create(client, cmd, guildId);
var cmd = await client.ApiClient.CreateGuildApplicationCommandAsync(model, guildId, options).ConfigureAwait(false);
return RestGuildCommand.Create(client, cmd, guildId);
}

public static async Task<RestGuildMessageCommand> CreateGuildMessageCommand(BaseDiscordClient client, ulong guildId, Action<ContextMenuCommandCreationProperties> func, RequestOptions options = null)
public static Task<ApplicationCommand> ModifyGuildCommand<TArg>(BaseDiscordClient client, IApplicationCommand command, ulong guildId,
Action<TArg> func, RequestOptions options = null) where TArg : ApplicationCommandProperties
{
var args = new ContextMenuCommandCreationProperties();
func(args);
return await CreateGuildMessageCommand(client, guildId, args, options).ConfigureAwait(false);
var arg = (TArg)Activator.CreateInstance(typeof(TArg));
func(arg);
return ModifyGuildCommand(client, command, guildId, arg, options);
}

public static async Task<RestGuildMessageCommand> CreateGuildMessageCommand(BaseDiscordClient client, ulong guildId, ContextMenuCommandCreationProperties arg, RequestOptions options = null)
public static async Task<ApplicationCommand> ModifyGuildCommand(BaseDiscordClient client, IApplicationCommand command, ulong guildId,
ApplicationCommandProperties arg, RequestOptions options = null)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));

var model = new CreateApplicationCommandParams()
var model = new ModifyApplicationCommandParams()
{
Name = arg.Name,
Type = arg.Type
Name = arg.Name.Value,
};

var cmd = await client.ApiClient.CreateGuildApplicationMessageCommandAsync(model, guildId, options).ConfigureAwait(false);
return RestGuildMessageCommand.Create(client, cmd, guildId);
}

public static async Task<IReadOnlyCollection<RestGuildUserCommand>> BulkOverwriteGuildUserCommands(BaseDiscordClient client, ulong guildId, ContextMenuCommandCreationProperties[] args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));

List<CreateApplicationCommandParams> models = new List<CreateApplicationCommandParams>();

foreach (var arg in args)
if (arg is SlashCommandProperties slashProps)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
Preconditions.Equals(arg.Type, ApplicationCommandType.User);
Preconditions.NotNullOrEmpty(slashProps.Description, nameof(slashProps.Description));

var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
Type = arg.Type
};
model.Description = slashProps.Description.Value;

models.Add(model);
}

var apiModels = await client.ApiClient.BulkOverwriteGuildApplicationUserCommands(guildId, models.ToArray(), options);

return apiModels.Select(x => RestGuildUserCommand.Create(client, x, guildId)).ToArray();
}
public static async Task<RestGuildUserCommand> ModifyGuildUserCommand(BaseDiscordClient client, RestGuildUserCommand command,
Action<ApplicationCommandProperties> func, RequestOptions options = null)
{
ApplicationCommandProperties args = new ApplicationCommandProperties();
func(args);
model.Options = slashProps.Options.IsSpecified
? slashProps.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified;

if (args.Name.IsSpecified)
{
Preconditions.AtMost(args.Name.Value.Length, 32, nameof(args.Name));
Preconditions.AtLeast(args.Name.Value.Length, 3, nameof(args.Name));
}
if (args.Description.IsSpecified)
{
Preconditions.Equals(args.Description.Value, "");
model.DefaultPermission = slashProps.DefaultPermission.IsSpecified
? slashProps.DefaultPermission.Value
: Optional<bool>.Unspecified;
}

var model = new Discord.API.Rest.ModifyApplicationCommandParams()
{
Name = args.Name,
Description = args.Description,
Type=args.Type
};

var msg = await client.ApiClient.ModifyGuildApplicationUserCommandAsync(model, command.GuildId, command.Id, options).ConfigureAwait(false);
command.Update(msg);
return command;
return await client.ApiClient.ModifyGuildApplicationCommandAsync(model, guildId, command.Id, options).ConfigureAwait(false);
}

public static async Task DeleteGuildUserCommand(BaseDiscordClient client, ulong guildId, RestGuildUserCommand command, RequestOptions options = null)
public static async Task DeleteGuildCommand(BaseDiscordClient client, ulong guildId, IApplicationCommand command, RequestOptions options = null)
{
Preconditions.NotNull(command, nameof(command));
Preconditions.NotEqual(command.Id, 0, nameof(command.Id));
@@ -559,67 +299,19 @@ namespace Discord.Rest
await client.ApiClient.DeleteGuildApplicationCommandAsync(guildId, command.Id, options).ConfigureAwait(false);
}

public static async Task<IReadOnlyCollection<RestGuildMessageCommand>> BulkOverwriteGuildMessageCommands(BaseDiscordClient client, ulong guildId, ContextMenuCommandCreationProperties[] args, RequestOptions options = null)
public static Task DeleteUnknownApplicationCommand(BaseDiscordClient client, ulong? guildId, IApplicationCommand command, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));

List<CreateApplicationCommandParams> models = new List<CreateApplicationCommandParams>();

foreach (var arg in args)
if (guildId.HasValue)
{
Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name));
Preconditions.Equals(arg.Type, ApplicationCommandType.Message);

var model = new CreateApplicationCommandParams()
{
Name = arg.Name,
Type = arg.Type
};

models.Add(model);
}

var apiModels = await client.ApiClient.BulkOverwriteGuildApplicationMessageCommands(guildId, models.ToArray(), options);

return apiModels.Select(x => RestGuildMessageCommand.Create(client, x, guildId)).ToArray();
}
public static async Task<RestGuildMessageCommand> ModifyGuildMessageCommand(BaseDiscordClient client, RestGuildMessageCommand command,
Action<ApplicationCommandProperties> func, RequestOptions options = null)
{
ApplicationCommandProperties args = new ApplicationCommandProperties();
func(args);

if (args.Name.IsSpecified)
{
Preconditions.AtMost(args.Name.Value.Length, 32, nameof(args.Name));
Preconditions.AtLeast(args.Name.Value.Length, 3, nameof(args.Name));
return DeleteGuildCommand(client, guildId.Value, command, options);
}
if (args.Description.IsSpecified)
else
{
Preconditions.Equals(args.Description.Value, "");
return DeleteGlobalCommand(client, command, options);
}

var model = new Discord.API.Rest.ModifyApplicationCommandParams()
{
Name = args.Name,
Description = args.Description,
Type = args.Type
};

var msg = await client.ApiClient.ModifyGuildApplicationMessageCommandAsync(model, command.GuildId, command.Id, options).ConfigureAwait(false);
command.Update(msg);
return command;
}

public static async Task DeleteGuildMessageCommand(BaseDiscordClient client, ulong guildId, RestGuildMessageCommand command, RequestOptions options = null)
{
Preconditions.NotNull(command, nameof(command));
Preconditions.NotEqual(command.Id, 0, nameof(command.Id));

await client.ApiClient.DeleteGuildApplicationCommandAsync(guildId, command.Id, options).ConfigureAwait(false);
}


// Responses
public static async Task<Discord.API.Message> ModifyFollowupMessage(BaseDiscordClient client, RestFollowupMessage message, Action<MessageProperties> func,
RequestOptions options = null)
{


+ 10
- 29
src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommand.cs View File

@@ -33,11 +33,6 @@ namespace Discord.Rest
/// </summary>
public IReadOnlyCollection<RestApplicationCommandOption> Options { get; private set; }

/// <summary>
/// The type of this rest application command.
/// </summary>
public RestApplicationCommandType CommandType { get; internal set; }

/// <inheritdoc/>
public DateTimeOffset CreatedAt
=> SnowflakeUtils.FromSnowflake(this.Id);
@@ -48,31 +43,15 @@ namespace Discord.Rest

}

internal static RestApplicationCommand Create(BaseDiscordClient client, Model model, RestApplicationCommandType type, ulong guildId = 0)
internal static RestApplicationCommand Create(BaseDiscordClient client, Model model, ulong? guildId)
{
switch (type)
if (guildId.HasValue)
{
return RestGuildCommand.Create(client, model, guildId.Value);
}
else
{
case RestApplicationCommandType.GlobalCommand:
return RestGlobalCommand.Create(client, model);
break;
case RestApplicationCommandType.GlobalUserCommand:
return RestGlobalUserCommand.Create(client, model);
break;
case RestApplicationCommandType.GlobalMessageCommand:
return RestGlobalMessageCommand.Create(client, model);
break;
case RestApplicationCommandType.GuildCommand:
return RestGuildCommand.Create(client, model, guildId);
break;
case RestApplicationCommandType.GuildUserCommand:
return RestGuildUserCommand.Create(client, model, guildId);
break;
case RestApplicationCommandType.GuildMessageCommand:
return RestGuildMessageCommand.Create(client, model, guildId);
break;
default:
return null;
break;
return RestGlobalCommand.Create(client, model);
}
}

@@ -92,7 +71,9 @@ namespace Discord.Rest
/// <inheritdoc/>
public abstract Task DeleteAsync(RequestOptions options = null);

IReadOnlyCollection<IApplicationCommandOption> IApplicationCommand.Options => Options;
/// <inheritdoc/>
public abstract Task ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null);

IReadOnlyCollection<IApplicationCommandOption> IApplicationCommand.Options => Options;
}
}

+ 5
- 2
src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandOption.cs View File

@@ -68,7 +68,10 @@ namespace Discord.Rest
: null;
}

IReadOnlyCollection<IApplicationCommandOption> IApplicationCommandOption.Options => Options;
IReadOnlyCollection<IApplicationCommandOptionChoice> IApplicationCommandOption.Choices => Choices;
//IApplicationCommandOption
IReadOnlyCollection<IApplicationCommandOption> IApplicationCommandOption.Options
=> Options;
IReadOnlyCollection<IApplicationCommandOptionChoice> IApplicationCommandOption.Choices
=> Choices;
}
}

+ 0
- 28
src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandType.cs View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord.Rest
{
/// <summary>
/// Represents a type of Rest-based command.
/// </summary>
public enum RestApplicationCommandType
{
/// <summary>
/// Specifies that this command is a Global command.
/// </summary>
GlobalCommand,
GlobalUserCommand,
GlobalMessageCommand,

/// <summary>
/// Specifies that this command is a Guild specific command.
/// </summary>
GuildCommand,
GuildUserCommand,
GuildMessageCommand
}
}

+ 7
- 4
src/Discord.Net.Rest/Entities/Interactions/RestGlobalCommand.cs View File

@@ -8,14 +8,14 @@ using Model = Discord.API.ApplicationCommand;
namespace Discord.Rest
{
/// <summary>
/// Represents a global Slash command.
/// Represents a Rest-based global application command.
/// </summary>
public class RestGlobalCommand : RestApplicationCommand
{
internal RestGlobalCommand(BaseDiscordClient client, ulong id)
: base(client, id)
{
this.CommandType = RestApplicationCommandType.GlobalCommand;
}

internal static RestGlobalCommand Create(BaseDiscordClient client, Model model)
@@ -37,7 +37,10 @@ namespace Discord.Rest
/// <returns>
/// The modified command.
/// </returns>
public async Task<RestGlobalCommand> ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null)
=> await InteractionHelper.ModifyGlobalCommand(Discord, this, func, options).ConfigureAwait(false);
public override async Task ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null)
{
var cmd = await InteractionHelper.ModifyGlobalCommand(Discord, this, func, options).ConfigureAwait(false);
this.Update(cmd);
}
}
}

+ 0
- 41
src/Discord.Net.Rest/Entities/Interactions/RestGlobalMessageCommand.cs View File

@@ -1,41 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Model = Discord.API.ApplicationCommand;

namespace Discord.Rest
{
public class RestGlobalMessageCommand : RestApplicationCommand
{
internal RestGlobalMessageCommand(BaseDiscordClient client, ulong id)
: base(client, id)
{
this.CommandType = RestApplicationCommandType.GlobalMessageCommand;
}

internal static RestGlobalMessageCommand Create(BaseDiscordClient client, Model model)
{
var entity = new RestGlobalMessageCommand(client, model.Id);
entity.Update(model);
return entity;
}

/// <inheritdoc/>
public override async Task DeleteAsync(RequestOptions options = null)
=> await InteractionHelper.DeleteGlobalMessageCommand(Discord, this).ConfigureAwait(false);

/// <summary>
/// Modifies this <see cref="RestApplicationCommand"/>.
/// </summary>
/// <param name="func">The delegate containing the properties to modify the command with.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// The modified command.
/// </returns>
public async Task<RestGlobalMessageCommand> ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null)
=> await InteractionHelper.ModifyGlobalMessageCommand(Discord, this, func, options).ConfigureAwait(false);
}
}

+ 0
- 41
src/Discord.Net.Rest/Entities/Interactions/RestGlobalUserCommand.cs View File

@@ -1,41 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Model = Discord.API.ApplicationCommand;

namespace Discord.Rest
{
public class RestGlobalUserCommand : RestApplicationCommand
{
internal RestGlobalUserCommand(BaseDiscordClient client, ulong id)
: base(client, id)
{
this.CommandType = RestApplicationCommandType.GlobalUserCommand;
}

internal static RestGlobalUserCommand Create(BaseDiscordClient client, Model model)
{
var entity = new RestGlobalUserCommand(client, model.Id);
entity.Update(model);
return entity;
}

/// <inheritdoc/>
public override async Task DeleteAsync(RequestOptions options = null)
=> await InteractionHelper.DeleteGlobalUserCommand(Discord, this).ConfigureAwait(false);

/// <summary>
/// Modifies this <see cref="RestApplicationCommand"/>.
/// </summary>
/// <param name="func">The delegate containing the properties to modify the command with.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// The modified command.
/// </returns>
public async Task<RestGlobalUserCommand> ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null)
=> await InteractionHelper.ModifyGlobalUserCommand(Discord, this, func, options).ConfigureAwait(false);
}
}

+ 6
- 4
src/Discord.Net.Rest/Entities/Interactions/RestGuildCommand.cs View File

@@ -8,7 +8,7 @@ using Model = Discord.API.ApplicationCommand;
namespace Discord.Rest
{
/// <summary>
/// Represents a Rest-based guild command.
/// Represents a Rest-based guild application command.
/// </summary>
public class RestGuildCommand : RestApplicationCommand
{
@@ -20,7 +20,6 @@ namespace Discord.Rest
internal RestGuildCommand(BaseDiscordClient client, ulong id, ulong guildId)
: base(client, id)
{
this.CommandType = RestApplicationCommandType.GuildCommand;
this.GuildId = guildId;
}

@@ -43,8 +42,11 @@ namespace Discord.Rest
/// <returns>
/// The modified command
/// </returns>
public async Task<RestGuildCommand> ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null)
=> await InteractionHelper.ModifyGuildCommand(Discord, this, func, options).ConfigureAwait(false);
public override async Task ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null)
{
var model = await InteractionHelper.ModifyGuildCommand(Discord, this, GuildId, func, options).ConfigureAwait(false);
this.Update(model);
}

/// <summary>
/// Gets this commands permissions inside of the current guild.


+ 0
- 61
src/Discord.Net.Rest/Entities/Interactions/RestGuildMessageCommand.cs View File

@@ -1,61 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Model = Discord.API.ApplicationCommand;

namespace Discord.Rest
{
/// <summary>
/// Represents a Rest-based guild command.
/// </summary>
public class RestGuildMessageCommand : RestApplicationCommand
{
/// <summary>
/// The guild Id where this command originates.
/// </summary>
public ulong GuildId { get; private set; }

internal RestGuildMessageCommand(BaseDiscordClient client, ulong id, ulong guildId)
: base(client, id)
{
this.CommandType = RestApplicationCommandType.GuildMessageCommand;
this.GuildId = guildId;
}

internal static RestGuildMessageCommand Create(BaseDiscordClient client, Model model, ulong guildId)
{
var entity = new RestGuildMessageCommand(client, model.Id, guildId);
entity.Update(model);
return entity;
}

/// <inheritdoc/>
public override async Task DeleteAsync(RequestOptions options = null)
=> await InteractionHelper.DeleteGuildMessageCommand(Discord, GuildId, this).ConfigureAwait(false);

/// <summary>
/// Modifies this <see cref="RestApplicationCommand"/>.
/// </summary>
/// <param name="func">The delegate containing the properties to modify the command with.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// The modified command
/// </returns>
public async Task<RestGuildMessageCommand> ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null)
=> await InteractionHelper.ModifyGuildMessageCommand(Discord, this, func, options).ConfigureAwait(false);

/// <summary>
/// Gets the guild that this slash command resides in.
/// </summary>
/// <param name="withCounts"><see langword="true"/> if you want the approximate member and presence counts for the guild, otherwise <see langword="false"/>.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous get operation. The task result contains a
/// <see cref="RestGuild"/>.
/// </returns>
public Task<RestGuild> GetGuild(bool withCounts = false, RequestOptions options = null)
=> ClientHelper.GetGuildAsync(this.Discord, this.GuildId, withCounts, options);
}
}

+ 0
- 61
src/Discord.Net.Rest/Entities/Interactions/RestGuildUserCommand.cs View File

@@ -1,61 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Model = Discord.API.ApplicationCommand;

namespace Discord.Rest
{
/// <summary>
/// Represents a Rest-based guild command.
/// </summary>
public class RestGuildUserCommand : RestApplicationCommand
{
/// <summary>
/// The guild Id where this command originates.
/// </summary>
public ulong GuildId { get; private set; }

internal RestGuildUserCommand(BaseDiscordClient client, ulong id, ulong guildId)
: base(client, id)
{
this.CommandType = RestApplicationCommandType.GuildUserCommand;
this.GuildId = guildId;
}

internal static RestGuildUserCommand Create(BaseDiscordClient client, Model model, ulong guildId)
{
var entity = new RestGuildUserCommand(client, model.Id, guildId);
entity.Update(model);
return entity;
}

/// <inheritdoc/>
public override async Task DeleteAsync(RequestOptions options = null)
=> await InteractionHelper.DeleteGuildUserCommand(Discord, GuildId, this).ConfigureAwait(false);

/// <summary>
/// Modifies this <see cref="RestApplicationCommand"/>.
/// </summary>
/// <param name="func">The delegate containing the properties to modify the command with.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// The modified command
/// </returns>
public async Task<RestGuildUserCommand> ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null)
=> await InteractionHelper.ModifyGuildUserCommand(Discord, this, func, options).ConfigureAwait(false);

/// <summary>
/// Gets the guild that this slash command resides in.
/// </summary>
/// <param name="withCounts"><see langword="true"/> if you want the approximate member and presence counts for the guild, otherwise <see langword="false"/>.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous get operation. The task result contains a
/// <see cref="RestGuild"/>.
/// </returns>
public Task<RestGuild> GetGuild(bool withCounts = false, RequestOptions options = null)
=> ClientHelper.GetGuildAsync(this.Discord, this.GuildId, withCounts, options);
}
}

+ 2
- 20
src/Discord.Net.WebSocket/API/Gateway/ApplicationCommandCreatedUpdatedEvent.cs View File

@@ -7,27 +7,9 @@ using System.Threading.Tasks;

namespace Discord.API.Gateway
{
internal class ApplicationCommandCreatedUpdatedEvent
internal class ApplicationCommandCreatedUpdatedEvent : API.ApplicationCommand
{
[JsonProperty("name")]
public string Name { get; set; }

[JsonProperty("id")]
public ulong Id { get; set; }

[JsonProperty("description")]
public string Description { get; set; }

[JsonProperty("application_id")]
public ulong ApplicationId { get; set; }

[JsonProperty("guild_id")]
public ulong GuildId { get; set; }

[JsonProperty("options")]
public Optional<List<Discord.API.ApplicationCommandOption>> Options { get; set; }

[JsonProperty("default_permission")]
public Optional<bool> DefaultPermission { get; set; }
public Optional<ulong> GuildId { get; set; }
}
}

+ 22
- 3
src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml View File

@@ -3752,7 +3752,12 @@
</member>
<member name="T:Discord.WebSocket.SocketApplicationCommand">
<summary>
Represends a Websocket-based <see cref="T:Discord.IApplicationCommand"/> recieved over the gateway.
Represends a Websocket-based <see cref="T:Discord.IApplicationCommand"/>.
</summary>
</member>
<member name="P:Discord.WebSocket.SocketApplicationCommand.IsGlobalCommand">
<summary>
<see langword="true"/> if this command is a global command, otherwise <see langword="false"/>.
</summary>
</member>
<member name="P:Discord.WebSocket.SocketApplicationCommand.ApplicationId">
@@ -3772,20 +3777,34 @@
</member>
<member name="P:Discord.WebSocket.SocketApplicationCommand.Options">
<summary>
A collection of <see cref="T:Discord.WebSocket.SocketApplicationCommandOption"/>'s recieved over the gateway.
A collection of <see cref="T:Discord.WebSocket.SocketApplicationCommandOption"/>'s for this command.
</summary>
<remarks>
If the <see cref="P:Discord.WebSocket.SocketApplicationCommand.Type"/> is not a slash command, this field will be an empty collection.
</remarks>
</member>
<member name="P:Discord.WebSocket.SocketApplicationCommand.CreatedAt">
<inheritdoc/>
</member>
<member name="P:Discord.WebSocket.SocketApplicationCommand.Guild">
<summary>
The <see cref="T:Discord.WebSocket.SocketGuild"/> where this application was created.
Returns the guild this command resides in, if this command is a global command then it will return <see langword="null"/>
</summary>
</member>
<member name="M:Discord.WebSocket.SocketApplicationCommand.DeleteAsync(Discord.RequestOptions)">
<inheritdoc/>
</member>
<member name="M:Discord.WebSocket.SocketApplicationCommand.ModifyAsync``1(System.Action{``0},Discord.RequestOptions)">
<summary>
Modifies the current application command.
</summary>
<param name="func">The new properties to use when modifying the command.</param>
<param name="options">The options to be used when sending the request.</param>
<returns>
A task that represents the asynchronous modification operation.
</returns>
<exception cref="T:System.InvalidOperationException">Thrown when you pass in an invalid <see cref="T:Discord.ApplicationCommandProperties"/> type.</exception>
</member>
<member name="T:Discord.WebSocket.SocketApplicationCommandChoice">
<summary>
Represents a choice for a <see cref="T:Discord.WebSocket.SocketApplicationCommandOption"/>.


+ 21
- 12
src/Discord.Net.WebSocket/DiscordSocketClient.cs View File

@@ -1946,11 +1946,14 @@ namespace Discord.WebSocket

var data = (payload as JToken).ToObject<API.Gateway.ApplicationCommandCreatedUpdatedEvent>(_serializer);

var guild = State.GetGuild(data.GuildId);
if(guild == null)
if (data.GuildId.IsSpecified)
{
await UnknownGuildAsync(type, data.GuildId).ConfigureAwait(false);
return;
var guild = State.GetGuild(data.GuildId.Value);
if (guild == null)
{
await UnknownGuildAsync(type, data.GuildId.Value).ConfigureAwait(false);
return;
}
}

var applicationCommand = SocketApplicationCommand.Create(this, data);
@@ -1964,11 +1967,14 @@ namespace Discord.WebSocket

var data = (payload as JToken).ToObject<API.Gateway.ApplicationCommandCreatedUpdatedEvent>(_serializer);

var guild = State.GetGuild(data.GuildId);
if (guild == null)
if (data.GuildId.IsSpecified)
{
await UnknownGuildAsync(type, data.GuildId).ConfigureAwait(false);
return;
var guild = State.GetGuild(data.GuildId.Value);
if (guild == null)
{
await UnknownGuildAsync(type, data.GuildId.Value).ConfigureAwait(false);
return;
}
}

var applicationCommand = SocketApplicationCommand.Create(this, data);
@@ -1982,11 +1988,14 @@ namespace Discord.WebSocket

var data = (payload as JToken).ToObject<API.Gateway.ApplicationCommandCreatedUpdatedEvent>(_serializer);

var guild = State.GetGuild(data.GuildId);
if (guild == null)
if (data.GuildId.IsSpecified)
{
await UnknownGuildAsync(type, data.GuildId).ConfigureAwait(false);
return;
var guild = State.GetGuild(data.GuildId.Value);
if (guild == null)
{
await UnknownGuildAsync(type, data.GuildId.Value).ConfigureAwait(false);
return;
}
}

var applicationCommand = SocketApplicationCommand.Create(this, data);


+ 57
- 13
src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketApplicationCommand.cs View File

@@ -10,10 +10,16 @@ using Model = Discord.API.Gateway.ApplicationCommandCreatedUpdatedEvent;
namespace Discord.WebSocket
{
/// <summary>
/// Represends a Websocket-based <see cref="IApplicationCommand"/> recieved over the gateway.
/// Represends a Websocket-based <see cref="IApplicationCommand"/>.
/// </summary>
public class SocketApplicationCommand : SocketEntity<ulong>, IApplicationCommand
{
/// <summary>
/// <see langword="true"/> if this command is a global command, otherwise <see langword="false"/>.
/// </summary>
public bool IsGlobalCommand
=> Guild == null;

/// <inheritdoc/>
public ulong ApplicationId { get; private set; }

@@ -30,8 +36,11 @@ namespace Discord.WebSocket
public bool DefaultPermission { get; private set; }

/// <summary>
/// A collection of <see cref="SocketApplicationCommandOption"/>'s recieved over the gateway.
/// A collection of <see cref="SocketApplicationCommandOption"/>'s for this command.
/// </summary>
/// <remarks>
/// If the <see cref="Type"/> is not a slash command, this field will be an empty collection.
/// </remarks>
public IReadOnlyCollection<SocketApplicationCommandOption> Options { get; private set; }

/// <inheritdoc/>
@@ -39,32 +48,31 @@ namespace Discord.WebSocket
=> SnowflakeUtils.FromSnowflake(this.Id);

/// <summary>
/// The <see cref="SocketGuild"/> where this application was created.
/// Returns the guild this command resides in, if this command is a global command then it will return <see langword="null"/>
/// </summary>
public SocketGuild Guild
=> Discord.GetGuild(this.GuildId);
private ulong GuildId { get; set; }
=> GuildId.HasValue ? Discord.GetGuild(this.GuildId.Value) : null;

private ulong? GuildId { get; set; }

internal SocketApplicationCommand(DiscordSocketClient client, ulong id)
internal SocketApplicationCommand(DiscordSocketClient client, ulong id, ulong? guildId)
: base(client, id)
{
this.GuildId = guildId;
}
internal static SocketApplicationCommand Create(DiscordSocketClient client, Model model)
{
var entity = new SocketApplicationCommand(client, model.Id);
var entity = new SocketApplicationCommand(client, model.Id, model.GuildId.ToNullable());
entity.Update(model);
return entity;
}

internal void Update(Model model)
internal void Update(API.ApplicationCommand model)
{
this.ApplicationId = model.ApplicationId;
this.Description = model.Description;
this.Name = model.Name;
this.GuildId = model.GuildId;
this.DefaultPermission = model.DefaultPermission.GetValueOrDefault(true);

this.DefaultPermission = model.DefaultPermissions.GetValueOrDefault(true);

this.Options = model.Options.IsSpecified
? model.Options.Value.Select(x => SocketApplicationCommandOption.Create(x)).ToImmutableArray()
@@ -73,8 +81,44 @@ namespace Discord.WebSocket

/// <inheritdoc/>
public Task DeleteAsync(RequestOptions options = null)
=> InteractionHelper.DeleteGuildCommand(Discord, this.GuildId, this, options);
=> InteractionHelper.DeleteUnknownApplicationCommand(Discord, this.GuildId, this, options);

/// <summary>
/// Modifies the current application command.
/// </summary>
/// <param name="func">The new properties to use when modifying the command.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous modification operation.
/// </returns>
/// <exception cref="InvalidOperationException">Thrown when you pass in an invalid <see cref="ApplicationCommandProperties"/> type.</exception>
public async Task ModifyAsync<TArg>(Action<TArg> func, RequestOptions options = null) where TArg : ApplicationCommandProperties
{
switch (typeof(TArg))
{
case Type messageCommand when messageCommand == typeof(MessageCommandProperties) && this.Type != ApplicationCommandType.Message:
case Type slashCommand when slashCommand == typeof(SlashCommandProperties) && this.Type != ApplicationCommandType.Slash:
case Type userCommand when userCommand == typeof(UserCommandProperties) && this.Type != ApplicationCommandType.User:
throw new InvalidOperationException($"Cannot modify this application command with the parameter type {nameof(TArg)}");
}

API.ApplicationCommand command = null;

if (this.IsGlobalCommand)
{
command = await InteractionHelper.ModifyGlobalCommand(Discord, this, func, options).ConfigureAwait(false);
}
else
{
command = await InteractionHelper.ModifyGuildCommand(Discord, this, this.GuildId.Value, func, options);
}

this.Update(command);
}

// IApplicationCommand
IReadOnlyCollection<IApplicationCommandOption> IApplicationCommand.Options => Options;
Task IApplicationCommand.ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options)
=> ModifyAsync(func, options);
}
}

Loading…
Cancel
Save