| @@ -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"/> | |||
| </summary> | |||
| </member> | |||
| <member name="P:Discord.IApplicationCommand.Id"> | |||
| <summary> | |||
| Gets the unique id of the command. | |||
| </summary> | |||
| </member> | |||
| <member name="P:Discord.IApplicationCommand.ApplicationId"> | |||
| <summary> | |||
| Gets the unique id of the parent application. | |||
| @@ -3987,6 +3982,11 @@ | |||
| The description of the command. | |||
| </summary> | |||
| </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"> | |||
| <summary> | |||
| 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. | |||
| </summary> | |||
| </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"> | |||
| <summary> | |||
| 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> | |||
| <returns>The current builder.</returns> | |||
| </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[])"> | |||
| <summary> | |||
| 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. | |||
| </summary> | |||
| </member> | |||
| <member name="P:Discord.ApplicationCommandPermission.Id"> | |||
| <member name="P:Discord.ApplicationCommandPermission.TargetId"> | |||
| <summary> | |||
| The id of the role or user. | |||
| </summary> | |||
| </member> | |||
| <member name="P:Discord.ApplicationCommandPermission.Type"> | |||
| <member name="P:Discord.ApplicationCommandPermission.TargetType"> | |||
| <summary> | |||
| The target of this permission. | |||
| </summary> | |||
| </member> | |||
| <member name="P:Discord.ApplicationCommandPermission.Value"> | |||
| <member name="P:Discord.ApplicationCommandPermission.Permission"> | |||
| <summary> | |||
| <see langword="true"/> to allow, otherwise <see langword="false"/>. | |||
| </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})"> | |||
| <summary> Creates a new <see cref="T:Discord.ChannelPermissions"/> from this one, changing the provided non-null permissions. </summary> | |||
| </member> | |||
| <member name="T:Discord.GuildApplicationCommandPermissions"> | |||
| <member name="T:Discord.GuildApplicationCommandPermission"> | |||
| <summary> | |||
| Returned when fetching the permissions for a command in a guild. | |||
| </summary> | |||
| </member> | |||
| <member name="P:Discord.GuildApplicationCommandPermissions.Id"> | |||
| <member name="P:Discord.GuildApplicationCommandPermission.CommandId"> | |||
| <summary> | |||
| The id of the command. | |||
| </summary> | |||
| </member> | |||
| <member name="P:Discord.GuildApplicationCommandPermissions.ApplicationId"> | |||
| <member name="P:Discord.GuildApplicationCommandPermission.ApplicationId"> | |||
| <summary> | |||
| The id of the application the command belongs to. | |||
| </summary> | |||
| </member> | |||
| <member name="P:Discord.GuildApplicationCommandPermissions.GuildId"> | |||
| <member name="P:Discord.GuildApplicationCommandPermission.GuildId"> | |||
| <summary> | |||
| The id of the guild. | |||
| </summary> | |||
| </member> | |||
| <member name="P:Discord.GuildApplicationCommandPermissions.Permissions"> | |||
| <member name="P:Discord.GuildApplicationCommandPermission.Permissions"> | |||
| <summary> | |||
| The permissions for the command in the guild. | |||
| </summary> | |||
| @@ -8,10 +8,10 @@ namespace Discord | |||
| /// <summary> | |||
| /// The target of the permission is a role. | |||
| /// </summary> | |||
| Role = 0, | |||
| Role = 1, | |||
| /// <summary> | |||
| /// The target of the permission is a user. | |||
| /// </summary> | |||
| User = 1, | |||
| User = 2, | |||
| } | |||
| } | |||
| @@ -11,11 +11,6 @@ namespace Discord | |||
| /// </summary> | |||
| public interface IApplicationCommand : ISnowflakeEntity | |||
| { | |||
| /// <summary> | |||
| /// Gets the unique id of the command. | |||
| /// </summary> | |||
| ulong Id { get; } | |||
| /// <summary> | |||
| /// Gets the unique id of the parent application. | |||
| /// </summary> | |||
| @@ -31,6 +26,11 @@ namespace Discord | |||
| /// </summary> | |||
| string Description { get; } | |||
| /// <summary> | |||
| /// Whether the command is enabled by default when the app is added to a guild. | |||
| /// </summary> | |||
| bool DefaultPermission { get; } | |||
| /// <summary> | |||
| /// If the option is a subcommand or subcommand group type, this nested options will be the parameters. | |||
| /// </summary> | |||
| @@ -82,6 +82,12 @@ namespace Discord | |||
| _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 _description { get; set; } | |||
| private List<SlashCommandOptionBuilder> _options { get; set; } | |||
| @@ -96,6 +102,7 @@ namespace Discord | |||
| { | |||
| Name = this.Name, | |||
| Description = this.Description, | |||
| DefaultPermission = this.DefaultPermission | |||
| }; | |||
| if (this.Options != null && this.Options.Any()) | |||
| @@ -135,6 +142,17 @@ namespace Discord | |||
| 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> | |||
| /// Adds an option to the current slash command. | |||
| /// </summary> | |||
| @@ -8,17 +8,17 @@ namespace Discord | |||
| /// <summary> | |||
| /// The id of the role or user. | |||
| /// </summary> | |||
| public ulong Id { get; } | |||
| public ulong TargetId { get; } | |||
| /// <summary> | |||
| /// The target of this permission. | |||
| /// </summary> | |||
| public PermissionTarget Type { get; } | |||
| public PermissionTarget TargetType { get; } | |||
| /// <summary> | |||
| /// <see langword="true"/> to allow, otherwise <see langword="false"/>. | |||
| /// </summary> | |||
| public bool Value { get; } | |||
| public bool Permission { get; } | |||
| internal ApplicationCommandPermission() { } | |||
| @@ -30,9 +30,9 @@ namespace Discord | |||
| /// <param name="allow">The value of this permission.</param> | |||
| 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> | |||
| @@ -42,9 +42,9 @@ namespace Discord | |||
| /// <param name="allow">The value of this permission.</param> | |||
| 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> | |||
| @@ -54,9 +54,9 @@ namespace Discord | |||
| /// <param name="allow">The value of this permission.</param> | |||
| 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; | |||
| } | |||
| } | |||
| } | |||
| @@ -9,12 +9,13 @@ namespace Discord | |||
| /// <summary> | |||
| /// Returned when fetching the permissions for a command in a guild. | |||
| /// </summary> | |||
| public class GuildApplicationCommandPermissions | |||
| public class GuildApplicationCommandPermission | |||
| { | |||
| /// <summary> | |||
| /// The id of the command. | |||
| /// </summary> | |||
| public ulong Id { get; } | |||
| public ulong CommandId { get; } | |||
| /// <summary> | |||
| /// The id of the application the command belongs to. | |||
| @@ -31,12 +32,12 @@ namespace Discord | |||
| /// </summary> | |||
| 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.GuildId = guildId; | |||
| this.Permissions = permissions.ToReadOnlyCollection(); | |||
| this.Permissions = permissions; | |||
| } | |||
| } | |||
| } | |||
| @@ -19,5 +19,7 @@ namespace Discord.API | |||
| public string Description { get; set; } | |||
| [JsonProperty("options")] | |||
| public Optional<ApplicationCommandOption[]> Options { get; set; } | |||
| [JsonProperty("default_permission")] | |||
| public Optional<bool> DefaultPermissions { get; set; } | |||
| } | |||
| } | |||
| @@ -7,7 +7,7 @@ using System.Threading.Tasks; | |||
| namespace Discord.API | |||
| { | |||
| public class ApplicationCommandPermissions | |||
| internal class ApplicationCommandPermissions | |||
| { | |||
| [JsonProperty("id")] | |||
| public ulong Id { get; set; } | |||
| @@ -7,16 +7,16 @@ using System.Threading.Tasks; | |||
| namespace Discord.API | |||
| { | |||
| public class GuildApplicationCommandPermission | |||
| internal class GuildApplicationCommandPermission | |||
| { | |||
| [JsonProperty("id")] | |||
| public ulong Id { get; } | |||
| public ulong Id { get; set; } | |||
| [JsonProperty("application_id")] | |||
| public ulong ApplicationId { get; } | |||
| public ulong ApplicationId { get; set; } | |||
| [JsonProperty("guild_id")] | |||
| public ulong GuildId { get; } | |||
| public ulong GuildId { get; set; } | |||
| [JsonProperty("permissions")] | |||
| public API.ApplicationCommandPermissions[] Permissions { get; set; } | |||
| @@ -13,6 +13,6 @@ namespace Discord.API.Rest | |||
| public ulong Id { get; set; } | |||
| [JsonProperty("permissions")] | |||
| public ApplicationCommandPermission[] Permissions { get; set; } | |||
| public ApplicationCommandPermissions[] Permissions { get; set; } | |||
| } | |||
| } | |||
| @@ -206,7 +206,7 @@ namespace Discord.Rest | |||
| 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()) | |||
| return new RestGuildCommand[0].ToImmutableArray(); | |||
| @@ -214,6 +214,7 @@ namespace Discord.Rest | |||
| 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) | |||
| => client.ApiClient.AddRoleAsync(guildId, userId, roleId, options); | |||
| @@ -9,7 +9,7 @@ | |||
| <TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0;netstandard2.1</TargetFrameworks> | |||
| <PackageIcon>Temporary.png</PackageIcon> | |||
| <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> | |||
| <RepositoryUrl>https://github.com/Discord-Net-Labs/Discord.Net-Labs</RepositoryUrl> | |||
| <AssemblyVersion>2.3.4</AssemblyVersion> | |||
| @@ -2740,6 +2740,27 @@ | |||
| <member name="M:Discord.Rest.RestGuild.LeaveAsync(Discord.RequestOptions)"> | |||
| <inheritdoc /> | |||
| </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)"> | |||
| <summary> | |||
| Gets a collection of all users banned in this guild. | |||
| @@ -3378,6 +3399,9 @@ | |||
| <member name="P:Discord.Rest.RestApplicationCommand.Description"> | |||
| <inheritdoc/> | |||
| </member> | |||
| <member name="P:Discord.Rest.RestApplicationCommand.DefaultPermission"> | |||
| <inheritdoc/> | |||
| </member> | |||
| <member name="P:Discord.Rest.RestApplicationCommand.Options"> | |||
| <summary> | |||
| The options of this command. | |||
| @@ -3391,6 +3415,9 @@ | |||
| <member name="P:Discord.Rest.RestApplicationCommand.CreatedAt"> | |||
| <inheritdoc/> | |||
| </member> | |||
| <member name="M:Discord.Rest.RestApplicationCommand.DeleteAsync(Discord.RequestOptions)"> | |||
| <inheritdoc/> | |||
| </member> | |||
| <member name="T:Discord.Rest.RestApplicationCommandChoice"> | |||
| <summary> | |||
| Represents a Rest-based implementation of <see cref="T:Discord.IApplicationCommandOptionChoice"/>. | |||
| @@ -3488,6 +3515,38 @@ | |||
| The modified command | |||
| </returns> | |||
| </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"> | |||
| <inheritdoc /> | |||
| </member> | |||
| @@ -827,54 +827,14 @@ namespace Discord.API | |||
| 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) | |||
| { | |||
| 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); | |||
| 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) | |||
| { | |||
| @@ -883,7 +843,14 @@ namespace Discord.API | |||
| 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); | |||
| @@ -891,49 +858,27 @@ namespace Discord.API | |||
| 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); | |||
| 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) | |||
| { | |||
| 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); | |||
| 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); | |||
| } | |||
| 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 | |||
| public async Task CreateInteractionResponse(InteractionResponse response, ulong interactionId, string interactionToken, RequestOptions options = null) | |||
| { | |||
| @@ -971,7 +925,7 @@ namespace Discord.API | |||
| 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) | |||
| { | |||
| @@ -1037,7 +991,7 @@ namespace Discord.API | |||
| 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) | |||
| @@ -1047,37 +1001,27 @@ namespace Discord.API | |||
| 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(commandId, 0, nameof(commandId)); | |||
| 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.NotNull(permissions, nameof(permissions)); | |||
| 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 | |||
| @@ -1772,6 +1716,27 @@ namespace Discord.API | |||
| 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 | |||
| { | |||
| public ulong GuildId { get; internal set; } | |||
| @@ -106,6 +106,7 @@ namespace Discord.Rest | |||
| => ClientHelper.GetVoiceRegionAsync(this, id, options); | |||
| public Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null) | |||
| => ClientHelper.GetWebhookAsync(this, id, options); | |||
| public Task<RestGlobalCommand> CreateGlobalCommand(SlashCommandCreationProperties properties, RequestOptions options = null) | |||
| => InteractionHelper.CreateGlobalCommand(this, properties, options); | |||
| public Task<RestGlobalCommand> CreateGlobalCommand(Action<SlashCommandCreationProperties> func, RequestOptions options = null) | |||
| @@ -118,6 +119,14 @@ namespace Discord.Rest | |||
| => ClientHelper.GetGlobalApplicationCommands(this, options); | |||
| public Task<IReadOnlyCollection<RestGuildCommand>> GetGuildApplicationCommands(ulong guildId, RequestOptions options = null) | |||
| => ClientHelper.GetGuildApplicationCommands(this, guildId, options); | |||
| public Task<IReadOnlyCollection<RestGlobalCommand>> BulkOverwriteGlobalCommands(SlashCommandCreationProperties[] commandProperties, RequestOptions options = null) | |||
| => 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) | |||
| => ClientHelper.AddRoleAsync(this, guildId, userId, roleId); | |||
| public Task RemoveRoleAsync(ulong guildId, ulong userId, ulong roleId) | |||
| @@ -270,6 +270,20 @@ namespace Discord.Rest | |||
| 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 | |||
| public static async Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(IGuild guild, BaseDiscordClient client, | |||
| RequestOptions options) | |||
| @@ -255,7 +255,30 @@ namespace Discord.Rest | |||
| public Task LeaveAsync(RequestOptions options = null) | |||
| => 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 | |||
| /// <summary> | |||
| /// Gets a collection of all users banned in this guild. | |||
| @@ -10,20 +10,20 @@ namespace Discord.Rest | |||
| { | |||
| 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) | |||
| { | |||
| 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) | |||
| { | |||
| var model = await client.ApiClient.GetInteractionResponse(interaction.Token, options).ConfigureAwait(false); | |||
| 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) | |||
| { | |||
| 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); | |||
| return entity; | |||
| } | |||
| // Global commands | |||
| internal static async Task<RestGlobalCommand> CreateGlobalCommand(BaseDiscordClient client, | |||
| public static async Task<RestGlobalCommand> CreateGlobalCommand(BaseDiscordClient client, | |||
| Action<SlashCommandCreationProperties> func, RequestOptions options = null) | |||
| { | |||
| var args = new SlashCommandCreationProperties(); | |||
| func(args); | |||
| 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() | |||
| { | |||
| 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, | |||
| DefaultPermission = args.DefaultPermission.IsSpecified | |||
| ? args.DefaultPermission.Value | |||
| DefaultPermission = arg.DefaultPermission.IsSpecified | |||
| ? arg.DefaultPermission.Value | |||
| : Optional<bool>.Unspecified | |||
| }; | |||
| var cmd = await client.ApiClient.CreateGlobalApplicationCommandAsync(model, options).ConfigureAwait(false); | |||
| 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) | |||
| { | |||
| 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.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.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.NotEqual(command.Id, 0, nameof(command.Id)); | |||
| @@ -105,7 +186,7 @@ namespace Discord.Rest | |||
| } | |||
| // 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) | |||
| { | |||
| var args = new SlashCommandCreationProperties(); | |||
| @@ -113,19 +194,23 @@ namespace Discord.Rest | |||
| 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) | |||
| { | |||
| Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name)); | |||
| Preconditions.NotNullOrEmpty(args.Description, nameof(args.Description)); | |||
| Preconditions.AtMost(args.Name.Length, 32, nameof(args.Name)); | |||
| Preconditions.AtLeast(args.Name.Length, 3, nameof(args.Name)); | |||
| Preconditions.AtMost(args.Description.Length, 100, nameof(args.Description)); | |||
| Preconditions.AtLeast(args.Description.Length, 1, nameof(args.Description)); | |||
| if (args.Options.IsSpecified) | |||
| { | |||
| if (args.Options.Value.Count > 10) | |||
| throw new ArgumentException("Option count must be 10 or less"); | |||
| foreach(var item in args.Options.Value) | |||
| foreach (var item in args.Options.Value) | |||
| { | |||
| Preconditions.NotNullOrEmpty(item.Name, nameof(item.Name)); | |||
| 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); | |||
| 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) | |||
| { | |||
| 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.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.Value.Count > 10) | |||
| @@ -176,15 +272,15 @@ namespace Discord.Rest | |||
| 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.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) | |||
| { | |||
| var args = new MessageProperties(); | |||
| @@ -204,10 +300,10 @@ namespace Discord.Rest | |||
| 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); | |||
| 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) | |||
| { | |||
| var args = new MessageProperties(); | |||
| @@ -227,16 +323,87 @@ namespace Discord.Rest | |||
| 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); | |||
| // 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(); | |||
| } | |||
| } | |||
| } | |||
| @@ -22,6 +22,9 @@ namespace Discord.Rest | |||
| /// <inheritdoc/> | |||
| public string Description { get; private set; } | |||
| /// <inheritdoc/> | |||
| public bool DefaultPermission { get; private set; } | |||
| /// <summary> | |||
| /// The options of this command. | |||
| /// </summary> | |||
| @@ -58,14 +61,18 @@ namespace Discord.Rest | |||
| this.ApplicationId = model.ApplicationId; | |||
| this.Name = model.Name; | |||
| this.Description = model.Description; | |||
| this.DefaultPermission = model.DefaultPermissions.GetValueOrDefault(true); | |||
| this.Options = model.Options.IsSpecified | |||
| ? model.Options.Value.Select(x => RestApplicationCommandOption.Create(x)).ToImmutableArray() | |||
| : null; | |||
| } | |||
| /// <inheritdoc/> | |||
| public abstract Task DeleteAsync(RequestOptions options = null); | |||
| IReadOnlyCollection<IApplicationCommandOption> IApplicationCommand.Options => Options; | |||
| public virtual Task DeleteAsync(RequestOptions options = null) => throw new NotImplementedException(); | |||
| } | |||
| } | |||
| @@ -33,7 +33,7 @@ namespace Discord.Rest | |||
| /// <inheritdoc/> | |||
| public override async Task DeleteAsync(RequestOptions options = null) | |||
| => await InteractionHelper.DeleteGuildCommand(Discord, this).ConfigureAwait(false); | |||
| => await InteractionHelper.DeleteGuildCommand(Discord, GuildId, this).ConfigureAwait(false); | |||
| /// <summary> | |||
| /// Modifies this <see cref="RestApplicationCommand"/>. | |||
| @@ -46,7 +46,39 @@ namespace Discord.Rest | |||
| public async Task<RestGuildCommand> ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null) | |||
| => 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); | |||
| } | |||
| } | |||
| @@ -26,5 +26,8 @@ namespace Discord.API.Gateway | |||
| [JsonProperty("options")] | |||
| public Optional<List<Discord.API.ApplicationCommandOption>> Options { get; set; } | |||
| [JsonProperty("default_permission")] | |||
| public Optional<bool> DefaultPermission { get; set; } | |||
| } | |||
| } | |||
| @@ -2843,6 +2843,27 @@ | |||
| voice regions the guild can access. | |||
| </returns> | |||
| </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)"> | |||
| <summary> | |||
| Gets a collection of all invites in this guild. | |||
| @@ -3243,6 +3264,9 @@ | |||
| <member name="P:Discord.WebSocket.SocketApplicationCommand.Description"> | |||
| <inheritdoc/> | |||
| </member> | |||
| <member name="P:Discord.WebSocket.SocketApplicationCommand.DefaultPermission"> | |||
| <inheritdoc/> | |||
| </member> | |||
| <member name="P:Discord.WebSocket.SocketApplicationCommand.Options"> | |||
| <summary> | |||
| 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. | |||
| </summary> | |||
| </member> | |||
| <member name="M:Discord.WebSocket.SocketApplicationCommand.DeleteAsync(Discord.RequestOptions)"> | |||
| <inheritdoc/> | |||
| </member> | |||
| <member name="T:Discord.WebSocket.SocketApplicationCommandChoice"> | |||
| <summary> | |||
| Represents a choice for a <see cref="T:Discord.WebSocket.SocketApplicationCommandOption"/>. | |||
| @@ -723,6 +723,30 @@ namespace Discord.WebSocket | |||
| public Task<RestGuildIntegration> CreateIntegrationAsync(ulong id, string type, RequestOptions options = null) | |||
| => 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 | |||
| /// <summary> | |||
| /// Gets a collection of all invites in this guild. | |||
| @@ -1,3 +1,4 @@ | |||
| using Discord.Rest; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| @@ -22,6 +23,9 @@ namespace Discord.WebSocket | |||
| /// <inheritdoc/> | |||
| public string Description { get; private set; } | |||
| /// <inheritdoc/> | |||
| public bool DefaultPermission { get; private set; } | |||
| /// <summary> | |||
| /// A collection of <see cref="SocketApplicationCommandOption"/>'s recieved over the gateway. | |||
| /// </summary> | |||
| @@ -56,13 +60,18 @@ namespace Discord.WebSocket | |||
| this.Description = model.Description; | |||
| this.Name = model.Name; | |||
| this.GuildId = model.GuildId; | |||
| this.DefaultPermission = model.DefaultPermission.GetValueOrDefault(true); | |||
| this.Options = model.Options.IsSpecified | |||
| ? model.Options.Value.Select(x => SocketApplicationCommandOption.Create(x)).ToImmutableArray() | |||
| : 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; | |||
| } | |||
| } | |||
| @@ -54,9 +54,20 @@ namespace Discord.WebSocket | |||
| { | |||
| 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); | |||
| this.channels.Add(ulong.Parse(channel.Key), socketChannel); | |||
| @@ -2,7 +2,7 @@ | |||
| <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> | |||
| <metadata> | |||
| <id>Discord.Net.Labs</id> | |||
| <version>2.4.2$suffix$</version> | |||
| <version>2.4.3$suffix$</version> | |||
| <title>Discord.Net Labs</title> | |||
| <authors>Discord.Net Contributors</authors> | |||
| <owners>quinchs</owners> | |||
| @@ -15,22 +15,22 @@ | |||
| <dependencies> | |||
| <group targetFramework="net461"> | |||
| <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.Webhook" version="2.3.4$suffix$" /> | |||
| </group> | |||
| <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.Webhook" version="2.3.4$suffix$" /> | |||
| </group> | |||
| <group targetFramework="netstandard2.1"> | |||
| <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.Webhook" version="2.3.4$suffix$" /> | |||
| </group> | |||