def get_inbound_phone_entry(msg): if msg.backend_id: backend = SQLMobileBackend.load(msg.backend_id, is_couch_id=True) if toggles.INBOUND_SMS_LENIENCY.enabled(backend.domain): p = None if toggles.ONE_PHONE_NUMBER_MULTIPLE_CONTACTS.enabled( backend.domain): running_session_info = XFormsSessionSynchronization.get_running_session_info_for_channel( SMSChannel(backend_id=msg.backend_id, phone_number=msg.phone_number)) contact_id = running_session_info.contact_id if contact_id: p = PhoneNumber.get_phone_number_for_owner( contact_id, msg.phone_number) if p is not None: return (p, True) elif running_session_info.session_id: # This would be very unusual, as it would mean the supposedly running form session # is linked to a phone number, contact pair that doesn't exist in the PhoneNumber table notify_error( "Contact from running session has no match in PhoneNumber table. " "Only known way for this to happen is if you " "unregister a phone number for a contact " "while they are in an active session.", details={'running_session_info': running_session_info}) if not backend.is_global: p = PhoneNumber.get_two_way_number_with_domain_scope( msg.phone_number, backend.domains_with_access) return (p, p is not None) return (PhoneNumber.get_reserved_number(msg.phone_number), False)
def handle_due_survey_action(domain, contact_id, session_id): with critical_section_for_smsforms_sessions(contact_id): session = SQLXFormsSession.by_session_id(session_id) if (not session or not session.session_is_open or session.current_action_due > utcnow()): return if session.current_action_is_a_reminder: # Resend the current question in the open survey to the contact p = PhoneNumber.get_phone_number_for_owner(session.connection_id, session.phone_number) if p: metadata = MessageMetadata( workflow=session.workflow, xforms_session_couch_id=session._id, ) resp = current_question(session.session_id, domain) send_sms_to_verified_number( p, resp.event.text_prompt, metadata, logged_subevent=session.related_subevent) session.move_to_next_action() session.save() else: # Close the session session.close() session.save()
def get_two_way_entry_or_phone_number(cls, recipient, try_user_case=True, domain_for_toggles=None): """ If recipient has a two-way number, returns it as a PhoneNumber entry. If recipient does not have a two-way number but has a phone number configured, returns the one-way phone number as a string. If try_user_case is True and recipient is a CommCareUser who doesn't have a two-way or one-way phone number, then it will try to get the two-way or one-way number from the user's user case if one exists. """ if settings.USE_PHONE_ENTRIES: phone_entry = get_two_way_number_for_recipient(recipient) if phone_entry: return phone_entry phone_number = get_one_way_number_for_recipient(recipient) if toggles.INBOUND_SMS_LENIENCY.enabled(domain_for_toggles) and \ toggles.ONE_PHONE_NUMBER_MULTIPLE_CONTACTS.enabled(domain_for_toggles): phone_entry = PhoneNumber.get_phone_number_for_owner(recipient.get_id, phone_number) if phone_entry: return phone_entry # Avoid processing phone numbers that are obviously fake (len <= 3) to # save on processing time if phone_number and len(phone_number) > 3: return phone_number if try_user_case and isinstance(recipient, CommCareUser) and recipient.memoized_usercase: return cls.get_two_way_entry_or_phone_number(recipient.memoized_usercase, domain_for_toggles=domain_for_toggles) return None
def handle_due_survey_action(domain, contact_id, session_id): with critical_section_for_smsforms_sessions(contact_id): session = SQLXFormsSession.by_session_id(session_id) if (not session or not session.session_is_open or session.current_action_due > utcnow()): return if toggles.ONE_PHONE_NUMBER_MULTIPLE_CONTACTS.enabled(domain): if not XFormsSessionSynchronization.claim_channel_for_session( session): from .management.commands import handle_survey_actions # Unless we release this lock, handle_survey_actions will be unable to requeue this task # for the default duration of 1h, which we don't want handle_survey_actions.Command.get_enqueue_lock( session_id, session.current_action_due).release() return if session_is_stale(session): # If a session is having some unrecoverable errors that aren't benefitting from # being retried, those errors should show up in sentry log and the fix should # be dealt with. In terms of the current session itself, we just close it out # to allow new sessions to start. session.mark_completed(False) session.save() return if session.current_action_is_a_reminder: # Resend the current question in the open survey to the contact p = PhoneNumber.get_phone_number_for_owner(session.connection_id, session.phone_number) if p: metadata = MessageMetadata( workflow=session.workflow, xforms_session_couch_id=session._id, ) resp = FormplayerInterface(session.session_id, domain).current_question() send_sms_to_verified_number( p, resp.event.text_prompt, metadata, logged_subevent=session.related_subevent) session.move_to_next_action() session.save() else: # Close the session session.close() session.save()
def handle_due_survey_action(domain, contact_id, session_id): with critical_section_for_smsforms_sessions(contact_id): session = SQLXFormsSession.by_session_id(session_id) if ( not session or not session.session_is_open or session.current_action_due > utcnow() ): return if session_is_stale(session): # If a session is having some unrecoverable errors that aren't benefitting from # being retried, those errors should show up in sentry log and the fix should # be dealt with. In terms of the current session itself, we just close it out # to allow new sessions to start. session.mark_completed(False) session.save() return if session.current_action_is_a_reminder: # Resend the current question in the open survey to the contact p = PhoneNumber.get_phone_number_for_owner(session.connection_id, session.phone_number) if p: metadata = MessageMetadata( workflow=session.workflow, xforms_session_couch_id=session._id, ) resp = current_question(session.session_id, domain) send_sms_to_verified_number( p, resp.event.text_prompt, metadata, logged_subevent=session.related_subevent ) session.move_to_next_action() session.save() else: # Close the session session.close() session.save()
def handle_due_survey_action(domain, contact_id, session_id): with critical_section_for_smsforms_sessions(contact_id): session = SQLXFormsSession.by_session_id(session_id) if ( not session or not session.session_is_open or session.current_action_due > utcnow() ): return if session_is_stale(session): # If a session is having some unrecoverable errors that aren't benefitting from # being retried, those errors should show up in sentry log and the fix should # be dealt with. In terms of the current session itself, we just close it out # to allow new sessions to start. session.mark_completed(False) session.save() return if session.current_action_is_a_reminder: # Resend the current question in the open survey to the contact p = PhoneNumber.get_phone_number_for_owner(session.connection_id, session.phone_number) if p: metadata = MessageMetadata( workflow=session.workflow, xforms_session_couch_id=session._id, ) resp = current_question(session.session_id, domain) send_sms_to_verified_number( p, resp.event.text_prompt, metadata, logged_subevent=session.related_subevent ) session.move_to_next_action() session.save() else: # Close the session session.close() session.save()
def get_channel_for_contact(contact_id, phone_number): """ For a given contact_id, phone_number pair, look up the gateway to be used and return the result as a Channel If a PhoneNumber object does not exist for the pair, or attempting to determine the gateway backend results in a BadSMSConfigException a channel will be returned with backend_id=None """ backend_id = None phone_number_record = PhoneNumber.get_phone_number_for_owner(contact_id, phone_number) if phone_number_record: try: backend = phone_number_record.backend except BadSMSConfigException: backend = None if backend: backend_id = backend.couch_id return SMSChannel( backend_id=backend_id, phone_number=phone_number, )