Esempio n. 1
0
def maybe_handle_verification(member_number: str, message: str):
    """Checks if the message is a verification message for the given number."""
    pending_member_record = db.find_pending_member_by_number(member_number)

    if not pending_member_record:
        return False

    if message.strip().lower() not in ("ok", "yes", "okay"):
        print(f"Verification message was not okay, was {message}")
        # This was "handled", even though verification wasn't approved.
        return True

    pending_member_record.verified = True
    pending_member_record.save()

    audit_log.log(
        audit_log.Kind.MEMBER_NUMBER_VERIFIED,
        description=f"{pending_member_record.name} verified their number.",
        event=pending_member_record.event,
    )

    sender = _get_sender_for_member(pending_member_record)
    reply = "Thank you, your number is confirmed."
    lowlevel.send_sms(sender, member_number, reply)

    return True
Esempio n. 2
0
def start_member_verification(member):
    sender = _get_sender_for_member(member)

    message = (
        f"You've been added as a member of the {member.event.name} event on conducthotline.com."
        " Reply with YES or OK to confirm."
    )

    lowlevel.send_sms(sender, member.number, message)
Esempio n. 3
0
def test_send_sms(sleep):
    client = mock.create_autospec(nexmo.Client)
    client.application_id = "appid"

    client.send_message.return_value = {"messages": [{}]}

    lowlevel.send_sms(to="1234", sender="5678", message="meep", client=client)

    client.send_message.assert_called_once_with({
        "from": "5678",
        "to": "1234",
        "text": "meep"
    })
Esempio n. 4
0
def handle_sms_chat_error(err: SmsChatError, sender: str, relay: str):
    if isinstance(err, EventDoesNotExist):
        lowlevel.send_sms(sender=relay, to=sender, message=common_text.sms_no_event)
    elif isinstance(err, NumberBlocked):
        pass
    elif isinstance(err, NoOrganizersAvailable):
        lowlevel.send_sms(sender=relay, to=sender, message=common_text.sms_no_members)
    elif isinstance(err, NoRelaysAvailable):
        lowlevel.send_sms(sender=relay, to=sender, message=common_text.sms_no_relays)
Esempio n. 5
0
def maybe_handle_stop(
    sender: str, relay: str, message: str, smschat: models.SmsChat
) -> bool:
    """Handle a potential stop request for a given number and SmsChat."""
    if message.strip().lower() != "stop":
        return False

    # Notify other chatroom members.
    room = smschat.room
    room.relay(sender, common_text.sms_left_chat, _send_sms_no_fail)

    # Remove the sender from the chat room.
    removed_user = room.remove_user(sender)
    smschat.save(only=[models.SmsChat.room])

    # Break the chat connection.
    models.SmsChatConnection.delete().where(
        models.SmsChatConnection.smschat == smschat,
        models.SmsChatConnection.user_number == sender,
        models.SmsChatConnection.relay_number == relay,
    ).execute()

    audit_log.log(
        audit_log.Kind.PARTICIPANT_LEFT_CHAT,
        description=f"{removed_user.name} has left the chat room "
        "with relay number"
        "{removed_user.relay}. "
        "The last 4 digits of the their number is {removed_user.number[-4:]}",
        event=smschat.event,
    )

    # Notify the sender they will no longer get messages.
    lowlevel.send_sms(
        sender=relay, to=sender, message=common_text.sms_stop_request_completed
    )

    return True
Esempio n. 6
0
def handle_sms_chat_error(err: SmsChatError, sender: str, relay: str):
    if isinstance(err, EventDoesNotExist):
        lowlevel.send_sms(
            sender=relay,
            to=sender,
            message="Sorry, there doesn't seem to be an event configured for that number.",
        )
    elif isinstance(err, NoOrganizersAvailable):
        lowlevel.send_sms(
            sender=relay,
            to=sender,
            message="Sorry, there aren't any organizers currently available. Please reach out to the event staff in person for assistance.",
        )
    elif isinstance(err, NoRelaysAvailable):
        lowlevel.send_sms(
            sender=relay,
            to=sender,
            message="Sorry, there aren't any relays available to send your message. You can try calling the hotline or reaching out to the event staff in person for assistance.",
        )
Esempio n. 7
0
def _create_room(event_number: str, reporter_number: str) -> hotline.chatroom.Chatroom:
    """Creates a room for the event with the given primary number.

    The alogrithm is a little tricky here. The event organizers can not use
    the primary number as the chat relay for this chat, so a new number must be
    used.
    """
    # Find the event.
    event = db.get_event_by_number(event_number)

    if not event:
        raise EventDoesNotExist(f"No event for number {event_number}.")

    # Create a chatroom
    chatroom = hotline.chatroom.Chatroom()
    chatroom.add_user(name="Reporter", number=reporter_number, relay=event_number)

    # Find all organizers.
    organizers = list(db.get_verified_event_members(event))

    if not organizers:
        raise NoOrganizersAvailable(f"No organizers found for {event.name}. :/")

    # Find an unused number to use for the organizers' relay.
    # Use the first organizer's number here, as all organizers should be
    # assigned the same relay anyway.
    organizer_number = organizers[0].number
    relay_number = db.find_unused_relay_number(event.primary_number, organizer_number)

    if not relay_number:
        raise NoRelaysAvailable()

    # Now add the organizers and their relay.
    for organizer in organizers:
        chatroom.add_user(
            name=organizer.name, number=organizer.number, relay=relay_number
        )

    # Save the chatroom.
    db.save_room(chatroom, event=event)

    audit_log.log(
        audit_log.Kind.SMS_CONVERSATION_STARTED,
        description=f"A new sms conversation was started last 4 digits of number is {reporter_number[-4:]}",
        event=event,
    )

    # Send welcome messages.
    lowlevel.send_sms(
        sender=event_number,
        to=reporter_number,
        message=f"You have started a new chat with the organizers of {event.name}.",
    )

    for organizer in organizers:
        lowlevel.send_sms(
            sender=relay_number,
            to=organizer.number,
            message=f"This is the beginning of a new chat for {event.name}, the last 4 digits of the reporters number are {reporter_number[-4:]}.",
        )

    return chatroom
Esempio n. 8
0
def _create_room(event_number: str,
                 reporter_number: str) -> hotline.chatroom.Chatroom:
    """Creates a room for the event with the given primary number.

    The alogrithm is a little tricky here. The event organizers can not use
    the primary number as the chat relay for this chat, so a new number must be
    used.
    """
    # Find the event.
    event = db.get_event_by_number(event_number)

    if not event:
        raise EventDoesNotExist()

    # Make sure the number isn't blocked.
    if db.check_if_blocked(event=event, number=reporter_number):
        raise NumberBlocked()

    # Create a chatroom
    chatroom = hotline.chatroom.Chatroom()
    chatroom.add_user(name="Reporter",
                      number=reporter_number,
                      relay=event_number)

    # Find all organizers.
    organizers = list(db.get_verified_event_members(event))

    if not organizers:
        raise NoOrganizersAvailable()

    # Find an unused number to use for the organizers' relay.
    relay_number = db.find_unused_relay_number(event)

    if not relay_number:
        raise NoRelaysAvailable()

    # Now add the organizers and their relay.
    for organizer in organizers:
        chatroom.add_user(name=organizer.name,
                          number=organizer.number,
                          relay=relay_number)

    # Save the chatroom.
    db.save_room(chatroom, relay_number=relay_number, event=event)

    audit_log.log(
        audit_log.Kind.SMS_CONVERSATION_STARTED,
        description=
        f"A new sms conversation was started. Last 4 digits of number is {reporter_number[-4:]}",
        event=event,
        reporter_number=reporter_number,
    )

    # Determine the greeting.
    if event.sms_greeting is not None and event.sms_greeting.strip():
        greeting = event.sms_greeting
    else:
        greeting = common_text.sms_default_greeting.format(event=event)

    # Send welcome messages.
    lowlevel.send_sms(sender=event_number,
                      to=reporter_number,
                      message=greeting)

    for organizer in organizers:
        lowlevel.send_sms(
            sender=relay_number,
            to=organizer.number,
            message=common_text.sms_introduction.format(
                event=event, reporter_number=reporter_number[-4:]),
        )

    return chatroom