private async Task <DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { return(await stepContext.EndDialogAsync(null, cancellationToken)); }
private async Task <DialogTurnResult> SignInStepAsync(WaterfallStepContext context, CancellationToken cancellationToken) { // This prompt won't show if the user is signed in to the root using SSO. return(await context.BeginDialogAsync(nameof(OAuthPrompt), null, cancellationToken)); }
/// <summary> /// Prompts the user for intput by sending a <see cref="ChoicePrompt"/> so the user may select their /// choice from a list of options. /// </summary> /// <param name="step">A <see cref="WaterfallStepContext"/> provides context for the current waterfall step.</param> /// <param name="cancellationToken" >(Optional) A <see cref="CancellationToken"/> that can be used by other objects /// or threads to receive notice of cancellation.</param> /// <returns>A <see cref="DialogTurnResult"/> to communicate some flow control back to the containing WaterfallDialog.</returns> private static async Task <DialogTurnResult> ChoiceCardStepAsync(WaterfallStepContext step, CancellationToken cancellationToken) { return(await step.PromptAsync("cardPrompt", GenerateOptions(step.Context.Activity), cancellationToken)); }
private async Task <DialogTurnResult> PromptForSlotStepAsync(WaterfallStepContext step, CancellationToken cancellationToken) { var state = await _stateAccessor.GetAsync(step.Context, cancellationToken : cancellationToken); if (state.StartDate == null && step.Result is IList <DateTimeResolution> resolution) { var timex = new TimexProperty(resolution[0].Timex); state.Timex = timex; var hour = timex.Hour ?? 0; state.StartDate = new DateTime( timex.Year.Value, timex.Month.Value, timex.DayOfMonth.Value, hour, 0, 0); await _stateAccessor.SetAsync(step.Context, state, cancellationToken); } var reservationCapacity = new List <CarwashService.ReservationCapacity>(); try { var api = new CarwashService(step, _telemetryClient, cancellationToken); reservationCapacity = (List <CarwashService.ReservationCapacity>) await api.GetReservationCapacityAsync(state.StartDate.Value, cancellationToken); } catch (AuthenticationException) { await step.Context.SendActivityAsync(AuthDialog.NotAuthenticatedMessage, cancellationToken : cancellationToken); return(await step.ClearStateAndEndDialogAsync(_stateAccessor, cancellationToken : cancellationToken)); } catch (Exception e) { _telemetryClient.TrackException(e); await step.Context.SendActivityAsync(e.Message, cancellationToken : cancellationToken); return(await step.ClearStateAndEndDialogAsync(_stateAccessor, cancellationToken : cancellationToken)); } // Check whether we already know the slot. if (Slots.Any(s => s.StartTime == state.StartDate?.Hour)) { // Check if slot is available. if (!reservationCapacity.Any(c => c.StartTime == state.StartDate && c.FreeCapacity > 0)) { await step.Context.SendActivityAsync("Sorry, this slot is already full.", cancellationToken : cancellationToken); } else { return(await step.NextAsync(cancellationToken : cancellationToken)); } } else if (!string.IsNullOrEmpty(state.Timex?.PartOfDay)) { // Check whether we can find out the slot from timex. Slot slot = null; switch (state.Timex.PartOfDay) { case "MO": slot = Slots[0]; break; case "AF": slot = Slots[1]; break; case "EV": slot = Slots[2]; break; } if (slot != null) { state.StartDate = new DateTime( state.StartDate.Value.Year, state.StartDate.Value.Month, state.StartDate.Value.Day, slot.StartTime, 0, 0); await _stateAccessor.SetAsync(step.Context, state, cancellationToken); return(await step.NextAsync(cancellationToken : cancellationToken)); } } var choices = new List <Choice>(); state.SlotChoices = new List <DateTime>(); foreach (var slot in reservationCapacity) { if (slot.FreeCapacity < 1) { continue; } choices.Add(new Choice($"{slot.StartTime.ToNaturalLanguage()} ({slot.StartTime.Hour}-{Slots.Single(s => s.StartTime == slot.StartTime.Hour).EndTime})")); // Save recommendations to state state.SlotChoices.Add(slot.StartTime); } await _stateAccessor.SetAsync(step.Context, state, cancellationToken); return(await step.PromptAsync( SlotPromptName, new PromptOptions { Prompt = MessageFactory.Text("Please choose one of these slots:"), Choices = choices, }, cancellationToken)); }
private async Task <DialogTurnResult> DisplayReservationStepAsync(WaterfallStepContext step, CancellationToken cancellationToken) { var state = await _stateAccessor.GetAsync(step.Context, cancellationToken : cancellationToken); if (string.IsNullOrWhiteSpace(state.Comment) && step.Result is string comment && !new[] { "skip", "nope", "thanks, no", "no" }.Contains(comment.ToLower())) { state.Comment = comment; await _stateAccessor.SetAsync(step.Context, state, cancellationToken); } Reservation reservation = new Reservation { VehiclePlateNumber = state.VehiclePlateNumber, Services = state.Services, Private = state.Private, StartDate = state.StartDate.Value, Comment = state.Comment, }; try { var api = new CarwashService(step, _telemetryClient, cancellationToken); // Submit reservation reservation = await api.SubmitReservationAsync(reservation, cancellationToken); } catch (AuthenticationException) { await step.Context.SendActivityAsync(AuthDialog.NotAuthenticatedMessage, cancellationToken : cancellationToken); return(await step.ClearStateAndEndDialogAsync(_stateAccessor, cancellationToken : cancellationToken)); } catch (Exception e) { _telemetryClient.TrackException(e); await step.Context.SendActivityAsync(e.Message, cancellationToken : cancellationToken); return(await step.ClearStateAndEndDialogAsync(_stateAccessor, cancellationToken : cancellationToken)); } await step.Context.SendActivityAsync($"OK, I have reserved a car wash for {reservation.StartDate.ToNaturalLanguage()}.", cancellationToken : cancellationToken); await step.Context.SendActivityAsync("🚗", cancellationToken : cancellationToken); await step.Context.SendActivityAsync("Here is the current state of your reservation. I'll let you know when you will need to drop off the keys.", cancellationToken : cancellationToken); var response = step.Context.Activity.CreateReply(); response.Attachments = new ReservationCard(reservation).ToAttachmentList(); await step.Context.SendActivityAsync(response, cancellationToken).ConfigureAwait(false); _telemetryClient.TrackEvent( "New reservation from chat bot.", new Dictionary <string, string> { { "Reservation ID", reservation.Id }, }, new Dictionary <string, double> { { "New reservation", 1 }, }); return(await step.ClearStateAndEndDialogAsync(_stateAccessor, cancellationToken : cancellationToken)); }
private static async Task <DialogTurnResult> CheckValidUserAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) {//0 var username = (string)stepContext.Result; try { SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); builder.ConnectionString = "Server=tcp:team02-server.database.windows.net,1433;Initial Catalog=healtheeDB;Persist Security Info=False;User ID=chatbot02;Password=chatee17!;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"; using (SqlConnection connection = new SqlConnection(builder.ConnectionString)) { connection.Open(); StringBuilder sb = new StringBuilder(); sb.Append("SELECT COUNT(*) FROM [dbo].[UserInfo] WHERE UserName='******'"); //유저가 입력한 이름으로 DB에서 사용자 찾기 String sql = sb.ToString(); int count = 0; using (SqlCommand command = new SqlCommand(sql, connection)) { using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { count = reader.GetInt32(0); } } } sb = new StringBuilder(); sb.Append("SELECT COUNT(*) FROM [dbo].[UserInfo] "); sql = sb.ToString(); using (SqlCommand command = new SqlCommand(sql, connection)) { using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { PrimaryNumber = reader.GetInt32(0) + 1; } } } if (count == 0) //DB에 기록이 없을 때, tutorial Async 실행시켜야 함 { connection.Close(); ModeManager.mode = (int)ModeManager.Modes.Tutorial; return(await stepContext.BeginDialogAsync(nameof(TutorialDialog), null, cancellationToken)); } else //DB에 기록이 있으면 기능 보여주기로 넘어감 { sb = new StringBuilder(); sb.Append("SELECT * FROM [dbo].[UserInfo] WHERE UserName='******'"); sql = sb.ToString(); using (SqlCommand command = new SqlCommand(sql, connection)) { using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { UserInfoManager.keyNum = (int)reader.GetValue(0); UserInfoManager.UserName = (string)reader.GetValue(1); UserInfoManager.PreWeight = (int)reader.GetValue(2); UserInfoManager.PostWeight = (int)reader.GetValue(3); UserInfoManager.SkillLevel = (string)reader.GetValue(4); UserInfoManager.Area = (string)reader.GetValue(5); UserInfoManager.Category = (string)reader.GetValue(6); UserInfoManager.ConversationCount = (int)reader.GetValue(7); break; } } } connection.Close(); ModeManager.mode = (int)ModeManager.Modes.ShowFunction; return(await stepContext.BeginDialogAsync(nameof(ShowFunctionsDialog), null, cancellationToken)); } } } catch (SqlException e) { await stepContext.Context.SendActivityAsync(MessageFactory.Text("DB 연결에 문제가 있습니다."), cancellationToken); Console.WriteLine(e.ToString()); return(await stepContext.NextAsync()); } }
private async Task <DialogTurnResult> EndGameAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { return(await stepContext.EndDialogAsync("optional", cancellationToken)); }
private async Task <DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { // Restart the main dialog with a different message the second time around return(await stepContext.ReplaceDialogAsync(InitialDialogId, _templateEngine.GenerateActivityForLocale("CompletedMessage"), cancellationToken)); }
private async Task <DialogTurnResult> DisplayCardAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { if (stepContext.Context.Activity.Value != null) { await HandleSpecialActivity(stepContext, cancellationToken); } else { // Checks to see if the activity is an adaptive card update or a bot action respose var card = ((FoundChoice)stepContext.Result).Value.ToLowerInvariant(); var cardType = ParseEnum <CardOptions>(card); if (ChannelSupportedCards.IsCardSupported(stepContext.Context.Activity.ChannelId, cardType)) { switch (cardType) { case CardOptions.AdaptiveCardBotAction: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(MakeAdaptiveCard("botaction").ToAttachment()), cancellationToken); break; case CardOptions.AdaptiveCardTeamsTaskModule: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(MakeAdaptiveCard("taskmodule").ToAttachment()), cancellationToken); break; case CardOptions.AdaptiveCardSubmitAction: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(MakeAdaptiveCard("submitaction").ToAttachment()), cancellationToken); break; case CardOptions.Hero: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(CardSampleHelper.CreateHeroCard().ToAttachment()), cancellationToken).ConfigureAwait(false); break; case CardOptions.Thumbnail: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(CardSampleHelper.CreateThumbnailCard().ToAttachment()), cancellationToken).ConfigureAwait(false); break; case CardOptions.Receipt: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(CardSampleHelper.CreateReceiptCard().ToAttachment()), cancellationToken).ConfigureAwait(false); break; case CardOptions.Signin: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(CardSampleHelper.CreateSigninCard().ToAttachment()), cancellationToken).ConfigureAwait(false); break; case CardOptions.Carousel: // NOTE: if cards are NOT the same height in a carousel, Teams will instead display as AttachmentLayoutTypes.List await stepContext.Context.SendActivityAsync( MessageFactory.Carousel(new[] { CardSampleHelper.CreateHeroCard().ToAttachment(), CardSampleHelper.CreateHeroCard().ToAttachment(), CardSampleHelper.CreateHeroCard().ToAttachment() }), cancellationToken).ConfigureAwait(false); break; case CardOptions.List: // NOTE: MessageFactory.Attachment with multiple attachments will default to AttachmentLayoutTypes.List await stepContext.Context.SendActivityAsync( MessageFactory.Attachment(new[] { CardSampleHelper.CreateHeroCard().ToAttachment(), CardSampleHelper.CreateHeroCard().ToAttachment(), CardSampleHelper.CreateHeroCard().ToAttachment() }), cancellationToken).ConfigureAwait(false); break; case CardOptions.O365: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(MakeO365CardAttachmentAsync()), cancellationToken).ConfigureAwait(false); break; case CardOptions.TeamsFileConsent: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(MakeTeamsFileConsentCard()), cancellationToken); break; case CardOptions.Animation: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(MakeAnimationCard().ToAttachment()), cancellationToken); break; case CardOptions.Audio: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(MakeAudioCard().ToAttachment()), cancellationToken); break; case CardOptions.Video: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(MakeVideoCard().ToAttachment()), cancellationToken); break; case CardOptions.AdaptiveUpdate: await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(MakeUpdateAdaptiveCard().ToAttachment()), cancellationToken); break; case CardOptions.End: return(new DialogTurnResult(DialogTurnStatus.Complete)); } } else { await stepContext.Context.SendActivityAsync(MessageFactory.Text($"{cardType} cards are not supported in the {stepContext.Context.Activity.ChannelId} channel."), cancellationToken); } } return(await stepContext.ReplaceDialogAsync(InitialDialogId, "What card would you want?", 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(UpdateEventResponses.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)); } }
/// <summary> /// Defines the second step of the main dialog, which is to process the user's input, and /// repeat or exit as appropriate. /// </summary> /// <param name="stepContext">The current waterfall step context.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task to perform.</returns> private async Task <DialogTurnResult> ProcessInputAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { // Get the order cart from dialog state. Order order = stepContext.Values[OrderCartId] as Order; // Get the user's choice from the previous prompt. string response = (stepContext.Result as FoundChoice).Value; if (response.Equals("process order", StringComparison.InvariantCultureIgnoreCase)) { order.ReadyToProcess = true; await stepContext.Context.SendActivityAsync( "Your order is on it's way!", cancellationToken : cancellationToken); // In production, you may want to store something more helpful. // "Process" the order and exit. order.OrderProcessed = true; return(await stepContext.EndDialogAsync(null, cancellationToken)); } else if (response.Equals("cancel", StringComparison.InvariantCultureIgnoreCase)) { // Cancel the order. await stepContext.Context.SendActivityAsync( "Your order has been canceled", cancellationToken : cancellationToken); // Exit without processing the order. return(await stepContext.EndDialogAsync(null, cancellationToken)); } else if (response.Equals("more info", StringComparison.InvariantCultureIgnoreCase)) { // Send more information about the options. string message = "More info: <br/>" + "Potato Salad: contains 330 calories per serving. Cost: 5.99 <br/>" + "Tuna Sandwich: contains 700 calories per serving. Cost: 6.89 <br/>" + "Clam Chowder: contains 650 calories per serving. Cost: 4.50"; await stepContext.Context.SendActivityAsync( message, cancellationToken : cancellationToken); // Continue the ordering process, passing in the current order cart. return(await stepContext.ReplaceDialogAsync(MainDialogId, order, cancellationToken)); } else if (response.Equals("help", StringComparison.InvariantCultureIgnoreCase)) { // Provide help information. string message = "To make an order, add as many items to your cart as " + "you like. Choose the `Process order` to check out. " + "Choose `Cancel` to cancel your order and exit."; await stepContext.Context.SendActivityAsync( message, cancellationToken : cancellationToken); // Continue the ordering process, passing in the current order cart. return(await stepContext.ReplaceDialogAsync(MainDialogId, order, cancellationToken)); } // We've checked for expected interruptions. Check for a valid item choice. if (!DinnerMenu.MenuItems.ContainsKey(response)) { await stepContext.Context.SendActivityAsync("Sorry, that is not a valid item. " + "Please pick one from the menu."); // Continue the ordering process, passing in the current order cart. return(await stepContext.ReplaceDialogAsync(MainDialogId, order, cancellationToken)); } else { // Add the item to cart. DinnerItem item = DinnerMenu.MenuItems[response]; order.Items.Add(item); order.Total += item.Price; // Acknowledge the input. await stepContext.Context.SendActivityAsync( $"Added `{response}` to your order; your total is ${order.Total:0.00}.", cancellationToken : cancellationToken); // Continue the ordering process, passing in the current order cart. return(await stepContext.ReplaceDialogAsync(MainDialogId, order, cancellationToken)); } }
public async Task <DialogTurnResult> AfterGetNewEventTime(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken)) { try { var state = await Accessor.GetAsync(sc.Context); if (state.NewStartDate.Any() || state.NewStartTime.Any() || state.MoveTimeSpan != 0) { var originalEvent = state.Events[0]; var originalStartDateTime = TimeConverter.ConvertUtcToUserTime(originalEvent.StartTime, state.GetUserTimeZone()); var userNow = TimeConverter.ConvertUtcToUserTime(DateTime.UtcNow, state.GetUserTimeZone()); if (state.NewStartDate.Any() || state.NewStartTime.Any()) { var newStartDate = state.NewStartDate.Any() ? state.NewStartDate.Last() : originalStartDateTime; var newStartTime = new List <DateTime>(); if (state.NewStartTime.Any()) { foreach (var time in state.NewStartTime) { var newStartDateTime = new DateTime( newStartDate.Year, newStartDate.Month, newStartDate.Day, time.Hour, time.Minute, time.Second); if (state.NewStartDateTime == null) { state.NewStartDateTime = newStartDateTime; } if (newStartDateTime >= userNow) { state.NewStartDateTime = newStartDateTime; break; } } } } else if (state.MoveTimeSpan != 0) { state.NewStartDateTime = originalStartDateTime.AddSeconds(state.MoveTimeSpan); } else { return(await sc.BeginDialogAsync(Actions.UpdateNewStartTime, new UpdateDateTimeDialogOptions(UpdateDateTimeDialogOptions.UpdateReason.NotFound))); } state.NewStartDateTime = TimeZoneInfo.ConvertTimeToUtc(state.NewStartDateTime.Value, state.GetUserTimeZone()); return(await sc.ContinueDialogAsync()); } else if (sc.Result != null) { IList <DateTimeResolution> dateTimeResolutions = sc.Result as List <DateTimeResolution>; DateTime?newStartTime = null; foreach (var resolution in dateTimeResolutions) { var utcNow = DateTime.UtcNow; var dateTimeConvertTypeString = resolution.Timex; var dateTimeConvertType = new TimexProperty(dateTimeConvertTypeString); var dateTimeValue = DateTime.Parse(resolution.Value); if (dateTimeValue == null) { continue; } var isRelativeTime = IsRelativeTime(sc.Context.Activity.Text, resolution.Value, dateTimeConvertTypeString); if (isRelativeTime) { dateTimeValue = DateTime.SpecifyKind(dateTimeValue, DateTimeKind.Local); } dateTimeValue = isRelativeTime ? TimeZoneInfo.ConvertTime(dateTimeValue, TimeZoneInfo.Local, state.GetUserTimeZone()) : dateTimeValue; var originalStartDateTime = TimeConverter.ConvertUtcToUserTime(state.Events[0].StartTime, state.GetUserTimeZone()); if (dateTimeConvertType.Types.Contains(Constants.TimexTypes.Date) && !dateTimeConvertType.Types.Contains(Constants.TimexTypes.DateTime)) { dateTimeValue = new DateTime( dateTimeValue.Year, dateTimeValue.Month, dateTimeValue.Day, originalStartDateTime.Hour, originalStartDateTime.Minute, originalStartDateTime.Second); } else if (dateTimeConvertType.Types.Contains(Constants.TimexTypes.Time) && !dateTimeConvertType.Types.Contains(Constants.TimexTypes.DateTime)) { dateTimeValue = new DateTime( originalStartDateTime.Year, originalStartDateTime.Month, originalStartDateTime.Day, dateTimeValue.Hour, dateTimeValue.Minute, dateTimeValue.Second); } dateTimeValue = TimeZoneInfo.ConvertTimeToUtc(dateTimeValue, state.GetUserTimeZone()); if (newStartTime == null) { newStartTime = dateTimeValue; } if (dateTimeValue >= utcNow) { newStartTime = dateTimeValue; break; } } if (newStartTime != null) { state.NewStartDateTime = newStartTime; return(await sc.ContinueDialogAsync()); } else { return(await sc.BeginDialogAsync(Actions.UpdateNewStartTime, new UpdateDateTimeDialogOptions(UpdateDateTimeDialogOptions.UpdateReason.NotADateTime))); } } else { return(await sc.BeginDialogAsync(Actions.UpdateNewStartTime, new UpdateDateTimeDialogOptions(UpdateDateTimeDialogOptions.UpdateReason.NotADateTime))); } } catch (Exception ex) { await HandleDialogExceptions(sc, ex); return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs)); } }
private async Task <DialogTurnResult> PromptToLogin(WaterfallStepContext sc, CancellationToken cancellationToken) { return(await sc.PromptAsync(AuthenticationResponses.ResponseIds.LoginPrompt, new PromptOptions())); }
private Task <DialogTurnResult> EndAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { return(stepContext.EndDialogAsync(cancellationToken: cancellationToken)); }
private async Task <DialogTurnResult> GetQRNGSourceStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { //_logger.LogInformation($"MainDialog.GetQRNGSourceStepAsync[{((FoundChoice)stepContext.Result)?.Value}]"); var userProfileTemporary = await _userProfileTemporaryAccessor.GetAsync(stepContext.Context, () => new UserProfileTemporary()); // Get the number of bytes we need from the camera's entropy int numDots = getOptimizedDots(userProfileTemporary.Radius); int bytesSize = requiredEnthropyBytes(numDots); switch (((FoundChoice)stepContext.Result)?.Value) { case "Camera": stepContext.Values["qrng_source"] = "Camera"; stepContext.Values["qrng_source_query_str"] = ""; // generated later in QRNG class var promptOptions = new PromptOptions { Prompt = MessageFactory.Text("Your smartphone's camera will now load to generate some local entropy to send to me."), RetryPrompt = MessageFactory.Text("That is not a valid entropy source."), }; // Send an EventActivity to for the webbot's JavaScript callback handler to pickup // and then pass onto the app layer to load the camera var requestEntropyActivity = Activity.CreateEventActivity(); requestEntropyActivity.ChannelData = $"camrng,{bytesSize}"; await stepContext.Context.SendActivityAsync(requestEntropyActivity); return(await stepContext.PromptAsync("GetQRNGSourceChoicePrompt", promptOptions, cancellationToken)); case "ANU Leftovers": stepContext.Values["qrng_source"] = "Pool"; // Chose a random entropy GID from the list of GIDs in the pool (pseudo randomly selecting quantum randomness?! there's a joke in there somewhere :) #if RELEASE_PROD var jsonStr = new WebClient().DownloadString($"https://api.randonauts.com/getpools"); #else var jsonStr = new WebClient().DownloadString($"https://devapi.randonauts.com/getpools"); #endif var pools = Newtonsoft.Json.JsonConvert.DeserializeObject <dynamic>(jsonStr); var r = new Random(); var idx = r.Next(pools.Count); var pool = pools[idx]; var time = DateTime.Parse(pool.time.ToString()); await stepContext.Context.SendActivityAsync($"Enjoy some residual ANU pool entropy from around {time.ToString("yyyy-MM-dd")}"); stepContext.Values["qrng_source_query_str"] = $"pool=true&gid={pool.pool.ToString().Replace(".pool", "")}&raw=true"; return(await stepContext.NextAsync(cancellationToken : cancellationToken)); case "GCP Retro": stepContext.Values["qrng_source"] = "GCPRetro"; stepContext.Values["qrng_source_query_str"] = $"gcp=true&size={bytesSize * 2}"; // Until the libwrapper supports proper paging spanning over multiple days restrict the amount of entropy we ask for to within 5km if (userProfileTemporary.Radius > 5000) { userProfileTemporary.Radius = 5000; await _userProfileTemporaryAccessor.SetAsync(stepContext.Context, userProfileTemporary); } return(await stepContext.NextAsync(cancellationToken : cancellationToken)); default: case "ANU": stepContext.Values["qrng_source"] = "ANU"; stepContext.Values["qrng_source_query_str"] = ""; // generated later in QRNG class return(await stepContext.NextAsync(cancellationToken : cancellationToken)); } }
// This step routes the user to different dialogs // In this case, there's only one other dialog, so it is more simple, // but in more complex scenarios you can go off to other dialogs in a similar public async Task <DialogTurnResult> MainMenuAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { // Check if we are currently processing a user's search var state = await _accessors.PictureState.GetAsync(stepContext.Context); // If Regex picks up on anything, store it var recognizedIntents = stepContext.Context.TurnState.Get <IRecognizedIntents>(); // Based on the recognized intent, direct the conversation switch (recognizedIntents.TopIntent?.Name) { case "search": // switch to the search dialog return(await stepContext.BeginDialogAsync("searchDialog", null, cancellationToken)); case "share": // respond that you're sharing the photo await MainResponses.ReplyWithShareConfirmation(stepContext.Context); return(await stepContext.EndDialogAsync()); case "order": // respond that you're ordering await MainResponses.ReplyWithOrderConfirmation(stepContext.Context); return(await stepContext.EndDialogAsync()); case "help": // show help await MainResponses.ReplyWithHelp(stepContext.Context); return(await stepContext.EndDialogAsync()); default: { // Call LUIS recognizer var result = await _recognizer.RecognizeAsync(stepContext.Context, cancellationToken); // Get the top intent from the results var topIntent = result?.GetTopScoringIntent(); // Based on the intent, switch the conversation, similar concept as with Regex above switch ((topIntent != null) ? topIntent.Value.intent : null) { case null: // Add app logic when there is no result. await MainResponses.ReplyWithConfused(stepContext.Context); break; case "None": await MainResponses.ReplyWithConfused(stepContext.Context); // with each statement, we're adding the LuisScore, purely to test, so we know whether LUIS was called or not await MainResponses.ReplyWithLuisScore(stepContext.Context, topIntent.Value.intent, topIntent.Value.score); break; case "Greeting": await MainResponses.ReplyWithGreeting(stepContext.Context); await MainResponses.ReplyWithHelp(stepContext.Context); await MainResponses.ReplyWithLuisScore(stepContext.Context, topIntent.Value.intent, topIntent.Value.score); break; case "OrderPic": await MainResponses.ReplyWithOrderConfirmation(stepContext.Context); await MainResponses.ReplyWithLuisScore(stepContext.Context, topIntent.Value.intent, topIntent.Value.score); break; case "SharePic": await MainResponses.ReplyWithShareConfirmation(stepContext.Context); await MainResponses.ReplyWithLuisScore(stepContext.Context, topIntent.Value.intent, topIntent.Value.score); break; case "SearchPic": await MainResponses.ReplyWithSearchConfirmation(stepContext.Context); await MainResponses.ReplyWithLuisScore(stepContext.Context, topIntent.Value.intent, topIntent.Value.score); break; default: await MainResponses.ReplyWithConfused(stepContext.Context); break; } return(await stepContext.EndDialogAsync()); } } }
private static async Task <DialogTurnResult> EndCheckUserAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) {//1 return(await stepContext.EndDialogAsync()); }
private async Task <DialogTurnResult> NoUndeliveredOrderStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { return(await stepContext.PromptAsync(nameof(NoUndeliveredOrderStepAsync), Utils.CreateMessagePrompt(Resource.No_Undelivered_Order, Utils.GetYesNoOptions()))); }
protected async Task <string> TryGetEntityValueAsync(WaterfallStepContext stepContext, string key) { var entityState = await GetEntityStateAsync(stepContext); return(entityState.TryGet(key)); }
private async Task <DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { var timex = ((List <DateTimeResolution>)stepContext.Result)[0].Timex; return(await stepContext.EndDialogAsync(timex, cancellationToken)); }
private async Task <DialogTurnResult> RecommendSlotsStepAsync(WaterfallStepContext step, CancellationToken cancellationToken) { var state = await _stateAccessor.GetAsync(step.Context, cancellationToken : cancellationToken); if (state.Services.Count == 0) { state.Services = ParseServiceSelectionCardResponse(step.Context.Activity); await _stateAccessor.SetAsync(step.Context, state, cancellationToken); } // Check whether we already know something about the date. if (state.StartDate != null) { return(await step.NextAsync(cancellationToken : cancellationToken)); } List <DateTime> recommendedSlots; try { var api = new CarwashService(step, _telemetryClient, cancellationToken); var notAvailable = await api.GetNotAvailableDatesAndTimesAsync(cancellationToken); recommendedSlots = GetRecommendedSlots(notAvailable); } catch (AuthenticationException) { await step.Context.SendActivityAsync(AuthDialog.NotAuthenticatedMessage, cancellationToken : cancellationToken); return(await step.ClearStateAndEndDialogAsync(_stateAccessor, cancellationToken : cancellationToken)); } catch (Exception e) { _telemetryClient.TrackException(e); await step.Context.SendActivityAsync(e.Message, cancellationToken : cancellationToken); return(await step.ClearStateAndEndDialogAsync(_stateAccessor, cancellationToken : cancellationToken)); } // Save recommendations to state state.RecommendedSlots = recommendedSlots; await _stateAccessor.SetAsync(step.Context, state, cancellationToken); var choices = new List <Choice>(); foreach (var slot in recommendedSlots) { var timex = TimexProperty.FromDateTime(slot); choices.Add(new Choice(timex.ToNaturalLanguage(DateTime.Now))); } return(await step.PromptAsync( RecommendedSlotsPromptName, new PromptOptions { Prompt = MessageFactory.Text("Can I recommend you one of these slots? If you want to choose something else, just type skip."), Choices = choices, }, cancellationToken)); }
private async Task <DialogTurnResult> ProcessQuestionDialog(WaterfallStepContext step, CancellationToken cancellationToken = default(CancellationToken)) { var question = (string)step.Result; step.ActiveDialog.State["question"] = question; if (question == "/start") { await step.EndDialogAsync(); return(Dialog.EndOfTurn); } var recognizerResult = await accessors.LuisServices[Settings.LuisName01].RecognizeAsync(step.Context, cancellationToken); var topIntent = recognizerResult?.GetTopScoringIntent(); if (topIntent != null && topIntent.HasValue && topIntent.Value.score >= .80 && topIntent.Value.intent != "None") { step.Context.Activity.Text = topIntent.Value.intent; var response = await accessors.QnAServices[Settings.QnAName01].GetAnswersAsync(step.Context); if (response != null && response.Length > 0) { string responseType = string.Empty; responseType = FindResponseTypeMetadata(response[0].Metadata); await step.Context.SendCustomResponseAsync(response[0].Answer, responseType); if (!string.IsNullOrEmpty(responseType)) { if (!topIntent.Value.intent.EndsWith("_Sample")) { List <Choice> choices = new List <Choice>(); choices.Add(new Choice { Value = $"Yes" }); choices.Add(new Choice { Value = $"No" }); var message = $"Would you like to see an example?"; await step.Context.SendCustomResponseAsync(message); PromptOptions options = new PromptOptions { Choices = choices }; return(await step.PromptAsync("AskForExampleValidator", options, cancellationToken : cancellationToken)); } } } else { await accessors.AskForExamplePreference.SetAsync(step.Context, false); await accessors.ConversationState.SaveChangesAsync(step.Context, false, cancellationToken); var message = $"I did not find information to show you"; await step.Context.SendCustomResponseAsync(message); } } else { await accessors.AskForExamplePreference.SetAsync(step.Context, false); await accessors.ConversationState.SaveChangesAsync(step.Context, false, cancellationToken); var message = $"I did not find information to show you"; await step.Context.SendCustomResponseAsync(message); } return(await step.NextAsync()); }
private async Task <DialogTurnResult> PromptForVehiclePlateNumberConfirmationStepAsync(WaterfallStepContext step, CancellationToken cancellationToken) { var state = await _stateAccessor.GetAsync(step.Context, cancellationToken : cancellationToken); if (!Slots.Any(s => s.StartTime == state.StartDate?.Hour) && step.Result is FoundChoice choice) { state.StartDate = state.SlotChoices[choice.Index]; await _stateAccessor.SetAsync(step.Context, state, cancellationToken); } // Check last settings if (string.IsNullOrEmpty(state.VehiclePlateNumber) && !string.IsNullOrEmpty(state.LastSettings?.VehiclePlateNumber)) { state.VehiclePlateNumber = state.LastSettings.VehiclePlateNumber; } // Check whether we don't know the vehicle plate number. if (string.IsNullOrEmpty(state.VehiclePlateNumber)) { return(await step.NextAsync(cancellationToken : cancellationToken)); } return(await step.PromptAsync( VehiclePlateNumberConfirmationPromptName, new PromptOptions { Prompt = MessageFactory.Text($"I have {state.VehiclePlateNumber} as your plate number, is that correct?"), }, cancellationToken)); }
private async Task <DialogTurnResult> ChoiceActionStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { if (Helpers.IsRandoLobby(stepContext.Context)) { // Don't spam Randonauts Telegram Lobby with dialog menus as they get sent to everyone return(await stepContext.EndDialogAsync(cancellationToken : cancellationToken)); } // Shortcut to trip report dialog testing //return await stepContext.ReplaceDialogAsync(nameof(TripReportDialog), new CallbackOptions(), cancellationToken); var userProfilePersistent = await _userProfilePersistentAccessor.GetAsync(stepContext.Context, () => new UserProfilePersistent()); var userProfileTemporary = await _userProfileTemporaryAccessor.GetAsync(stepContext.Context, () => new UserProfileTemporary()); // Must agree to Privacy Policy and Terms of Service before using if (!userProfilePersistent.HasAgreedToToS) { await stepContext.EndDialogAsync(cancellationToken : cancellationToken); return(await stepContext.BeginDialogAsync(nameof(PrivacyAndTermsDialog), this, cancellationToken)); } if (stepContext.Options != null) { // Callback options passed after resuming dialog after long-running background threads etc have finished // and resume dialog via the Adapter class's callback method. var callbackOptions = (CallbackOptions)stepContext.Options; if (callbackOptions.ResetFlag) { userProfileTemporary.IsScanning = false; await _userProfileTemporaryAccessor.SetAsync(stepContext.Context, userProfileTemporary, cancellationToken); await _userTemporaryState.SaveChangesAsync(stepContext.Context, false, cancellationToken); } if (callbackOptions.StartTripReportDialog) { return(await stepContext.ReplaceDialogAsync(nameof(TripReportDialog), callbackOptions, cancellationToken)); } if (callbackOptions.UpdateIntentSuggestions) { userProfileTemporary.IntentSuggestions = callbackOptions.IntentSuggestions; userProfileTemporary.TimeIntentSuggestionsSet = callbackOptions.TimeIntentSuggestionsSet; await _userProfileTemporaryAccessor.SetAsync(stepContext.Context, userProfileTemporary, cancellationToken); await _userTemporaryState.SaveChangesAsync(stepContext.Context, false, cancellationToken); } if (callbackOptions.UpdateSettings) { userProfilePersistent.IsIncludeWaterPoints = userProfileTemporary.IsIncludeWaterPoints; userProfilePersistent.IsDisplayGoogleThumbnails = userProfileTemporary.IsDisplayGoogleThumbnails; await _userProfilePersistentAccessor.SetAsync(stepContext.Context, userProfilePersistent, cancellationToken); await _userPersistentState.SaveChangesAsync(stepContext.Context, false, cancellationToken); } } // Make sure the persistent settings are in synch with the temporary ones bool doSync = false; if (userProfileTemporary.IsIncludeWaterPoints != userProfilePersistent.IsIncludeWaterPoints) { userProfileTemporary.IsIncludeWaterPoints = userProfilePersistent.IsIncludeWaterPoints; doSync = true; } if (userProfileTemporary.IsDisplayGoogleThumbnails != userProfilePersistent.IsDisplayGoogleThumbnails) { userProfileTemporary.IsDisplayGoogleThumbnails = userProfilePersistent.IsDisplayGoogleThumbnails; doSync = true; } if (doSync) { await _userTemporaryState.SaveChangesAsync(stepContext.Context, false, cancellationToken); } //_logger.LogInformation("MainDialog.ChoiceActionStepAsync"); var options = new PromptOptions() { Prompt = MessageFactory.Text("What would you like to get?"), RetryPrompt = MessageFactory.Text("That is not a valid action. What would you like to get?"), Choices = GetActionChoices(stepContext.Context), }; return(await stepContext.PromptAsync(nameof(ChoicePrompt), options, cancellationToken)); }
private async Task <DialogTurnResult> InitializeStateStepAsync(WaterfallStepContext step, CancellationToken cancellationToken) { var state = await _stateAccessor.GetAsync(step.Context, () => null, cancellationToken); if (state == null) { if (step.Options is NewReservationState o) { state = o; } else { state = new NewReservationState(); } await _stateAccessor.SetAsync(step.Context, state, cancellationToken); } // Load LUIS entities var options = step.Options as NewReservationDialogOptions ?? new NewReservationDialogOptions(); foreach (var entity in options.LuisEntities) { switch (entity.Type) { case LuisEntityType.Service: var service = (ServiceModel)entity; state.Services.Add(service.Service); break; case LuisEntityType.DateTime: var dateTime = (DateTimeModel)entity; state.Timex = dateTime.Timex; if (dateTime.Timex.Year != null && dateTime.Timex.Month != null && dateTime.Timex.DayOfMonth != null) { var hour = dateTime.Timex.Hour ?? 0; state.StartDate = new DateTime( dateTime.Timex.Year.Value, dateTime.Timex.Month.Value, dateTime.Timex.DayOfMonth.Value, hour, 0, 0); } break; case LuisEntityType.Comment: state.Comment = entity.Text; break; case LuisEntityType.Private: state.Private = true; break; case LuisEntityType.VehiclePlateNumber: state.VehiclePlateNumber = entity.Text; break; } } // Load last reservation settings if (string.IsNullOrWhiteSpace(state.VehiclePlateNumber)) { try { var api = new CarwashService(step, _telemetryClient, cancellationToken); state.LastSettings = await api.GetLastSettingsAsync(cancellationToken); } catch (AuthenticationException) { await step.Context.SendActivityAsync(AuthDialog.NotAuthenticatedMessage, cancellationToken : cancellationToken); return(await step.ClearStateAndEndDialogAsync(_stateAccessor, cancellationToken : cancellationToken)); } catch (Exception e) { _telemetryClient.TrackException(e); await step.Context.SendActivityAsync(e.Message, cancellationToken : cancellationToken); return(await step.ClearStateAndEndDialogAsync(_stateAccessor, cancellationToken : cancellationToken)); } } await _stateAccessor.SetAsync(step.Context, state, cancellationToken); return(await step.NextAsync(cancellationToken : cancellationToken)); }
private async Task <DialogTurnResult> PerformActionStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { //_logger.LogInformation($"MainDialog.PerformActionStepAsync[{((FoundChoice)stepContext.Result)?.Value}]"); var userProfileTemporary = await _userProfileTemporaryAccessor.GetAsync(stepContext.Context, () => new UserProfileTemporary()); var actionHandler = new ActionHandler(); var repromptThisRound = false; switch (((FoundChoice)stepContext.Result)?.Value) { // Hack coz Facebook Messenge stopped showing "Send Location" button case "Set Location": repromptThisRound = true; await stepContext.Context.SendActivityAsync(CardFactory.CreateGetLocationFromGoogleMapsReply()); break; case "Attractor": stepContext.Values["PointType"] = "Attractor"; return(await stepContext.NextAsync(cancellationToken : cancellationToken)); case "Void": stepContext.Values["PointType"] = "Void"; return(await stepContext.NextAsync(cancellationToken : cancellationToken)); case "Anomaly": stepContext.Values["PointType"] = "Anomaly"; return(await stepContext.NextAsync(cancellationToken : cancellationToken)); case "Intent Suggestions": await actionHandler.IntentSuggestionActionAsync(stepContext.Context, userProfileTemporary, cancellationToken, this); break; case "Pair": stepContext.Values["PointType"] = "Pair"; return(await stepContext.NextAsync(cancellationToken : cancellationToken)); case "Blind Spots & More": await stepContext.EndDialogAsync(cancellationToken : cancellationToken); return(await stepContext.BeginDialogAsync(nameof(MoreStuffDialog), this, cancellationToken)); case "Scan": await stepContext.EndDialogAsync(cancellationToken : cancellationToken); return(await stepContext.BeginDialogAsync(nameof(ScanDialog), this, cancellationToken)); case "My Location": repromptThisRound = true; await actionHandler.LocationActionAsync(stepContext.Context, userProfileTemporary, cancellationToken); break; case "Settings": await stepContext.EndDialogAsync(cancellationToken : cancellationToken); return(await stepContext.BeginDialogAsync(nameof(SettingsDialog), this, cancellationToken)); } if (repromptThisRound) { return(await stepContext.ReplaceDialogAsync(nameof(MainDialog), cancellationToken : cancellationToken)); } else { // Long-running tasks like /getattractors etc will make use of ContinueDialog to re-prompt users return(await stepContext.EndDialogAsync(cancellationToken : cancellationToken)); } }
private async Task <DialogTurnResult> DisplayTokenAsync(WaterfallStepContext context, CancellationToken cancellationToken) { if (!(context.Result is TokenResponse result)) { await context.Context.SendActivityAsync("No token was provided for the skill.", cancellationToken : cancellationToken); }
private async Task <DialogTurnResult> SelectQRNGSourceStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { //_logger.LogInformation($"MainDialog.SelectQRNGSourceStepAsync[{((FoundChoice)stepContext.Result)?.Value}]"); // Number of IDAs to look for from previous step if (stepContext.Result == null) { stepContext.Values["idacou"] = int.Parse(stepContext.Context.Activity.Text); // manually inputted a number } else { stepContext.Values["idacou"] = int.Parse(((FoundChoice)stepContext.Result)?.Value); } var userProfileTemporary = await _userProfileTemporaryAccessor.GetAsync(stepContext.Context, () => new UserProfileTemporary()); if (userProfileTemporary.BotSrc == Enums.WebSrc.ios || userProfileTemporary.BotSrc == Enums.WebSrc.android) { var options = new PromptOptions() { Prompt = MessageFactory.Text("Chose your entropy source for the quantum random number generator (choose ANU if unsure):"), RetryPrompt = MessageFactory.Text("That is not a valid QRNG source."), Choices = new List <Choice>() { new Choice() { Value = "Camera" }, new Choice() { Value = "ANU" }, new Choice() { Value = "ANU Leftovers" }, new Choice() { Value = "GCP Retro" }, } }; return(await stepContext.PromptAsync(nameof(ChoicePrompt), options, cancellationToken)); } else { var options = new PromptOptions() { Prompt = MessageFactory.Text("Chose your entropy source for the quantum random number generator (choose ANU if unsure):"), RetryPrompt = MessageFactory.Text("That is not a valid entropy source."), Choices = new List <Choice>() { //new Choice() { Value = "Camera" }, new Choice() { Value = "ANU" }, new Choice() { Value = "ANU Leftovers" }, new Choice() { Value = "GCP Retro" }, } }; return(await stepContext.PromptAsync(nameof(ChoicePrompt), options, cancellationToken)); } }
/// <summary> /// This method uses the text of the activity to decide which type /// of card to resond with and reply with that card to the user. /// </summary> /// <param name="step">A <see cref="WaterfallStepContext"/> provides context for the current waterfall step.</param> /// <param name="cancellationToken" >(Optional) A <see cref="CancellationToken"/> that can be used by other objects /// or threads to receive notice of cancellation.</param> /// <returns>A <see cref="DialogTurnResult"/> indicating the turn has ended.</returns> /// <remarks>Related types <see cref="Attachment"/> and <see cref="AttachmentLayoutTypes"/>.</remarks> private static async Task <DialogTurnResult> ShowCardStepAsync(WaterfallStepContext step, CancellationToken cancellationToken) { // Get the text from the activity to use to show the correct card var text = step.Context.Activity.Text.ToLowerInvariant().Split(' ')[0]; // Replay to the activity we received with an activity. var reply = step.Context.Activity.CreateReply(); // Cards are sent as Attackments in the Bot Framework. // So we need to create a list of attachments on the activity. reply.Attachments = new List <Attachment>(); // Decide which type of card(s) we are going to show the user if (text.StartsWith("hero")) { // Display a HeroCard. reply.Attachments.Add(GetHeroCard().ToAttachment()); } else if (text.StartsWith("thumb")) { // Display a ThumbnailCard. reply.Attachments.Add(GetThumbnailCard().ToAttachment()); } else if (text.StartsWith("receipt")) { // Display a ReceiptCard. reply.Attachments.Add(GetReceiptCard().ToAttachment()); } else if (text.StartsWith("sign")) { // Display a SignInCard. reply.Attachments.Add(GetSigninCard().ToAttachment()); } else if (text.StartsWith("animation")) { // Display an AnimationCard. reply.Attachments.Add(GetAnimationCard().ToAttachment()); } else if (text.StartsWith("video")) { // Display a VideoCard reply.Attachments.Add(GetVideoCard().ToAttachment()); } else if (text.StartsWith("audio")) { // Display an AudioCard reply.Attachments.Add(GetAudioCard().ToAttachment()); } else if (text.StartsWith("adaptive")) { reply.Attachments.Add(CreateAdaptiveCardAttachment()); } else { // Display a carousel of all the rich card types. reply.AttachmentLayout = AttachmentLayoutTypes.Carousel; reply.Attachments.Add(CreateAdaptiveCardAttachment()); reply.Attachments.Add(GetHeroCard().ToAttachment()); reply.Attachments.Add(GetThumbnailCard().ToAttachment()); reply.Attachments.Add(GetReceiptCard().ToAttachment()); reply.Attachments.Add(GetSigninCard().ToAttachment()); reply.Attachments.Add(GetAnimationCard().ToAttachment()); reply.Attachments.Add(GetVideoCard().ToAttachment()); reply.Attachments.Add(GetAudioCard().ToAttachment()); } // Send the card(s) to the user as an attachment to the activity await step.Context.SendActivityAsync(reply, cancellationToken); // Give the user instructions about what to do next await step.Context.SendActivityAsync("Type anything to see another card.", cancellationToken : cancellationToken); return(await step.EndDialogAsync(cancellationToken : cancellationToken)); }
private Task <DialogTurnResult> DescriptionStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { throw new NotImplementedException(); }