Browse Source

Added flags to interaction response and webhook message. see https://discord.com/developers/docs/interactions/slash-commands#interaction-response-interactionapplicationcommandcallbackdata. Interaction response types 2 and 3 have been deprecated.

pull/1717/head
quin lynch 4 years ago
parent
commit
ead960961b
4 changed files with 45 additions and 16 deletions
  1. +12
    -4
      src/Discord.Net.Core/Entities/Interactions/InteractionResponseType.cs
  2. +4
    -0
      src/Discord.Net.Rest/API/Common/InteractionApplicationCommandCallbackData.cs
  3. +8
    -0
      src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs
  4. +21
    -12
      src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs

+ 12
- 4
src/Discord.Net.Core/Entities/Interactions/InteractionResponseType.cs View File

@@ -9,6 +9,12 @@ namespace Discord
/// <summary>
/// The response type for an <see cref="IDiscordInteraction"/>.
/// </summary>
/// <remarks>
/// After receiving an interaction, you must respond to acknowledge it. You can choose to respond with a message immediately using <see cref="ChannelMessageWithSource"/>
/// or you can choose to send a deferred response with <see cref="ACKWithSource"/>. If choosing a deferred response, the user will see a loading state for the interaction,
/// and you'll have up to 15 minutes to edit the original deferred response using Edit Original Interaction Response.
/// You can read more about Response types <see href="https://discord.com/developers/docs/interactions/slash-commands#interaction-response">Here</see>
/// </remarks>
public enum InteractionResponseType : byte
{
/// <summary>
@@ -16,24 +22,26 @@ namespace Discord
/// </summary>
Pong = 1,

[Obsolete("This response type has been depricated by discord. Either use ChannelMessageWithSource or ACKWithSource", true)]
/// <summary>
/// ACK a command without sending a message, eating the user's input.
/// </summary>
Acknowledge = 2,

[Obsolete("This response type has been depricated by discord. Either use ChannelMessageWithSource or ACKWithSource", true)]
/// <summary>
/// Respond with a message, eating the user's input.
/// Respond with a message, showing the user's input.
/// </summary>
ChannelMessage = 3,

/// <summary>
/// Respond with a message, showing the user's input.
/// Respond to an interaction with a message.
/// </summary>
ChannelMessageWithSource = 4,

/// <summary>
/// ACK a command without sending a message, showing the user's input.
/// ACK an interaction and edit a response later, the user sees a loading state.
/// </summary>
ACKWithSource = 5
DeferredChannelMessageWithSource = 5
}
}

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

@@ -21,6 +21,10 @@ namespace Discord.API
[JsonProperty("allowed_mentions")]
public Optional<AllowedMentions> AllowedMentions { get; set; }

// New flags prop. this make the response "ephemeral". see https://discord.com/developers/docs/interactions/slash-commands#interaction-response-interactionapplicationcommandcallbackdata
[JsonProperty("flags")]
public Optional<int> Flags { get; set; }

public InteractionApplicationCommandCallbackData() { }
public InteractionApplicationCommandCallbackData(string text)
{


+ 8
- 0
src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs View File

@@ -11,17 +11,25 @@ namespace Discord.API.Rest

[JsonProperty("nonce")]
public Optional<string> Nonce { get; set; }

[JsonProperty("tts")]
public Optional<bool> IsTTS { get; set; }

[JsonProperty("embeds")]
public Optional<Embed[]> Embeds { get; set; }

[JsonProperty("username")]
public Optional<string> Username { get; set; }

[JsonProperty("avatar_url")]
public Optional<string> AvatarUrl { get; set; }

[JsonProperty("allowed_mentions")]
public Optional<AllowedMentions> AllowedMentions { get; set; }

[JsonProperty("flags")]
public Optional<int> Flags { get; set; }

public CreateWebhookMessageParams(string content)
{
Content = content;


+ 21
- 12
src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs View File

@@ -104,7 +104,8 @@ namespace Discord.WebSocket
/// <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="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>
@@ -113,16 +114,17 @@ namespace Discord.WebSocket
/// <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 async Task<IMessage> RespondAsync(string text = null, bool isTTS = false, Embed embed = null, InteractionResponseType Type = InteractionResponseType.ChannelMessageWithSource, AllowedMentions allowedMentions = null, RequestOptions options = null)
public async Task<IMessage> RespondAsync(string text = null, bool isTTS = false, Embed embed = null, InteractionResponseType type = InteractionResponseType.ChannelMessageWithSource,
bool ephemeral = false, AllowedMentions allowedMentions = null, RequestOptions options = null)
{
if (Type == InteractionResponseType.Pong)
if (type == InteractionResponseType.Pong)
throw new InvalidOperationException($"Cannot use {Type} on a send message function");

if (!IsValidToken)
throw new InvalidOperationException("Interaction token is no longer valid");

if (Discord.AlwaysAcknowledgeInteractions)
return await FollowupAsync();
return await FollowupAsync(text, isTTS, embed, ephemeral, type, allowedMentions, options); // The arguments should be passed? What was i thinking...

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.");
@@ -146,17 +148,20 @@ namespace Discord.WebSocket

var response = new API.InteractionResponse()
{
Type = Type,
Type = type,
Data = new API.InteractionApplicationCommandCallbackData(text)
{
AllowedMentions = allowedMentions?.ToModel(),
Embeds = embed != null
? new API.Embed[] { embed.ToModel() }
: Optional<API.Embed[]>.Unspecified,
TTS = isTTS
TTS = isTTS,
}
};

if (ephemeral)
response.Data.Value.Flags = 64;

await Discord.Rest.ApiClient.CreateInteractionResponse(response, this.Id, Token, options);
return null;
}
@@ -168,15 +173,17 @@ namespace Discord.WebSocket
/// <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>
public async Task<IMessage> FollowupAsync(string text = null, bool isTTS = false, Embed embed = null, InteractionResponseType Type = InteractionResponseType.ChannelMessageWithSource,
public async Task<IMessage> FollowupAsync(string text = null, bool isTTS = false, Embed embed = null, bool ephemeral = false,
InteractionResponseType Type = InteractionResponseType.ChannelMessageWithSource,
AllowedMentions allowedMentions = null, RequestOptions options = null)
{
if (Type == InteractionResponseType.ACKWithSource || Type == InteractionResponseType.ACKWithSource || Type == InteractionResponseType.Pong)
if (Type == InteractionResponseType.DeferredChannelMessageWithSource || Type == InteractionResponseType.DeferredChannelMessageWithSource || Type == InteractionResponseType.Pong)
throw new InvalidOperationException($"Cannot use {Type} on a send message function");

if (!IsValidToken)
@@ -189,13 +196,15 @@ namespace Discord.WebSocket
? new API.Embed[] { embed.ToModel() }
: Optional<API.Embed[]>.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.ACKWithSource"/>.
/// Acknowledges this interaction with the <see cref="InteractionResponseType.DeferredChannelMessageWithSource"/>.
/// </summary>
/// <returns>
/// A task that represents the asynchronous operation of acknowledging the interaction.
@@ -204,7 +213,7 @@ namespace Discord.WebSocket
{
var response = new API.InteractionResponse()
{
Type = InteractionResponseType.ACKWithSource,
Type = InteractionResponseType.DeferredChannelMessageWithSource,
};

await Discord.Rest.ApiClient.CreateInteractionResponse(response, this.Id, Token, options).ConfigureAwait(false);


Loading…
Cancel
Save