コード例 #1
0
        public MarkToDoItemDialog(
            SkillConfigurationBase services,
            ResponseManager responseManager,
            IStatePropertyAccessor <ToDoSkillState> toDoStateAccessor,
            IStatePropertyAccessor <ToDoSkillUserState> userStateAccessor,
            IServiceManager serviceManager,
            IBotTelemetryClient telemetryClient)
            : base(nameof(MarkToDoItemDialog), services, responseManager, toDoStateAccessor, userStateAccessor, serviceManager, telemetryClient)
        {
            TelemetryClient = telemetryClient;

            var markTask = new WaterfallStep[]
            {
                GetAuthToken,
                AfterGetAuthToken,
                ClearContext,
                CollectListTypeForComplete,
                InitAllTasks,
                DoMarkTask,
            };

            var doMarkTask = new WaterfallStep[]
            {
                CollectTaskIndexForComplete,
                MarkTaskCompleted,
                ContinueMarkTask,
            };

            var collectListTypeForComplete = new WaterfallStep[]
            {
                AskListType,
                AfterAskListType,
            };

            var collectTaskIndexForComplete = new WaterfallStep[]
            {
                AskTaskIndex,
                AfterAskTaskIndex,
            };

            var continueMarkTask = new WaterfallStep[]
            {
                AskContinueMarkTask,
                AfterAskContinueMarkTask,
            };

            // Define the conversation flow using a waterfall model.
            AddDialog(new WaterfallDialog(Action.DoMarkTask, doMarkTask)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Action.MarkTaskCompleted, markTask)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Action.CollectListTypeForComplete, collectListTypeForComplete)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Action.CollectTaskIndexForComplete, collectTaskIndexForComplete)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Action.ContinueMarkTask, continueMarkTask)
            {
                TelemetryClient = telemetryClient
            });

            // Set starting dialog for component
            InitialDialogId = Action.MarkTaskCompleted;
        }
コード例 #2
0
        protected async Task <DialogTurnResult> ReadEmail(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await EmailStateAccessor.GetAsync(sc.Context);

                var skillOptions = (EmailSkillDialogOptions)sc.Options;

                sc.Context.Activity.Properties.TryGetValue("OriginText", out var content);
                var userInput = content != null?content.ToString() : sc.Context.Activity.Text;

                var luisResult        = sc.Context.TurnState.Get <EmailLuis>(StateProperties.EmailLuisResult);
                var topIntent         = luisResult?.TopIntent().intent;
                var generalLuisResult = sc.Context.TurnState.Get <General>(StateProperties.GeneralLuisResult);
                var generalTopIntent  = generalLuisResult?.TopIntent().intent;

                if (topIntent == null)
                {
                    return(await sc.EndDialogAsync(true));
                }

                await DigestFocusEmailAsync(sc);

                var message = state.Message.FirstOrDefault();
                if (message == null)
                {
                    state.Message.Add(state.MessageList[0]);
                    message = state.Message.FirstOrDefault();
                }

                var promptRecognizerResult = ConfirmRecognizerHelper.ConfirmYesOrNo(userInput, sc.Context.Activity.Locale);

                if ((topIntent == EmailLuis.Intent.None ||
                     topIntent == EmailLuis.Intent.SearchMessages ||
                     (topIntent == EmailLuis.Intent.ReadAloud && !IsReadMoreIntent(generalTopIntent, sc.Context.Activity.Text)) ||
                     (promptRecognizerResult.Succeeded && promptRecognizerResult.Value == true)) &&
                    message != null)
                {
                    var senderIcon = await GetUserPhotoUrlAsync(sc.Context, message.Sender.EmailAddress);

                    var emailCard = new EmailCardData
                    {
                        Subject          = message.Subject,
                        Sender           = message.Sender.EmailAddress.Name,
                        EmailContent     = message.BodyPreview,
                        EmailLink        = message.WebLink,
                        ReceivedDateTime = message?.ReceivedDateTime == null
                            ? CommonStrings.NotAvailable
                            : message.ReceivedDateTime.Value.UtcDateTime.ToDetailRelativeString(state.GetUserTimeZone()),
                        Speak      = SpeakHelper.ToSpeechEmailDetailOverallString(message, state.GetUserTimeZone()),
                        SenderIcon = senderIcon
                    };

                    emailCard = await ProcessRecipientPhotoUrl(sc.Context, emailCard, message.ToRecipients);

                    var tokens = new StringDictionary()
                    {
                        { "EmailDetails", SpeakHelper.ToSpeechEmailDetailString(message, state.GetUserTimeZone()) },
                        { "EmailDetailsWithContent", SpeakHelper.ToSpeechEmailDetailString(message, state.GetUserTimeZone(), true) },
                    };

                    var recipientCard = message.ToRecipients.Count() > 5 ? GetDivergedCardName(sc.Context, "DetailCard_RecipientMoreThanFive") : GetDivergedCardName(sc.Context, "DetailCard_RecipientLessThanFive");
                    var replyMessage  = ResponseManager.GetCardResponse(
                        ShowEmailResponses.ReadOutMessage,
                        new Card("EmailDetailCard", emailCard),
                        tokens,
                        "items",
                        new List <Card>().Append(new Card(recipientCard, emailCard)));

                    // Set email as read.
                    var service = ServiceManager.InitMailService(state.Token, state.GetUserTimeZone(), state.MailSourceType);
                    await service.MarkMessageAsReadAsync(message.Id);

                    await sc.Context.SendActivityAsync(replyMessage);
                }

                return(await sc.NextAsync());
            }
            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));
            }
        }
コード例 #3
0
        protected async Task <DialogTurnResult> ShowFilteredEmails(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await EmailStateAccessor.GetAsync(sc.Context);

                if (state.MessageList.Count > 0)
                {
                    if (state.Message.Count == 0)
                    {
                        state.Message.Add(state.MessageList[0]);

                        if (state.MessageList.Count > 1)
                        {
                            var importCount = 0;

                            foreach (var msg in state.MessageList)
                            {
                                if (msg.Importance.HasValue && msg.Importance.Value == Importance.High)
                                {
                                    importCount++;
                                }
                            }

                            await ShowMailList(sc, state.MessageList, state.MessageList.Count(), importCount, cancellationToken);

                            return(await sc.NextAsync());
                        }
                        else if (state.MessageList.Count == 1)
                        {
                            return(await sc.ReplaceDialogAsync(Actions.Read, options : sc.Options));
                        }
                    }
                    else
                    {
                        return(await sc.ReplaceDialogAsync(Actions.Read, options : sc.Options));
                    }

                    await sc.Context.SendActivityAsync(ResponseManager.GetResponse(EmailSharedResponses.DidntUnderstandMessage));

                    return(await sc.EndDialogAsync(true));
                }
                else
                {
                    await sc.Context.SendActivityAsync(ResponseManager.GetResponse(EmailSharedResponses.EmailNotFound));
                }

                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));
            }
        }
コード例 #4
0
        public async Task <DialogTurnResult> AfterUpdateUserName(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var userInput = sc.Result as string;
                var state     = await Accessor.GetAsync(sc.Context);

                var options = (UpdateUserNameDialogOptions)sc.Options;

                if (string.IsNullOrEmpty(userInput) && options.Reason != UpdateUserNameDialogOptions.UpdateReason.Initialize)
                {
                    await sc.Context.SendActivityAsync(ResponseManager.GetResponse(FindContactResponses.UserNotFoundAgain, new StringDictionary()
                    {
                        { "source", state.EventSource == EventSource.Microsoft ? "Outlook Calendar" : "Google Calendar" }
                    }));

                    return(await sc.EndDialogAsync());
                }

                string currentRecipientName = string.IsNullOrEmpty(userInput) ? state.CurrentAttendeeName : userInput;
                state.CurrentAttendeeName = currentRecipientName;

                // if it's an email, add to attendee and kepp the state.ConfirmedPerson null
                if (!string.IsNullOrEmpty(currentRecipientName) && IsEmail(currentRecipientName))
                {
                    var attendee = new EventModel.Attendee
                    {
                        DisplayName = currentRecipientName,
                        Address     = currentRecipientName
                    };
                    if (state.Attendees.All(r => r.Address != attendee.Address))
                    {
                        state.Attendees.Add(attendee);
                    }

                    state.CurrentAttendeeName = string.Empty;
                    state.ConfirmedPerson     = null;
                    return(await sc.EndDialogAsync());
                }

                List <CustomizedPerson> unionList = new List <CustomizedPerson>();

                if (CreateEventWhiteList.GetMyself(currentRecipientName))
                {
                    var me = await GetMe(sc.Context);

                    unionList.Add(new CustomizedPerson(me));
                }
                else
                {
                    var originPersonList = await GetPeopleWorkWithAsync(sc, currentRecipientName);

                    var originContactList = await GetContactsAsync(sc, currentRecipientName);

                    originPersonList.AddRange(originContactList);

                    var originUserList = new List <PersonModel>();
                    try
                    {
                        originUserList = await GetUserAsync(sc, currentRecipientName);
                    }
                    catch
                    {
                        // do nothing when get user failed. because can not use token to ensure user use a work account.
                    }

                    (var personList, var userList) = FormatRecipientList(originPersonList, originUserList);

                    // people you work with has the distinct email address has the highest priority
                    if (personList.Count == 1 && personList.First().Emails.Any() && personList.First().Emails.First() != null)
                    {
                        unionList.Add(new CustomizedPerson(personList.First()));
                    }
                    else
                    {
                        personList.AddRange(userList);

                        foreach (var person in personList)
                        {
                            if (unionList.Find(p => p.DisplayName == person.DisplayName) == null)
                            {
                                var personWithSameName = personList.FindAll(p => p.DisplayName == person.DisplayName);
                                if (personWithSameName.Count == 1)
                                {
                                    unionList.Add(new CustomizedPerson(personWithSameName.First()));
                                }
                                else
                                {
                                    var unionPerson  = new CustomizedPerson(personWithSameName.FirstOrDefault());
                                    var curEmailList = new List <ScoredEmailAddress>();
                                    foreach (var sameNamePerson in personWithSameName)
                                    {
                                        sameNamePerson.Emails.ToList().ForEach(e =>
                                        {
                                            if (!string.IsNullOrEmpty(e))
                                            {
                                                curEmailList.Add(new ScoredEmailAddress {
                                                    Address = e
                                                });
                                            }
                                        });
                                    }

                                    unionPerson.Emails = curEmailList;
                                    unionList.Add(unionPerson);
                                }
                            }
                        }
                    }
                }

                unionList.RemoveAll(person => !person.Emails.Exists(email => email.Address != null));
                unionList.RemoveAll(person => !person.Emails.Any());

                state.UnconfirmedPerson = unionList;

                if (unionList.Count == 0)
                {
                    return(await sc.ReplaceDialogAsync(Actions.UpdateName, new UpdateUserNameDialogOptions(UpdateUserNameDialogOptions.UpdateReason.NotFound)));
                }
                else
                if (unionList.Count == 1)
                {
                    state.ConfirmedPerson = unionList.First();
                    return(await sc.EndDialogAsync());
                }
                else
                {
                    return(await sc.ReplaceDialogAsync(Actions.SelectPerson, sc.Options, cancellationToken));
                }
            }
            catch (SkillException skillEx)
            {
                await HandleDialogExceptions(sc, skillEx);

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

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
コード例 #5
0
        protected async Task <DialogTurnResult> PromptToHandle(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await EmailStateAccessor.GetAsync(sc.Context);

                if (state.MessageList.Count == 1)
                {
                    return(await sc.PromptAsync(Actions.Prompt, new PromptOptions { Prompt = ResponseManager.GetResponse(ShowEmailResponses.ReadOutOnlyOnePrompt) }));
                }
                else
                {
                    return(await sc.PromptAsync(Actions.Prompt, new PromptOptions { Prompt = ResponseManager.GetResponse(ShowEmailResponses.ReadOutPrompt) }));
                }
            }
            catch (Exception ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
コード例 #6
0
        public async Task <DialogTurnResult> AfterConfirmNameList(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context);

                // get name list from sc.result
                if (sc.Result != null)
                {
                    sc.Context.Activity.Properties.TryGetValue("OriginText", out var content);
                    var userInput = content != null?content.ToString() : sc.Context.Activity.Text;

                    // if is skip. set the name list to be myself only.
                    if (CreateEventWhiteList.IsSkip(userInput))
                    {
                        state.AttendeesNameList = new List <string>
                        {
                            CalendarCommonStrings.MyselfConst
                        };
                    }
                    else
                    if (state.EventSource != EventSource.Other)
                    {
                        if (userInput != null)
                        {
                            var nameList = userInput.Split(CreateEventWhiteList.GetContactNameSeparator(), StringSplitOptions.None)
                                           .Select(x => x.Trim())
                                           .Where(x => !string.IsNullOrWhiteSpace(x))
                                           .ToList();
                            state.AttendeesNameList = nameList;
                        }
                    }
                }

                if (state.AttendeesNameList.Any())
                {
                    if (state.AttendeesNameList.Count > 1)
                    {
                        var nameString = await GetReadyToSendNameListStringAsync(sc);

                        await sc.Context.SendActivityAsync(ResponseManager.GetResponse(FindContactResponses.BeforeSendingMessage, new StringDictionary()
                        {
                            { "NameList", nameString }
                        }));
                    }

                    // go to loop to go through all the names
                    state.ConfirmAttendeesNameIndex = 0;
                    return(await sc.ReplaceDialogAsync(Actions.LoopNameList, sc.Options, cancellationToken));
                }

                state.AttendeesNameList         = new List <string>();
                state.CurrentAttendeeName       = string.Empty;
                state.ConfirmAttendeesNameIndex = 0;
                return(await sc.EndDialogAsync());
            }
            catch (Exception ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
コード例 #7
0
        public async Task <DialogTurnResult> ConfirmEmail(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await Accessor.GetAsync(sc.Context);

            var confirmedPerson = state.ConfirmedPerson;

            if (confirmedPerson == null)
            {
                return(await sc.EndDialogAsync());
            }

            var name = confirmedPerson.DisplayName;

            if (confirmedPerson.Emails.Count() == 1)
            {
                // Highest probability
                return(await sc.PromptAsync(Actions.TakeFurtherAction, new PromptOptions { Prompt = ResponseManager.GetResponse(FindContactResponses.PromptOneNameOneAddress, new StringDictionary()
                    {
                        { "UserName", name }, { "EmailAddress", confirmedPerson.Emails.First().Address ?? confirmedPerson.UserPrincipalName }
                    }), }));
            }
            else
            {
                return(await sc.BeginDialogAsync(Actions.SelectEmail));
            }
        }
コード例 #8
0
        public override void Initialize()
        {
            this.ServiceManager = MockServiceManager.GetCalendarService();

            // Initialize service collection
            Services = new ServiceCollection();
            Services.AddSingleton(new BotSettings()
            {
                OAuthConnections = new List <OAuthConnection>()
                {
                    new OAuthConnection()
                    {
                        Name = "Microsoft", Provider = "Microsoft"
                    }
                }
            });

            Services.AddSingleton(new BotServices());
            Services.AddSingleton <IBotTelemetryClient, NullBotTelemetryClient>();
            Services.AddSingleton(new UserState(new MemoryStorage()));
            Services.AddSingleton(new ConversationState(new MemoryStorage()));
            Services.AddSingleton(new ProactiveState(new MemoryStorage()));
            Services.AddSingleton(new MicrosoftAppCredentials(string.Empty, string.Empty));
            Services.AddSingleton(sp =>
            {
                var userState         = sp.GetService <UserState>();
                var conversationState = sp.GetService <ConversationState>();
                var proactiveState    = sp.GetService <ProactiveState>();
                return(new BotStateSet(userState, conversationState));
            });

            ResponseManager = new ResponseManager(
                new string[] { "en", "de", "es", "fr", "it", "zh" },
                new FindContactResponses(),
                new ChangeEventStatusResponses(),
                new CreateEventResponses(),
                new JoinEventResponses(),
                new CalendarMainResponses(),
                new CalendarSharedResponses(),
                new SummaryResponses(),
                new TimeRemainingResponses(),
                new UpdateEventResponses(),
                new UpcomingEventResponses());
            Services.AddSingleton(ResponseManager);

            Services.AddSingleton <IBackgroundTaskQueue, BackgroundTaskQueue>();
            Services.AddSingleton(ServiceManager);
            Services.AddSingleton <TestAdapter, DefaultTestAdapter>();
            Services.AddTransient <MainDialog>();
            Services.AddTransient <ChangeEventStatusDialog>();
            Services.AddTransient <ConnectToMeetingDialog>();
            Services.AddTransient <CreateEventDialog>();
            Services.AddTransient <FindContactDialog>();
            Services.AddTransient <SummaryDialog>();
            Services.AddTransient <TimeRemainingDialog>();
            Services.AddTransient <UpcomingEventDialog>();
            Services.AddTransient <UpdateEventDialog>();
            Services.AddTransient <FindContactDialog>();
            Services.AddTransient <IBot, DialogBot <MainDialog> >();

            var state = Services.BuildServiceProvider().GetService <ConversationState>();

            CalendarStateAccessor = state.CreateProperty <CalendarSkillState>(nameof(CalendarSkillState));
        }
コード例 #9
0
ファイル: FakeSkill.cs プロジェクト: omarnahhas30/AI
        public FakeSkill(SkillConfigurationBase services, EndpointService endpointService, ConversationState conversationState, UserState userState, ProactiveState proactiveState, IBotTelemetryClient telemetryClient, IBackgroundTaskQueue backgroundTaskQueue, bool skillMode = false, ResponseManager responseManager = null, ServiceManager serviceManager = null)
        {
            _skillMode           = skillMode;
            _services            = services ?? throw new ArgumentNullException(nameof(services));
            _userState           = userState ?? throw new ArgumentNullException(nameof(userState));
            _conversationState   = conversationState ?? throw new ArgumentNullException(nameof(conversationState));
            _proactiveState      = proactiveState;
            _endpointService     = endpointService;
            _backgroundTaskQueue = backgroundTaskQueue;
            _telemetryClient     = telemetryClient ?? throw new ArgumentNullException(nameof(telemetryClient));
            _serviceManager      = serviceManager ?? new ServiceManager();

            if (responseManager == null)
            {
                var locales = new string[] { "en-us", "de-de", "es-es", "fr-fr", "it-it", "zh-cn" };
                responseManager = new ResponseManager(
                    locales,
                    new SampleAuthResponses(),
                    new MainResponses(),
                    new SharedResponses(),
                    new SampleResponses());
            }

            _responseManager = responseManager;
            _dialogs         = new DialogSet(_conversationState.CreateProperty <DialogState>(nameof(DialogState)));
            _dialogs.Add(new MainDialog(_services, _responseManager, _conversationState, _userState, _telemetryClient, _serviceManager, _skillMode));
        }
コード例 #10
0
        private async Task <DialogTurnResult> SendChange(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await Accessor.GetAsync(sc.Context);

            var settingChangeConfirmed = false;

            // If we skip the ConfirmPrompt due to no confirmation needed then Result will be NULL
            if (sc.Result == null)
            {
                settingChangeConfirmed = true;
            }
            else
            {
                settingChangeConfirmed = (bool)sc.Result;
            }

            if (settingChangeConfirmed)
            {
                var change = state.Changes[0];

                // If the change involves an amount then we add this to the change event
                if (change.Amount != null)
                {
                    var promptReplacements = new StringDictionary
                    {
                        { "settingName", change.SettingName },
                        { "amount", change.Amount.Amount.ToString() },
                        { "unit", UnitToString(change.Amount.Unit) },
                    };
                    if (change.IsRelativeAmount)
                    {
                        if (change.Amount.Amount < 0)
                        {
                            promptReplacements["increasingDecreasing"] = VehicleSettingsStrings.DECREASING;
                            promptReplacements["amount"] = (-change.Amount.Amount).ToString();
                        }
                        else
                        {
                            promptReplacements["increasingDecreasing"] = VehicleSettingsStrings.INCREASING;
                        }

                        // Send an event to the device along with the text confirmation
                        await SendActionToDevice(sc, change, promptReplacements);

                        await sc.Context.SendActivityAsync(ResponseManager.GetResponse(
                                                               VehicleSettingsResponses.VehicleSettingsChangingRelativeAmount, promptReplacements));
                    }
                    else
                    {
                        // Send an event to the device along with the text confirmation
                        await SendActionToDevice(sc, change, promptReplacements);

                        await sc.Context.SendActivityAsync(ResponseManager.GetResponse(
                                                               VehicleSettingsResponses.VehicleSettingsChangingAmount, promptReplacements));
                    }
                }
                else
                {
                    // Nominal (non-numeric) change (e.g., on/off)
                    string promptTemplate;
                    var    promptReplacements = new StringDictionary {
                        { "settingName", change.SettingName }
                    };
                    if (SettingValueToSpeakableIngForm.TryGetValue(change.Value.ToLowerInvariant(), out var valueIngForm))
                    {
                        promptTemplate = VehicleSettingsResponses.VehicleSettingsChangingValueKnown;
                        promptReplacements["valueIngForm"] = valueIngForm;
                    }
                    else
                    {
                        promptTemplate = VehicleSettingsResponses.VehicleSettingsChangingValue;
                        promptReplacements["value"] = change.Value;
                    }

                    // Send an event to the device along with the text confirmation
                    await SendActionToDevice(sc, change, promptReplacements);

                    await sc.Context.SendActivityAsync(ResponseManager.GetResponse(promptTemplate, promptReplacements));
                }
            }
            else
            {
                await sc.Context.SendActivityAsync(ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsSettingChangeConfirmationDenied));
            }

            return(await sc.EndDialogAsync());
        }
コード例 #11
0
        public VehicleSettingsDialog(
            SkillConfigurationBase services,
            ResponseManager responseManager,
            IStatePropertyAccessor <AutomotiveSkillState> accessor,
            IServiceManager serviceManager,
            IBotTelemetryClient telemetryClient,
            IHttpContextAccessor httpContext)
            : base(nameof(VehicleSettingsDialog), services, responseManager, accessor, serviceManager, telemetryClient)
        {
            TelemetryClient = telemetryClient;

            // Initialise supporting LUIS models for followup questions
            vehicleSettingNameSelectionLuisRecognizer  = services.LocaleConfigurations["en"].LuisServices["settings_name"];
            vehicleSettingValueSelectionLuisRecognizer = services.LocaleConfigurations["en"].LuisServices["settings_value"];

            // Initialise supporting LUIS models for followup questions
            vehicleSettingNameSelectionLuisRecognizer  = services.LocaleConfigurations["en"].LuisServices["settings_name"];
            vehicleSettingValueSelectionLuisRecognizer = services.LocaleConfigurations["en"].LuisServices["settings_value"];

            // Supporting setting files are stored as embeddded resources
            Assembly resourceAssembly = typeof(VehicleSettingsDialog).Assembly;

            var settingFile = resourceAssembly
                              .GetManifestResourceNames()
                              .Where(x => x.Contains(AvailableSettingsFileName))
                              .First();

            var alternativeSettingFileName = resourceAssembly
                                             .GetManifestResourceNames()
                                             .Where(x => x.Contains(AlternativeSettingsFileName))
                                             .First();

            if (string.IsNullOrEmpty(settingFile) || string.IsNullOrEmpty(alternativeSettingFileName))
            {
                throw new FileNotFoundException($"Unable to find Available Setting and/or Alternative Names files in \"{resourceAssembly.FullName}\" assembly.");
            }

            settingList   = new SettingList(resourceAssembly, settingFile, alternativeSettingFileName);
            settingFilter = new SettingFilter(settingList);

            // Setting Change waterfall
            var processVehicleSettingChangeWaterfall = new WaterfallStep[]
            {
                ProcessSetting,
                ProcessVehicleSettingsChange,
                ProcessChange,
                SendChange
            };

            AddDialog(new WaterfallDialog(Actions.ProcessVehicleSettingChange, processVehicleSettingChangeWaterfall)
            {
                TelemetryClient = telemetryClient
            });

            // Prompts
            AddDialog(new ChoicePrompt(Actions.SettingNameSelectionPrompt, SettingNameSelectionValidator, Culture.English)
            {
                Style = ListStyle.Inline, ChoiceOptions = new ChoiceFactoryOptions {
                    InlineSeparator = string.Empty, InlineOr = string.Empty, InlineOrMore = string.Empty, IncludeNumbers = true
                }
            });
            AddDialog(new ChoicePrompt(Actions.SettingValueSelectionPrompt, SettingValueSelectionValidator, Culture.English)
            {
                Style = ListStyle.Inline, ChoiceOptions = new ChoiceFactoryOptions {
                    InlineSeparator = string.Empty, InlineOr = string.Empty, InlineOrMore = string.Empty, IncludeNumbers = true
                }
            });

            AddDialog(new ConfirmPrompt(Actions.SettingConfirmationPrompt));

            // Set starting dialog for component
            InitialDialogId = Actions.ProcessVehicleSettingChange;

            // Used to resolve image paths (local or hosted)
            _httpContext = httpContext;
        }
コード例 #12
0
        /// <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> ProcessVehicleSettingsChange(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await Accessor.GetAsync(sc.Context);

            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(ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsMissingSettingValue));

                    return(await sc.EndDialogAsync());
                }
                else
                {
                    // We have found multiple setting values, which we need to prompt the user to resolve
                    if (settingValues.Count() > 1)
                    {
                        string 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
                        string 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];
                            List <string> synonyms = new List <string>();
                            synonyms.Add(item);
                            synonyms.Add((i + 1).ToString());
                            synonyms.AddRange(settingList.GetAlternativeNamesForSettingValue(settingName, item));
                            var choice = new Choice()
                            {
                                Value    = item,
                                Synonyms = synonyms,
                            };
                            options.Choices.Add(choice);
                        }

                        var promptReplacements = new StringDictionary {
                            { "settingName", settingName }
                        };
                        options.Prompt = ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsSettingValueSelection, promptReplacements);

                        var card = new ThumbnailCard
                        {
                            Text   = options.Prompt.Text,
                            Images = new List <CardImage> {
                                new CardImage(GetSettingCardImageUri(imageName))
                            },
                            Buttons = options.Choices.Select(choice =>
                                                             new CardAction(ActionTypes.ImBack, choice.Value, value: choice.Value)).ToList(),
                        };

                        options.Prompt.Attachments.Add(card.ToAttachment());

                        // Default Text property is clumsy for speech
                        options.Prompt.Speak = $"{options.Prompt.Text} {GetSpeakableOptions(options.Choices)}";

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

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

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

            switch (topIntent.Value)
            {
            case Luis.VehicleSettings.Intent.VEHICLE_SETTINGS_CHANGE:
            case Luis.VehicleSettings.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 == Luis.VehicleSettings.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];
                        List <string> synonyms = new List <string>();
                        synonyms.Add(item);
                        synonyms.Add((i + 1).ToString());
                        synonyms.AddRange(settingList.GetAlternativeNamesForSetting(item));
                        var choice = new Choice()
                        {
                            Value    = item,
                            Synonyms = synonyms,
                        };
                        options.Choices.Add(choice);
                    }

                    options.Prompt = ResponseManager.GetResponse(VehicleSettingsResponses.VehicleSettingsSettingNameSelection);

                    var card = new ThumbnailCard
                    {
                        Images = new List <CardImage> {
                            new CardImage(GetSettingCardImageUri(FallbackSettingImageFileName))
                        },
                        Text    = options.Prompt.Text,
                        Buttons = options.Choices.Select(choice =>
                                                         new CardAction(ActionTypes.ImBack, choice.Value, value: choice.Value)).ToList(),
                    };

                    options.Prompt.Attachments.Add(card.ToAttachment());

                    // Default Text property is clumsy for speech
                    options.Prompt.Speak = $"{options.Prompt.Text} {GetSpeakableOptions(options.Choices)}";

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

            case Luis.VehicleSettings.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));
            }
        }
コード例 #14
0
        public void ConfigureServices(IServiceCollection services)
        {
            // add background task queue
            services.AddSingleton <IBackgroundTaskQueue, BackgroundTaskQueue>();
            services.AddHostedService <QueuedHostedService>();

            // Load the connected services from .bot file.
            var botFilePath   = Configuration.GetSection("botFilePath")?.Value;
            var botFileSecret = Configuration.GetSection("botFileSecret")?.Value;
            var botConfig     = BotConfiguration.Load(botFilePath ?? @".\CalendarSkill.bot", botFileSecret);

            services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot config file could not be loaded."));

            // Use Application Insights
            services.AddBotApplicationInsights(botConfig);

            // Initializes your bot service clients and adds a singleton that your Bot can access through dependency injection.
            var parameters         = Configuration.GetSection("parameters")?.Get <string[]>();
            var configuration      = Configuration.GetSection("configuration")?.GetChildren()?.ToDictionary(x => x.Key, y => y.Value as object);
            var supportedProviders = Configuration.GetSection("supportedProviders")?.Get <string[]>();
            var languageModels     = Configuration.GetSection("languageModels").Get <Dictionary <string, Dictionary <string, string> > >();
            var connectedServices  = new SkillConfiguration(botConfig, languageModels, supportedProviders, parameters, configuration);

            services.AddSingleton <SkillConfigurationBase>(sp => connectedServices);

            var supportedLanguages = languageModels.Select(l => l.Key).ToArray();
            var responses          = new IResponseIdCollection[]
            {
                new FindContactResponses(),
                new ChangeEventStatusResponses(),
                new CreateEventResponses(),
                new JoinEventResponses(),
                new CalendarMainResponses(),
                new CalendarSharedResponses(),
                new SummaryResponses(),
                new TimeRemainingResponses(),
                new UpdateEventResponses(),
            };

            var responseManager = new ResponseManager(responses, supportedLanguages);

            // Register bot responses for all supported languages.
            services.AddSingleton(sp => responseManager);

            // Initialize Bot State
            var cosmosDbService = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.CosmosDB) ?? throw new Exception("Please configure your CosmosDb service in your .bot file.");
            var cosmosDb        = cosmosDbService as CosmosDbService;
            var cosmosOptions   = new CosmosDbStorageOptions()
            {
                CosmosDBEndpoint = new Uri(cosmosDb.Endpoint),
                AuthKey          = cosmosDb.Key,
                CollectionId     = cosmosDb.Collection,
                DatabaseId       = cosmosDb.Database,
            };
            var dataStore         = new CosmosDbStorage(cosmosOptions);
            var userState         = new UserState(dataStore);
            var conversationState = new ConversationState(dataStore);
            var proactiveState    = new ProactiveState(dataStore);

            services.AddSingleton(dataStore);
            services.AddSingleton(userState);
            services.AddSingleton(conversationState);
            services.AddSingleton(proactiveState);
            services.AddSingleton(new BotStateSet(userState, conversationState));

            var environment = _isProduction ? "production" : "development";
            var service     = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.Endpoint && s.Name == environment);

            if (!(service is EndpointService endpointService))
            {
                throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'.");
            }

            services.AddSingleton(endpointService);

            // Initialize calendar service client
            services.AddSingleton <IServiceManager, ServiceManager>();

            // Add the bot with options
            services.AddBot <CalendarSkill>(options =>
            {
                options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);

                // Telemetry Middleware (logs activity messages in Application Insights)
                var sp = services.BuildServiceProvider();
                var telemetryClient   = sp.GetService <IBotTelemetryClient>();
                var appInsightsLogger = new TelemetryLoggerMiddleware(telemetryClient, logPersonalInformation: true);
                options.Middleware.Add(appInsightsLogger);

                // Catches any errors that occur during a conversation turn and logs them to AppInsights.
                options.OnTurnError = async(context, exception) =>
                {
                    CultureInfo.CurrentUICulture = new CultureInfo(context.Activity.Locale);
                    await context.SendActivityAsync(responseManager.GetResponse(CalendarSharedResponses.CalendarErrorMessage));
                    await context.SendActivityAsync(new Activity(type: ActivityTypes.Trace, text: $"Calendar Skill Error: {exception.Message} | {exception.StackTrace}"));
                    telemetryClient.TrackExceptionEx(exception, context.Activity);
                };

                // Transcript Middleware (saves conversation history in a standard format)
                var storageService       = botConfig.Services.FirstOrDefault(s => s.Type == ServiceTypes.BlobStorage) ?? throw new Exception("Please configure your Azure Storage service in your .bot file.");
                var blobStorage          = storageService as BlobStorageService;
                var transcriptStore      = new AzureBlobTranscriptStore(blobStorage.ConnectionString, blobStorage.Container);
                var transcriptMiddleware = new TranscriptLoggerMiddleware(transcriptStore);
                options.Middleware.Add(transcriptMiddleware);

                // Typing Middleware (automatically shows typing when the bot is responding/working)
                var typingMiddleware = new ShowTypingMiddleware();
                options.Middleware.Add(typingMiddleware);

                options.Middleware.Add(new AutoSaveStateMiddleware(userState, conversationState));

                var defaultLocale = Configuration.GetSection("defaultLocale").Get <string>();
                options.Middleware.Add(new SetLocaleMiddleware(defaultLocale ?? "en"));
            });
        }
コード例 #15
0
        public override void Initialize()
        {
            // Initialize mock service manager
            ServiceManager = new MockServiceManager();

            // Initialize service collection
            Services = new ServiceCollection();
            Services.AddSingleton(new BotSettings()
            {
                OAuthConnections = new List <OAuthConnection>()
                {
                    new OAuthConnection()
                    {
                        Name = "Microsoft", Provider = "Microsoft"
                    }
                }
            });

            Services.AddSingleton(new BotServices()
            {
                CognitiveModelSets = new Dictionary <string, CognitiveModelSet>
                {
                    {
                        "en", new CognitiveModelSet()
                        {
                            LuisServices = new Dictionary <string, ITelemetryRecognizer>
                            {
                                { "general", new MockGeneralLuisRecognizer() },
                                {
                                    "email", new MockEmailLuisRecognizer(
                                        new ForwardEmailUtterances(),
                                        new ReplyEmailUtterances(),
                                        new DeleteEmailUtterances(),
                                        new SendEmailUtterances(),
                                        new ShowEmailUtterances())
                                }
                            }
                        }
                    }
                }
            });

            Services.AddSingleton <IBotTelemetryClient, NullBotTelemetryClient>();
            Services.AddSingleton(new UserState(new MemoryStorage()));
            Services.AddSingleton(new ConversationState(new MemoryStorage()));
            Services.AddSingleton(new ProactiveState(new MemoryStorage()));
            Services.AddSingleton(new MicrosoftAppCredentials(string.Empty, string.Empty));
            Services.AddSingleton(sp =>
            {
                var userState         = sp.GetService <UserState>();
                var conversationState = sp.GetService <ConversationState>();
                var proactiveState    = sp.GetService <ProactiveState>();
                return(new BotStateSet(userState, conversationState));
            });

            ResponseManager = new ResponseManager(
                new string[] { "en", "de", "es", "fr", "it", "zh" },
                new FindContactResponses(),
                new DeleteEmailResponses(),
                new ForwardEmailResponses(),
                new EmailMainResponses(),
                new ReplyEmailResponses(),
                new SendEmailResponses(),
                new EmailSharedResponses(),
                new ShowEmailResponses());
            Services.AddSingleton(ResponseManager);

            Services.AddSingleton <IBackgroundTaskQueue, BackgroundTaskQueue>();
            Services.AddSingleton <IServiceManager>(ServiceManager);
            Services.AddSingleton <TestAdapter, DefaultTestAdapter>();
            Services.AddTransient <MainDialog>();
            Services.AddTransient <DeleteEmailDialog>();
            Services.AddTransient <FindContactDialog>();
            Services.AddTransient <ForwardEmailDialog>();
            Services.AddTransient <ReplyEmailDialog>();
            Services.AddTransient <SendEmailDialog>();
            Services.AddTransient <ShowEmailDialog>();
            Services.AddTransient <IBot, DialogBot <MainDialog> >();

            ConfigData.GetInstance().MaxDisplaySize = 3;
            ConfigData.GetInstance().MaxReadSize    = 3;
        }
コード例 #16
0
        public ForwardEmailDialog(
            SkillConfigurationBase services,
            ResponseManager responseManager,
            IStatePropertyAccessor <EmailSkillState> emailStateAccessor,
            IStatePropertyAccessor <DialogState> dialogStateAccessor,
            IServiceManager serviceManager,
            IBotTelemetryClient telemetryClient)
            : base(nameof(ForwardEmailDialog), services, responseManager, emailStateAccessor, dialogStateAccessor, serviceManager, telemetryClient)
        {
            TelemetryClient = telemetryClient;

            var forwardEmail = new WaterfallStep[]
            {
                IfClearContextStep,
                GetAuthToken,
                AfterGetAuthToken,
                SetDisplayConfig,
                CollectSelectedEmail,
                AfterCollectSelectedEmail,
                CollectRecipient,
                CollectAdditionalText,
                AfterCollectAdditionalText,
                ConfirmBeforeSending,
                ConfirmAllRecipient,
                ForwardEmail,
            };

            var showEmail = new WaterfallStep[]
            {
                PagingStep,
                ShowEmails,
            };

            var collectRecipients = new WaterfallStep[]
            {
                PromptRecipientCollection,
                GetRecipients,
            };

            var updateSelectMessage = new WaterfallStep[]
            {
                UpdateMessage,
                PromptUpdateMessage,
                AfterUpdateMessage,
            };

            // Define the conversation flow using a waterfall model.
            AddDialog(new WaterfallDialog(Actions.Forward, forwardEmail)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.Show, showEmail)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.CollectRecipient, collectRecipients)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.UpdateSelectMessage, updateSelectMessage)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new FindContactDialog(services, responseManager, emailStateAccessor, dialogStateAccessor, serviceManager, telemetryClient));
            InitialDialogId = Actions.Forward;
        }
コード例 #17
0
        public async Task <DialogTurnResult> ConfirmNameList(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context);

                // got attendee name list already.
                if (state.AttendeesNameList.Any())
                {
                    return(await sc.NextAsync());
                }

                // ask for attendee
                return(await sc.PromptAsync(Actions.Prompt, new PromptOptions { Prompt = ResponseManager.GetResponse(FindContactResponses.NoAttendees) }, cancellationToken));
            }
            catch (Exception ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
コード例 #18
0
        public JoinEventDialog(
            BotSettings settings,
            BotServices services,
            ResponseManager responseManager,
            ConversationState conversationState,
            IServiceManager serviceManager,
            IBotTelemetryClient telemetryClient,
            MicrosoftAppCredentials appCredentials)
            : base(nameof(JoinEventDialog), settings, services, responseManager, conversationState, serviceManager, telemetryClient, appCredentials)
        {
            TelemetryClient = telemetryClient;

            var joinMeeting = new WaterfallStep[]
            {
                GetAuthToken,
                AfterGetAuthToken,
                CheckFocusedEvent,
                ConfirmNumber,
                AfterConfirmNumber
            };

            var findEvent = new WaterfallStep[]
            {
                SearchEventsWithEntities,
                GetEvents,
                AddConflictFlag,
                ChooseEvent
            };

            var getEvents = new WaterfallStep[]
            {
                GetEventsPrompt,
                AfterGetEventsPrompt,
                CheckValid,
            };

            var chooseEvent = new WaterfallStep[]
            {
                ChooseEventPrompt,
                AfterChooseEvent
            };

            AddDialog(new WaterfallDialog(Actions.ConnectToMeeting, joinMeeting)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.GetEvents, getEvents)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.FindEvent, findEvent)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.ChooseEvent, chooseEvent)
            {
                TelemetryClient = telemetryClient
            });

            // Set starting dialog for component
            InitialDialogId = Actions.ConnectToMeeting;
        }
コード例 #19
0
        public FindContactDialog(
            SkillConfigurationBase services,
            ResponseManager responseManager,
            IStatePropertyAccessor <CalendarSkillState> accessor,
            IServiceManager serviceManager,
            IBotTelemetryClient telemetryClient)
            : base(nameof(FindContactDialog), services, responseManager, accessor, serviceManager, telemetryClient)
        {
            TelemetryClient = telemetryClient;

            // entry, get the name list
            var confirmNameList = new WaterfallStep[]
            {
                ConfirmNameList,
                AfterConfirmNameList,
            };

            // go through the name list, replace the confirmNameList
            // set state.CurrentAttendeeName
            var loopNameList = new WaterfallStep[]
            {
                LoopNameList,
                AfterLoopNameList
            };

            // check on the attendee of state.CurrentAttendeeName.
            // called by loopNameList
            var confirmAttendee = new WaterfallStep[]
            {
                // call updateName to get the person state.ConfirmedPerson.
                // state.ConfirmedPerson should be set after this step
                ConfirmName,

                // check if the state.ConfirmedPerson
                //  - null : failed to parse this name for multiple try.
                //  - one email : check if this one is wanted
                //  - multiple emails : call selectEmail
                ConfirmEmail,

                // if got no on last step, replace/restart this flow.
                AfterConfirmEmail
            };

            // use the user name of state.CurrentAttendeeName or user input to find the persons.
            // and will call select person.
            // after all this done, state.ConfirmedPerson should be set.
            var updateName = new WaterfallStep[]
            {
                // check whether should the bot ask for attendee name.
                // if called by confirmAttendee then skip this step.
                // if called by itself when can not find the last input, it will ask back or end this one when multiple try.
                UpdateUserName,

                // check if email. add email direct into attendee and set state.ConfirmedPerson null.
                // if not, search for the attendee.
                // if got multiple persons, call selectPerson. use replace
                // if got no person, replace/restart this flow.
                AfterUpdateUserName,
            };

            // select person, called bt updateName with replace.
            var selectPerson = new WaterfallStep[]
            {
                SelectPerson,
                AfterSelectPerson
            };

            // select email.
            // called by ConfirmEmail
            var selectEmail = new WaterfallStep[]
            {
                SelectEmail,
                AfterSelectEmail
            };

            AddDialog(new WaterfallDialog(Actions.ConfirmNameList, confirmNameList)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.LoopNameList, loopNameList)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.ConfirmAttendee, confirmAttendee)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.UpdateName, updateName)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.SelectPerson, selectPerson)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.SelectEmail, selectEmail)
            {
                TelemetryClient = telemetryClient
            });
            InitialDialogId = Actions.ConfirmNameList;
        }
コード例 #20
0
 public IActionResult AddPlot(PlotVm plot)
 {
     _service.AddPlot(plot);
     return(Ok(ResponseManager.GenerateResponse(null, (int)MessageType.Ok, plot)));
 }
コード例 #21
0
        public async Task <DialogTurnResult> UpdateUserName(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context);

                state.UnconfirmedPerson.Clear();
                state.ConfirmedPerson = null;
                var options = (UpdateUserNameDialogOptions)sc.Options;

                // if it is confirm no, thenask user to give a new attendee
                if (options.Reason == UpdateUserNameDialogOptions.UpdateReason.ConfirmNo)
                {
                    return(await sc.PromptAsync(
                               Actions.Prompt,
                               new PromptOptions
                    {
                        Prompt = ResponseManager.GetResponse(CreateEventResponses.NoAttendees)
                    }));
                }

                var currentRecipientName = state.CurrentAttendeeName;

                // if not initialize ask user for attendee
                if (options.Reason != UpdateUserNameDialogOptions.UpdateReason.Initialize)
                {
                    if (state.FirstRetryInFindContact)
                    {
                        state.FirstRetryInFindContact = false;
                        return(await sc.PromptAsync(
                                   Actions.Prompt,
                                   new PromptOptions
                        {
                            Prompt = ResponseManager.GetResponse(
                                FindContactResponses.UserNotFound,
                                new StringDictionary()
                            {
                                { "UserName", currentRecipientName }
                            })
                        }));
                    }
                    else
                    {
                        await sc.Context.SendActivityAsync(ResponseManager.GetResponse(
                                                               FindContactResponses.UserNotFoundAgain,
                                                               new StringDictionary()
                        {
                            { "source", state.EventSource == Models.EventSource.Microsoft ? "Outlook" : "Gmail" },
                            { "UserName", currentRecipientName }
                        }));

                        state.FirstRetryInFindContact = true;
                        state.CurrentAttendeeName     = string.Empty;
                        return(await sc.EndDialogAsync());
                    }
                }

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

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
コード例 #22
0
        protected async Task <DialogTurnResult> AddTask(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await ToDoStateAccessor.GetAsync(sc.Context);

                if (state.AddDupTask)
                {
                    state.ListType     = state.ListType ?? ToDoStrings.ToDo;
                    state.LastListType = state.ListType;
                    var service = await InitListTypeIds(sc);

                    var currentAllTasks = await service.GetTasksAsync(state.ListType);

                    var duplicatedTaskIndex = currentAllTasks.FindIndex(t => t.Topic.Equals(state.TaskContent, StringComparison.InvariantCultureIgnoreCase));

                    //if (state.TaskContentPattern.ToLower().Contains("on my way home"))
                    //{
                    var dateTime = new DateTime(
                        DateTime.Now.Year,
                        DateTime.Now.Month,
                        DateTime.Now.Day,
                        17,
                        0,
                        0);
                    await service.AddTaskAsync(state.ListType, state.TaskContent, dateTime);

                    //}
                    //else
                    //{
                    //	await service.AddTaskAsync(state.ListType, state.TaskContent);
                    //}

                    state.AllTasks = await service.GetTasksAsync(state.ListType);

                    state.ShowTaskPageIndex = 0;
                    var rangeCount = Math.Min(state.PageSize, state.AllTasks.Count);
                    state.Tasks = state.AllTasks.GetRange(0, rangeCount);
                    var toDoListCard = ToAdaptiveCardForTaskAddedFlow(
                        sc.Context,
                        state.Tasks,
                        state.TaskContent,
                        state.AllTasks.Count,
                        state.ListType);

                    toDoListCard.InputHint = InputHints.IgnoringInput;
                    await sc.Context.SendActivityAsync(toDoListCard);

                    return(await sc.NextAsync());
                }
                else
                {
                    await sc.Context.SendActivityAsync(ResponseManager.GetResponse(ToDoSharedResponses.ActionEnded));

                    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));
            }
        }
コード例 #23
0
        private async Task <PromptOptions> GenerateOptionsForName(WaterfallStepContext sc, List <CustomizedPerson> unionList, ITurnContext context, bool isSinglePage = true)
        {
            var state = await Accessor.GetAsync(context);

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

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

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

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

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

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

                if (skip <= 0)
                {
                    if (options.Choices.Count >= pageSize)
                    {
                        options.Prompt.Speak = SpeechUtility.ListToSpeechReadyString(options, ReadPreference.Chronological, ConfigData.GetInstance().MaxReadSize);
                        options.Prompt.Text  = GetSelectPromptString(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  = GetSelectPromptString(options, true);
            options.RetryPrompt  = ResponseManager.GetResponse(CalendarSharedResponses.DidntUnderstandMessage);
            return(options);
        }
コード例 #24
0
        public AddToDoItemDialog(
            BotSettings settings,
            BotServices services,
            ResponseManager responseManager,
            ConversationState conversationState,
            UserState userState,
            IServiceManager serviceManager,
            IBotTelemetryClient telemetryClient,
            MicrosoftAppCredentials appCredentials,
            IHttpContextAccessor httpContext)
            : base(nameof(AddToDoItemDialog), settings, services, responseManager, conversationState, userState, serviceManager, telemetryClient, appCredentials, httpContext)
        {
            TelemetryClient = telemetryClient;

            var addTask = new WaterfallStep[]
            {
                GetAuthToken,
                AfterGetAuthToken,
                ClearContext,
                DoAddTask,
            };

            var doAddTask = new WaterfallStep[]
            {
                CollectTaskContent,
                CollectSwitchListTypeConfirmation,
                CollectAddDupTaskConfirmation,
                AddTask,
                ContinueAddTask,
            };

            var collectTaskContent = new WaterfallStep[]
            {
                AskTaskContent,
                AfterAskTaskContent,
            };

            var collectSwitchListTypeConfirmation = new WaterfallStep[]
            {
                AskSwitchListTypeConfirmation,
                AfterAskSwitchListTypeConfirmation,
            };

            var collectAddDupTaskConfirmation = new WaterfallStep[]
            {
                AskAddDupTaskConfirmation,
                AfterAskAddDupTaskConfirmation,
            };

            var continueAddTask = new WaterfallStep[]
            {
                AskContinueAddTask,
                AfterAskContinueAddTask,
            };

            // Define the conversation flow using a waterfall model.
            AddDialog(new WaterfallDialog(Actions.DoAddTask, doAddTask)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.AddTask, addTask)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.CollectTaskContent, collectTaskContent)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.CollectSwitchListTypeConfirmation, collectSwitchListTypeConfirmation)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.CollectAddDupTaskConfirmation, collectAddDupTaskConfirmation)
            {
                TelemetryClient = telemetryClient
            });
            AddDialog(new WaterfallDialog(Actions.ContinueAddTask, continueAddTask)
            {
                TelemetryClient = telemetryClient
            });

            // Set starting dialog for component
            InitialDialogId = Actions.AddTask;
        }
コード例 #25
0
        protected async Task <DialogTurnResult> PromptToReshow(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                return(await sc.PromptAsync(Actions.Prompt, new PromptOptions { Prompt = ResponseManager.GetResponse(ShowEmailResponses.ReadOutMorePrompt) }));
            }
            catch (Exception ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
コード例 #26
0
        private async Task <DialogTurnResult> ShowEventsSummary(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var tokenResponse = sc.Result as TokenResponse;

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

                var options = sc.Options as ShowMeetingsDialogOptions;
                if (state.SummaryEvents == null)
                {
                    // this will lead to error when test
                    if (string.IsNullOrEmpty(state.APIToken))
                    {
                        state.Clear();
                        return(await sc.EndDialogAsync(true));
                    }

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

                    state.SummaryEvents = await GetMeetingToJoin(sc);
                }

                if (state.SummaryEvents.Count == 0)
                {
                    await sc.Context.SendActivityAsync(ResponseManager.GetResponse(JoinEventResponses.MeetingNotFound));

                    state.Clear();
                    return(await sc.EndDialogAsync(true));
                }
                else if (state.SummaryEvents.Count == 1)
                {
                    state.ConfirmedMeeting.Add(state.SummaryEvents.First());
                    return(await sc.ReplaceDialogAsync(Actions.ConfirmNumber, sc.Options));
                }

                // Multiple events
                var firstEvent = GetCurrentPageMeetings(state.SummaryEvents, state).First();

                var responseParams = new StringDictionary()
                {
                    { "EventName1", firstEvent.Title },
                    { "EventTime1", SpeakHelper.ToSpeechMeetingTime(TimeConverter.ConvertUtcToUserTime(firstEvent.StartTime, state.GetUserTimeZone()), firstEvent.IsAllDay == true) },
                    { "Participants1", DisplayHelper.ToDisplayParticipantsStringSummary(firstEvent.Attendees, 1) }
                };

                var reply = await GetGeneralMeetingListResponseAsync(sc, CalendarCommonStrings.MeetingsToJoin, GetCurrentPageMeetings(state.SummaryEvents, state), JoinEventResponses.SelectMeeting, responseParams);

                return(await sc.PromptAsync(Actions.Prompt, new PromptOptions()
                {
                    Prompt = reply
                }));
            }
            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));
            }
        }
コード例 #27
0
        protected async Task <DialogTurnResult> HandleMore(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await EmailStateAccessor.GetAsync(sc.Context);

                var luisResult = sc.Context.TurnState.Get <EmailLuis>(StateProperties.EmailLuisResult);
                var topIntent  = luisResult?.TopIntent().intent;

                var generalIntent    = sc.Context.TurnState.Get <General>(StateProperties.GeneralLuisResult);
                var topGeneralIntent = generalIntent?.TopIntent().intent;
                if (topIntent == null)
                {
                    return(await sc.EndDialogAsync(true));
                }

                sc.Context.Activity.Properties.TryGetValue("OriginText", out var content);
                var userInput = content != null?content.ToString() : sc.Context.Activity.Text;

                await DigestFocusEmailAsync(sc);

                var skillOptions = (EmailSkillDialogOptions)sc.Options;
                skillOptions.SubFlowMode = true;

                if (topIntent == EmailLuis.Intent.Delete)
                {
                    return(await sc.BeginDialogAsync(Actions.Delete, skillOptions));
                }
                else if (topIntent == EmailLuis.Intent.Forward)
                {
                    return(await sc.BeginDialogAsync(Actions.Forward, skillOptions));
                }
                else if (topIntent == EmailLuis.Intent.Reply)
                {
                    return(await sc.BeginDialogAsync(Actions.Reply, skillOptions));
                }
                else if (IsReadMoreIntent(topGeneralIntent, userInput) ||
                         (topIntent == EmailLuis.Intent.ShowNext || topIntent == EmailLuis.Intent.ShowPrevious || topGeneralIntent == General.Intent.ShowPrevious || topGeneralIntent == General.Intent.ShowNext))
                {
                    return(await sc.ReplaceDialogAsync(Actions.Display, skillOptions));
                }
                else
                {
                    await DigestEmailLuisResult(sc, true);
                    await SearchEmailsFromList(sc, cancellationToken);

                    if (state.MessageList.Count > 0)
                    {
                        return(await sc.ReplaceDialogAsync(Actions.DisplayFiltered, skillOptions));
                    }

                    await sc.Context.SendActivityAsync(ResponseManager.GetResponse(EmailSharedResponses.DidntUnderstandMessage));

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

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
コード例 #28
0
        private async Task <DialogTurnResult> AfterSelectEvent(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context);

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

                var generalLuisResult = state.GeneralLuisResult;
                var generalTopIntent  = generalLuisResult?.TopIntent().intent;

                if (topIntent == null)
                {
                    state.Clear();
                    return(await sc.CancelAllDialogsAsync());
                }

                if (generalTopIntent == General.Intent.ShowNext && state.SummaryEvents != null)
                {
                    if ((state.ShowEventIndex + 1) * state.PageSize < state.SummaryEvents.Count)
                    {
                        state.ShowEventIndex++;
                    }
                    else
                    {
                        await sc.Context.SendActivityAsync(ResponseManager.GetResponse(SummaryResponses.CalendarNoMoreEvent));
                    }

                    return(await sc.ReplaceDialogAsync(Actions.ConnectToMeeting, sc.Options));
                }
                else if (generalTopIntent == General.Intent.ShowPrevious && state.SummaryEvents != null)
                {
                    if (state.ShowEventIndex > 0)
                    {
                        state.ShowEventIndex--;
                    }
                    else
                    {
                        await sc.Context.SendActivityAsync(ResponseManager.GetResponse(SummaryResponses.CalendarNoPreviousEvent));
                    }

                    return(await sc.ReplaceDialogAsync(Actions.ConnectToMeeting, sc.Options));
                }

                sc.Context.Activity.Properties.TryGetValue("OriginText", out var content);
                var userInput = content != null?content.ToString() : sc.Context.Activity.Text;

                var promptRecognizerResult = ConfirmRecognizerHelper.ConfirmYesOrNo(userInput, sc.Context.Activity.Locale);
                if (promptRecognizerResult.Succeeded && promptRecognizerResult.Value == false)
                {
                    state.Clear();
                    return(await sc.CancelAllDialogsAsync());
                }
                else if (promptRecognizerResult.Succeeded && promptRecognizerResult.Value == true)
                {
                    var currentList = GetCurrentPageMeetings(state.SummaryEvents, state);
                    state.ConfirmedMeeting.Add(currentList.First());
                    return(await sc.ReplaceDialogAsync(Actions.ConfirmNumber, sc.Options));
                }
                else if (state.SummaryEvents.Count == 1)
                {
                    state.Clear();
                    return(await sc.CancelAllDialogsAsync());
                }

                if (state.SummaryEvents.Count > 1)
                {
                    var    filteredMeetingList = new List <EventModel>();
                    var    showMeetingReason   = ShowMeetingReason.FirstShowOverview;
                    string filterKeyWord       = null;

                    // filter meetings with number
                    if (luisResult.Entities.ordinal != null)
                    {
                        var value       = luisResult.Entities.ordinal[0];
                        var num         = int.Parse(value.ToString());
                        var currentList = GetCurrentPageMeetings(state.SummaryEvents, state);
                        if (num > 0 && num <= currentList.Count)
                        {
                            filteredMeetingList.Add(currentList[num - 1]);
                        }
                    }

                    if (filteredMeetingList.Count <= 0 && generalLuisResult.Entities.number != null && (luisResult.Entities.ordinal == null || luisResult.Entities.ordinal.Length == 0))
                    {
                        var value       = generalLuisResult.Entities.number[0];
                        var num         = int.Parse(value.ToString());
                        var currentList = GetCurrentPageMeetings(state.SummaryEvents, state);
                        if (num > 0 && num <= currentList.Count)
                        {
                            filteredMeetingList.Add(currentList[num - 1]);
                        }
                    }

                    // filter meetings with start time
                    var timeResult = RecognizeDateTime(userInput, sc.Context.Activity.Locale ?? English, false);
                    if (filteredMeetingList.Count <= 0 && timeResult != null)
                    {
                        foreach (var result in timeResult)
                        {
                            var dateTimeConvertTypeString = result.Timex;
                            var dateTimeConvertType       = new TimexProperty(dateTimeConvertTypeString);
                            if (result.Value != null || (dateTimeConvertType.Types.Contains(Constants.TimexTypes.Time) || dateTimeConvertType.Types.Contains(Constants.TimexTypes.DateTime)))
                            {
                                var dateTime = DateTime.Parse(result.Value);

                                if (dateTime != null)
                                {
                                    var utcStartTime = TimeZoneInfo.ConvertTimeToUtc(dateTime, state.GetUserTimeZone());
                                    foreach (var meeting in GetCurrentPageMeetings(state.SummaryEvents, state))
                                    {
                                        if (meeting.StartTime.TimeOfDay == utcStartTime.TimeOfDay)
                                        {
                                            showMeetingReason = ShowMeetingReason.ShowFilteredByTimeMeetings;
                                            filterKeyWord     = string.Format("H:mm", dateTime);
                                            filteredMeetingList.Add(meeting);
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // filter meetings with subject
                    if (filteredMeetingList.Count <= 0)
                    {
                        var subject = userInput;
                        if (luisResult.Entities.Subject != null)
                        {
                            subject = GetSubjectFromEntity(luisResult.Entities);
                        }

                        foreach (var meeting in GetCurrentPageMeetings(state.SummaryEvents, state))
                        {
                            if (meeting.Title.ToLower().Contains(subject.ToLower()))
                            {
                                showMeetingReason = ShowMeetingReason.ShowFilteredByTitleMeetings;
                                filterKeyWord     = subject;
                                filteredMeetingList.Add(meeting);
                            }
                        }
                    }

                    // filter meetings with contact name
                    if (filteredMeetingList.Count <= 0)
                    {
                        var contactNameList = new List <string>()
                        {
                            userInput
                        };
                        if (luisResult.Entities.personName != null)
                        {
                            contactNameList = GetAttendeesFromEntity(luisResult.Entities, userInput);
                        }

                        foreach (var meeting in GetCurrentPageMeetings(state.SummaryEvents, state))
                        {
                            var containsAllContacts = true;
                            foreach (var contactName in contactNameList)
                            {
                                if (!meeting.ContainsAttendee(contactName))
                                {
                                    containsAllContacts = false;
                                    break;
                                }
                            }

                            if (containsAllContacts)
                            {
                                showMeetingReason = ShowMeetingReason.ShowFilteredByParticipantNameMeetings;
                                filterKeyWord     = string.Join(", ", contactNameList);
                                filteredMeetingList.Add(meeting);
                            }
                        }
                    }

                    if (filteredMeetingList.Count == 1)
                    {
                        state.ReadOutEvents = filteredMeetingList;
                        return(await sc.BeginDialogAsync(Actions.ConfirmNumber, sc.Options));
                    }
                    else if (filteredMeetingList.Count > 1)
                    {
                        state.SummaryEvents        = filteredMeetingList;
                        state.FilterMeetingKeyWord = filterKeyWord;
                        return(await sc.ReplaceDialogAsync(Actions.ConnectToMeeting, new ShowMeetingsDialogOptions(showMeetingReason, sc.Options)));
                    }
                }

                if (state.ConfirmedMeeting != null && state.ConfirmedMeeting.Count > 0)
                {
                    return(await sc.ReplaceDialogAsync(Actions.ConfirmNumber, sc.Options));
                }
                else
                {
                    state.Clear();
                    return(await sc.CancelAllDialogsAsync());
                }
            }
            catch (Exception ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
コード例 #29
0
        /// <summary>
        /// Look up parking 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> GetParkingInterestPoints(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context);

                var mapsService        = 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.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.GetPointOfInterestListByQueryAsync(double.NaN, double.NaN, state.Address);

                    if (pointOfInterestAddressList.Any())
                    {
                        var pointOfInterest = pointOfInterestAddressList[0];
                        pointOfInterestList = await mapsService.GetPointOfInterestListByParkingCategoryAsync(pointOfInterest.Geolocation.Latitude, pointOfInterest.Geolocation.Longitude);

                        cards = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                    }
                    else
                    {
                        // Find parking lot near address
                        pointOfInterestList = await mapsService.GetPointOfInterestListByParkingCategoryAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude);

                        cards = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                    }
                }
                else
                {
                    // No entities identified, find nearby parking lots
                    pointOfInterestList = await mapsService.GetPointOfInterestListByParkingCategoryAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude);

                    cards = await GetPointOfInterestLocationCards(sc, pointOfInterestList);
                }

                if (cards.Count == 0)
                {
                    var replyMessage = ResponseManager.GetResponse(POISharedResponses.NoLocationsFound);
                    await sc.Context.SendActivityAsync(replyMessage);

                    return(await sc.EndDialogAsync());
                }
                else if (cards.Count == 1)
                {
                    pointOfInterestList[0].SubmitText = GetConfirmPromptTrue();

                    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));
                }
            }
            catch (Exception ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
コード例 #30
0
        public async Task <DialogTurnResult> AfterGetRecreateInfo(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context, cancellationToken : cancellationToken);

                if (sc.Result != null)
                {
                    var recreateState = sc.Result as RecreateEventState?;
                    switch (recreateState.Value)
                    {
                    case RecreateEventState.Cancel:
                        await sc.Context.SendActivityAsync(ResponseManager.GetResponse(CalendarSharedResponses.ActionEnded), cancellationToken);

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

                    case RecreateEventState.Time:
                        state.ClearTimes();
                        return(await sc.ReplaceDialogAsync(Actions.CreateEvent, options : sc.Options, cancellationToken : cancellationToken));

                    case RecreateEventState.Duration:
                        state.ClearTimesExceptStartTime();
                        return(await sc.ReplaceDialogAsync(Actions.CreateEvent, options : sc.Options, cancellationToken : cancellationToken));

                    case RecreateEventState.Location:
                        state.ClearLocation();
                        return(await sc.ReplaceDialogAsync(Actions.CreateEvent, options : sc.Options, cancellationToken : cancellationToken));

                    case RecreateEventState.Participants:
                        state.ClearParticipants();
                        return(await sc.ReplaceDialogAsync(Actions.CreateEvent, options : sc.Options, cancellationToken : cancellationToken));

                    case RecreateEventState.Subject:
                        state.ClearSubject();
                        return(await sc.ReplaceDialogAsync(Actions.CreateEvent, options : sc.Options, cancellationToken : cancellationToken));

                    case RecreateEventState.Content:
                        state.ClearContent();
                        return(await sc.ReplaceDialogAsync(Actions.CreateEvent, options : sc.Options, cancellationToken : cancellationToken));

                    default:
                        // should not go to this part. place an error handling for save.
                        await HandleDialogExceptions(sc, new Exception("Get unexpect state in recreate."));

                        return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
                    }
                }
                else
                {
                    // should not go to this part. place an error handling for save.
                    await HandleDialogExceptions(sc, new Exception("Get unexpect result in recreate."));

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

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }