Browse Source

Finished command permissions as well as bug fixes

pull/1923/head
quin lynch 4 years ago
parent
commit
8e507915e3
26 changed files with 574 additions and 190 deletions
  1. +25
    -13
      src/Discord.Net.Core/Discord.Net.Core.xml
  2. +2
    -2
      src/Discord.Net.Core/Entities/Guilds/PermissionTarget.cs
  3. +5
    -5
      src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs
  4. +18
    -0
      src/Discord.Net.Core/Entities/Interactions/SlashCommandBuilder.cs
  5. +12
    -12
      src/Discord.Net.Core/Entities/Permissions/ApplicationCommandPermissions.cs
  6. +6
    -5
      src/Discord.Net.Core/Entities/Permissions/GuildApplicationCommandPermissions.cs
  7. +2
    -0
      src/Discord.Net.Rest/API/Common/ApplicationCommand.cs
  8. +1
    -1
      src/Discord.Net.Rest/API/Common/ApplicationCommandPermissions.cs
  9. +4
    -4
      src/Discord.Net.Rest/API/Common/GuildApplicationCommandPermissions.cs
  10. +1
    -1
      src/Discord.Net.Rest/API/Rest/ModifyGuildApplicationCommandPermissions.cs
  11. +2
    -1
      src/Discord.Net.Rest/ClientHelper.cs
  12. +1
    -1
      src/Discord.Net.Rest/Discord.Net.Rest.csproj
  13. +59
    -0
      src/Discord.Net.Rest/Discord.Net.Rest.xml
  14. +58
    -93
      src/Discord.Net.Rest/DiscordRestApiClient.cs
  15. +9
    -0
      src/Discord.Net.Rest/DiscordRestClient.cs
  16. +14
    -0
      src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
  17. +24
    -1
      src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
  18. +202
    -35
      src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs
  19. +8
    -1
      src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommand.cs
  20. +35
    -3
      src/Discord.Net.Rest/Entities/Interactions/RestGuildCommand.cs
  21. +3
    -0
      src/Discord.Net.WebSocket/API/Gateway/ApplicationCommandCreatedUpdatedEvent.cs
  22. +27
    -0
      src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml
  23. +24
    -0
      src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
  24. +10
    -1
      src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketApplicationCommand.cs
  25. +14
    -3
      src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandData.cs
  26. +8
    -8
      src/Discord.Net/Discord.Net.nuspec

+ 25
- 13
src/Discord.Net.Core/Discord.Net.Core.xml View File

@@ -3967,11 +3967,6 @@
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. see <see href="https://discord.com/developers/docs/interactions/slash-commands#applicationcommand"/>
</summary> </summary>
</member> </member>
<member name="P:Discord.IApplicationCommand.Id">
<summary>
Gets the unique id of the command.
</summary>
</member>
<member name="P:Discord.IApplicationCommand.ApplicationId"> <member name="P:Discord.IApplicationCommand.ApplicationId">
<summary> <summary>
Gets the unique id of the parent application. Gets the unique id of the parent application.
@@ -3987,6 +3982,11 @@
The description of the command. The description of the command.
</summary> </summary>
</member> </member>
<member name="P:Discord.IApplicationCommand.DefaultPermission">
<summary>
Whether the command is enabled by default when the app is added to a guild.
</summary>
</member>
<member name="P:Discord.IApplicationCommand.Options"> <member name="P:Discord.IApplicationCommand.Options">
<summary> <summary>
If the option is a subcommand or subcommand group type, this nested options will be the parameters. If the option is a subcommand or subcommand group type, this nested options will be the parameters.
@@ -4886,6 +4886,11 @@
Gets or sets the options for this command. Gets or sets the options for this command.
</summary> </summary>
</member> </member>
<member name="P:Discord.SlashCommandBuilder.DefaultPermission">
<summary>
Whether the command is enabled by default when the app is added to a guild
</summary>
</member>
<member name="M:Discord.SlashCommandBuilder.Build"> <member name="M:Discord.SlashCommandBuilder.Build">
<summary> <summary>
Build the current builder into a <see cref="T:Discord.SlashCommandCreationProperties"/> class. Build the current builder into a <see cref="T:Discord.SlashCommandCreationProperties"/> class.
@@ -4908,6 +4913,13 @@
<param name="description">The description of this command.</param> <param name="description">The description of this command.</param>
<returns>The current builder.</returns> <returns>The current builder.</returns>
</member> </member>
<member name="M:Discord.SlashCommandBuilder.WithDefaultPermission(System.Boolean)">
<summary>
Sets the default permission of the current command.
</summary>
<param name="value">The default permission value to set.</param>
<returns>The current builder.</returns>
</member>
<member name="M:Discord.SlashCommandBuilder.AddOption(System.String,Discord.ApplicationCommandOptionType,System.String,System.Boolean,System.Boolean,System.Collections.Generic.List{Discord.SlashCommandOptionBuilder},Discord.ApplicationCommandOptionChoiceProperties[])"> <member name="M:Discord.SlashCommandBuilder.AddOption(System.String,Discord.ApplicationCommandOptionType,System.String,System.Boolean,System.Boolean,System.Collections.Generic.List{Discord.SlashCommandOptionBuilder},Discord.ApplicationCommandOptionChoiceProperties[])">
<summary> <summary>
Adds an option to the current slash command. Adds an option to the current slash command.
@@ -7243,17 +7255,17 @@
Application command permissions allow you to enable or disable commands for specific users or roles within a guild. Application command permissions allow you to enable or disable commands for specific users or roles within a guild.
</summary> </summary>
</member> </member>
<member name="P:Discord.ApplicationCommandPermission.Id">
<member name="P:Discord.ApplicationCommandPermission.TargetId">
<summary> <summary>
The id of the role or user. The id of the role or user.
</summary> </summary>
</member> </member>
<member name="P:Discord.ApplicationCommandPermission.Type">
<member name="P:Discord.ApplicationCommandPermission.TargetType">
<summary> <summary>
The target of this permission. The target of this permission.
</summary> </summary>
</member> </member>
<member name="P:Discord.ApplicationCommandPermission.Value">
<member name="P:Discord.ApplicationCommandPermission.Permission">
<summary> <summary>
<see langword="true"/> to allow, otherwise <see langword="false"/>. <see langword="true"/> to allow, otherwise <see langword="false"/>.
</summary> </summary>
@@ -7525,27 +7537,27 @@
<member name="M:Discord.ChannelPermissions.Modify(System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean})"> <member name="M:Discord.ChannelPermissions.Modify(System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean},System.Nullable{System.Boolean})">
<summary> Creates a new <see cref="T:Discord.ChannelPermissions"/> from this one, changing the provided non-null permissions. </summary> <summary> Creates a new <see cref="T:Discord.ChannelPermissions"/> from this one, changing the provided non-null permissions. </summary>
</member> </member>
<member name="T:Discord.GuildApplicationCommandPermissions">
<member name="T:Discord.GuildApplicationCommandPermission">
<summary> <summary>
Returned when fetching the permissions for a command in a guild. Returned when fetching the permissions for a command in a guild.
</summary> </summary>
</member> </member>
<member name="P:Discord.GuildApplicationCommandPermissions.Id">
<member name="P:Discord.GuildApplicationCommandPermission.CommandId">
<summary> <summary>
The id of the command. The id of the command.
</summary> </summary>
</member> </member>
<member name="P:Discord.GuildApplicationCommandPermissions.ApplicationId">
<member name="P:Discord.GuildApplicationCommandPermission.ApplicationId">
<summary> <summary>
The id of the application the command belongs to. The id of the application the command belongs to.
</summary> </summary>
</member> </member>
<member name="P:Discord.GuildApplicationCommandPermissions.GuildId">
<member name="P:Discord.GuildApplicationCommandPermission.GuildId">
<summary> <summary>
The id of the guild. The id of the guild.
</summary> </summary>
</member> </member>
<member name="P:Discord.GuildApplicationCommandPermissions.Permissions">
<member name="P:Discord.GuildApplicationCommandPermission.Permissions">
<summary> <summary>
The permissions for the command in the guild. The permissions for the command in the guild.
</summary> </summary>


+ 2
- 2
src/Discord.Net.Core/Entities/Guilds/PermissionTarget.cs View File

@@ -8,10 +8,10 @@ namespace Discord
/// <summary> /// <summary>
/// The target of the permission is a role. /// The target of the permission is a role.
/// </summary> /// </summary>
Role = 0,
Role = 1,
/// <summary> /// <summary>
/// The target of the permission is a user. /// The target of the permission is a user.
/// </summary> /// </summary>
User = 1,
User = 2,
} }
} }

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

@@ -11,11 +11,6 @@ namespace Discord
/// </summary> /// </summary>
public interface IApplicationCommand : ISnowflakeEntity public interface IApplicationCommand : ISnowflakeEntity
{ {
/// <summary>
/// Gets the unique id of the command.
/// </summary>
ulong Id { get; }

/// <summary> /// <summary>
/// Gets the unique id of the parent application. /// Gets the unique id of the parent application.
/// </summary> /// </summary>
@@ -31,6 +26,11 @@ namespace Discord
/// </summary> /// </summary>
string Description { get; } string Description { get; }


/// <summary>
/// Whether the command is enabled by default when the app is added to a guild.
/// </summary>
bool DefaultPermission { get; }

/// <summary> /// <summary>
/// If the option is a subcommand or subcommand group type, this nested options will be the parameters. /// If the option is a subcommand or subcommand group type, this nested options will be the parameters.
/// </summary> /// </summary>


+ 18
- 0
src/Discord.Net.Core/Entities/Interactions/SlashCommandBuilder.cs View File

@@ -82,6 +82,12 @@ namespace Discord
_options = value; _options = value;
} }
} }

/// <summary>
/// Whether the command is enabled by default when the app is added to a guild
/// </summary>
public bool DefaultPermission { get; set; } = true;

private string _name { get; set; } private string _name { get; set; }
private string _description { get; set; } private string _description { get; set; }
private List<SlashCommandOptionBuilder> _options { get; set; } private List<SlashCommandOptionBuilder> _options { get; set; }
@@ -96,6 +102,7 @@ namespace Discord
{ {
Name = this.Name, Name = this.Name,
Description = this.Description, Description = this.Description,
DefaultPermission = this.DefaultPermission
}; };


if (this.Options != null && this.Options.Any()) if (this.Options != null && this.Options.Any())
@@ -135,6 +142,17 @@ namespace Discord
return this; return this;
} }


/// <summary>
/// Sets the default permission of the current command.
/// </summary>
/// <param name="value">The default permission value to set.</param>
/// <returns>The current builder.</returns>
public SlashCommandBuilder WithDefaultPermission(bool value)
{
this.DefaultPermission = value;
return this;
}

/// <summary> /// <summary>
/// Adds an option to the current slash command. /// Adds an option to the current slash command.
/// </summary> /// </summary>


+ 12
- 12
src/Discord.Net.Core/Entities/Permissions/ApplicationCommandPermissions.cs View File

@@ -8,17 +8,17 @@ namespace Discord
/// <summary> /// <summary>
/// The id of the role or user. /// The id of the role or user.
/// </summary> /// </summary>
public ulong Id { get; }
public ulong TargetId { get; }


/// <summary> /// <summary>
/// The target of this permission. /// The target of this permission.
/// </summary> /// </summary>
public PermissionTarget Type { get; }
public PermissionTarget TargetType { get; }


/// <summary> /// <summary>
/// <see langword="true"/> to allow, otherwise <see langword="false"/>. /// <see langword="true"/> to allow, otherwise <see langword="false"/>.
/// </summary> /// </summary>
public bool Value { get; }
public bool Permission { get; }


internal ApplicationCommandPermission() { } internal ApplicationCommandPermission() { }


@@ -30,9 +30,9 @@ namespace Discord
/// <param name="allow">The value of this permission.</param> /// <param name="allow">The value of this permission.</param>
public ApplicationCommandPermission(ulong targetId, PermissionTarget targetType, bool allow) public ApplicationCommandPermission(ulong targetId, PermissionTarget targetType, bool allow)
{ {
this.Id = targetId;
this.Type = targetType;
this.Value = allow;
this.TargetId = targetId;
this.TargetType = targetType;
this.Permission = allow;
} }


/// <summary> /// <summary>
@@ -42,9 +42,9 @@ namespace Discord
/// <param name="allow">The value of this permission.</param> /// <param name="allow">The value of this permission.</param>
public ApplicationCommandPermission(IUser target, bool allow) public ApplicationCommandPermission(IUser target, bool allow)
{ {
this.Id = target.Id;
this.Value = allow;
this.Type = PermissionTarget.User;
this.TargetId = target.Id;
this.Permission = allow;
this.TargetType = PermissionTarget.User;
} }


/// <summary> /// <summary>
@@ -54,9 +54,9 @@ namespace Discord
/// <param name="allow">The value of this permission.</param> /// <param name="allow">The value of this permission.</param>
public ApplicationCommandPermission(IRole target, bool allow) public ApplicationCommandPermission(IRole target, bool allow)
{ {
this.Id = target.Id;
this.Value = allow;
this.Type = PermissionTarget.Role;
this.TargetId = target.Id;
this.Permission = allow;
this.TargetType = PermissionTarget.Role;
} }
} }
} }

+ 6
- 5
src/Discord.Net.Core/Entities/Permissions/GuildApplicationCommandPermissions.cs View File

@@ -9,12 +9,13 @@ namespace Discord
/// <summary> /// <summary>
/// Returned when fetching the permissions for a command in a guild. /// Returned when fetching the permissions for a command in a guild.
/// </summary> /// </summary>
public class GuildApplicationCommandPermissions
public class GuildApplicationCommandPermission

{ {
/// <summary> /// <summary>
/// The id of the command. /// The id of the command.
/// </summary> /// </summary>
public ulong Id { get; }
public ulong CommandId { get; }


/// <summary> /// <summary>
/// The id of the application the command belongs to. /// The id of the application the command belongs to.
@@ -31,12 +32,12 @@ namespace Discord
/// </summary> /// </summary>
public IReadOnlyCollection<ApplicationCommandPermission> Permissions { get; } public IReadOnlyCollection<ApplicationCommandPermission> Permissions { get; }


internal GuildApplicationCommandPermissions(ulong id, ulong appId, ulong guildId, List<ApplicationCommandPermission> permissions)
internal GuildApplicationCommandPermission(ulong commandId, ulong appId, ulong guildId, ApplicationCommandPermission[] permissions)
{ {
this.Id = id;
this.CommandId = commandId;
this.ApplicationId = appId; this.ApplicationId = appId;
this.GuildId = guildId; this.GuildId = guildId;
this.Permissions = permissions.ToReadOnlyCollection();
this.Permissions = permissions;
} }
} }
} }

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

@@ -19,5 +19,7 @@ namespace Discord.API
public string Description { get; set; } public string Description { get; set; }
[JsonProperty("options")] [JsonProperty("options")]
public Optional<ApplicationCommandOption[]> Options { get; set; } public Optional<ApplicationCommandOption[]> Options { get; set; }
[JsonProperty("default_permission")]
public Optional<bool> DefaultPermissions { get; set; }
} }
} }

+ 1
- 1
src/Discord.Net.Rest/API/Common/ApplicationCommandPermissions.cs View File

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


namespace Discord.API namespace Discord.API
{ {
public class ApplicationCommandPermissions
internal class ApplicationCommandPermissions
{ {
[JsonProperty("id")] [JsonProperty("id")]
public ulong Id { get; set; } public ulong Id { get; set; }


+ 4
- 4
src/Discord.Net.Rest/API/Common/GuildApplicationCommandPermissions.cs View File

@@ -7,16 +7,16 @@ using System.Threading.Tasks;


namespace Discord.API namespace Discord.API
{ {
public class GuildApplicationCommandPermission
internal class GuildApplicationCommandPermission
{ {
[JsonProperty("id")] [JsonProperty("id")]
public ulong Id { get; }
public ulong Id { get; set; }


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


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


[JsonProperty("permissions")] [JsonProperty("permissions")]
public API.ApplicationCommandPermissions[] Permissions { get; set; } public API.ApplicationCommandPermissions[] Permissions { get; set; }


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

@@ -13,6 +13,6 @@ namespace Discord.API.Rest
public ulong Id { get; set; } public ulong Id { get; set; }


[JsonProperty("permissions")] [JsonProperty("permissions")]
public ApplicationCommandPermission[] Permissions { get; set; }
public ApplicationCommandPermissions[] Permissions { get; set; }
} }
} }

+ 2
- 1
src/Discord.Net.Rest/ClientHelper.cs View File

@@ -206,7 +206,7 @@ namespace Discord.Rest


public static async Task<IReadOnlyCollection<RestGuildCommand>> GetGuildApplicationCommands(BaseDiscordClient client, ulong guildId, RequestOptions options) public static async Task<IReadOnlyCollection<RestGuildCommand>> GetGuildApplicationCommands(BaseDiscordClient client, ulong guildId, RequestOptions options)
{ {
var response = await client.ApiClient.GetGuildApplicationCommandAsync(guildId, options).ConfigureAwait(false);
var response = await client.ApiClient.GetGuildApplicationCommandsAsync(guildId, options).ConfigureAwait(false);


if (!response.Any()) if (!response.Any())
return new RestGuildCommand[0].ToImmutableArray(); return new RestGuildCommand[0].ToImmutableArray();
@@ -214,6 +214,7 @@ namespace Discord.Rest
return response.Select(x => RestGuildCommand.Create(client, x, guildId)).ToImmutableArray(); return response.Select(x => RestGuildCommand.Create(client, x, guildId)).ToImmutableArray();
} }



public static Task AddRoleAsync(BaseDiscordClient client, ulong guildId, ulong userId, ulong roleId, RequestOptions options = null) public static Task AddRoleAsync(BaseDiscordClient client, ulong guildId, ulong userId, ulong roleId, RequestOptions options = null)
=> client.ApiClient.AddRoleAsync(guildId, userId, roleId, options); => client.ApiClient.AddRoleAsync(guildId, userId, roleId, options);


+ 1
- 1
src/Discord.Net.Rest/Discord.Net.Rest.csproj View File

@@ -9,7 +9,7 @@
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0;netstandard2.1</TargetFrameworks> <TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0;netstandard2.1</TargetFrameworks>
<PackageIcon>Temporary.png</PackageIcon> <PackageIcon>Temporary.png</PackageIcon>
<PackageProjectUrl>https://github.com/Discord-Net-Labs/Discord.Net-Labs</PackageProjectUrl> <PackageProjectUrl>https://github.com/Discord-Net-Labs/Discord.Net-Labs</PackageProjectUrl>
<Version>2.4.1</Version>
<Version>2.4.2</Version>
<PackageId>Discord.Net.Labs.Rest</PackageId> <PackageId>Discord.Net.Labs.Rest</PackageId>
<RepositoryUrl>https://github.com/Discord-Net-Labs/Discord.Net-Labs</RepositoryUrl> <RepositoryUrl>https://github.com/Discord-Net-Labs/Discord.Net-Labs</RepositoryUrl>
<AssemblyVersion>2.3.4</AssemblyVersion> <AssemblyVersion>2.3.4</AssemblyVersion>


+ 59
- 0
src/Discord.Net.Rest/Discord.Net.Rest.xml View File

@@ -2740,6 +2740,27 @@
<member name="M:Discord.Rest.RestGuild.LeaveAsync(Discord.RequestOptions)"> <member name="M:Discord.Rest.RestGuild.LeaveAsync(Discord.RequestOptions)">
<inheritdoc /> <inheritdoc />
</member> </member>
<member name="M:Discord.Rest.RestGuild.GetSlashCommandsAsync(Discord.RequestOptions)">
<summary>
Gets a collection of slash commands created by the current user in this guild.
</summary>
<param name="options">The options to be used when sending the request.</param>
<returns>
A task that represents the asynchronous get operation. The task result contains a read-only collection of
slash commands created by the current user.
</returns>
</member>
<member name="M:Discord.Rest.RestGuild.GetSlashCommandAsync(System.UInt64,Discord.RequestOptions)">
<summary>
Gets a slash command in the current guild.
</summary>
<param name="id">The unique identifier of the slash command.</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
slash command created by the current user.
</returns>
</member>
<member name="M:Discord.Rest.RestGuild.GetBansAsync(Discord.RequestOptions)"> <member name="M:Discord.Rest.RestGuild.GetBansAsync(Discord.RequestOptions)">
<summary> <summary>
Gets a collection of all users banned in this guild. Gets a collection of all users banned in this guild.
@@ -3378,6 +3399,9 @@
<member name="P:Discord.Rest.RestApplicationCommand.Description"> <member name="P:Discord.Rest.RestApplicationCommand.Description">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="P:Discord.Rest.RestApplicationCommand.DefaultPermission">
<inheritdoc/>
</member>
<member name="P:Discord.Rest.RestApplicationCommand.Options"> <member name="P:Discord.Rest.RestApplicationCommand.Options">
<summary> <summary>
The options of this command. The options of this command.
@@ -3391,6 +3415,9 @@
<member name="P:Discord.Rest.RestApplicationCommand.CreatedAt"> <member name="P:Discord.Rest.RestApplicationCommand.CreatedAt">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:Discord.Rest.RestApplicationCommand.DeleteAsync(Discord.RequestOptions)">
<inheritdoc/>
</member>
<member name="T:Discord.Rest.RestApplicationCommandChoice"> <member name="T:Discord.Rest.RestApplicationCommandChoice">
<summary> <summary>
Represents a Rest-based implementation of <see cref="T:Discord.IApplicationCommandOptionChoice"/>. Represents a Rest-based implementation of <see cref="T:Discord.IApplicationCommandOptionChoice"/>.
@@ -3488,6 +3515,38 @@
The modified command The modified command
</returns> </returns>
</member> </member>
<member name="M:Discord.Rest.RestGuildCommand.GetCommandPermission(Discord.RequestOptions)">
<summary>
Gets this commands permissions inside of the current guild.
</summary>
<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.GuildApplicationCommandPermission"/> object defining the permissions of the current slash command.
</returns>
</member>
<member name="M:Discord.Rest.RestGuildCommand.ModifyCommandPermissions(Discord.ApplicationCommandPermission[],Discord.RequestOptions)">
<summary>
Modifies the current command permissions for this guild command.
</summary>
<param name="permissions">The permissions to overwrite.</param>
<param name="options">The options to be used when sending the request.</param>
<returns>
A task that represents the asynchronous modification operation. The task result contains a
<see cref="T:Discord.GuildApplicationCommandPermission"/> object containing the modified permissions.
</returns>
</member>
<member name="M:Discord.Rest.RestGuildCommand.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"> <member name="P:Discord.Rest.RestInvite.ChannelName">
<inheritdoc /> <inheritdoc />
</member> </member>


+ 58
- 93
src/Discord.Net.Rest/DiscordRestApiClient.cs View File

@@ -827,54 +827,14 @@ namespace Discord.API


options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);


try
{
return await SendJsonAsync<ApplicationCommand>("POST", () => $"applications/{this.CurrentUserId}/commands", command, new BucketIds(), options: options).ConfigureAwait(false);
}
catch (HttpException x)
{
if (x.HttpCode == HttpStatusCode.BadRequest)
{
var json = (x.Request as JsonRestRequest).Json;
throw new ApplicationCommandException(json, x);
}


// Re-throw the http exception
throw;
}
return await TrySendApplicationCommand(SendJsonAsync<ApplicationCommand>("POST", () => $"applications/{this.CurrentUserId}/commands", command, new BucketIds(), options: options)).ConfigureAwait(false);
} }
public async Task<ApplicationCommand> ModifyGlobalApplicationCommandAsync(ModifyApplicationCommandParams command, ulong commandId, RequestOptions options = null) public async Task<ApplicationCommand> ModifyGlobalApplicationCommandAsync(ModifyApplicationCommandParams command, ulong commandId, RequestOptions options = null)
{ {
Preconditions.NotNull(command, nameof(command));

if (command.Name.IsSpecified)
{
Preconditions.AtMost(command.Name.Value.Length, 32, nameof(command.Name));
Preconditions.AtLeast(command.Name.Value.Length, 3, nameof(command.Name));
}
if (command.Description.IsSpecified)
{
Preconditions.AtMost(command.Description.Value.Length, 100, nameof(command.Description));
Preconditions.AtLeast(command.Description.Value.Length, 1, nameof(command.Description));
}

options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);


try
{
return await SendJsonAsync<ApplicationCommand>("PATCH", () => $"applications/{this.CurrentUserId}/commands/{commandId}", command, new BucketIds(), options: options).ConfigureAwait(false);
}
catch (HttpException x)
{
if (x.HttpCode == HttpStatusCode.BadRequest)
{
var json = (x.Request as JsonRestRequest).Json;
throw new ApplicationCommandException(json, x);
}

// Re-throw the http exception
throw;
}
return await TrySendApplicationCommand(SendJsonAsync<ApplicationCommand>("PATCH", () => $"applications/{this.CurrentUserId}/commands/{commandId}", command, new BucketIds(), options: options)).ConfigureAwait(false);
} }
public async Task DeleteGlobalApplicationCommandAsync(ulong commandId, RequestOptions options = null) public async Task DeleteGlobalApplicationCommandAsync(ulong commandId, RequestOptions options = null)
{ {
@@ -883,7 +843,14 @@ namespace Discord.API
await SendAsync("DELETE", () => $"applications/{this.CurrentUserId}/commands/{commandId}", new BucketIds(), options: options).ConfigureAwait(false); await SendAsync("DELETE", () => $"applications/{this.CurrentUserId}/commands/{commandId}", new BucketIds(), options: options).ConfigureAwait(false);
} }


public async Task<ApplicationCommand[]> GetGuildApplicationCommandAsync(ulong guildId, RequestOptions options = null)
public async Task<ApplicationCommand[]> BulkOverwriteGlobalApplicationCommands(CreateApplicationCommandParams[] commands, RequestOptions options = null)
{
options = RequestOptions.CreateOrClone(options);

return await TrySendApplicationCommand(SendJsonAsync<ApplicationCommand[]>("PUT", () => $"applications/{this.CurrentUserId}/commands", commands, new BucketIds(), options: options)).ConfigureAwait(false);
}

public async Task<ApplicationCommand[]> GetGuildApplicationCommandsAsync(ulong guildId, RequestOptions options = null)
{ {
options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);


@@ -891,49 +858,27 @@ namespace Discord.API


return await SendAsync<ApplicationCommand[]>("GET", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", bucket, options: options).ConfigureAwait(false); return await SendAsync<ApplicationCommand[]>("GET", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", bucket, options: options).ConfigureAwait(false);
} }
public async Task<ApplicationCommand> CreateGuildApplicationCommandAsync(CreateApplicationCommandParams command, ulong guildId, RequestOptions options = null)

public async Task<ApplicationCommand> GetGuildApplicationCommandAsync(ulong guildId, ulong commandId, 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.AtMost(command.Description.Length, 100, nameof(command.Description));
Preconditions.AtLeast(command.Description.Length, 1, nameof(command.Description));
options = RequestOptions.CreateOrClone(options);


var bucket = new BucketIds(guildId: guildId);

return await SendAsync<ApplicationCommand>("GET", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", bucket, options: options);
}

public async Task<ApplicationCommand> CreateGuildApplicationCommandAsync(CreateApplicationCommandParams command, ulong guildId, RequestOptions options = null)
{
options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);


var bucket = new BucketIds(guildId: guildId); var bucket = new BucketIds(guildId: guildId);


try
{
return await SendJsonAsync<ApplicationCommand>("POST", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", 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);
}
return await TrySendApplicationCommand(SendJsonAsync<ApplicationCommand>("POST", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", command, bucket, options: options)).ConfigureAwait(false);


// Re-throw the http exception
throw;
}
} }
public async Task<ApplicationCommand> ModifyGuildApplicationCommandAsync(ModifyApplicationCommandParams command, ulong guildId, ulong commandId, RequestOptions options = null) public async Task<ApplicationCommand> ModifyGuildApplicationCommandAsync(ModifyApplicationCommandParams command, ulong guildId, ulong commandId, RequestOptions options = null)
{ {
Preconditions.NotNull(command, nameof(command));

if (command.Name.IsSpecified)
{
Preconditions.AtMost(command.Name.Value.Length, 32, nameof(command.Name));
Preconditions.AtLeast(command.Name.Value.Length, 3, nameof(command.Name));
}
if (command.Description.IsSpecified)
{
Preconditions.AtMost(command.Description.Value.Length, 100, nameof(command.Description));
Preconditions.AtLeast(command.Description.Value.Length, 1, nameof(command.Description));
}

options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);


var bucket = new BucketIds(guildId: guildId); var bucket = new BucketIds(guildId: guildId);
@@ -963,6 +908,15 @@ namespace Discord.API
await SendAsync<ApplicationCommand>("DELETE", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", bucket, options: options).ConfigureAwait(false); await SendAsync<ApplicationCommand>("DELETE", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", bucket, options: options).ConfigureAwait(false);
} }


public async Task<ApplicationCommand[]> BulkOverwriteGuildApplicationCommands(ulong guildId, CreateApplicationCommandParams[] commands, RequestOptions options = null)
{
options = RequestOptions.CreateOrClone(options);

var bucket = new BucketIds(guildId: guildId);

return await TrySendApplicationCommand(SendJsonAsync<ApplicationCommand[]>("PUT", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", commands, bucket, options: options)).ConfigureAwait(false);
}

//Interaction Responses //Interaction Responses
public async Task CreateInteractionResponse(InteractionResponse response, ulong interactionId, string interactionToken, RequestOptions options = null) public async Task CreateInteractionResponse(InteractionResponse response, ulong interactionId, string interactionToken, RequestOptions options = null)
{ {
@@ -971,7 +925,7 @@ namespace Discord.API


options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);


await SendJsonAsync("POST", () => $"interactions/{interactionId}/{interactionToken}/callback", response, new BucketIds(), options: options);
await SendJsonAsync<Message>("POST", () => $"interactions/{interactionId}/{interactionToken}/callback", response, new BucketIds(), options: options);
} }
public async Task<Message> GetInteractionResponse(string interactionToken, RequestOptions options = null) public async Task<Message> GetInteractionResponse(string interactionToken, RequestOptions options = null)
{ {
@@ -1037,7 +991,7 @@ namespace Discord.API


options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);


return await SendAsync<GuildApplicationCommandPermission[]>("GET", () => $"/applications/{this.CurrentUserId}/guilds/{guildId}/commands/permissions", new BucketIds(), options: options).ConfigureAwait(false);
return await SendAsync<GuildApplicationCommandPermission[]>("GET", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/permissions", new BucketIds(), options: options).ConfigureAwait(false);
} }


public async Task<GuildApplicationCommandPermission> GetGuildApplicationCommandPermission(ulong guildId, ulong commandId, RequestOptions options = null) public async Task<GuildApplicationCommandPermission> GetGuildApplicationCommandPermission(ulong guildId, ulong commandId, RequestOptions options = null)
@@ -1047,37 +1001,27 @@ namespace Discord.API


options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);


return await SendAsync<GuildApplicationCommandPermission>("GET", () => $"/applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}/permissions", new BucketIds(), options: options).ConfigureAwait(false);
return await SendAsync<GuildApplicationCommandPermission>("GET", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}/permissions", new BucketIds(), options: options).ConfigureAwait(false);
} }


public async Task ModifyApplicationCommandPermissions(ApplicationCommandPermissions[] permissions, ulong guildId, ulong commandId, RequestOptions options = null)
public async Task<GuildApplicationCommandPermission> ModifyApplicationCommandPermissions(ApplicationCommandPermissions[] permissions, ulong guildId, ulong commandId, RequestOptions options = null)
{ {
Preconditions.NotEqual(guildId, 0, nameof(guildId)); Preconditions.NotEqual(guildId, 0, nameof(guildId));
Preconditions.NotEqual(commandId, 0, nameof(commandId)); Preconditions.NotEqual(commandId, 0, nameof(commandId));


options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);


await SendJsonAsync("PUT", () => $"/applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}/permissions", permissions, new BucketIds(), options: options).ConfigureAwait(false);
return await SendJsonAsync<GuildApplicationCommandPermission>("PUT", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}/permissions", permissions, new BucketIds(), options: options).ConfigureAwait(false);
} }


public async Task BatchModifyApplicationCommandPermissions(ModifyGuildApplicationCommandPermissions[] permissions, ulong guildId, RequestOptions options = null)
public async Task<IReadOnlyCollection<GuildApplicationCommandPermission>> BatchModifyApplicationCommandPermissions(ModifyGuildApplicationCommandPermissions[] permissions, ulong guildId, RequestOptions options = null)
{ {
Preconditions.NotEqual(guildId, 0, nameof(guildId)); Preconditions.NotEqual(guildId, 0, nameof(guildId));
Preconditions.NotNull(permissions, nameof(permissions)); Preconditions.NotNull(permissions, nameof(permissions));


options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);


await SendJsonAsync("PUT", () => $"/applications/{this.CurrentUserId}/guilds/{guildId}/commands/premissions", permissions, new BucketIds(), options: options).ConfigureAwait(false);
}

public async Task BulkOverrideGuildApplicationCommand(API.ApplicationCommand[] commands, ulong guildId, RequestOptions options = null)
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));
Preconditions.NotNull(commands, nameof(commands));

options = RequestOptions.CreateOrClone(options);

await SendJsonAsync("PUT", () => $"/applications/{this.CurrentUserId}/guilds/{guildId}/commands", commands, new BucketIds(), options: options).ConfigureAwait(false);
return await SendJsonAsync<GuildApplicationCommandPermission[]>("PUT", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/permissions", permissions, new BucketIds(), options: options).ConfigureAwait(false);
} }


//Guilds //Guilds
@@ -1772,6 +1716,27 @@ namespace Discord.API
return _serializer.Deserialize<T>(reader); return _serializer.Deserialize<T>(reader);
} }


protected async Task<T> TrySendApplicationCommand<T>(Task<T> sendTask)
{
var result = await sendTask.ConfigureAwait(false);

if (sendTask.Exception != null)
{
if (sendTask.Exception.InnerException is HttpException x)
{
if (x.HttpCode == HttpStatusCode.BadRequest)
{
var json = (x.Request as JsonRestRequest).Json;
throw new ApplicationCommandException(json, x);
}
}

throw sendTask.Exception;
}
else
return result;
}

internal class BucketIds internal class BucketIds
{ {
public ulong GuildId { get; internal set; } public ulong GuildId { get; internal set; }


+ 9
- 0
src/Discord.Net.Rest/DiscordRestClient.cs View File

@@ -106,6 +106,7 @@ namespace Discord.Rest
=> ClientHelper.GetVoiceRegionAsync(this, id, options); => ClientHelper.GetVoiceRegionAsync(this, id, options);
public Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null) public Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null)
=> ClientHelper.GetWebhookAsync(this, id, options); => ClientHelper.GetWebhookAsync(this, id, options);

public Task<RestGlobalCommand> CreateGlobalCommand(SlashCommandCreationProperties properties, RequestOptions options = null) public Task<RestGlobalCommand> CreateGlobalCommand(SlashCommandCreationProperties properties, RequestOptions options = null)
=> InteractionHelper.CreateGlobalCommand(this, properties, options); => InteractionHelper.CreateGlobalCommand(this, properties, options);
public Task<RestGlobalCommand> CreateGlobalCommand(Action<SlashCommandCreationProperties> func, RequestOptions options = null) public Task<RestGlobalCommand> CreateGlobalCommand(Action<SlashCommandCreationProperties> func, RequestOptions options = null)
@@ -118,6 +119,14 @@ namespace Discord.Rest
=> ClientHelper.GetGlobalApplicationCommands(this, options); => ClientHelper.GetGlobalApplicationCommands(this, options);
public Task<IReadOnlyCollection<RestGuildCommand>> GetGuildApplicationCommands(ulong guildId, RequestOptions options = null) public Task<IReadOnlyCollection<RestGuildCommand>> GetGuildApplicationCommands(ulong guildId, RequestOptions options = null)
=> ClientHelper.GetGuildApplicationCommands(this, guildId, options); => ClientHelper.GetGuildApplicationCommands(this, guildId, options);
public Task<IReadOnlyCollection<RestGlobalCommand>> BulkOverwriteGlobalCommands(SlashCommandCreationProperties[] commandProperties, RequestOptions options = null)
=> InteractionHelper.BulkOverwriteGlobalCommands(this, commandProperties, options);
public Task<IReadOnlyCollection<RestGuildCommand>> BulkOverwriteGuildCommands(SlashCommandCreationProperties[] 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);


public Task AddRoleAsync(ulong guildId, ulong userId, ulong roleId) public Task AddRoleAsync(ulong guildId, ulong userId, ulong roleId)
=> ClientHelper.AddRoleAsync(this, guildId, userId, roleId); => ClientHelper.AddRoleAsync(this, guildId, userId, roleId);
public Task RemoveRoleAsync(ulong guildId, ulong userId, ulong roleId) public Task RemoveRoleAsync(ulong guildId, ulong userId, ulong roleId)


+ 14
- 0
src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs View File

@@ -270,6 +270,20 @@ namespace Discord.Rest
return RestGuildIntegration.Create(client, guild, model); return RestGuildIntegration.Create(client, guild, model);
} }


//Interactions
public static async Task<IReadOnlyCollection<RestGuildCommand>> GetSlashCommandsAsync(IGuild guild, BaseDiscordClient client,
RequestOptions options)
{
var models = await client.ApiClient.GetGuildApplicationCommandsAsync(guild.Id, options);
return models.Select(x => RestGuildCommand.Create(client, x, guild.Id)).ToImmutableArray();
}
public static async Task<RestGuildCommand> GetSlashCommandAsync(IGuild guild, ulong id, BaseDiscordClient client,
RequestOptions options)
{
var model = await client.ApiClient.GetGuildApplicationCommandAsync(guild.Id, id, options);
return RestGuildCommand.Create(client, model, guild.Id);
}

//Invites //Invites
public static async Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(IGuild guild, BaseDiscordClient client, public static async Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(IGuild guild, BaseDiscordClient client,
RequestOptions options) RequestOptions options)


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

@@ -255,7 +255,30 @@ namespace Discord.Rest
public Task LeaveAsync(RequestOptions options = null) public Task LeaveAsync(RequestOptions options = null)
=> GuildHelper.LeaveAsync(this, Discord, options); => GuildHelper.LeaveAsync(this, Discord, options);


//Bans
//Interactions
/// <summary>
/// Gets a collection of slash commands created by the current user in this guild.
/// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous get operation. The task result contains a read-only collection of
/// slash commands created by the current user.
/// </returns>
public Task<IReadOnlyCollection<RestGuildCommand>> GetSlashCommandsAsync(RequestOptions options = null)
=> GuildHelper.GetSlashCommandsAsync(this, Discord, options);

/// <summary>
/// Gets a slash command in the current guild.
/// </summary>
/// <param name="id">The unique identifier of the slash command.</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
/// slash command created by the current user.
/// </returns>
public Task<RestGuildCommand> GetSlashCommandAsync(ulong id, RequestOptions options = null)
=> GuildHelper.GetSlashCommandAsync(this, id, Discord, options);

//Bans //Bans
/// <summary> /// <summary>
/// Gets a collection of all users banned in this guild. /// Gets a collection of all users banned in this guild.


+ 202
- 35
src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs View File

@@ -10,20 +10,20 @@ namespace Discord.Rest
{ {
internal static class InteractionHelper internal static class InteractionHelper
{ {
internal static Task SendInteractionResponse(BaseDiscordClient client, IMessageChannel channel, InteractionResponse response,
public static Task SendInteractionResponse(BaseDiscordClient client, IMessageChannel channel, InteractionResponse response,
ulong interactionId, string interactionToken, RequestOptions options = null) ulong interactionId, string interactionToken, RequestOptions options = null)
{ {
return client.ApiClient.CreateInteractionResponse(response, interactionId, interactionToken, options); return client.ApiClient.CreateInteractionResponse(response, interactionId, interactionToken, options);
} }


internal static async Task<RestInteractionMessage> GetOriginalResponseAsync(BaseDiscordClient client, IMessageChannel channel,
public static async Task<RestInteractionMessage> GetOriginalResponseAsync(BaseDiscordClient client, IMessageChannel channel,
IDiscordInteraction interaction, RequestOptions options = null) IDiscordInteraction interaction, RequestOptions options = null)
{ {
var model = await client.ApiClient.GetInteractionResponse(interaction.Token, options).ConfigureAwait(false); var model = await client.ApiClient.GetInteractionResponse(interaction.Token, options).ConfigureAwait(false);
return RestInteractionMessage.Create(client, model, interaction.Token, channel); return RestInteractionMessage.Create(client, model, interaction.Token, channel);
} }


internal static async Task<RestFollowupMessage> SendFollowupAsync(BaseDiscordClient client, CreateWebhookMessageParams args,
public static async Task<RestFollowupMessage> SendFollowupAsync(BaseDiscordClient client, CreateWebhookMessageParams args,
string token, IMessageChannel channel, RequestOptions options = null) string token, IMessageChannel channel, RequestOptions options = null)
{ {
var model = await client.ApiClient.CreateInteractionFollowupMessage(args, token, options).ConfigureAwait(false); var model = await client.ApiClient.CreateInteractionFollowupMessage(args, token, options).ConfigureAwait(false);
@@ -31,47 +31,128 @@ namespace Discord.Rest
RestFollowupMessage entity = RestFollowupMessage.Create(client, model, token, channel); RestFollowupMessage entity = RestFollowupMessage.Create(client, model, token, channel);
return entity; return entity;
} }
// Global commands // Global commands
internal static async Task<RestGlobalCommand> CreateGlobalCommand(BaseDiscordClient client,
public static async Task<RestGlobalCommand> CreateGlobalCommand(BaseDiscordClient client,
Action<SlashCommandCreationProperties> func, RequestOptions options = null) Action<SlashCommandCreationProperties> func, RequestOptions options = null)
{ {
var args = new SlashCommandCreationProperties(); var args = new SlashCommandCreationProperties();
func(args); func(args);
return await CreateGlobalCommand(client, args, options).ConfigureAwait(false); return await CreateGlobalCommand(client, args, options).ConfigureAwait(false);
} }
internal static async Task<RestGlobalCommand> CreateGlobalCommand(BaseDiscordClient client,
SlashCommandCreationProperties args, RequestOptions options = null)
public static async Task<RestGlobalCommand> CreateGlobalCommand(BaseDiscordClient client,
SlashCommandCreationProperties arg, RequestOptions options = null)
{ {
if (args.Options.IsSpecified)
{
if (args.Options.Value.Count > 10)
throw new ArgumentException("Option count must be 10 or less");
}
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() var model = new CreateApplicationCommandParams()
{ {
Name = args.Name,
Description = args.Description,
Options = args.Options.IsSpecified
? args.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
Name = arg.Name,
Description = arg.Description,
Options = arg.Options.IsSpecified
? arg.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray()
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified, : Optional<Discord.API.ApplicationCommandOption[]>.Unspecified,
DefaultPermission = args.DefaultPermission.IsSpecified
? args.DefaultPermission.Value
DefaultPermission = arg.DefaultPermission.IsSpecified
? arg.DefaultPermission.Value
: Optional<bool>.Unspecified : Optional<bool>.Unspecified
}; };


var cmd = await client.ApiClient.CreateGlobalApplicationCommandAsync(model, options).ConfigureAwait(false); var cmd = await client.ApiClient.CreateGlobalApplicationCommandAsync(model, options).ConfigureAwait(false);
return RestGlobalCommand.Create(client, cmd); return RestGlobalCommand.Create(client, cmd);
} }
internal static async Task<RestGlobalCommand> ModifyGlobalCommand(BaseDiscordClient client, RestGlobalCommand command,

public static async Task<IReadOnlyCollection<RestGlobalCommand>> BulkOverwriteGlobalCommands(BaseDiscordClient client,
SlashCommandCreationProperties[] 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.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,
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.BulkOverwriteGlobalApplicationCommands(models.ToArray(), options);

return apiModels.Select(x => RestGlobalCommand.Create(client, x)).ToArray();
}

public static async Task<IReadOnlyCollection<RestGuildCommand>> BulkOverwriteGuildCommands(BaseDiscordClient client, ulong guildId,
SlashCommandCreationProperties[] 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.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,
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();
}

public static async Task<RestGlobalCommand> ModifyGlobalCommand(BaseDiscordClient client, RestGlobalCommand command,
Action<ApplicationCommandProperties> func, RequestOptions options = null) Action<ApplicationCommandProperties> func, RequestOptions options = null)
{ {
ApplicationCommandProperties args = new ApplicationCommandProperties(); ApplicationCommandProperties args = new ApplicationCommandProperties();
func(args); 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.AtMost(args.Description.Value.Length, 100, nameof(args.Description));
Preconditions.AtLeast(args.Description.Value.Length, 1, nameof(args.Description));
}


if (args.Options.IsSpecified) if (args.Options.IsSpecified)
{ {
if (args.Options.Value.Count > 10) if (args.Options.Value.Count > 10)
@@ -96,7 +177,7 @@ namespace Discord.Rest
} }




internal static async Task DeleteGlobalCommand(BaseDiscordClient client, RestGlobalCommand command, RequestOptions options = null)
public static async Task DeleteGlobalCommand(BaseDiscordClient client, RestGlobalCommand command, RequestOptions options = null)
{ {
Preconditions.NotNull(command, nameof(command)); Preconditions.NotNull(command, nameof(command));
Preconditions.NotEqual(command.Id, 0, nameof(command.Id)); Preconditions.NotEqual(command.Id, 0, nameof(command.Id));
@@ -105,7 +186,7 @@ namespace Discord.Rest
} }


// Guild Commands // Guild Commands
internal static async Task<RestGuildCommand> CreateGuildCommand(BaseDiscordClient client, ulong guildId,
public static async Task<RestGuildCommand> CreateGuildCommand(BaseDiscordClient client, ulong guildId,
Action<SlashCommandCreationProperties> func, RequestOptions options = null) Action<SlashCommandCreationProperties> func, RequestOptions options = null)
{ {
var args = new SlashCommandCreationProperties(); var args = new SlashCommandCreationProperties();
@@ -113,19 +194,23 @@ namespace Discord.Rest


return await CreateGuildCommand(client, guildId, args, options).ConfigureAwait(false); return await CreateGuildCommand(client, guildId, args, options).ConfigureAwait(false);
} }
internal static async Task<RestGuildCommand> CreateGuildCommand(BaseDiscordClient client, ulong guildId,
public static async Task<RestGuildCommand> CreateGuildCommand(BaseDiscordClient client, ulong guildId,
SlashCommandCreationProperties args, RequestOptions options = null) SlashCommandCreationProperties args, RequestOptions options = null)
{ {
Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name)); Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name));
Preconditions.NotNullOrEmpty(args.Description, nameof(args.Description)); 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.IsSpecified)
{ {
if (args.Options.Value.Count > 10) if (args.Options.Value.Count > 10)
throw new ArgumentException("Option count must be 10 or less"); throw new ArgumentException("Option count must be 10 or less");


foreach(var item in args.Options.Value)
foreach (var item in args.Options.Value)
{ {
Preconditions.NotNullOrEmpty(item.Name, nameof(item.Name)); Preconditions.NotNullOrEmpty(item.Name, nameof(item.Name));
Preconditions.NotNullOrEmpty(item.Description, nameof(item.Description)); Preconditions.NotNullOrEmpty(item.Description, nameof(item.Description));
@@ -147,12 +232,23 @@ namespace Discord.Rest
var cmd = await client.ApiClient.CreateGuildApplicationCommandAsync(model, guildId, options).ConfigureAwait(false); var cmd = await client.ApiClient.CreateGuildApplicationCommandAsync(model, guildId, options).ConfigureAwait(false);
return RestGuildCommand.Create(client, cmd, guildId); return RestGuildCommand.Create(client, cmd, guildId);
} }
internal static async Task<RestGuildCommand> ModifyGuildCommand(BaseDiscordClient client, RestGuildCommand command,
public static async Task<RestGuildCommand> ModifyGuildCommand(BaseDiscordClient client, RestGuildCommand command,
Action<ApplicationCommandProperties> func, RequestOptions options = null) Action<ApplicationCommandProperties> func, RequestOptions options = null)
{ {
ApplicationCommandProperties args = new ApplicationCommandProperties(); ApplicationCommandProperties args = new ApplicationCommandProperties();
func(args); 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.AtMost(args.Description.Value.Length, 100, nameof(args.Description));
Preconditions.AtLeast(args.Description.Value.Length, 1, nameof(args.Description));
}

if (args.Options.IsSpecified) if (args.Options.IsSpecified)
{ {
if (args.Options.Value.Count > 10) if (args.Options.Value.Count > 10)
@@ -176,15 +272,15 @@ namespace Discord.Rest
return command; return command;
} }


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


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


internal static async Task<Discord.API.Message> ModifyFollowupMessage(BaseDiscordClient client, RestFollowupMessage message, Action<MessageProperties> func,
public static async Task<Discord.API.Message> ModifyFollowupMessage(BaseDiscordClient client, RestFollowupMessage message, Action<MessageProperties> func,
RequestOptions options = null) RequestOptions options = null)
{ {
var args = new MessageProperties(); var args = new MessageProperties();
@@ -204,10 +300,10 @@ namespace Discord.Rest
return await client.ApiClient.ModifyInteractionFollowupMessage(apiArgs, message.Id, message.Token, options).ConfigureAwait(false); return await client.ApiClient.ModifyInteractionFollowupMessage(apiArgs, message.Id, message.Token, options).ConfigureAwait(false);
} }


internal static async Task DeleteFollowupMessage(BaseDiscordClient client, RestFollowupMessage message, RequestOptions options = null)
public static async Task DeleteFollowupMessage(BaseDiscordClient client, RestFollowupMessage message, RequestOptions options = null)
=> await client.ApiClient.DeleteInteractionFollowupMessage(message.Id, message.Token, options); => await client.ApiClient.DeleteInteractionFollowupMessage(message.Id, message.Token, options);


internal static async Task<Discord.API.Message> ModifyInteractionResponse(BaseDiscordClient client, RestInteractionMessage message, Action<MessageProperties> func,
public static async Task<Discord.API.Message> ModifyInteractionResponse(BaseDiscordClient client, RestInteractionMessage message, Action<MessageProperties> func,
RequestOptions options = null) RequestOptions options = null)
{ {
var args = new MessageProperties(); var args = new MessageProperties();
@@ -227,16 +323,87 @@ namespace Discord.Rest
return await client.ApiClient.ModifyInteractionFollowupMessage(apiArgs, message.Id, message.Token, options).ConfigureAwait(false); return await client.ApiClient.ModifyInteractionFollowupMessage(apiArgs, message.Id, message.Token, options).ConfigureAwait(false);
} }


internal static async Task DeletedInteractionResponse(BaseDiscordClient client, RestInteractionMessage message, RequestOptions options = null)
public static async Task DeletedInteractionResponse(BaseDiscordClient client, RestInteractionMessage message, RequestOptions options = null)
=> await client.ApiClient.DeleteInteractionFollowupMessage(message.Id, message.Token, options); => await client.ApiClient.DeleteInteractionFollowupMessage(message.Id, message.Token, options);


// Guild permissions // Guild permissions
internal static async Task<IReadOnlyCollection<Discord.GuildApplicationCommandPermissions>> GetCommandGuildPermissions(BaseDiscordClient client,
RestGuildCommand command)
public static async Task<IReadOnlyCollection<GuildApplicationCommandPermission>> GetGuildCommandPermissionsAsync(BaseDiscordClient client,
ulong guildId, RequestOptions options)
{ {
// TODO
return null;
var models = await client.ApiClient.GetGuildApplicationCommandPermissions(guildId, options);
return models.Select(x =>
new GuildApplicationCommandPermission(x.Id, x.ApplicationId, guildId, x.Permissions.Select(
y => new Discord.ApplicationCommandPermission(y.Id, y.Type, y.Permission))
.ToArray())
).ToArray();
} }


public static async Task<GuildApplicationCommandPermission> GetGuildCommandPermissionAsync(BaseDiscordClient client,
ulong guildId, ulong commandId, RequestOptions options)
{
var model = await client.ApiClient.GetGuildApplicationCommandPermission(guildId, commandId, options);
return new GuildApplicationCommandPermission(model.Id, model.ApplicationId, guildId, model.Permissions.Select(
y => new ApplicationCommandPermission(y.Id, y.Type, y.Permission)).ToArray());
}

public static async Task<GuildApplicationCommandPermission> ModifyGuildCommandPermissionsAsync(BaseDiscordClient client, ulong guildId, ulong commandId,
ApplicationCommandPermission[] args, RequestOptions options)
{
Preconditions.NotNull(args, nameof(args));
Preconditions.AtMost(args.Length, 10, nameof(args));
Preconditions.GreaterThan(args.Length, 0, nameof(args));

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

foreach(var arg in args)
{
var model = new ApplicationCommandPermissions()
{
Id = arg.TargetId,
Permission = arg.Permission,
Type = arg.TargetType
};

models.Add(model);
}

var apiModel = await client.ApiClient.ModifyApplicationCommandPermissions(models.ToArray(), guildId, commandId, options);

return new GuildApplicationCommandPermission(apiModel.Id, apiModel.ApplicationId, guildId, apiModel.Permissions.Select(
x => new ApplicationCommandPermission(x.Id, x.Type, x.Permission)).ToArray());
}

public static async Task<IReadOnlyCollection<GuildApplicationCommandPermission>> BatchEditGuildCommandPermissionsAsync(BaseDiscordClient client, ulong guildId,
IDictionary<ulong, ApplicationCommandPermission[]> args, RequestOptions options)
{
Preconditions.NotNull(args, nameof(args));
Preconditions.NotEqual(args.Count, 0, nameof(args));

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

foreach(var arg in args)
{
Preconditions.AtMost(arg.Value.Length, 10, nameof(args));

var model = new ModifyGuildApplicationCommandPermissions()
{
Id = arg.Key,
Permissions = arg.Value.Select(x => new ApplicationCommandPermissions()
{
Id = x.TargetId,
Permission = x.Permission,
Type = x.TargetType
}).ToArray()
};

models.Add(model);
}

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

return apiModels.Select(
x => new GuildApplicationCommandPermission(x.Id, x.ApplicationId, x.GuildId, x.Permissions.Select(
y => new ApplicationCommandPermission(y.Id, y.Type, y.Permission)).ToArray())).ToArray();
}
} }
} }

+ 8
- 1
src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommand.cs View File

@@ -22,6 +22,9 @@ namespace Discord.Rest
/// <inheritdoc/> /// <inheritdoc/>
public string Description { get; private set; } public string Description { get; private set; }


/// <inheritdoc/>
public bool DefaultPermission { get; private set; }

/// <summary> /// <summary>
/// The options of this command. /// The options of this command.
/// </summary> /// </summary>
@@ -58,14 +61,18 @@ namespace Discord.Rest
this.ApplicationId = model.ApplicationId; this.ApplicationId = model.ApplicationId;
this.Name = model.Name; this.Name = model.Name;
this.Description = model.Description; this.Description = model.Description;
this.DefaultPermission = model.DefaultPermissions.GetValueOrDefault(true);


this.Options = model.Options.IsSpecified this.Options = model.Options.IsSpecified
? model.Options.Value.Select(x => RestApplicationCommandOption.Create(x)).ToImmutableArray() ? model.Options.Value.Select(x => RestApplicationCommandOption.Create(x)).ToImmutableArray()
: null; : null;
} }



/// <inheritdoc/>
public abstract Task DeleteAsync(RequestOptions options = null);

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


public virtual Task DeleteAsync(RequestOptions options = null) => throw new NotImplementedException();
} }
} }

+ 35
- 3
src/Discord.Net.Rest/Entities/Interactions/RestGuildCommand.cs View File

@@ -33,7 +33,7 @@ namespace Discord.Rest


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


/// <summary> /// <summary>
/// Modifies this <see cref="RestApplicationCommand"/>. /// Modifies this <see cref="RestApplicationCommand"/>.
@@ -46,7 +46,39 @@ namespace Discord.Rest
public async Task<RestGuildCommand> ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null) public async Task<RestGuildCommand> ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null)
=> await InteractionHelper.ModifyGuildCommand(Discord, this, func, options).ConfigureAwait(false); => await InteractionHelper.ModifyGuildCommand(Discord, this, func, options).ConfigureAwait(false);


public async Task<IReadOnlyCollection<Discord.GuildApplicationCommandPermissions>> GetCommandPermissions()
=> await InteractionHelper.GetCommandGuildPermissions(Discord, this);
/// <summary>
/// Gets this commands permissions inside of the current guild.
/// </summary>
/// <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="GuildApplicationCommandPermission"/> object defining the permissions of the current slash command.
/// </returns>
public Task<GuildApplicationCommandPermission> GetCommandPermission(RequestOptions options = null)
=> InteractionHelper.GetGuildCommandPermissionAsync(Discord, this.GuildId, this.Id, options);

/// <summary>
/// Modifies the current command permissions for this guild command.
/// </summary>
/// <param name="permissions">The permissions to overwrite.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous modification operation. The task result contains a
/// <see cref="GuildApplicationCommandPermission"/> object containing the modified permissions.
/// </returns>
public Task<GuildApplicationCommandPermission> ModifyCommandPermissions(ApplicationCommandPermission[] permissions, RequestOptions options = null)
=> InteractionHelper.ModifyGuildCommandPermissionsAsync(Discord, this.GuildId, this.Id, permissions, options);

/// <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);
} }
} }

+ 3
- 0
src/Discord.Net.WebSocket/API/Gateway/ApplicationCommandCreatedUpdatedEvent.cs View File

@@ -26,5 +26,8 @@ namespace Discord.API.Gateway


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

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

+ 27
- 0
src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml View File

@@ -2843,6 +2843,27 @@
voice regions the guild can access. voice regions the guild can access.
</returns> </returns>
</member> </member>
<member name="M:Discord.WebSocket.SocketGuild.GetSlashCommandsAsync(Discord.RequestOptions)">
<summary>
Gets a collection of slash commands created by the current user in this guild.
</summary>
<param name="options">The options to be used when sending the request.</param>
<returns>
A task that represents the asynchronous get operation. The task result contains a read-only collection of
slash commands created by the current user.
</returns>
</member>
<member name="M:Discord.WebSocket.SocketGuild.GetSlashCommandAsync(System.UInt64,Discord.RequestOptions)">
<summary>
Gets a slash command in the current guild.
</summary>
<param name="id">The unique identifier of the slash command.</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
slash command created by the current user.
</returns>
</member>
<member name="M:Discord.WebSocket.SocketGuild.GetInvitesAsync(Discord.RequestOptions)"> <member name="M:Discord.WebSocket.SocketGuild.GetInvitesAsync(Discord.RequestOptions)">
<summary> <summary>
Gets a collection of all invites in this guild. Gets a collection of all invites in this guild.
@@ -3243,6 +3264,9 @@
<member name="P:Discord.WebSocket.SocketApplicationCommand.Description"> <member name="P:Discord.WebSocket.SocketApplicationCommand.Description">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="P:Discord.WebSocket.SocketApplicationCommand.DefaultPermission">
<inheritdoc/>
</member>
<member name="P:Discord.WebSocket.SocketApplicationCommand.Options"> <member name="P:Discord.WebSocket.SocketApplicationCommand.Options">
<summary> <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 recieved over the gateway.
@@ -3256,6 +3280,9 @@
The <see cref="T:Discord.WebSocket.SocketGuild"/> where this application was created. The <see cref="T:Discord.WebSocket.SocketGuild"/> where this application was created.
</summary> </summary>
</member> </member>
<member name="M:Discord.WebSocket.SocketApplicationCommand.DeleteAsync(Discord.RequestOptions)">
<inheritdoc/>
</member>
<member name="T:Discord.WebSocket.SocketApplicationCommandChoice"> <member name="T:Discord.WebSocket.SocketApplicationCommandChoice">
<summary> <summary>
Represents a choice for a <see cref="T:Discord.WebSocket.SocketApplicationCommandOption"/>. Represents a choice for a <see cref="T:Discord.WebSocket.SocketApplicationCommandOption"/>.


+ 24
- 0
src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs View File

@@ -723,6 +723,30 @@ namespace Discord.WebSocket
public Task<RestGuildIntegration> CreateIntegrationAsync(ulong id, string type, RequestOptions options = null) public Task<RestGuildIntegration> CreateIntegrationAsync(ulong id, string type, RequestOptions options = null)
=> GuildHelper.CreateIntegrationAsync(this, Discord, id, type, options); => GuildHelper.CreateIntegrationAsync(this, Discord, id, type, options);


//Interactions
/// <summary>
/// Gets a collection of slash commands created by the current user in this guild.
/// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous get operation. The task result contains a read-only collection of
/// slash commands created by the current user.
/// </returns>
public Task<IReadOnlyCollection<RestGuildCommand>> GetSlashCommandsAsync(RequestOptions options = null)
=> GuildHelper.GetSlashCommandsAsync(this, Discord, options);

/// <summary>
/// Gets a slash command in the current guild.
/// </summary>
/// <param name="id">The unique identifier of the slash command.</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
/// slash command created by the current user.
/// </returns>
public Task<RestGuildCommand> GetSlashCommandAsync(ulong id, RequestOptions options = null)
=> GuildHelper.GetSlashCommandAsync(this, id, Discord, options);

//Invites //Invites
/// <summary> /// <summary>
/// Gets a collection of all invites in this guild. /// Gets a collection of all invites in this guild.


+ 10
- 1
src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketApplicationCommand.cs View File

@@ -1,3 +1,4 @@
using Discord.Rest;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
@@ -22,6 +23,9 @@ namespace Discord.WebSocket
/// <inheritdoc/> /// <inheritdoc/>
public string Description { get; private set; } public string Description { get; private set; }


/// <inheritdoc/>
public bool DefaultPermission { get; private set; }

/// <summary> /// <summary>
/// A collection of <see cref="SocketApplicationCommandOption"/>'s recieved over the gateway. /// A collection of <see cref="SocketApplicationCommandOption"/>'s recieved over the gateway.
/// </summary> /// </summary>
@@ -56,13 +60,18 @@ namespace Discord.WebSocket
this.Description = model.Description; this.Description = model.Description;
this.Name = model.Name; this.Name = model.Name;
this.GuildId = model.GuildId; this.GuildId = model.GuildId;
this.DefaultPermission = model.DefaultPermission.GetValueOrDefault(true);



this.Options = model.Options.IsSpecified this.Options = model.Options.IsSpecified
? model.Options.Value.Select(x => SocketApplicationCommandOption.Create(x)).ToImmutableArray() ? model.Options.Value.Select(x => SocketApplicationCommandOption.Create(x)).ToImmutableArray()
: new ImmutableArray<SocketApplicationCommandOption>(); : new ImmutableArray<SocketApplicationCommandOption>();
} }


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

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

+ 14
- 3
src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandData.cs View File

@@ -54,9 +54,20 @@ namespace Discord.WebSocket
{ {
foreach (var channel in resolved.Channels.Value) foreach (var channel in resolved.Channels.Value)
{ {
SocketChannel socketChannel = channel.Value.GuildId.IsSpecified
? SocketGuildChannel.Create(Discord.GetGuild(channel.Value.GuildId.Value), Discord.State, channel.Value)
: SocketDMChannel.Create(Discord, Discord.State, channel.Value);
SocketChannel socketChannel = guild != null
? guild.GetChannel(channel.Value.Id)
: Discord.GetChannel(channel.Value.Id);

if (socketChannel == null)
{
var channelModel = guild != null
? Discord.Rest.ApiClient.GetChannelAsync(guild.Id, channel.Value.Id).ConfigureAwait(false).GetAwaiter().GetResult()
: Discord.Rest.ApiClient.GetChannelAsync(channel.Value.Id).ConfigureAwait(false).GetAwaiter().GetResult();

socketChannel = guild != null
? SocketGuildChannel.Create(guild, Discord.State, channelModel)
: (SocketChannel)SocketChannel.CreatePrivate(Discord, Discord.State, channelModel);
}


Discord.State.AddChannel(socketChannel); Discord.State.AddChannel(socketChannel);
this.channels.Add(ulong.Parse(channel.Key), socketChannel); this.channels.Add(ulong.Parse(channel.Key), socketChannel);


+ 8
- 8
src/Discord.Net/Discord.Net.nuspec View File

@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>Discord.Net.Labs</id> <id>Discord.Net.Labs</id>
<version>2.4.2$suffix$</version>
<version>2.4.3$suffix$</version>
<title>Discord.Net Labs</title> <title>Discord.Net Labs</title>
<authors>Discord.Net Contributors</authors> <authors>Discord.Net Contributors</authors>
<owners>quinchs</owners> <owners>quinchs</owners>
@@ -15,22 +15,22 @@
<dependencies> <dependencies>
<group targetFramework="net461"> <group targetFramework="net461">
<dependency id="Discord.Net.Labs.Core" version="2.4.1$suffix$" /> <dependency id="Discord.Net.Labs.Core" version="2.4.1$suffix$" />
<dependency id="Discord.Net.Labs.Rest" version="2.4.0$suffix$" />
<dependency id="Discord.Net.Labs.WebSocket" version="2.4.2$suffix$" />
<dependency id="Discord.Net.Labs.Rest" version="2.4.2$suffix$" />
<dependency id="Discord.Net.Labs.WebSocket" version="2.4.3$suffix$" />
<dependency id="Discord.Net.Labs.Commands" version="2.3.5$suffix$" /> <dependency id="Discord.Net.Labs.Commands" version="2.3.5$suffix$" />
<dependency id="Discord.Net.Labs.Webhook" version="2.3.4$suffix$" /> <dependency id="Discord.Net.Labs.Webhook" version="2.3.4$suffix$" />
</group> </group>
<group targetFramework="netstandard2.0"> <group targetFramework="netstandard2.0">
<dependency id="Discord.Net.Labs.Core" version="2.4.1$suffix$" />
<dependency id="Discord.Net.Labs.Rest" version="2.4.0$suffix$" />
<dependency id="Discord.Net.Labs.WebSocket" version="2.4.2$suffix$" />
<dependency id="Discord.Net.Labs.Core" version="2.4.1$suffix$" />
<dependency id="Discord.Net.Labs.Rest" version="2.4.2$suffix$" />
<dependency id="Discord.Net.Labs.WebSocket" version="2.4.3$suffix$" />
<dependency id="Discord.Net.Labs.Commands" version="2.3.5$suffix$" /> <dependency id="Discord.Net.Labs.Commands" version="2.3.5$suffix$" />
<dependency id="Discord.Net.Labs.Webhook" version="2.3.4$suffix$" /> <dependency id="Discord.Net.Labs.Webhook" version="2.3.4$suffix$" />
</group> </group>
<group targetFramework="netstandard2.1"> <group targetFramework="netstandard2.1">
<dependency id="Discord.Net.Labs.Core" version="2.4.1$suffix$" /> <dependency id="Discord.Net.Labs.Core" version="2.4.1$suffix$" />
<dependency id="Discord.Net.Labs.Rest" version="2.4.0$suffix$" />
<dependency id="Discord.Net.Labs.WebSocket" version="2.4.2$suffix$" />
<dependency id="Discord.Net.Labs.Rest" version="2.4.2$suffix$" />
<dependency id="Discord.Net.Labs.WebSocket" version="2.4.3$suffix$" />
<dependency id="Discord.Net.Labs.Commands" version="2.3.5$suffix$" /> <dependency id="Discord.Net.Labs.Commands" version="2.3.5$suffix$" />
<dependency id="Discord.Net.Labs.Webhook" version="2.3.4$suffix$" /> <dependency id="Discord.Net.Labs.Webhook" version="2.3.4$suffix$" />
</group> </group>


Loading…
Cancel
Save