private async Task <DialogTurnResult> CheckEntities(WaterfallStepContext sc, CancellationToken cancellationToken) { var userState = await UserStateAccessor.GetAsync(sc.Context, () => new HospitalityUserSkillState(HotelService)); var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState()); var entities = convState.LuisResult.Entities; convState.UpdatedReservation = userState.UserReservation.Copy(); // check for valid datetime entity if (entities.datetime != null && (entities.datetime[0].Type == "date" || entities.datetime[0].Type == "datetime" || entities.datetime[0].Type == "daterange") && await DateValidation(sc.Context, entities.datetime[0].Expressions)) { return(await sc.NextAsync()); } // check for valid number composite entity if (entities.NumNights?[0].HotelNights != null && entities.NumNights?[0].number[0] != null && await NumValidation(sc.Context, entities.NumNights[0].number[0])) { return(await sc.NextAsync()); } // need clarification on input else if (entities.datetime == null && entities.number != null) { convState.NumberEntity = entities.number[0]; var tokens = new StringDictionary { { "Number", convState.NumberEntity.ToString() } }; return(await sc.PromptAsync(DialogIds.CheckNumNights, new PromptOptions() { Prompt = ResponseManager.GetResponse(ExtendStayResponses.ConfirmAddNights, tokens) })); } // trying to request late check out time else if (entities.datetime != null && (entities.datetime[0].Type == "time" || entities.datetime[0].Type == "timerange")) { return(await sc.ReplaceDialogAsync(nameof(LateCheckOutDialog))); } return(await sc.NextAsync()); }
protected async Task <DialogTurnResult> InputState(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState()); if (!(bool)sc.Result || state.TicketState == TicketState.None) { var options = new PromptOptions() { Prompt = ResponseManager.GetResponse(SharedResponses.InputState), Choices = new List <Choice>() { new Choice() { Value = TicketState.New.ToLocalizedString() }, new Choice() { Value = TicketState.InProgress.ToLocalizedString() }, new Choice() { Value = TicketState.OnHold.ToLocalizedString() }, new Choice() { Value = TicketState.Resolved.ToLocalizedString() }, new Choice() { Value = TicketState.Closed.ToLocalizedString() }, new Choice() { Value = TicketState.Canceled.ToLocalizedString() } } }; return(await sc.PromptAsync(nameof(ChoicePrompt), options)); } else { // use Index to skip localization return(await sc.NextAsync(new FoundChoice() { Index = (int)state.TicketState - 1 })); } }
private async Task <bool> DateValidation(ITurnContext turnContext, IReadOnlyList <string> dates) { var convState = await StateAccessor.GetAsync(turnContext, () => new HospitalitySkillState()); var userState = await UserStateAccessor.GetAsync(turnContext, () => new HospitalityUserSkillState(HotelService)); DateTime dateObject = new DateTime(); bool dateIsEarly = false; string[] formats = { "XXXX-MM-dd", "yyyy-MM-dd" }; foreach (var date in dates) { // try parse exact date format so it won't accept time inputs if (DateTime.TryParseExact(date, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateObject)) { if (dateObject > DateTime.Now && dateObject > DateTime.Parse(userState.UserReservation.CheckOutDate)) { // get first future date that is formatted correctly convState.UpdatedReservation.CheckOutDate = dateObject.ToString(ReservationData.DateFormat); return(await Task.FromResult(true)); } else { dateIsEarly = true; } } } // found correctly formatted date, but date is not after current check-out date if (dateIsEarly) { // same date as current check-out date if (dateObject.ToString(ReservationData.DateFormat) == userState.UserReservation.CheckOutDate) { await turnContext.SendActivityAsync(ResponseManager.GetResponse(ExtendStayResponses.SameDayRequested)); } else { var tokens = new StringDictionary { { "Date", userState.UserReservation.CheckOutDate } }; await turnContext.SendActivityAsync(ResponseManager.GetResponse(ExtendStayResponses.NotFutureDateError, tokens)); } } return(await Task.FromResult(false)); }
private async Task <bool> SettingValueSelectionValidator(PromptValidatorContext <FoundChoice> promptContext, CancellationToken cancellationToken) { var state = await StateAccessor.GetAsync(promptContext.Context, cancellationToken : cancellationToken); // Use the value selection LUIS model to perform validation of the users entered setting value var skillResult = promptContext.Context.TurnState.Get <MusicSkillLuis>(StateProperties.MusicLuisResultKey); if (skillResult.Entities.VolumeDirection != null && skillResult.Entities.VolumeDirection.Length > 0) { state.VolumeDirection = skillResult.Entities.VolumeDirection[0][0]; return(true); } return(false); }
private async Task <bool> ValidateFoodOrder(PromptValidatorContext <string> promptContext, CancellationToken cancellationToken) { var convState = await StateAccessor.GetAsync(promptContext.Context, () => new HospitalitySkillState()); var entities = convState.LuisResult.Entities; if (promptContext.Recognized.Succeeded && (entities.FoodRequest != null || !string.IsNullOrWhiteSpace(entities.Food?[0]))) { await GetFoodEntities(promptContext.Context); return(await Task.FromResult(true)); } return(await Task.FromResult(false)); }
/// <summary> /// Check if geography is stored in state and route to prompt or go to API call. /// </summary> private async Task <DialogTurnResult> RouteToGeographyPromptOrForecastResponseAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { var state = await StateAccessor.GetAsync(stepContext.Context, cancellationToken : cancellationToken); var geography = state.Geography; if (string.IsNullOrEmpty(geography) && double.IsNaN(state.Latitude)) { return(await stepContext.NextAsync(cancellationToken : cancellationToken)); } else { return(await stepContext.ReplaceDialogAsync(DialogIds.GetForecastResponseDialog, cancellationToken : cancellationToken)); } }
protected async Task <DialogTurnResult> AfterIfCreateTicketAsync(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { if ((bool)sc.Result) { var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState(), cancellationToken); state.DisplayExisting = false; // note that it replaces the active WaterfallDialog instead of ShowKnowledgeDialog return(await sc.ReplaceDialogAsync(nameof(CreateTicketDialog), cancellationToken : cancellationToken)); } else { return(await sc.EndDialogAsync(cancellationToken : cancellationToken)); } }
// Helpers protected async Task GetLuisResult(DialogContext dc) { if (dc.Context.Activity.Type == ActivityTypes.Message) { var state = await StateAccessor.GetAsync(dc.Context, () => new SkillState()); // Get luis service for current locale var localeConfig = Services.GetCognitiveModels(); var luisService = localeConfig.LuisServices["BingSearchSkill"]; // Get intent and entities for activity var result = await luisService.RecognizeAsync <BingSearchSkillLuis>(dc.Context, CancellationToken.None); state.LuisResult = result; } }
private async Task <DialogTurnResult> ConfirmExtentionPrompt(WaterfallStepContext sc, CancellationToken cancellationToken) { var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState()); var tokens = new StringDictionary { { "Date", convState.UpdatedReservation.CheckOutDate } }; // confirm reservation extension with user return(await sc.PromptAsync(DialogIds.ConfirmExtendStay, new PromptOptions() { Prompt = ResponseManager.GetResponse(ExtendStayResponses.ConfirmExtendStay, tokens), RetryPrompt = ResponseManager.GetResponse(ExtendStayResponses.RetryConfirmExtendStay, tokens) })); }
private async Task <bool> ValidateAddItemsAsync(PromptValidatorContext <string> promptContext, CancellationToken cancellationToken) { var convState = await StateAccessor.GetAsync(promptContext.Context, () => new HospitalitySkillState(), cancellationToken); var entities = convState.LuisResult?.Entities; if (promptContext.Recognized.Succeeded && (entities?.FoodRequest != null || !string.IsNullOrWhiteSpace(entities?.Food?[0]))) { // added an item await GetFoodEntitiesAsync(promptContext.Context, cancellationToken); await ShowFoodOrderAsync(promptContext.Context, cancellationToken); } // only asks once return(await Task.FromResult(true)); }
protected async Task <DialogTurnResult> UpdateSelectedAttribute(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState()); var attribute = state.AttributeType; state.AttributeType = AttributeType.None; if (attribute == AttributeType.Description) { state.TicketDescription = null; return(await sc.BeginDialogAsync(Actions.SetDescription)); } else if (attribute == AttributeType.Title) { state.TicketTitle = null; return(await sc.BeginDialogAsync(Actions.SetTitle)); } else if (attribute == AttributeType.Search) { state.TicketTitle = null; return(await sc.BeginDialogAsync(Actions.SetSearch)); } else if (attribute == AttributeType.Urgency) { state.UrgencyLevel = UrgencyLevel.None; return(await sc.BeginDialogAsync(Actions.SetUrgency)); } else if (attribute == AttributeType.Id) { state.Id = null; return(await sc.BeginDialogAsync(Actions.SetId)); } else if (attribute == AttributeType.State) { state.TicketState = TicketState.None; return(await sc.BeginDialogAsync(Actions.SetState)); } else if (attribute == AttributeType.Number) { state.TicketNumber = null; return(await sc.BeginDialogAsync(Actions.SetNumber)); } else { throw new Exception($"Invalid AttributeType: {attribute}"); } }
protected async Task <DialogTurnResult> ShowConstraints(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState()); // always prompt for search state.AttributeType = AttributeType.None; var sb = new StringBuilder(); if (!string.IsNullOrEmpty(state.TicketNumber)) { sb.AppendLine(string.Format(SharedStrings.TicketNumber, state.TicketNumber)); } if (!string.IsNullOrEmpty(state.TicketTitle)) { sb.AppendLine(string.Format(SharedStrings.Search, state.TicketTitle)); } if (state.UrgencyLevel != UrgencyLevel.None) { sb.AppendLine(string.Format(SharedStrings.Urgency, state.UrgencyLevel.ToLocalizedString())); } if (state.TicketState != TicketState.None) { sb.AppendLine(string.Format(SharedStrings.TicketState, state.TicketState.ToLocalizedString())); } if (sb.Length == 0) { // await sc.Context.SendActivityAsync(ResponseManager.GetResponse(TicketResponses.ShowConstraintNone)); } else { var token = new StringDictionary() { { "Attributes", sb.ToString() } }; await sc.Context.SendActivityAsync(ResponseManager.GetResponse(TicketResponses.ShowConstraints, token)); } state.PageIndex = -1; return(await sc.ReplaceDialogAsync(Actions.ShowTicketLoop)); }
// Helpers protected async Task GetLuisResult(DialogContext dc) { if (dc.Context.Activity.Type == ActivityTypes.Message) { var state = await StateAccessor.GetAsync(dc.Context, () => new SkillState()); // Get luis service for current locale var locale = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName; var localeConfig = Services.CognitiveModelSets[locale]; var luisService = localeConfig.LuisServices["TestBot"]; // Get intent and entities for activity var result = await luisService.RecognizeAsync <TestBotLuis>(dc.Context, CancellationToken.None); state.LuisResult = result; } }
protected async Task <DialogTurnResult> AfterIfCreateTicket(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { if ((bool)sc.Result) { var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState()); state.DisplayExisting = false; return(await sc.ReplaceDialogAsync(nameof(CreateTicketDialog))); } else { await sc.Context.SendActivityAsync(ResponseManager.GetResponse(SharedResponses.ActionEnded)); return(await sc.CancelAllDialogsAsync()); } }
protected async Task <DialogTurnResult> CreateTicketAsync(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState(), cancellationToken); var management = ServiceManager.CreateManagement(Settings, sc.Result as TokenResponse, state.ServiceCache); var result = await management.CreateTicket(state.TicketTitle, state.TicketDescription, state.UrgencyLevel); if (!result.Success) { return(await SendServiceErrorAndCancelAsync(sc, result, cancellationToken)); } var card = GetTicketCard(sc.Context, state, result.Tickets[0]); await sc.Context.SendActivityAsync(TemplateManager.GenerateActivity(TicketResponses.TicketCreated, card, null), cancellationToken); return(await sc.EndDialogAsync(await CreateActionResultAsync(sc.Context, true, cancellationToken), cancellationToken)); }
private async Task <bool> NumValidation(ITurnContext turnContext, double extraNights) { var userState = await UserStateAccessor.GetAsync(turnContext, () => new HospitalityUserSkillState()); var convState = await StateAccessor.GetAsync(turnContext, () => new HospitalitySkillState()); if (extraNights >= 1) { // add entity number to the current check out date DateTime currentDate = DateTime.Parse(userState.UserReservation.CheckOutDate); convState.UpdatedReservation.CheckOutDate = currentDate.AddDays(extraNights).ToString("MMMM d, yyyy"); return(await Task.FromResult(true)); } await turnContext.SendActivityAsync(ResponseManager.GetResponse(ExtendStayResponses.NumberEntityError)); return(await Task.FromResult(false)); }
protected async Task <DialogTurnResult> CloseTicket(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState()); var management = ServiceManager.CreateManagement(Settings, sc.Result as TokenResponse); var result = await management.CloseTicket(id : state.Id, reason : state.CloseReason); if (!result.Success) { return(await SendServiceErrorAndCancel(sc, result)); } var card = GetTicketCard(sc.Context, result.Tickets[0]); await sc.Context.SendActivityAsync(ResponseManager.GetCardResponse(TicketResponses.TicketClosed, card, null)); return(await sc.NextAsync()); }
protected async Task <DialogTurnResult> InputTicketNumber(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState()); if (string.IsNullOrEmpty(state.TicketNumber)) { var options = new PromptOptions() { Prompt = ResponseManager.GetResponse(SharedResponses.InputTicketNumber) }; return(await sc.PromptAsync(nameof(TicketNumberPrompt), options)); } else { return(await sc.NextAsync(state.TicketNumber)); } }
private async Task <bool> NumValidationAsync(ITurnContext turnContext, double extraNights, CancellationToken cancellationToken) { var userState = await UserStateAccessor.GetAsync(turnContext, () => new HospitalityUserSkillState(HotelService), cancellationToken); var convState = await StateAccessor.GetAsync(turnContext, () => new HospitalitySkillState(), cancellationToken); if (extraNights >= 1) { // add entity number to the current check out date DateTime currentDate = DateTime.Parse(userState.UserReservation.CheckOutDate); convState.UpdatedReservation.CheckOutDate = currentDate.AddDays(extraNights).ToString(ReservationData.DateFormat); return(await Task.FromResult(true)); } await turnContext.SendActivityAsync(TemplateManager.GenerateActivity(ExtendStayResponses.NumberEntityError), cancellationToken); return(await Task.FromResult(false)); }
protected async Task <DialogTurnResult> InputAttribute(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState()); if (!(bool)sc.Result || state.AttributeType == AttributeType.None) { var options = new PromptOptions() { Prompt = ResponseManager.GetResponse(InputAttributeResponse) }; return(await sc.PromptAsync(InputAttributePrompt, options)); } else { return(await sc.NextAsync(state.AttributeType)); } }
protected async Task <DialogTurnResult> IfContinueShow(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState()); if (state.InterruptedIntent == ITSMLuis.Intent.TicketClose) { return(await sc.ReplaceDialogAsync(nameof(CloseTicketDialog))); } else if (state.InterruptedIntent == ITSMLuis.Intent.TicketUpdate) { return(await sc.ReplaceDialogAsync(nameof(UpdateTicketDialog))); } else if (state.InterruptedIntent != ITSMLuis.Intent.None) { throw new Exception($"Invalid InterruptedIntent {state.InterruptedIntent}"); } var intent = (GeneralLuis.Intent)sc.Result; if (intent == GeneralLuis.Intent.Reject) { await sc.Context.SendActivityAsync(ResponseManager.GetResponse(SharedResponses.ActionEnded)); return(await sc.CancelAllDialogsAsync()); } else if (intent == GeneralLuis.Intent.Confirm) { return(await sc.ReplaceDialogAsync(Actions.ShowAttribute)); } else if (intent == GeneralLuis.Intent.ShowNext) { state.PageIndex += 1; return(await sc.ReplaceDialogAsync(Actions.ShowTicketLoop)); } else if (intent == GeneralLuis.Intent.ShowPrevious) { state.PageIndex = Math.Max(0, state.PageIndex - 1); return(await sc.ReplaceDialogAsync(Actions.ShowTicketLoop)); } else { throw new Exception($"Invalid GeneralLuis.Intent {intent}"); } }
private async Task <DialogTurnResult> MenuPrompt(WaterfallStepContext sc, CancellationToken cancellationToken) { var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState()); convState.FoodList = new List <FoodRequestClass>(); await GetFoodEntities(sc.Context); var menu = convState.LuisResult.Entities.Menu; // didn't order, prompt if 1 menu type not identified if (convState.FoodList.Count == 0 && string.IsNullOrWhiteSpace(menu?[0][0]) && menu?.Length != 1) { var prompt = ResponseManager.GetResponse(RoomServiceResponses.MenuPrompt); var actions = new List <CardAction>() { new CardAction(type: ActionTypes.ImBack, title: "Breakfast", value: "Breakfast menu"), new CardAction(type: ActionTypes.ImBack, title: "Lunch", value: "Lunch menu"), new CardAction(type: ActionTypes.ImBack, title: "Dinner", value: "Dinner menu"), new CardAction(type: ActionTypes.ImBack, title: "24 Hour", value: "24 hour menu") }; // create hero card instead when channel does not support suggested actions if (!Channel.SupportsSuggestedActions(sc.Context.Activity.ChannelId)) { var hero = new HeroCard(buttons: actions); prompt.Attachments.Add(hero.ToAttachment()); } else { prompt.SuggestedActions = new SuggestedActions { Actions = actions }; } return(await sc.PromptAsync(DialogIds.MenuPrompt, new PromptOptions() { Prompt = prompt, RetryPrompt = ResponseManager.GetResponse(RoomServiceResponses.ChooseOneMenu) })); } return(await sc.NextAsync()); }
// This method is called by any waterfall step that throws an exception to ensure consistency protected async Task HandleDialogExceptions(WaterfallStepContext sc, Exception ex) { // send trace back to emulator var trace = new Activity(type: ActivityTypes.Trace, text: $"DialogException: {ex.Message}, StackTrace: {ex.StackTrace}"); await sc.Context.SendActivityAsync(trace); // log exception TelemetryClient.TrackException(ex, new Dictionary <string, string> { { nameof(sc.ActiveDialog), sc.ActiveDialog?.Id } }); // send error message to bot user await sc.Context.SendActivityAsync(ResponseManager.GetResponse(SharedResponses.ErrorMessage)); // clear state var state = await StateAccessor.GetAsync(sc.Context); state.Clear(); }
private async Task <DialogTurnResult> ExtendDatePrompt(WaterfallStepContext sc, CancellationToken cancellationToken) { var userState = await UserStateAccessor.GetAsync(sc.Context, () => new HospitalityUserSkillState()); var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState()); // if new date hasnt been set yet if (userState.UserReservation.CheckOutDate == convState.UpdatedReservation.CheckOutDate) { // get extended reservation date return(await sc.PromptAsync(DialogIds.ExtendDatePrompt, new PromptOptions() { Prompt = ResponseManager.GetResponse(ExtendStayResponses.ExtendDatePrompt), RetryPrompt = ResponseManager.GetResponse(ExtendStayResponses.RetryExtendDate) })); } return(await sc.NextAsync()); }
protected async Task <DialogTurnResult> IfContinueShowAsync(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState(), cancellationToken); // Skip in Action mode in ShowNavigateValidator if (state.InterruptedIntent == ITSMLuis.Intent.TicketClose) { return(await sc.ReplaceDialogAsync(nameof(CloseTicketDialog), cancellationToken : cancellationToken)); } else if (state.InterruptedIntent == ITSMLuis.Intent.TicketUpdate) { return(await sc.ReplaceDialogAsync(nameof(UpdateTicketDialog), cancellationToken : cancellationToken)); } else if (state.InterruptedIntent != ITSMLuis.Intent.None) { throw new Exception($"Invalid InterruptedIntent {state.InterruptedIntent}"); } var intent = (GeneralLuis.Intent)sc.Result; if (intent == GeneralLuis.Intent.Reject) { return(await sc.EndDialogAsync(await CreateActionResultAsync(sc.Context, true, cancellationToken), cancellationToken)); } else if (intent == GeneralLuis.Intent.Confirm) { return(await sc.ReplaceDialogAsync(Actions.ShowAttribute, cancellationToken : cancellationToken)); } else if (intent == GeneralLuis.Intent.ShowNext) { state.PageIndex += 1; return(await sc.ReplaceDialogAsync(Actions.ShowTicketLoop, cancellationToken : cancellationToken)); } else if (intent == GeneralLuis.Intent.ShowPrevious) { state.PageIndex = Math.Max(0, state.PageIndex - 1); return(await sc.ReplaceDialogAsync(Actions.ShowTicketLoop, cancellationToken : cancellationToken)); } else { throw new Exception($"Invalid GeneralLuis.Intent {intent}"); } }
// This method is called by any waterfall step that throws an exception to ensure consistency protected async Task HandleDialogExceptionsAsync(WaterfallStepContext sc, Exception ex, CancellationToken cancellationToken) { // send trace back to emulator var trace = new Activity(type: ActivityTypes.Trace, text: $"DialogException: {ex.Message}, StackTrace: {ex.StackTrace}"); await sc.Context.SendActivityAsync(trace, cancellationToken); // log exception TelemetryClient.TrackException(ex, new Dictionary <string, string> { { nameof(sc.ActiveDialog), sc.ActiveDialog?.Id } }); // send error message to bot user await sc.Context.SendActivityAsync(TemplateEngine.GenerateActivityForLocale("ErrorMessage"), cancellationToken); // clear state var state = await StateAccessor.GetAsync(sc.Context, cancellationToken : cancellationToken); state.Clear(); }
private async Task <DialogTurnResult> ItemPrompt(WaterfallStepContext sc, CancellationToken cancellationToken) { var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState()); convState.ItemList = new List <ItemRequestClass>(); await GetEntities(sc.Context); if (convState.ItemList.Count == 0) { // prompt for item return(await sc.PromptAsync(DialogIds.ItemPrompt, new PromptOptions() { Prompt = ResponseManager.GetResponse(RequestItemResponses.ItemPrompt), RetryPrompt = ResponseManager.GetResponse(RequestItemResponses.RetryItemPrompt) })); } return(await sc.NextAsync()); }
protected async Task <DialogTurnResult> CloseTicketAsync(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { var state = await StateAccessor.GetAsync(sc.Context, () => new SkillState(), cancellationToken); var management = ServiceManager.CreateManagement(Settings, sc.Result as TokenResponse, state.ServiceCache); var result = await management.CloseTicket(id : state.Id, reason : state.CloseReason); if (!result.Success) { // Check if Error is UnAuthorized and logout user return(await HandleAPIUnauthorizedError(sc, result, cancellationToken)); } var card = GetTicketCard(sc.Context, state, result.Tickets[0]); await sc.Context.SendActivityAsync(TemplateManager.GenerateActivity(TicketResponses.TicketClosed, card, null), cancellationToken); return(await sc.NextAsync(await CreateActionResultAsync(sc.Context, true, cancellationToken), cancellationToken)); }
private async Task <DialogTurnResult> ItemRequest(WaterfallStepContext sc, CancellationToken cancellationToken) { var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState()); // check json, if item is available List <ItemRequestClass> notAvailable = new List <ItemRequestClass>(); foreach (var itemRequest in convState.ItemList.ToList()) { var roomItem = _hotelService.CheckRoomItemAvailability(itemRequest.Item[0]); if (roomItem == null) { // specific item is not available notAvailable.Add(itemRequest); convState.ItemList.Remove(itemRequest); } else { itemRequest.Item[0] = roomItem.Item; } } if (notAvailable.Count > 0) { var reply = ResponseManager.GetResponse(RequestItemResponses.ItemNotAvailable).Text; foreach (var itemRequest in notAvailable) { reply += Environment.NewLine + "- " + itemRequest.Item[0]; } await sc.Context.SendActivityAsync(reply); return(await sc.PromptAsync(DialogIds.GuestServicesPrompt, new PromptOptions() { Prompt = ResponseManager.GetResponse(RequestItemResponses.GuestServicesPrompt), RetryPrompt = ResponseManager.GetResponse(RequestItemResponses.RetryGuestServicesPrompt) })); } return(await sc.NextAsync()); }
private async Task <DialogTurnResult> EndDialogAsync(WaterfallStepContext sc, CancellationToken cancellationToken) { var convState = await StateAccessor.GetAsync(sc.Context, () => new HospitalitySkillState(), cancellationToken); var result = convState.IsAction ? new ActionResult(false) : null; if (result != null && sc.Result is bool && (bool)sc.Result) { result.ActionSuccess = true; } if (convState.ItemList.Count > 0) { List <Card> roomItems = new List <Card>(); foreach (var itemRequest in convState.ItemList) { var roomItem = new RoomItem { Item = itemRequest.Item[0], Quantity = itemRequest.number == null ? 1 : (int)itemRequest.number[0] }; roomItems.Add(new Card(GetCardName(sc.Context, "RoomItemCard"), roomItem)); } await HotelService.RequestItems(convState.ItemList); // if at least one item was available send this card reply await sc.Context.SendActivityAsync(TemplateManager.GenerateActivity(null, new Card(GetCardName(sc.Context, "RequestItemCard")), null, "items", roomItems), cancellationToken); await sc.Context.SendActivityAsync(TemplateManager.GenerateActivity(RequestItemResponses.ItemsRequested), cancellationToken); if (result != null) { result.ActionSuccess = true; } } return(await sc.EndDialogAsync(result, cancellationToken)); }