From afa480a8e69a1b3626b1c2257759c9c9c7b7989b Mon Sep 17 00:00:00 2001 From: drobbins329 Date: Wed, 11 Aug 2021 20:04:23 -0400 Subject: [PATCH] Implemented Context Menus Added ApplicationCommand types: Slash : 1 User: 2 Message: 3 And the appropriate CRUD methods. --- Discord.Net.sln | 20 +- src/Discord.Net.Core/Discord.Net.Core.csproj | 2 +- src/Discord.Net.Core/Discord.Net.Core.xml | 149 ++++++++ .../ApplicationCommandProperties.cs | 6 +- .../Interactions/ApplicationCommandTypes.cs | 15 + .../Interactions/IApplicationCommand.cs | 5 + .../Interactions/MessageCommandBuilder.cs | 109 ++++++ .../MessageCommandCreationProperties.cs | 30 ++ .../Interactions/SlashCommandBuilder.cs | 3 +- .../SlashCommandCreationProperties.cs | 4 + .../Interactions/UserCommandBuilder.cs | 109 ++++++ .../UserCommandCreationProperties.cs | 30 ++ .../Rest/CreateApplicationCommandParams.cs | 6 +- .../Rest/ModifyApplicationCommandParams.cs | 3 + src/Discord.Net.Rest/Discord.Net.Rest.xml | 97 +++++ src/Discord.Net.Rest/DiscordRestApiClient.cs | 134 +++++++ src/Discord.Net.Rest/DiscordRestClient.cs | 17 + .../Interactions/InteractionHelper.cs | 346 ++++++++++++++++++ .../Interactions/RestApplicationCommand.cs | 34 +- .../RestApplicationCommandType.cs | 6 +- .../Interactions/RestGlobalMessageCommand.cs | 41 +++ .../Interactions/RestGlobalUserCommand.cs | 41 +++ .../Interactions/RestGuildMessageCommand.cs | 61 +++ .../Interactions/RestGuildUserCommand.cs | 61 +++ .../Discord.Net.WebSocket.xml | 3 + .../SocketApplicationCommand.cs | 3 + 26 files changed, 1320 insertions(+), 15 deletions(-) create mode 100644 src/Discord.Net.Core/Entities/Interactions/ApplicationCommandTypes.cs create mode 100644 src/Discord.Net.Core/Entities/Interactions/MessageCommandBuilder.cs create mode 100644 src/Discord.Net.Core/Entities/Interactions/MessageCommandCreationProperties.cs create mode 100644 src/Discord.Net.Core/Entities/Interactions/UserCommandBuilder.cs create mode 100644 src/Discord.Net.Core/Entities/Interactions/UserCommandCreationProperties.cs create mode 100644 src/Discord.Net.Rest/Entities/Interactions/RestGlobalMessageCommand.cs create mode 100644 src/Discord.Net.Rest/Entities/Interactions/RestGlobalUserCommand.cs create mode 100644 src/Discord.Net.Rest/Entities/Interactions/RestGuildMessageCommand.cs create mode 100644 src/Discord.Net.Rest/Entities/Interactions/RestGuildUserCommand.cs diff --git a/Discord.Net.sln b/Discord.Net.sln index 1a32f1270..c11739aef 100644 --- a/Discord.Net.sln +++ b/Discord.Net.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28407.52 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31521.260 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Core", "src\Discord.Net.Core\Discord.Net.Core.csproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}" EndProject @@ -40,7 +40,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Analyzers.Tests EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Examples", "src\Discord.Net.Examples\Discord.Net.Examples.csproj", "{47820065-3CFB-401C-ACEA-862BD564A404}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "idn", "samples\idn\idn.csproj", "{4A03840B-9EBE-47E3-89AB-E0914DF21AFB}" +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 @@ -232,6 +234,18 @@ Global {4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|x64.Build.0 = Release|Any CPU {4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|x86.ActiveCfg = Release|Any CPU {4A03840B-9EBE-47E3-89AB-E0914DF21AFB}.Release|x86.Build.0 = Release|Any CPU + {0CC57A32-3AC7-489D-8DF5-C431925E4675}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0CC57A32-3AC7-489D-8DF5-C431925E4675}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0CC57A32-3AC7-489D-8DF5-C431925E4675}.Debug|x64.ActiveCfg = Debug|Any CPU + {0CC57A32-3AC7-489D-8DF5-C431925E4675}.Debug|x64.Build.0 = Debug|Any CPU + {0CC57A32-3AC7-489D-8DF5-C431925E4675}.Debug|x86.ActiveCfg = Debug|Any CPU + {0CC57A32-3AC7-489D-8DF5-C431925E4675}.Debug|x86.Build.0 = Debug|Any CPU + {0CC57A32-3AC7-489D-8DF5-C431925E4675}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0CC57A32-3AC7-489D-8DF5-C431925E4675}.Release|Any CPU.Build.0 = Release|Any CPU + {0CC57A32-3AC7-489D-8DF5-C431925E4675}.Release|x64.ActiveCfg = Release|Any CPU + {0CC57A32-3AC7-489D-8DF5-C431925E4675}.Release|x64.Build.0 = Release|Any CPU + {0CC57A32-3AC7-489D-8DF5-C431925E4675}.Release|x86.ActiveCfg = Release|Any CPU + {0CC57A32-3AC7-489D-8DF5-C431925E4675}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Discord.Net.Core/Discord.Net.Core.csproj b/src/Discord.Net.Core/Discord.Net.Core.csproj index f0be10059..babda86b7 100644 --- a/src/Discord.Net.Core/Discord.Net.Core.csproj +++ b/src/Discord.Net.Core/Discord.Net.Core.csproj @@ -8,7 +8,7 @@ net461;netstandard2.0;netstandard2.1 netstandard2.0;netstandard2.1 Discord.Net.Labs.Core - 3.0.0-pre + 3.3.1.0 Discord.Net.Labs.Core https://github.com/Discord-Net-Labs/Discord.Net-Labs Temporary.png diff --git a/src/Discord.Net.Core/Discord.Net.Core.xml b/src/Discord.Net.Core/Discord.Net.Core.xml index 059d9d16b..d1e4770e3 100644 --- a/src/Discord.Net.Core/Discord.Net.Core.xml +++ b/src/Discord.Net.Core/Discord.Net.Core.xml @@ -4452,6 +4452,11 @@ Gets or sets the discription of this command. + + + Gets or sets the type for this command. + + Gets or sets the options for this command. @@ -4472,6 +4477,11 @@ Gets the unique id of the parent application. + + + The type of the command + + The name of the command. @@ -5444,6 +5454,73 @@ Will render this option as selected by default. + + + A class used to build slash commands. + + + + + 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 + + + + + Build the current builder into a class. + + A that can be used to create user commands over rest. + + + + Sets the field name. + + The value to set the field name to. + + 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. @@ -5691,6 +5768,11 @@ The discription of this command. + + + Gets or sets the type for this command. + + Gets or sets the options for this command. @@ -5701,6 +5783,73 @@ Whether the command is enabled by default when the app is added to a guild. Default is + + + A class used to build slash commands. + + + + + 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 + + + + + Build the current builder into a class. + + A that can be used to create user commands over rest. + + + + Sets the field name. + + The value to set the field name to. + + 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. + + + + + The name of this command. + + + + + The discription of this command. + + + + + Gets or sets the type for this command. + + Represents a generic invite object. diff --git a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandProperties.cs b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandProperties.cs index e0d10af87..70b430bfc 100644 --- a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandProperties.cs +++ b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandProperties.cs @@ -20,7 +20,11 @@ namespace Discord /// Gets or sets the discription of this command. /// public Optional Description { get; set; } - + + /// + /// Gets or sets the type for this command. + /// + public Optional Type { get; set; } /// /// Gets or sets the options for this command. diff --git a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandTypes.cs b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandTypes.cs new file mode 100644 index 000000000..23b00f2a2 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandTypes.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Discord +{ + public enum ApplicationCommandType : byte + { + Slash = 1, + User = 2, + Message = 3 + } +} diff --git a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs index eb61c539f..ab4b3eac0 100644 --- a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs +++ b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs @@ -16,6 +16,11 @@ namespace Discord /// ulong ApplicationId { get; } + /// + /// The type of the command + /// + ApplicationCommandType Type { get; } + /// /// The name of the command. /// diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageCommandBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageCommandBuilder.cs new file mode 100644 index 000000000..792d7d19f --- /dev/null +++ b/src/Discord.Net.Core/Entities/Interactions/MessageCommandBuilder.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Discord +{ + /// + /// A class used to build slash commands. + /// + public class MessageCommandBuilder + { + /// + /// 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. + /// + public string Name + { + get + { + return _name; + } + set + { + Preconditions.NotNullOrEmpty(value, nameof(Name)); + Preconditions.AtLeast(value.Length, 3, nameof(Name)); + Preconditions.AtMost(value.Length, MaxNameLength, nameof(Name)); + + // Discord updated the docs, this regex prevents special characters like @!$%(... etc, + // https://discord.com/developers/docs/interactions/slash-commands#applicationcommand + if (!Regex.IsMatch(value, @"^[\w -]{3,32}$")) + throw new ArgumentException("Command name cannot contain any special characters or whitespaces!"); + + _name = value; + } + } + + /// + /// 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. + /// + /// A that can be used to create user commands over rest. + public MessageCommandCreationProperties Build() + { + MessageCommandCreationProperties props = new MessageCommandCreationProperties() + { + Name = this.Name, + Description = this.Description, + Type=ApplicationCommandType.Message + }; + + return props; + + } + + /// + /// Sets the field name. + /// + /// The value to set the field name to. + /// + /// The current builder. + /// + public MessageCommandBuilder WithName(string name) + { + 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/MessageCommandCreationProperties.cs b/src/Discord.Net.Core/Entities/Interactions/MessageCommandCreationProperties.cs new file mode 100644 index 000000000..7c7dac593 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Interactions/MessageCommandCreationProperties.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Discord +{ + /// + /// A class used to create Message commands. + /// + public class MessageCommandCreationProperties + { + /// + /// 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. + /// + public ApplicationCommandType Type { get; set; } + } +} diff --git a/src/Discord.Net.Core/Entities/Interactions/SlashCommandBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/SlashCommandBuilder.cs index e0afde50c..933f511e1 100644 --- a/src/Discord.Net.Core/Entities/Interactions/SlashCommandBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/SlashCommandBuilder.cs @@ -102,7 +102,8 @@ namespace Discord { Name = this.Name, Description = this.Description, - DefaultPermission = this.DefaultPermission + DefaultPermission = this.DefaultPermission, + Type = ApplicationCommandType.Slash }; if (this.Options != null && this.Options.Any()) diff --git a/src/Discord.Net.Core/Entities/Interactions/SlashCommandCreationProperties.cs b/src/Discord.Net.Core/Entities/Interactions/SlashCommandCreationProperties.cs index 7f4a3a62d..3021d7a2c 100644 --- a/src/Discord.Net.Core/Entities/Interactions/SlashCommandCreationProperties.cs +++ b/src/Discord.Net.Core/Entities/Interactions/SlashCommandCreationProperties.cs @@ -21,6 +21,10 @@ namespace Discord /// public string Description { get; set; } + /// + /// Gets or sets the type for this command. + /// + public ApplicationCommandType Type { get; set; } /// /// Gets or sets the options for this command. diff --git a/src/Discord.Net.Core/Entities/Interactions/UserCommandBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/UserCommandBuilder.cs new file mode 100644 index 000000000..0dc6526ba --- /dev/null +++ b/src/Discord.Net.Core/Entities/Interactions/UserCommandBuilder.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Discord +{ + /// + /// A class used to build slash commands. + /// + public class UserCommandBuilder + { + /// + /// 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. + /// + public string Name + { + get + { + return _name; + } + set + { + Preconditions.NotNullOrEmpty(value, nameof(Name)); + Preconditions.AtLeast(value.Length, 3, nameof(Name)); + Preconditions.AtMost(value.Length, MaxNameLength, nameof(Name)); + + // Discord updated the docs, this regex prevents special characters like @!$%(... etc, + // https://discord.com/developers/docs/interactions/slash-commands#applicationcommand + if (!Regex.IsMatch(value, @"^[\w -]{3,32}$")) + throw new ArgumentException("Command name cannot contain any special characters or whitespaces!"); + + _name = value; + } + } + + /// + /// 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. + /// + /// A that can be used to create user commands over rest. + public UserCommandCreationProperties Build() + { + UserCommandCreationProperties props = new UserCommandCreationProperties() + { + Name = this.Name, + Description = this.Description, + Type=ApplicationCommandType.User + }; + + return props; + + } + + /// + /// Sets the field name. + /// + /// The value to set the field name to. + /// + /// The current builder. + /// + public UserCommandBuilder WithName(string name) + { + 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/Interactions/UserCommandCreationProperties.cs b/src/Discord.Net.Core/Entities/Interactions/UserCommandCreationProperties.cs new file mode 100644 index 000000000..323b2ce1d --- /dev/null +++ b/src/Discord.Net.Core/Entities/Interactions/UserCommandCreationProperties.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Discord +{ + /// + /// A class used to create User commands. + /// + public class UserCommandCreationProperties + { + /// + /// 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. + /// + public ApplicationCommandType Type { get; set; } + } +} diff --git a/src/Discord.Net.Rest/API/Rest/CreateApplicationCommandParams.cs b/src/Discord.Net.Rest/API/Rest/CreateApplicationCommandParams.cs index 2e66245d7..ff72429a3 100644 --- a/src/Discord.Net.Rest/API/Rest/CreateApplicationCommandParams.cs +++ b/src/Discord.Net.Rest/API/Rest/CreateApplicationCommandParams.cs @@ -13,6 +13,9 @@ namespace Discord.API.Rest [JsonProperty("name")] public string Name { get; set; } + [JsonProperty("type")] + public ApplicationCommandType Type { get; set; } + [JsonProperty("description")] public string Description { get; set; } @@ -23,11 +26,12 @@ namespace Discord.API.Rest public Optional DefaultPermission { get; set; } public CreateApplicationCommandParams() { } - public CreateApplicationCommandParams(string name, string description, ApplicationCommandOption[] options = null) + public CreateApplicationCommandParams(string name, string description, ApplicationCommandType type, ApplicationCommandOption[] options = null) { this.Name = name; this.Description = description; this.Options = Optional.Create(options); + this.Type = type; } } } diff --git a/src/Discord.Net.Rest/API/Rest/ModifyApplicationCommandParams.cs b/src/Discord.Net.Rest/API/Rest/ModifyApplicationCommandParams.cs index 2ed9466c0..29a6ff796 100644 --- a/src/Discord.Net.Rest/API/Rest/ModifyApplicationCommandParams.cs +++ b/src/Discord.Net.Rest/API/Rest/ModifyApplicationCommandParams.cs @@ -15,6 +15,9 @@ namespace Discord.API.Rest [JsonProperty("description")] public Optional Description { get; set; } + [JsonProperty("type")] + public Optional Type { get; set; } + [JsonProperty("options")] public Optional Options { get; set; } diff --git a/src/Discord.Net.Rest/Discord.Net.Rest.xml b/src/Discord.Net.Rest/Discord.Net.Rest.xml index 920e0bf60..c6c81ee75 100644 --- a/src/Discord.Net.Rest/Discord.Net.Rest.xml +++ b/src/Discord.Net.Rest/Discord.Net.Rest.xml @@ -3732,6 +3732,9 @@ + + + @@ -3831,6 +3834,32 @@ The modified command. + + + + + + Modifies this . + + The delegate containing the properties to modify the command with. + The options to be used when sending the request. + + The modified command. + + + + + + + + Modifies this . + + The delegate containing the properties to modify the command with. + The options to be used when sending the request. + + The modified command. + + Represents a Rest-based guild command. @@ -3886,6 +3915,74 @@ . + + + Represents a Rest-based guild command. + + + + + The guild Id where this command originates. + + + + + + + + Modifies this . + + The delegate containing the properties to modify the command with. + The options to be used when sending the request. + + The modified command + + + + + Gets the guild that this slash command resides in. + + if you want the approximate member and presence counts for the guild, otherwise . + The options to be used when sending the request. + + A task that represents the asynchronous get operation. The task result contains a + . + + + + + Represents a Rest-based guild command. + + + + + The guild Id where this command originates. + + + + + + + + Modifies this . + + The delegate containing the properties to modify the command with. + The options to be used when sending the request. + + The modified command + + + + + Gets the guild that this slash command resides in. + + if you want the approximate member and presence counts for the guild, otherwise . + The options to be used when sending the request. + + A task that represents the asynchronous get operation. The task result contains a + . + + diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index 3e9ed4393..350a156c7 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -235,6 +235,7 @@ namespace Discord.API options.BucketId = bucketId; string json = payload != null ? SerializeJson(payload) : null; + Console.WriteLine($"Sending JSON....\n{json}"); var request = new JsonRestRequest(RestClient, method, endpoint, json, options); return DeserializeJson(await SendInternalAsync(method, endpoint, request).ConfigureAwait(false)); } @@ -1082,6 +1083,18 @@ namespace Discord.API return await TrySendApplicationCommand(SendJsonAsync("PATCH", () => $"applications/{this.CurrentUserId}/commands/{commandId}", command, new BucketIds(), options: options)).ConfigureAwait(false); } + public async Task ModifyGlobalApplicationUserCommandAsync(ModifyApplicationCommandParams command, ulong commandId, RequestOptions options = null) + { + options = RequestOptions.CreateOrClone(options); + + return await TrySendApplicationCommand(SendJsonAsync("PATCH", () => $"applications/{this.CurrentUserId}/commands/{commandId}", command, new BucketIds(), options: options)).ConfigureAwait(false); + } + public async Task ModifyGlobalApplicationMessageCommandAsync(ModifyApplicationCommandParams command, ulong commandId, RequestOptions options = null) + { + options = RequestOptions.CreateOrClone(options); + + return await TrySendApplicationCommand(SendJsonAsync("PATCH", () => $"applications/{this.CurrentUserId}/commands/{commandId}", command, new BucketIds(), options: options)).ConfigureAwait(false); + } public async Task DeleteGlobalApplicationCommandAsync(ulong commandId, RequestOptions options = null) { options = RequestOptions.CreateOrClone(options); @@ -1095,6 +1108,46 @@ namespace Discord.API return await TrySendApplicationCommand(SendJsonAsync("PUT", () => $"applications/{this.CurrentUserId}/commands", commands, new BucketIds(), options: options)).ConfigureAwait(false); } + public async Task CreateGlobalApplicationUserCommandAsync(CreateApplicationCommandParams command, RequestOptions options = null) + { + 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); + } + public async Task CreateGlobalApplicationMessageCommandAsync(CreateApplicationCommandParams command, RequestOptions options = null) + { + 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); + } + + public async Task BulkOverwriteGlobalApplicationUserCommands(CreateApplicationCommandParams[] commands, RequestOptions options = null) + { + options = RequestOptions.CreateOrClone(options); + + return await TrySendApplicationCommand(SendJsonAsync("PUT", () => $"applications/{this.CurrentUserId}/commands", commands, new BucketIds(), options: options)).ConfigureAwait(false); + } + + public async Task BulkOverwriteGlobalApplicationMessageCommands(CreateApplicationCommandParams[] commands, RequestOptions options = null) + { + options = RequestOptions.CreateOrClone(options); + + return await TrySendApplicationCommand(SendJsonAsync("PUT", () => $"applications/{this.CurrentUserId}/commands", commands, new BucketIds(), options: options)).ConfigureAwait(false); + } public async Task GetGuildApplicationCommandsAsync(ulong guildId, RequestOptions options = null) { @@ -1163,6 +1216,87 @@ namespace Discord.API return await TrySendApplicationCommand(SendJsonAsync("PUT", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", commands, bucket, options: options)).ConfigureAwait(false); } + public async Task CreateGuildApplicationUserCommandAsync(CreateApplicationCommandParams command, ulong guildId, RequestOptions options = null) + { + options = RequestOptions.CreateOrClone(options); + + 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; + } + } + public async Task BulkOverwriteGuildApplicationUserCommands(ulong guildId, CreateApplicationCommandParams[] commands, RequestOptions options = null) + { + options = RequestOptions.CreateOrClone(options); + + var bucket = new BucketIds(guildId: guildId); + + return await TrySendApplicationCommand(SendJsonAsync("PUT", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", commands, bucket, options: options)).ConfigureAwait(false); + } + + public async Task CreateGuildApplicationMessageCommandAsync(CreateApplicationCommandParams command, ulong guildId, RequestOptions options = null) + { + options = RequestOptions.CreateOrClone(options); + + 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) + { + 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; + } + } + + public async Task BulkOverwriteGuildApplicationMessageCommands(ulong guildId, CreateApplicationCommandParams[] commands, RequestOptions options = null) + { + options = RequestOptions.CreateOrClone(options); + + var bucket = new BucketIds(guildId: guildId); + + return await TrySendApplicationCommand(SendJsonAsync("PUT", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", commands, bucket, options: options)).ConfigureAwait(false); + } + //Interaction Responses public async Task CreateInteractionResponse(InteractionResponse response, ulong interactionId, string interactionToken, RequestOptions options = null) { diff --git a/src/Discord.Net.Rest/DiscordRestClient.cs b/src/Discord.Net.Rest/DiscordRestClient.cs index a8849525e..cb28d19b6 100644 --- a/src/Discord.Net.Rest/DiscordRestClient.cs +++ b/src/Discord.Net.Rest/DiscordRestClient.cs @@ -1,3 +1,4 @@ +//using Discord.Rest.Entities.Interactions; using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -111,10 +112,26 @@ 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) + => InteractionHelper.CreateGlobalUserCommand(this, properties, options); + public Task CreateGlobalUserCommand(Action func, RequestOptions options = null) + => InteractionHelper.CreateGlobalUserCommand(this, func, options); + public Task CreateGlobalMessageCommand(MessageCommandCreationProperties properties, RequestOptions options = null) + => InteractionHelper.CreateGlobalMessageCommand(this, properties, options); + 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) + => InteractionHelper.CreateGuildUserCommand(this, guildId, properties, options); + 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) + => InteractionHelper.CreateGuildMessageCommand(this, guildId, properties, options); + 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); public Task> GetGuildApplicationCommands(ulong guildId, RequestOptions options = null) diff --git a/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs b/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs index e4df0d75e..d5006a6a9 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs @@ -1,6 +1,7 @@ using Discord.API; using Discord.API.Rest; using Discord.Net; +//using Discord.Rest.Entities.Interactions; using System; using System.Collections.Generic; using System.Linq; @@ -63,6 +64,7 @@ namespace Discord.Rest { 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.Unspecified, @@ -94,6 +96,7 @@ namespace Discord.Rest { 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.Unspecified, @@ -129,6 +132,7 @@ namespace Discord.Rest { 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.Unspecified, @@ -173,6 +177,7 @@ namespace Discord.Rest { 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.Unspecified, @@ -195,6 +200,174 @@ namespace Discord.Rest await client.ApiClient.DeleteGlobalApplicationCommandAsync(command.Id, options).ConfigureAwait(false); } + public static async Task CreateGlobalUserCommand(BaseDiscordClient client, Action func, RequestOptions options = null) + { + var args = new UserCommandCreationProperties(); + func(args); + return await CreateGlobalUserCommand(client, args, options).ConfigureAwait(false); + } + + public static async Task CreateGlobalUserCommand(BaseDiscordClient client, UserCommandCreationProperties 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 + }; + + var cmd = await client.ApiClient.CreateGlobalApplicationUserCommandAsync(model, options).ConfigureAwait(false); + return RestGlobalUserCommand.Create(client, cmd); + } + + public static async Task CreateGlobalMessageCommand(BaseDiscordClient client, Action func, RequestOptions options = null) + { + var args = new MessageCommandCreationProperties(); + func(args); + return await CreateGlobalMessageCommand(client, args, options).ConfigureAwait(false); + } + + public static async Task CreateGlobalMessageCommand(BaseDiscordClient client, MessageCommandCreationProperties 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 + }; + + var cmd = await client.ApiClient.CreateGlobalApplicationMessageCommandAsync(model, options).ConfigureAwait(false); + return RestGlobalMessageCommand.Create(client, cmd); + } + + public static async Task> BulkOverwriteGlobalUserCommands(BaseDiscordClient client, UserCommandCreationProperties[] args, RequestOptions options = null) + { + Preconditions.NotNull(args, nameof(args)); + + List models = new List(); + + 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 + }; + + 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 ModifyGlobalUserCommand(BaseDiscordClient client, RestGlobalUserCommand command, + Action 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> BulkOverwriteGlobalMessageCommands(BaseDiscordClient client, MessageCommandCreationProperties[] args, RequestOptions options = null) + { + Preconditions.NotNull(args, nameof(args)); + + List models = new List(); + + 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 + }; + + models.Add(model); + } + + var apiModels = await client.ApiClient.BulkOverwriteGlobalApplicationMessageCommands(models.ToArray(), options); + + return apiModels.Select(x => RestGlobalMessageCommand.Create(client, x)).ToArray(); + } + public static async Task ModifyGlobalMessageCommand(BaseDiscordClient client, RestGlobalMessageCommand command, + Action 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.ModifyGlobalApplicationMessageCommandAsync(model, command.Id, options).ConfigureAwait(false); + command.Update(msg); + return command; + } + + public static async Task DeleteGlobalMessageCommand(BaseDiscordClient client, RestGlobalMessageCommand 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); + } + // Guild Commands public static async Task CreateGuildCommand(BaseDiscordClient client, ulong guildId, Action func, RequestOptions options = null) @@ -231,6 +404,7 @@ namespace Discord.Rest { 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.Unspecified, @@ -269,6 +443,7 @@ namespace Discord.Rest { 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.Unspecified, @@ -290,6 +465,177 @@ 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) + { + var args = new UserCommandCreationProperties(); + 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) + { + Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name)); + Preconditions.Equals(arg.Description, ""); + + var model = new CreateApplicationCommandParams() + { + Name = arg.Name, + Description = arg.Description, + Type = arg.Type + }; + + var cmd = await client.ApiClient.CreateGuildApplicationUserCommandAsync(model, guildId, options).ConfigureAwait(false); + return RestGuildUserCommand.Create(client, cmd, guildId); + } + + public static async Task CreateGuildMessageCommand(BaseDiscordClient client, ulong guildId, Action func, RequestOptions options = null) + { + var args = new MessageCommandCreationProperties(); + 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) + { + Preconditions.NotNullOrEmpty(arg.Name, nameof(arg.Name)); + Preconditions.Equals(arg.Description, ""); + + var model = new CreateApplicationCommandParams() + { + Name = arg.Name, + Description = arg.Description, + Type = arg.Type + }; + + var cmd = await client.ApiClient.CreateGuildApplicationMessageCommandAsync(model, guildId, options).ConfigureAwait(false); + return RestGuildMessageCommand.Create(client, cmd, guildId); + } + + public static async Task> BulkOverwriteGuildUserCommands(BaseDiscordClient client, ulong guildId, UserCommandCreationProperties[] args, RequestOptions options = null) + { + Preconditions.NotNull(args, nameof(args)); + + List models = new List(); + + 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 + }; + + 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 ModifyGuildUserCommand(BaseDiscordClient client, RestGuildUserCommand command, + Action 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, + Type=args.Type + }; + + var msg = await client.ApiClient.ModifyGuildApplicationUserCommandAsync(model, command.GuildId, command.Id, options).ConfigureAwait(false); + command.Update(msg); + return command; + } + + public static async Task DeleteGuildUserCommand(BaseDiscordClient client, ulong guildId, RestGuildUserCommand 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> BulkOverwriteGuildMessageCommands(BaseDiscordClient client, ulong guildId, MessageCommandCreationProperties[] args, RequestOptions options = null) + { + Preconditions.NotNull(args, nameof(args)); + + List models = new List(); + + 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 + }; + + 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 ModifyGuildMessageCommand(BaseDiscordClient client, RestGuildMessageCommand command, + Action 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, + 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); + } + + public static async Task ModifyFollowupMessage(BaseDiscordClient client, RestFollowupMessage message, Action func, RequestOptions options = null) { diff --git a/src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommand.cs b/src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommand.cs index e1a854187..2744c7967 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommand.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommand.cs @@ -16,6 +16,9 @@ namespace Discord.Rest /// public ulong ApplicationId { get; private set; } + /// + public ApplicationCommandType Type { get; private set; } + /// public string Name { get; private set; } @@ -47,13 +50,30 @@ namespace Discord.Rest internal static RestApplicationCommand Create(BaseDiscordClient client, Model model, RestApplicationCommandType type, ulong guildId = 0) { - if (type == RestApplicationCommandType.GlobalCommand) - return RestGlobalCommand.Create(client, model); - - if (type == RestApplicationCommandType.GuildCommand) - return RestGuildCommand.Create(client, model, guildId); - - return null; + switch (type) + { + 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; + } } internal virtual void Update(Model model) diff --git a/src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandType.cs b/src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandType.cs index 96ba07053..cf2fb1110 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandType.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandType.cs @@ -15,10 +15,14 @@ namespace Discord.Rest /// Specifies that this command is a Global command. /// GlobalCommand, + GlobalUserCommand, + GlobalMessageCommand, /// /// Specifies that this command is a Guild specific command. /// - GuildCommand + GuildCommand, + GuildUserCommand, + GuildMessageCommand } } diff --git a/src/Discord.Net.Rest/Entities/Interactions/RestGlobalMessageCommand.cs b/src/Discord.Net.Rest/Entities/Interactions/RestGlobalMessageCommand.cs new file mode 100644 index 000000000..2c0ed222c --- /dev/null +++ b/src/Discord.Net.Rest/Entities/Interactions/RestGlobalMessageCommand.cs @@ -0,0 +1,41 @@ +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; + } + + /// + public override async Task DeleteAsync(RequestOptions options = null) + => await InteractionHelper.DeleteGlobalMessageCommand(Discord, this).ConfigureAwait(false); + + /// + /// Modifies this . + /// + /// The delegate containing the properties to modify the command with. + /// The options to be used when sending the request. + /// + /// The modified command. + /// + public async Task ModifyAsync(Action func, RequestOptions options = null) + => await InteractionHelper.ModifyGlobalMessageCommand(Discord, this, func, options).ConfigureAwait(false); + } +} diff --git a/src/Discord.Net.Rest/Entities/Interactions/RestGlobalUserCommand.cs b/src/Discord.Net.Rest/Entities/Interactions/RestGlobalUserCommand.cs new file mode 100644 index 000000000..981686379 --- /dev/null +++ b/src/Discord.Net.Rest/Entities/Interactions/RestGlobalUserCommand.cs @@ -0,0 +1,41 @@ +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; + } + + /// + public override async Task DeleteAsync(RequestOptions options = null) + => await InteractionHelper.DeleteGlobalUserCommand(Discord, this).ConfigureAwait(false); + + /// + /// Modifies this . + /// + /// The delegate containing the properties to modify the command with. + /// The options to be used when sending the request. + /// + /// The modified command. + /// + public async Task ModifyAsync(Action func, RequestOptions options = null) + => await InteractionHelper.ModifyGlobalUserCommand(Discord, this, func, options).ConfigureAwait(false); + } +} diff --git a/src/Discord.Net.Rest/Entities/Interactions/RestGuildMessageCommand.cs b/src/Discord.Net.Rest/Entities/Interactions/RestGuildMessageCommand.cs new file mode 100644 index 000000000..e057b2fe3 --- /dev/null +++ b/src/Discord.Net.Rest/Entities/Interactions/RestGuildMessageCommand.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Model = Discord.API.ApplicationCommand; + +namespace Discord.Rest +{ + /// + /// Represents a Rest-based guild command. + /// + public class RestGuildMessageCommand : RestApplicationCommand + { + /// + /// The guild Id where this command originates. + /// + 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; + } + + /// + public override async Task DeleteAsync(RequestOptions options = null) + => await InteractionHelper.DeleteGuildMessageCommand(Discord, GuildId, this).ConfigureAwait(false); + + /// + /// Modifies this . + /// + /// The delegate containing the properties to modify the command with. + /// The options to be used when sending the request. + /// + /// The modified command + /// + public async Task ModifyAsync(Action func, RequestOptions options = null) + => await InteractionHelper.ModifyGuildMessageCommand(Discord, this, func, options).ConfigureAwait(false); + + /// + /// Gets the guild that this slash command resides in. + /// + /// if you want the approximate member and presence counts for the guild, otherwise . + /// The options to be used when sending the request. + /// + /// A task that represents the asynchronous get operation. The task result contains a + /// . + /// + public Task GetGuild(bool withCounts = false, RequestOptions options = null) + => ClientHelper.GetGuildAsync(this.Discord, this.GuildId, withCounts, options); + } +} diff --git a/src/Discord.Net.Rest/Entities/Interactions/RestGuildUserCommand.cs b/src/Discord.Net.Rest/Entities/Interactions/RestGuildUserCommand.cs new file mode 100644 index 000000000..02dc173db --- /dev/null +++ b/src/Discord.Net.Rest/Entities/Interactions/RestGuildUserCommand.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Model = Discord.API.ApplicationCommand; + +namespace Discord.Rest +{ + /// + /// Represents a Rest-based guild command. + /// + public class RestGuildUserCommand : RestApplicationCommand + { + /// + /// The guild Id where this command originates. + /// + 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; + } + + /// + public override async Task DeleteAsync(RequestOptions options = null) + => await InteractionHelper.DeleteGuildUserCommand(Discord, GuildId, this).ConfigureAwait(false); + + /// + /// Modifies this . + /// + /// The delegate containing the properties to modify the command with. + /// The options to be used when sending the request. + /// + /// The modified command + /// + public async Task ModifyAsync(Action func, RequestOptions options = null) + => await InteractionHelper.ModifyGuildUserCommand(Discord, this, func, options).ConfigureAwait(false); + + /// + /// Gets the guild that this slash command resides in. + /// + /// if you want the approximate member and presence counts for the guild, otherwise . + /// The options to be used when sending the request. + /// + /// A task that represents the asynchronous get operation. The task result contains a + /// . + /// + public Task GetGuild(bool withCounts = false, RequestOptions options = null) + => ClientHelper.GetGuildAsync(this.Discord, this.GuildId, withCounts, options); + } +} diff --git a/src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml b/src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml index d22c00429..bec25d285 100644 --- a/src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml +++ b/src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml @@ -3668,6 +3668,9 @@ + + + diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketApplicationCommand.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketApplicationCommand.cs index 81decb4be..9f53af562 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketApplicationCommand.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketApplicationCommand.cs @@ -20,6 +20,9 @@ namespace Discord.WebSocket /// public string Name { get; private set; } + /// + public ApplicationCommandType Type { get; private set; } + /// public string Description { get; private set; }