forked from DSharpPlus/DSharpPlus
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixed WaitForModalAsync() and added overload (DSharpPlus#1230)
* Fixed WaitForModalAsync and added overload Created an event handler dedicated for modals. WaitForModalAsync() will no longer result in an internal NRE. Added a overload for WaitForModalAsync() that takes a user. * Minor formatting * Resolving code reviews from @VelvetThePanda
- Loading branch information
Showing
5 changed files
with
306 additions
and
5 deletions.
There are no files selected for viewing
97 changes: 97 additions & 0 deletions
97
DSharpPlus.Interactivity/EventHandling/ModalEventWaiter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// This file is part of the DSharpPlus project. | ||
// | ||
// Copyright (c) 2015 Mike Santiago | ||
// Copyright (c) 2016-2022 DSharpPlus Contributors | ||
// | ||
// Permission is hereby granted, free of charge, to any person obtaining a copy | ||
// of this software and associated documentation files (the "Software"), to deal | ||
// in the Software without restriction, including without limitation the rights | ||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
// copies of the Software, and to permit persons to whom the Software is | ||
// furnished to do so, subject to the following conditions: | ||
// | ||
// The above copyright notice and this permission notice shall be included in all | ||
// copies or substantial portions of the Software. | ||
// | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
// SOFTWARE. | ||
|
||
using System; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using ConcurrentCollections; | ||
using DSharpPlus.EventArgs; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace DSharpPlus.Interactivity.EventHandling | ||
{ | ||
/// <summary> | ||
/// Modal version of <see cref="EventWaiter{T}"/> | ||
/// </summary> | ||
internal class ModalEventWaiter : IDisposable | ||
{ | ||
private DiscordClient Client { get; } | ||
|
||
/// <summary> | ||
/// Collection of <see cref = "ModalMatchRequest"/> representing requests to wait for modals. | ||
/// </summary> | ||
private ConcurrentHashSet<ModalMatchRequest> MatchRequests { get; } = new(); | ||
|
||
public ModalEventWaiter(DiscordClient client) | ||
{ | ||
this.Client = client; | ||
this.Client.ModalSubmitted += this.Handle; //registering Handle event to be fired upon ModalSubmitted | ||
} | ||
|
||
/// <summary> | ||
/// Waits for a specified <see cref="ModalMatchRequest"/>'s predicate to be fufilled. | ||
/// </summary> | ||
/// <param name="request">The request to wait for a match.</param> | ||
/// <returns>The returned args, or null if it timed out.</returns> | ||
public async Task<ModalSubmitEventArgs> WaitForMatchAsync(ModalMatchRequest request) | ||
{ | ||
this.MatchRequests.Add(request); | ||
|
||
try | ||
{ | ||
return await request.Tcs.Task.ConfigureAwait(false); // awaits request until completeion or cancellation | ||
} | ||
catch (Exception e) | ||
{ | ||
this.Client.Logger.LogError(InteractivityEvents.InteractivityWaitError, e, "An exception was thrown while waiting for a modal."); | ||
return null; | ||
} | ||
finally | ||
{ | ||
this.MatchRequests.TryRemove(request); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Is called whenever <see cref="ModalSubmitEventArgs"/> is fired. Checks to see submitted modal matches any of the current requests. | ||
/// </summary> | ||
/// <param name="_"></param> | ||
/// <param name="args">The <see cref="ModalSubmitEventArgs"/> to match.</param> | ||
/// <returns>A task that represents matching the requests.</returns> | ||
private Task Handle(DiscordClient _, ModalSubmitEventArgs args) | ||
{ | ||
foreach (var req in this.MatchRequests.ToArray()) // ToArray to get a copy of the collection that won't be modified during iteration | ||
{ | ||
if (req.ModalId == args.Interaction.Data.CustomId && req.IsMatch(args)) // will catch all matches | ||
req.Tcs.TrySetResult(args); | ||
} | ||
return Task.CompletedTask; | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
this.MatchRequests.Clear(); | ||
this.Client.ModalSubmitted -= this.Handle; | ||
} | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
DSharpPlus.Interactivity/EventHandling/Requests/ModalMatchRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// This file is part of the DSharpPlus project. | ||
// | ||
// Copyright (c) 2015 Mike Santiago | ||
// Copyright (c) 2016-2022 DSharpPlus Contributors | ||
// | ||
// Permission is hereby granted, free of charge, to any person obtaining a copy | ||
// of this software and associated documentation files (the "Software"), to deal | ||
// in the Software without restriction, including without limitation the rights | ||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
// copies of the Software, and to permit persons to whom the Software is | ||
// furnished to do so, subject to the following conditions: | ||
// | ||
// The above copyright notice and this permission notice shall be included in all | ||
// copies or substantial portions of the Software. | ||
// | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
// SOFTWARE. | ||
|
||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using DSharpPlus.EventArgs; | ||
|
||
namespace DSharpPlus.Interactivity.EventHandling | ||
{ | ||
/// <summary> | ||
/// Represents a match request for a modal of the given Id and predicate. | ||
/// </summary> | ||
internal class ModalMatchRequest | ||
{ | ||
/// <summary> | ||
/// The custom Id of the modal. | ||
/// </summary> | ||
public string ModalId { get; } | ||
|
||
/// <summary> | ||
/// The completion source that represents the result of the match. | ||
/// </summary> | ||
public TaskCompletionSource<ModalSubmitEventArgs> Tcs { get; private set; } = new(); | ||
|
||
protected CancellationToken Cancellation { get; } | ||
|
||
/// <summary> | ||
/// The predicate/criteria that this match will be fulfilled under. | ||
/// </summary> | ||
protected Func<ModalSubmitEventArgs, bool> Predicate { get; } | ||
|
||
public ModalMatchRequest(string modal_id, Func<ModalSubmitEventArgs, bool> predicate, CancellationToken cancellation) | ||
{ | ||
this.ModalId = modal_id; | ||
this.Predicate = predicate; | ||
this.Cancellation = cancellation; | ||
this.Cancellation.Register(() => this.Tcs.TrySetResult(null)); // "TrySetCancelled would probably be better but I digress" - Velvet // "TrySetCancelled throws an exception when you await the task, actually" - Velvet, 2022 | ||
} | ||
|
||
/// <summary> | ||
/// Checks whether the <see cref="ModalSubmitEventArgs"/> matches the predicate criteria. | ||
/// </summary> | ||
/// <param name="args">The <see cref="ModalSubmitEventArgs"/> to check.</param> | ||
/// <returns>Whether the <see cref="ModalSubmitEventArgs"/> matches the predicate.</returns> | ||
public bool IsMatch(ModalSubmitEventArgs args) | ||
=> this.Predicate(args); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters