@@ -21,5 +21,10 @@ namespace Discord | |||
/// Gets or sets the embed the message should display. | |||
/// </summary> | |||
public Optional<Embed> Embed { get; set; } | |||
/// <summary> | |||
/// Gets or sets the components for this message. | |||
/// </summary> | |||
public Optional<MessageComponent> Components { get; set; } | |||
} | |||
} |
@@ -1,4 +1,4 @@ | |||
#pragma warning disable CS1591 | |||
#pragma warning disable CS1591 | |||
using Newtonsoft.Json; | |||
namespace Discord.API.Rest | |||
@@ -10,5 +10,7 @@ namespace Discord.API.Rest | |||
public Optional<string> Content { get; set; } | |||
[JsonProperty("embed")] | |||
public Optional<Embed> Embed { get; set; } | |||
[JsonProperty("components")] | |||
public Optional<API.ActionRowComponent[]> Components { get; set; } | |||
} | |||
} |
@@ -41,7 +41,8 @@ namespace Discord.Rest | |||
var apiArgs = new API.Rest.ModifyMessageParams | |||
{ | |||
Content = args.Content, | |||
Embed = args.Embed.IsSpecified ? args.Embed.Value.ToModel() : Optional.Create<API.Embed>() | |||
Embed = args.Embed.IsSpecified ? args.Embed.Value.ToModel() : Optional.Create<API.Embed>(), | |||
Components = args?.Components.GetValueOrDefault()?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified | |||
}; | |||
return await client.ApiClient.ModifyMessageAsync(msg.Channel.Id, msg.Id, apiArgs, options).ConfigureAwait(false); | |||
} | |||
@@ -13,6 +13,9 @@ namespace Discord.API.Gateway | |||
[JsonProperty("id")] | |||
public ulong Id { get; set; } | |||
[JsonProperty("application_id")] | |||
public ulong ApplicationId { get; set; } | |||
[JsonProperty("type")] | |||
public InteractionType Type { get; set; } | |||
@@ -20,18 +23,25 @@ namespace Discord.API.Gateway | |||
public Optional<object> Data { get; set; } | |||
[JsonProperty("guild_id")] | |||
public ulong GuildId { get; set; } | |||
public Optional<ulong> GuildId { get; set; } | |||
[JsonProperty("channel_id")] | |||
public ulong ChannelId { get; set; } | |||
public Optional<ulong> ChannelId { get; set; } | |||
[JsonProperty("member")] | |||
public GuildMember Member { get; set; } | |||
public Optional<GuildMember> Member { get; set; } | |||
[JsonProperty("user")] | |||
public Optional<User> User { get; set; } | |||
[JsonProperty("token")] | |||
public string Token { get; set; } | |||
[JsonProperty("version")] | |||
public int Version { get; set; } | |||
[JsonProperty("message")] | |||
public Optional<Message> Message { get; set; } | |||
} | |||
} |
@@ -1785,26 +1785,33 @@ namespace Discord.WebSocket | |||
await _gatewayLogger.DebugAsync("Received Dispatch (INTERACTION_CREATE)").ConfigureAwait(false); | |||
var data = (payload as JToken).ToObject<API.Gateway.InteractionCreated>(_serializer); | |||
if (State.GetChannel(data.ChannelId) is SocketGuildChannel channel) | |||
if (data.Member.IsSpecified && data.ChannelId.IsSpecified) | |||
{ | |||
var guild = channel.Guild; | |||
if (!guild.IsSynced) | |||
if (State.GetChannel(data.ChannelId.Value) is SocketGuildChannel channel) | |||
{ | |||
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false); | |||
return; | |||
} | |||
var guild = channel.Guild; | |||
if (!guild.IsSynced) | |||
{ | |||
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false); | |||
return; | |||
} | |||
var interaction = SocketInteraction.Create(this, data); | |||
var interaction = SocketInteraction.Create(this, data); | |||
if (this.AlwaysAcknowledgeInteractions) | |||
await interaction.AcknowledgeAsync().ConfigureAwait(false); | |||
if (this.AlwaysAcknowledgeInteractions) | |||
await interaction.AcknowledgeAsync().ConfigureAwait(false); | |||
await TimedInvokeAsync(_interactionCreatedEvent, nameof(InteractionCreated), interaction).ConfigureAwait(false); | |||
await TimedInvokeAsync(_interactionCreatedEvent, nameof(InteractionCreated), interaction).ConfigureAwait(false); | |||
} | |||
else | |||
{ | |||
await UnknownChannelAsync(type, data.ChannelId.Value).ConfigureAwait(false); | |||
return; | |||
} | |||
} | |||
else | |||
{ | |||
await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false); | |||
return; | |||
// DM TODO | |||
} | |||
} | |||
break; | |||
@@ -14,6 +14,8 @@ namespace Discord.WebSocket | |||
{ | |||
new public SocketMessageComponentData Data { get; } | |||
public SocketMessage Message { get; private set; } | |||
internal SocketMessageComponent(DiscordSocketClient client, Model model) | |||
: base(client, model.Id) | |||
{ | |||
@@ -22,6 +24,8 @@ namespace Discord.WebSocket | |||
: null; | |||
this.Data = new SocketMessageComponentData(dataModel); | |||
} | |||
new internal static SocketMessageComponent Create(DiscordSocketClient client, Model model) | |||
@@ -31,6 +35,23 @@ namespace Discord.WebSocket | |||
return entity; | |||
} | |||
internal override void Update(Model model) | |||
{ | |||
base.Update(model); | |||
if (model.Message.IsSpecified) | |||
{ | |||
if (this.Message == null) | |||
{ | |||
this.Message = SocketMessage.Create(this.Discord, this.Discord.State, this.User, this.Channel, model.Message.Value); | |||
} | |||
else | |||
{ | |||
this.Message.Update(this.Discord.State, model.Message.Value); | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// Responds to an Interaction. | |||
/// <para> | |||
@@ -24,7 +24,7 @@ namespace Discord.WebSocket | |||
(model.Data.Value as JToken).ToObject<DataModel>() | |||
: null; | |||
Data = SocketSlashCommandData.Create(client, dataModel, model.GuildId); | |||
Data = SocketSlashCommandData.Create(client, dataModel, model.Id); | |||
} | |||
new internal static SocketInteraction Create(DiscordSocketClient client, Model model) | |||
@@ -40,7 +40,7 @@ namespace Discord.WebSocket | |||
(model.Data.Value as JToken).ToObject<DataModel>() | |||
: null; | |||
this.Data.Update(data, this.Guild.Id); | |||
this.Data.Update(data); | |||
base.Update(model); | |||
} | |||
@@ -18,27 +18,23 @@ namespace Discord.WebSocket | |||
/// </summary> | |||
public IReadOnlyCollection<SocketSlashCommandDataOption> Options { get; private set; } | |||
private ulong guildId; | |||
internal SocketSlashCommandData(DiscordSocketClient client, ulong id) | |||
: base(client, id) | |||
{ | |||
} | |||
internal static SocketSlashCommandData Create(DiscordSocketClient client, Model model, ulong guildId) | |||
internal static SocketSlashCommandData Create(DiscordSocketClient client, Model model, ulong id) | |||
{ | |||
var entity = new SocketSlashCommandData(client, model.Id); | |||
entity.Update(model, guildId); | |||
entity.Update(model); | |||
return entity; | |||
} | |||
internal void Update(Model model, ulong guildId) | |||
internal void Update(Model model) | |||
{ | |||
this.Name = model.Name; | |||
this.guildId = guildId; | |||
this.Options = model.Options.IsSpecified | |||
? model.Options.Value.Select(x => new SocketSlashCommandDataOption(x, this.Discord, guildId)).ToImmutableArray() | |||
? model.Options.Value.Select(x => new SocketSlashCommandDataOption(x, this.Discord)).ToImmutableArray() | |||
: null; | |||
} | |||
@@ -25,18 +25,16 @@ namespace Discord.WebSocket | |||
public IReadOnlyCollection<SocketSlashCommandDataOption> Options { get; private set; } | |||
private DiscordSocketClient discord; | |||
private ulong guild; | |||
internal SocketSlashCommandDataOption() { } | |||
internal SocketSlashCommandDataOption(Model model, DiscordSocketClient discord, ulong guild) | |||
internal SocketSlashCommandDataOption(Model model, DiscordSocketClient discord) | |||
{ | |||
this.Name = model.Name; | |||
this.Value = model.Value.IsSpecified ? model.Value.Value : null; | |||
this.discord = discord; | |||
this.guild = guild; | |||
this.Options = model.Options.IsSpecified | |||
? model.Options.Value.Select(x => new SocketSlashCommandDataOption(x, discord, guild)).ToImmutableArray() | |||
? model.Options.Value.Select(x => new SocketSlashCommandDataOption(x, discord)).ToImmutableArray() | |||
: null; | |||
} | |||
@@ -52,7 +50,7 @@ namespace Discord.WebSocket | |||
{ | |||
if (option.Value is ulong id) | |||
{ | |||
var guild = option.discord.GetGuild(option.guild); | |||
var guild = option.discord.GetGuild(id); | |||
if (guild == null) | |||
return null; | |||
@@ -67,7 +65,7 @@ namespace Discord.WebSocket | |||
{ | |||
if (option.Value is ulong id) | |||
{ | |||
var guild = option.discord.GetGuild(option.guild); | |||
var guild = option.discord.GetGuild(id); | |||
if (guild == null) | |||
return null; | |||
@@ -82,7 +80,7 @@ namespace Discord.WebSocket | |||
{ | |||
if(option.Value is ulong id) | |||
{ | |||
var guild = option.discord.GetGuild(option.guild); | |||
var guild = option.discord.GetGuild(id); | |||
if (guild == null) | |||
return null; | |||
@@ -14,21 +14,14 @@ namespace Discord.WebSocket | |||
public abstract class SocketInteraction : SocketEntity<ulong>, IDiscordInteraction | |||
{ | |||
/// <summary> | |||
/// The <see cref="SocketGuild"/> this interaction was used in. | |||
/// The <see cref="ISocketMessageChannel"/> this interaction was used in. | |||
/// </summary> | |||
public SocketGuild Guild | |||
=> Discord.GetGuild(GuildId); | |||
public ISocketMessageChannel Channel { get; private set; } | |||
/// <summary> | |||
/// The <see cref="SocketTextChannel"/> this interaction was used in. | |||
/// The <see cref="SocketUser"/> who triggered this interaction. | |||
/// </summary> | |||
public SocketTextChannel Channel | |||
=> Guild.GetTextChannel(ChannelId); | |||
/// <summary> | |||
/// The <see cref="SocketGuildUser"/> who triggered this interaction. | |||
/// </summary> | |||
public SocketGuildUser User { get; private set; } | |||
public SocketUser User { get; private set; } | |||
/// <summary> | |||
/// The type of this interaction. | |||
@@ -58,9 +51,8 @@ namespace Discord.WebSocket | |||
public bool IsValidToken | |||
=> CheckToken(); | |||
private ulong GuildId { get; set; } | |||
private ulong ChannelId { get; set; } | |||
private ulong UserId { get; set; } | |||
private ulong? GuildId { get; set; } | |||
private ulong? ChannelId { get; set; } | |||
internal SocketInteraction(DiscordSocketClient client, ulong id) | |||
: base(client, id) | |||
@@ -83,15 +75,35 @@ namespace Discord.WebSocket | |||
? model.Data.Value | |||
: null; | |||
this.GuildId = model.GuildId; | |||
this.ChannelId = model.ChannelId; | |||
this.GuildId = model.GuildId.ToNullable(); | |||
this.ChannelId = model.ChannelId.ToNullable(); | |||
this.Token = model.Token; | |||
this.Version = model.Version; | |||
this.UserId = model.Member.User.Id; | |||
this.Type = model.Type; | |||
if (this.User == null) | |||
this.User = SocketGuildUser.Create(this.Guild, Discord.State, model.Member); // Change from getter. | |||
{ | |||
if (model.Member.IsSpecified && model.GuildId.IsSpecified) | |||
{ | |||
this.User = SocketGuildUser.Create(Discord.State.GetGuild(this.GuildId.Value), Discord.State, model.Member.Value); | |||
} | |||
else | |||
{ | |||
this.User = SocketGlobalUser.Create(this.Discord, this.Discord.State, model.User.Value); | |||
} | |||
} | |||
if (this.Channel == null) | |||
{ | |||
if (model.ChannelId.IsSpecified) | |||
{ | |||
this.Channel = Discord.State.GetChannel(model.ChannelId.Value) as ISocketMessageChannel; | |||
} | |||
else | |||
{ | |||
this.Channel = Discord.State.GetDMChannel(this.User.Id); | |||
} | |||
} | |||
} | |||
/// <summary> | |||