Added SocketApplicationCommands, Added method in SocketGuild to fetch that guilds ApplicationCommands. Tested all rest routes and fixed them accordingly. Did more testing and I think its ready to gopull/1717/head
@@ -0,0 +1,72 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord | |||||
{ | |||||
/// <summary> | |||||
/// Represents a <see cref="IApplicationCommandOption"/> for making slash commands. | |||||
/// </summary> | |||||
public class ApplicationCommandOptionProperties | |||||
{ | |||||
private string _name; | |||||
private string _description; | |||||
/// <summary> | |||||
/// The name of this option. | |||||
/// </summary> | |||||
public string Name | |||||
{ | |||||
get => _name; | |||||
set | |||||
{ | |||||
if (value?.Length > 32) | |||||
throw new ArgumentException("Name length must be less than or equal to 32"); | |||||
_name = value; | |||||
} | |||||
} | |||||
/// <summary> | |||||
/// The description of this option. | |||||
/// </summary> | |||||
public string Description | |||||
{ | |||||
get => _description; | |||||
set | |||||
{ | |||||
if (value?.Length > 100) | |||||
throw new ArgumentException("Name length must be less than or equal to 32"); | |||||
_description = value; | |||||
} | |||||
} | |||||
/// <summary> | |||||
/// The type of this option. | |||||
/// </summary> | |||||
public ApplicationCommandOptionType Type { get; set; } | |||||
/// <summary> | |||||
/// The first required option for the user to complete. only one option can be default. | |||||
/// </summary> | |||||
public bool? Default { get; set; } | |||||
/// <summary> | |||||
/// <see langword="true"/> if this option is required for this command, otherwise <see langword="false"/>. | |||||
/// </summary> | |||||
public bool? Required { get; set; } | |||||
/// <summary> | |||||
/// choices for string and int types for the user to pick from | |||||
/// </summary> | |||||
public List<ApplicationCommandOptionChoiceProperties> Choices { get; set; } | |||||
/// <summary> | |||||
/// If the option is a subcommand or subcommand group type, this nested options will be the parameters. | |||||
/// </summary> | |||||
public List<ApplicationCommandOptionProperties> Options { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,49 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord | |||||
{ | |||||
/// <summary> | |||||
/// Represents a choice for a <see cref="IApplicationCommandInteractionDataOption"/>. This class is used when making new commands | |||||
/// </summary> | |||||
public class ApplicationCommandOptionChoiceProperties | |||||
{ | |||||
private string _name; | |||||
private object _value; | |||||
/// <summary> | |||||
/// The name of this choice | |||||
/// </summary> | |||||
public string Name | |||||
{ | |||||
get => _name; | |||||
set | |||||
{ | |||||
if(value?.Length > 100) | |||||
throw new ArgumentException("Name length must be less than or equal to 100"); | |||||
_name = value; | |||||
} | |||||
} | |||||
// Note: discord allows strings & ints as values. how should that be handled? | |||||
// should we make this an object and then just type check it? | |||||
/// <summary> | |||||
/// The value of this choice | |||||
/// </summary> | |||||
public object Value | |||||
{ | |||||
get => _value; | |||||
set | |||||
{ | |||||
if(value != null) | |||||
{ | |||||
if(!(value is int) && !(value is string)) | |||||
throw new ArgumentException("The value of a choice must be a string or int!"); | |||||
} | |||||
_value = value; | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -11,41 +11,20 @@ namespace Discord | |||||
/// </summary> | /// </summary> | ||||
public class ApplicationCommandProperties | public class ApplicationCommandProperties | ||||
{ | { | ||||
private string _name { get; set; } | |||||
private string _description { get; set; } | |||||
/// <summary> | /// <summary> | ||||
/// Gets or sets the name of this command. | /// Gets or sets the name of this command. | ||||
/// </summary> | /// </summary> | ||||
public string Name | |||||
{ | |||||
get => _name; | |||||
set | |||||
{ | |||||
if(value.Length > 32) | |||||
throw new ArgumentException("Name length must be less than or equal to 32"); | |||||
_name = value; | |||||
} | |||||
} | |||||
public Optional<string> Name { get; set; } | |||||
/// <summary> | /// <summary> | ||||
/// Gets or sets the discription of this command. | /// Gets or sets the discription of this command. | ||||
/// </summary> | /// </summary> | ||||
public string Description | |||||
{ | |||||
get => _description; | |||||
set | |||||
{ | |||||
if (value.Length > 100) | |||||
throw new ArgumentException("Description length must be less than or equal to 100"); | |||||
_description = value; | |||||
} | |||||
} | |||||
public Optional<string> Description { get; set; } | |||||
/// <summary> | /// <summary> | ||||
/// Gets or sets the options for this command. | /// Gets or sets the options for this command. | ||||
/// </summary> | /// </summary> | ||||
public Optional<List<IApplicationCommandOption>> Options { get; set; } | |||||
public Optional<List<ApplicationCommandOptionProperties>> Options { get; set; } | |||||
} | } | ||||
} | } |
@@ -22,7 +22,7 @@ namespace Discord | |||||
/// This objects type can be any one of the option types in <see cref="ApplicationCommandOptionType"/> | /// This objects type can be any one of the option types in <see cref="ApplicationCommandOptionType"/> | ||||
/// </note> | /// </note> | ||||
/// </summary> | /// </summary> | ||||
object? Value { get; } | |||||
object Value { get; } | |||||
/// <summary> | /// <summary> | ||||
/// Present if this option is a group or subcommand. | /// Present if this option is a group or subcommand. | ||||
@@ -42,7 +42,7 @@ namespace Discord | |||||
IReadOnlyCollection<IApplicationCommandOptionChoice>? Choices { get; } | IReadOnlyCollection<IApplicationCommandOptionChoice>? Choices { 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> | ||||
IReadOnlyCollection<IApplicationCommandOption>? Options { get; } | IReadOnlyCollection<IApplicationCommandOption>? Options { get; } | ||||
} | } | ||||
@@ -19,7 +19,7 @@ namespace Discord | |||||
/// <summary> | /// <summary> | ||||
/// value of the choice. | /// value of the choice. | ||||
/// </summary> | /// </summary> | ||||
string Value { get; } | |||||
object Value { get; } | |||||
} | } | ||||
} | } |
@@ -0,0 +1,30 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord | |||||
{ | |||||
/// <summary> | |||||
/// A class used to create slash commands | |||||
/// </summary> | |||||
public class SlashCommandCreationProperties | |||||
{ | |||||
/// <summary> | |||||
/// The name of this command. | |||||
/// </summary> | |||||
public string Name { get; set; } | |||||
/// <summary> | |||||
/// The discription of this command. | |||||
/// </summary> | |||||
public string Description { get; set; } | |||||
/// <summary> | |||||
/// Gets or sets the options for this command. | |||||
/// </summary> | |||||
public Optional<List<ApplicationCommandOptionProperties>> Options { get; set; } | |||||
} | |||||
} |
@@ -53,5 +53,28 @@ namespace Discord.API | |||||
this.Type = cmd.Type; | this.Type = cmd.Type; | ||||
this.Description = cmd.Description; | this.Description = cmd.Description; | ||||
} | } | ||||
public ApplicationCommandOption(Discord.ApplicationCommandOptionProperties option) | |||||
{ | |||||
this.Choices = option.Choices != null | |||||
? option.Choices.Select(x => new ApplicationCommandOptionChoice() | |||||
{ | |||||
Name = x.Name, | |||||
Value = x.Value | |||||
}).ToArray() | |||||
: Optional<ApplicationCommandOptionChoice[]>.Unspecified; | |||||
this.Options = option.Options != null | |||||
? option.Options.Select(x => new ApplicationCommandOption(x)).ToArray() | |||||
: Optional<ApplicationCommandOption[]>.Unspecified; | |||||
this.Required = option.Required.Value; | |||||
this.Default = option.Default.HasValue | |||||
? option.Default.Value | |||||
: Optional<bool>.Unspecified; | |||||
this.Name = option.Name; | |||||
this.Type = option.Type; | |||||
this.Description = option.Description; | |||||
} | |||||
} | } | ||||
} | } |
@@ -13,6 +13,6 @@ namespace Discord.API | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("value")] | [JsonProperty("value")] | ||||
public string Value { get; set; } | |||||
public object Value { get; set; } | |||||
} | } | ||||
} | } |
@@ -8,7 +8,7 @@ using System.Threading.Tasks; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
internal class ApplicationCommandParams | |||||
internal class CreateApplicationCommandParams | |||||
{ | { | ||||
[JsonProperty("name")] | [JsonProperty("name")] | ||||
public string Name { get; set; } | public string Name { get; set; } | ||||
@@ -19,8 +19,8 @@ namespace Discord.API.Rest | |||||
[JsonProperty("options")] | [JsonProperty("options")] | ||||
public Optional<ApplicationCommandOption[]> Options { get; set; } | public Optional<ApplicationCommandOption[]> Options { get; set; } | ||||
public ApplicationCommandParams() { } | |||||
public ApplicationCommandParams(string name, string description, ApplicationCommandOption[] options = null) | |||||
public CreateApplicationCommandParams() { } | |||||
public CreateApplicationCommandParams(string name, string description, ApplicationCommandOption[] options = null) | |||||
{ | { | ||||
this.Name = name; | this.Name = name; | ||||
this.Description = description; | this.Description = description; |
@@ -0,0 +1,21 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord.API.Rest | |||||
{ | |||||
internal class ModifyApplicationCommandParams | |||||
{ | |||||
[JsonProperty("name")] | |||||
public Optional<string> Name { get; set; } | |||||
[JsonProperty("description")] | |||||
public Optional<string> Description { get; set; } | |||||
[JsonProperty("options")] | |||||
public Optional<ApplicationCommandOption[]> Options { get; set; } | |||||
} | |||||
} |
@@ -202,23 +202,23 @@ namespace Discord.Rest | |||||
}; | }; | ||||
} | } | ||||
public static async Task<RestGlobalCommand[]> GetGlobalApplicationCommands(BaseDiscordClient client, RequestOptions options) | |||||
public static async Task<IReadOnlyCollection<RestGlobalCommand>> GetGlobalApplicationCommands(BaseDiscordClient client, RequestOptions options) | |||||
{ | { | ||||
var response = await client.ApiClient.GetGlobalApplicationCommandsAsync(options).ConfigureAwait(false); | var response = await client.ApiClient.GetGlobalApplicationCommandsAsync(options).ConfigureAwait(false); | ||||
if (!response.Any()) | if (!response.Any()) | ||||
return null; | |||||
return new RestGlobalCommand[0]; | |||||
return response.Select(x => RestGlobalCommand.Create(client, x)).ToArray(); | return response.Select(x => RestGlobalCommand.Create(client, x)).ToArray(); | ||||
} | } | ||||
public static async Task<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.GetGuildApplicationCommandAsync(guildId, options).ConfigureAwait(false); | ||||
if (!response.Any()) | if (!response.Any()) | ||||
return null; | |||||
return new RestGuildCommand[0].ToImmutableArray(); | |||||
return response.Select(x => RestGuildCommand.Create(client, x, guildId)).ToArray(); | |||||
return response.Select(x => RestGuildCommand.Create(client, x, guildId)).ToImmutableArray(); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -46,7 +46,7 @@ namespace Discord.API | |||||
internal IRestClient RestClient { get; private set; } | internal IRestClient RestClient { get; private set; } | ||||
internal ulong? CurrentUserId { get; set; } | internal ulong? CurrentUserId { get; set; } | ||||
public RateLimitPrecision RateLimitPrecision { get; private set; } | public RateLimitPrecision RateLimitPrecision { get; private set; } | ||||
internal bool UseSystemClock { get; set; } | |||||
internal bool UseSystemClock { get; set; } | |||||
internal JsonSerializer Serializer => _serializer; | internal JsonSerializer Serializer => _serializer; | ||||
/// <exception cref="ArgumentException">Unknown OAuth token type.</exception> | /// <exception cref="ArgumentException">Unknown OAuth token type.</exception> | ||||
@@ -58,7 +58,7 @@ namespace Discord.API | |||||
DefaultRetryMode = defaultRetryMode; | DefaultRetryMode = defaultRetryMode; | ||||
_serializer = serializer ?? new JsonSerializer { ContractResolver = new DiscordContractResolver() }; | _serializer = serializer ?? new JsonSerializer { ContractResolver = new DiscordContractResolver() }; | ||||
RateLimitPrecision = rateLimitPrecision; | RateLimitPrecision = rateLimitPrecision; | ||||
UseSystemClock = useSystemClock; | |||||
UseSystemClock = useSystemClock; | |||||
RequestQueue = new RequestQueue(); | RequestQueue = new RequestQueue(); | ||||
_stateLock = new SemaphoreSlim(1, 1); | _stateLock = new SemaphoreSlim(1, 1); | ||||
@@ -262,8 +262,8 @@ namespace Discord.API | |||||
CheckState(); | CheckState(); | ||||
if (request.Options.RetryMode == null) | if (request.Options.RetryMode == null) | ||||
request.Options.RetryMode = DefaultRetryMode; | request.Options.RetryMode = DefaultRetryMode; | ||||
if (request.Options.UseSystemClock == null) | |||||
request.Options.UseSystemClock = UseSystemClock; | |||||
if (request.Options.UseSystemClock == null) | |||||
request.Options.UseSystemClock = UseSystemClock; | |||||
var stopwatch = Stopwatch.StartNew(); | var stopwatch = Stopwatch.StartNew(); | ||||
var responseStream = await RequestQueue.SendAsync(request).ConfigureAwait(false); | var responseStream = await RequestQueue.SendAsync(request).ConfigureAwait(false); | ||||
@@ -787,9 +787,14 @@ namespace Discord.API | |||||
//Interactions | //Interactions | ||||
public async Task<ApplicationCommand[]> GetGlobalApplicationCommandsAsync(RequestOptions options = null) | public async Task<ApplicationCommand[]> GetGlobalApplicationCommandsAsync(RequestOptions options = null) | ||||
=> await SendAsync<ApplicationCommand[]>("GET", $"applications/{this.CurrentUserId}/commands", options: options).ConfigureAwait(false); | |||||
{ | |||||
options = RequestOptions.CreateOrClone(options); | |||||
return await SendAsync<ApplicationCommand[]>("GET", () => $"applications/{this.CurrentUserId}/commands", new BucketIds(), options: options).ConfigureAwait(false); | |||||
} | |||||
public async Task<ApplicationCommand> CreateGlobalApplicationCommandAsync(ApplicationCommandParams command, RequestOptions options = null) | |||||
public async Task<ApplicationCommand> CreateGlobalApplicationCommandAsync(CreateApplicationCommandParams command, RequestOptions options = null) | |||||
{ | { | ||||
Preconditions.NotNull(command, nameof(command)); | Preconditions.NotNull(command, nameof(command)); | ||||
Preconditions.AtMost(command.Name.Length, 32, nameof(command.Name)); | Preconditions.AtMost(command.Name.Length, 32, nameof(command.Name)); | ||||
@@ -797,24 +802,45 @@ namespace Discord.API | |||||
Preconditions.AtMost(command.Description.Length, 100, nameof(command.Description)); | Preconditions.AtMost(command.Description.Length, 100, nameof(command.Description)); | ||||
Preconditions.AtLeast(command.Description.Length, 1, nameof(command.Description)); | Preconditions.AtLeast(command.Description.Length, 1, nameof(command.Description)); | ||||
return await SendJsonAsync<ApplicationCommand>("POST", $"applications/{this.CurrentUserId}/commands", command, options: options).ConfigureAwait(false); | |||||
options = RequestOptions.CreateOrClone(options); | |||||
return await SendJsonAsync<ApplicationCommand>("POST", () => $"applications/{this.CurrentUserId}/commands", command, new BucketIds(), options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<ApplicationCommand> ModifyGlobalApplicationCommandAsync(ApplicationCommandParams command, ulong commandId, RequestOptions options = null) | |||||
public async Task<ApplicationCommand> ModifyGlobalApplicationCommandAsync(ModifyApplicationCommandParams command, ulong commandId, RequestOptions options = null) | |||||
{ | { | ||||
Preconditions.NotNull(command, nameof(command)); | 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)); | |||||
return await SendJsonAsync<ApplicationCommand>("PATCH", $"applications/{this.CurrentUserId}/commands/{commandId}", command, options: options).ConfigureAwait(false); | |||||
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); | |||||
return await 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) | ||||
=> await SendAsync("DELETE", $"applications/{this.CurrentUserId}/commands/{commandId}", options: options).ConfigureAwait(false); | |||||
{ | |||||
options = RequestOptions.CreateOrClone(options); | |||||
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[]> GetGuildApplicationCommandAsync(ulong guildId, RequestOptions options = null) | ||||
=> await SendAsync<ApplicationCommand[]>("GET", $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", options: options).ConfigureAwait(false); | |||||
public async Task<ApplicationCommand> CreateGuildApplicationCommandAsync(ApplicationCommandParams command, ulong guildId, RequestOptions options = null) | |||||
{ | |||||
options = RequestOptions.CreateOrClone(options); | |||||
var bucket = new BucketIds(guildId: guildId); | |||||
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) | |||||
{ | { | ||||
Preconditions.NotNull(command, nameof(command)); | Preconditions.NotNull(command, nameof(command)); | ||||
Preconditions.AtMost(command.Name.Length, 32, nameof(command.Name)); | Preconditions.AtMost(command.Name.Length, 32, nameof(command.Name)); | ||||
@@ -822,20 +848,41 @@ namespace Discord.API | |||||
Preconditions.AtMost(command.Description.Length, 100, nameof(command.Description)); | Preconditions.AtMost(command.Description.Length, 100, nameof(command.Description)); | ||||
Preconditions.AtLeast(command.Description.Length, 1, nameof(command.Description)); | Preconditions.AtLeast(command.Description.Length, 1, nameof(command.Description)); | ||||
return await SendJsonAsync<ApplicationCommand>("POST", $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", command, options: options).ConfigureAwait(false); | |||||
options = RequestOptions.CreateOrClone(options); | |||||
var bucket = new BucketIds(guildId: guildId); | |||||
return await SendJsonAsync<ApplicationCommand>("POST", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands", command, bucket, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<ApplicationCommand> ModifyGuildApplicationCommandAsync(ApplicationCommandParams 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)); | 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)); | |||||
return await SendJsonAsync<ApplicationCommand>("PATCH", $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", command, options: options).ConfigureAwait(false); | |||||
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); | |||||
return await SendJsonAsync<ApplicationCommand>("PATCH", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", command, bucket, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task DeleteGuildApplicationCommandAsync(ulong guildId, ulong commandId, RequestOptions options = null) | public async Task DeleteGuildApplicationCommandAsync(ulong guildId, ulong commandId, RequestOptions options = null) | ||||
=> await SendAsync<ApplicationCommand>("DELETE", $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", options: options).ConfigureAwait(false); | |||||
{ | |||||
options = RequestOptions.CreateOrClone(options); | |||||
var bucket = new BucketIds(guildId: guildId); | |||||
await SendAsync<ApplicationCommand>("DELETE", () => $"applications/{this.CurrentUserId}/guilds/{guildId}/commands/{commandId}", 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) | ||||
@@ -845,12 +892,20 @@ 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("POST", () => $"interactions/{interactionId}/{interactionToken}/callback", response, new BucketIds(), options: options); | |||||
} | } | ||||
public async Task ModifyInteractionResponse(ModifyInteractionResponseParams args, string interactionToken, RequestOptions options = null) | public async Task ModifyInteractionResponse(ModifyInteractionResponseParams args, string interactionToken, RequestOptions options = null) | ||||
=> await SendJsonAsync("POST", $"webhooks/{this.CurrentUserId}/{interactionToken}/messages/@original", args, options: options); | |||||
{ | |||||
options = RequestOptions.CreateOrClone(options); | |||||
await SendJsonAsync("POST", () => $"webhooks/{this.CurrentUserId}/{interactionToken}/messages/@original", args, new BucketIds(), options: options); | |||||
} | |||||
public async Task DeleteInteractionResponse(string interactionToken, RequestOptions options = null) | public async Task DeleteInteractionResponse(string interactionToken, RequestOptions options = null) | ||||
=> await SendAsync("DELETE", $"webhooks/{this.CurrentUserId}/{interactionToken}/messages/@original", options: options); | |||||
{ | |||||
options = RequestOptions.CreateOrClone(options); | |||||
await SendAsync("DELETE", () => $"webhooks/{this.CurrentUserId}/{interactionToken}/messages/@original", new BucketIds(), options: options); | |||||
} | |||||
public async Task<Message> CreateInteractionFollowupMessage(CreateWebhookMessageParams args, string token, RequestOptions options = null) | public async Task<Message> CreateInteractionFollowupMessage(CreateWebhookMessageParams args, string token, RequestOptions options = null) | ||||
{ | { | ||||
@@ -862,7 +917,7 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
return await SendJsonAsync<Message>("POST", $"webhooks/{CurrentUserId}/{token}?wait=true", args, options: options).ConfigureAwait(false); | |||||
return await SendJsonAsync<Message>("POST", () => $"webhooks/{CurrentUserId}/{token}?wait=true", args, new BucketIds(), options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<Message> ModifyInteractionFollowupMessage(CreateWebhookMessageParams args, ulong id, string token, RequestOptions options = null) | public async Task<Message> ModifyInteractionFollowupMessage(CreateWebhookMessageParams args, ulong id, string token, RequestOptions options = null) | ||||
@@ -875,7 +930,7 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
return await SendJsonAsync<Message>("PATCH", $"webhooks/{CurrentUserId}/{token}/messages/{id}", args, options: options).ConfigureAwait(false); | |||||
return await SendJsonAsync<Message>("PATCH", () => $"webhooks/{CurrentUserId}/{token}/messages/{id}", args, new BucketIds(), options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task DeleteInteractionFollowupMessage(ulong id, string token, RequestOptions options = null) | public async Task DeleteInteractionFollowupMessage(ulong id, string token, RequestOptions options = null) | ||||
@@ -884,7 +939,7 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
await SendAsync("DELETE", $"webhooks/{CurrentUserId}/{token}/messages/{id}", options: options).ConfigureAwait(false); | |||||
await SendAsync("DELETE", () => $"webhooks/{CurrentUserId}/{token}/messages/{id}", new BucketIds(), options: options).ConfigureAwait(false); | |||||
} | } | ||||
//Guilds | //Guilds | ||||
@@ -107,13 +107,17 @@ 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> CreateGobalCommand(Action<ApplicationCommandProperties> func, RequestOptions options = null) | |||||
public Task<RestGlobalCommand> CreateGlobalCommand(SlashCommandCreationProperties properties, RequestOptions options = null) | |||||
=> InteractionHelper.CreateGlobalCommand(this, properties, options); | |||||
public Task<RestGlobalCommand> CreateGlobalCommand(Action<SlashCommandCreationProperties> func, RequestOptions options = null) | |||||
=> InteractionHelper.CreateGlobalCommand(this, func, options); | => InteractionHelper.CreateGlobalCommand(this, func, options); | ||||
public Task<RestGuildCommand> CreateGuildCommand(Action<ApplicationCommandProperties> func, ulong guildId, RequestOptions options = null) | |||||
public Task<RestGuildCommand> CreateGuildCommand(SlashCommandCreationProperties properties, ulong guildId, RequestOptions options = null) | |||||
=> InteractionHelper.CreateGuildCommand(this, guildId, properties, options); | |||||
public Task<RestGuildCommand> CreateGuildCommand(Action<SlashCommandCreationProperties> func, ulong guildId, RequestOptions options = null) | |||||
=> InteractionHelper.CreateGuildCommand(this, guildId, func, options); | => InteractionHelper.CreateGuildCommand(this, guildId, func, options); | ||||
public Task<RestGlobalCommand[]> GetGlobalApplicationCommands(RequestOptions options = null) | |||||
public Task<IReadOnlyCollection<RestGlobalCommand>> GetGlobalApplicationCommands(RequestOptions options = null) | |||||
=> ClientHelper.GetGlobalApplicationCommands(this, options); | => ClientHelper.GetGlobalApplicationCommands(this, options); | ||||
public Task<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); | ||||
//IDiscordClient | //IDiscordClient | ||||
@@ -21,30 +21,35 @@ namespace Discord.Rest | |||||
// Global commands | // Global commands | ||||
internal static async Task<RestGlobalCommand> CreateGlobalCommand(BaseDiscordClient client, | internal static async Task<RestGlobalCommand> CreateGlobalCommand(BaseDiscordClient client, | ||||
Action<ApplicationCommandProperties> func, RequestOptions options = null) | |||||
Action<SlashCommandCreationProperties> func, RequestOptions options = null) | |||||
{ | { | ||||
var args = new ApplicationCommandProperties(); | |||||
var args = new SlashCommandCreationProperties(); | |||||
func(args); | func(args); | ||||
return await CreateGlobalCommand(client, args, options).ConfigureAwait(false); | |||||
} | |||||
internal static async Task<RestGlobalCommand> CreateGlobalCommand(BaseDiscordClient client, | |||||
SlashCommandCreationProperties args, RequestOptions options = null) | |||||
{ | |||||
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"); | ||||
} | } | ||||
var model = new ApplicationCommandParams() | |||||
var model = new CreateApplicationCommandParams() | |||||
{ | { | ||||
Name = args.Name, | Name = args.Name, | ||||
Description = args.Description, | Description = args.Description, | ||||
Options = args.Options.IsSpecified | Options = args.Options.IsSpecified | ||||
? args.Options.Value.Select(x => new ApplicationCommandOption(x)).ToArray() | |||||
: Optional<ApplicationCommandOption[]>.Unspecified | |||||
? args.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray() | |||||
: Optional<Discord.API.ApplicationCommandOption[]>.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, | internal static async Task<RestGlobalCommand> ModifyGlobalCommand(BaseDiscordClient client, RestGlobalCommand command, | ||||
Action<ApplicationCommandProperties> func, RequestOptions options = null) | Action<ApplicationCommandProperties> func, RequestOptions options = null) | ||||
{ | { | ||||
@@ -57,13 +62,13 @@ namespace Discord.Rest | |||||
throw new ArgumentException("Option count must be 10 or less"); | throw new ArgumentException("Option count must be 10 or less"); | ||||
} | } | ||||
var model = new Discord.API.Rest.ApplicationCommandParams() | |||||
var model = new Discord.API.Rest.ModifyApplicationCommandParams() | |||||
{ | { | ||||
Name = args.Name, | Name = args.Name, | ||||
Description = args.Description, | Description = args.Description, | ||||
Options = args.Options.IsSpecified | Options = args.Options.IsSpecified | ||||
? args.Options.Value.Select(x => new ApplicationCommandOption(x)).ToArray() | |||||
: Optional<ApplicationCommandOption[]>.Unspecified | |||||
? args.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray() | |||||
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified | |||||
}; | }; | ||||
var msg = await client.ApiClient.ModifyGlobalApplicationCommandAsync(model, command.Id, options).ConfigureAwait(false); | var msg = await client.ApiClient.ModifyGlobalApplicationCommandAsync(model, command.Id, options).ConfigureAwait(false); | ||||
@@ -82,30 +87,44 @@ namespace Discord.Rest | |||||
// Guild Commands | // Guild Commands | ||||
internal static async Task<RestGuildCommand> CreateGuildCommand(BaseDiscordClient client, ulong guildId, | internal static async Task<RestGuildCommand> CreateGuildCommand(BaseDiscordClient client, ulong guildId, | ||||
Action<ApplicationCommandProperties> func, RequestOptions options = null) | |||||
Action<SlashCommandCreationProperties> func, RequestOptions options = null) | |||||
{ | { | ||||
var args = new ApplicationCommandProperties(); | |||||
var args = new SlashCommandCreationProperties(); | |||||
func(args); | func(args); | ||||
return await CreateGuildCommand(client, guildId, args, options).ConfigureAwait(false); | |||||
} | |||||
internal 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)); | |||||
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) | |||||
{ | |||||
Preconditions.NotNullOrEmpty(item.Name, nameof(item.Name)); | |||||
Preconditions.NotNullOrEmpty(item.Description, nameof(item.Description)); | |||||
} | |||||
} | } | ||||
var model = new ApplicationCommandParams() | |||||
var model = new CreateApplicationCommandParams() | |||||
{ | { | ||||
Name = args.Name, | Name = args.Name, | ||||
Description = args.Description, | Description = args.Description, | ||||
Options = args.Options.IsSpecified | Options = args.Options.IsSpecified | ||||
? args.Options.Value.Select(x => new ApplicationCommandOption(x)).ToArray() | |||||
: Optional<ApplicationCommandOption[]>.Unspecified | |||||
? args.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray() | |||||
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified | |||||
}; | }; | ||||
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, | internal static async Task<RestGuildCommand> ModifyGuildCommand(BaseDiscordClient client, RestGuildCommand command, | ||||
Action<ApplicationCommandProperties> func, RequestOptions options = null) | Action<ApplicationCommandProperties> func, RequestOptions options = null) | ||||
{ | { | ||||
@@ -118,16 +137,16 @@ namespace Discord.Rest | |||||
throw new ArgumentException("Option count must be 10 or less"); | throw new ArgumentException("Option count must be 10 or less"); | ||||
} | } | ||||
var model = new Discord.API.Rest.ApplicationCommandParams() | |||||
var model = new Discord.API.Rest.ModifyApplicationCommandParams() | |||||
{ | { | ||||
Name = args.Name, | Name = args.Name, | ||||
Description = args.Description, | Description = args.Description, | ||||
Options = args.Options.IsSpecified | Options = args.Options.IsSpecified | ||||
? args.Options.Value.Select(x => new ApplicationCommandOption(x)).ToArray() | |||||
: Optional<ApplicationCommandOption[]>.Unspecified | |||||
? args.Options.Value.Select(x => new Discord.API.ApplicationCommandOption(x)).ToArray() | |||||
: Optional<Discord.API.ApplicationCommandOption[]>.Unspecified | |||||
}; | }; | ||||
var msg = await client.ApiClient.ModifyGuildApplicationCommandAsync(model, command.Id, command.GuildId, options).ConfigureAwait(false); | |||||
var msg = await client.ApiClient.ModifyGuildApplicationCommandAsync(model, command.GuildId, command.Id, options).ConfigureAwait(false); | |||||
command.Update(msg); | command.Update(msg); | ||||
return command; | return command; | ||||
} | } | ||||
@@ -137,7 +156,7 @@ namespace Discord.Rest | |||||
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.Id, command.GuildId, options).ConfigureAwait(false); | |||||
await client.ApiClient.DeleteGuildApplicationCommandAsync(command.GuildId, command.Id, options).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -19,9 +19,9 @@ namespace Discord.Rest | |||||
public string Description { get; private set; } | public string Description { get; private set; } | ||||
public IReadOnlyCollection<IApplicationCommandOption> Options { get; private set; } | |||||
public IReadOnlyCollection<RestApplicationCommandOption> Options { get; private set; } | |||||
public RestApplicationCommandType CommandType { get; private set; } | |||||
public RestApplicationCommandType CommandType { get; internal set; } | |||||
public DateTimeOffset CreatedAt | public DateTimeOffset CreatedAt | ||||
=> SnowflakeUtils.FromSnowflake(this.Id); | => SnowflakeUtils.FromSnowflake(this.Id); | ||||
@@ -47,12 +47,15 @@ namespace Discord.Rest | |||||
{ | { | ||||
this.ApplicationId = model.ApplicationId; | this.ApplicationId = model.ApplicationId; | ||||
this.Name = model.Name; | this.Name = model.Name; | ||||
this.Description = model.Description; | |||||
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; | ||||
} | } | ||||
IReadOnlyCollection<IApplicationCommandOption> IApplicationCommand.Options => Options; | |||||
public virtual Task DeleteAsync(RequestOptions options = null) => throw new NotImplementedException(); | public virtual Task DeleteAsync(RequestOptions options = null) => throw new NotImplementedException(); | ||||
} | } | ||||
} | } |
@@ -11,7 +11,7 @@ namespace Discord.Rest | |||||
{ | { | ||||
public string Name { get; } | public string Name { get; } | ||||
public string Value { get; } | |||||
public object Value { get; } | |||||
internal RestApplicationCommandChoice(Model model) | internal RestApplicationCommandChoice(Model model) | ||||
{ | { | ||||
@@ -20,9 +20,9 @@ namespace Discord.Rest | |||||
public bool? Required { get; private set; } | public bool? Required { get; private set; } | ||||
public IReadOnlyCollection<IApplicationCommandOptionChoice> Choices { get; private set; } | |||||
public IReadOnlyCollection<RestApplicationCommandChoice> Choices { get; private set; } | |||||
public IReadOnlyCollection<IApplicationCommandOption> Options { get; private set; } | |||||
public IReadOnlyCollection<RestApplicationCommandOption> Options { get; private set; } | |||||
internal RestApplicationCommandOption() { } | internal RestApplicationCommandOption() { } | ||||
@@ -53,5 +53,8 @@ namespace Discord.Rest | |||||
? model.Choices.Value.Select(x => new RestApplicationCommandChoice(x)).ToImmutableArray() | ? model.Choices.Value.Select(x => new RestApplicationCommandChoice(x)).ToImmutableArray() | ||||
: null; | : null; | ||||
} | } | ||||
IReadOnlyCollection<IApplicationCommandOption> IApplicationCommandOption.Options => Options; | |||||
IReadOnlyCollection<IApplicationCommandOptionChoice> IApplicationCommandOption.Choices => Choices; | |||||
} | } | ||||
} | } |
@@ -15,7 +15,7 @@ namespace Discord.Rest | |||||
internal RestGlobalCommand(BaseDiscordClient client, ulong id) | internal RestGlobalCommand(BaseDiscordClient client, ulong id) | ||||
: base(client, id) | : base(client, id) | ||||
{ | { | ||||
this.CommandType = RestApplicationCommandType.GlobalCommand; | |||||
} | } | ||||
internal static RestGlobalCommand Create(BaseDiscordClient client, Model model) | internal static RestGlobalCommand Create(BaseDiscordClient client, Model model) | ||||
@@ -13,6 +13,7 @@ namespace Discord.Rest | |||||
internal RestGuildCommand(BaseDiscordClient client, ulong id, ulong guildId) | internal RestGuildCommand(BaseDiscordClient client, ulong id, ulong guildId) | ||||
: base(client, id) | : base(client, id) | ||||
{ | { | ||||
this.CommandType = RestApplicationCommandType.GuildCommand; | |||||
this.GuildId = guildId; | this.GuildId = guildId; | ||||
} | } | ||||
@@ -0,0 +1,30 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord.API.Gateway | |||||
{ | |||||
internal class ApplicationCommandCreatedUpdatedEvent | |||||
{ | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
[JsonProperty("id")] | |||||
public ulong Id { get; set; } | |||||
[JsonProperty("description")] | |||||
public string Description { get; set; } | |||||
[JsonProperty("application_id")] | |||||
public ulong ApplicationId { get; set; } | |||||
[JsonProperty("guild_id")] | |||||
public ulong GuildId { get; set; } | |||||
[JsonProperty("options")] | |||||
public List<Discord.API.ApplicationCommandOption> Options { get; set; } | |||||
} | |||||
} |
@@ -45,7 +45,8 @@ namespace Discord.WebSocket | |||||
/// <code language="cs" region="ChannelDestroyed" | /// <code language="cs" region="ChannelDestroyed" | ||||
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/> | /// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/> | ||||
/// </example> | /// </example> | ||||
public event Func<SocketChannel, Task> ChannelDestroyed { | |||||
public event Func<SocketChannel, Task> ChannelDestroyed | |||||
{ | |||||
add { _channelDestroyedEvent.Add(value); } | add { _channelDestroyedEvent.Add(value); } | ||||
remove { _channelDestroyedEvent.Remove(value); } | remove { _channelDestroyedEvent.Remove(value); } | ||||
} | } | ||||
@@ -67,7 +68,8 @@ namespace Discord.WebSocket | |||||
/// <code language="cs" region="ChannelUpdated" | /// <code language="cs" region="ChannelUpdated" | ||||
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/> | /// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/> | ||||
/// </example> | /// </example> | ||||
public event Func<SocketChannel, SocketChannel, Task> ChannelUpdated { | |||||
public event Func<SocketChannel, SocketChannel, Task> ChannelUpdated | |||||
{ | |||||
add { _channelUpdatedEvent.Add(value); } | add { _channelUpdatedEvent.Add(value); } | ||||
remove { _channelUpdatedEvent.Remove(value); } | remove { _channelUpdatedEvent.Remove(value); } | ||||
} | } | ||||
@@ -92,7 +94,8 @@ namespace Discord.WebSocket | |||||
/// <code language="cs" region="MessageReceived" | /// <code language="cs" region="MessageReceived" | ||||
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/> | /// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/> | ||||
/// </example> | /// </example> | ||||
public event Func<SocketMessage, Task> MessageReceived { | |||||
public event Func<SocketMessage, Task> MessageReceived | |||||
{ | |||||
add { _messageReceivedEvent.Add(value); } | add { _messageReceivedEvent.Add(value); } | ||||
remove { _messageReceivedEvent.Remove(value); } | remove { _messageReceivedEvent.Remove(value); } | ||||
} | } | ||||
@@ -124,7 +127,8 @@ namespace Discord.WebSocket | |||||
/// <code language="cs" region="MessageDeleted" | /// <code language="cs" region="MessageDeleted" | ||||
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs" /> | /// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs" /> | ||||
/// </example> | /// </example> | ||||
public event Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task> MessageDeleted { | |||||
public event Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task> MessageDeleted | |||||
{ | |||||
add { _messageDeletedEvent.Add(value); } | add { _messageDeletedEvent.Add(value); } | ||||
remove { _messageDeletedEvent.Remove(value); } | remove { _messageDeletedEvent.Remove(value); } | ||||
} | } | ||||
@@ -182,7 +186,8 @@ namespace Discord.WebSocket | |||||
/// <see cref="ISocketMessageChannel"/> parameter. | /// <see cref="ISocketMessageChannel"/> parameter. | ||||
/// </para> | /// </para> | ||||
/// </remarks> | /// </remarks> | ||||
public event Func<Cacheable<IMessage, ulong>, SocketMessage, ISocketMessageChannel, Task> MessageUpdated { | |||||
public event Func<Cacheable<IMessage, ulong>, SocketMessage, ISocketMessageChannel, Task> MessageUpdated | |||||
{ | |||||
add { _messageUpdatedEvent.Add(value); } | add { _messageUpdatedEvent.Add(value); } | ||||
remove { _messageUpdatedEvent.Remove(value); } | remove { _messageUpdatedEvent.Remove(value); } | ||||
} | } | ||||
@@ -217,19 +222,22 @@ namespace Discord.WebSocket | |||||
/// <code language="cs" region="ReactionAdded" | /// <code language="cs" region="ReactionAdded" | ||||
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/> | /// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/> | ||||
/// </example> | /// </example> | ||||
public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task> ReactionAdded { | |||||
public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task> ReactionAdded | |||||
{ | |||||
add { _reactionAddedEvent.Add(value); } | add { _reactionAddedEvent.Add(value); } | ||||
remove { _reactionAddedEvent.Remove(value); } | remove { _reactionAddedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>>(); | internal readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>>(); | ||||
/// <summary> Fired when a reaction is removed from a message. </summary> | /// <summary> Fired when a reaction is removed from a message. </summary> | ||||
public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved { | |||||
public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved | |||||
{ | |||||
add { _reactionRemovedEvent.Add(value); } | add { _reactionRemovedEvent.Add(value); } | ||||
remove { _reactionRemovedEvent.Remove(value); } | remove { _reactionRemovedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>>(); | internal readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>>(); | ||||
/// <summary> Fired when all reactions to a message are cleared. </summary> | /// <summary> Fired when all reactions to a message are cleared. </summary> | ||||
public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, Task> ReactionsCleared { | |||||
public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, Task> ReactionsCleared | |||||
{ | |||||
add { _reactionsClearedEvent.Add(value); } | add { _reactionsClearedEvent.Add(value); } | ||||
remove { _reactionsClearedEvent.Remove(value); } | remove { _reactionsClearedEvent.Remove(value); } | ||||
} | } | ||||
@@ -259,19 +267,22 @@ namespace Discord.WebSocket | |||||
//Roles | //Roles | ||||
/// <summary> Fired when a role is created. </summary> | /// <summary> Fired when a role is created. </summary> | ||||
public event Func<SocketRole, Task> RoleCreated { | |||||
public event Func<SocketRole, Task> RoleCreated | |||||
{ | |||||
add { _roleCreatedEvent.Add(value); } | add { _roleCreatedEvent.Add(value); } | ||||
remove { _roleCreatedEvent.Remove(value); } | remove { _roleCreatedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketRole, Task>> _roleCreatedEvent = new AsyncEvent<Func<SocketRole, Task>>(); | internal readonly AsyncEvent<Func<SocketRole, Task>> _roleCreatedEvent = new AsyncEvent<Func<SocketRole, Task>>(); | ||||
/// <summary> Fired when a role is deleted. </summary> | /// <summary> Fired when a role is deleted. </summary> | ||||
public event Func<SocketRole, Task> RoleDeleted { | |||||
public event Func<SocketRole, Task> RoleDeleted | |||||
{ | |||||
add { _roleDeletedEvent.Add(value); } | add { _roleDeletedEvent.Add(value); } | ||||
remove { _roleDeletedEvent.Remove(value); } | remove { _roleDeletedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketRole, Task>> _roleDeletedEvent = new AsyncEvent<Func<SocketRole, Task>>(); | internal readonly AsyncEvent<Func<SocketRole, Task>> _roleDeletedEvent = new AsyncEvent<Func<SocketRole, Task>>(); | ||||
/// <summary> Fired when a role is updated. </summary> | /// <summary> Fired when a role is updated. </summary> | ||||
public event Func<SocketRole, SocketRole, Task> RoleUpdated { | |||||
public event Func<SocketRole, SocketRole, Task> RoleUpdated | |||||
{ | |||||
add { _roleUpdatedEvent.Add(value); } | add { _roleUpdatedEvent.Add(value); } | ||||
remove { _roleUpdatedEvent.Remove(value); } | remove { _roleUpdatedEvent.Remove(value); } | ||||
} | } | ||||
@@ -279,37 +290,43 @@ namespace Discord.WebSocket | |||||
//Guilds | //Guilds | ||||
/// <summary> Fired when the connected account joins a guild. </summary> | /// <summary> Fired when the connected account joins a guild. </summary> | ||||
public event Func<SocketGuild, Task> JoinedGuild { | |||||
public event Func<SocketGuild, Task> JoinedGuild | |||||
{ | |||||
add { _joinedGuildEvent.Add(value); } | add { _joinedGuildEvent.Add(value); } | ||||
remove { _joinedGuildEvent.Remove(value); } | remove { _joinedGuildEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketGuild, Task>> _joinedGuildEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | internal readonly AsyncEvent<Func<SocketGuild, Task>> _joinedGuildEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | ||||
/// <summary> Fired when the connected account leaves a guild. </summary> | /// <summary> Fired when the connected account leaves a guild. </summary> | ||||
public event Func<SocketGuild, Task> LeftGuild { | |||||
public event Func<SocketGuild, Task> LeftGuild | |||||
{ | |||||
add { _leftGuildEvent.Add(value); } | add { _leftGuildEvent.Add(value); } | ||||
remove { _leftGuildEvent.Remove(value); } | remove { _leftGuildEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketGuild, Task>> _leftGuildEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | internal readonly AsyncEvent<Func<SocketGuild, Task>> _leftGuildEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | ||||
/// <summary> Fired when a guild becomes available. </summary> | /// <summary> Fired when a guild becomes available. </summary> | ||||
public event Func<SocketGuild, Task> GuildAvailable { | |||||
public event Func<SocketGuild, Task> GuildAvailable | |||||
{ | |||||
add { _guildAvailableEvent.Add(value); } | add { _guildAvailableEvent.Add(value); } | ||||
remove { _guildAvailableEvent.Remove(value); } | remove { _guildAvailableEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketGuild, Task>> _guildAvailableEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | internal readonly AsyncEvent<Func<SocketGuild, Task>> _guildAvailableEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | ||||
/// <summary> Fired when a guild becomes unavailable. </summary> | /// <summary> Fired when a guild becomes unavailable. </summary> | ||||
public event Func<SocketGuild, Task> GuildUnavailable { | |||||
public event Func<SocketGuild, Task> GuildUnavailable | |||||
{ | |||||
add { _guildUnavailableEvent.Add(value); } | add { _guildUnavailableEvent.Add(value); } | ||||
remove { _guildUnavailableEvent.Remove(value); } | remove { _guildUnavailableEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketGuild, Task>> _guildUnavailableEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | internal readonly AsyncEvent<Func<SocketGuild, Task>> _guildUnavailableEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | ||||
/// <summary> Fired when offline guild members are downloaded. </summary> | /// <summary> Fired when offline guild members are downloaded. </summary> | ||||
public event Func<SocketGuild, Task> GuildMembersDownloaded { | |||||
public event Func<SocketGuild, Task> GuildMembersDownloaded | |||||
{ | |||||
add { _guildMembersDownloadedEvent.Add(value); } | add { _guildMembersDownloadedEvent.Add(value); } | ||||
remove { _guildMembersDownloadedEvent.Remove(value); } | remove { _guildMembersDownloadedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketGuild, Task>> _guildMembersDownloadedEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | internal readonly AsyncEvent<Func<SocketGuild, Task>> _guildMembersDownloadedEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | ||||
/// <summary> Fired when a guild is updated. </summary> | /// <summary> Fired when a guild is updated. </summary> | ||||
public event Func<SocketGuild, SocketGuild, Task> GuildUpdated { | |||||
public event Func<SocketGuild, SocketGuild, Task> GuildUpdated | |||||
{ | |||||
add { _guildUpdatedEvent.Add(value); } | add { _guildUpdatedEvent.Add(value); } | ||||
remove { _guildUpdatedEvent.Remove(value); } | remove { _guildUpdatedEvent.Remove(value); } | ||||
} | } | ||||
@@ -317,43 +334,50 @@ namespace Discord.WebSocket | |||||
//Users | //Users | ||||
/// <summary> Fired when a user joins a guild. </summary> | /// <summary> Fired when a user joins a guild. </summary> | ||||
public event Func<SocketGuildUser, Task> UserJoined { | |||||
public event Func<SocketGuildUser, Task> UserJoined | |||||
{ | |||||
add { _userJoinedEvent.Add(value); } | add { _userJoinedEvent.Add(value); } | ||||
remove { _userJoinedEvent.Remove(value); } | remove { _userJoinedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketGuildUser, Task>> _userJoinedEvent = new AsyncEvent<Func<SocketGuildUser, Task>>(); | internal readonly AsyncEvent<Func<SocketGuildUser, Task>> _userJoinedEvent = new AsyncEvent<Func<SocketGuildUser, Task>>(); | ||||
/// <summary> Fired when a user leaves a guild. </summary> | /// <summary> Fired when a user leaves a guild. </summary> | ||||
public event Func<SocketGuildUser, Task> UserLeft { | |||||
public event Func<SocketGuildUser, Task> UserLeft | |||||
{ | |||||
add { _userLeftEvent.Add(value); } | add { _userLeftEvent.Add(value); } | ||||
remove { _userLeftEvent.Remove(value); } | remove { _userLeftEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketGuildUser, Task>> _userLeftEvent = new AsyncEvent<Func<SocketGuildUser, Task>>(); | internal readonly AsyncEvent<Func<SocketGuildUser, Task>> _userLeftEvent = new AsyncEvent<Func<SocketGuildUser, Task>>(); | ||||
/// <summary> Fired when a user is banned from a guild. </summary> | /// <summary> Fired when a user is banned from a guild. </summary> | ||||
public event Func<SocketUser, SocketGuild, Task> UserBanned { | |||||
public event Func<SocketUser, SocketGuild, Task> UserBanned | |||||
{ | |||||
add { _userBannedEvent.Add(value); } | add { _userBannedEvent.Add(value); } | ||||
remove { _userBannedEvent.Remove(value); } | remove { _userBannedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketUser, SocketGuild, Task>> _userBannedEvent = new AsyncEvent<Func<SocketUser, SocketGuild, Task>>(); | internal readonly AsyncEvent<Func<SocketUser, SocketGuild, Task>> _userBannedEvent = new AsyncEvent<Func<SocketUser, SocketGuild, Task>>(); | ||||
/// <summary> Fired when a user is unbanned from a guild. </summary> | /// <summary> Fired when a user is unbanned from a guild. </summary> | ||||
public event Func<SocketUser, SocketGuild, Task> UserUnbanned { | |||||
public event Func<SocketUser, SocketGuild, Task> UserUnbanned | |||||
{ | |||||
add { _userUnbannedEvent.Add(value); } | add { _userUnbannedEvent.Add(value); } | ||||
remove { _userUnbannedEvent.Remove(value); } | remove { _userUnbannedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketUser, SocketGuild, Task>> _userUnbannedEvent = new AsyncEvent<Func<SocketUser, SocketGuild, Task>>(); | internal readonly AsyncEvent<Func<SocketUser, SocketGuild, Task>> _userUnbannedEvent = new AsyncEvent<Func<SocketUser, SocketGuild, Task>>(); | ||||
/// <summary> Fired when a user is updated. </summary> | /// <summary> Fired when a user is updated. </summary> | ||||
public event Func<SocketUser, SocketUser, Task> UserUpdated { | |||||
public event Func<SocketUser, SocketUser, Task> UserUpdated | |||||
{ | |||||
add { _userUpdatedEvent.Add(value); } | add { _userUpdatedEvent.Add(value); } | ||||
remove { _userUpdatedEvent.Remove(value); } | remove { _userUpdatedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketUser, SocketUser, Task>> _userUpdatedEvent = new AsyncEvent<Func<SocketUser, SocketUser, Task>>(); | internal readonly AsyncEvent<Func<SocketUser, SocketUser, Task>> _userUpdatedEvent = new AsyncEvent<Func<SocketUser, SocketUser, Task>>(); | ||||
/// <summary> Fired when a guild member is updated, or a member presence is updated. </summary> | /// <summary> Fired when a guild member is updated, or a member presence is updated. </summary> | ||||
public event Func<SocketGuildUser, SocketGuildUser, Task> GuildMemberUpdated { | |||||
public event Func<SocketGuildUser, SocketGuildUser, Task> GuildMemberUpdated | |||||
{ | |||||
add { _guildMemberUpdatedEvent.Add(value); } | add { _guildMemberUpdatedEvent.Add(value); } | ||||
remove { _guildMemberUpdatedEvent.Remove(value); } | remove { _guildMemberUpdatedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketGuildUser, SocketGuildUser, Task>> _guildMemberUpdatedEvent = new AsyncEvent<Func<SocketGuildUser, SocketGuildUser, Task>>(); | internal readonly AsyncEvent<Func<SocketGuildUser, SocketGuildUser, Task>> _guildMemberUpdatedEvent = new AsyncEvent<Func<SocketGuildUser, SocketGuildUser, Task>>(); | ||||
/// <summary> Fired when a user joins, leaves, or moves voice channels. </summary> | /// <summary> Fired when a user joins, leaves, or moves voice channels. </summary> | ||||
public event Func<SocketUser, SocketVoiceState, SocketVoiceState, Task> UserVoiceStateUpdated { | |||||
public event Func<SocketUser, SocketVoiceState, SocketVoiceState, Task> UserVoiceStateUpdated | |||||
{ | |||||
add { _userVoiceStateUpdatedEvent.Add(value); } | add { _userVoiceStateUpdatedEvent.Add(value); } | ||||
remove { _userVoiceStateUpdatedEvent.Remove(value); } | remove { _userVoiceStateUpdatedEvent.Remove(value); } | ||||
} | } | ||||
@@ -366,25 +390,29 @@ namespace Discord.WebSocket | |||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketVoiceServer, Task>> _voiceServerUpdatedEvent = new AsyncEvent<Func<SocketVoiceServer, Task>>(); | internal readonly AsyncEvent<Func<SocketVoiceServer, Task>> _voiceServerUpdatedEvent = new AsyncEvent<Func<SocketVoiceServer, Task>>(); | ||||
/// <summary> Fired when the connected account is updated. </summary> | /// <summary> Fired when the connected account is updated. </summary> | ||||
public event Func<SocketSelfUser, SocketSelfUser, Task> CurrentUserUpdated { | |||||
public event Func<SocketSelfUser, SocketSelfUser, Task> CurrentUserUpdated | |||||
{ | |||||
add { _selfUpdatedEvent.Add(value); } | add { _selfUpdatedEvent.Add(value); } | ||||
remove { _selfUpdatedEvent.Remove(value); } | remove { _selfUpdatedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketSelfUser, SocketSelfUser, Task>> _selfUpdatedEvent = new AsyncEvent<Func<SocketSelfUser, SocketSelfUser, Task>>(); | internal readonly AsyncEvent<Func<SocketSelfUser, SocketSelfUser, Task>> _selfUpdatedEvent = new AsyncEvent<Func<SocketSelfUser, SocketSelfUser, Task>>(); | ||||
/// <summary> Fired when a user starts typing. </summary> | /// <summary> Fired when a user starts typing. </summary> | ||||
public event Func<SocketUser, ISocketMessageChannel, Task> UserIsTyping { | |||||
public event Func<SocketUser, ISocketMessageChannel, Task> UserIsTyping | |||||
{ | |||||
add { _userIsTypingEvent.Add(value); } | add { _userIsTypingEvent.Add(value); } | ||||
remove { _userIsTypingEvent.Remove(value); } | remove { _userIsTypingEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketUser, ISocketMessageChannel, Task>> _userIsTypingEvent = new AsyncEvent<Func<SocketUser, ISocketMessageChannel, Task>>(); | internal readonly AsyncEvent<Func<SocketUser, ISocketMessageChannel, Task>> _userIsTypingEvent = new AsyncEvent<Func<SocketUser, ISocketMessageChannel, Task>>(); | ||||
/// <summary> Fired when a user joins a group channel. </summary> | /// <summary> Fired when a user joins a group channel. </summary> | ||||
public event Func<SocketGroupUser, Task> RecipientAdded { | |||||
public event Func<SocketGroupUser, Task> RecipientAdded | |||||
{ | |||||
add { _recipientAddedEvent.Add(value); } | add { _recipientAddedEvent.Add(value); } | ||||
remove { _recipientAddedEvent.Remove(value); } | remove { _recipientAddedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketGroupUser, Task>> _recipientAddedEvent = new AsyncEvent<Func<SocketGroupUser, Task>>(); | internal readonly AsyncEvent<Func<SocketGroupUser, Task>> _recipientAddedEvent = new AsyncEvent<Func<SocketGroupUser, Task>>(); | ||||
/// <summary> Fired when a user is removed from a group channel. </summary> | /// <summary> Fired when a user is removed from a group channel. </summary> | ||||
public event Func<SocketGroupUser, Task> RecipientRemoved { | |||||
public event Func<SocketGroupUser, Task> RecipientRemoved | |||||
{ | |||||
add { _recipientRemovedEvent.Add(value); } | add { _recipientRemovedEvent.Add(value); } | ||||
remove { _recipientRemovedEvent.Remove(value); } | remove { _recipientRemovedEvent.Remove(value); } | ||||
} | } | ||||
@@ -452,5 +480,70 @@ namespace Discord.WebSocket | |||||
} | } | ||||
internal readonly AsyncEvent<Func<SocketInteraction, Task>> _interactionCreatedEvent = new AsyncEvent<Func<SocketInteraction, Task>>(); | internal readonly AsyncEvent<Func<SocketInteraction, Task>> _interactionCreatedEvent = new AsyncEvent<Func<SocketInteraction, Task>>(); | ||||
/// <summary> | |||||
/// Fired when a guild application command is created. | |||||
///</summary> | |||||
///<remarks> | |||||
/// <para> | |||||
/// This event is fired when an application command is created. The event handler must return a | |||||
/// <see cref="Task"/> and accept a <see cref="SocketApplicationCommand"/> as its parameter. | |||||
/// </para> | |||||
/// <para> | |||||
/// The command that was deleted will be passed into the <see cref="SocketApplicationCommand"/> parameter. | |||||
/// </para> | |||||
/// <note> | |||||
/// <b>This event is an undocumented discord event and may break at any time, its not recommended to rely on this event</b> | |||||
/// </note> | |||||
/// </remarks> | |||||
public event Func<SocketApplicationCommand, Task> ApplicationCommandCreated | |||||
{ | |||||
add { _applicationCommandCreated.Add(value); } | |||||
remove { _applicationCommandCreated.Remove(value); } | |||||
} | |||||
internal readonly AsyncEvent<Func<SocketApplicationCommand, Task>> _applicationCommandCreated = new AsyncEvent<Func<SocketApplicationCommand, Task>>(); | |||||
/// <summary> | |||||
/// Fired when a guild application command is updated. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// <para> | |||||
/// This event is fired when an application command is updated. The event handler must return a | |||||
/// <see cref="Task"/> and accept a <see cref="SocketApplicationCommand"/> as its parameter. | |||||
/// </para> | |||||
/// <para> | |||||
/// The command that was deleted will be passed into the <see cref="SocketApplicationCommand"/> parameter. | |||||
/// </para> | |||||
/// <note> | |||||
/// <b>This event is an undocumented discord event and may break at any time, its not recommended to rely on this event</b> | |||||
/// </note> | |||||
/// </remarks> | |||||
public event Func<SocketApplicationCommand, Task> ApplicationCommandUpdated | |||||
{ | |||||
add { _applicationCommandUpdated.Add(value); } | |||||
remove { _applicationCommandUpdated.Remove(value); } | |||||
} | |||||
internal readonly AsyncEvent<Func<SocketApplicationCommand, Task>> _applicationCommandUpdated = new AsyncEvent<Func<SocketApplicationCommand, Task>>(); | |||||
/// <summary> | |||||
/// Fired when a guild application command is deleted. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// <para> | |||||
/// This event is fired when an application command is deleted. The event handler must return a | |||||
/// <see cref="Task"/> and accept a <see cref="SocketApplicationCommand"/> as its parameter. | |||||
/// </para> | |||||
/// <para> | |||||
/// The command that was deleted will be passed into the <see cref="SocketApplicationCommand"/> parameter. | |||||
/// </para> | |||||
/// <note> | |||||
/// <b>This event is an undocumented discord event and may break at any time, its not recommended to rely on this event</b> | |||||
/// </note> | |||||
/// </remarks> | |||||
public event Func<SocketApplicationCommand, Task> ApplicationCommandDeleted | |||||
{ | |||||
add { _applicationCommandDeleted.Add(value); } | |||||
remove { _applicationCommandDeleted.Remove(value); } | |||||
} | |||||
internal readonly AsyncEvent<Func<SocketApplicationCommand, Task>> _applicationCommandDeleted = new AsyncEvent<Func<SocketApplicationCommand, Task>>(); | |||||
} | } | ||||
} | } |
@@ -613,7 +613,7 @@ namespace Discord.WebSocket | |||||
} | } | ||||
else if (_connection.CancelToken.IsCancellationRequested) | else if (_connection.CancelToken.IsCancellationRequested) | ||||
return; | return; | ||||
if (BaseConfig.AlwaysDownloadUsers) | if (BaseConfig.AlwaysDownloadUsers) | ||||
_ = DownloadUsersAsync(Guilds.Where(x => x.IsAvailable && !x.HasAllMembers)); | _ = DownloadUsersAsync(Guilds.Where(x => x.IsAvailable && !x.HasAllMembers)); | ||||
@@ -1808,6 +1808,60 @@ namespace Discord.WebSocket | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
case "APPLICATION_COMMAND_CREATE": | |||||
{ | |||||
await _gatewayLogger.DebugAsync("Received Dispatch (APPLICATION_COMMAND_CREATE)").ConfigureAwait(false); | |||||
var data = (payload as JToken).ToObject<API.Gateway.ApplicationCommandCreatedUpdatedEvent>(_serializer); | |||||
var guild = State.GetGuild(data.GuildId); | |||||
if(guild == null) | |||||
{ | |||||
await UnknownGuildAsync(type, data.GuildId).ConfigureAwait(false); | |||||
return; | |||||
} | |||||
var applicationCommand = SocketApplicationCommand.Create(this, data); | |||||
await TimedInvokeAsync(_applicationCommandCreated, nameof(ApplicationCommandCreated), applicationCommand).ConfigureAwait(false); | |||||
} | |||||
break; | |||||
case "APPLICATION_COMMAND_UPDATE": | |||||
{ | |||||
await _gatewayLogger.DebugAsync("Received Dispatch (APPLICATION_COMMAND_UPDATE)").ConfigureAwait(false); | |||||
var data = (payload as JToken).ToObject<API.Gateway.ApplicationCommandCreatedUpdatedEvent>(_serializer); | |||||
var guild = State.GetGuild(data.GuildId); | |||||
if (guild == null) | |||||
{ | |||||
await UnknownGuildAsync(type, data.GuildId).ConfigureAwait(false); | |||||
return; | |||||
} | |||||
var applicationCommand = SocketApplicationCommand.Create(this, data); | |||||
await TimedInvokeAsync(_applicationCommandUpdated, nameof(ApplicationCommandUpdated), applicationCommand).ConfigureAwait(false); | |||||
} | |||||
break; | |||||
case "APPLICATION_COMMAND_DELETE": | |||||
{ | |||||
await _gatewayLogger.DebugAsync("Received Dispatch (APPLICATION_COMMAND_DELETE)").ConfigureAwait(false); | |||||
var data = (payload as JToken).ToObject<API.Gateway.ApplicationCommandCreatedUpdatedEvent>(_serializer); | |||||
var guild = State.GetGuild(data.GuildId); | |||||
if (guild == null) | |||||
{ | |||||
await UnknownGuildAsync(type, data.GuildId).ConfigureAwait(false); | |||||
return; | |||||
} | |||||
var applicationCommand = SocketApplicationCommand.Create(this, data); | |||||
await TimedInvokeAsync(_applicationCommandDeleted, nameof(ApplicationCommandDeleted), applicationCommand).ConfigureAwait(false); | |||||
} | |||||
break; | |||||
//Ignored (User only) | //Ignored (User only) | ||||
case "CHANNEL_PINS_ACK": | case "CHANNEL_PINS_ACK": | ||||
await _gatewayLogger.DebugAsync("Ignored Dispatch (CHANNEL_PINS_ACK)").ConfigureAwait(false); | await _gatewayLogger.DebugAsync("Ignored Dispatch (CHANNEL_PINS_ACK)").ConfigureAwait(false); | ||||
@@ -1006,6 +1006,18 @@ namespace Discord.WebSocket | |||||
public Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) | public Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) | ||||
=> GuildHelper.GetWebhooksAsync(this, Discord, options); | => GuildHelper.GetWebhooksAsync(this, Discord, options); | ||||
//Interactions | |||||
/// <summary> | |||||
/// Gets this guilds slash commands commands | |||||
/// </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 application commands found within the guild. | |||||
/// </returns> | |||||
public async Task<IReadOnlyCollection<RestApplicationCommand>> GetApplicationCommandsAsync(RequestOptions options = null) | |||||
=> await Discord.Rest.GetGuildApplicationCommands(this.Id, options); | |||||
//Emotes | //Emotes | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public Task<GuildEmote> GetEmoteAsync(ulong id, RequestOptions options = null) | public Task<GuildEmote> GetEmoteAsync(ulong id, RequestOptions options = null) | ||||
@@ -0,0 +1,55 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Collections.Immutable; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Model = Discord.API.Gateway.ApplicationCommandCreatedUpdatedEvent; | |||||
namespace Discord.WebSocket | |||||
{ | |||||
public class SocketApplicationCommand : SocketEntity<ulong>, IApplicationCommand | |||||
{ | |||||
public ulong ApplicationId { get; private set; } | |||||
public string Name { get; private set; } | |||||
public string Description { get; private set; } | |||||
public IReadOnlyCollection<SocketApplicationCommandOption> Options { get; private set; } | |||||
public DateTimeOffset CreatedAt | |||||
=> SnowflakeUtils.FromSnowflake(this.Id); | |||||
public SocketGuild Guild | |||||
=> Discord.GetGuild(this.GuildId); | |||||
private ulong GuildId { get; set; } | |||||
internal SocketApplicationCommand(DiscordSocketClient client, ulong id) | |||||
: base(client, id) | |||||
{ | |||||
} | |||||
internal static SocketApplicationCommand Create(DiscordSocketClient client, Model model) | |||||
{ | |||||
var entity = new SocketApplicationCommand(client, model.Id); | |||||
entity.Update(model); | |||||
return entity; | |||||
} | |||||
internal void Update(Model model) | |||||
{ | |||||
this.ApplicationId = model.ApplicationId; | |||||
this.Description = model.Description; | |||||
this.Name = model.Name; | |||||
this.GuildId = model.GuildId; | |||||
this.Options = model.Options.Any() | |||||
? model.Options.Select(x => SocketApplicationCommandOption.Create(x)).ToImmutableArray() | |||||
: new ImmutableArray<SocketApplicationCommandOption>(); | |||||
} | |||||
public Task DeleteAsync(RequestOptions options = null) => throw new NotImplementedException(); | |||||
IReadOnlyCollection<IApplicationCommandOption> IApplicationCommand.Options => Options; | |||||
} | |||||
} |
@@ -0,0 +1,32 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Model = Discord.API.ApplicationCommandOptionChoice; | |||||
namespace Discord.WebSocket | |||||
{ | |||||
/// <summary> | |||||
/// Represents a choice for a <see cref="SocketApplicationCommandOption"/> | |||||
/// </summary> | |||||
public class SocketApplicationCommandChoice : IApplicationCommandOptionChoice | |||||
{ | |||||
public string Name { get; private set; } | |||||
public object Value { get; private set; } | |||||
internal SocketApplicationCommandChoice() { } | |||||
internal static SocketApplicationCommandChoice Create(Model model) | |||||
{ | |||||
var entity = new SocketApplicationCommandChoice(); | |||||
entity.Update(model); | |||||
return entity; | |||||
} | |||||
internal void Update(Model model) | |||||
{ | |||||
this.Name = model.Name; | |||||
this.Value = model.Value; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,70 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Collections.Immutable; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Model = Discord.API.ApplicationCommandOption; | |||||
namespace Discord.WebSocket | |||||
{ | |||||
/// <summary> | |||||
/// Represents an option for a <see cref="SocketApplicationCommand"/> | |||||
/// </summary> | |||||
public class SocketApplicationCommandOption : IApplicationCommandOption | |||||
{ | |||||
public string Name { get; private set; } | |||||
public ApplicationCommandOptionType Type { get; private set; } | |||||
public string Description { get; private set; } | |||||
public bool? Default { get; private set; } | |||||
public bool? Required { get; private set; } | |||||
/// <summary> | |||||
/// Choices for string and int types for the user to pick from. | |||||
/// </summary> | |||||
public IReadOnlyCollection<SocketApplicationCommandChoice> Choices { get; private set; } | |||||
/// <summary> | |||||
/// If the option is a subcommand or subcommand group type, this nested options will be the parameters. | |||||
/// </summary> | |||||
public IReadOnlyCollection<SocketApplicationCommandOption> Options { get; private set; } | |||||
internal SocketApplicationCommandOption() { } | |||||
internal static SocketApplicationCommandOption Create(Model model) | |||||
{ | |||||
var entity = new SocketApplicationCommandOption(); | |||||
entity.Update(model); | |||||
return entity; | |||||
} | |||||
internal void Update(Model model) | |||||
{ | |||||
this.Name = model.Name; | |||||
this.Type = model.Type; | |||||
this.Description = model.Description; | |||||
this.Default = model.Default.IsSpecified | |||||
? model.Default.Value | |||||
: null; | |||||
this.Required = model.Required.IsSpecified | |||||
? model.Required.Value | |||||
: null; | |||||
this.Choices = model.Choices.IsSpecified | |||||
? model.Choices.Value.Select(x => SocketApplicationCommandChoice.Create(x)).ToImmutableArray() | |||||
: new ImmutableArray<SocketApplicationCommandChoice>(); | |||||
this.Options = model.Options.IsSpecified | |||||
? model.Options.Value.Select(x => SocketApplicationCommandOption.Create(x)).ToImmutableArray() | |||||
: new ImmutableArray<SocketApplicationCommandOption>(); | |||||
} | |||||
IReadOnlyCollection<IApplicationCommandOptionChoice> IApplicationCommandOption.Choices => Choices; | |||||
IReadOnlyCollection<IApplicationCommandOption> IApplicationCommandOption.Options => Options; | |||||
} | |||||
} |
@@ -39,7 +39,7 @@ namespace Discord.WebSocket | |||||
/// <summary> | /// <summary> | ||||
/// The data associated with this interaction | /// The data associated with this interaction | ||||
/// </summary> | /// </summary> | ||||
public IApplicationCommandInteractionData Data { get; private set; } | |||||
public SocketInteractionData Data { get; private set; } | |||||
/// <summary> | /// <summary> | ||||
/// The token used to respond to this interaction | /// The token used to respond to this interaction | ||||
@@ -209,5 +209,7 @@ namespace Discord.WebSocket | |||||
await Discord.Rest.ApiClient.CreateInteractionResponse(response, this.Id, Token, options).ConfigureAwait(false); | await Discord.Rest.ApiClient.CreateInteractionResponse(response, this.Id, Token, options).ConfigureAwait(false); | ||||
} | } | ||||
IApplicationCommandInteractionData IDiscordInteraction.Data => Data; | |||||
} | } | ||||
} | } |
@@ -11,7 +11,7 @@ namespace Discord.WebSocket | |||||
public class SocketInteractionData : SocketEntity<ulong>, IApplicationCommandInteractionData | public class SocketInteractionData : SocketEntity<ulong>, IApplicationCommandInteractionData | ||||
{ | { | ||||
public string Name { get; private set; } | public string Name { get; private set; } | ||||
public IReadOnlyCollection<IApplicationCommandInteractionDataOption> Options { get; private set; } | |||||
public IReadOnlyCollection<SocketInteractionDataOption> Options { get; private set; } | |||||
internal SocketInteractionData(DiscordSocketClient client, ulong id) | internal SocketInteractionData(DiscordSocketClient client, ulong id) | ||||
: base(client, id) | : base(client, id) | ||||
@@ -33,5 +33,7 @@ namespace Discord.WebSocket | |||||
: null; | : null; | ||||
} | } | ||||
IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionData.Options => Options; | |||||
} | } | ||||
} | } |