@@ -3609,23 +3609,9 @@ | |||||
The data associated with this interaction. | The data associated with this interaction. | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketApplicationMessageCommand.RespondAsync(System.String,Discord.Embed[],System.Boolean,System.Boolean,Discord.AllowedMentions,Discord.RequestOptions,Discord.MessageComponent,Discord.Embed)"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketApplicationMessageCommand.FollowupAsync(System.String,Discord.Embed[],System.Boolean,System.Boolean,Discord.AllowedMentions,Discord.RequestOptions,Discord.MessageComponent,Discord.Embed)"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketApplicationMessageCommand.DeferAsync(Discord.RequestOptions)"> | |||||
<summary> | |||||
Acknowledges this interaction with the <see cref="F:Discord.InteractionResponseType.DeferredChannelMessageWithSource"/>. | |||||
</summary> | |||||
<returns> | |||||
A task that represents the asynchronous operation of acknowledging the interaction. | |||||
</returns> | |||||
</member> | |||||
<member name="T:Discord.WebSocket.SocketApplicationMessageCommandData"> | <member name="T:Discord.WebSocket.SocketApplicationMessageCommandData"> | ||||
<summary> | <summary> | ||||
Represents the data tied with the <see cref="T:Discord.WebSocket.SocketSlashCommand"/> interaction. | |||||
Represents the data tied with the <see cref="T:Discord.WebSocket.SocketApplicationMessageCommand"/> interaction. | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:Discord.WebSocket.SocketApplicationMessageCommandData.Name"> | <member name="P:Discord.WebSocket.SocketApplicationMessageCommandData.Name"> | ||||
@@ -3641,23 +3627,9 @@ | |||||
The data associated with this interaction. | The data associated with this interaction. | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketApplicationUserCommand.RespondAsync(System.String,Discord.Embed[],System.Boolean,System.Boolean,Discord.AllowedMentions,Discord.RequestOptions,Discord.MessageComponent,Discord.Embed)"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketApplicationUserCommand.FollowupAsync(System.String,Discord.Embed[],System.Boolean,System.Boolean,Discord.AllowedMentions,Discord.RequestOptions,Discord.MessageComponent,Discord.Embed)"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="M:Discord.WebSocket.SocketApplicationUserCommand.DeferAsync(Discord.RequestOptions)"> | |||||
<summary> | |||||
Acknowledges this interaction with the <see cref="F:Discord.InteractionResponseType.DeferredChannelMessageWithSource"/>. | |||||
</summary> | |||||
<returns> | |||||
A task that represents the asynchronous operation of acknowledging the interaction. | |||||
</returns> | |||||
</member> | |||||
<member name="T:Discord.WebSocket.SocketApplicationUserCommandData"> | <member name="T:Discord.WebSocket.SocketApplicationUserCommandData"> | ||||
<summary> | <summary> | ||||
Represents the data tied with the <see cref="T:Discord.WebSocket.SocketSlashCommand"/> interaction. | |||||
Represents the data tied with the <see cref="T:Discord.WebSocket.SocketApplicationUserCommand"/> interaction. | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:Discord.WebSocket.SocketApplicationUserCommandData.Name"> | <member name="P:Discord.WebSocket.SocketApplicationUserCommandData.Name"> | ||||
@@ -3721,6 +3693,48 @@ | |||||
The value(s) of a <see cref="T:Discord.SelectMenu"/> interaction response. | The value(s) of a <see cref="T:Discord.SelectMenu"/> interaction response. | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="T:Discord.WebSocket.SocketSlashCommand"> | |||||
<summary> | |||||
Represents a Websocket-based slash command received over the gateway. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketSlashCommand.Data"> | |||||
<summary> | |||||
The data associated with this interaction. | |||||
</summary> | |||||
</member> | |||||
<member name="T:Discord.WebSocket.SocketSlashCommandData"> | |||||
<summary> | |||||
Represents the data tied with the <see cref="T:Discord.WebSocket.SocketSlashCommand"/> interaction. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketSlashCommandData.Name"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketSlashCommandData.Options"> | |||||
<summary> | |||||
The <see cref="T:Discord.WebSocket.SocketSlashCommandDataOption"/>'s received with this interaction. | |||||
</summary> | |||||
</member> | |||||
<member name="T:Discord.WebSocket.SocketSlashCommandDataOption"> | |||||
<summary> | |||||
Represents a Websocket-based <see cref="T:Discord.IApplicationCommandInteractionDataOption"/> recieved by the gateway | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketSlashCommandDataOption.Name"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketSlashCommandDataOption.Value"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketSlashCommandDataOption.Type"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketSlashCommandDataOption.Options"> | |||||
<summary> | |||||
The sub command options received for this sub command group. | |||||
</summary> | |||||
</member> | |||||
<member name="T:Discord.WebSocket.SocketApplicationCommand"> | <member name="T:Discord.WebSocket.SocketApplicationCommand"> | ||||
<summary> | <summary> | ||||
Represends a Websocket-based <see cref="T:Discord.IApplicationCommand"/> recieved over the gateway. | Represends a Websocket-based <see cref="T:Discord.IApplicationCommand"/> recieved over the gateway. | ||||
@@ -3798,23 +3812,18 @@ | |||||
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> | ||||
</member> | </member> | ||||
<member name="T:Discord.WebSocket.SocketSlashCommand"> | |||||
<summary> | |||||
Represents a Websocket-based slash command received over the gateway. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketSlashCommand.Data"> | |||||
<member name="P:Discord.WebSocket.SocketCommandBase.Data"> | |||||
<summary> | <summary> | ||||
The data associated with this interaction. | The data associated with this interaction. | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketSlashCommand.RespondAsync(System.String,Discord.Embed[],System.Boolean,System.Boolean,Discord.AllowedMentions,Discord.RequestOptions,Discord.MessageComponent,Discord.Embed)"> | |||||
<member name="M:Discord.WebSocket.SocketCommandBase.RespondAsync(System.String,Discord.Embed[],System.Boolean,System.Boolean,Discord.AllowedMentions,Discord.RequestOptions,Discord.MessageComponent,Discord.Embed)"> | |||||
<inheritdoc/> | <inheritdoc/> | ||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketSlashCommand.FollowupAsync(System.String,Discord.Embed[],System.Boolean,System.Boolean,Discord.AllowedMentions,Discord.RequestOptions,Discord.MessageComponent,Discord.Embed)"> | |||||
<member name="M:Discord.WebSocket.SocketCommandBase.FollowupAsync(System.String,Discord.Embed[],System.Boolean,System.Boolean,Discord.AllowedMentions,Discord.RequestOptions,Discord.MessageComponent,Discord.Embed)"> | |||||
<inheritdoc/> | <inheritdoc/> | ||||
</member> | </member> | ||||
<member name="M:Discord.WebSocket.SocketSlashCommand.DeferAsync(Discord.RequestOptions)"> | |||||
<member name="M:Discord.WebSocket.SocketCommandBase.DeferAsync(Discord.RequestOptions)"> | |||||
<summary> | <summary> | ||||
Acknowledges this interaction with the <see cref="F:Discord.InteractionResponseType.DeferredChannelMessageWithSource"/>. | Acknowledges this interaction with the <see cref="F:Discord.InteractionResponseType.DeferredChannelMessageWithSource"/>. | ||||
</summary> | </summary> | ||||
@@ -3822,34 +3831,13 @@ | |||||
A task that represents the asynchronous operation of acknowledging the interaction. | A task that represents the asynchronous operation of acknowledging the interaction. | ||||
</returns> | </returns> | ||||
</member> | </member> | ||||
<member name="T:Discord.WebSocket.SocketSlashCommandData"> | |||||
<summary> | |||||
Represents the data tied with the <see cref="T:Discord.WebSocket.SocketSlashCommand"/> interaction. | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketSlashCommandData.Name"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketSlashCommandData.Options"> | |||||
<summary> | |||||
The <see cref="T:Discord.WebSocket.SocketSlashCommandDataOption"/>'s received with this interaction. | |||||
</summary> | |||||
</member> | |||||
<member name="T:Discord.WebSocket.SocketSlashCommandDataOption"> | |||||
<summary> | |||||
Represents a Websocket-based <see cref="T:Discord.IApplicationCommandInteractionDataOption"/> recieved by the gateway | |||||
</summary> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketSlashCommandDataOption.Name"> | |||||
<inheritdoc/> | |||||
</member> | |||||
<member name="P:Discord.WebSocket.SocketSlashCommandDataOption.Value"> | |||||
<member name="P:Discord.WebSocket.SocketCommandBaseDataOption.Value"> | |||||
<inheritdoc/> | <inheritdoc/> | ||||
</member> | </member> | ||||
<member name="P:Discord.WebSocket.SocketSlashCommandDataOption.Type"> | |||||
<member name="P:Discord.WebSocket.SocketCommandBaseDataOption.Type"> | |||||
<inheritdoc/> | <inheritdoc/> | ||||
</member> | </member> | ||||
<member name="P:Discord.WebSocket.SocketSlashCommandDataOption.Options"> | |||||
<member name="P:Discord.WebSocket.SocketCommandBaseDataOption.Options"> | |||||
<summary> | <summary> | ||||
The sub command options received for this sub command group. | The sub command options received for this sub command group. | ||||
</summary> | </summary> | ||||
@@ -10,7 +10,7 @@ namespace Discord.WebSocket | |||||
/// <summary> | /// <summary> | ||||
/// Represents a Websocket-based slash command received over the gateway. | /// Represents a Websocket-based slash command received over the gateway. | ||||
/// </summary> | /// </summary> | ||||
public class SocketApplicationMessageCommand : SocketSlashCommand | |||||
public class SocketApplicationMessageCommand : SocketCommandBase | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// The data associated with this interaction. | /// The data associated with this interaction. | ||||
@@ -37,129 +37,5 @@ namespace Discord.WebSocket | |||||
entity.Update(model); | entity.Update(model); | ||||
return entity; | return entity; | ||||
} | } | ||||
internal override void Update(Model model) | |||||
{ | |||||
var data = model.Data.IsSpecified ? | |||||
(DataModel)model.Data.Value | |||||
: null; | |||||
this.Data.Update(data); | |||||
base.Update(model); | |||||
} | |||||
/// <inheritdoc/> | |||||
public override async Task RespondAsync( | |||||
string text = null, | |||||
Embed[] embeds = null, | |||||
bool isTTS = false, | |||||
bool ephemeral = false, | |||||
AllowedMentions allowedMentions = null, | |||||
RequestOptions options = null, | |||||
MessageComponent component = null, | |||||
Embed embed = null) | |||||
{ | |||||
if (!IsValidToken) | |||||
throw new InvalidOperationException("Interaction token is no longer valid"); | |||||
if (embeds == null && embed != null) | |||||
embeds = new[] { embed }; | |||||
if (Discord.AlwaysAcknowledgeInteractions) | |||||
{ | |||||
await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, options, component); | |||||
return; | |||||
} | |||||
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); | |||||
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); | |||||
Preconditions.AtMost(embeds?.Length ?? 0, 10, nameof(embeds), "A max of 10 embeds are allowed."); | |||||
// check that user flag and user Id list are exclusive, same with role flag and role Id list | |||||
if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) | |||||
{ | |||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) && | |||||
allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0) | |||||
{ | |||||
throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions)); | |||||
} | |||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) && | |||||
allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0) | |||||
{ | |||||
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions)); | |||||
} | |||||
} | |||||
var response = new API.InteractionResponse | |||||
{ | |||||
Type = InteractionResponseType.ChannelMessageWithSource, | |||||
Data = new API.InteractionCallbackData | |||||
{ | |||||
Content = text, | |||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified, | |||||
Embeds = embeds?.Select(x => x.ToModel()).ToArray() ?? Optional<API.Embed[]>.Unspecified, | |||||
TTS = isTTS ? true : Optional<bool>.Unspecified, | |||||
Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified | |||||
} | |||||
}; | |||||
if (ephemeral) | |||||
response.Data.Value.Flags = 64; | |||||
await InteractionHelper.SendInteractionResponse(this.Discord, response, this.Id, Token, options); | |||||
} | |||||
/// <inheritdoc/> | |||||
public override async Task<RestFollowupMessage> FollowupAsync( | |||||
string text = null, | |||||
Embed[] embeds = null, | |||||
bool isTTS = false, | |||||
bool ephemeral = false, | |||||
AllowedMentions allowedMentions = null, | |||||
RequestOptions options = null, | |||||
MessageComponent component = null, | |||||
Embed embed = null) | |||||
{ | |||||
if (!IsValidToken) | |||||
throw new InvalidOperationException("Interaction token is no longer valid"); | |||||
if (embeds == null && embed != null) | |||||
embeds = new[] { embed }; | |||||
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); | |||||
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); | |||||
Preconditions.AtMost(embeds?.Length ?? 0, 10, nameof(embeds), "A max of 10 embeds are allowed."); | |||||
var args = new API.Rest.CreateWebhookMessageParams | |||||
{ | |||||
Content = text, | |||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified, | |||||
IsTTS = isTTS, | |||||
Embeds = embeds?.Select(x => x.ToModel()).ToArray() ?? Optional<API.Embed[]>.Unspecified, | |||||
Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified | |||||
}; | |||||
if (ephemeral) | |||||
args.Flags = 64; | |||||
return await InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options); | |||||
} | |||||
/// <summary> | |||||
/// Acknowledges this interaction with the <see cref="InteractionResponseType.DeferredChannelMessageWithSource"/>. | |||||
/// </summary> | |||||
/// <returns> | |||||
/// A task that represents the asynchronous operation of acknowledging the interaction. | |||||
/// </returns> | |||||
public override Task DeferAsync(RequestOptions options = null) | |||||
{ | |||||
var response = new API.InteractionResponse | |||||
{ | |||||
Type = InteractionResponseType.DeferredChannelMessageWithSource, | |||||
}; | |||||
return Discord.Rest.ApiClient.CreateInteractionResponse(response, this.Id, this.Token, options); | |||||
} | |||||
} | } | ||||
} | } |
@@ -6,7 +6,7 @@ using Model = Discord.API.ApplicationCommandInteractionData; | |||||
namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// Represents the data tied with the <see cref="SocketSlashCommand"/> interaction. | |||||
/// Represents the data tied with the <see cref="SocketApplicationMessageCommand"/> interaction. | |||||
/// </summary> | /// </summary> | ||||
public class SocketApplicationMessageCommandData : SocketEntity<ulong>, IApplicationCommandInteractionData | public class SocketApplicationMessageCommandData : SocketEntity<ulong>, IApplicationCommandInteractionData | ||||
{ | { | ||||
@@ -10,7 +10,7 @@ namespace Discord.WebSocket | |||||
/// <summary> | /// <summary> | ||||
/// Represents a Websocket-based slash command received over the gateway. | /// Represents a Websocket-based slash command received over the gateway. | ||||
/// </summary> | /// </summary> | ||||
public class SocketApplicationUserCommand : SocketSlashCommand | |||||
public class SocketApplicationUserCommand : SocketCommandBase | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// The data associated with this interaction. | /// The data associated with this interaction. | ||||
@@ -36,130 +36,6 @@ namespace Discord.WebSocket | |||||
var entity = new SocketApplicationUserCommand(client, model, channel); | var entity = new SocketApplicationUserCommand(client, model, channel); | ||||
entity.Update(model); | entity.Update(model); | ||||
return entity; | return entity; | ||||
} | |||||
internal override void Update(Model model) | |||||
{ | |||||
var data = model.Data.IsSpecified ? | |||||
(DataModel)model.Data.Value | |||||
: null; | |||||
this.Data.Update(data); | |||||
base.Update(model); | |||||
} | |||||
/// <inheritdoc/> | |||||
public override async Task RespondAsync( | |||||
string text = null, | |||||
Embed[] embeds = null, | |||||
bool isTTS = false, | |||||
bool ephemeral = false, | |||||
AllowedMentions allowedMentions = null, | |||||
RequestOptions options = null, | |||||
MessageComponent component = null, | |||||
Embed embed = null) | |||||
{ | |||||
if (!IsValidToken) | |||||
throw new InvalidOperationException("Interaction token is no longer valid"); | |||||
if (embeds == null && embed != null) | |||||
embeds = new[] { embed }; | |||||
if (Discord.AlwaysAcknowledgeInteractions) | |||||
{ | |||||
await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, options, component); | |||||
return; | |||||
} | |||||
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); | |||||
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); | |||||
Preconditions.AtMost(embeds?.Length ?? 0, 10, nameof(embeds), "A max of 10 embeds are allowed."); | |||||
// check that user flag and user Id list are exclusive, same with role flag and role Id list | |||||
if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) | |||||
{ | |||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) && | |||||
allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0) | |||||
{ | |||||
throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions)); | |||||
} | |||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) && | |||||
allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0) | |||||
{ | |||||
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions)); | |||||
} | |||||
} | |||||
var response = new API.InteractionResponse | |||||
{ | |||||
Type = InteractionResponseType.ChannelMessageWithSource, | |||||
Data = new API.InteractionCallbackData | |||||
{ | |||||
Content = text, | |||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified, | |||||
Embeds = embeds?.Select(x => x.ToModel()).ToArray() ?? Optional<API.Embed[]>.Unspecified, | |||||
TTS = isTTS ? true : Optional<bool>.Unspecified, | |||||
Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified | |||||
} | |||||
}; | |||||
if (ephemeral) | |||||
response.Data.Value.Flags = 64; | |||||
await InteractionHelper.SendInteractionResponse(this.Discord, response, this.Id, Token, options); | |||||
} | |||||
/// <inheritdoc/> | |||||
public override async Task<RestFollowupMessage> FollowupAsync( | |||||
string text = null, | |||||
Embed[] embeds = null, | |||||
bool isTTS = false, | |||||
bool ephemeral = false, | |||||
AllowedMentions allowedMentions = null, | |||||
RequestOptions options = null, | |||||
MessageComponent component = null, | |||||
Embed embed = null) | |||||
{ | |||||
if (!IsValidToken) | |||||
throw new InvalidOperationException("Interaction token is no longer valid"); | |||||
if (embeds == null && embed != null) | |||||
embeds = new[] { embed }; | |||||
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); | |||||
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); | |||||
Preconditions.AtMost(embeds?.Length ?? 0, 10, nameof(embeds), "A max of 10 embeds are allowed."); | |||||
var args = new API.Rest.CreateWebhookMessageParams | |||||
{ | |||||
Content = text, | |||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified, | |||||
IsTTS = isTTS, | |||||
Embeds = embeds?.Select(x => x.ToModel()).ToArray() ?? Optional<API.Embed[]>.Unspecified, | |||||
Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified | |||||
}; | |||||
if (ephemeral) | |||||
args.Flags = 64; | |||||
return await InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options); | |||||
} | |||||
/// <summary> | |||||
/// Acknowledges this interaction with the <see cref="InteractionResponseType.DeferredChannelMessageWithSource"/>. | |||||
/// </summary> | |||||
/// <returns> | |||||
/// A task that represents the asynchronous operation of acknowledging the interaction. | |||||
/// </returns> | |||||
public override Task DeferAsync(RequestOptions options = null) | |||||
{ | |||||
var response = new API.InteractionResponse | |||||
{ | |||||
Type = InteractionResponseType.DeferredChannelMessageWithSource, | |||||
}; | |||||
return Discord.Rest.ApiClient.CreateInteractionResponse(response, this.Id, this.Token, options); | |||||
} | |||||
} | |||||
} | } | ||||
} | } |
@@ -6,7 +6,7 @@ using Model = Discord.API.ApplicationCommandInteractionData; | |||||
namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// Represents the data tied with the <see cref="SocketSlashCommand"/> interaction. | |||||
/// Represents the data tied with the <see cref="SocketApplicationUserCommand"/> interaction. | |||||
/// </summary> | /// </summary> | ||||
public class SocketApplicationUserCommandData : SocketEntity<ulong>, IApplicationCommandInteractionData | public class SocketApplicationUserCommandData : SocketEntity<ulong>, IApplicationCommandInteractionData | ||||
{ | { | ||||
@@ -10,7 +10,7 @@ namespace Discord.WebSocket | |||||
/// <summary> | /// <summary> | ||||
/// Represents a Websocket-based slash command received over the gateway. | /// Represents a Websocket-based slash command received over the gateway. | ||||
/// </summary> | /// </summary> | ||||
public class SocketSlashCommand : SocketInteraction | |||||
public class SocketSlashCommand : SocketCommandBase | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// The data associated with this interaction. | /// The data associated with this interaction. | ||||
@@ -18,7 +18,7 @@ namespace Discord.WebSocket | |||||
new public SocketSlashCommandData Data { get; } | new public SocketSlashCommandData Data { get; } | ||||
internal SocketSlashCommand(DiscordSocketClient client, Model model, ISocketMessageChannel channel) | internal SocketSlashCommand(DiscordSocketClient client, Model model, ISocketMessageChannel channel) | ||||
: base(client, model.Id, channel) | |||||
: base(client, model, channel) | |||||
{ | { | ||||
var dataModel = model.Data.IsSpecified ? | var dataModel = model.Data.IsSpecified ? | ||||
(DataModel)model.Data.Value | (DataModel)model.Data.Value | ||||
@@ -36,130 +36,6 @@ namespace Discord.WebSocket | |||||
var entity = new SocketSlashCommand(client, model, channel); | var entity = new SocketSlashCommand(client, model, channel); | ||||
entity.Update(model); | entity.Update(model); | ||||
return entity; | return entity; | ||||
} | |||||
internal override void Update(Model model) | |||||
{ | |||||
var data = model.Data.IsSpecified ? | |||||
(DataModel)model.Data.Value | |||||
: null; | |||||
this.Data.Update(data); | |||||
base.Update(model); | |||||
} | |||||
/// <inheritdoc/> | |||||
public override async Task RespondAsync( | |||||
string text = null, | |||||
Embed[] embeds = null, | |||||
bool isTTS = false, | |||||
bool ephemeral = false, | |||||
AllowedMentions allowedMentions = null, | |||||
RequestOptions options = null, | |||||
MessageComponent component = null, | |||||
Embed embed = null) | |||||
{ | |||||
if (!IsValidToken) | |||||
throw new InvalidOperationException("Interaction token is no longer valid"); | |||||
if (embeds == null && embed != null) | |||||
embeds = new[] { embed }; | |||||
if (Discord.AlwaysAcknowledgeInteractions) | |||||
{ | |||||
await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, options, component); | |||||
return; | |||||
} | |||||
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); | |||||
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); | |||||
Preconditions.AtMost(embeds?.Length ?? 0, 10, nameof(embeds), "A max of 10 embeds are allowed."); | |||||
// check that user flag and user Id list are exclusive, same with role flag and role Id list | |||||
if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) | |||||
{ | |||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) && | |||||
allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0) | |||||
{ | |||||
throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions)); | |||||
} | |||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) && | |||||
allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0) | |||||
{ | |||||
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions)); | |||||
} | |||||
} | |||||
var response = new API.InteractionResponse | |||||
{ | |||||
Type = InteractionResponseType.ChannelMessageWithSource, | |||||
Data = new API.InteractionCallbackData | |||||
{ | |||||
Content = text, | |||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified, | |||||
Embeds = embeds?.Select(x => x.ToModel()).ToArray() ?? Optional<API.Embed[]>.Unspecified, | |||||
TTS = isTTS ? true : Optional<bool>.Unspecified, | |||||
Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified | |||||
} | |||||
}; | |||||
if (ephemeral) | |||||
response.Data.Value.Flags = 64; | |||||
await InteractionHelper.SendInteractionResponse(this.Discord, response, this.Id, Token, options); | |||||
} | |||||
/// <inheritdoc/> | |||||
public override async Task<RestFollowupMessage> FollowupAsync( | |||||
string text = null, | |||||
Embed[] embeds = null, | |||||
bool isTTS = false, | |||||
bool ephemeral = false, | |||||
AllowedMentions allowedMentions = null, | |||||
RequestOptions options = null, | |||||
MessageComponent component = null, | |||||
Embed embed = null) | |||||
{ | |||||
if (!IsValidToken) | |||||
throw new InvalidOperationException("Interaction token is no longer valid"); | |||||
if (embeds == null && embed != null) | |||||
embeds = new[] { embed }; | |||||
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); | |||||
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); | |||||
Preconditions.AtMost(embeds?.Length ?? 0, 10, nameof(embeds), "A max of 10 embeds are allowed."); | |||||
var args = new API.Rest.CreateWebhookMessageParams | |||||
{ | |||||
Content = text, | |||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified, | |||||
IsTTS = isTTS, | |||||
Embeds = embeds?.Select(x => x.ToModel()).ToArray() ?? Optional<API.Embed[]>.Unspecified, | |||||
Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified | |||||
}; | |||||
if (ephemeral) | |||||
args.Flags = 64; | |||||
return await InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options); | |||||
} | |||||
/// <summary> | |||||
/// Acknowledges this interaction with the <see cref="InteractionResponseType.DeferredChannelMessageWithSource"/>. | |||||
/// </summary> | |||||
/// <returns> | |||||
/// A task that represents the asynchronous operation of acknowledging the interaction. | |||||
/// </returns> | |||||
public override Task DeferAsync(RequestOptions options = null) | |||||
{ | |||||
var response = new API.InteractionResponse | |||||
{ | |||||
Type = InteractionResponseType.DeferredChannelMessageWithSource, | |||||
}; | |||||
return Discord.Rest.ApiClient.CreateInteractionResponse(response, this.Id, this.Token, options); | |||||
} | |||||
} | |||||
} | } | ||||
} | } |
@@ -0,0 +1,164 @@ | |||||
using Discord.Rest; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using DataModel = Discord.API.ApplicationCommandInteractionData; | |||||
using Model = Discord.API.Interaction; | |||||
namespace Discord.WebSocket | |||||
{ | |||||
public class SocketCommandBase : SocketInteraction | |||||
{ | |||||
/// <summary> | |||||
/// The data associated with this interaction. | |||||
/// </summary> | |||||
new internal SocketCommandBaseData Data { get; } | |||||
internal SocketCommandBase(DiscordSocketClient client, Model model, ISocketMessageChannel channel) | |||||
: base(client, model.Id, channel) | |||||
{ | |||||
var dataModel = model.Data.IsSpecified ? | |||||
(DataModel)model.Data.Value | |||||
: null; | |||||
ulong? guildId = null; | |||||
if (this.Channel is SocketGuildChannel guildChannel) | |||||
guildId = guildChannel.Guild.Id; | |||||
Data = SocketCommandBaseData.Create(client, dataModel, model.Id, guildId); | |||||
} | |||||
new internal static SocketInteraction Create(DiscordSocketClient client, Model model, ISocketMessageChannel channel) | |||||
{ | |||||
var entity = new SocketSlashCommand(client, model, channel); | |||||
entity.Update(model); | |||||
return entity; | |||||
} | |||||
internal override void Update(Model model) | |||||
{ | |||||
var data = model.Data.IsSpecified ? | |||||
(DataModel)model.Data.Value | |||||
: null; | |||||
this.Data.Update(data); | |||||
base.Update(model); | |||||
} | |||||
/// <inheritdoc/> | |||||
public override async Task RespondAsync( | |||||
string text = null, | |||||
Embed[] embeds = null, | |||||
bool isTTS = false, | |||||
bool ephemeral = false, | |||||
AllowedMentions allowedMentions = null, | |||||
RequestOptions options = null, | |||||
MessageComponent component = null, | |||||
Embed embed = null) | |||||
{ | |||||
if (!IsValidToken) | |||||
throw new InvalidOperationException("Interaction token is no longer valid"); | |||||
if (embeds == null && embed != null) | |||||
embeds = new[] { embed }; | |||||
if (Discord.AlwaysAcknowledgeInteractions) | |||||
{ | |||||
await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, options, component); | |||||
return; | |||||
} | |||||
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); | |||||
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); | |||||
Preconditions.AtMost(embeds?.Length ?? 0, 10, nameof(embeds), "A max of 10 embeds are allowed."); | |||||
// check that user flag and user Id list are exclusive, same with role flag and role Id list | |||||
if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) | |||||
{ | |||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) && | |||||
allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0) | |||||
{ | |||||
throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions)); | |||||
} | |||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) && | |||||
allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0) | |||||
{ | |||||
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions)); | |||||
} | |||||
} | |||||
var response = new API.InteractionResponse | |||||
{ | |||||
Type = InteractionResponseType.ChannelMessageWithSource, | |||||
Data = new API.InteractionCallbackData | |||||
{ | |||||
Content = text, | |||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified, | |||||
Embeds = embeds?.Select(x => x.ToModel()).ToArray() ?? Optional<API.Embed[]>.Unspecified, | |||||
TTS = isTTS ? true : Optional<bool>.Unspecified, | |||||
Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified | |||||
} | |||||
}; | |||||
if (ephemeral) | |||||
response.Data.Value.Flags = 64; | |||||
await InteractionHelper.SendInteractionResponse(this.Discord, response, this.Id, Token, options); | |||||
} | |||||
/// <inheritdoc/> | |||||
public override async Task<RestFollowupMessage> FollowupAsync( | |||||
string text = null, | |||||
Embed[] embeds = null, | |||||
bool isTTS = false, | |||||
bool ephemeral = false, | |||||
AllowedMentions allowedMentions = null, | |||||
RequestOptions options = null, | |||||
MessageComponent component = null, | |||||
Embed embed = null) | |||||
{ | |||||
if (!IsValidToken) | |||||
throw new InvalidOperationException("Interaction token is no longer valid"); | |||||
if (embeds == null && embed != null) | |||||
embeds = new[] { embed }; | |||||
Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); | |||||
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); | |||||
Preconditions.AtMost(embeds?.Length ?? 0, 10, nameof(embeds), "A max of 10 embeds are allowed."); | |||||
var args = new API.Rest.CreateWebhookMessageParams | |||||
{ | |||||
Content = text, | |||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified, | |||||
IsTTS = isTTS, | |||||
Embeds = embeds?.Select(x => x.ToModel()).ToArray() ?? Optional<API.Embed[]>.Unspecified, | |||||
Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified | |||||
}; | |||||
if (ephemeral) | |||||
args.Flags = 64; | |||||
return await InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options); | |||||
} | |||||
/// <summary> | |||||
/// Acknowledges this interaction with the <see cref="InteractionResponseType.DeferredChannelMessageWithSource"/>. | |||||
/// </summary> | |||||
/// <returns> | |||||
/// A task that represents the asynchronous operation of acknowledging the interaction. | |||||
/// </returns> | |||||
public override Task DeferAsync(RequestOptions options = null) | |||||
{ | |||||
var response = new API.InteractionResponse | |||||
{ | |||||
Type = InteractionResponseType.DeferredChannelMessageWithSource, | |||||
}; | |||||
return Discord.Rest.ApiClient.CreateInteractionResponse(response, this.Id, this.Token, options); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,145 @@ | |||||
using System.Collections.Generic; | |||||
using System.Collections.Immutable; | |||||
using System.Linq; | |||||
using Model = Discord.API.ApplicationCommandInteractionData; | |||||
namespace Discord.WebSocket | |||||
{ | |||||
public class SocketCommandBaseData : SocketEntity<ulong>, IApplicationCommandInteractionData | |||||
{ | |||||
public string Name { get; private set; } | |||||
public IReadOnlyCollection<SocketCommandBaseDataOption> Options { get; private set; } | |||||
// id | |||||
// type | |||||
internal Dictionary<ulong, SocketGuildUser> guildMembers { get; private set; } | |||||
= new Dictionary<ulong, SocketGuildUser>(); | |||||
internal Dictionary<ulong, SocketGlobalUser> users { get; private set; } | |||||
= new Dictionary<ulong, SocketGlobalUser>(); | |||||
internal Dictionary<ulong, SocketChannel> channels { get; private set; } | |||||
= new Dictionary<ulong, SocketChannel>(); | |||||
internal Dictionary<ulong, SocketRole> roles { get; private set; } | |||||
= new Dictionary<ulong, SocketRole>(); | |||||
private ulong? guildId; | |||||
internal SocketMessage Message { get; private set; } | |||||
private ApplicationCommandType Type { get; set; } | |||||
internal SocketCommandBaseData(DiscordSocketClient client, Model model, ulong? guildId) | |||||
: base(client, model.Id) | |||||
{ | |||||
this.guildId = guildId; | |||||
this.Type = (ApplicationCommandType)model.Type; | |||||
if (model.Resolved.IsSpecified) | |||||
{ | |||||
var guild = this.guildId.HasValue ? Discord.GetGuild(this.guildId.Value) : null; | |||||
var resolved = model.Resolved.Value; | |||||
if (resolved.Users.IsSpecified) | |||||
{ | |||||
foreach (var user in resolved.Users.Value) | |||||
{ | |||||
var socketUser = Discord.GetOrCreateUser(this.Discord.State, user.Value); | |||||
this.users.Add(ulong.Parse(user.Key), socketUser); | |||||
} | |||||
} | |||||
if (resolved.Channels.IsSpecified) | |||||
{ | |||||
foreach (var channel in resolved.Channels.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); | |||||
} | |||||
} | |||||
if (resolved.Members.IsSpecified) | |||||
{ | |||||
foreach (var member in resolved.Members.Value) | |||||
{ | |||||
member.Value.User = resolved.Users.Value[member.Key]; | |||||
var user = guild.AddOrUpdateUser(member.Value); | |||||
this.guildMembers.Add(ulong.Parse(member.Key), user); | |||||
} | |||||
} | |||||
if (resolved.Roles.IsSpecified) | |||||
{ | |||||
foreach (var role in resolved.Roles.Value) | |||||
{ | |||||
var socketRole = guild.AddOrUpdateRole(role.Value); | |||||
this.roles.Add(ulong.Parse(role.Key), socketRole); | |||||
} | |||||
} | |||||
if (resolved.Messages.IsSpecified) | |||||
{ | |||||
foreach (var msg in resolved.Messages.Value) | |||||
{ | |||||
var channel = client.GetChannel(msg.Value.ChannelId) as ISocketMessageChannel; | |||||
SocketUser author; | |||||
if (guild != null) | |||||
{ | |||||
if (msg.Value.WebhookId.IsSpecified) | |||||
author = SocketWebhookUser.Create(guild, client.State, msg.Value.Author.Value, msg.Value.WebhookId.Value); | |||||
else | |||||
author = guild.GetUser(msg.Value.Author.Value.Id); | |||||
} | |||||
else | |||||
author = (channel as SocketChannel).GetUser(msg.Value.Author.Value.Id); | |||||
if (channel == null) | |||||
{ | |||||
if (!msg.Value.GuildId.IsSpecified) // assume it is a DM | |||||
{ | |||||
channel = client.CreateDMChannel(msg.Value.ChannelId, msg.Value.Author.Value, client.State); | |||||
} | |||||
} | |||||
this.Message = SocketMessage.Create(client, client.State, author, channel, msg.Value); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
internal static SocketCommandBaseData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId) | |||||
{ | |||||
var entity = new SocketCommandBaseData(client, model, guildId); | |||||
entity.Update(model); | |||||
return entity; | |||||
} | |||||
internal void Update(Model model) | |||||
{ | |||||
this.Name = model.Name; | |||||
this.Options = model.Options.IsSpecified | |||||
? model.Options.Value.Select(x => new SocketCommandBaseDataOption(this, x)).ToImmutableArray() | |||||
: null; | |||||
} | |||||
IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionData.Options => Options; | |||||
} | |||||
} |
@@ -0,0 +1,130 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Collections.Immutable; | |||||
using System.Linq; | |||||
using System.Reflection; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Model = Discord.API.ApplicationCommandInteractionDataOption; | |||||
namespace Discord.WebSocket | |||||
{ | |||||
public class SocketCommandBaseDataOption : IApplicationCommandInteractionDataOption | |||||
{ | |||||
public string Name { get; private set; } | |||||
/// <inheritdoc/> | |||||
public object Value { get; private set; } | |||||
/// <inheritdoc/> | |||||
public ApplicationCommandOptionType Type { get; private set; } | |||||
/// <summary> | |||||
/// The sub command options received for this sub command group. | |||||
/// </summary> | |||||
public IReadOnlyCollection<IApplicationCommandInteractionDataOption> Options { get; private set; } | |||||
internal SocketCommandBaseDataOption() { } | |||||
internal SocketCommandBaseDataOption(SocketCommandBaseData data, Model model) | |||||
{ | |||||
this.Name = model.Name; | |||||
this.Type = model.Type; | |||||
if (model.Value.IsSpecified) | |||||
{ | |||||
switch (Type) | |||||
{ | |||||
case ApplicationCommandOptionType.User: | |||||
case ApplicationCommandOptionType.Role: | |||||
case ApplicationCommandOptionType.Channel: | |||||
case ApplicationCommandOptionType.Mentionable: | |||||
if (ulong.TryParse($"{model.Value.Value}", out var valueId)) | |||||
{ | |||||
switch (this.Type) | |||||
{ | |||||
case ApplicationCommandOptionType.User: | |||||
{ | |||||
var guildUser = data.guildMembers.FirstOrDefault(x => x.Key == valueId).Value; | |||||
if (guildUser != null) | |||||
this.Value = guildUser; | |||||
else | |||||
this.Value = data.users.FirstOrDefault(x => x.Key == valueId).Value; | |||||
} | |||||
break; | |||||
case ApplicationCommandOptionType.Channel: | |||||
this.Value = data.channels.FirstOrDefault(x => x.Key == valueId).Value; | |||||
break; | |||||
case ApplicationCommandOptionType.Role: | |||||
this.Value = data.roles.FirstOrDefault(x => x.Key == valueId).Value; | |||||
break; | |||||
case ApplicationCommandOptionType.Mentionable: | |||||
{ | |||||
if (data.guildMembers.Any(x => x.Key == valueId) || data.users.Any(x => x.Key == valueId)) | |||||
{ | |||||
var guildUser = data.guildMembers.FirstOrDefault(x => x.Key == valueId).Value; | |||||
if (guildUser != null) | |||||
this.Value = guildUser; | |||||
else | |||||
this.Value = data.users.FirstOrDefault(x => x.Key == valueId).Value; | |||||
} | |||||
else if (data.roles.Any(x => x.Key == valueId)) | |||||
{ | |||||
this.Value = data.roles.FirstOrDefault(x => x.Key == valueId).Value; | |||||
} | |||||
} | |||||
break; | |||||
default: | |||||
this.Value = model.Value.Value; | |||||
break; | |||||
} | |||||
} | |||||
break; | |||||
case ApplicationCommandOptionType.String: | |||||
this.Value = model.Value.ToString(); | |||||
break; | |||||
case ApplicationCommandOptionType.Integer: | |||||
{ | |||||
if (model.Value.Value is int val) | |||||
this.Value = val; | |||||
else if (int.TryParse(model.Value.Value.ToString(), out int res)) | |||||
this.Value = res; | |||||
} | |||||
break; | |||||
case ApplicationCommandOptionType.Boolean: | |||||
{ | |||||
if (model.Value.Value is bool val) | |||||
this.Value = val; | |||||
else if (bool.TryParse(model.Value.Value.ToString(), out bool res)) | |||||
this.Value = res; | |||||
} | |||||
break; | |||||
case ApplicationCommandOptionType.Number: | |||||
{ | |||||
if (model.Value.Value is int val) | |||||
this.Value = val; | |||||
else if (double.TryParse(model.Value.Value.ToString(), out double res)) | |||||
this.Value = res; | |||||
} | |||||
break; | |||||
} | |||||
} | |||||
this.Options = model.Options.IsSpecified | |||||
? model.Options.Value.Select(x => new SocketCommandBaseDataOption(data, x)).ToImmutableArray() | |||||
: null; | |||||
} | |||||
// Converters | |||||
public static explicit operator bool(SocketCommandBaseDataOption option) | |||||
=> (bool)option.Value; | |||||
public static explicit operator int(SocketCommandBaseDataOption option) | |||||
=> (int)option.Value; | |||||
public static explicit operator string(SocketCommandBaseDataOption option) | |||||
=> option.Value.ToString(); | |||||
IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionDataOption.Options => this.Options; | |||||
} | |||||
} |
@@ -62,12 +62,13 @@ namespace Discord.WebSocket | |||||
internal static SocketInteraction Create(DiscordSocketClient client, Model model, ISocketMessageChannel channel) | internal static SocketInteraction Create(DiscordSocketClient client, Model model, ISocketMessageChannel channel) | ||||
{ | { | ||||
if (model.Type == InteractionType.ApplicationCommand) | if (model.Type == InteractionType.ApplicationCommand) | ||||
if(model.ApplicationId != null) | |||||
{ | |||||
if (model.ApplicationId != null) | |||||
{ | { | ||||
var dataModel = model.Data.IsSpecified ? | var dataModel = model.Data.IsSpecified ? | ||||
(DataModel)model.Data.Value | (DataModel)model.Data.Value | ||||
: null; | : null; | ||||
if(dataModel != null) | |||||
if (dataModel != null) | |||||
{ | { | ||||
if (dataModel.Type.Equals(ApplicationCommandType.User)) | if (dataModel.Type.Equals(ApplicationCommandType.User)) | ||||
return SocketApplicationUserCommand.Create(client, model, channel); | return SocketApplicationUserCommand.Create(client, model, channel); | ||||
@@ -76,6 +77,7 @@ namespace Discord.WebSocket | |||||
} | } | ||||
} | } | ||||
return SocketSlashCommand.Create(client, model, channel); | return SocketSlashCommand.Create(client, model, channel); | ||||
} | |||||
if (model.Type == InteractionType.MessageComponent) | if (model.Type == InteractionType.MessageComponent) | ||||
return SocketMessageComponent.Create(client, model, channel); | return SocketMessageComponent.Create(client, model, channel); | ||||
else | else | ||||