Ejemplo n.º 1
0
 def test_api_sms_start_sms(self):
     self.testApp.post('/api/sms/switchboard', data = {
         "Body": "start",
         "From": "%2B13155696221"
     })
     service = MongoengineService(User)
     u = service.with_phoneNumber('3155696221')
     assert u.receiveSMSUpdates is True
Ejemplo n.º 2
0
 def test_api_sms_start_sms(self):
     self.testApp.post('/api/sms/switchboard',
                       data={
                           "Body": "start",
                           "From": "%2B13155696221"
                       })
     service = MongoengineService(User)
     u = service.with_phoneNumber('3155696221')
     assert u.receiveSMSUpdates is True
Ejemplo n.º 3
0
 def test_api_sms_post_message(self):
     service = MongoengineService(Post)
     posts_before = len(service.with_fields(**{"thread":self.user.threadSubscription}))
     
     self.testApp.post('/api/sms/switchboard', data = {
         "Body": "Whats up? This is a message",
         "From": "%s" % self.user.phoneNumber
     })
     
     posts_after = len(service.with_fields(**{"thread":self.user.threadSubscription}))
     assert posts_after == posts_before + 1
Ejemplo n.º 4
0
    def test_api_sms_post_message(self):
        service = MongoengineService(Post)
        posts_before = len(
            service.with_fields(**{"thread": self.user.threadSubscription}))

        self.testApp.post('/api/sms/switchboard',
                          data={
                              "Body": "Whats up? This is a message",
                              "From": "%s" % self.user.phoneNumber
                          })

        posts_after = len(
            service.with_fields(**{"thread": self.user.threadSubscription}))
        assert posts_after == posts_before + 1
Ejemplo n.º 5
0
 def test_api_sms_stop_sms(self):
     url = '/api/questions/%s/threads' % str(self.question.id)
     params = self.valid_post_params
     params['follow_sms'] = 'yes'
     
     self.doApiPost(url, params)
     self.testApp.post('/api/sms/switchboard', data = {
         "Body": "stop",
         "From": "%2B1" + self.user.phoneNumber
     })
     
     service = MongoengineService(User)
     u = service.with_phoneNumber(self.user.phoneNumber)
     assert u.receiveSMSUpdates is False
Ejemplo n.º 6
0
    def test_api_sms_stop_sms(self):
        url = '/api/questions/%s/threads' % str(self.question.id)
        params = self.valid_post_params
        params['follow_sms'] = 'yes'

        self.doApiPost(url, params)
        self.testApp.post('/api/sms/switchboard',
                          data={
                              "Body": "stop",
                              "From": "%2B1" + self.user.phoneNumber
                          })

        service = MongoengineService(User)
        u = service.with_phoneNumber(self.user.phoneNumber)
        assert u.receiveSMSUpdates is False
Ejemplo n.º 7
0
class MongoengineServiceTests(BaseTestCase):
    def setUp(self):
        super(MongoengineServiceTests, self).setUp()
        self.users = MongoengineService(User)

    def test_user_entity_is_new(self):
        u = User()
        assert u.is_new() is True

    def test_with_id(self):
        assert isinstance(self.users.with_id(str(self.user.id)), User)

    def test_with_username(self):
        assert isinstance(self.users.with_username('matt'), User)

    def test_with_dynamic_query(self):
        assert isinstance(self.users.with_phoneNumber('3155696217'), User)

    @raises(FieldNotFoundException)
    def test_with_dynamic_bad_field(self):
        self.users.with_something(1)

    @raises(EntityNotFoundException)
    def test_entity_not_found(self):
        self.users.with_username('bogus')
Ejemplo n.º 8
0
class MongoengineServiceTests(BaseTestCase):
    def setUp(self):
        super(MongoengineServiceTests, self).setUp()
        self.users = MongoengineService(User)

    def test_user_entity_is_new(self):
        u = User()
        assert u.is_new() is True

    def test_with_id(self):
        assert isinstance(self.users.with_id(str(self.user.id)), User)

    def test_with_username(self):
        assert isinstance(self.users.with_username("matt"), User)

    def test_with_dynamic_query(self):
        assert isinstance(self.users.with_phoneNumber("3155696217"), User)

    @raises(FieldNotFoundException)
    def test_with_dynamic_bad_field(self):
        self.users.with_something(1)

    @raises(EntityNotFoundException)
    def test_entity_not_found(self):
        self.users.with_username("bogus")
Ejemplo n.º 9
0
 def init_app(self, app):
     if app is None: return
     
     blueprint = Blueprint('cdwapi', __name__)
     
     config = default_config.copy()
     config.update(app.config.get('CDWAPI', {}))
     
     self.config = config
     self.sms = MongoengineService(SMSRegistrationMessage)
     self.switchboard_number = app.config['CDW']['twilio']['switchboard_number']
     app.twilio = TwilioService()
     
     app.cdwapi = self
     
     from cdwapi.views import load_views
     load_views(blueprint)
     
     app.register_blueprint(blueprint, url_prefix=config['url_prefix'])
Ejemplo n.º 10
0
 def setUp(self):
     super(MongoengineServiceTests, self).setUp()
     self.users = MongoengineService(User)
Ejemplo n.º 11
0
 def setUp(self):
     super(MongoengineServiceTests, self).setUp()
     self.users = MongoengineService(User)
Ejemplo n.º 12
0
class CDWApi(object):
    def __init__(self, app=None):
        self.init_app(app)

    def init_app(self, app):
        if app is None: return

        blueprint = Blueprint('cdwapi', __name__)

        config = default_config.copy()
        config.update(app.config.get('CDWAPI', {}))

        self.config = config
        self.sms = MongoengineService(SMSRegistrationMessage)
        self.switchboard_number = app.config['CDW']['twilio'][
            'switchboard_number']
        app.twilio = TwilioService()

        app.cdwapi = self

        from cdwapi.views import load_views
        load_views(blueprint)

        app.register_blueprint(blueprint, url_prefix=config['url_prefix'])

    def save_incoming_sms(self, kiosk_number, phone, message):
        msg = SMSRegistrationMessage(kioskNumber=kiosk_number,
                                     phoneNumber=phone,
                                     message=message,
                                     profane=has_bad_words(message))
        self.sms.save(msg)
        return msg

    def get_recent_sms_messages(self, kiosk_number):
        return [
            x.as_dict()
            for x in self.sms.with_fields(**{
                "kioskNumber": kiosk_number
            }).order_by('-created')[:5]
        ]

    def stop_sms_updates(self, user):
        if not user.phoneNumber or \
           not user.receiveSMSUpdates:
            return False

        user.receiveSMSUpdates = False
        cdw.users.save(user)

        msg = "Message following stopped. To start again, text " \
              "back START, or begin a new debate."

        current_app.twilio.send_message(msg, self.switchboard_number,
                                        [user.phoneNumber])
        return True

    def resume_sms_updates(self, user):
        if not user.phoneNumber or \
           user.receiveSMSUpdates or \
           not user.threadSubscription:
            return False

        user.receiveSMSUpdates = True
        cdw.users.save(user)

        message = "You will now begin to receive SMS updates for the last " \
                  "debate you participated in."

        self.send_sms_message(message, [user.phoneNumber])

    def start_sms_updates(self, user, thread):
        if not user.phoneNumber or \
           user.threadSubscription == thread:
            return False

        switched_msg = "You can follow one debate at a time via SMS. We " \
                       "will switch to the debate you joined" \
                       ". If you want to stay in your previous debate, " \
                       "text back STAY."

        message = "You are now subscribed to the debate you joined. " \
                  "You can reply to messages you receive via SMS " \
                  "to continue the debate. To stop these messages " \
                  "text back STOP."

        all_users = cdw.users.with_fields(
            phoneNumber=user.phoneNumber).order_by('-lastPostDate')

        previous = None

        if len(all_users) == 1:

            if user.threadSubscription != None:
                previous = user.threadSubscription
                message = switched_msg

        else:
            if user.origin == 'web' and \
               user.previousThreadSubscription == None and \
               all_users[1].origin =='kiosk' and \
               all_users[1].threadSubscription != None:

                current_app.logger.info('Setting previous thread subscription '
                                        'for web user based on last kiosk '
                                        'interaction')

                previous = all_users[1].threadSubscription
                message = switched_msg

            if user.origin == 'kiosk' and \
               user.previousThreadSubscription == None and \
               all_users[1].origin =='web' and \
               all_users[1].threadSubscription != None:

                current_app.logger.info('Setting previous thread subscription '
                                        'for kiosk user based on last web '
                                        'interaction')

                previous = all_users[1].threadSubscription
                message = switched_msg

        for u in all_users[1:]:
            u.threadSubscription = None
            u.previousThreadSubscription = None
            cdw.users.save(u)

        user.threadSubscription = thread
        user.previousThreadSubscription = previous
        user.receiveSMSUpdates = True
        cdw.users.save(user)

        current_app.twilio.send_message(message, self.switchboard_number,
                                        [user.phoneNumber])
        return True

    def revert_sms_updates(self, user):
        if not user.phoneNumber or \
           not user.previousThreadSubscription:
            return False

        user.threadSubscription = user.previousThreadSubscription
        user.previousThreadSubscription = None
        cdw.users.save(user)

        msg = "Got it. We've changed your subscription " \
              "to the previous debate."

        current_app.twilio.send_message(msg, self.switchboard_number,
                                        [user.phoneNumber])

        return True

    def send_sms_message(self, message, recipients):
        current_app.twilio.send_message(message, self.switchboard_number,
                                        recipients)

    def notify_sms_subscribers(self, thread, exclude, message):
        subscribers = cdw.users.with_fields(threadSubscription=thread)

        # Just their phone numbers
        subscribers = [ u.phoneNumber \
                        for u in subscribers \
                        if u.phoneNumber not in exclude and u.receiveSMSUpdates ]

        self.send_sms_message(message, subscribers)

    def start_email_updates(self, user, thread):
        if user not in thread.emailSubscribers:
            thread.emailSubscribers.append(user)
            cdw.threads.save(thread)

    def stop_email_updates(self, user, thread):
        thread.emailSubscribers.remove(user)
        cdw.threads.save(thread)

    def stop_all_email_updates(self, user):
        thread_subscriptions = cdw.threads.with_fields(emailSubscribers=user)

        for thread in thread_subscriptions:
            self.stop_email_updates(user, thread)

    def notify_email_subscribers(self, thread, exclude, message):
        subscribers = [u for u in thread.emailSubscribers \
                       if u.email not in exclude]

        from cdw.emailers import send_reply_notification

        for s in subscribers:
            ctx = dict(question_id=str(thread.question.id),
                       thread_id=str(thread.id),
                       user_id=str(s.id),
                       local_request=current_app.config['LOCAL_REQUEST'],
                       message=message)

            attempts = 0
            attempts_allowed = 5

            current_app.logger.debug('Attempting to send email to %s' %
                                     s.email)

            while True:
                try:
                    send_reply_notification(s.email, ctx)
                    break

                except Exception, e:
                    attempts += 1
                    if attempts == attempts_allowed:
                        current_app.logger.error(
                            "Error sending email notification: %s" % e)
                        break
                    else:
                        current_app.logger.warn(
                            "Attempt %s to send email failed. "
                            "Error: %s" % (attempts, e))

                    time.sleep(1)
Ejemplo n.º 13
0
class CDWApi(object):
    def __init__(self, app=None):
        self.init_app(app)
        
    def init_app(self, app):
        if app is None: return
        
        blueprint = Blueprint('cdwapi', __name__)
        
        config = default_config.copy()
        config.update(app.config.get('CDWAPI', {}))
        
        self.config = config
        self.sms = MongoengineService(SMSRegistrationMessage)
        self.switchboard_number = app.config['CDW']['twilio']['switchboard_number']
        app.twilio = TwilioService()
        
        app.cdwapi = self
        
        from cdwapi.views import load_views
        load_views(blueprint)
        
        app.register_blueprint(blueprint, url_prefix=config['url_prefix'])
        
    def save_incoming_sms(self, kiosk_number, phone, message):
        msg = SMSRegistrationMessage(kioskNumber=kiosk_number, phoneNumber=phone, 
                                     message=message, profane=has_bad_words(message))
        self.sms.save(msg)
        return msg
    
    def get_recent_sms_messages(self, kiosk_number):
        return [x.as_dict() for x in self.sms.with_fields(
                    **{"kioskNumber":kiosk_number}).order_by('-created')[:5]]
    
    def stop_sms_updates(self, user):
        if not user.phoneNumber or \
           not user.receiveSMSUpdates: 
            return False
        
        user.receiveSMSUpdates = False;
        cdw.users.save(user)
        
        msg = "Message following stopped. To start again, text " \
              "back START, or begin a new debate."
              
        current_app.twilio.send_message(msg, 
                                        self.switchboard_number, 
                                        [user.phoneNumber])
        return True
    
    def resume_sms_updates(self, user):
        if not user.phoneNumber or \
           user.receiveSMSUpdates or \
           not user.threadSubscription:
            return False
        
        user.receiveSMSUpdates = True
        cdw.users.save(user)
        
        message = "You will now begin to receive SMS updates for the last " \
                  "debate you participated in."
                  
        self.send_sms_message(message, [user.phoneNumber])
    
    def start_sms_updates(self, user, thread):
        if not user.phoneNumber or \
           user.threadSubscription == thread:
            return False
        
        switched_msg = "You can follow one debate at a time via SMS. We " \
                       "will switch to the debate you joined" \
                       ". If you want to stay in your previous debate, " \
                       "text back STAY."
                       
        message = "You are now subscribed to the debate you joined. " \
                  "You can reply to messages you receive via SMS " \
                  "to continue the debate. To stop these messages " \
                  "text back STOP."
        
        all_users = cdw.users.with_fields(
                        phoneNumber=user.phoneNumber).order_by('-lastPostDate')
        
        previous = None
        
        if len(all_users) == 1:
            
            if user.threadSubscription != None:
                previous = user.threadSubscription
                message = switched_msg
                
        else:
            if user.origin == 'web' and \
               user.previousThreadSubscription == None and \
               all_users[1].origin =='kiosk' and \
               all_users[1].threadSubscription != None:
            
                current_app.logger.info('Setting previous thread subscription '
                                        'for web user based on last kiosk '
                                        'interaction')
                
                previous = all_users[1].threadSubscription
                message = switched_msg
                
            if user.origin == 'kiosk' and \
               user.previousThreadSubscription == None and \
               all_users[1].origin =='web' and \
               all_users[1].threadSubscription != None:
            
                current_app.logger.info('Setting previous thread subscription '
                                        'for kiosk user based on last web '
                                        'interaction')
                
                previous = all_users[1].threadSubscription
                message = switched_msg
           
        for u in all_users[1:]:
            u.threadSubscription = None
            u.previousThreadSubscription = None
            cdw.users.save(u)
        
        user.threadSubscription = thread
        user.previousThreadSubscription = previous
        user.receiveSMSUpdates = True;
        cdw.users.save(user)
        
        current_app.twilio.send_message(message, 
                                        self.switchboard_number, 
                                        [user.phoneNumber])
        return True
    
    def revert_sms_updates(self, user):
        if not user.phoneNumber or \
           not user.previousThreadSubscription:
            return False
        
        user.threadSubscription = user.previousThreadSubscription;
        user.previousThreadSubscription = None
        cdw.users.save(user)
        
        msg = "Got it. We've changed your subscription " \
              "to the previous debate."
              
        current_app.twilio.send_message(msg, 
            self.switchboard_number, [user.phoneNumber])
        
        return True
        
    def send_sms_message(self, message, recipients):
        current_app.twilio.send_message(message, 
            self.switchboard_number, recipients)
            
    def notify_sms_subscribers(self, thread, exclude, message):
        subscribers = cdw.users.with_fields(threadSubscription=thread)
        
        # Just their phone numbers
        subscribers = [ u.phoneNumber \
                        for u in subscribers \
                        if u.phoneNumber not in exclude and u.receiveSMSUpdates ]
        
        self.send_sms_message(message, subscribers)
        
    def start_email_updates(self, user, thread):
        if user not in thread.emailSubscribers:
            thread.emailSubscribers.append(user)
            cdw.threads.save(thread)
        
    def stop_email_updates(self, user, thread):
        thread.emailSubscribers.remove(user)
        cdw.threads.save(thread)
        
    def stop_all_email_updates(self, user):
        thread_subscriptions = cdw.threads.with_fields(emailSubscribers=user)
        
        for thread in thread_subscriptions:
            self.stop_email_updates(user, thread)
            
    def notify_email_subscribers(self, thread, exclude, message):
        subscribers = [u for u in thread.emailSubscribers \
                       if u.email not in exclude]
        
        from cdw.emailers import send_reply_notification
        
        for s in subscribers:
            ctx = dict(question_id=str(thread.question.id),
                       thread_id=str(thread.id), 
                       user_id=str(s.id),
                       local_request=current_app.config['LOCAL_REQUEST'],
                       message=message)
            
            attempts = 0;
            attempts_allowed = 5
            
            current_app.logger.debug('Attempting to send email to %s' % s.email)
            
            while True:
                try:
                    send_reply_notification(s.email, ctx)
                    break
                
                except Exception, e:
                    attempts += 1
                    if attempts == attempts_allowed:
                        current_app.logger.error(
                            "Error sending email notification: %s" % e)
                        break;
                    else:
                        current_app.logger.warn(
                            "Attempt %s to send email failed. "
                            "Error: %s" % (attempts, e))
                        
                    time.sleep(1)