/// <summary>
        /// we call for every turn while the topic is still active
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task <bool> ContinueTopic(IBotContext context)
        {
            // for messages
            if (context.Request.Type == ActivityTypes.Message)
            {
                switch (context.TopIntent?.Name)
                {
                case "showAlarms":
                    // allow show alarm to interrupt, but it's one turn, so we show the data without changing the topic
                    await new ShowAlarmsTopic().StartTopic(context);
                    return(await this.PromptForMissingData(context));

                case "help":
                    // show contextual help
                    context.ReplyWith(AddAlarmTopicView.HELP, this.Alarm);
                    return(await this.PromptForMissingData(context));

                case "cancel":
                    // prompt to cancel
                    context.ReplyWith(AddAlarmTopicView.CANCELPROMPT, this.Alarm);
                    this.TopicState = TopicStates.CancelConfirmation;
                    return(true);

                default:
                    return(await ProcessTopicState(context));
                }
            }
            return(true);
        }
        /// <summary>
        /// Called when the default topic is started
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task <bool> StartTopic(IBotContext context)
        {
            switch (context.Request.Type)
            {
            case ActivityTypes.ConversationUpdate:
            {
                // greet when added to conversation
                var activity = context.Request.AsConversationUpdateActivity();
                if (activity.MembersAdded.Where(m => m.Id == activity.Recipient.Id).Any())
                {
                    context.ReplyWith(DefaultTopicView.GREETING);
                    context.ReplyWith(DefaultTopicView.HELP);
                    this.Greeted = true;
                }
            }
            break;

            case ActivityTypes.Message:
                // greet on first message if we haven't already
                if (!Greeted)
                {
                    context.ReplyWith(DefaultTopicView.GREETING);
                    this.Greeted = true;
                }
                return(this.ContinueTopic(context));
            }
            return(Task.FromResult(true));
        }
        /// <summary>
        /// Shared method to get missing information
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private async Task <bool> PromptForMissingData(IBotContext context)
        {
            // If we don't have a title (or if its too long), prompt the user to get it.
            if (String.IsNullOrWhiteSpace(this.Alarm.Title))
            {
                this.TopicState = TopicStates.TitlePrompt;
                context.ReplyWith(AddAlarmTopicView.TITLEPROMPT, this.Alarm);
                return(true);
            }
            // if title exists but is not valid, then provide feedback and prompt again
            else if (this.Alarm.Title.Length < 1 || this.Alarm.Title.Length > 100)
            {
                this.Alarm.Title = null;
                this.TopicState  = TopicStates.TitlePrompt;
                context.ReplyWith(AddAlarmTopicView.TITLEVALIDATIONPROMPT, this.Alarm);
                return(true);
            }

            // If we don't have a time, prompt the user to get it.
            if (this.Alarm.Time == null)
            {
                this.TopicState = TopicStates.TimePrompt;
                context.ReplyWith(AddAlarmTopicView.TIMEPROMPTFUTURE, this.Alarm);
                return(true);
            }

            // ask for confirmation that we want to add it
            context.ReplyWith(AddAlarmTopicView.ADDCONFIRMATION, this.Alarm);
            this.TopicState = TopicStates.AddConfirmation;
            return(true);
        }
示例#4
0
        public async Task <bool> FindAlarm(IBotContext context)
        {
            var alarms = (List <Alarm>)context.State.User[UserProperties.ALARMS];

            if (alarms == null)
            {
                alarms = new List <Alarm>();
                context.State.User[UserProperties.ALARMS] = alarms;
            }

            // Ensure there are alarms to delete
            if (alarms.Count == 0)
            {
                context.ReplyWith(DeleteAlarmTopicView.NOALARMS);
                return(false);
            }

            // Validate title
            if (!String.IsNullOrWhiteSpace(this.AlarmTitle))
            {
                if (int.TryParse(this.AlarmTitle.Split(' ').FirstOrDefault(), out int index))
                {
                    if (index > 0 && index <= alarms.Count)
                    {
                        index--;
                        // Delete selected alarm and end topic
                        var alarm = alarms.Skip(index).First();
                        alarms.Remove(alarm);
                        context.ReplyWith(DeleteAlarmTopicView.DELETEDALARM, alarm);
                        return(false); // cancel topic
                    }
                }
                else
                {
                    var parts   = this.AlarmTitle.Split(' ');
                    var choices = alarms.FindAll(alarm => parts.Any(part => alarm.Title.Contains(part)));

                    if (choices.Count == 0)
                    {
                        context.ReplyWith(DeleteAlarmTopicView.NOALARMSFOUND, this.AlarmTitle);
                        return(false);
                    }
                    else if (choices.Count == 1)
                    {
                        // Delete selected alarm and end topic
                        var alarm = choices.First();
                        alarms.Remove(alarm);
                        context.ReplyWith(DeleteAlarmTopicView.DELETEDALARM, alarm);
                        return(false); // cancel topic
                    }
                }
            }

            // Prompt for title
            context.ReplyWith(DeleteAlarmTopicView.TITLEPROMPT, alarms);
            return(true);
        }
示例#5
0
        public static Task ShowAlarms(IBotContext context)
        {
            List <Alarm> alarms = GetAlarms(context);

            context.ReplyWith(ShowAlarmsTopicView.SHOWALARMS, alarms);
            return(Task.CompletedTask);
        }
 /// <summary>
 /// Called when this topic is resumed after being interrupted
 /// </summary>
 /// <param name="context"></param>
 /// <returns></returns>
 public Task <bool> ResumeTopic(IBotContext context)
 {
     // simply prompt again based on our state
     this.TopicState = TopicStates.AddingCard;
     context.ReplyWith(AddAlarmTopicView.STARTTOPIC, this.Alarm);
     return(Task.FromResult(true));
 }
        /// <summary>
        /// Continue the topic, method which is routed to while this topic is active
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task <bool> ContinueTopic(IBotContext context)
        {
            var activeTopic = (ITopic)context.State.Conversation[ConversationProperties.ACTIVETOPIC];

            switch (context.Request.Type)
            {
            case ActivityTypes.Message:
                switch (context.TopIntent?.Name)
                {
                case "addAlarm":
                    // switch to addAlarm topic
                    activeTopic = new AddAlarmTopic();
                    context.State.Conversation[ConversationProperties.ACTIVETOPIC] = activeTopic;
                    return(activeTopic.StartTopic(context));

                case "showAlarms":
                    // switch to show alarms topic
                    activeTopic = new ShowAlarmsTopic();
                    context.State.Conversation[ConversationProperties.ACTIVETOPIC] = activeTopic;
                    return(activeTopic.StartTopic(context));

                case "deleteAlarm":
                    // switch to delete alarm topic
                    activeTopic = new DeleteAlarmTopic();
                    context.State.Conversation[ConversationProperties.ACTIVETOPIC] = activeTopic;
                    return(activeTopic.StartTopic(context));

                case "help":
                    // show help
                    context.ReplyWith(DefaultTopicView.HELP);
                    return(Task.FromResult(true));

                default:
                    // show our confusion
                    context.ReplyWith(DefaultTopicView.CONFUSED);
                    return(Task.FromResult(true));
                }

            default:
                break;
            }
            return(Task.FromResult(true));
        }
        public static Task ShowAlarms(IBotContext context)
        {
            var alarms = (List <Alarm>)context.State.User[UserProperties.ALARMS];

            if (alarms == null)
            {
                alarms = new List <Alarm>();
                context.State.User[UserProperties.ALARMS] = alarms;
            }

            context.ReplyWith(ShowAlarmsTopicView.SHOWALARMS, alarms);
            return(Task.CompletedTask);
        }
        /// <summary>
        /// Called when the add alarm topic is started
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task <bool> StartTopic(IBotContext context)
        {
            var times = context.TopIntent?.Entities.Where(entity => entity.GroupName == "AlarmTime")
                        .Select(entity => DateTimeOffset.Parse(entity.ValueAs <string>()));

            this.Alarm = new Alarm()
            {
                // initialize from intent entities
                Title = context.TopIntent?.Entities.Where(entity => entity.GroupName == "AlarmTitle")
                        .Select(entity => entity.ValueAs <string>()).FirstOrDefault(),

                // initialize from intent entities
                Time = times.Where(t => t > DateTime.Now).FirstOrDefault()
            };
            if (Alarm.Time == default(DateTimeOffset))
            {
                // use today 1 HOUR as default
                var defaultTime = DateTimeOffset.Now + TimeSpan.FromHours(1);
                Alarm.Time = new DateTimeOffset(defaultTime.Year, defaultTime.Month, defaultTime.Day, defaultTime.Hour, 0, 0, DateTimeOffset.Now.Offset);
            }
            this.TopicState = TopicStates.AddingCard;
            context.ReplyWith(AddAlarmTopicView.STARTTOPIC, this.Alarm);
            return(true);
        }
示例#10
0
        private async Task <bool> ProcessTopicState(IBotContext context)
        {
            string utterance = (context.Request.AsMessageActivity().Text ?? "").Trim();

            // we ar eusing TopicState to remember what we last asked
            switch (this.TopicState)
            {
            case TopicStates.TitlePrompt:
                this.Alarm.Title = utterance;
                return(await this.PromptForMissingData(context));

            case TopicStates.TimePrompt:
                // take first one in the future
                this.Alarm.Time = ((BotContext)context).GetDateTimes().Where(t => t > DateTimeOffset.Now).FirstOrDefault();
                return(await this.PromptForMissingData(context));

            case TopicStates.CancelConfirmation:
                switch (context.TopIntent.Name)
                {
                case "confirmYes":
                    context.ReplyWith(AddAlarmTopicView.TOPICCANCELED, this.Alarm);
                    // End current topic
                    return(false);

                case "confirmNo":
                    // Re-prompt user for current field.
                    context.ReplyWith(AddAlarmTopicView.CANCELCANCELED, this.Alarm);
                    return(await this.PromptForMissingData(context));

                default:
                    // prompt again to confirm the cancelation
                    context.ReplyWith(AddAlarmTopicView.CANCELREPROMPT, this.Alarm);
                    return(true);
                }

            case TopicStates.AddConfirmation:
                switch (context.TopIntent?.Name)
                {
                case "confirmYes":
                    var alarms = (List <Alarm>)context.State.User[UserProperties.ALARMS];
                    if (alarms == null)
                    {
                        alarms = new List <Alarm>();
                        context.State.User[UserProperties.ALARMS] = alarms;
                    }
                    alarms.Add(this.Alarm);
                    context.ReplyWith(AddAlarmTopicView.ADDEDALARM, this.Alarm);
                    // end topic
                    return(false);

                case "confirmNo":
                    context.ReplyWith(AddAlarmTopicView.TOPICCANCELED, this.Alarm);
                    // End current topic
                    return(false);

                default:
                    return(await this.PromptForMissingData(context));
                }

            default:
                return(await this.PromptForMissingData(context));
            }
        }
示例#11
0
 /// <summary>
 /// Method which is called when this topic is resumed after an interruption
 /// </summary>
 /// <param name="context"></param>
 /// <returns></returns>
 public Task <bool> ResumeTopic(IBotContext context)
 {
     // just prompt the user to ask what they want to do
     context.ReplyWith(DefaultTopicView.RESUMETOPIC);
     return(Task.FromResult(true));
 }
示例#12
0
        private async Task <bool> ProcessTopicState(IBotContext context)
        {
            string utterance = (((Activity)context.Request).Text ?? "").Trim();

            // we ar eusing TopicState to remember what we last asked
            switch (this.TopicState)
            {
            case TopicStates.AddingCard:
            {
                dynamic payload = ((Activity)context.Request).Value;
                if (payload != null)
                {
                    if (payload.Action == "Submit")
                    {
                        this.Alarm.Title = payload.Title;
                        if (DateTimeOffset.TryParse((string)payload.Day, out DateTimeOffset date))
                        {
                            if (DateTimeOffset.TryParse((string)payload.Time, out DateTimeOffset time))
                            {
                                this.Alarm.Time = new DateTimeOffset(date.Year, date.Month, date.Day, time.Hour, time.Minute, time.Second, date.Offset);
                                var alarms = (List <Alarm>)context.State.User[UserProperties.ALARMS];
                                if (alarms == null)
                                {
                                    alarms = new List <Alarm>();
                                    context.State.User[UserProperties.ALARMS] = alarms;
                                }
                                alarms.Add(this.Alarm);
                                context.ReplyWith(AddAlarmTopicView.ADDEDALARM, this.Alarm);
                                // end topic
                                return(false);
                            }
                        }
                    }
                    else if (payload.Action == "Cancel")
                    {
                        context.ReplyWith(AddAlarmTopicView.TOPICCANCELED, this.Alarm);
                        // End current topic
                        return(false);
                    }
                }
            }
                return(true);

            case TopicStates.CancelConfirmation:
            {
                dynamic payload = ((Activity)context.Request).Value;
                switch (payload.Action)
                {
                case "Yes":
                {
                    context.ReplyWith(AddAlarmTopicView.TOPICCANCELED, this.Alarm);
                    // End current topic
                    return(false);
                }

                case "No":
                {
                    this.TopicState = TopicStates.AddingCard;
                    return(await this.ContinueTopic(context));
                }

                default:
                {
                    context.ReplyWith(AddAlarmTopicView.CANCELREPROMPT, this.Alarm);
                    return(true);
                }
                }
            }

            default:
                return(true);
            }
        }