@@ -8,7 +8,7 @@ | |||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net461;netstandard2.0;netstandard2.1</TargetFrameworks> | |||
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0;netstandard2.1</TargetFrameworks> | |||
<PackageId>Discord.Net.Labs.Core</PackageId> | |||
<Version>2.3.8</Version> | |||
<Version>2.3.9-pre</Version> | |||
<Product>Discord.Net.Labs.Core</Product> | |||
<RepositoryUrl>https://github.com/Discord-Net-Labs/Discord.Net-Labs</RepositoryUrl> | |||
<PackageIcon>Temporary.png</PackageIcon> | |||
@@ -3932,6 +3932,11 @@ | |||
A <see cref="T:Discord.IRole"/>. | |||
</summary> | |||
</member> | |||
<member name="F:Discord.ApplicationCommandOptionType.Mentionable"> | |||
<summary> | |||
</summary> | |||
</member> | |||
<member name="T:Discord.ApplicationCommandProperties"> | |||
<summary> | |||
Provides properties that are used to modify a <see cref="T:Discord.IApplicationCommand" /> with the specified changes. | |||
@@ -4032,6 +4037,11 @@ | |||
</note> | |||
</summary> | |||
</member> | |||
<member name="P:Discord.IApplicationCommandInteractionDataOption.Type"> | |||
<summary> | |||
The type of this data's option. | |||
</summary> | |||
</member> | |||
<member name="P:Discord.IApplicationCommandInteractionDataOption.Options"> | |||
<summary> | |||
Present if this option is a group or subcommand. | |||
@@ -49,6 +49,11 @@ namespace Discord | |||
/// <summary> | |||
/// A <see cref="IRole"/>. | |||
/// </summary> | |||
Role = 8 | |||
Role = 8, | |||
/// <summary> | |||
/// | |||
/// </summary> | |||
Mentionable = 9 | |||
} | |||
} |
@@ -24,6 +24,11 @@ namespace Discord | |||
/// </summary> | |||
object Value { get; } | |||
/// <summary> | |||
/// The type of this data's option. | |||
/// </summary> | |||
ApplicationCommandOptionType Type { get; } | |||
/// <summary> | |||
/// Present if this option is a group or subcommand. | |||
/// </summary> | |||
@@ -341,7 +341,7 @@ namespace Discord | |||
Default = this.Default, | |||
Required = this.Required, | |||
Type = this.Type, | |||
Options = new List<ApplicationCommandOptionProperties>(this.Options.Select(x => x.Build())), | |||
Options = this.Options?.Count > 0 ? new List<ApplicationCommandOptionProperties>(this.Options.Select(x => x.Build())) : null, | |||
Choices = this.Choices | |||
}; | |||
} | |||
@@ -12,6 +12,10 @@ namespace Discord.API | |||
public string Name { get; set; } | |||
[JsonProperty("options")] | |||
public List<ApplicationCommandInteractionDataOption> Options { get; set; } = new(); | |||
public List<ApplicationCommandInteractionDataOption> Options { get; set; } | |||
[JsonProperty("resolved")] | |||
public Optional<ApplicationCommandInteractionDataResolved> Resolved { get; set; } | |||
} | |||
} |
@@ -6,15 +6,15 @@ namespace Discord.API | |||
internal class ApplicationCommandInteractionDataResolved | |||
{ | |||
[JsonProperty("users")] | |||
public Optional<Dictionary<ulong, User>> Users { get; set; } | |||
public Optional<Dictionary<string, User>> Users { get; set; } | |||
[JsonProperty("members")] | |||
public Optional<Dictionary<ulong, GuildMember>> Members { get; set; } | |||
public Optional<Dictionary<string, GuildMember>> Members { get; set; } | |||
[JsonProperty("channels")] | |||
public Optional<Dictionary<ulong, Channel>> Channels { get; set; } | |||
public Optional<Dictionary<string, Channel>> Channels { get; set; } | |||
[JsonProperty("roles")] | |||
public Optional<Dictionary<ulong, Role>> Roles { get; set; } | |||
public Optional<Dictionary<string, Role>> Roles { get; set; } | |||
} | |||
} |
@@ -9,7 +9,7 @@ | |||
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0;netstandard2.1</TargetFrameworks> | |||
<PackageIcon>Temporary.png</PackageIcon> | |||
<PackageProjectUrl>https://github.com/Discord-Net-Labs/Discord.Net-Labs</PackageProjectUrl> | |||
<Version>2.3.8</Version> | |||
<Version>2.3.9-pre</Version> | |||
<PackageId>Discord.Net.Labs.Rest</PackageId> | |||
<RepositoryUrl>https://github.com/Discord-Net-Labs/Discord.Net-Labs</RepositoryUrl> | |||
<AssemblyVersion>2.3.4</AssemblyVersion> | |||
@@ -10,20 +10,20 @@ namespace Discord.Rest | |||
{ | |||
internal static class InteractionHelper | |||
{ | |||
internal static async Task<RestInteractionMessage> SendInteractionResponse(BaseDiscordClient client, IMessageChannel channel, InteractionResponse response, | |||
internal static Task SendInteractionResponse(BaseDiscordClient client, IMessageChannel channel, InteractionResponse response, | |||
ulong interactionId, string interactionToken, RequestOptions options = null) | |||
{ | |||
await client.ApiClient.CreateInteractionResponse(response, interactionId, interactionToken, options).ConfigureAwait(false); | |||
// get the original message | |||
var msg = await client.ApiClient.GetInteractionResponse(interactionToken).ConfigureAwait(false); | |||
var entity = RestInteractionMessage.Create(client, msg, interactionToken, channel); | |||
return client.ApiClient.CreateInteractionResponse(response, interactionId, interactionToken, options); | |||
} | |||
return entity; | |||
internal static async Task<RestInteractionMessage> GetOriginalResponseAsync(BaseDiscordClient client, IMessageChannel channel, | |||
IDiscordInteraction interaction, RequestOptions options = null) | |||
{ | |||
var model = await client.ApiClient.GetInteractionResponse(interaction.Token, options).ConfigureAwait(false); | |||
return RestInteractionMessage.Create(client, model, interaction.Token, channel); | |||
} | |||
internal static async Task<RestFollowupMessage> SendFollowupAsync(BaseDiscordClient client, API.Rest.CreateWebhookMessageParams args, | |||
internal static async Task<RestFollowupMessage> SendFollowupAsync(BaseDiscordClient client, CreateWebhookMessageParams args, | |||
string token, IMessageChannel channel, RequestOptions options = null) | |||
{ | |||
var model = await client.ApiClient.CreateInteractionFollowupMessage(args, token, options).ConfigureAwait(false); | |||
@@ -8,7 +8,7 @@ | |||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net461;netstandard2.0;netstandard2.1</TargetFrameworks> | |||
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0;netstandard2.1</TargetFrameworks> | |||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | |||
<Version>2.3.8</Version> | |||
<Version>2.3.9-pre</Version> | |||
<RepositoryUrl>https://github.com/Discord-Net-Labs/Discord.Net-Labs</RepositoryUrl> | |||
<PackageProjectUrl>https://github.com/Discord-Net-Labs/Discord.Net-Labs</PackageProjectUrl> | |||
<PackageIcon>Temporary.png</PackageIcon> | |||
@@ -3299,41 +3299,17 @@ | |||
The data associated with this interaction. | |||
</summary> | |||
</member> | |||
<member name="M:Discord.WebSocket.SocketSlashCommand.RespondAsync(System.String,System.Boolean,Discord.Embed,Discord.InteractionResponseType,System.Boolean,Discord.AllowedMentions,Discord.RequestOptions,Discord.MessageComponent)"> | |||
<member name="M:Discord.WebSocket.SocketSlashCommand.GetOriginalResponse"> | |||
<summary> | |||
Responds to an Interaction. | |||
<para> | |||
If you have <see cref="P:Discord.WebSocket.DiscordSocketConfig.AlwaysAcknowledgeInteractions"/> set to <see langword="true"/>, You should use | |||
<see cref="!:FollowupAsync(string, bool, Embed, InteractionResponseType, AllowedMentions, RequestOptions)"/> instead. | |||
</para> | |||
Gets the original response to this slash command. | |||
</summary> | |||
<param name="text">The text of the message to be sent.</param> | |||
<param name="isTTS"><see langword="true"/> if the message should be read out by a text-to-speech reader, otherwise <see langword="false"/>.</param> | |||
<param name="embed">A <see cref="T:Discord.Embed"/> to send with this response.</param> | |||
<param name="type">The type of response to this Interaction.</param> | |||
<param name="ephemeral"><see langword="true"/> if the response should be hidden to everyone besides the invoker of the command, otherwise <see langword="false"/>.</param> | |||
<param name="allowedMentions">The allowed mentions for this response.</param> | |||
<param name="options">The request options for this response.</param> | |||
<returns> | |||
The <see cref="T:Discord.IMessage"/> sent as the response. If this is the first acknowledgement, it will return null. | |||
</returns> | |||
<exception cref="T:System.ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="F:Discord.DiscordConfig.MaxMessageSize"/>.</exception> | |||
<exception cref="T:System.InvalidOperationException">The parameters provided were invalid or the token was invalid.</exception> | |||
<returns>A <see cref="T:Discord.Rest.RestInteractionMessage"/> that represents the initial response to this interaction.</returns> | |||
</member> | |||
<member name="M:Discord.WebSocket.SocketSlashCommand.RespondAsync(System.String,System.Boolean,Discord.Embed,Discord.InteractionResponseType,System.Boolean,Discord.AllowedMentions,Discord.RequestOptions,Discord.MessageComponent)"> | |||
<inheritdoc/> | |||
</member> | |||
<member name="M:Discord.WebSocket.SocketSlashCommand.FollowupAsync(System.String,System.Boolean,Discord.Embed,System.Boolean,Discord.InteractionResponseType,Discord.AllowedMentions,Discord.RequestOptions,Discord.MessageComponent)"> | |||
<summary> | |||
Sends a followup message for this interaction. | |||
</summary> | |||
<param name="text">The text of the message to be sent</param> | |||
<param name="isTTS"><see langword="true"/> if the message should be read out by a text-to-speech reader, otherwise <see langword="false"/>.</param> | |||
<param name="embed">A <see cref="T:Discord.Embed"/> to send with this response.</param> | |||
<param name="type">The type of response to this Interaction.</param> | |||
/// <param name="ephemeral"><see langword="true"/> if the response should be hidden to everyone besides the invoker of the command, otherwise <see langword="false"/>.</param> | |||
<param name="allowedMentions">The allowed mentions for this response.</param> | |||
<param name="options">The request options for this response.</param> | |||
<returns> | |||
The sent message. | |||
</returns> | |||
<inheritdoc/> | |||
</member> | |||
<member name="T:Discord.WebSocket.SocketSlashCommandData"> | |||
<summary> | |||
@@ -3359,6 +3335,9 @@ | |||
<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. | |||
@@ -3420,9 +3399,6 @@ | |||
<param name="allowedMentions">The allowed mentions for this response.</param> | |||
<param name="options">The request options for this response.</param> | |||
<param name="component">A <see cref="T:Discord.MessageComponent"/> to be sent with this response</param> | |||
<returns> | |||
The <see cref="T:Discord.IMessage"/> sent as the response. If this is the first acknowledgement, it will return null. | |||
</returns> | |||
<exception cref="T:System.ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="F:Discord.DiscordConfig.MaxMessageSize"/>.</exception> | |||
<exception cref="T:System.InvalidOperationException">The parameters provided were invalid or the token was invalid.</exception> | |||
</member> | |||
@@ -3442,6 +3418,13 @@ | |||
The sent message. | |||
</returns> | |||
</member> | |||
<member name="M:Discord.WebSocket.SocketInteraction.GetOriginalResponseAsync(Discord.RequestOptions)"> | |||
<summary> | |||
Gets the original response for this interaction. | |||
</summary> | |||
<param name="options">The request options for this async request.</param> | |||
<returns>A <see cref="T:Discord.Rest.RestInteractionMessage"/> that represents the intitial response, or <see langword="null"/> if there is no response.</returns> | |||
</member> | |||
<member name="M:Discord.WebSocket.SocketInteraction.AcknowledgeAsync(Discord.RequestOptions)"> | |||
<summary> | |||
Acknowledges this interaction with the <see cref="F:Discord.InteractionResponseType.DeferredChannelMessageWithSource"/>. | |||
@@ -25,7 +25,7 @@ namespace Discord.WebSocket | |||
public partial class DiscordSocketClient : BaseSocketClient, IDiscordClient | |||
{ | |||
private readonly ConcurrentQueue<ulong> _largeGuilds; | |||
private readonly JsonSerializer _serializer; | |||
internal readonly JsonSerializer _serializer; | |||
private readonly DiscordShardedClient _shardedClient; | |||
private readonly DiscordSocketClient _parentClient; | |||
private readonly ConcurrentQueue<long> _heartbeatTimes; | |||
@@ -794,6 +794,16 @@ namespace Discord.WebSocket | |||
return null; | |||
} | |||
internal SocketRole AddOrUpdateRole(RoleModel model) | |||
{ | |||
if (_roles.TryGetValue(model.Id, out SocketRole role)) | |||
_roles[model.Id].Update(this.Discord.State, model); | |||
else | |||
role = AddRole(model); | |||
return role; | |||
} | |||
//Users | |||
/// <inheritdoc /> | |||
public Task<RestGuildUser> AddGuildUserAsync(ulong id, string accessToken, Action<AddGuildUserProperties> func = null, RequestOptions options = null) | |||
@@ -92,7 +92,7 @@ namespace Discord.WebSocket | |||
/// </returns> | |||
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||
/// <exception cref="InvalidOperationException">The parameters provided were invalid or the token was invalid.</exception> | |||
public override async Task<RestUserMessage> RespondAsync(string text = null, bool isTTS = false, Embed embed = null, InteractionResponseType type = InteractionResponseType.ChannelMessageWithSource, | |||
public override async Task RespondAsync(string text = null, bool isTTS = false, Embed embed = null, InteractionResponseType type = InteractionResponseType.ChannelMessageWithSource, | |||
bool ephemeral = false, AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent component = null) | |||
{ | |||
if (type == InteractionResponseType.Pong) | |||
@@ -102,7 +102,10 @@ namespace Discord.WebSocket | |||
throw new InvalidOperationException("Interaction token is no longer valid"); | |||
if (Discord.AlwaysAcknowledgeInteractions) | |||
return await FollowupAsync(text, isTTS, embed, ephemeral, type, allowedMentions, options); | |||
{ | |||
await FollowupAsync(text, isTTS, embed, ephemeral, type, allowedMentions, options); | |||
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."); | |||
@@ -141,7 +144,7 @@ namespace Discord.WebSocket | |||
if (ephemeral) | |||
response.Data.Value.Flags = 64; | |||
return await InteractionHelper.SendInteractionResponse(this.Discord, this.Channel, response, this.Id, Token, options); | |||
await InteractionHelper.SendInteractionResponse(this.Discord, this.Channel, response, this.Id, Token, options); | |||
} | |||
/// <summary> | |||
@@ -22,10 +22,14 @@ namespace Discord.WebSocket | |||
: base(client, model.Id, channel) | |||
{ | |||
var dataModel = model.Data.IsSpecified ? | |||
(model.Data.Value as JToken).ToObject<DataModel>() | |||
(model.Data.Value as JToken).ToObject<DataModel>(client._serializer) | |||
: null; | |||
Data = SocketSlashCommandData.Create(client, dataModel, model.Id); | |||
ulong? guildId = null; | |||
if (this.Channel is SocketGuildChannel guildChannel) | |||
guildId = guildChannel.Guild.Id; | |||
Data = SocketSlashCommandData.Create(client, dataModel, model.Id, guildId); | |||
} | |||
new internal static SocketInteraction Create(DiscordSocketClient client, Model model, ISocketMessageChannel channel) | |||
@@ -38,7 +42,7 @@ namespace Discord.WebSocket | |||
internal override void Update(Model model) | |||
{ | |||
var data = model.Data.IsSpecified ? | |||
(model.Data.Value as JToken).ToObject<DataModel>() | |||
(model.Data.Value as JToken).ToObject<DataModel>(Discord._serializer) | |||
: null; | |||
this.Data.Update(data); | |||
@@ -47,26 +51,21 @@ namespace Discord.WebSocket | |||
} | |||
/// <summary> | |||
/// Responds to an Interaction. | |||
/// <para> | |||
/// If you have <see cref="DiscordSocketConfig.AlwaysAcknowledgeInteractions"/> set to <see langword="true"/>, You should use | |||
/// <see cref="FollowupAsync(string, bool, Embed, InteractionResponseType, AllowedMentions, RequestOptions)"/> instead. | |||
/// </para> | |||
/// Gets the original response to this slash command. | |||
/// </summary> | |||
/// <param name="text">The text of the message to be sent.</param> | |||
/// <param name="isTTS"><see langword="true"/> if the message should be read out by a text-to-speech reader, otherwise <see langword="false"/>.</param> | |||
/// <param name="embed">A <see cref="Embed"/> to send with this response.</param> | |||
/// <param name="type">The type of response to this Interaction.</param> | |||
/// <param name="ephemeral"><see langword="true"/> if the response should be hidden to everyone besides the invoker of the command, otherwise <see langword="false"/>.</param> | |||
/// <param name="allowedMentions">The allowed mentions for this response.</param> | |||
/// <param name="options">The request options for this response.</param> | |||
/// <returns> | |||
/// The <see cref="IMessage"/> sent as the response. If this is the first acknowledgement, it will return null. | |||
/// </returns> | |||
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||
/// <exception cref="InvalidOperationException">The parameters provided were invalid or the token was invalid.</exception> | |||
public override async Task<RestUserMessage> RespondAsync(string text = null, bool isTTS = false, Embed embed = null, InteractionResponseType type = InteractionResponseType.ChannelMessageWithSource, | |||
/// <returns>A <see cref="RestInteractionMessage"/> that represents the initial response to this interaction.</returns> | |||
public async Task<RestInteractionMessage> GetOriginalResponse() | |||
{ | |||
// get the original message | |||
var msg = await Discord.ApiClient.GetInteractionResponse(this.Token).ConfigureAwait(false); | |||
var entity = RestInteractionMessage.Create(Discord, msg, this.Token, this.Channel); | |||
return entity; | |||
} | |||
/// <inheritdoc/> | |||
public override async Task RespondAsync(string text = null, bool isTTS = false, Embed embed = null, InteractionResponseType type = InteractionResponseType.ChannelMessageWithSource, | |||
bool ephemeral = false, AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent component = null) | |||
{ | |||
if (type == InteractionResponseType.Pong) | |||
@@ -79,7 +78,10 @@ namespace Discord.WebSocket | |||
throw new InvalidOperationException("Interaction token is no longer valid"); | |||
if (Discord.AlwaysAcknowledgeInteractions) | |||
return await FollowupAsync(text, isTTS, embed, ephemeral, type, allowedMentions, options); // The arguments should be passed? What was i thinking... | |||
{ | |||
await FollowupAsync(text, isTTS, embed, ephemeral, type, allowedMentions, options); | |||
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."); | |||
@@ -118,22 +120,10 @@ namespace Discord.WebSocket | |||
if (ephemeral) | |||
response.Data.Value.Flags = 64; | |||
return await InteractionHelper.SendInteractionResponse(this.Discord, this.Channel, response, this.Id, Token, options); | |||
await InteractionHelper.SendInteractionResponse(this.Discord, this.Channel, response, this.Id, Token, options); | |||
} | |||
/// <summary> | |||
/// Sends a followup message for this interaction. | |||
/// </summary> | |||
/// <param name="text">The text of the message to be sent</param> | |||
/// <param name="isTTS"><see langword="true"/> if the message should be read out by a text-to-speech reader, otherwise <see langword="false"/>.</param> | |||
/// <param name="embed">A <see cref="Embed"/> to send with this response.</param> | |||
/// <param name="type">The type of response to this Interaction.</param> | |||
/// /// <param name="ephemeral"><see langword="true"/> if the response should be hidden to everyone besides the invoker of the command, otherwise <see langword="false"/>.</param> | |||
/// <param name="allowedMentions">The allowed mentions for this response.</param> | |||
/// <param name="options">The request options for this response.</param> | |||
/// <returns> | |||
/// The sent message. | |||
/// </returns> | |||
/// <inheritdoc/> | |||
public override async Task<RestFollowupMessage> FollowupAsync(string text = null, bool isTTS = false, Embed embed = null, bool ephemeral = false, | |||
InteractionResponseType type = InteractionResponseType.ChannelMessageWithSource, | |||
AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent component = null) | |||
@@ -18,15 +18,71 @@ namespace Discord.WebSocket | |||
/// </summary> | |||
public IReadOnlyCollection<SocketSlashCommandDataOption> Options { get; private set; } | |||
internal SocketSlashCommandData(DiscordSocketClient client, ulong id) | |||
: base(client, id) | |||
internal Dictionary<ulong, SocketGuildUser> guildMembers { get; private set; } = new(); | |||
internal Dictionary<ulong, SocketGlobalUser> users { get; private set; } = new(); | |||
internal Dictionary<ulong, SocketChannel> channels { get; private set; } = new(); | |||
internal Dictionary<ulong, SocketRole> roles { get; private set; } = new(); | |||
private ulong? guildId; | |||
internal SocketSlashCommandData(DiscordSocketClient client, Model model, ulong? guildId) | |||
: base(client, model.Id) | |||
{ | |||
this.guildId = guildId; | |||
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 = channel.Value.GuildId.IsSpecified | |||
? SocketGuildChannel.Create(Discord.GetGuild(channel.Value.GuildId.Value), Discord.State, channel.Value) | |||
: SocketDMChannel.Create(Discord, Discord.State, channel.Value); | |||
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); | |||
} | |||
} | |||
} | |||
} | |||
internal static SocketSlashCommandData Create(DiscordSocketClient client, Model model, ulong id) | |||
internal static SocketSlashCommandData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId) | |||
{ | |||
var entity = new SocketSlashCommandData(client, model.Id); | |||
var entity = new SocketSlashCommandData(client, model, guildId); | |||
entity.Update(model); | |||
return entity; | |||
} | |||
@@ -35,7 +91,7 @@ namespace Discord.WebSocket | |||
this.Name = model.Name; | |||
this.Options = model.Options.Any() | |||
? model.Options.Select(x => new SocketSlashCommandDataOption(x, this.Discord)).ToImmutableArray() | |||
? model.Options.Select(x => new SocketSlashCommandDataOption(this, x)).ToImmutableArray() | |||
: null; | |||
} | |||
@@ -16,22 +16,25 @@ namespace Discord.WebSocket | |||
/// <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<SocketSlashCommandDataOption> Options { get; private set; } | |||
private DiscordSocketClient discord; | |||
private SocketSlashCommandData data; | |||
internal SocketSlashCommandDataOption() { } | |||
internal SocketSlashCommandDataOption(Model model, DiscordSocketClient discord) | |||
internal SocketSlashCommandDataOption(SocketSlashCommandData data, Model model) | |||
{ | |||
this.Name = model.Name; | |||
this.Value = model.Value.IsSpecified ? model.Value.Value : null; | |||
this.discord = discord; | |||
this.Options = model.Options.Any() | |||
? model.Options.Select(x => new SocketSlashCommandDataOption(x, discord)).ToImmutableArray() | |||
? model.Options.Select(x => new SocketSlashCommandDataOption(data, x)).ToImmutableArray() | |||
: null; | |||
} | |||
@@ -43,16 +46,12 @@ namespace Discord.WebSocket | |||
public static explicit operator string(SocketSlashCommandDataOption option) | |||
=> option.Value.ToString(); | |||
public static explicit operator SocketGuildChannel(SocketSlashCommandDataOption option) | |||
public static explicit operator SocketChannel(SocketSlashCommandDataOption option) | |||
{ | |||
if (option.Value is ulong id) | |||
if(ulong.TryParse(option.Value.ToString(), out ulong id)) | |||
{ | |||
var guild = option.discord.GetGuild(id); | |||
if (guild == null) | |||
return null; | |||
return guild.GetChannel(id); | |||
if (option.data.channels.TryGetValue(id, out var channel)) | |||
return channel; | |||
} | |||
return null; | |||
@@ -60,34 +59,35 @@ namespace Discord.WebSocket | |||
public static explicit operator SocketRole(SocketSlashCommandDataOption option) | |||
{ | |||
if (option.Value is ulong id) | |||
if (ulong.TryParse(option.Value.ToString(), out ulong id)) | |||
{ | |||
var guild = option.discord.GetGuild(id); | |||
if (guild == null) | |||
return null; | |||
return guild.GetRole(id); | |||
if (option.data.roles.TryGetValue(id, out var role)) | |||
return role; | |||
} | |||
return null; | |||
} | |||
public static explicit operator SocketGuildUser(SocketSlashCommandDataOption option) | |||
public static explicit operator SocketUser(SocketSlashCommandDataOption option) | |||
{ | |||
if(option.Value is ulong id) | |||
if (ulong.TryParse(option.Value.ToString(), out ulong id)) | |||
{ | |||
var guild = option.discord.GetGuild(id); | |||
if (option.data.users.TryGetValue(id, out var user)) | |||
return user; | |||
} | |||
if (guild == null) | |||
return null; | |||
return null; | |||
} | |||
return guild.GetUser(id); | |||
} | |||
public static explicit operator SocketGuildUser(SocketSlashCommandDataOption option) | |||
{ | |||
if (option.Value as SocketUser is SocketGuildUser guildUser) | |||
return guildUser; | |||
return null; | |||
} | |||
IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionDataOption.Options => this.Options; | |||
} | |||
} |
@@ -110,13 +110,10 @@ namespace Discord.WebSocket | |||
/// <param name="allowedMentions">The allowed mentions for this response.</param> | |||
/// <param name="options">The request options for this response.</param> | |||
/// <param name="component">A <see cref="MessageComponent"/> to be sent with this response</param> | |||
/// <returns> | |||
/// The <see cref="IMessage"/> sent as the response. If this is the first acknowledgement, it will return null. | |||
/// </returns> | |||
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||
/// <exception cref="InvalidOperationException">The parameters provided were invalid or the token was invalid.</exception> | |||
public abstract Task<RestUserMessage> RespondAsync(string text = null, bool isTTS = false, Embed embed = null, InteractionResponseType type = InteractionResponseType.ChannelMessageWithSource, | |||
public abstract Task RespondAsync(string text = null, bool isTTS = false, Embed embed = null, InteractionResponseType type = InteractionResponseType.ChannelMessageWithSource, | |||
bool ephemeral = false, AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent component = null); | |||
/// <summary> | |||
@@ -137,6 +134,16 @@ namespace Discord.WebSocket | |||
InteractionResponseType type = InteractionResponseType.ChannelMessageWithSource, | |||
AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent component = null); | |||
/// <summary> | |||
/// Gets the original response for this interaction. | |||
/// </summary> | |||
/// <param name="options">The request options for this async request.</param> | |||
/// <returns>A <see cref="RestInteractionMessage"/> that represents the intitial response, or <see langword="null"/> if there is no response.</returns> | |||
public Task<RestInteractionMessage> GetOriginalResponseAsync(RequestOptions options = null) | |||
{ | |||
return InteractionHelper.GetOriginalResponseAsync(this.Discord, this.Channel, this, options); | |||
} | |||
/// <summary> | |||
/// Acknowledges this interaction with the <see cref="InteractionResponseType.DeferredChannelMessageWithSource"/>. | |||
/// </summary> | |||