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)); }
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); } }
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)); }
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)); } }
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); }
/// <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)); } }
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)); }
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)); }
/// <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)); } }
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)); }
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)); } }
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)); } }
/// <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); } }
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); }
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)); }
public Prompt(PromptOptions <U> promptOptions) { SetField.NotNull(out this.promptOptions, nameof(promptOptions), promptOptions); }
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)); }