public static async Task <bool> PromptYesNo(this Context ctx, DiscordMessage message, DiscordUser user = null, Duration?timeout = null) { var cts = new CancellationTokenSource(); if (user == null) { user = ctx.Author; } if (timeout == null) { timeout = Duration.FromMinutes(5); } // "Fork" the task adding the reactions off so we don't have to wait for them to be finished to start listening for presses var _ = message.CreateReactionsBulk(new[] { Emojis.Success, Emojis.Error }); bool ReactionPredicate(MessageReactionAddEventArgs e) { if (e.Channel.Id != message.ChannelId || e.Message.Id != message.Id) { return(false); } if (e.User.Id != user.Id) { return(false); } return(true); } bool MessagePredicate(MessageCreateEventArgs e) { if (e.Channel.Id != message.ChannelId) { return(false); } if (e.Author.Id != user.Id) { return(false); } var strings = new [] { "y", "yes", "n", "no" }; foreach (var str in strings) { if (e.Message.Content.Equals(str, StringComparison.InvariantCultureIgnoreCase)) { return(true); } } return(false); } var messageTask = ctx.Services.Resolve <HandlerQueue <MessageCreateEventArgs> >().WaitFor(MessagePredicate, timeout, cts.Token); var reactionTask = ctx.Services.Resolve <HandlerQueue <MessageReactionAddEventArgs> >().WaitFor(ReactionPredicate, timeout, cts.Token); var theTask = await Task.WhenAny(messageTask, reactionTask); cts.Cancel(); if (theTask == messageTask) { var responseMsg = (await messageTask).Message; var positives = new[] { "y", "yes" }; foreach (var p in positives) { if (responseMsg.Content.Equals(p, StringComparison.InvariantCultureIgnoreCase)) { return(true); } } return(false); } if (theTask == reactionTask) { return((await reactionTask).Emoji.Name == Emojis.Success); } return(false); }