예제 #1
0
    def process_troublemaker(self):
        if super().is_number_in_db():
            GuestAttendanceClient(self.guest).check_guest_in()

            # Number is in table, but this is a repeat troublemaker.
            if self.guest.name == "TROUBLEMAKER":
                return get_messaging_response(basic_troublemaker_response())
            # For some reason they've gotten cold feet about sending their name to us, even
            # though they've done so in the past.
            else:
                return get_messaging_response(
                    cheeky_troublemaker_response(self.guest.name))
        else:
            is_member = self.member is not None

            new_guest = Guest.objects.create(
                phone=self.number,
                name=self.member.name if is_member else "TROUBLEMAKER",
            )

            if is_member:
                new_guest.member = self.member

            new_guest.save()
            GuestAttendanceClient(new_guest).check_guest_in()

            if is_member:
                return get_messaging_response(
                    member_troublemaker_response(self.member.first_name))
            else:
                return get_messaging_response(basic_troublemaker_response())
    def create_needshelp_guest_and_proceed(self):
        guest = Guest.objects.create(phone=self.phone, name="NEEDSHELP")
        guest.save()
        self.guest = guest

        self.raise_flag(GuestAttendanceClient(self.guest).check_guest_in())
        return get_messaging_response(needshelp_guest_orientation_message())
    def get_more_info_or_fwd_sms(self, message_body):
        if self.guest.name == "NEEDSHELP":
            # TODO: It's entirely possible for them to respond with something other than their name, meaning we'd set
            # their name to be something weird here. Is there a way we can validate?
            self.guest.name = message_body
            self.guest.save()
            self.twilio.notify_exec_and_sbs(
                needshelp_was_identified_message(message_body,
                                                 self.guest.phone))
            self.notify_slack(
                needshelp_was_identified_message(message_body,
                                                 self.guest.phone))

            return get_messaging_response(
                needshelp_identified_themselves_message(message_body))
        else:
            self.twilio.notify_exec_and_sbs(
                message_from_guest_message(message_body, self.guest))
            return get_messaging_response(successfully_forwarded_message())
    def process_guest(self):
        # Account linking and setup.
        if self.is_number_in_db():
            # We've established that there's a guest account in here.
            self.check_troublemaker_and_alias()
        else:
            self.add_to_database()

        GuestAttendanceClient(self.guest).check_guest_in()
        return get_messaging_response(welcome_to_event_message(
            self.guest.name))
    def handle_request_for_help(self):
        self.logger.warning("Attemping to notify slack")
        self.notify_slack(generic_asked_for_help_slack_message(self.phone))

        if self.guest is None:
            return self.create_needshelp_guest_and_proceed()

        attendance = EventAttendance.objects.filter(
            guest__id=self.guest.id, event__id=self.event[0].id).first()

        if not attendance.help_flag:
            attendance.help_flag = True
            attendance.help_flag_raised_at = get_current_time_mst()
            attendance.save()

        if self.guest.name == "TROUBLEMAKER":
            self.logger.warning("Troublemaker asking for emergency help.")
            self.guest.name = "NEEDSHELP"
            self.guest.save()
            self.twilio.notify_exec_and_sbs(
                troublemaker_asked_for_help_message(self.guest))
            return get_messaging_response(
                needshelp_guest_orientation_message())
        else:
            self.logger.warning(
                f"Guest name {self.guest.name} is asking for help.")
            self.notify_slack(
                f"Guest asking for help is named {self.guest.name}, phone is {self.guest.phone}."
            )
            self.twilio.notify_exec_and_sbs(
                guest_asked_for_help_exec_sb_message(self.guest))

            response_message = get_messaging_response(
                guest_asked_for_help_initial_message().strip())

            self.logger.warning(f"Returning: {response_message}")

            return response_message
    def create(self, request):
        """
        Handles the SMS Requests POSTed In by Twilio
        """
        logger.info(f"Received request: {request}")
        logger.info(f"Request body: {request.body}")

        headers = request.headers

        try:
            body = extract_twilio_body(request.body)
        except Exception as e:
            logger.error("Encountered error when parsing Twilio request body")
            return Response(
                {
                    "improper_format":
                    f"Was unable to parse Twilio data from your requests",
                    "body": f"{request.body}",
                    "headers": f"{headers}",
                    "error_message": f"{e}",
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Twilio's verification will sporadically decide to fail. Who knows why or how. This code
        # enables a server setting to bypass verification checking as a bandaid.
        # TODO: Remove this bandaid and actually determine why verification is failing. Will probably need logging to go off.
        is_valid_message = verify_twilio_request(headers, body)

        # By default, we'll check all messages for authenticity.
        server_setting = server_setting_get_or_none("verify-twilio-requests")
        checking_message = bool(
            server_setting) if server_setting is not None else True

        logger.warning(f"Valid Twilio Signature? {is_valid_message}")
        logger.warning(
            f"For Body: {body}, Uri: {request.get_full_path()}, Signature: {headers['X-Twilio-Signature']}"
        )

        if checking_message and not is_valid_message:
            return Response(
                {
                    "signature_invalid":
                    f"The signature included with the request is invalid. Who are you?",
                    "body": f"{body}",
                    "signature": f"{headers['X-Twilio-Signature']}",
                    "uri": f"{request.get_full_path()}",
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Check for flag
        if help_flag_is_present(body["From"]):
            # For this flow, this is CRITICAL. In the event of an emergency coinciding with something breaking, we need
            # to provide some support still.
            try:
                emergency_response = EmergencyResponseClient(
                    body["From"]).get_more_info_or_fwd_sms(body["Body"])
                return HttpResponse(
                    emergency_response,
                    status=status.HTTP_200_OK,
                    content_type="text/xml",
                )
            except Exception as e:
                logger.error(
                    "Error in EmergencyResponseClient, get_more_info_or_fwd_sms"
                )
                logger.error(e)
                return HttpResponse(
                    get_messaging_response(code_is_breaking_message()),
                    status=status.HTTP_200_OK,
                    content_type="text/xml",
                )

        # Check if there's an event going on
        if len(get_active_event()) == 0:
            return HttpResponse(
                get_messaging_response(no_event_message()),
                status=status.HTTP_200_OK,
                content_type="text/xml",
            )

        # Check if text is the default
        if text_is_default(body["Body"]):
            troublemaker_response = TroublemakerClient(
                body["From"]).process_troublemaker()
            return HttpResponse(
                troublemaker_response,
                status=status.HTTP_200_OK,
                content_type="text/xml",
            )

        # Checking if the message says help me
        if text_is_help(body["Body"]):
            # For this flow, this is CRITICAL. In the event of an emergency coinciding with something breaking, we need
            # to provide some support still.
            try:
                return HttpResponse(
                    EmergencyResponseClient(
                        body["From"]).handle_request_for_help(),
                    status=status.HTTP_200_OK,
                    content_type="text/xml",
                )
            except Exception as e:
                logger.error(
                    "Error in EmergencyResponseClient, handle_request_for_help"
                )
                logger.error(e)
                return HttpResponse(
                    get_messaging_response(code_is_breaking_message()),
                    status=status.HTTP_200_OK,
                    content_type="text/xml",
                )

        else:
            logger.warning(
                "All pre-message checks passed, continuing with add guest flow"
            )
            add_guest_client_response = AddGuestClient(
                body["From"], body["Body"]).process_guest()
            return HttpResponse(
                add_guest_client_response,
                status=status.HTTP_200_OK,
                content_type="text/xml",
            )