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)
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)
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)
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