private async Task <bool> ImageValidatorAsync(PromptValidatorContext <IList <Attachment> > promptContext, CancellationToken cancellationToken) { var userData = await BotStateAccessor.GetAsync(promptContext.Context, () => new UserData(), cancellationToken); bool result = false; var userInput = promptContext.Recognized.Value; if (userInput != null && userInput.Any()) { var remoteFileUrl = userInput[0].ContentUrl; // We make the call to the CustomVisionService var imageResult = await CustomVisionService.AnalyzeAsync(remoteFileUrl); if (imageResult != null) { userData.ImageBoundingBox = imageResult.BoundingBox; userData.CroppedImage = await ImageUtils.GetCroppedImageAsync(remoteFileUrl, imageResult.BoundingBox.Left, imageResult.BoundingBox.Top, imageResult.BoundingBox.Width, imageResult.BoundingBox.Height); result = imageResult.TagName.Contains("watch"); } } return(await Task.FromResult(result)); }
private async Task <DialogTurnResult> AskforPhotoStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { var userData = await BotStateAccessor.GetAsync(stepContext.Context, () => new UserData(), cancellationToken); // Get the text from the activity to use to show the correct card var text = stepContext.Context.Activity.Text.ToLowerInvariant(); var isPositiveFeedback = await TextAnalyticsService.GetTextSentimentAsync(text) > 0.5; userData.ProductWasFound = isPositiveFeedback; if (isPositiveFeedback) { // We go directly to the next step as we don't need any input from the user return(await stepContext.NextAsync()); } else { return(await stepContext.PromptAsync( AskForImage, new PromptOptions { Prompt = MessageFactory.Text("Do you have a photo of a watch you like? In order to help you we will need an image of a simillar watch to search."), RetryPrompt = MessageFactory.Text("I didn't find any watch on the provided image. Please provide an image with a similar watch you are looking for to continue"), }, cancellationToken)); } }
private async Task <DialogTurnResult> SearchWatchesStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { var userData = await BotStateAccessor.GetAsync(stepContext.Context, () => new UserData(), cancellationToken); if (userData.ProductWasFound) { await stepContext.Context.SendActivityAsync("I'm happy that you like them! Please take your time looking at these items. I'm here to help in case of any questions.", cancellationToken : cancellationToken); // We end the dialog flow on this step as we don't need any other confirmation at this point. return(await stepContext.EndDialogAsync(cancellationToken : cancellationToken)); } else { var activity = stepContext.Context.Activity; var file = activity.Attachments[0]; var reply = activity.CreateReply(); // Display cropped picture of the watch var croppedImageAttachment = await BotUtils.CreateAndUploadAttachmentAsync(reply.ServiceUrl, "image/png", reply.Conversation.Id, userData.CroppedImage.Image, "Cropped Image", _botConfigOptions); reply.Attachments = new List <Attachment>() { croppedImageAttachment }; reply.Text = "I can see the watch. Let me see what we have in stock."; await stepContext.Context.SendActivityAsync(reply, cancellationToken); var imageBoxCoordinates = userData.ImageBoundingBox; var boundingRectangle = await ImageUtils.GetBoundingRectangleAsync(imageBoxCoordinates.Top, imageBoxCoordinates.Left, imageBoxCoordinates.Width, imageBoxCoordinates.Height, file.ContentUrl); reply.Attachments = await GetSimilarWatchesAsync(file.ContentUrl, boundingRectangle); reply.AttachmentLayout = AttachmentLayoutTypes.Carousel; reply.Text = "I found these similar watches. Let me know if you have any questions."; // Send the card(s) to the user as an attachment to the activity await stepContext.Context.SendActivityAsync(reply, cancellationToken); // We end the dialog flow on this step as we don't need any other confirmation at this point. return(await stepContext.EndDialogAsync(cancellationToken : cancellationToken)); } }