/***************************************************************************************** ***************************************************************************************** ***************************************************************************************** ***************************************************************************************** ***************************************************************************************** * Core implementation of this component. * * TO-DO * * Will interact like this: * * do * 1. yield wait until a result if available * 2. check if any selected element is invalid * Notes: The very checking of the validity should trigger the display of the * appropriate error messages. * while any selected element is invalid ***************************************************************************************** ***************************************************************************************** ***************************************************************************************** ***************************************************************************************** *****************************************************************************************/ /** * Executes the interaction by looping like this: * 1. Expect a result of selected items. * 2. Expect all of them be valid elements. Otherwise, messages will be reported to * the console (interactive message). Perhaps even providing heading and trailing * messages for the overall errors. * 3. Keep valid items. */ protected override IEnumerator Input(InteractiveMessage message) { if (cancelButton == null && !AtLeastOneSelectableItem()) { throw new Types.Exception("A list interactor with no cancel button must provide at least one item in the list of selectable items when calling Input(). Otherwise, the interaction will no way of ending"); } // Reset the list's position Rewind(); // Start this whole loop bool allSelectedItemsAreValid; do { allSelectedItemsAreValid = true; // On each loop we will: // 1. Release the fact that we have a result. // 2. Wait for a result (i.e. a selection). HasResult = false; yield return(new WaitUntil(() => HasResult)); System.Collections.Generic.List <InteractiveMessage.Prompt> prompt = new System.Collections.Generic.List <InteractiveMessage.Prompt>(); ValidateSelection(SelectedItems, (InteractiveMessage.Prompt[] reported) => prompt.AddRange(reported)); if (prompt.Count > 0) { allSelectedItemsAreValid = false; yield return(message.PromptMessages(prompt.ToArray())); } // 4. Repeat until the validation does not fail. }while (!allSelectedItemsAreValid); // At this point, each item in SelectedItems is valid }
/// <summary> /// Handles interactive messages. Used for button presses on previews. /// </summary> /// <param name="interactiveMessage"></param> /// <returns></returns> public async Task HandleInteractive(InteractiveMessage interactiveMessage) { if (Slack.ValidInteractiveMessage(interactiveMessage)) { var action = interactiveMessage.Actions[0]; var slackUser = await Slack.GetUser(interactiveMessage.User.Id); if (action.Name == "post") { await Slack.PostMessage(new ChatMessage { Channel = interactiveMessage.Channel.Id, Username = slackUser.Profile.DisplayName, Text = action.Value, IconUrl = slackUser.Profile.ImageOriginal, User = interactiveMessage.User.Id, }); } else if (action.Name == "random") { var url = await ImageSearch(action.Value, true); await SendGif(interactiveMessage.Channel.Id, slackUser.Profile.DisplayName, slackUser.Profile.ImageOriginal, slackUser.Id, action.Value, url); } await Slack.DeleteResponse(interactiveMessage.ResponseUrl.ToString()); } }
public async Task ProccesRequest_HelpedAction_ShouldCallExecutorServiceWithAppropriateArgs() { // Arrange var action = new AttachmentActionDto("actionName", "some text"); var request = new InteractiveMessage { Actions = new List <AttachmentActionDto> { action } }; var paramsType = typeof(HelpedSlackActionParams); var actionParams = new HelpedSlackActionParams(); _slackParamsSelectServiceMock.Setup(m => m.Choose(It.IsAny <string>())) .Returns(paramsType); _mapperMock.Setup(m => m.Map(It.IsAny <object>(), It.IsAny <Type>(), It.IsAny <Type>())) .Returns(actionParams); _slackExecutorServiceMock.Setup(m => m.ExecuteAction(It.IsAny <Type>(), It.IsAny <object[]>())) .Returns(Task.CompletedTask); // Act await _service.ProcessRequest(request); // Assert _slackParamsSelectServiceMock.Verify(m => m.Choose(It.Is <string>(n => n == action.Name)), Times.Once); _slackParamsSelectServiceMock.VerifyNoOtherCalls(); _mapperMock.Verify(m => m.Map(It.Is <object>(r => r == request), It.Is <Type>(t => t == request.GetType()), It.Is <Type>(t => t == actionParams.GetType()))); _mapperMock.VerifyNoOtherCalls(); _slackExecutorServiceMock.Verify(m => m.ExecuteAction(It.Is <Type>(t => t == paramsType), It.IsAny <object[]>()), Times.Once); _slackExecutorServiceMock.VerifyNoOtherCalls(); }
private IEnumerator WrappedInteraction(InteractiveMessage interactiveMessage, InteractiveMessage.Prompt[] prompt) { if (interactionRunning) { throw new Types.Exception("Cannot run the interaction: A previous interaction is already running"); } interactionRunning = true; // We may add extra spaces to the last message to be rendered. // This helps us allocating more visual space so the displayed // interface does not hide the text in the message. int length = prompt.Length; if (length > 0 && (prompt[length - 1] is InteractiveMessage.MessagePrompt)) { // Adds newlines to the last prompt. string extraSpaces = new String('\n', (int)newlinesToAddWhenShowing); InteractiveMessage.MessagePrompt lastPrompt = prompt[length - 1] as InteractiveMessage.MessagePrompt; prompt[length - 1] = new InteractiveMessage.MessagePrompt(lastPrompt.Message + extraSpaces); } yield return(interactiveMessage.PromptMessages(prompt)); interactionDisplaying = true; yield return(StartCoroutine(Input(interactiveMessage))); interactionDisplaying = false; interactionRunning = false; }
private async Task SendCriteriaErrorMessages(InteractiveMessage interactiveMessage, InteractiveResponse response) { switch (response.CriteriaResult) { case CriteriaResult.Timeout: await interactiveMessage.SendTimeoutMessages(); break; case CriteriaResult.Canceled: await interactiveMessage.SendCancellationMessages(); break; case CriteriaResult.Success: break; case CriteriaResult.WrongResponse: break; default: throw new ArgumentOutOfRangeException(); } }
public void ShowNotification(string notification) { // basic checks if (String.IsNullOrWhiteSpace(notification)) { return; } // show or enque message lock (syncObject) { // if no items are queued then show the message, else enque var message = new InteractiveMessage() { Message = notification }; if (this.messages.Count == 0 && this.currentMessage == null) { ShowMessage(message); } else { messages.Enqueue(message); } } }
public override async Task <MessageResponse> Handle(InteractiveMessage message) { using (var scope = _serviceProvider.CreateScope()) { var handler = scope.ServiceProvider.GetRequiredService <T>(); return(await handler.Handle(message).ConfigureAwait(false)); } }
private IEnumerator Yay(InteractorsManager manager, InteractiveMessage message) { NullInteractor dummyInteractor = (NullInteractor)manager["null"]; ButtonsInteractor continueInteractor = (ButtonsInteractor)manager["continue"]; yield return(continueInteractor.RunInteraction(message, new InteractiveMessage.PromptBuilder().Clear().Write("Siiiiii funciono!").Wait(0.5f).End())); SceneManager.LoadSceneAsync(nextSceneName, LoadSceneMode.Single); }
private async Task <SlackResult> HandleInteractiveMessage(InteractiveMessage interactiveMessage) { var response = await _interactiveMessageHandler.Handle(interactiveMessage).ConfigureAwait(false); var responseObject = response == null ? null : interactiveMessage.IsAppUnfurl ? (object)new AttachmentUpdateResponse(response) : new MessageUpdateResponse(response); return(new JsonResult(_jsonSettings, HttpStatusCode.OK, responseObject)); }
private void ProcessQueue() { lock (syncObject) { if (messages.Count == 0) { currentMessage = null; } else { ShowMessage(messages.Dequeue()); } } }
private static Message VoteToBan(InteractiveMessage slackMessage) { var vote = Vote.Create(slackMessage); var voted = Repository.Get <Vote>().FirstOrDefault(v => v.Voteban.Id == vote.Voteban.Id && v.UserId == vote.UserId); if (voted != null) { voted.Update(vote); voted.Save(); } else { vote.Save(); } return(VotebanController.FormatMessage(vote.Voteban)); }
public void Map__InteractiveMessage_To_MoreSlackActionParams__AllNecessaryFieldsAreMapped() { // Arrange const string questionId = "questionId"; const string answerId = "answerId"; var firstAction = new AttachmentActionDto("name", "text") { Value = JsonConvert.SerializeObject(new ShowMoreAnswersActionButtonParams { QuestionId = questionId, AnswerId = answerId }) }; var originalMessage = new OriginalMessageDto { Text = "attachmentText", TimeStamp = "1212132421", Attachments = new List <AttachmentDto>() }; var source = new InteractiveMessage { Actions = new List <AttachmentActionDto> { firstAction }, User = new ItemInfo { Id = "id", Name = "userName" }, Channel = new ItemInfo { Id = "channelId", Name = "channelName" }, OriginalMessage = originalMessage }; // Act var destination = _mapper.Map <InteractiveMessage, ShowMoreAnswersSlackActionParams>(source); // Assert Assert.Equal(source.User.Name, destination.User.Name); Assert.Equal(source.User.Id, destination.User.Id); Assert.Equal(source.Channel.Name, destination.Channel.Name); Assert.Equal(source.Channel.Id, destination.Channel.Id); Assert.Equal(questionId, destination.ButtonParams.QuestionId); Assert.Equal(answerId, destination.ButtonParams.AnswerId); Assert.Equal(source.OriginalMessage.Text, destination.OriginalMessage.Text); Assert.Equal(source.OriginalMessage.TimeStamp, destination.OriginalMessage.TimeStamp); Assert.Equal(source.OriginalMessage.Attachments, destination.OriginalMessage.Attachments); }
private IEnumerator Swear(InteractorsManager manager, InteractiveMessage message) { ButtonsInteractor restartInteractor = (ButtonsInteractor)manager["restart"]; yield return(restartInteractor.RunInteraction(message, new InteractiveMessage.PromptBuilder().Clear().Write("Coooo#$%^&*o!").Wait(0.5f).End())); if (restartInteractor.Result == "current") { // reinicia el nivel. SceneManager.LoadScene(SceneManager.GetActiveScene().name, LoadSceneMode.Single); } else { // reinicia el juego. SceneManager.LoadScene(0, LoadSceneMode.Single); } }
public static async Task DeactivateInteractiveMessage(InteractiveMessage message, bool isBecauseInactive = false) { // Acquire the semaphore await InteractiveMessageSemaphore.WaitAsync(); // Check if this message is inactive if (!message.IsActive) { goto done; } // Set as inactive message.IsActive = false; // Add this to the active messages bool isSuccess = ActiveInteractiveMessages.Remove(message); // Clear all reactions if needed if (isSuccess) { await message.ClearReactions(); } // Get a Language if possible IGuildChannel guildChannel = message.Channel as IGuildChannel; Language language = guildChannel != null?DiscordUtil.GetDefaultLanguage(guildChannel.Guild, guildChannel) : Language.EnglishUS; // Modify the message to say that it has timed out if needed if (isBecauseInactive) { await message.TargetMessage.ModifyAsync(p => { p.Content = null; p.Embed = new EmbedBuilder() .WithTitle(Localizer.Localize("discord.interactive_timeout.title", language)) .WithDescription(Localizer.Localize("discord.interactive_timeout.description", language)) .Build(); }); } done: // Release the semaphore InteractiveMessageSemaphore.Release(); }
public void Map__InteractiveMessage_To_AskExpertsSlackActionParams__AllNecessaryFieldsAreMapped() { // Arrange var firstAction = new AttachmentActionDto("name", "text") { Value = "value" }; var originalMessage = new OriginalMessageDto { Text = "attachmentText", TimeStamp = "1212132421", Attachments = new List <AttachmentDto>() }; var source = new InteractiveMessage { Actions = new List <AttachmentActionDto> { firstAction }, User = new ItemInfo { Id = "id", Name = "userName" }, Channel = new ItemInfo { Id = "channelId", Name = "channelName" }, AttachmentId = 1, OriginalMessage = originalMessage }; // Act var destination = _mapper.Map <InteractiveMessage, AskExpertsSlackActionParams>(source); // Assert Assert.Equal(source.User.Name, destination.User.Name); Assert.Equal(source.User.Id, destination.User.Id); Assert.Equal(source.Channel.Name, destination.Channel.Name); Assert.Equal(source.Channel.Id, destination.Channel.Id); Assert.Equal(source.AttachmentId - 1, destination.AttachmentId); Assert.Equal(firstAction.Value, destination.ButtonParams.QuestionText); Assert.Equal(source.OriginalMessage.Text, destination.OriginalMessage.Text); Assert.Equal(source.OriginalMessage.TimeStamp, destination.OriginalMessage.TimeStamp); Assert.Equal(source.OriginalMessage.Attachments, destination.OriginalMessage.Attachments); }
public async Task <MessageResponse> Handle(InteractiveMessage message) { var counterText = _counterPattern.Match(message.OriginalAttachment.Text); if (counterText.Success) { var count = int.Parse(counterText.Groups[1].Value); var increment = int.Parse(message.Action.Value); message.OriginalAttachment.Text = $"Counter: {count + increment}"; message.OriginalAttachment.Actions = Actions; return(new MessageResponse { ReplaceOriginal = true, Message = message.OriginalMessage }); } return(null); }
private InteractiveResponse EvaluateResponseType(SocketMessage message, InteractiveMessage interactiveMessage, InteractiveResponse response) { switch (interactiveMessage.ResponseType) { case InteractiveTextResponseType.Channel: if (message.ContainsChannel()) { response.CriteriaResult = CriteriaResult.Success; } break; case InteractiveTextResponseType.User: if (message.ContainsUser()) { response.CriteriaResult = CriteriaResult.Success; } break; case InteractiveTextResponseType.Role: if (message.ContainsRole()) { response.CriteriaResult = CriteriaResult.Success; } break; case InteractiveTextResponseType.Options: if (message.ContainsWords(1, interactiveMessage.CaseSensitive, interactiveMessage.Options)) { response.CriteriaResult = CriteriaResult.Success; } break; case InteractiveTextResponseType.Any: response.CriteriaResult = CriteriaResult.Success; break; default: throw new ArgumentOutOfRangeException(); } return(response); }
public Task ProcessRequest(InteractiveMessage request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } var invokedAction = request.Actions.FirstOrDefault(); if (invokedAction == null) { throw new ArgumentNullException(nameof(invokedAction)); } var paramsType = _slackParamsSelectService.Choose(invokedAction.Name); var actionParams = _mapper.Map(request, request.GetType(), paramsType); return(_slackExecutorService.ExecuteAction(paramsType, actionParams)); }
public void Map__InteractiveMessage_To_AddAnswerSlackActionParams__AllNecessaryFieldsAreMapped() { // Arrange const string buttonValue = "value"; var firstAction = new AttachmentActionDto("name", "text") { Value = JsonConvert.SerializeObject(new AddAnswerActionButtonParams { QuestionId = buttonValue }) }; var originalMessage = new OriginalMessageDto { Text = "attachmentText", TimeStamp = "1212132421", Attachments = new List <AttachmentDto>() }; var source = new InteractiveMessage { TriggerId = "trigger", Actions = new List <AttachmentActionDto> { firstAction }, User = new ItemInfo { Id = "id", Name = "userName" }, OriginalMessage = originalMessage }; // Act var destination = _mapper.Map <InteractiveMessage, AddAnswerSlackActionParams>(source); // Assert Assert.Equal(source.TriggerId, destination.TriggerId); Assert.Equal(source.User.Name, destination.User.Name); Assert.Equal(source.User.Id, destination.User.Id); Assert.Equal(buttonValue, destination.ButtonParams.QuestionId); Assert.Equal(source.OriginalMessage.Text, destination.OriginalMessage.Text); Assert.Equal(source.OriginalMessage.TimeStamp, destination.OriginalMessage.TimeStamp); Assert.Equal(source.OriginalMessage.Attachments, destination.OriginalMessage.Attachments); }
public async Task <MessageResponse> Handle(InteractiveMessage message) { var menu = (Menu)message.Action; message.OriginalAttachment.Color = menu.SelectedValue; ((Menu)message.OriginalAttachment.Actions[0]).SelectedOptions = new List <Option> { GetOptions(string.Empty) .FirstOrDefault(o => o.Value == menu.SelectedValue) ?? new Option { Text = menu.SelectedValue, Value = menu.SelectedValue } }; return(new MessageResponse { ReplaceOriginal = true, Message = message.OriginalMessage }); }
IEnumerator WelcomeRoutine(InteractorsManager manager, InteractiveMessage message) { NullInteractor dummyInteractor = (NullInteractor)manager["null"]; ButtonsInteractor continueInteractor = (ButtonsInteractor)manager["continue"]; string[] textLines = text.Split('\n'); int cntTextLines = textLines.Length; int lastTextLineIndex = cntTextLines - 1; for (int i = 0; i < cntTextLines; i++) { string textLine = textLines[i]; InteractiveMessage.PromptBuilder builder = new InteractiveMessage.PromptBuilder().Write(textLine); if (i < lastTextLineIndex) { builder.NewlinePrompt(true); } builder.Wait(0.5f); yield return(dummyInteractor.RunInteraction(message, builder.End())); } yield return(continueInteractor.RunInteraction(message, new InteractiveMessage.PromptBuilder().End())); }
public async Task Route_InvocationIsInteractiveMessage_ShouldCallInteractiveMessageService() { // Arrange var message = new InteractiveMessage { Type = MessageType.InteractiveMessage }; var payloadRaw = JsonConvert.SerializeObject(message, SlackSerializerSettings.DefaultSettings); _interactiveMessageServiceMock.Setup(m => m.ProcessRequest(It.IsAny <InteractiveMessage>())) .Returns(Task.CompletedTask); // Act await _service.Route(payloadRaw); // Assert _interactiveMessageServiceMock.Verify(m => m.ProcessRequest(It.IsAny <InteractiveMessage>()), Times.Once); _interactiveMessageServiceMock.VerifyNoOtherCalls(); _slackExecutorServiceMock.VerifyNoOtherCalls(); _submissionSelectServiceMock.VerifyNoOtherCalls(); }
/// <summary> /// Sends a paginated message to the context user's direct messaging channel, alerting them if they are /// not already in it, and deletes it after a certain timeout. Defaults to 5 minutes. /// </summary> /// <param name="this">The interactive service.</param> /// <param name="context">The command context.</param> /// <param name="feedback">The feedback service to use.</param> /// <param name="message">The message to send.</param> /// <param name="timeout">The timeout after which the embed will be deleted. Defaults to 5 minutes.</param> /// <returns>The message that was sent.</returns> public static async Task SendPrivateInteractiveMessageAndDeleteAsync ( [NotNull] this InteractivityService @this, [NotNull] ICommandContext context, [NotNull] UserFeedbackService feedback, [NotNull] InteractiveMessage message, [CanBeNull] TimeSpan?timeout = null ) { timeout = timeout ?? TimeSpan.FromMinutes(5.0); var userChannel = await context.User.GetOrCreateDMChannelAsync(); try { var eb = feedback.CreateFeedbackEmbed(context.User, Color.DarkPurple, "Loading..."); await feedback.SendEmbedAndDeleteAsync(userChannel, eb, TimeSpan.FromSeconds(1)); if (!(context.Channel is IDMChannel)) { await feedback.SendConfirmationAsync(context, "Please check your private messages."); } await @this.SendInteractiveMessageAndDeleteAsync(userChannel, message, timeout); } catch (HttpException hex) { if (hex.WasCausedByDMsNotAccepted()) { await feedback.SendWarningAsync ( context, "You don't accept DMs from non-friends on this server, so I'm unable to do that." ); } throw; } }
public void RegisterInteractiveMessageHandler() { // Arrange var handler = Substitute.For <IInteractiveMessageHandler>(); var otherInteractiveMessage = new InteractiveMessage { Actions = { new Button { Name = "other" } } }; var interactiveMessage = new InteractiveMessage { Actions = { new Button { Name = "action" } } }; var sut = Configure(c => c.RegisterInteractiveMessageHandler("action", handler)); // Act HandleLegacyInteractiveMessages(sut, new[] { otherInteractiveMessage, interactiveMessage }); // Assert handler.DidNotReceive().Handle(otherInteractiveMessage); handler.Received().Handle(interactiveMessage); }
public async Task <InteractiveResponse> NextMessageAsync(SocketCommandContext context, InteractiveMessage interactiveMessage) { var eventTrigger = new TaskCompletionSource <InteractiveResponse>(); Task Func(SocketMessage m) => HandlerAsync(m, context, eventTrigger, interactiveMessage); context.Client.MessageReceived += Func; var trigger = eventTrigger.Task; var delay = Task.Delay(interactiveMessage.TimeSpan); var task = await Task.WhenAny(trigger, delay).ConfigureAwait(false); context.Client.MessageReceived -= Func; if (task == trigger) { return(await trigger.ConfigureAwait(false)); } return(new InteractiveResponse(CriteriaResult.Timeout, null)); }
private async Task <InteractiveResponse> EvaluateResponse(SocketMessage message, InteractiveMessage interactiveMessage) { var response = new InteractiveResponse(CriteriaResult.WrongResponse, message); if (interactiveMessage.CancelationWords != null) { if (message.ContainsWords(1, interactiveMessage.CaseSensitive, interactiveMessage.CancelationWords)) { response.CriteriaResult = CriteriaResult.Canceled; response.Message = null; return(response); } } response = EvaluateResponseType(message, interactiveMessage, response); if (response.CriteriaResult != CriteriaResult.Success && interactiveMessage.ResponseType != InteractiveTextResponseType.Any) { await interactiveMessage.SendWrongResponseMessages(); } return(response); }
public void ShowNotification(string notification) { // basic checks if (String.IsNullOrWhiteSpace(notification)) { throw new ArgumentNullException("notification"); } // show or enque message lock (syncObject) { // if no items are queued then show the message, else enque var message = new InteractiveMessage() { Message = notification }; if (this.messages.Count == 0 && this.currentMessage == null) { ShowMessage(message); } else { messages.Enqueue(message); } } }
/** * A null interactor does nothing. When the messages end displaying, the interactor * terminates. One would prefer the simple "End"/"Continue" terminator (i.e. a * button or game input with those semantics), however, this one serves also for * a testing purpose. */ protected override IEnumerator Input(InteractiveMessage interactiveMessage) { yield break; }
public Task <MessageResponse> Handle(InteractiveMessage request) => _interactiveMessages.Handle(request);
private void ShowMessage(InteractiveMessage message) { this.HeaderText.Text = message.Message; VisualStateManager.GoToState(this, VISIBLE_STATENAME, true); this.currentMessage = message; }
private async Task <HttpResponse> HandleInteractiveMessage(HttpContext context, InteractiveMessage interactiveMessage) { var response = await _slackInteractiveMessages.Handle(interactiveMessage).ConfigureAwait(false); var responseJson = response == null ? null : interactiveMessage.IsAppUnfurl ? Serialize(new AttachmentUpdateResponse(response)) : Serialize(new MessageUpdateResponse(response)); return(await context.Respond(HttpStatusCode.OK, "application/json", responseJson).ConfigureAwait(false)); }
/** * The implementation of this input does three important stuff: * 1. Sets the result in null, and content in null. * 2. Waits until the result is no longer null. */ protected override IEnumerator Input(InteractiveMessage interactiveMessage) { Result = null; Content = null; yield return(new WaitWhile(delegate() { return Result == null; })); }