Skip to content

Commit

Permalink
[Fix] Update modal's DeferAsync impl (#2722)
Browse files Browse the repository at this point in the history
* initial commit

* updates
  • Loading branch information
Misha-133 authored Aug 10, 2023
1 parent 4dbb594 commit 5f580f6
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,13 @@ public interface IModalInteraction : IDiscordInteraction
/// This method can be used only if the modal was created from a message component.
/// </remarks>
Task UpdateAsync(Action<MessageProperties> func, RequestOptions options = null);

/// <summary>
/// Defers an interaction with the response type 5 (<see cref="InteractionResponseType.DeferredChannelMessageWithSource"/>).
/// </summary>
/// <param name="ephemeral"><see langword="true"/> to defer ephemerally, otherwise <see langword="false"/>.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>A task that represents the asynchronous operation of acknowledging the interaction.</returns>
Task DeferLoadingAsync(bool ephemeral = false, RequestOptions options = null);
}
}
44 changes: 42 additions & 2 deletions src/Discord.Net.Rest/Entities/Interactions/Modals/RestModal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ internal RestModal(DiscordRestClient client, ModelBase model)
private object _lock = new object();

/// <summary>
/// Acknowledges this interaction with the <see cref="InteractionResponseType.DeferredChannelMessageWithSource"/>.
/// Acknowledges this interaction with the <see cref="InteractionResponseType.DeferredUpdateMessage"/> if the modal was created
/// in a response to a message component interaction, <see cref="InteractionResponseType.DeferredChannelMessageWithSource"/> otherwise.
/// </summary>
/// <returns>
/// A string that contains json to write back to the incoming http request.
Expand All @@ -55,7 +56,9 @@ public override string Defer(bool ephemeral = false, RequestOptions options = nu

var response = new API.InteractionResponse
{
Type = InteractionResponseType.DeferredChannelMessageWithSource,
Type = Message is not null
? InteractionResponseType.DeferredUpdateMessage
: InteractionResponseType.DeferredChannelMessageWithSource,
Data = new API.InteractionCallbackData
{
Flags = ephemeral ? MessageFlags.Ephemeral : Optional<MessageFlags>.Unspecified
Expand All @@ -78,6 +81,39 @@ public override string Defer(bool ephemeral = false, RequestOptions options = nu
return SerializePayload(response);
}

/// <summary>
/// Defers an interaction and responds with type 5 (<see cref="InteractionResponseType.DeferredChannelMessageWithSource"/>)
/// </summary>
/// <param name="ephemeral"><see langword="true"/> to send this message ephemerally, otherwise <see langword="false"/>.</param>
/// <param name="options">The request options for this <see langword="async"/> request.</param>
/// <returns>
/// A string that contains json to write back to the incoming http request.
/// </returns>
public string DeferLoading(bool ephemeral = false, RequestOptions options = null)
{
if (!InteractionHelper.CanSendResponse(this))
throw new TimeoutException($"Cannot defer an interaction after {InteractionHelper.ResponseTimeLimit} seconds of no response/acknowledgement");

var response = new API.InteractionResponse
{
Type = InteractionResponseType.DeferredChannelMessageWithSource,
Data = ephemeral ? new API.InteractionCallbackData { Flags = MessageFlags.Ephemeral } : Optional<API.InteractionCallbackData>.Unspecified
};

lock (_lock)
{
if (HasResponded)
{
throw new InvalidOperationException("Cannot respond or defer twice to the same interaction");
}

HasResponded = true;
}

return SerializePayload(response);
}


/// <summary>
/// Sends a followup message for this interaction.
/// </summary>
Expand Down Expand Up @@ -413,6 +449,10 @@ public override string RespondWithModal(Modal modal, RequestOptions requestOptio

IModalInteractionData IModalInteraction.Data => Data;

/// <inheritdoc />
Task IModalInteraction.DeferLoadingAsync(bool ephemeral, RequestOptions options)
=> Task.FromResult(DeferLoading(ephemeral, options));

/// <inheritdoc/>
public async Task UpdateAsync(Action<MessageProperties> func, RequestOptions options = null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,14 +376,20 @@ public override async Task<RestFollowupMessage> FollowupWithFilesAsync(
}

/// <inheritdoc/>
/// <remarks>
/// Acknowledges this interaction with the <see cref="InteractionResponseType.DeferredUpdateMessage"/> if the modal was created
/// in a response to a message component interaction, <see cref="InteractionResponseType.DeferredChannelMessageWithSource"/> otherwise.
/// </remarks>
public override async Task DeferAsync(bool ephemeral = false, RequestOptions options = null)
{
if (!InteractionHelper.CanSendResponse(this))
throw new TimeoutException($"Cannot defer an interaction after {InteractionHelper.ResponseTimeLimit} seconds of no response/acknowledgement");

var response = new API.InteractionResponse
{
Type = InteractionResponseType.DeferredUpdateMessage,
Type = Message is not null
? InteractionResponseType.DeferredUpdateMessage
: InteractionResponseType.DeferredChannelMessageWithSource,
Data = ephemeral ? new API.InteractionCallbackData { Flags = MessageFlags.Ephemeral } : Optional<API.InteractionCallbackData>.Unspecified
};

Expand All @@ -403,6 +409,30 @@ public override async Task DeferAsync(bool ephemeral = false, RequestOptions opt
}
}

/// <inheritdoc/>
public async Task DeferLoadingAsync(bool ephemeral = false, RequestOptions options = null)
{
if (!InteractionHelper.CanSendResponse(this))
throw new TimeoutException($"Cannot defer an interaction after {InteractionHelper.ResponseTimeLimit} seconds of no response/acknowledgement");

var response = new API.InteractionResponse
{
Type = InteractionResponseType.DeferredChannelMessageWithSource,
Data = ephemeral ? new API.InteractionCallbackData { Flags = MessageFlags.Ephemeral } : Optional<API.InteractionCallbackData>.Unspecified
};

lock (_lock)
{
if (HasResponded)
{
throw new InvalidOperationException("Cannot respond or defer twice to the same interaction");
}
}

await Discord.Rest.ApiClient.CreateInteractionResponseAsync(response, Id, Token, options).ConfigureAwait(false);
HasResponded = true;
}

/// <inheritdoc/>
public override Task RespondWithModalAsync(Modal modal, RequestOptions options = null)
=> throw new NotSupportedException("You cannot respond to a modal with a modal!");
Expand Down

0 comments on commit 5f580f6

Please sign in to comment.