Ejemplo n.º 1
0
 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))
Ejemplo n.º 2
0
 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))
Ejemplo n.º 3
0
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()
Ejemplo n.º 4
0
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()
Ejemplo n.º 5
0
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()
Ejemplo n.º 6
0
    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()
Ejemplo n.º 7
0
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()
Ejemplo n.º 8
0
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
""")