def locked_func(*a, **kw): if lock.acquire(blocking=blocking, timeout=timeout): try: return func(*a, **kw) finally: lock.release() else: log.warn("Can't acquire lock, skipping background thread: {}".format(name))
def attractions_check_notification_replies(): twilio_client = get_twilio_client(c.PANELS_TWILIO_SID, c.PANELS_TWILIO_TOKEN) if not twilio_client or not c.PANELS_TWILIO_NUMBER: log.warn('SMS notification replies disabled for attractions') return with Session() as session: messages = twilio_client.messages.list(to=c.PANELS_TWILIO_NUMBER) sids = set(m.sid for m in messages) existing_sids = set( sid for [sid] in session.query(AttractionNotificationReply.sid).filter( AttractionNotificationReply.sid.in_(sids))) attendees = session.query(Attendee).filter( Attendee.cellphone != '', Attendee.attraction_notifications.any()) attendees_by_phone = groupify(attendees, lambda a: normalize_phone(a.cellphone)) for message in filter(lambda m: m.sid not in existing_sids, messages): attraction_event_id = None attraction_id = None attendee_id = None attendees = attendees_by_phone.get(normalize_phone(message.from_), []) for attendee in attendees: notifications = sorted(filter( lambda s: s.notification_type == Attendee. _NOTIFICATION_TEXT, attendee.attraction_notifications), key=lambda s: s.sent_time) if notifications: notification = notifications[-1] attraction_event_id = notification.attraction_event_id attraction_id = notification.attraction_id attendee_id = notification.attendee_id if 'N' in message.body.upper() and notification.signup: session.delete(notification.signup) break session.add( AttractionNotificationReply( attraction_event_id=attraction_event_id, attraction_id=attraction_id, attendee_id=attendee_id, notification_type=Attendee._NOTIFICATION_TEXT, from_phonenumber=message.from_, to_phonenumber=message.to, sid=message.sid, received_time=datetime.now(pytz.UTC), sent_time=message.date_sent.replace(tzinfo=pytz.UTC), body=message.body)) session.commit()
def tabletop_send_notifications(): twilio_client = get_twilio_client(c.TABLETOP_TWILIO_SID, c.TABLETOP_TWILIO_TOKEN) if not twilio_client or not c.TABLETOP_TWILIO_NUMBER: log.warn('SMS notification sending disabled for tabletop') return with Session() as session: for entrant in session.entrants(): if entrant.should_send_reminder: body = c.TABLETOP_REMINDER_SMS.format(entrant=entrant) sid = send_sms_with_client(twilio_client, entrant.attendee.cellphone, body, c.TABLETOP_TWILIO_NUMBER) entrant.session.add(TabletopSmsReminder(entrant=entrant, text=body, sid=sid)) entrant.session.commit()
def attractions_check_notification_replies(): twilio_client = get_twilio_client(c.PANELS_TWILIO_SID, c.PANELS_TWILIO_TOKEN) if not twilio_client or not c.PANELS_TWILIO_NUMBER: log.warn('SMS notification replies disabled for attractions') return with Session() as session: messages = twilio_client.messages.list(to=c.PANELS_TWILIO_NUMBER) sids = set(m.sid for m in messages) existing_sids = set( sid for [sid] in session.query(AttractionNotificationReply.sid).filter(AttractionNotificationReply.sid.in_(sids))) attendees = session.query(Attendee).filter(Attendee.cellphone != '', Attendee.attraction_notifications.any()) attendees_by_phone = groupify(attendees, lambda a: normalize_phone(a.cellphone)) for message in filter(lambda m: m.sid not in existing_sids, messages): attraction_event_id = None attraction_id = None attendee_id = None attendees = attendees_by_phone.get(normalize_phone(message.from_), []) for attendee in attendees: notifications = sorted(filter( lambda s: s.notification_type == Attendee._NOTIFICATION_TEXT, attendee.attraction_notifications), key=lambda s: s.sent_time) if notifications: notification = notifications[-1] attraction_event_id = notification.attraction_event_id attraction_id = notification.attraction_id attendee_id = notification.attendee_id if 'N' in message.body.upper() and notification.signup: session.delete(notification.signup) break session.add(AttractionNotificationReply( attraction_event_id=attraction_event_id, attraction_id=attraction_id, attendee_id=attendee_id, notification_type=Attendee._NOTIFICATION_TEXT, from_phonenumber=message.from_, to_phonenumber=message.to, sid=message.sid, received_time=datetime.now(pytz.UTC), sent_time=message.date_sent.replace(tzinfo=pytz.UTC), body=message.body)) session.commit()
def run(self, raise_errors=False): """ Do one run of our automated email service. Call this periodically to send any emails that should go out automatically. This will NOT run if we're on-site, or not configured to send emails. :param raise_errors: If False, exceptions are squashed during email sending and we'll try the next email. """ if not (c.DEV_BOX or c.SEND_EMAILS): return if not SendAllAutomatedEmailsJob.run_lock.acquire(blocking=False): log.warn( "can't acquire lock for email daemon (already running?), skipping this run." ) return try: self._run(raise_errors) finally: SendAllAutomatedEmailsJob.run_lock.release()
def tabletop_check_notification_replies(): twilio_client = get_twilio_client(c.TABLETOP_TWILIO_SID, c.TABLETOP_TWILIO_TOKEN) if not twilio_client or not c.TABLETOP_TWILIO_NUMBER: log.warn('SMS notification replies disabled for tabletop') return with Session() as session: entrants = session.entrants_by_phone() existing_sids = {sid for [sid] in session.query(TabletopSmsReply.sid)} messages = [] # Pull all the messages down before attempting to act on them. The new # twilio client uses a streaming mode, so the stream might be timing # out while it waits for us to act on each message inside our loop. try: stream = twilio_client.messages.list(to=c.TABLETOP_TWILIO_NUMBER) messages = [message for message in stream] except ConnectionError as ex: if ex.errno == 'Connection aborted.' \ and isinstance(ex.strerror, BadStatusLine) \ and ex.strerror.line == "''": log.warning('Twilio connection closed unexpectedly') else: raise ex for message in messages: if message.sid in existing_sids: continue for entrant in entrants[message.from_]: if entrant.matches(message): session.add(TabletopSmsReply( entrant=entrant, sid=message.sid, text=message.body, when=message.date_sent.replace(tzinfo=UTC) )) entrant.confirmed = 'Y' in message.body.upper() session.commit()
def test_eager_formatting_adapter(log_stream): log = AutoLogger(EagerFormattingAdapter) log.log(0, 'suppressed') log.debug('a %(a)d b %(b)s', {'a': 1, 'b': 2}) log.trace('TEST NO INTERPOLATION') log.trace('TEST %s', 'MSG') log.debug('TEST %s', 'MSG') log.info('TEST %s%s%s', 'M', 'S', 'G') log.warn('TEST %s', 'MSG') log.warning('TEST %s', 'MSG') log.error('TEST %s', 'MSG') try: assert False except Exception: log.exception('TEST %s', 'MSG') log.critical('TEST %s', 'MSG') log.fatal('TEST %s', 'MSG') result = log_stream.getvalue() assert result.startswith("""\ [DEBUG] tests.test_logging: a 1 b 2 [TRACE] tests.test_logging: TEST NO INTERPOLATION [TRACE] tests.test_logging: TEST MSG [DEBUG] tests.test_logging: TEST MSG [INFO] tests.test_logging: TEST MSG [WARNING] tests.test_logging: TEST MSG [WARNING] tests.test_logging: TEST MSG [ERROR] tests.test_logging: TEST MSG [ERROR] tests.test_logging: TEST MSG Traceback (most recent call last): """) assert result.endswith("""\ AssertionError: assert False [CRITICAL] tests.test_logging: TEST MSG [CRITICAL] tests.test_logging: TEST MSG """)