Browse Source

handling context menu usage events

pull/1923/head
drobbins329 3 years ago
parent
commit
d488744378
8 changed files with 666 additions and 0 deletions
  1. +3
    -0
      src/Discord.Net.Rest/API/Common/ApplicationCommandInteractionData.cs
  2. +2
    -0
      src/Discord.Net.Rest/API/Common/ApplicationCommandInteractionDataResolved.cs
  3. +64
    -0
      src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml
  4. +165
    -0
      src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketApplicationMessageCommand.cs
  5. +140
    -0
      src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketApplicationMessageCommandData.cs
  6. +165
    -0
      src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketApplicationUserCommand.cs
  7. +113
    -0
      src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketApplicationUserCommandData.cs
  8. +14
    -0
      src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs

+ 3
- 0
src/Discord.Net.Rest/API/Common/ApplicationCommandInteractionData.cs View File

@@ -17,5 +17,8 @@ namespace Discord.API
[JsonProperty("resolved")]
public Optional<ApplicationCommandInteractionDataResolved> Resolved { get; set; }

[JsonProperty("type")]
public Optional<ApplicationCommandType> Type { get; set; }

}
}

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

@@ -16,5 +16,7 @@ namespace Discord.API

[JsonProperty("roles")]
public Optional<Dictionary<string, Role>> Roles { get; set; }
[JsonProperty("messages")]
public Optional<Dictionary<string, Message>> Messages { get; set; }
}
}

+ 64
- 0
src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml View File

@@ -3599,6 +3599,70 @@
<member name="M:Discord.WebSocket.SocketGuild.Discord#IGuild#GetWebhooksAsync(Discord.RequestOptions)">
<inheritdoc />
</member>
<member name="T:Discord.WebSocket.SocketApplicationMessageCommand">
<summary>
Represents a Websocket-based slash command received over the gateway.
</summary>
</member>
<member name="P:Discord.WebSocket.SocketApplicationMessageCommand.Data">
<summary>
The data associated with this interaction.
</summary>
</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">
<summary>
Represents the data tied with the <see cref="T:Discord.WebSocket.SocketSlashCommand"/> interaction.
</summary>
</member>
<member name="P:Discord.WebSocket.SocketApplicationMessageCommandData.Name">
<inheritdoc/>
</member>
<member name="T:Discord.WebSocket.SocketApplicationUserCommand">
<summary>
Represents a Websocket-based slash command received over the gateway.
</summary>
</member>
<member name="P:Discord.WebSocket.SocketApplicationUserCommand.Data">
<summary>
The data associated with this interaction.
</summary>
</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">
<summary>
Represents the data tied with the <see cref="T:Discord.WebSocket.SocketSlashCommand"/> interaction.
</summary>
</member>
<member name="P:Discord.WebSocket.SocketApplicationUserCommandData.Name">
<inheritdoc/>
</member>
<member name="T:Discord.WebSocket.SocketMessageComponent">
<summary>
Represents a Websocket-based interaction type for Message Components.


+ 165
- 0
src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketApplicationMessageCommand.cs View File

@@ -0,0 +1,165 @@
using Discord.Rest;
using System;
using System.Linq;
using System.Threading.Tasks;
using DataModel = Discord.API.ApplicationCommandInteractionData;
using Model = Discord.API.Interaction;

namespace Discord.WebSocket
{
/// <summary>
/// Represents a Websocket-based slash command received over the gateway.
/// </summary>
public class SocketApplicationMessageCommand : SocketSlashCommand
{
/// <summary>
/// The data associated with this interaction.
/// </summary>
new public SocketApplicationMessageCommandData Data { get; }

internal SocketApplicationMessageCommand(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
: base(client, model, 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 = SocketApplicationMessageCommandData.Create(client, dataModel, model.Id, guildId);
}

new internal static SocketInteraction Create(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
{
var entity = new SocketApplicationMessageCommand(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);
}
}
}

+ 140
- 0
src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/Message Commands/SocketApplicationMessageCommandData.cs View File

@@ -0,0 +1,140 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Model = Discord.API.ApplicationCommandInteractionData;

namespace Discord.WebSocket
{
/// <summary>
/// Represents the data tied with the <see cref="SocketSlashCommand"/> interaction.
/// </summary>
public class SocketApplicationMessageCommandData : SocketEntity<ulong>, IApplicationCommandInteractionData
{
/// <inheritdoc/>
public string Name { get; private set; }
public SocketMessage Message { get; private set; }

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

IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionData.Options => throw new System.NotImplementedException();

private ulong? guildId;

private ApplicationCommandType Type;

internal SocketApplicationMessageCommandData(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 SocketApplicationMessageCommandData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId)
{
var entity = new SocketApplicationMessageCommandData(client, model, guildId);
entity.Update(model);
return entity;
}
internal void Update(Model model)
{
this.Name = model.Name;
}
}
}

+ 165
- 0
src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketApplicationUserCommand.cs View File

@@ -0,0 +1,165 @@
using Discord.Rest;
using System;
using System.Linq;
using System.Threading.Tasks;
using DataModel = Discord.API.ApplicationCommandInteractionData;
using Model = Discord.API.Interaction;

namespace Discord.WebSocket
{
/// <summary>
/// Represents a Websocket-based slash command received over the gateway.
/// </summary>
public class SocketApplicationUserCommand : SocketSlashCommand
{
/// <summary>
/// The data associated with this interaction.
/// </summary>
new public SocketApplicationUserCommandData Data { get; }

internal SocketApplicationUserCommand(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
: base(client, model, 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 = SocketApplicationUserCommandData.Create(client, dataModel, model.Id, guildId);
}

new internal static SocketInteraction Create(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
{
var entity = new SocketApplicationUserCommand(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);
}
}
}

+ 113
- 0
src/Discord.Net.WebSocket/Entities/Interaction/Context Menu Commands/User Commands/SocketApplicationUserCommandData.cs View File

@@ -0,0 +1,113 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Model = Discord.API.ApplicationCommandInteractionData;

namespace Discord.WebSocket
{
/// <summary>
/// Represents the data tied with the <see cref="SocketSlashCommand"/> interaction.
/// </summary>
public class SocketApplicationUserCommandData : SocketEntity<ulong>, IApplicationCommandInteractionData
{
/// <inheritdoc/>
public string Name { get; private set; }

public SocketUser Member { get; private set; }

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

IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionData.Options => throw new System.NotImplementedException();

private ulong? guildId;

private ApplicationCommandType Type;

internal SocketApplicationUserCommandData(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);
this.Member = 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 SocketApplicationUserCommandData Create(DiscordSocketClient client, Model model, ulong id, ulong? guildId)
{
var entity = new SocketApplicationUserCommandData(client, model, guildId);
entity.Update(model);
return entity;
}
internal void Update(Model model)
{
this.Name = model.Name;
}
}
}

+ 14
- 0
src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs View File

@@ -2,6 +2,7 @@ using Discord.Rest;
using System;
using System.Threading.Tasks;
using Model = Discord.API.Interaction;
using DataModel = Discord.API.ApplicationCommandInteractionData;

namespace Discord.WebSocket
{
@@ -61,6 +62,19 @@ namespace Discord.WebSocket
internal static SocketInteraction Create(DiscordSocketClient client, Model model, ISocketMessageChannel channel)
{
if (model.Type == InteractionType.ApplicationCommand)
if(model.ApplicationId != null)
{
var dataModel = model.Data.IsSpecified ?
(DataModel)model.Data.Value
: null;
if(dataModel != null)
{
if (dataModel.Type.Equals(ApplicationCommandType.User))
return SocketApplicationUserCommand.Create(client, model, channel);
if (dataModel.Type.Equals(ApplicationCommandType.Message))
return SocketApplicationMessageCommand.Create(client, model, channel);
}
}
return SocketSlashCommand.Create(client, model, channel);
if (model.Type == InteractionType.MessageComponent)
return SocketMessageComponent.Create(client, model, channel);


Loading…
Cancel
Save