public bool PersistIncommingTwillioMessage(string twilioMessageUrl)
        {
            NameValueCollection vals = HttpUtility.ParseQueryString(twilioMessageUrl);

            var twilioMessage = new TwilioMessageSM
            {
                From = vals["From"],
                Body = vals["body"],
            };

            if (twilioMessage.Body == null)
            {
                _log.Warning("twilioMessage body is null, unable to process.");
                return false;
            }
            if (twilioMessage.From == null)
            {
                _log.Warning("twilioMessage From is null, unable to process.");
                return false;
            }

            var txt = new TxtMsgInbound
            {
                MobilePhone = twilioMessage.From,
                Message = twilioMessage.Body,
                State = TxtMsgProcessState.New,
            };
            _txtMsgInboundDal.Insert(txt);

            return true;
        }
        public IHttpActionResult SendSimulatedInboundMessage([FromBody] SimulatedInboundTxt simMsg)
        {
            var txt = new TxtMsgInbound
            {
                MobilePhone = simMsg.FromMobilePhone,
                Message = simMsg.Message
            };

            _smsSimulatorRepository.InsertInbound(txt);
            return Ok();
        }
 private void ProcessInviteCommand(TxtMsgInbound msgInbound, AppUser user)
 {
     if (user.UserRole != UserRole.Parent)
     {
         //STEP - make sure user is a Parent, if not say only parents can invite sitters.
         _omm.SendFeedbackToInboundMessage(msgInbound, MessageTemplates.OnlyParentsCanSendSignupInvites(), user.Id);
     }
     else
     {
         _omm.SendFeedbackToInboundMessageAndAwait(msgInbound, "Ok, I'll invite someone to join your MySitters. What is their mobile number?", user.Id, InboundMessageType.SignupInvite);
     }
 }
        public void ProcessNewConverastion(TxtMsgInbound msgInbound)
        {
            // STEP - Check if user is member
            AppUser user = _appUserDal.GetByMobile(msgInbound.MobilePhone);
            if (user == null)
            {
                if (msgInbound.Message == NewCommandType.signup.ToString())
                {
                    ProcessSignupCommand(msgInbound, null);
                    return;
                }

                string msg = "To signup for mysitterhub.com, say 'signup' or go to the website";
                _omm.SendFeedbackToInboundMessage(msgInbound, msg, AppUser.NotSignedUpUserId);
                return;
            }

            NewCommandType newCommand;
            Enum.TryParse(msgInbound.Message, out newCommand);

            switch (newCommand)
            {
                case NewCommandType.unrecognized:
                    _omm.SendFeedbackToInboundMessage(msgInbound, "mysitterhub.com " + MessageTemplates.FormatValidCommands(user.UserRole), user.Id);
                    break;
                case NewCommandType.job:
                    ProcessPostJobCommand(msgInbound, user);
                    break;
                case NewCommandType.help:
                    ProcessHelpCommand(msgInbound, user);
                    break;
                case NewCommandType.invite:
                    ProcessInviteCommand(msgInbound, user);
                    break;
                case NewCommandType.status:
                    ProcessStatusCommand(msgInbound, user);
                    break;
                case NewCommandType.signup:
                    ProcessSignupCommand(msgInbound, user);
                    break;
                default:
                    throw new Exception("command not implimented: " + newCommand);
            }
        }
 public void ProcessSelfSignupConversation_Step2(TxtMsgInbound msgInbound, TxtMsgAwaitingResponse awaiting, AppUser user)
 {
 }
        public void ProcessPostJobConversation(TxtMsgInbound msgInbound, TxtMsgAwaitingResponse awaiting, AppUser parentUser)
        {
            string conversationContext;
            string msg;

            if (MessageUtility.IsCancelRequested(msgInbound))
            {
                msg = "Ok, job posting cancelled";
                _omm.SendFeedbackToInboundMessageAndDeleteAwaiting(msgInbound, msg, parentUser.Id, awaiting);
            }

            switch (msgInbound.InboundMessageType)
            {
                case InboundMessageType.PostJob_Step2_DayOfWeek:
                    DayOfWeekMessage? dayOfWeek = MessageUtility.ParseDayOfWeek(msgInbound.Message);
                    if (dayOfWeek == null)
                    {
                        msg = string.Format("Invalid day of week, post a job for which day: {0}? Or say 'cancel'", new NewCommandManager().DaysOfWeekStartingToday(parentUser));
                        _omm.SendFeedbackToInboundMessage(msgInbound, msg, parentUser.Id);
                    }
                    else
                    {
                        conversationContext = JsonSerializerHelper.Serialize(new PostJobViaTxtAnswers {DayOfWeek = dayOfWeek.Value});
                        msg = "What time?";
                        _omm.SendFeedbackToInboundMessageAndAwait(msgInbound, msg, parentUser.Id, InboundMessageType.PostJob_Step3_StartTime, awaiting, conversationContext);
                    }
                    break;
                case InboundMessageType.PostJob_Step3_StartTime:
                    JobTimeSmall startHour = MessageUtility.ParseStartTime(msgInbound.Message, _log);
                    if (startHour == null)
                    {
                        msg = string.Format("Please enter a valid job start time. Valid examples: 9am, 9pm, 12:30am, 10:00pm. What time?");
                        _omm.SendFeedbackToInboundMessage(msgInbound, msg, parentUser.Id);
                    }
                    else
                    {
                        var postJobAnswers = JsonSerializerHelper.DeSerialize<PostJobViaTxtAnswers>(awaiting.ConversationMemory);
                        postJobAnswers.StartHour = startHour;
                        conversationContext = JsonSerializerHelper.Serialize(postJobAnswers);
#if OFF
                        var sits = ListSittersForParent(msgInbound.UserId);
                        if (sits == null)
                        {
                            msg = "Unable to post job because you do not have any sitters. Please invite babysitters to your MySitters."; //FutureDev: do this earlier
                            _omm.SendFeedbackToInboundMessage(msgInbound, msg);
                            _txtMsgAwaitingResponseDal.DeleteAwaiting(awaiting.Id);
                        }
                        else
                        {
                            newAwaitingType = InboundMessageType.PostJob_Step5_Confirm;
                            msg = string.Format("Which sitters? {0}", sits);
                        }
#endif
                        msg = MessageUtility.FormatJobConfirm(postJobAnswers, parentUser, _parentRepository);
                        _omm.SendFeedbackToInboundMessageAndAwait(msgInbound, msg, parentUser.Id, InboundMessageType.PostJob_Step5_Confirm, awaiting, conversationContext);
                    }
                    break;
#if OFF
                case InboundMessageType.PostJob_Step4_SelectSitters:
                    int? sitterId = ParseSitterNum(msgInbound.Message, msgInbound.UserId);

#endif

                case InboundMessageType.PostJob_Step5_Confirm:
                    MessageAffirmativeType affirmative = MessageUtility.ParseAffirmativeType(msgInbound, true);

                    if (affirmative == MessageAffirmativeType.yes)
                    {
                        var pa = JsonSerializerHelper.DeSerialize<PostJobViaTxtAnswers>(awaiting.ConversationMemory);

                        var jobSM = new PostJobSM();


                        jobSM.DateTimeStartDte = MessageUtility.CalcJobStartTime(pa).AddHours(- parentUser.TimezoneOffset); // Convert to UTC
                        jobSM.Duration = 3; // note, default to 3
                        jobSM.JobInvites = new List<JobInvite>();
                        List<ParentMySitterSM> psitters = _parentRepository.GetSittersForParent(parentUser.Id).Sitters;
                        foreach (ParentMySitterSM s in psitters)
                        {
                            jobSM.JobInvites.Add(new JobInvite { SitterId = s.Id, InvitedDate = TimeUtil.GetCurrentUtcTime(), RatePerHour = s.Rate, State = InvitationState.InvitePending });
                        }

                        jobSM.ParentId = parentUser.Id;
                        _jobRepo.PostJob(jobSM);

                        _omm.SendFeedbackToInboundMessageAndDeleteAwaiting(msgInbound, "Congrats! Job posted. You can view details at mysitterhub.com", parentUser.Id, awaiting);
                    }
                    else if (affirmative == MessageAffirmativeType.no)
                    {
                        _omm.SendFeedbackToInboundMessageAndDeleteAwaiting(msgInbound, "Ok, Job posting cancelled", parentUser.Id, awaiting); //note, this will only get hit when the user says "no".
                    }
                    else
                    {
                        _omm.SendFeedbackToInboundMessage(msgInbound, "Please say 'yes' to post job or 'cancel'", parentUser.Id);
                    }

                    break;
                default:
                    throw new Exception("InboundMessageType not recognized in ProcessPostJobConversation. " + msgInbound.InboundMessageType);
            }
        }
        public void ProcessSitterResonseToJobPosting(TxtMsgInbound msgInbound, TxtMsgAwaitingResponse awaiting, AppUser user)
        {
            string feedback = null;
            bool stillAwaiting = true;
            Job job = _jobRepo.GetById(awaiting.JobId);

            if (job == null)
            {
                string msgError = "Unable to find job with id " + awaiting.JobId;
                _log.Error(msgInbound.MobilePhone, msgError, null);
                _txtMsgInboundDal.UpdateState(msgInbound.Id, TxtMsgProcessState.Error, msgError);
                _txtMsgAwaitingResponseDal.DeleteAwaiting(awaiting.Id);
                return;
            }
            var response = new SitterJobInviteResponseSM
            {
                JobId = job.Id,
                SitterId = awaiting.WaitingForUserId,
                Message = msgInbound.Message
            };

            MessageAffirmativeType aff = MessageUtility.ParseAffirmativeType(msgInbound);

            if (aff == MessageAffirmativeType.yes)
            {
                response.Response = SitterResponse.Accept;
                feedback = MessageTemplates.FormatSitterAcceptJob();
                stillAwaiting = false;
            }
            else if (aff == MessageAffirmativeType.no)
            {
                response.Response = SitterResponse.Decline;
                feedback = MessageTemplates.FormatSitterDeclineJob("parent"); //TODO
                stillAwaiting = false;
            }
            else
            {
                response.Response = SitterResponse.Unrecognized;
                feedback = MessageTemplates.FormatSitterInvalidResponseToJobOrSignup(true);
                stillAwaiting = true;
            }
            _jobRepo.ProcessSitterResponse(response, job);


            _txtMsgInboundDal.UpdateState(msgInbound.Id, TxtMsgProcessState.Processed);

            if (feedback != null)
            {
                _omm.SendFeedbackToInboundMessage(msgInbound, feedback, user.Id);
            }

            if (!stillAwaiting)
            {
                _txtMsgAwaitingResponseDal.DeleteAwaiting(awaiting.Id);
            }

            if (aff == MessageAffirmativeType.yes && job != null)
            {
                try
                {
                    // STEP - Send confirm to parent, and closed notice to other sitters
                    _omm.SendNoticeOfSitterAccept(job);
                }
                catch (Exception ex)
                {
                    _log.Error(job.ParentId.ToString(), "error while SendParentNoticeOfSitterAccept(). msgInbound.Id:" + msgInbound.Id, ex);
                    throw;
                }
            }
        }
        public void ProcessSelfSignupConversation_Step1(TxtMsgInbound msgInbound, TxtMsgAwaitingResponse awaiting, AppUser user)
        {
            bool deleteAwaiting = true;
            if (MessageUtility.IsCancelRequested(msgInbound))
            {
                _omm.SendFeedbackToInboundMessage(msgInbound, "Ok, signup cancelled", user.Id);
            }
            else if (msgInbound.Message == "sitter" || msgInbound.Message == "parent" || msgInbound.Message == "babysitter")
            {
                bool isSitter = (msgInbound.Message == "sitter" || msgInbound.Message == "babysitter");
                // STEP - Create new AppUser
                var newUser = new SignupInfo
                {
                    User = new AppUser
                    {
                        FirstName = "New Self Signup",
                        LastName = "",
                        Email = "",
                        MobilePhone = msgInbound.MobilePhone,
                        UserRole = isSitter ? UserRole.Sitter : UserRole.Parent,
                    },
                    Pass = GeneratePassForNewUser()
                };
                if (isSitter)
                {
                    newUser.SitterSignupInfo = new SitterSignupInfo {ParentEmail = "", ParentMobile = ""};
                }

                SignupResult result = new SignupRepository().SaveNewSignup(newUser, false);
                if (result.IsSuccess)
                {
                    _omm.SendFeedbackToInboundMessage(msgInbound, string.Format("Ok, you have signed up for mysitterhub.com, you can login at mysitterhub.com with your mobile number and password: {0}.", newUser.Pass), user.Id);
                    //_omm.SendFeedbackToInboundMessage(msgInbound, string.Format("You can finish filling out your profile. What is your name? Or say 'cancel'."));
                    //_txtMsgAwaitingResponseDal.Insert(new TxtMsgAwaitingResponse(outboundTxtMsgId, 0, msgInbound.MobilePhone, InboundMessageType.SelfSignup_Step2_Name, 0)); //FutureDev
                }
                else
                {
                    _omm.SendFeedbackToInboundMessage(msgInbound, string.Format("Error while signing up:" + result.Error), user.Id);
                    new LogUtil().LogMessage("signup unsuccessful " + result.Error);
                    deleteAwaiting = false;
                }
            }
            else
            {
                _omm.SendFeedbackToInboundMessage(msgInbound, string.Format("Invalid response, are you a 'parent' or a 'sitter'? Or say 'cancel' to quit the signup process."), user.Id);
                deleteAwaiting = false;
            }

            if (deleteAwaiting)
                _txtMsgAwaitingResponseDal.DeleteAwaiting(awaiting.Id);
        }
 public void SendFeedbackToInboundMessageAndDeleteAwaiting(TxtMsgInbound msgInbound, string feedback, int senderId, TxtMsgAwaitingResponse previousAwaitingMsgToDelete)
 {
     SendFeedbackToInboundMessage(msgInbound, feedback, senderId);
     _txtMsgAwaitingResponseDal.DeleteAwaiting(previousAwaitingMsgToDelete.Id);
 }
        public void ProcessSignupInviteConversation(TxtMsgInbound msgInbound, TxtMsgAwaitingResponse awaiting, AppUser user)
        {
            string mobileToInvite = PhoneUtil.CleanAndEnsureCountryCode(msgInbound.Message);
            if (MessageUtility.IsCancelRequested(msgInbound))
            {
                _omm.SendFeedbackToInboundMessageAndDeleteAwaiting(msgInbound, string.Format("Ok, invitation cancelled."), user.Id, awaiting);
                return;
            }
            if (!PhoneUtil.IsValidPhoneNumber(mobileToInvite))
            {
                _omm.SendFeedbackToInboundMessage(msgInbound, string.Format("'{0}' is not a valid mobile number to invite to signup for mysitterhub.com. Please enter 10 digit number. Or say 'cancel'.", msgInbound.Message), user.Id);
                return;
            }

            int parentId = awaiting.WaitingForUserId;
            AppUser parentUser = new AppUserDal().GetById(parentId);

            if (parentUser.UserRole != UserRole.Parent)
            {
                //STEP - make sure user is a Parent, if not say only parents can invite sitters.
                _omm.SendFeedbackToInboundMessage(msgInbound, MessageTemplates.OnlyParentsCanSendSignupInvites(), user.Id);
            }
            else
            {
                //STEP - confirm sending invite
                _omm.SendFeedbackToInboundMessage(msgInbound, "Sending invite to " + mobileToInvite, user.Id);
                var sitterInvite = new InviteToSignup {MobilePhone = mobileToInvite};
                ServiceResult result = new ParentRepository().AddSitterInviteByMobile(parentId, sitterInvite);
                if (!result.IsSuccess)
                {
                    _omm.SendFeedbackToInboundMessage(msgInbound, "Error while sending invite to " + mobileToInvite + " please try again.", user.Id);
                }
            }
            _txtMsgAwaitingResponseDal.DeleteAwaiting(awaiting.Id);
        }
        public string SendFeedbackToInboundMessage(TxtMsgInbound msgInbound, string feedback, int senderId)
        {
            var txtFeedback = new TxtMsgOutbound
            {
                MobilePhone = msgInbound.MobilePhone,
                Message = feedback,
                OutboundMessageType = OutboundMessageType.Feeback,
                SenderId = senderId,
                MessageDate =  TimeUtil.GetCurrentUtcTime()
            };

            return _smsOutboundRepo.QueueSmsForSend(txtFeedback);
        }
 private void ProcessStatusCommand(TxtMsgInbound msgInbound, AppUser user)
 {
     _omm.SendFeedbackToInboundMessage(msgInbound, "Ok, I'll list your jobs. Your open jobs are..", user.Id);
     //FutureDev: implement
 }
        public void ProcessResponseToSignupInvite(TxtMsgInbound msgInbound, TxtMsgAwaitingResponse awaiting, AppUser user)
        {
            MessageAffirmativeType affirmativeType = MessageUtility.ParseAffirmativeType(msgInbound);
            string feedback = null;
            Parent parent = _parentRepository.GetById(awaiting.ParentId, true);
            if (parent == null)
                throw new Exception("Error while processing inbound message. Parent not found with ID" + awaiting.ParentId);
            // If user answers 'yes'.
            if (affirmativeType == MessageAffirmativeType.yes)
            {
                // If user already exists we simply add hib to parent's sitterhub.
                if (user != null)
                {
                    if (user.UserRole == UserRole.Sitter)
                    {
                        // ..sure if this user is a sitter.
                        AddSitterToParentMySitters(user.Id, parent, msgInbound.MobilePhone);
                        feedback = MessageTemplates.FormatUserAddedToSitters(parent);
                    }
                    else
                    {
                        // Otherwise we cannot add user because he is not a sitter.
                        feedback = MessageTemplates.FormatInvitedUserIsNotASitter();
                    }
                }
                    // If user doesn't exist we need to create new one.
                else
                {
                    // Create new (default) sitter profile.
                    var newSitter = new SignupInfo
                    {
                        User = new AppUser
                        {
                            FirstName = "New Sitter",
                            LastName = "",
                            Email = "",
                            MobilePhone = msgInbound.MobilePhone,
                            UserRole = UserRole.Sitter,
                        },
                        Pass = GeneratePassForNewUser() //FutureDev: text this password to sitter as their new temp password.
                    };
                    newSitter.SitterSignupInfo = new SitterSignupInfo {ParentEmail = "", ParentMobile = ""};

                    SignupResult result = new SignupRepository().SaveNewSignup(newSitter, false, false);
                    if (!result.IsSuccess)
                        throw new Exception("Failed to create new profile for sitter during parent invite." + result.Error);
                    // If there were no errors we can continue.
                    // We need to add newly created user into parent's sitterhub.
                    AddSitterToParentMySitters(result.NewId, parent, msgInbound.MobilePhone);
                    // Send message about new account created and user successfully added to parent's hub.
                    feedback = MessageTemplates.FormatUserAddedToSittersAndProfileCreated(parent, newSitter.Pass);
                }
            }
                // If user answered 'no'.
            else if (affirmativeType == MessageAffirmativeType.no)
            {
                // TODO: separate failure message.
                // We send message to sitter that we didn't added him to parent's hub.
                feedback = MessageTemplates.FormatDeclineInvitationToSitterhub(parent);
                _parentRepository.CancelInviteSitter(parent.Id, msgInbound.MobilePhone, true);
            }
                // If user's answer can't be parsed.
            else
            {
                feedback = MessageTemplates.FormatSitterInvalidResponseToJobOrSignup(false);
            }
            // Update state of message.
            _txtMsgInboundDal.UpdateState(msgInbound.Id, TxtMsgProcessState.Processed);
            // If sitter's answer was successfully parsed we can mark this message as processed.
            if (affirmativeType != MessageAffirmativeType.Unknown)
            {
                _txtMsgAwaitingResponseDal.DeleteAwaiting(awaiting.Id);
            }
            // TODO: where we send messages to parent? Seems like we can do it here.
            if (feedback != null)
            {
                _omm.SendFeedbackToInboundMessage(msgInbound, feedback, user.Id);
            }
        }
        public void ProcessPostJobCommand(TxtMsgInbound msgInbound, AppUser parentUser)
        {
            if (parentUser.UserRole != UserRole.Parent)
            {
                string msg3 = string.Format(MessageTemplates.MySitterHubPefix() + " Sorry, only parents can post jobs.");
                _omm.SendFeedbackToInboundMessage(msgInbound, msg3, parentUser.Id);
                return;
            }
            int count = new ParentRepository().GetSitterCountForParent(parentUser.Id);
            if (count == 0)
            {
                string msg2 = string.Format(MessageTemplates.MySitterHubPefix() + " Sorry, you can't post a job until you have added sitters. Say 'invite' to invite sitters.");
                _omm.SendFeedbackToInboundMessage(msgInbound, msg2, parentUser.Id);
                return;
            }

            string msg = string.Format("I'll post a job for you. Which day: {0}?", DaysOfWeekStartingToday(parentUser));
            _omm.SendFeedbackToInboundMessageAndAwait(msgInbound, msg, parentUser.Id, InboundMessageType.PostJob_Step2_DayOfWeek);
        }
        private void ProcessSignupCommand(TxtMsgInbound msgInbound, AppUser user)
        {
            if (user != null)
            {
                _omm.SendFeedbackToInboundMessage(msgInbound, "You are already signed up for mysitterhub.com", user.Id);
                return;
            }

            string msg = MessageTemplates.MySitterHubPefix() + " OK, I'll sign you up for mysitterhub.com, the easiest way to hire a sitter. Would you like to signup as a parent or a sitter?";
            _omm.SendFeedbackToInboundMessageAndAwait(msgInbound, msg, AppUser.NotSignedUpUserId, InboundMessageType.SelfSignup_Step1_ParentOrSitter);
        }
        public string SendFeedbackToInboundMessageAndAwait(TxtMsgInbound inboundMsg, string feedback, int senderId, InboundMessageType inboundMessageType, TxtMsgAwaitingResponse previousAwaitingMsg = null, string conversationMemory = null)
        {
            string outboundTxtMsgId = SendFeedbackToInboundMessage(inboundMsg, feedback, senderId);
            var t = new TxtMsgAwaitingResponse(outboundTxtMsgId, senderId, inboundMsg.MobilePhone, inboundMessageType,
                previousAwaitingMsg == null ? 0 : previousAwaitingMsg.JobId, previousAwaitingMsg == null ? 0 : previousAwaitingMsg.ParentId) {ConversationMemory = conversationMemory};

            _txtMsgAwaitingResponseDal.Insert(t);

            if (previousAwaitingMsg != null)
            {
                _txtMsgAwaitingResponseDal.DeleteAwaiting(previousAwaitingMsg.Id);
            }

            return outboundTxtMsgId;
        }
        public void InsertInbound(TxtMsgInbound msg)
        {
            //TODO: validation

            _txtMsgInboundDal.Insert(msg);
        }
 public void Insert(TxtMsgInbound msg)
 {
     msg.Id = ObjectId.GenerateNewId().ToString();
     MongoCnn.GetTxtMsgInboundCollection().Insert(msg);
 }
 private void ProcessHelpCommand(TxtMsgInbound msgInbound, AppUser user)
 {
     _omm.SendFeedbackToInboundMessage(msgInbound, "mysitterhub.com help. " + MessageTemplates.FormatValidCommands(user.UserRole), user.Id);
 }