Example #1
0
        protected override async Task <PromptRecognizerResult <RecreateEventState?> > OnRecognizeAsync(ITurnContext turnContext, IDictionary <string, object> state, PromptOptions options, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            var result = new PromptRecognizerResult <RecreateEventState?>();

            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                var message       = turnContext.Activity.AsMessageActivity();
                var culture       = turnContext.Activity.Locale ?? DefaultLocale ?? English;
                var recreateState = GetStateFromMessage(message.Text, culture);
                if (recreateState != null)
                {
                    result.Succeeded = true;
                    result.Value     = recreateState;
                }
            }

            if (maxReprompt > 0 && Convert.ToInt32(state[AttemptCountKey]) >= maxReprompt)
            {
                result.Succeeded = true;
            }

            return(await Task.FromResult(result));
        }
Example #2
0
        protected override async Task OnPromptAsync(ITurnContext turnContext, IDictionary <string, object> state, PromptOptions options, bool isRetry, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            if (!(options is GetEventOptions))
            {
                throw new Exception(nameof(options) + " should be GetEventOptions");
            }

            if (calendarService == null || userTimeZone == null)
            {
                var getEventOptions = (GetEventOptions)options;
                calendarService = getEventOptions.CalendarService;
                userTimeZone    = getEventOptions.TimeZone;
            }

            if (isRetry && options.RetryPrompt != null)
            {
                await turnContext.SendActivityAsync(options.RetryPrompt, cancellationToken).ConfigureAwait(false);
            }
            else if (options.Prompt != null)
            {
                await turnContext.SendActivityAsync(options.Prompt, cancellationToken).ConfigureAwait(false);
            }
        }
Example #3
0
        protected override async Task <PromptRecognizerResult <ResendEmailState?> > OnRecognizeAsync(ITurnContext turnContext, IDictionary <string, object> state, PromptOptions options, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            var result = new PromptRecognizerResult <ResendEmailState?>();

            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                var message = turnContext.Activity.AsMessageActivity();
                ResendEmailState?recreateState = GetStateFromMessage(message.Text);

                var promptRecognizerResult = ConfirmRecognizerHelper.ConfirmYesOrNo(message.Text, turnContext.Activity.Locale);
                if (promptRecognizerResult.Succeeded && promptRecognizerResult.Value == false)
                {
                    recreateState = ResendEmailState.Cancel;
                }

                if (recreateState != null)
                {
                    result.Succeeded = true;
                    result.Value     = recreateState;
                }
            }

            return(await Task.FromResult(result));
        }
Example #4
0
        protected async Task <PromptOptions> GenerateOptions(List <Person> personList, List <Person> userList, DialogContext dc)
        {
            var state = await Accessor.GetAsync(dc.Context);

            var pageIndex = state.ShowAttendeesIndex;
            var pageSize  = 5;
            var skip      = pageSize * pageIndex;
            var options   = new PromptOptions
            {
                Choices = new List <Choice>(),
                Prompt  = dc.Context.Activity.CreateReply(CreateEventResponses.ConfirmRecipient),
            };

            for (var i = 0; i < personList.Count; i++)
            {
                var user        = personList[i];
                var mailAddress = user.ScoredEmailAddresses.FirstOrDefault()?.Address ?? user.UserPrincipalName;

                var choice = new Choice()
                {
                    Value    = $"**{user.DisplayName}: {mailAddress}**",
                    Synonyms = new List <string> {
                        (i + 1).ToString(), user.DisplayName, user.DisplayName.ToLower(), mailAddress
                    },
                };

                var userName = user.UserPrincipalName?.Split("@").FirstOrDefault() ?? user.UserPrincipalName;
                if (!string.IsNullOrEmpty(userName))
                {
                    {
                        choice.Synonyms.Add(userName);
                        choice.Synonyms.Add(userName.ToLower());
                    }

                    if (skip <= 0)
                    {
                        if (options.Choices.Count >= pageSize)
                        {
                            return(options);
                        }

                        options.Choices.Add(choice);
                    }
                    else
                    {
                        skip--;
                    }
                }
            }

            if (options.Choices.Count == 0)
            {
                pageSize = 10;
            }

            for (var i = 0; i < userList.Count; i++)
            {
                var user        = userList[i];
                var mailAddress = user.ScoredEmailAddresses.FirstOrDefault()?.Address ?? user.UserPrincipalName;
                var choice      = new Choice()
                {
                    Value    = $"{user.DisplayName}: {mailAddress}",
                    Synonyms = new List <string> {
                        (i + 1).ToString(), user.DisplayName, user.DisplayName.ToLower(), mailAddress
                    },
                };

                var userName = user.UserPrincipalName?.Split("@").FirstOrDefault() ?? user.UserPrincipalName;
                if (!string.IsNullOrEmpty(userName))
                {
                    choice.Synonyms.Add(userName);
                    choice.Synonyms.Add(userName.ToLower());
                }

                if (skip <= 0)
                {
                    if (options.Choices.Count >= pageSize)
                    {
                        return(options);
                    }

                    options.Choices.Add(choice);
                }
                else if (skip >= 10)
                {
                    return(options);
                }
                else
                {
                    skip--;
                }
            }

            return(options);
        }
        /// <summary>
        /// Once we have a setting we need to process the corresponding value.
        /// </summary>
        /// <param name="sc">Step Context.</param>
        /// <returns>Dialog Turn Result.</returns>
        private async Task <DialogTurnResult> ProcessVehicleSettingsChangeAsync(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await Accessor.GetAsync(sc.Context, cancellationToken : cancellationToken);

            if (state.Changes.Any())
            {
                var settingValues = state.GetUniqueSettingValues();
                if (!settingValues.Any())
                {
                    // This shouldn't happen because the SettingFilter would just add all possible values to let the user select from them.
                    await sc.Context.SendActivityAsync(TemplateManager.GenerateActivityForLocale(VehicleSettingsResponses.VehicleSettingsMissingSettingValue), cancellationToken);

                    return(await sc.EndDialogAsync(cancellationToken : cancellationToken));
                }
                else
                {
                    // We have found multiple setting values, which we need to prompt the user to resolve
                    if (settingValues.Count() > 1)
                    {
                        var settingName = state.Changes.First().SettingName;
                        var setting     = this.settingList.FindSetting(settingName);

                        // If an image filename is provided we'll use it otherwise fall back to the generic car one
                        var imageName = setting.ImageFileName ?? FallbackSettingImageFileName;

                        // If we have more than one setting value matching, prompt the user to choose
                        var options = new PromptOptions()
                        {
                            Choices = new List <Choice>(),
                        };

                        for (var i = 0; i < settingValues.Count; ++i)
                        {
                            var item     = settingValues[i];
                            var synonyms = new List <string>
                            {
                                item,
                                (i + 1).ToString()
                            };
                            synonyms.AddRange(settingList.GetAlternativeNamesForSettingValue(settingName, item));
                            var choice = new Choice()
                            {
                                Value    = item,
                                Synonyms = synonyms,
                            };
                            options.Choices.Add(choice);
                        }

                        var promptReplacements = new { settingName };
                        var cardModel          = new AutomotiveCardModel()
                        {
                            ImageUrl = GetSettingCardImageUri(imageName)
                        };

                        var card = TemplateManager.GenerateActivityForLocale(GetDivergedCardName(sc.Context, "AutomotiveCard"), cardModel);
                        options.Prompt             = TemplateManager.GenerateActivityForLocale(VehicleSettingsResponses.VehicleSettingsSettingValueSelection, promptReplacements);
                        options.Prompt.Attachments = card.Attachments;

                        // Default Text property is clumsy for speech
                        options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options.Prompt);

                        // Workaround. In teams, prompt will be changed to HeroCard and adaptive card could not be shown. So send them separatly
                        if (Channel.GetChannelId(sc.Context) == Channels.Msteams)
                        {
                            await sc.Context.SendActivityAsync(options.Prompt, cancellationToken);

                            options.Prompt = null;
                        }

                        return(await sc.PromptAsync(Actions.SettingValueSelectionPrompt, options, cancellationToken));
                    }
                    else
                    {
                        // We only have one setting value so proceed to next step
                        return(await sc.NextAsync(cancellationToken : cancellationToken));
                    }
                }
            }
            else
            {
                // No setting value was understood
                await sc.Context.SendActivityAsync(TemplateManager.GenerateActivityForLocale(VehicleSettingsResponses.VehicleSettingsOutOfDomain), cancellationToken);

                return(await sc.EndDialogAsync(cancellationToken : cancellationToken));
            }
        }
Example #6
0
        public async Task <DialogTurnResult> AfterUpdateStartTime(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context);

                if (sc.Result != null)
                {
                    state.Events = sc.Result as List <EventModel>;
                }

                if (state.Events.Count == 0)
                {
                    // should not doto this part. add log here for safe
                    await HandleDialogExceptions(sc, new Exception("Unexpect zero events count"));

                    return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
                }
                else
                if (state.Events.Count > 1)
                {
                    var options = new PromptOptions()
                    {
                        Choices = new List <Choice>(),
                    };

                    for (var i = 0; i < state.Events.Count; i++)
                    {
                        var item   = state.Events[i];
                        var choice = new Choice()
                        {
                            Value    = string.Empty,
                            Synonyms = new List <string> {
                                (i + 1).ToString(), item.Title
                            },
                        };
                        options.Choices.Add(choice);
                    }

                    var replyToConversation = sc.Context.Activity.CreateReply(ChangeEventStatusResponses.MultipleEventsStartAtSameTime);
                    replyToConversation.AttachmentLayout = AttachmentLayoutTypes.Carousel;
                    replyToConversation.Attachments      = new List <Microsoft.Bot.Schema.Attachment>();

                    var cardsData = new List <CalendarCardData>();
                    foreach (var item in state.Events)
                    {
                        var meetingCard = item.ToAdaptiveCardData(state.GetUserTimeZone());
                        var replyTemp   = sc.Context.Activity.CreateAdaptiveCardReply(CalendarMainResponses.GreetingMessage, item.OnlineMeetingUrl == null ? "Dialogs/Shared/Resources/Cards/CalendarCardNoJoinButton.json" : "Dialogs/Shared/Resources/Cards/CalendarCard.json", meetingCard);
                        replyToConversation.Attachments.Add(replyTemp.Attachments[0]);
                    }

                    options.Prompt = replyToConversation;

                    return(await sc.PromptAsync(Actions.EventChoice, options));
                }
                else
                {
                    return(await sc.EndDialogAsync(true));
                }
            }
            catch (SkillException ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
            catch (Exception ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
        public async Task ConfirmPromptChoiceOptionsMultipleAttempts()
        {
            var convoState  = new ConversationState(new MemoryStorage());
            var dialogState = convoState.CreateProperty <DialogState>("dialogState");

            var adapter = new TestAdapter(TestAdapter.CreateConversation(TestContext.TestName))
                          .Use(new AutoSaveStateMiddleware(convoState))
                          .Use(new TranscriptLoggerMiddleware(new FileTranscriptLogger()));

            var dialogs = new DialogSet(dialogState);
            var prompt  = new ConfirmPrompt("ConfirmPrompt", defaultLocale: Culture.English);

            // Set options
            prompt.ChoiceOptions = new Choices.ChoiceFactoryOptions {
                IncludeNumbers = true
            };
            prompt.Style = Choices.ListStyle.Inline;
            dialogs.Add(prompt);

            await new TestFlow(adapter, async(turnContext, cancellationToken) =>
            {
                var dc = await dialogs.CreateContextAsync(turnContext, cancellationToken);

                var results = await dc.ContinueDialogAsync(cancellationToken);
                if (results.Status == DialogTurnStatus.Empty)
                {
                    var options = new PromptOptions
                    {
                        Prompt = new Activity
                        {
                            Type = ActivityTypes.Message,
                            Text = "Please confirm.",
                        },
                        RetryPrompt = new Activity
                        {
                            Type = ActivityTypes.Message,
                            Text = "Please confirm, say 'yes' or 'no' or something like that.",
                        },
                    };
                    await dc.PromptAsync("ConfirmPrompt", options, cancellationToken);
                }
                else if (results.Status == DialogTurnStatus.Complete)
                {
                    if ((bool)results.Result)
                    {
                        await turnContext.SendActivityAsync(MessageFactory.Text("Confirmed."), cancellationToken);
                    }
                    else
                    {
                        await turnContext.SendActivityAsync(MessageFactory.Text("Not confirmed."), cancellationToken);
                    }
                }
            })
            .Send("hello")
            .AssertReply("Please confirm. (1) Yes or (2) No")
            .Send("lala")
            .AssertReply("Please confirm, say 'yes' or 'no' or something like that. (1) Yes or (2) No")
            .Send("what")
            .AssertReply("Please confirm, say 'yes' or 'no' or something like that. (1) Yes or (2) No")
            .Send("2")
            .AssertReply("Not confirmed.")
            .StartTestAsync();
        }
 public EditablePromptChoice(PromptOptions <T> promptOptions) : base(promptOptions)
 {
 }
        public new static void Choice <T>(IDialogContext context, ResumeAfter <T> resume, PromptOptions <T> promptOptions)
        {
            if (!(context is TranslatingDialogContext))
            {
                context = new TranslatingDialogContext(context);
            }

            var child = new EditablePromptChoice <T>(promptOptions);

            var cp = new ResumeReplacer <T>(resume);

            context.Call <T>(child, cp.ResumeReplace);
        }
Example #10
0
        /// <summary>
        /// Process result from choice prompt and begin route direction dialog.
        /// </summary>
        /// <param name="sc">Step Context.</param>
        /// <param name="cancellationToken">Cancellation Token.</param>
        /// <returns>Dialog Turn Result.</returns>
        protected async Task <DialogTurnResult> ProcessPointOfInterestSelectionAsync(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context, () => new PointOfInterestSkillState(), cancellationToken);

                bool shouldInterrupt = sc.Context.TurnState.ContainsKey(StateProperties.InterruptKey);

                if (shouldInterrupt)
                {
                    return(await sc.CancelAllDialogsAsync(cancellationToken));
                }

                var defaultReplyMessage = TemplateManager.GenerateActivity(POISharedResponses.GetRouteToActiveLocationLater);

                if (sc.Result != null)
                {
                    var userSelectIndex = 0;

                    if (sc.Result is bool)
                    {
                        state.Destination = state.LastFoundPointOfInterests[userSelectIndex];
                        state.LastFoundPointOfInterests = null;
                    }
                    else if (sc.Result is FoundChoice)
                    {
                        // Update the destination state with user choice.
                        userSelectIndex = (sc.Result as FoundChoice).Index;

                        if (userSelectIndex == SpecialChoices.Cancel || userSelectIndex >= state.LastFoundPointOfInterests.Count)
                        {
                            await sc.Context.SendActivityAsync(TemplateManager.GenerateActivity(POISharedResponses.CancellingMessage), cancellationToken);

                            return(await sc.EndDialogAsync(cancellationToken : cancellationToken));
                        }

                        state.Destination = state.LastFoundPointOfInterests[userSelectIndex];
                        state.LastFoundPointOfInterests = null;
                    }

                    var options = new PromptOptions()
                    {
                        Choices = new List <Choice>()
                    };

                    var callString            = TemplateManager.GetString(PointOfInterestSharedStrings.CALL);
                    var showDirectionsString  = TemplateManager.GetString(PointOfInterestSharedStrings.SHOW_DIRECTIONS);
                    var startNavigationString = TemplateManager.GetString(PointOfInterestSharedStrings.START_NAVIGATION);
                    var cardTitleString       = TemplateManager.GetString(PointOfInterestSharedStrings.CARD_TITLE);

                    bool hasCall = !string.IsNullOrEmpty(state.Destination.Phone);
                    if (hasCall)
                    {
                        options.Choices.Add(new Choice {
                            Value = callString
                        });
                    }

                    options.Choices.Add(new Choice {
                        Value = showDirectionsString
                    });
                    options.Choices.Add(new Choice {
                        Value = startNavigationString
                    });

                    var mapsService = ServiceManager.InitMapsService(Settings, sc.Context.Activity.Locale);
                    state.Destination = await mapsService.GetPointOfInterestDetailsAsync(state.Destination, ImageSize.DetailsWidth, ImageSize.DetailsHeight);

                    state.Destination.ProviderDisplayText = state.Destination.GenerateProviderDisplayText();

                    state.Destination.CardTitle             = cardTitleString;
                    state.Destination.ActionCall            = callString;
                    state.Destination.ActionShowDirections  = showDirectionsString;
                    state.Destination.ActionStartNavigation = startNavigationString;

                    var card = new Card
                    {
                        Name = GetDivergedCardName(sc.Context, hasCall ? CardNames.PointOfInterestDetails : CardNames.PointOfInterestDetailsNoCall),
                        Data = state.Destination,
                    };

                    string promptResponse = hasCall ? FindPointOfInterestResponses.PointOfInterestDetails : FindPointOfInterestResponses.PointOfInterestDetailsNoCall;

                    if (promptResponse == null)
                    {
                        options.Prompt = TemplateManager.GenerateActivity(card);
                    }
                    else
                    {
                        options.Prompt = TemplateManager.GenerateActivity(promptResponse, card, card.Data);
                    }

                    // If DestinationActionType is provided, skip the SelectActionPrompt with appropriate choice index
                    if (state.DestinationActionType != DestinationActionType.None)
                    {
                        int choiceIndex = -1;
                        if (state.DestinationActionType == DestinationActionType.Call)
                        {
                            choiceIndex = hasCall ? 0 : -1;
                        }
                        else if (state.DestinationActionType == DestinationActionType.ShowDirectionsThenStartNavigation)
                        {
                            choiceIndex = hasCall ? 1 : 0;
                        }
                        else if (state.DestinationActionType == DestinationActionType.StartNavigation)
                        {
                            choiceIndex = hasCall ? 2 : 1;
                        }

                        if (choiceIndex >= 0)
                        {
                            await sc.Context.SendActivityAsync(options.Prompt, cancellationToken);

                            return(await sc.NextAsync(new FoundChoice()
                            {
                                Index = choiceIndex
                            }, cancellationToken));
                        }
                    }

                    return(await sc.PromptAsync(Actions.SelectActionPrompt, options, cancellationToken));
                }

                await sc.Context.SendActivityAsync(defaultReplyMessage, cancellationToken);

                return(await sc.EndDialogAsync(cancellationToken : cancellationToken));
            }
            catch (Exception ex)
            {
                await HandleDialogExceptionsAsync(sc, ex, cancellationToken);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
Example #11
0
        protected override async Task <PromptRecognizerResult <IList <DateTimeResolution> > > OnRecognizeAsync(ITurnContext turnContext, IDictionary <string, object> state, PromptOptions options, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            var result = new PromptRecognizerResult <IList <DateTimeResolution> >();

            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                var message = turnContext.Activity.AsMessageActivity();
                var culture = turnContext.Activity.Locale ?? DefaultLocale ?? English;
                IList <DateTimeResolution> date = GetDateFromMessage(message.Text, culture);
                if (date.Count > 0)
                {
                    result.Succeeded = true;
                    result.Value     = date;
                }
            }

            return(await Task.FromResult(result));
        }
Example #12
0
        private async Task <DialogTurnResult> Center2StepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            string  json = @$ "{stepContext.Result}";
            JObject jobj = JObject.Parse(json);

            stepContext.Values["center1"] = jobj["center1"].ToString();

            if ((string)stepContext.Values["center1"] == "서울")
            {
                // Create the Adaptive Card
                var cardJson       = File.ReadAllText("./Cards/center2_1Card.json");
                var cardAttachment = new Attachment()
                {
                    ContentType = "application/vnd.microsoft.card.adaptive",
                    Content     = JsonConvert.DeserializeObject(cardJson),
                };

                // Create the text prompt
                var opts = new PromptOptions
                {
                    Prompt = new Activity
                    {
                        Attachments = new List <Attachment>()
                        {
                            cardAttachment
                        },
                        Type = ActivityTypes.Message,
                    }
                };

                // Display a Text Prompt and wait for input
                return(await stepContext.PromptAsync(AdaptivePromptId, opts, cancellationToken));
            }

            else
            {
                // Create the Adaptive Card
                var cardJson       = File.ReadAllText("./Cards/center2_2Card.json");
                var cardAttachment = new Attachment()
                {
                    ContentType = "application/vnd.microsoft.card.adaptive",
                    Content     = JsonConvert.DeserializeObject(cardJson),
                };

                // Create the text prompt
                var opts = new PromptOptions
                {
                    Prompt = new Activity
                    {
                        Attachments = new List <Attachment>()
                        {
                            cardAttachment
                        },
                        Type = ActivityTypes.Message,
                    }
                };

                // Display a Text Prompt and wait for input
                return(await stepContext.PromptAsync(AdaptivePromptId, opts, cancellationToken));
            }
        }
        protected override async Task OnPromptAsync(ITurnContext turnContext, IDictionary <string, object> state, PromptOptions options, bool isRetry, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            if (!(options is NoSkipPromptOptions))
            {
                throw new Exception(nameof(options) + " should be NoSkipPromptOptions");
            }

            NoSkipPromptOptions noSkipOption = (NoSkipPromptOptions)options;

            if (isRetry && noSkipOption.RetryPrompt != null && !IsSkip)
            {
                await turnContext.SendActivityAsync(noSkipOption.RetryPrompt, cancellationToken).ConfigureAwait(false);
            }
            else if (IsSkip && noSkipOption.NoSkipPrompt != null)
            {
                await turnContext.SendActivityAsync(noSkipOption.NoSkipPrompt, cancellationToken).ConfigureAwait(false);
            }
            else if (noSkipOption.Prompt != null)
            {
                await turnContext.SendActivityAsync(noSkipOption.Prompt, cancellationToken).ConfigureAwait(false);
            }
        }
        protected override async Task <PromptRecognizerResult <AttributeType?> > OnRecognizeAsync(ITurnContext turnContext, IDictionary <string, object> state, PromptOptions options, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            var result = new PromptRecognizerResult <AttributeType?>();

            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                var message = turnContext.Activity.AsMessageActivity();

                var promptRecognizerResult = ConfirmRecognizerHelper.ConfirmYesOrNo(message.Text, turnContext.Activity.Locale);
                if (promptRecognizerResult.Succeeded && !promptRecognizerResult.Value)
                {
                    result.Succeeded = true;
                    result.Value     = null;
                }

                if (!result.Succeeded)
                {
                    var text = message.Text.ToLowerInvariant();
                    foreach (var attribute in attributes)
                    {
                        if (IsMessageAttributeMatch(text, attribute))
                        {
                            result.Succeeded = true;
                            result.Value     = attribute;
                            break;
                        }
                    }
                }
            }

            return(await Task.FromResult(result));
        }
Example #15
0
        /// <summary>
        /// Top level processing, is the user trying to check or change a setting?.
        /// </summary>
        /// <param name="sc">Step Context.</param>
        /// <param name="cancellationToken">Cancellation Token.</param>
        /// <returns>Dialog Turn Result.</returns>
        public async Task <DialogTurnResult> ProcessSetting(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await Accessor.GetAsync(sc.Context, () => new AutomotiveSkillState());

            var luisResult = state.VehicleSettingsLuisResult;
            var topIntent  = luisResult?.TopIntent().intent;

            switch (topIntent.Value)
            {
            case SettingsLuis.Intent.VEHICLE_SETTINGS_CHANGE:
            case SettingsLuis.Intent.VEHICLE_SETTINGS_DECLARATIVE:

                // Perform post-processing on the entities, if it's declarative we indicate for special processing (opposite of the condition they've expressed)
                settingFilter.PostProcessSettingName(state, topIntent.Value == SettingsLuis.Intent.VEHICLE_SETTINGS_DECLARATIVE ? true : false);

                // Perform content logic and remove entities that don't make sense
                settingFilter.ApplyContentLogic(state);

                var settingNames = state.GetUniqueSettingNames();
                if (!settingNames.Any())
                {
                    // missing setting name
                    await sc.Context.SendActivityAsync(ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsMissingSettingName));

                    return(await sc.EndDialogAsync());
                }
                else if (settingNames.Count() > 1)
                {
                    // If we have more than one setting name matching prompt the user to choose
                    var options = new PromptOptions()
                    {
                        Choices = new List <Choice>(),
                    };

                    for (var i = 0; i < settingNames.Count; ++i)
                    {
                        var item     = settingNames[i];
                        var synonyms = new List <string>
                        {
                            item,
                            (i + 1).ToString()
                        };
                        synonyms.AddRange(settingList.GetAlternativeNamesForSetting(item));
                        var choice = new Choice()
                        {
                            Value    = item,
                            Synonyms = synonyms,
                        };
                        options.Choices.Add(choice);
                    }

                    var cardModel = new AutomotiveCardModel()
                    {
                        ImageUrl = GetSettingCardImageUri(FallbackSettingImageFileName)
                    };

                    var card = new Card(GetDivergedCardName(sc.Context, "AutomotiveCard"), cardModel);

                    options.Prompt = ResponseManager.GetCardResponse(VehicleSettingsResponses.VehicleSettingsSettingNameSelection, card, tokens: null);

                    // Default Text property is clumsy for speech
                    options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options);

                    // Workaround. In teams, prompt will be changed to HeroCard and adaptive card could not be shown. So send them separatly
                    if (Channel.GetChannelId(sc.Context) == Channels.Msteams)
                    {
                        await sc.Context.SendActivityAsync(options.Prompt);

                        options.Prompt = null;
                    }

                    return(await sc.PromptAsync(Actions.SettingNameSelectionPrompt, options));
                }
                else
                {
                    // Only one setting detected so move on to next stage
                    return(await sc.NextAsync());
                }

            case SettingsLuis.Intent.VEHICLE_SETTINGS_CHECK:
                await sc.Context.SendActivityAsync(sc.Context.Activity.CreateReply("The skill doesn't support checking vehicle settings quite yet!"));

                return(await sc.EndDialogAsync(true, cancellationToken));

            default:
                await sc.Context.SendActivityAsync(ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsOutOfDomain));

                return(await sc.EndDialogAsync(true, cancellationToken));
            }
        }
        protected async Task <DialogTurnResult> ShowTicketAsync(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState(), cancellationToken);

            state.InterruptedIntent = ITSMLuis.Intent.None;

            bool firstDisplay = false;

            if (state.PageIndex == -1)
            {
                firstDisplay    = true;
                state.PageIndex = 0;
            }

            var management = ServiceManager.CreateManagement(Settings, sc.Result as TokenResponse, state.ServiceCache);

            var urgencies = new List <UrgencyLevel>();

            if (state.UrgencyLevel != UrgencyLevel.None)
            {
                urgencies.Add(state.UrgencyLevel);
            }

            var states = new List <TicketState>();

            if (state.TicketState != TicketState.None)
            {
                if (state.TicketState == TicketState.Active)
                {
                    states.Add(TicketState.New);
                    states.Add(TicketState.InProgress);
                    states.Add(TicketState.OnHold);
                    states.Add(TicketState.Resolved);
                }
                else if (state.TicketState == TicketState.Inactive)
                {
                    states.Add(TicketState.Closed);
                    states.Add(TicketState.Canceled);
                }
                else
                {
                    states.Add(state.TicketState);
                }
            }

            var countResult = await management.CountTicket(query : state.TicketTitle, urgencies : urgencies, number : state.TicketNumber, states : states);

            if (!countResult.Success)
            {
                return(await SendServiceErrorAndCancelAsync(sc, countResult, cancellationToken));
            }

            // adjust PageIndex
            int maxPage = Math.Max(0, (countResult.Tickets.Length - 1) / Settings.LimitSize);

            state.PageIndex = Math.Max(0, Math.Min(state.PageIndex, maxPage));

            // TODO handle consistency with count
            var result = await management.SearchTicket(state.PageIndex, query : state.TicketTitle, urgencies : urgencies, number : state.TicketNumber, states : states);

            if (!result.Success)
            {
                return(await SendServiceErrorAndCancelAsync(sc, result, cancellationToken));
            }

            if (result.Tickets == null || result.Tickets.Length == 0)
            {
                if (firstDisplay)
                {
                    var options = new PromptOptions()
                    {
                        Prompt = TemplateManager.GenerateActivity(TicketResponses.TicketShowNone)
                    };

                    return(await sc.PromptAsync(Actions.NavigateYesNoPrompt, options, cancellationToken));
                }
                else
                {
                    // it is unlikely to happen now
                    var token = new Dictionary <string, object>()
                    {
                        { "Page", (state.PageIndex + 1).ToString() }
                    };

                    var options = new PromptOptions()
                    {
                        Prompt = TemplateManager.GenerateActivity(TicketResponses.TicketEnd, token)
                    };

                    return(await sc.PromptAsync(Actions.NavigateYesNoPrompt, options, cancellationToken));
                }
            }
            else
            {
                var cards = new List <Card>();
                foreach (var ticket in result.Tickets)
                {
                    cards.Add(GetTicketCard(sc.Context, state, ticket));
                }

                await sc.Context.SendActivityAsync(GetCardsWithIndicator(state.PageIndex, maxPage, cards), cancellationToken);

                var options = new PromptOptions()
                {
                    Prompt = GetNavigatePrompt(sc.Context, TicketResponses.TicketShow, state.PageIndex, maxPage),
                };

                return(await sc.PromptAsync(Actions.ShowNavigatePrompt, options, cancellationToken));
            }
        }
Example #17
0
        protected override Task <PromptRecognizerResult <Activity> > OnRecognizeAsync(ITurnContext turnContext, IDictionary <string, object> state, PromptOptions options, CancellationToken cancellationToken)
        {
            var result   = new PromptRecognizerResult <Activity>();
            var activity = turnContext.Activity;

            if (activity.Type == ActivityTypes.Event)
            {
                var ev = activity.AsEventActivity();

                if (ev.Name == EventName)
                {
                    result.Succeeded = true;
                    result.Value     = turnContext.Activity;
                }
            }

            return(Task.FromResult(result));
        }
        protected override Task <PromptRecognizerResult <string> > OnRecognizeAsync(ITurnContext turnContext, IDictionary <string, object> state, PromptOptions options, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            var result = new PromptRecognizerResult <string>();

            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                var message = turnContext.Activity.AsMessageActivity();
                if (!string.IsNullOrEmpty(message.Text))
                {
                    result.Succeeded = true;
                    result.Value     = message.Text;
                }
                /*Add handling for Value from adaptive card*/
                else if (message.Value != null)
                {
                    result.Succeeded = true;
                    result.Value     = message.Value.ToString();
                }
            }

            return(Task.FromResult(result));
        }
Example #19
0
        protected override async Task <PromptRecognizerResult <RecreateMeetingRoomState?> > OnRecognizeAsync(ITurnContext turnContext, IDictionary <string, object> state, PromptOptions options, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            var result = new PromptRecognizerResult <RecreateMeetingRoomState?>();

            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                var luisResult = turnContext.TurnState.Get <CalendarLuis>(StateProperties.CalendarLuisResultKey);
                if (luisResult == null)
                {
                    // Get cognitive models for the current locale.
                    var localizedServices = Services.GetCognitiveModels();

                    // Run LUIS recognition on Skill model and store result in turn state.
                    localizedServices.LuisServices.TryGetValue("Calendar", out var skillLuisService);
                    if (skillLuisService != null)
                    {
                        luisResult = await skillLuisService.RecognizeAsync <CalendarLuis>(turnContext, default);

                        turnContext.TurnState[StateProperties.CalendarLuisResultKey] = luisResult;
                    }
                    else
                    {
                        throw new Exception("The skill LUIS Model could not be found in your Bot Services configuration.");
                    }
                }

                var recreateState = GetStateFromMessage(turnContext);
                if (recreateState != null)
                {
                    result.Succeeded = true;
                    result.Value     = recreateState;
                }
            }

            if (maxReprompt > 0 && Convert.ToInt32(state[AttemptCountKey]) >= maxReprompt)
            {
                result.Succeeded = true;
            }

            return(await Task.FromResult(result));
        }
        private async Task <PromptOptions> GenerateOptionsForEmail(WaterfallStepContext sc, CustomizedPerson confirmedPerson, ITurnContext context, bool isSinglePage = true)
        {
            var state = await Accessor.GetAsync(context);

            var pageIndex = state.ShowAttendeesIndex;
            var pageSize  = 3;
            var skip      = pageSize * pageIndex;
            var emailList = confirmedPerson.Emails.ToList();

            // Go back to the last page when reaching the end.
            if (skip >= emailList.Count && pageIndex > 0)
            {
                state.ShowAttendeesIndex--;
                pageIndex = state.ShowAttendeesIndex;
                skip      = pageSize * pageIndex;
                await sc.Context.SendActivityAsync(ResponseManager.GetResponse(FindContactResponses.AlreadyLastPage));
            }

            var options = new PromptOptions
            {
                Choices = new List <Choice>(),
                Prompt  = ResponseManager.GetResponse(FindContactResponses.ConfirmMultiplContactEmailSinglePage, new StringDictionary()
                {
                    { "UserName", confirmedPerson.DisplayName }
                })
            };

            if (!isSinglePage)
            {
                options.Prompt = ResponseManager.GetResponse(FindContactResponses.ConfirmMultiplContactEmailMultiPage, new StringDictionary()
                {
                    { "UserName", confirmedPerson.DisplayName }
                });
            }

            for (var i = 0; i < emailList.Count; i++)
            {
                var user        = confirmedPerson;
                var mailAddress = emailList[i].Address ?? user.UserPrincipalName;

                var choice = new Choice()
                {
                    Value    = $"{user.DisplayName}: {mailAddress}",
                    Synonyms = new List <string> {
                        (options.Choices.Count + 1).ToString(), user.DisplayName, user.DisplayName.ToLower(), mailAddress
                    },
                };
                var userName = user.UserPrincipalName?.Split("@").FirstOrDefault() ?? user.UserPrincipalName;
                if (!string.IsNullOrEmpty(userName))
                {
                    choice.Synonyms.Add(userName);
                    choice.Synonyms.Add(userName.ToLower());
                }

                if (skip <= 0)
                {
                    if (options.Choices.Count >= pageSize)
                    {
                        options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options, ReadPreference.Chronological, ConfigData.GetInstance().MaxReadSize);
                        options.Prompt.Text += "\r\n" + GetSelectPromptEmailString(options, true);
                        options.RetryPrompt  = ResponseManager.GetResponse(CalendarSharedResponses.DidntUnderstandMessage);
                        return(options);
                    }

                    options.Choices.Add(choice);
                }
                else
                {
                    skip--;
                }
            }

            options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options, ReadPreference.Chronological, ConfigData.GetInstance().MaxReadSize);
            options.Prompt.Text += "\r\n" + GetSelectPromptEmailString(options, true);
            options.RetryPrompt  = ResponseManager.GetResponse(CalendarSharedResponses.DidntUnderstandMessage);
            return(options);
        }
        /// <summary>
        /// Look up points of interest, render cards, and ask user which to route to.
        /// </summary>
        /// <param name="sc">Step Context.</param>
        /// <param name="cancellationToken">Cancellation Token.</param>
        /// <returns>Dialog Turn Result.</returns>
        protected async Task <DialogTurnResult> GetPointOfInterestLocations(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context);

                var service            = ServiceManager.InitMapsService(Settings, sc.Context.Activity.Locale);
                var addressMapsService = ServiceManager.InitAddressMapsService(Settings, sc.Context.Activity.Locale);

                var pointOfInterestList = new List <PointOfInterestModel>();
                var cards = new List <Card>();

                if (string.IsNullOrEmpty(state.Keyword) && string.IsNullOrEmpty(state.Address))
                {
                    // No entities identified, find nearby locations
                    pointOfInterestList = await service.GetNearbyPointOfInterestListAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude);

                    cards = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                }
                else if (!string.IsNullOrEmpty(state.Keyword) && !string.IsNullOrEmpty(state.Address))
                {
                    // Get first POI matched with address, if there are multiple this could be expanded to confirm which address to use
                    var pointOfInterestAddressList = await addressMapsService.GetPointOfInterestListByAddressAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Address);

                    if (pointOfInterestAddressList.Any())
                    {
                        var pointOfInterest = pointOfInterestAddressList[0];
                        pointOfInterestList = await service.GetPointOfInterestListByQueryAsync(pointOfInterest.Geolocation.Latitude, pointOfInterest.Geolocation.Longitude, state.Keyword);

                        cards = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                    }
                    else
                    {
                        // No POIs found from address - search near current coordinates
                        pointOfInterestList = await service.GetPointOfInterestListByQueryAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Keyword);

                        cards = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                    }
                }
                else if (!string.IsNullOrEmpty(state.Keyword))
                {
                    // Fuzzy query search with keyword
                    pointOfInterestList = await service.GetPointOfInterestListByQueryAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Keyword);

                    cards = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                }
                else if (!string.IsNullOrEmpty(state.Address))
                {
                    // Fuzzy query search with address
                    pointOfInterestList = await service.GetPointOfInterestListByAddressAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Address);

                    cards = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                }

                if (cards.Count() == 0)
                {
                    var replyMessage = ResponseManager.GetResponse(POISharedResponses.NoLocationsFound);
                    await sc.Context.SendActivityAsync(replyMessage);
                }
                else if (cards.Count == 1)
                {
                    var options = new PromptOptions
                    {
                        Prompt = ResponseManager.GetCardResponse(POISharedResponses.PromptToGetRoute, cards)
                    };

                    // Workaround. In teams, HeroCard will be used for prompt and adaptive card could not be shown. So send them separatly
                    if (Channel.GetChannelId(sc.Context) == Channels.Msteams)
                    {
                        await sc.Context.SendActivityAsync(options.Prompt);

                        options.Prompt = null;
                    }

                    return(await sc.PromptAsync(Actions.ConfirmPrompt, options));
                }
                else
                {
                    var options = GetPointOfInterestPrompt(POISharedResponses.MultipleLocationsFound, pointOfInterestList, cards);

                    // Workaround. In teams, HeroCard will be used for prompt and adaptive card could not be shown. So send them separatly
                    if (Channel.GetChannelId(sc.Context) == Channels.Msteams)
                    {
                        await sc.Context.SendActivityAsync(options.Prompt);

                        options.Prompt = null;
                    }

                    return(await sc.PromptAsync(Actions.SelectPointOfInterestPrompt, options));
                }

                state.ClearLuisResults();

                return(await sc.EndDialogAsync());
            }
            catch (Exception ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
Example #22
0
        public async Task <DialogTurnResult> AfterUpdateStartTime(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await _accessor.GetAsync(sc.Context);

                var events = new List <EventModel>();

                var calendarService = _serviceManager.InitCalendarService(state.APIToken, state.EventSource);

                if (state.OriginalStartDate != null || state.OriginalStartTime != null)
                {
                    events = await GetEventsByTime(state.OriginalStartDate, state.OriginalStartTime, state.OriginalEndDate, state.OriginalEndTime, state.GetUserTimeZone(), calendarService);

                    state.OriginalStartDate = null;
                    state.OriginalStartTime = null;
                    state.OriginalEndDate   = null;
                    state.OriginalStartTime = null;
                }
                else if (state.Title != null)
                {
                    events = await calendarService.GetEventsByTitle(state.Title);

                    state.Title = null;
                }
                else
                {
                    DateTime?startTime = null;
                    sc.Context.Activity.Properties.TryGetValue("OriginText", out var content);
                    var userInput = content != null?content.ToString() : sc.Context.Activity.Text;

                    try
                    {
                        IList <DateTimeResolution> dateTimeResolutions = sc.Result as List <DateTimeResolution>;
                        if (dateTimeResolutions.Count > 0)
                        {
                            startTime = DateTime.Parse(dateTimeResolutions.First().Value);
                            var  dateTimeConvertType = dateTimeResolutions.First().Timex;
                            bool isRelativeTime      = IsRelativeTime(sc.Context.Activity.Text, dateTimeResolutions.First().Value, dateTimeResolutions.First().Timex);
                            startTime = isRelativeTime ? TimeZoneInfo.ConvertTime(startTime.Value, TimeZoneInfo.Local, state.GetUserTimeZone()) : startTime;
                        }
                    }
                    catch
                    {
                    }

                    if (startTime != null)
                    {
                        startTime = DateTime.SpecifyKind(startTime.Value, DateTimeKind.Local);
                        events    = await calendarService.GetEventsByStartTime(startTime.Value);
                    }
                    else
                    {
                        state.Title = userInput;
                        events      = await calendarService.GetEventsByTitle(userInput);
                    }
                }

                state.Events = events;
                if (events.Count <= 0)
                {
                    return(await sc.BeginDialogAsync(Actions.UpdateStartTime, new UpdateDateTimeDialogOptions(UpdateDateTimeDialogOptions.UpdateReason.NoEvent)));
                }
                else if (events.Count > 1)
                {
                    var options = new PromptOptions()
                    {
                        Choices = new List <Choice>(),
                    };

                    for (var i = 0; i < events.Count; i++)
                    {
                        var item   = events[i];
                        var choice = new Choice()
                        {
                            Value    = string.Empty,
                            Synonyms = new List <string> {
                                (i + 1).ToString(), item.Title
                            },
                        };
                        options.Choices.Add(choice);
                    }

                    var replyToConversation = sc.Context.Activity.CreateReply(UpdateEventResponses.MultipleEventsStartAtSameTime);
                    replyToConversation.AttachmentLayout = AttachmentLayoutTypes.Carousel;
                    replyToConversation.Attachments      = new List <Microsoft.Bot.Schema.Attachment>();

                    var cardsData = new List <CalendarCardData>();
                    foreach (var item in events)
                    {
                        var meetingCard = item.ToAdaptiveCardData(state.GetUserTimeZone());
                        var replyTemp   = sc.Context.Activity.CreateAdaptiveCardReply(CalendarMainResponses.GreetingMessage, item.OnlineMeetingUrl == null ? "Dialogs/Shared/Resources/Cards/CalendarCardNoJoinButton.json" : "Dialogs/Shared/Resources/Cards/CalendarCard.json", meetingCard);
                        replyToConversation.Attachments.Add(replyTemp.Attachments[0]);
                    }

                    options.Prompt = replyToConversation;

                    return(await sc.PromptAsync(Actions.EventChoice, options));
                }
                else
                {
                    return(await sc.EndDialogAsync(true));
                }
            }
            catch
            {
                await sc.Context.SendActivityAsync(sc.Context.Activity.CreateReply(CalendarSharedResponses.CalendarErrorMessage, _responseBuilder));

                var state = await _accessor.GetAsync(sc.Context);

                state.Clear();
                return(await sc.CancelAllDialogsAsync());
            }
        }
        /// <summary>
        /// Top level processing, is the user trying to check or change a setting?.
        /// </summary>
        /// <param name="sc">Step Context.</param>
        /// <param name="cancellationToken">Cancellation Token.</param>
        /// <returns>Dialog Turn Result.</returns>
        public async Task <DialogTurnResult> ProcessSettingAsync(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await Accessor.GetAsync(sc.Context, () => new AutomotiveSkillState(), cancellationToken);

            var  skillResult   = sc.Context.TurnState.Get <SettingsLuis>(StateProperties.SettingsLuisResultKey);
            bool isDeclarative = skillResult?.TopIntent().intent == SettingsLuis.Intent.VEHICLE_SETTINGS_DECLARATIVE;

            // Perform post-processing on the entities, if it's declarative we indicate for special processing (opposite of the condition they've expressed)
            settingFilter.PostProcessSettingName(state, isDeclarative);

            // Perform content logic and remove entities that don't make sense
            settingFilter.ApplyContentLogic(state);

            var settingNames = state.GetUniqueSettingNames();

            if (!settingNames.Any())
            {
                // missing setting name
                await sc.Context.SendActivityAsync(TemplateManager.GenerateActivityForLocale(VehicleSettingsResponses.VehicleSettingsMissingSettingName), cancellationToken);

                return(await sc.EndDialogAsync(cancellationToken : cancellationToken));
            }
            else if (settingNames.Count() > 1)
            {
                // If we have more than one setting name matching prompt the user to choose
                var options = new PromptOptions()
                {
                    Choices = new List <Choice>(),
                };

                for (var i = 0; i < settingNames.Count; ++i)
                {
                    var item     = settingNames[i];
                    var synonyms = new List <string>
                    {
                        item,
                        (i + 1).ToString()
                    };
                    synonyms.AddRange(settingList.GetAlternativeNamesForSetting(item));
                    var choice = new Choice()
                    {
                        Value    = item,
                        Synonyms = synonyms,
                    };
                    options.Choices.Add(choice);
                }

                var cardModel = new AutomotiveCardModel()
                {
                    ImageUrl = GetSettingCardImageUri(FallbackSettingImageFileName)
                };

                var card = TemplateManager.GenerateActivityForLocale(GetDivergedCardName(sc.Context, "AutomotiveCard"), cardModel);
                options.Prompt             = TemplateManager.GenerateActivityForLocale(VehicleSettingsResponses.VehicleSettingsSettingNameSelection);
                options.Prompt.Attachments = card.Attachments;

                // Default Text property is clumsy for speech
                options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options);

                // Workaround. In teams, prompt will be changed to HeroCard and adaptive card could not be shown. So send them separatly
                if (Channel.GetChannelId(sc.Context) == Channels.Msteams)
                {
                    await sc.Context.SendActivityAsync(options.Prompt, cancellationToken);

                    options.Prompt = null;
                }

                return(await sc.PromptAsync(Actions.SettingNameSelectionPrompt, options, cancellationToken));
            }
            else
            {
                // Only one setting detected so move on to next stage
                return(await sc.NextAsync(cancellationToken : cancellationToken));
            }
        }
Example #24
0
        /// <summary>
        /// Look up points of interest, render cards, and ask user which to route to.
        /// </summary>
        /// <param name="sc">Step Context.</param>
        /// <param name="cancellationToken">Cancellation Token.</param>
        /// <returns>Dialog Turn Result.</returns>
        protected async Task <DialogTurnResult> GetPointOfInterestLocations(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context);

                var service            = ServiceManager.InitMapsService(Services, sc.Context.Activity.Locale);
                var addressMapsService = ServiceManager.InitAddressMapsService(Services, sc.Context.Activity.Locale);

                var pointOfInterestList = new List <PointOfInterestModel>();

                if (string.IsNullOrEmpty(state.Keyword) && string.IsNullOrEmpty(state.Address))
                {
                    // No entities identified, find nearby locations
                    pointOfInterestList = await service.GetNearbyPointOfInterestListAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude);

                    pointOfInterestList = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                }
                else if (!string.IsNullOrEmpty(state.Keyword) && !string.IsNullOrEmpty(state.Address))
                {
                    // Get first POI matched with address, if there are multiple this could be expanded to confirm which address to use
                    var pointOfInterestAddressList = await addressMapsService.GetPointOfInterestListByAddressAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Address);

                    if (pointOfInterestAddressList.Any())
                    {
                        var pointOfInterest = pointOfInterestAddressList[0];
                        pointOfInterestList = await service.GetPointOfInterestListByQueryAsync(pointOfInterest.Geolocation.Latitude, pointOfInterest.Geolocation.Longitude, state.Keyword);

                        pointOfInterestList = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                    }
                    else
                    {
                        // No POIs found from address - search near current coordinates
                        pointOfInterestList = await service.GetPointOfInterestListByQueryAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Keyword);

                        pointOfInterestList = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                    }
                }
                else if (!string.IsNullOrEmpty(state.Keyword))
                {
                    // Fuzzy query search with keyword
                    pointOfInterestList = await service.GetPointOfInterestListByQueryAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Keyword);

                    pointOfInterestList = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                }
                else if (!string.IsNullOrEmpty(state.Address))
                {
                    // Fuzzy query search with address
                    pointOfInterestList = await service.GetPointOfInterestListByAddressAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Address);

                    pointOfInterestList = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                }

                if (pointOfInterestList?.ToList().Count == 1)
                {
                    return(await sc.PromptAsync(Actions.ConfirmPrompt, new PromptOptions { Prompt = ResponseManager.GetResponse(POISharedResponses.PromptToGetRoute) }));
                }
                else
                {
                    PromptOptions options = GetPointOfInterestChoicePromptOptions(pointOfInterestList);

                    return(await sc.PromptAsync(Actions.SelectPointOfInterestPrompt, options));
                }
            }
            catch (Exception ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
        /// <summary>
        /// Called when a prompt dialog is pushed onto the dialog stack and is being activated.
        /// </summary>
        /// <param name="dc">The dialog context for the current turn of the conversation.</param>
        /// <param name="options">Optional, additional information to pass to the prompt being started.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        /// <remarks>If the task is successful, the result indicates whether the prompt is still
        /// active after the turn has been processed by the prompt.</remarks>
        public override async Task <DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (dc == null)
            {
                throw new ArgumentNullException(nameof(dc));
            }

            if (options is CancellationToken)
            {
                throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
            }

            if (Disabled != null && Disabled.GetValue(dc.State))
            {
                return(await dc.EndDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false));
            }

            PromptOptions opt = null;

            if (options != null)
            {
                if (options is PromptOptions)
                {
                    // Ensure prompts have input hint set
                    opt = options as PromptOptions;
                    if (opt.Prompt != null && string.IsNullOrEmpty(opt.Prompt.InputHint))
                    {
                        opt.Prompt.InputHint = InputHints.AcceptingInput;
                    }

                    if (opt.RetryPrompt != null && string.IsNullOrEmpty(opt.RetryPrompt.InputHint))
                    {
                        opt.RetryPrompt.InputHint = InputHints.AcceptingInput;
                    }
                }
            }

            var op = OnInitializeOptions(dc, options);

            dc.State.SetValue(ThisPath.Options, op);
            dc.State.SetValue(TURN_COUNT_PROPERTY, 0);

            // If AlwaysPrompt is set to true, then clear Property value for turn 0.
            if (this.Property != null && this.AlwaysPrompt != null && this.AlwaysPrompt.GetValue(dc.State))
            {
                dc.State.SetValue(this.Property.GetValue(dc.State), null);
            }

            // Initialize state
            var state = dc.ActiveDialog.State;

            state[PersistedOptions] = opt;
            state[PersistedState]   = new Dictionary <string, object>
            {
                { AttemptCountKey, 0 },
            };

            state[PersistedExpires] = DateTime.UtcNow.AddMilliseconds(Timeout.GetValue(dc.State));
            OAuthPrompt.SetCallerInfoInDialogState(state, dc.Context);

            // Attempt to get the users token
            var output = await GetUserTokenAsync(dc, cancellationToken).ConfigureAwait(false);

            if (output != null)
            {
                if (this.Property != null)
                {
                    dc.State.SetValue(this.Property.GetValue(dc.State), output);
                }

                // Return token
                return(await dc.EndDialogAsync(output, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                dc.State.SetValue(TURN_COUNT_PROPERTY, 1);

                // Prompt user to login
                await SendOAuthCardAsync(dc, opt?.Prompt, cancellationToken).ConfigureAwait(false);

                return(Dialog.EndOfTurn);
            }
        }
Example #26
0
        private async Task <PromptOptions> GenerateOptionsForName(WaterfallStepContext sc, List <CustomizedPerson> unionList, ITurnContext context, bool isSinglePage = true)
        {
            var state = await Accessor.GetAsync(context);

            var pageIndex            = state.ShowAttendeesIndex;
            var pageSize             = 3;
            var skip                 = pageSize * pageIndex;
            var currentRecipientName = state.CurrentAttendeeName;

            // Go back to the last page when reaching the end.
            if (skip >= unionList.Count && pageIndex > 0)
            {
                state.ShowAttendeesIndex--;
                pageIndex = state.ShowAttendeesIndex;
                skip      = pageSize * pageIndex;
                await sc.Context.SendActivityAsync(ResponseManager.GetResponse(FindContactResponses.AlreadyLastPage));
            }

            var options = new PromptOptions
            {
                Choices = new List <Choice>(),
                Prompt  = ResponseManager.GetResponse(FindContactResponses.ConfirmMultipleContactNameSinglePage, new StringDictionary()
                {
                    { "UserName", currentRecipientName }
                })
            };

            if (!isSinglePage)
            {
                options.Prompt = ResponseManager.GetResponse(FindContactResponses.ConfirmMultipleContactNameMultiPage, new StringDictionary()
                {
                    { "UserName", currentRecipientName }
                });
            }

            for (var i = 0; i < unionList.Count; i++)
            {
                var user = unionList[i];

                var choice = new Choice()
                {
                    Value    = $"**{user.DisplayName}**",
                    Synonyms = new List <string> {
                        (options.Choices.Count + 1).ToString(), user.DisplayName, user.DisplayName.ToLower()
                    },
                };
                var userName = user.UserPrincipalName?.Split("@").FirstOrDefault() ?? user.UserPrincipalName;
                if (!string.IsNullOrEmpty(userName))
                {
                    choice.Synonyms.Add(userName);
                    choice.Synonyms.Add(userName.ToLower());
                }

                if (skip <= 0)
                {
                    if (options.Choices.Count >= pageSize)
                    {
                        options.Prompt.Speak = SpeakHelper.ToSpeechSelectionDetailString(options, Common.ConfigData.GetInstance().MaxDisplaySize);
                        options.Prompt.Text  = GetSelectPromptString(options, true);
                        options.RetryPrompt  = ResponseManager.GetResponse(CalendarSharedResponses.DidntUnderstandMessage);
                        return(options);
                    }

                    options.Choices.Add(choice);
                }
                else
                {
                    skip--;
                }
            }

            options.Prompt.Speak = SpeakHelper.ToSpeechSelectionDetailString(options, Common.ConfigData.GetInstance().MaxDisplaySize);
            options.Prompt.Text  = GetSelectPromptString(options, true);
            options.RetryPrompt  = ResponseManager.GetResponse(CalendarSharedResponses.DidntUnderstandMessage);
            return(options);
        }
Example #27
0
        protected override async Task <PromptRecognizerResult <IList <EventModel> > > OnRecognizeAsync(ITurnContext turnContext, IDictionary <string, object> state, PromptOptions options, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            var result = new PromptRecognizerResult <IList <EventModel> >();

            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                var message = turnContext.Activity.AsMessageActivity();
                var culture = turnContext.Activity.Locale ?? DefaultLocale ?? English;
                var date    = GetTimeFromMessage(message.Text, culture);
                if (date.Count > 0)
                {
                    // input is a time
                    var results = await GetEventsWithStartTime(date, message.Text);

                    if (results.Count > 0)
                    {
                        result.Succeeded = true;
                        result.Value     = results;
                    }
                }

                if (!result.Succeeded)
                {
                    var results = await GetEventsWithTitle(message.Text);

                    if (results.Count > 0)
                    {
                        result.Succeeded = true;
                        result.Value     = results;
                    }
                }
            }

            return(await Task.FromResult(result));
        }
Example #28
0
 public Prompt(PromptOptions <U> promptOptions)
 {
     SetField.NotNull(out this.promptOptions, nameof(promptOptions), promptOptions);
 }
Example #29
0
        protected override async Task OnPromptAsync(ITurnContext turnContext, IDictionary <string, object> state, PromptOptions options, bool isRetry, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext == null)
            {
                throw new ArgumentNullException(nameof(turnContext));
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            if (isRetry && options.RetryPrompt != null)
            {
                await turnContext.SendActivityAsync(options.RetryPrompt, cancellationToken).ConfigureAwait(false);
            }
            else if (options.Prompt != null)
            {
                await turnContext.SendActivityAsync(options.Prompt, cancellationToken).ConfigureAwait(false);
            }
        }
        /// <summary>
        /// Prompt for Restaurant to book.
        /// </summary>
        /// <param name="sc">Waterfall Step Context.</param>
        /// <param name="cancellationToken">Cancellation Token.</param>
        /// <returns>Dialog Turn Result.</returns>
        private async Task <DialogTurnResult> AskForRestaurant(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            var state = await ConversationStateAccessor.GetAsync(sc.Context);

            var reservation = state.Booking;

            // Reset the dialog if the user hasn't confirmed the reservation.
            if (!reservation.Confirmed)
            {
                state.Booking = CreateNewReservationInfo();
                return(await sc.EndDialogAsync());
            }

            // Prompt for restaurant
            var restaurants = SeedReservationSampleData.GetListOfRestaurants(reservation.Category, "London", _urlResolver);

            state.Restaurants = restaurants;

            var restaurantOptionsForSpeak = new StringBuilder();

            for (var i = 0; i < restaurants.Count; i++)
            {
                restaurantOptionsForSpeak.Append(restaurants[i].Name);
                restaurantOptionsForSpeak.Append(i == restaurants.Count - 2 ? $" {BotStrings.Or} " : ", ");
            }

            var tokens = new StringDictionary
            {
                { "RestaurantCount", restaurants.Count.ToString() },
                { "ServerUrl", _urlResolver.ServerUrl },
                { "RestaurantList", restaurantOptionsForSpeak.ToString() }
            };

            var cards   = new List <Card>();
            var options = new PromptOptions()
            {
                Choices = new List <Choice>(),
            };

            foreach (var restaurant in restaurants)
            {
                cards.Add(new Card(
                              GetDivergedCardName(sc.Context, "RestaurantChoiceCard"),
                              new RestaurantChoiceCardData
                {
                    ImageUrl         = restaurant.PictureUrl,
                    ImageSize        = AdaptiveImageSize.Stretch,
                    ImageAlign       = AdaptiveHorizontalAlignment.Stretch,
                    Name             = restaurant.Name,
                    Title            = restaurant.Name,
                    Location         = restaurant.Location,
                    SelectedItemData = restaurant.Name
                }));

                options.Choices.Add(new Choice(restaurant.Name));
            }

            var replyMessage = ResponseManager.GetCardResponse(RestaurantBookingSharedResponses.BookRestaurantRestaurantSelectionPrompt, cards, tokens);

            return(await sc.PromptAsync(Actions.RestaurantPrompt, new PromptOptions { Prompt = replyMessage, Choices = options.Choices }, cancellationToken));
        }