Browse Source

Added resolved entity support (untested), closes #21. Added GetOriginalResponseAsync to SocketInteraction. Fixed a few null bugs

pull/1923/head
quin lynch 4 years ago
parent
commit
b394987d77
18 changed files with 202 additions and 129 deletions
  1. +1
    -1
      src/Discord.Net.Core/Discord.Net.Core.csproj
  2. +10
    -0
      src/Discord.Net.Core/Discord.Net.Core.xml
  3. +6
    -1
      src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOptionType.cs
  4. +5
    -0
      src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionDataOption.cs
  5. +1
    -1
      src/Discord.Net.Core/Entities/Interactions/SlashCommandBuilder.cs
  6. +5
    -1
      src/Discord.Net.Rest/API/Common/ApplicationCommandInteractionData.cs
  7. +4
    -4
      src/Discord.Net.Rest/API/Common/ApplicationCommandInteractionDataResolved.cs
  8. +1
    -1
      src/Discord.Net.Rest/Discord.Net.Rest.csproj
  9. +9
    -9
      src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs
  10. +1
    -1
      src/Discord.Net.WebSocket/Discord.Net.WebSocket.csproj
  11. +17
    -34
      src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml
  12. +1
    -1
      src/Discord.Net.WebSocket/DiscordSocketClient.cs
  13. +10
    -0
      src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
  14. +6
    -3
      src/Discord.Net.WebSocket/Entities/Interaction/Message Components/SocketMessageComponent.cs
  15. +27
    -37
      src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommand.cs
  16. +61
    -5
      src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandData.cs
  17. +26
    -26
      src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandDataOption.cs
  18. +11
    -4
      src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs

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

@@ -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>


+ 10
- 0
src/Discord.Net.Core/Discord.Net.Core.xml View File

@@ -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.


+ 6
- 1
src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOptionType.cs View File

@@ -49,6 +49,11 @@ namespace Discord
/// <summary>
/// A <see cref="IRole"/>.
/// </summary>
Role = 8
Role = 8,

/// <summary>
///
/// </summary>
Mentionable = 9
}
}

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

@@ -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>


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

@@ -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
};
}


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

@@ -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; }

}
}

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

@@ -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; }
}
}

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

@@ -9,7 +9,7 @@
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0;netstandard2.1</TargetFrameworks>
<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>


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

@@ -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);


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

@@ -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>


+ 17
- 34
src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml View File

@@ -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"/>.


+ 1
- 1
src/Discord.Net.WebSocket/DiscordSocketClient.cs View File

@@ -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;


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

@@ -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)


+ 6
- 3
src/Discord.Net.WebSocket/Entities/Interaction/Message Components/SocketMessageComponent.cs View File

@@ -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>


+ 27
- 37
src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommand.cs View File

@@ -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)


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

@@ -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;
}



+ 26
- 26
src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommandDataOption.cs View File

@@ -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;
}
}

+ 11
- 4
src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs View File

@@ -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>


Loading…
Cancel
Save