Ejemplo n.º 1
0
def _send_sms(conversation, user, msg):
    """ Send an SMS message to the given user within the given conversation.

        Note that we only send the SMS if the user's phone number has been
        verified.
    """
    logger.debug('in core.lib.conversationHandler._send_sms(' +
                 'conversation=%s, user=%s, msg=%s' 
                 % (repr(conversation), repr(user), repr(msg)))

    if user.verified:
        sending_number = twilio_gateway.calc_sending_phone_number(conversation,
                                                                  user)
        twilio_gateway.send_sms(sending_number, user.phone_number, msg)
Ejemplo n.º 2
0
def send_verification_code(user_id=None, phone_number=None):
    """ Calculate and send out a verification code to a phone number.
    """
    raise UnauthorizedException() # Disable for now.

    logger.debug("in core.api.users.send_verification_code(" +
                 "user_id=%s, phone_number=%s)" %
                 (repr(user_id), repr(phone_number)))

    # Get the user to send the verification message to.

    if user_id != None:
        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            raise NoSuchUserException()
    elif phone_number != None:
        phone_number = utils.format_phone_number(phone_number)

        try:
            user = User.objects.get(phone_number=phone_number)
        except User.DoesNotExist:
            raise NoSuchPhoneNumberException()
    else:
        raise InvalidParametersException()

    # Check that the user has a phone number.

    if user.phone_number == None:
        raise NoPhoneNumberException()

    # Calculate a new verification code for this user.

    user.verification_code = utils.random_digits(min_length=4, max_length=4)
    user.save()

    # Finally, send the verification code to the user's phone as an SMS
    # message.

    message = settings.SMS_TEXT_VERIFICATION_CODE % user.verification_code

    twilio_gateway.send_sms(from_phone=settings.SYSTEM_PHONE_NUMBER,
                            to_phone=user.phone_number,
                            sms_message=message)
Ejemplo n.º 3
0
def merge(old_session, new_session):
    """ Merge two users.
    """
    raise UnauthorizedException() # Disable for now.

    logger.debug("in core.api.users.merge(" +
                 "old_session=%s, new_session=%s)" %
                 (repr(old_session), repr(new_session)))

    # Check that the session parameters are correct.  We require two valid
    # session IDs, the old one for an ad hoc user, and the new one for a non-ad
    # hoc user.

    if old_session == None or new_session == None:
        raise InvalidParametersException()

    sessionHandler.validate(old_session)
    sessionHandler.validate(new_session)

    old_user = sessionHandler.get_user(old_session)
    new_user = sessionHandler.get_user(new_session)

    if not old_user.ad_hoc or new_user.ad_hoc:
        raise UnauthorizedException()

    # Build a list of the old user's conversations.

    old_conversations = []
    for conversation in Conversation.objects.filter(user_1=old_user):
        old_conversations.append(conversation)
    for conversation in Conversation.objects.filter(user_2=old_user):
        if conversation.user_1 != old_user:
            old_conversations.append(conversation)

    # Build a list of the old user's active conversations.  Note that we only
    # store the ID of the other user and the topic ID for the conversation, as
    # the Conversation object itself may get deleted as part of the merge
    # process.  We'll need this to send an SMS to the new user telling them
    # that they've taken the conversation mobile.

    active_conversations = [] # List of (other_user_id, topic_id) tuples.
    for conversation in Conversation.objects.filter(user_1=old_user):
        if not conversation.stopped:
            active_conversations.append((conversation.user_2.id,
                                         conversation.topic.id))
    for conversation in Conversation.objects.filter(user_2=old_user):
        if not conversation.stopped and conversation.user_1 != old_user:
            active_conversations.append((conversation.user_1.id,
                                         conversation.topic.id))

    # Build a list of the new user's conversations.

    new_conversations = []
    for conversation in Conversation.objects.filter(user_1=new_user):
        new_conversations.append(conversation)
    for conversation in Conversation.objects.filter(user_2=new_user):
        if conversation.user_1 == new_user:
            new_conversations.append(conversation)

    # Change each of the old conversations to belong to the new user.  If the
    # updated conversation is a duplicate of an existing conversation for the
    # new user, we have to delete the old conversation and update the
    # associated messages.

    for old_conversation in old_conversations:
        if old_conversation.user_1 == old_user:
            other_old_user = old_conversation.user_2
        else:
            other_old_user = old_conversation.user_1

        is_duplicate = False
        for new_conversation in new_conversations:
            if new_conversation.user_1 == new_user:
                other_new_user = new_conversation.user_2
            else:
                other_new_user = new_conversation.user_1

            if other_old_user == other_new_user:
                is_duplicate = True
                break

        if is_duplicate:
            # Update the messages for old_conversation to be part of the
            # new_conversation instead, and delete the old conversation.
            Message.objects.filter(conversation=old_conversation).update(
                                            conversation=new_conversation)
            old_conversation.delete()
        else:
            # Change the old_conversation to belong to the new_user instead of
            # the old_user.
            if old_conversation.user_1 == old_user:
                old_conversation.user_1 = new_user
            else:
                old_conversation.user_2 = new_user
            old_conversation.save()

    # Update the old user's messages to refer to the new user.

    Message.objects.filter(sender=old_user).update(sender=new_user)

    # Update any topics owned by the old user to now be owned by the new user.
    # Note that we deliberately avoid overwriting the default and any existing
    # named topics for the new user.

    topics = []
    for topic in Topic.objects.filter(user=old_user):
        topics.append(topic)

    for topic in topics:
        if topic.default:
            continue # Don't copy across default topic.
        if Topic.objects.filter(user=new_user, name=topic.name):
            continue # Don't overwrite existing named topic.
        topic.user = new_user
        topic.save()

    # Update any SMS channels which sent messages to the old user to now send
    # messages to the new user.

    channels = []
    for channel in TwilioSMSChannel.objects.filter(sender=old_user):
        channels.append(channel)

    for channel in channels:
        if TwilioSMSChannel.objects.filter(conversation=channel.conversation,
                                           recipient=channel.recipient,
                                           phone_number=channel.phone_number,
                                           sender=new_user).exists():
            continue # Don't overwrite existing SMS channel.
        channel.sender = new_user
        channel.save()

    # Update any SMS channels which sent messages from the old user to now send
    # messages from the new user.

    channels = []
    for channel in TwilioSMSChannel.objects.filter(recipient=old_user):
        channels.append(channel)

    for channel in channels:
        if TwilioSMSChannel.objects.filter(conversation=channel.conversation,
                                           sender=channel.sender,
                                           phone_number=channel.phone_number,
                                           recipient=new_user).exists():
            continue # Don't overwrite existing SMS channel.
        channel.recipient = new_user
        channel.save()

    # Finally, if the new user has a verified phone number, send a message to
    # the new user for each active conversation, telling the user that they
    # have "taken the conversation mobile."

    if new_user.verified:
        for other_user,topic in active_conversations:
            try:
                conversation = Conversation.objects.get(user_1=new_user,
                                                        user_2__id=other_user,
                                                        topic=topic)
            except Conversation.DoesNotExist:
                conversation = Conversation.objects.get(user_1__id=other_user,
                                                        user_2=new_user,
                                                        topic=topic)

            sending_phone_number = twilio_gateway.calc_sending_phone_number(
                                                    conversation, new_user)
            msg = settings.SMS_TEXT_CONVERSATION_TAKEN_MOBILE
            twilio_gateway.send_sms(sending_phone_number,
                                    new_user.phone_number, msg)
Ejemplo n.º 4
0
def send_message(sender, recipient, topic, sender_name, message_text):
    """ Create and send a new message.

        The parameters are as follows:

            'sender'

                The User object for the message's sender.

            'recipient'

                The User object for the message's recipient.

            'topic'

                The Topic object that this message is about.

            'sender_name'

                The optional name for the sender of the message.

            'message_text'

                The text of the message.

        We send the given message from the given sender to the given recipient,
        about the given topic.  Note that we'll automatically create a
        conversation (and send an "intro" message") if one doesn't already
        exist.

        Upon completion, we return the newly-created Message object, or None if
        the conversation has been stopped.  If the message recipient has
        reached their rate limit, we raise a RateLimitReachedException.
    """
    logger.debug('in core.lib.messageHandler.send_mesage(' +
                 'sender=%s, recipient=%s, topic=%s, sender_name=%s, msg=%s)'
                 % (repr(sender), repr(recipient), repr(topic),
                    repr(sender_name), repr(message_text)))

    # Find the Conversation object to use for this message, creating it if
    # necessary.

    try:
        conversation = conversationHandler.get(sender.id,
                                               recipient.id,
                                               topic.id)
    except NoSuchConversationException:
        conversation = conversationHandler.start_conversation(sender.id,
                                                              recipient.id,
                                                              topic.id,
                                                              sender_name)

    # If the conversation has been stopped, don't send out the message.

    if conversation.stopped:
        return None

    # See if we can send this message via SMS.  We do this if the receipient
    # has a verified phone number.

    send_via_sms = False # initially.
    if recipient.phone_number not in ["", None] and recipient.verified:
        send_via_sms = True

    # Create the new Message object.

    message = Message()
    message.conversation = conversation
    message.sender       = sender
    message.sender_name  = sender_name
    message.body         = message_text
    message.sent_via_sms = send_via_sms
    message.created_at   = datetime.datetime.utcnow()
    message.updated_at   = datetime.datetime.utcnow()
    message.save()

    # Send the message via PubNub.

    pubnub_gateway.send_notification(message)
    pubnub_gateway.send_message_to_firehose(message)

    # Send the message via Twilio, if we can.  Note that we append the sender's
    # name (if any) to the outgoing SMS message.

    if send_via_sms:
        sending_phone_number = \
           twilio_gateway.calc_sending_phone_number(conversation, recipient)

        if sender_name not in ["", None]:
            message_text = message_text + " [" + sender_name + "]"

        twilio_gateway.send_sms(sending_phone_number, recipient.phone_number,
                                message_text)

    # Finally, return the newly-created message back to the caller.

    return message