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