Esempio n. 1
0
        protected override async Task OnEventAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
        {
            switch (dc.Context.Activity.Name)
            {
            case Events.SkillBeginEvent:
            {
                var state = await _stateAccessor.GetAsync(dc.Context, () => new CalendarSkillState());

                if (dc.Context.Activity.Value is Dictionary <string, object> userData)
                {
                    if (userData.TryGetValue("IPA.Timezone", out var timezone))
                    {
                        // we have a timezone
                        state.UserInfo.Timezone = (TimeZoneInfo)timezone;
                    }
                }

                break;
            }

            case Events.TokenResponseEvent:
            {
                // Auth dialog completion
                var result = await dc.ContinueDialogAsync();

                // If the dialog completed when we sent the token, end the skill conversation
                if (result.Status != DialogTurnStatus.Waiting)
                {
                    var response = dc.Context.Activity.CreateReply();
                    response.Type = ActivityTypes.EndOfConversation;

                    await dc.Context.SendActivityAsync(response);
                }

                break;
            }

            case Events.DeviceStart:
            {
                var skillOptions = new CalendarSkillDialogOptions
                {
                    SkillMode = _skillMode,
                };

                await dc.BeginDialogAsync(nameof(UpcomingEventDialog), skillOptions);

                break;
            }
            }
        }
        private async Task <DialogTurnResult> GetIntentSwitchingResult(WaterfallStepContext sc, CalendarLuis.Intent topIntent, CalendarSkillState state)
        {
            var newFlowOptions = new CalendarSkillDialogOptions()
            {
                SubFlowMode = false
            };

            if (topIntent == CalendarLuis.Intent.DeleteCalendarEntry || topIntent == CalendarLuis.Intent.AcceptEventEntry)
            {
                return(await sc.BeginDialogAsync(Actions.ChangeEventStatus));
            }
            else if (topIntent == CalendarLuis.Intent.ChangeCalendarEntry)
            {
                return(await sc.BeginDialogAsync(Actions.UpdateEvent));
            }
            else if (topIntent == CalendarLuis.Intent.CheckAvailability)
            {
                state.Clear();
                return(await sc.ReplaceDialogAsync(nameof(CheckPersonAvailableDialog), newFlowOptions));
            }
            else if (topIntent == CalendarLuis.Intent.ConnectToMeeting)
            {
                return(await sc.BeginDialogAsync(Actions.ConnectToMeeting));
            }
            else if (topIntent == CalendarLuis.Intent.CreateCalendarEntry)
            {
                state.Clear();
                return(await sc.ReplaceDialogAsync(nameof(CreateEventDialog), newFlowOptions));
            }
            else if (topIntent == CalendarLuis.Intent.FindCalendarDetail ||
                     topIntent == CalendarLuis.Intent.FindCalendarEntry ||
                     topIntent == CalendarLuis.Intent.FindCalendarWhen ||
                     topIntent == CalendarLuis.Intent.FindCalendarWhere ||
                     topIntent == CalendarLuis.Intent.FindCalendarWho ||
                     topIntent == CalendarLuis.Intent.FindDuration ||
                     topIntent == CalendarLuis.Intent.FindMeetingRoom)
            {
                state.Clear();
                return(await sc.ReplaceDialogAsync(nameof(ShowEventsDialog), new ShowMeetingsDialogOptions(ShowMeetingsDialogOptions.ShowMeetingReason.FirstShowOverview, newFlowOptions)));
            }
            else if (topIntent == CalendarLuis.Intent.TimeRemaining)
            {
                state.Clear();
                return(await sc.ReplaceDialogAsync(nameof(TimeRemainingDialog), newFlowOptions));
            }

            return(null);
        }
        private async Task <DialogTurnResult> UpdateEvent(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var options = new CalendarSkillDialogOptions()
                {
                    SubFlowMode = true
                };
                return(await sc.BeginDialogAsync(nameof(UpdateEventDialog), options));
            }
            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));
            }
        }
Esempio n. 4
0
        protected override async Task RouteAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await _stateAccessor.GetAsync(dc.Context, () => new CalendarSkillState());

            // get current activity locale
            var locale       = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
            var localeConfig = _services.LocaleConfigurations[locale];

            // Initialize the PageSize parameters in state from configuration
            InitializeConfig(state);

            // If dispatch result is general luis model
            localeConfig.LuisServices.TryGetValue("calendar", out var luisService);

            if (luisService == null)
            {
                throw new Exception("The specified LUIS Model could not be found in your Bot Services configuration.");
            }
            else
            {
                var result = await luisService.RecognizeAsync <Luis.Calendar>(dc.Context, CancellationToken.None);

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

                var skillOptions = new CalendarSkillDialogOptions
                {
                    SkillMode = _skillMode,
                };

                // switch on general intents
                switch (intent)
                {
                case Luis.Calendar.Intent.FindMeetingRoom:
                case Luis.Calendar.Intent.CreateCalendarEntry:
                {
                    await dc.BeginDialogAsync(nameof(CreateEventDialog), skillOptions);

                    break;
                }

                case Luis.Calendar.Intent.AcceptCalendarEntry:
                case Luis.Calendar.Intent.DeleteCalendarEntry:
                {
                    await dc.BeginDialogAsync(nameof(ChangeEventStatusDialog), skillOptions);

                    break;
                }

                case Luis.Calendar.Intent.ChangeCalendarEntry:
                {
                    await dc.BeginDialogAsync(nameof(UpdateEventDialog), skillOptions);

                    break;
                }

                case Luis.Calendar.Intent.ConnectToMeeting:
                {
                    await dc.BeginDialogAsync(nameof(ConnectToMeetingDialog), skillOptions);

                    break;
                }

                case Luis.Calendar.Intent.FindCalendarEntry:
                {
                    await dc.BeginDialogAsync(nameof(SummaryDialog), skillOptions);

                    break;
                }

                case Luis.Calendar.Intent.TimeRemaining:
                {
                    await dc.BeginDialogAsync(nameof(TimeRemainingDialog), skillOptions);

                    break;
                }

                case Luis.Calendar.Intent.None:
                {
                    if (generalTopIntent == General.Intent.Next || generalTopIntent == General.Intent.Previous)
                    {
                        await dc.BeginDialogAsync(nameof(SummaryDialog), skillOptions);
                    }
                    else
                    {
                        await dc.Context.SendActivityAsync(dc.Context.Activity.CreateReply(CalendarSharedResponses.DidntUnderstandMessage));

                        if (_skillMode)
                        {
                            await CompleteAsync(dc);
                        }
                    }

                    break;
                }

                default:
                {
                    await dc.Context.SendActivityAsync(dc.Context.Activity.CreateReply(CalendarMainResponses.FeatureNotAvailable));

                    if (_skillMode)
                    {
                        await CompleteAsync(dc);
                    }

                    break;
                }
                }
            }
        }
        // Handles routing to additional dialogs logic.
        private async Task <DialogTurnResult> RouteStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var a     = stepContext.Context.Activity;
            var state = await _stateAccessor.GetAsync(stepContext.Context, () => new CalendarSkillState());

            if (a.Type == ActivityTypes.Message && !string.IsNullOrEmpty(a.Text))
            {
                var luisResult = stepContext.Context.TurnState.Get <CalendarLuis>(StateProperties.CalendarLuisResultKey);
                var intent     = luisResult?.TopIntent().intent;
                state.InitialIntent = intent.Value;

                var generalResult = stepContext.Context.TurnState.Get <General>(StateProperties.GeneralLuisResultKey);
                var generalIntent = generalResult?.TopIntent().intent;

                InitializeConfig(state);

                var options = new CalendarSkillDialogOptions()
                {
                    SubFlowMode = false
                };

                // switch on general intents
                switch (intent)
                {
                case CalendarLuis.Intent.FindMeetingRoom:
                {
                    // check whether the meeting room feature supported.
                    if (!string.IsNullOrEmpty(_settings.AzureSearch?.SearchServiceName))
                    {
                        return(await stepContext.BeginDialogAsync(_bookMeetingRoomDialog.Id, options));
                    }
                    else
                    {
                        var activity = _templateEngine.GenerateActivityForLocale(CalendarMainResponses.FeatureNotAvailable);
                        await stepContext.Context.SendActivityAsync(activity);
                    }

                    break;
                }

                case CalendarLuis.Intent.AddCalendarEntryAttribute:
                {
                    // Determine the exact intent using entities
                    if (luisResult.Entities.MeetingRoom != null || luisResult.Entities.MeetingRoomPatternAny != null || CalendarCommonUtil.ContainMeetingRoomSlot(luisResult))
                    {
                        if (!string.IsNullOrEmpty(_settings.AzureSearch?.SearchServiceName))
                        {
                            return(await stepContext.BeginDialogAsync(_updateMeetingRoomDialog.Id, options));
                        }
                        else
                        {
                            var activity = _templateEngine.GenerateActivityForLocale(CalendarMainResponses.FeatureNotAvailable);
                            await stepContext.Context.SendActivityAsync(activity);
                        }
                    }
                    else
                    {
                        var activity = _templateEngine.GenerateActivityForLocale(CalendarMainResponses.FeatureNotAvailable);
                        await stepContext.Context.SendActivityAsync(activity);
                    }

                    break;
                }

                case CalendarLuis.Intent.CreateCalendarEntry:
                {
                    return(await stepContext.BeginDialogAsync(_createEventDialog.Id, options));
                }

                case CalendarLuis.Intent.AcceptEventEntry:
                {
                    return(await stepContext.BeginDialogAsync(_changeEventStatusDialog.Id, new ChangeEventStatusDialogOptions(options, EventStatus.Accepted)));
                }

                case CalendarLuis.Intent.DeleteCalendarEntry:
                {
                    if (luisResult.Entities.MeetingRoom != null || luisResult.Entities.MeetingRoomPatternAny != null || CalendarCommonUtil.ContainMeetingRoomSlot(luisResult))
                    {
                        if (!string.IsNullOrEmpty(_settings.AzureSearch?.SearchServiceName))
                        {
                            return(await stepContext.BeginDialogAsync(_updateMeetingRoomDialog.Id, options));
                        }
                        else
                        {
                            var activity = _templateEngine.GenerateActivityForLocale(CalendarMainResponses.FeatureNotAvailable);
                            await stepContext.Context.SendActivityAsync(activity);
                        }
                    }
                    else
                    {
                        return(await stepContext.BeginDialogAsync(_changeEventStatusDialog.Id, new ChangeEventStatusDialogOptions(options, EventStatus.Cancelled)));
                    }

                    break;
                }

                case CalendarLuis.Intent.ChangeCalendarEntry:
                {
                    if (luisResult.Entities.MeetingRoom != null || luisResult.Entities.MeetingRoomPatternAny != null || CalendarCommonUtil.ContainMeetingRoomSlot(luisResult))
                    {
                        if (!string.IsNullOrEmpty(_settings.AzureSearch?.SearchServiceName))
                        {
                            return(await stepContext.BeginDialogAsync(_updateMeetingRoomDialog.Id, options));
                        }
                        else
                        {
                            var activity = _templateEngine.GenerateActivityForLocale(CalendarMainResponses.FeatureNotAvailable);
                            await stepContext.Context.SendActivityAsync(activity);
                        }
                    }
                    else
                    {
                        return(await stepContext.BeginDialogAsync(_updateEventDialog.Id, options));
                    }

                    break;
                }

                case CalendarLuis.Intent.ConnectToMeeting:
                {
                    return(await stepContext.BeginDialogAsync(_joinEventDialog.Id, options));
                }

                case CalendarLuis.Intent.FindCalendarEntry:
                case CalendarLuis.Intent.FindCalendarDetail:
                case CalendarLuis.Intent.FindCalendarWhen:
                case CalendarLuis.Intent.FindCalendarWhere:
                case CalendarLuis.Intent.FindCalendarWho:
                case CalendarLuis.Intent.FindDuration:
                {
                    return(await stepContext.BeginDialogAsync(_showEventsDialog.Id, new ShowMeetingsDialogOptions(ShowMeetingsDialogOptions.ShowMeetingReason.FirstShowOverview, options)));
                }

                case CalendarLuis.Intent.TimeRemaining:
                {
                    return(await stepContext.BeginDialogAsync(_timeRemainingDialog.Id));
                }

                case CalendarLuis.Intent.CheckAvailability:
                {
                    if (luisResult.Entities.MeetingRoom != null || luisResult.Entities.MeetingRoomPatternAny != null || CalendarCommonUtil.ContainMeetingRoomSlot(luisResult))
                    {
                        if (!string.IsNullOrEmpty(_settings.AzureSearch?.SearchServiceName))
                        {
                            state.InitialIntent = CalendarLuis.Intent.FindMeetingRoom;
                            return(await stepContext.BeginDialogAsync(_bookMeetingRoomDialog.Id, options));
                        }
                        else
                        {
                            var activity = _templateEngine.GenerateActivityForLocale(CalendarMainResponses.FeatureNotAvailable);
                            await stepContext.Context.SendActivityAsync(activity);
                        }
                    }
                    else
                    {
                        return(await stepContext.BeginDialogAsync(_checkPersonAvailableDialog.Id));
                    }

                    break;
                }

                case CalendarLuis.Intent.ShowNextCalendar:
                case CalendarLuis.Intent.ShowPreviousCalendar:
                {
                    return(await stepContext.BeginDialogAsync(_showEventsDialog.Id, new ShowMeetingsDialogOptions(ShowMeetingsDialogOptions.ShowMeetingReason.FirstShowOverview, options)));
                }

                case CalendarLuis.Intent.None:
                {
                    if (generalIntent == General.Intent.ShowNext || generalIntent == General.Intent.ShowPrevious)
                    {
                        return(await stepContext.BeginDialogAsync(_showEventsDialog.Id, new ShowMeetingsDialogOptions(ShowMeetingsDialogOptions.ShowMeetingReason.FirstShowOverview, options)));
                    }
                    else
                    {
                        var activity = _templateEngine.GenerateActivityForLocale(CalendarSharedResponses.DidntUnderstandMessage);
                        await stepContext.Context.SendActivityAsync(activity);
                    }

                    break;
                }

                default:
                {
                    var activity = _templateEngine.GenerateActivityForLocale(CalendarMainResponses.FeatureNotAvailable);
                    await stepContext.Context.SendActivityAsync(activity);

                    break;
                }
                }
            }
            else if (a.Type == ActivityTypes.Event)
            {
                var ev = a.AsEventActivity();

                switch (stepContext.Context.Activity.Name)
                {
                case Events.DeviceStart:
                {
                    return(await stepContext.BeginDialogAsync(_upcomingEventDialog.Id));
                }

                default:
                {
                    await stepContext.Context.SendActivityAsync(new Activity(type : ActivityTypes.Trace, text : $"Unknown Event '{ev.Name ?? "undefined"}' was received but not processed."));

                    break;
                }
                }
            }

            // If activity was unhandled, flow should continue to next step
            return(await stepContext.NextAsync());
        }
        // Runs on every turn of the conversation to check if the conversation should be interrupted.
        protected async Task <bool> InterruptDialogAsync(DialogContext innerDc, CancellationToken cancellationToken)
        {
            var interrupted = false;
            var activity    = innerDc.Context.Activity;

            if (activity.Type == ActivityTypes.Message && !string.IsNullOrEmpty(activity.Text))
            {
                // Get connected LUIS result from turn state.
                var state = await _stateAccessor.GetAsync(innerDc.Context, () => new CalendarSkillState());

                var generalResult = innerDc.Context.TurnState.Get <General>(StateProperties.GeneralLuisResultKey);
                (var generalIntent, var generalScore) = generalResult.TopIntent();

                if (generalScore > 0.5)
                {
                    switch (generalIntent)
                    {
                    case General.Intent.Cancel:
                    {
                        await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale(CalendarMainResponses.CancelMessage));

                        await innerDc.CancelAllDialogsAsync();

                        await innerDc.BeginDialogAsync(InitialDialogId);

                        interrupted = true;
                        break;
                    }

                    case General.Intent.Help:
                    {
                        await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale(CalendarMainResponses.HelpMessage));

                        await innerDc.RepromptDialogAsync();

                        interrupted = true;
                        break;
                    }

                    case General.Intent.Logout:
                    {
                        // Log user out of all accounts.
                        await LogUserOut(innerDc);

                        await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale(CalendarMainResponses.LogOut));

                        await innerDc.CancelAllDialogsAsync();

                        await innerDc.BeginDialogAsync(InitialDialogId);

                        interrupted = true;
                        break;
                    }
                    }

                    if (!interrupted && innerDc.ActiveDialog != null)
                    {
                        var calendarLuisResult = innerDc.Context.TurnState.Get <CalendarLuis>(StateProperties.CalendarLuisResultKey);
                        var topCalendarIntent  = calendarLuisResult.TopIntent();

                        if (topCalendarIntent.score > 0.9 && !CalendarCommonUtil.IsFindEventsDialog(state.InitialIntent))
                        {
                            var intentSwitchingResult = CalendarCommonUtil.CheckIntentSwitching(topCalendarIntent.intent);
                            var newFlowOptions        = new CalendarSkillDialogOptions()
                            {
                                SubFlowMode = false
                            };

                            if (intentSwitchingResult != CalendarLuis.Intent.None)
                            {
                                state.Clear();
                                await innerDc.CancelAllDialogsAsync();

                                state.InitialIntent = intentSwitchingResult;

                                switch (intentSwitchingResult)
                                {
                                case CalendarLuis.Intent.DeleteCalendarEntry:
                                    await innerDc.BeginDialogAsync(nameof(ChangeEventStatusDialog), new ChangeEventStatusDialogOptions(newFlowOptions, EventStatus.Cancelled));

                                    interrupted = true;
                                    break;

                                case CalendarLuis.Intent.AcceptEventEntry:
                                    await innerDc.BeginDialogAsync(nameof(ChangeEventStatusDialog), new ChangeEventStatusDialogOptions(newFlowOptions, EventStatus.Accepted));

                                    interrupted = true;
                                    break;

                                case CalendarLuis.Intent.ChangeCalendarEntry:
                                    await innerDc.BeginDialogAsync(nameof(UpdateEventDialog), newFlowOptions);

                                    interrupted = true;
                                    break;

                                case CalendarLuis.Intent.CheckAvailability:
                                    await innerDc.BeginDialogAsync(nameof(CheckPersonAvailableDialog), newFlowOptions);

                                    interrupted = true;
                                    break;

                                case CalendarLuis.Intent.ConnectToMeeting:
                                    await innerDc.BeginDialogAsync(nameof(JoinEventDialog), newFlowOptions);

                                    interrupted = true;
                                    break;

                                case CalendarLuis.Intent.CreateCalendarEntry:
                                    await innerDc.BeginDialogAsync(nameof(CreateEventDialog), newFlowOptions);

                                    interrupted = true;
                                    break;

                                case CalendarLuis.Intent.FindCalendarDetail:
                                case CalendarLuis.Intent.FindCalendarEntry:
                                case CalendarLuis.Intent.FindCalendarWhen:
                                case CalendarLuis.Intent.FindCalendarWhere:
                                case CalendarLuis.Intent.FindCalendarWho:
                                case CalendarLuis.Intent.FindDuration:
                                    await innerDc.BeginDialogAsync(nameof(ShowEventsDialog), new ShowMeetingsDialogOptions(ShowMeetingsDialogOptions.ShowMeetingReason.FirstShowOverview, newFlowOptions));

                                    interrupted = true;
                                    break;

                                case CalendarLuis.Intent.TimeRemaining:
                                    await innerDc.BeginDialogAsync(nameof(TimeRemainingDialog), newFlowOptions);

                                    interrupted = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            return(interrupted);
        }
Esempio n. 7
0
        protected override async Task RouteAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await _stateAccessor.GetAsync(dc.Context, () => new CalendarSkillState());

            // get current activity locale
            var locale       = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
            var localeConfig = _services.CognitiveModelSets[locale];

            await PopulateStateFromSemanticAction(dc.Context);

            // Initialize the PageSize parameters in state from configuration
            InitializeConfig(state);

            // If dispatch result is general luis model
            localeConfig.LuisServices.TryGetValue("Calendar", out var luisService);

            var options = new CalendarSkillDialogOptions()
            {
                SubFlowMode = false
            };

            if (luisService == null)
            {
                throw new Exception("The specified LUIS Model could not be found in your Bot Services configuration.");
            }
            else
            {
                var intent           = state.LuisResult?.TopIntent().intent;
                var generalTopIntent = state.GeneralLuisResult?.TopIntent().intent;

                // switch on general intents
                switch (intent)
                {
                case CalendarLuis.Intent.FindMeetingRoom:
                case CalendarLuis.Intent.CreateCalendarEntry:
                {
                    await dc.BeginDialogAsync(nameof(CreateEventDialog), options);

                    break;
                }

                case CalendarLuis.Intent.AcceptEventEntry:
                {
                    await dc.BeginDialogAsync(nameof(ChangeEventStatusDialog), new ChangeEventStatusDialogOptions(options, EventStatus.Accepted));

                    break;
                }

                case CalendarLuis.Intent.DeleteCalendarEntry:
                {
                    await dc.BeginDialogAsync(nameof(ChangeEventStatusDialog), new ChangeEventStatusDialogOptions(options, EventStatus.Cancelled));

                    break;
                }

                case CalendarLuis.Intent.ChangeCalendarEntry:
                {
                    await dc.BeginDialogAsync(nameof(UpdateEventDialog), options);

                    break;
                }

                case CalendarLuis.Intent.ConnectToMeeting:
                {
                    await dc.BeginDialogAsync(nameof(JoinEventDialog), options);

                    break;
                }

                case CalendarLuis.Intent.FindCalendarEntry:
                case CalendarLuis.Intent.FindCalendarDetail:
                case CalendarLuis.Intent.FindCalendarWhen:
                case CalendarLuis.Intent.FindCalendarWhere:
                case CalendarLuis.Intent.FindCalendarWho:
                case CalendarLuis.Intent.FindDuration:
                {
                    await dc.BeginDialogAsync(nameof(ShowEventsDialog), new ShowMeetingsDialogOptions(ShowMeetingsDialogOptions.ShowMeetingReason.FirstShowOverview, options));

                    break;
                }

                case CalendarLuis.Intent.TimeRemaining:
                {
                    await dc.BeginDialogAsync(nameof(TimeRemainingDialog));

                    break;
                }

                case CalendarLuis.Intent.ShowNextCalendar:
                case CalendarLuis.Intent.ShowPreviousCalendar:
                {
                    await dc.BeginDialogAsync(nameof(ShowEventsDialog), new ShowMeetingsDialogOptions(ShowMeetingsDialogOptions.ShowMeetingReason.FirstShowOverview, options));

                    break;
                }

                case CalendarLuis.Intent.None:
                {
                    if (generalTopIntent == General.Intent.ShowNext || generalTopIntent == General.Intent.ShowPrevious)
                    {
                        await dc.BeginDialogAsync(nameof(ShowEventsDialog), new ShowMeetingsDialogOptions(ShowMeetingsDialogOptions.ShowMeetingReason.FirstShowOverview, options));
                    }
                    else
                    {
                        await dc.Context.SendActivityAsync(_responseManager.GetResponse(CalendarSharedResponses.DidntUnderstandMessage));
                    }

                    break;
                }

                default:
                {
                    await dc.Context.SendActivityAsync(_responseManager.GetResponse(CalendarMainResponses.FeatureNotAvailable));

                    break;
                }
                }
            }
        }