def advance_checkin_label(self):
     if self.advance_checkin < 0:
         return 'anytime during the event'
     return humanize_timedelta(seconds=self.advance_checkin,
                               separator=' ',
                               now='by the time the event starts',
                               prefix='at least ',
                               suffix=' before the event starts')
示例#2
0
 def advance_checkin_label(self):
     if self.advance_checkin < 0:
         return 'anytime during the event'
     return humanize_timedelta(
         seconds=self.advance_checkin,
         separator=' ',
         now='by the time the event starts',
         prefix='at least ',
         suffix=' before the event starts')
示例#3
0
    def checklist_completion(self, out, session):
        header_row = ['Studio']
        for key, val in c.MIVS_CHECKLIST.items():
            header_row.append(val['name'])
            header_row.append('Past Due?')
        out.writerow(header_row)

        for studio in session.query(IndieStudio).join(IndieStudio.group).join(Group.guest):
            row = [studio.name]
            for key, val in c.MIVS_CHECKLIST.items():
                row.extend([
                    'Not Completed' if getattr(studio, key + "_status", None) is None
                    else getattr(studio, key + "_status"),
                    'No' if localized_now() <= studio.checklist_deadline(key)
                    else humanize_timedelta(studio.past_checklist_deadline(key), granularity='hours'),
                ])
            out.writerow(row)
示例#4
0
 def test_humanize_timedelta(self, test_args, test_kwargs, expected):
     assert expected == humanize_timedelta(*test_args, **test_kwargs)
示例#5
0
def send_attraction_notifications(session):
    for attraction in session.query(Attraction):
        now = datetime.now(pytz.UTC)
        from_time = now - timedelta(seconds=300)
        to_time = now + timedelta(seconds=300)
        signups = attraction.signups_requiring_notification(
            session, from_time, to_time, [
                subqueryload(AttractionSignup.attendee).subqueryload(
                    Attendee.attraction_notifications),
                subqueryload(AttractionSignup.event).subqueryload(
                    AttractionEvent.feature)
            ])

        for signup, advance_notices in signups.items():
            attendee = signup.attendee
            if not attendee.first_name or not attendee.email:
                try:
                    log.error('ERROR: Unassigned attendee signed up for an '
                              'attraction, deleting signup:\n'
                              '\tAttendee.id: {}\n'
                              '\tAttraction.id: {}\n'
                              '\tAttractionEvent.id: {}\n'
                              '\tAttractionSignup.id: {}'.format(
                                  attendee.id, signup.attraction_id,
                                  signup.attraction_event_id, signup.id))
                    session.delete(signup)
                    session.commit()
                except:
                    log.error(
                        'ERROR: Failed to delete signup with '
                        'unassigned attendee',
                        exc_info=True)
                continue

            # The first time someone signs up for an attractions, they always
            # receive the welcome email (even if they've chosen SMS or None
            # for their notification prefs). If they've chosen to receive SMS
            # notifications, they'll also get a text message.
            is_first_signup = not (attendee.attraction_notifications)

            if not is_first_signup and \
                    attendee.notification_pref == Attendee.NOTIFICATION_NONE:
                continue

            use_text = twilio_client \
                and attendee.cellphone \
                and attendee.notification_pref == Attendee.NOTIFICATION_TEXT

            event = signup.event

            # If we overlap multiple notices, we only want to send a single
            # notification. So if we have both "5 minutes before checkin" and
            # "when checkin starts", we only want to send the notification
            # for "when checkin starts".
            advance_notice = min(advance_notices)
            if advance_notice == -1 or advance_notice > 1800:
                checkin = 'is at {}'.format(event.checkin_start_time_label)
            else:
                checkin = humanize_timedelta(event.time_remaining_to_checkin,
                                             granularity='minutes',
                                             separator=' ',
                                             prefix='is in ',
                                             now='is right now',
                                             past_prefix='was ',
                                             past_suffix=' ago')

            ident = AttractionEvent.get_ident(event.id, advance_notice)
            try:
                if use_text:
                    type_ = Attendee.NOTIFICATION_TEXT
                    type_str = 'TEXT'
                    from_ = c.PANELS_TWILIO_NUMBER
                    to_ = attendee.cellphone
                    body = TEXT_TPL.format(signup=signup, checkin=checkin)
                    subject = ''
                    sid = send_sms(to_, body, from_)

                if not use_text or is_first_signup:
                    type_ = Attendee.NOTIFICATION_EMAIL
                    type_str = 'EMAIL'
                    from_ = c.ATTRACTIONS_EMAIL
                    to_ = attendee.email
                    if is_first_signup:
                        template = 'emails/attractions_welcome.html'
                        subject = 'Welcome to {} Attractions'.format(
                            c.EVENT_NAME)
                    else:
                        template = 'emails/attractions_notification.html'
                        subject = 'Checkin for {} is at {}'.format(
                            event.name, event.checkin_start_time_label)

                    body = render(template, {
                        'signup': signup,
                        'checkin': checkin,
                        'c': c
                    }).decode('utf-8')
                    sid = ident
                    send_email(from_,
                               to_,
                               subject=subject,
                               body=body,
                               format='html',
                               model=attendee,
                               ident=ident)
            except:
                log.error('Error sending notification\n'
                          '\tfrom: {}\n'
                          '\tto: {}\n'
                          '\tsubject: {}\n'
                          '\tbody: {}\n'
                          '\ttype: {}\n'
                          '\tattendee: {}\n'
                          '\tident: {}\n'.format(from_, to_, subject, body,
                                                 type_str, attendee.id, ident),
                          exc_info=True)
            else:
                session.add(
                    AttractionNotification(attraction_event_id=event.id,
                                           attraction_id=event.attraction_id,
                                           attendee_id=attendee.id,
                                           notification_type=type_,
                                           ident=ident,
                                           sid=sid,
                                           sent_time=datetime.now(pytz.UTC),
                                           subject=subject,
                                           body=body))
                session.commit()
示例#6
0
def attractions_send_notifications():
    twilio_client = get_twilio_client(c.PANELS_TWILIO_SID, c.PANELS_TWILIO_TOKEN)

    with Session() as session:
        for attraction in session.query(Attraction):
            now = datetime.now(pytz.UTC)
            from_time = now - timedelta(seconds=300)
            to_time = now + timedelta(seconds=300)
            signups = attraction.signups_requiring_notification(session, from_time, to_time, [
                subqueryload(
                    AttractionSignup.attendee).subqueryload(
                        Attendee.attraction_notifications),
                subqueryload(
                    AttractionSignup.event).subqueryload(
                        AttractionEvent.feature)])

            for signup, advance_notices in signups.items():
                attendee = signup.attendee
                if not attendee.first_name or not attendee.email:
                    try:
                        log.error(
                            'ERROR: Unassigned attendee signed up for an attraction, deleting signup:\n'
                            '\tAttendee.id: {}\n'
                            '\tAttraction.id: {}\n'
                            '\tAttractionEvent.id: {}\n'
                            '\tAttractionSignup.id: {}'.format(
                                attendee.id,
                                signup.attraction_id,
                                signup.attraction_event_id,
                                signup.id))

                        session.delete(signup)
                        session.commit()
                    except Exception:
                        log.error('ERROR: Failed to delete signup with unassigned attendee', exc_info=True)
                    continue

                # The first time someone signs up for an attractions, they always
                # receive the welcome email (even if they've chosen SMS or None
                # for their notification prefs). If they've chosen to receive SMS
                # notifications, they'll also get a text message.
                is_first_signup = not(attendee.attraction_notifications)

                if not is_first_signup and attendee.notification_pref == Attendee._NOTIFICATION_NONE:
                    continue

                use_text = twilio_client \
                    and c.PANELS_TWILIO_NUMBER \
                    and attendee.cellphone \
                    and attendee.notification_pref == Attendee._NOTIFICATION_TEXT

                event = signup.event

                # If we overlap multiple notices, we only want to send a single
                # notification. So if we have both "5 minutes before checkin" and
                # "when checkin starts", we only want to send the notification
                # for "when checkin starts".
                advance_notice = min(advance_notices)
                if advance_notice == -1 or advance_notice > 1800:
                    checkin = 'is at {}'.format(event.checkin_start_time_label)
                else:
                    checkin = humanize_timedelta(
                        event.time_remaining_to_checkin,
                        granularity='minutes',
                        separator=' ',
                        prefix='is in ',
                        now='is right now',
                        past_prefix='was ',
                        past_suffix=' ago')

                ident = AttractionEvent.get_ident(event.id, advance_notice)
                try:
                    if use_text:
                        type_ = Attendee._NOTIFICATION_TEXT
                        type_str = 'TEXT'
                        from_ = c.PANELS_TWILIO_NUMBER
                        to_ = attendee.cellphone
                        body = TEXT_TEMPLATE.format(signup=signup, checkin=checkin)
                        subject = ''
                        sid = send_sms_with_client(twilio_client, to_, body, from_)

                    if not use_text or is_first_signup:
                        type_ = Attendee._NOTIFICATION_EMAIL
                        type_str = 'EMAIL'
                        from_ = c.ATTRACTIONS_EMAIL
                        to_ = attendee.email
                        if is_first_signup:
                            template = 'emails/panels/attractions_welcome.html'
                            subject = 'Welcome to {} Attractions'.format(c.EVENT_NAME)
                        else:
                            template = 'emails/panels/attractions_notification.html'
                            subject = 'Checkin for {} is at {}'.format(event.name, event.checkin_start_time_label)

                        body = render(template, {
                            'signup': signup,
                            'checkin': checkin,
                            'c': c}).decode('utf-8')
                        sid = ident
                        send_email(from_, to_, subject=subject, body=body, format='html', model=attendee, ident=ident)
                except Exception:
                    log.error(
                        'Error sending notification\n'
                        '\tfrom: {}\n'
                        '\tto: {}\n'
                        '\tsubject: {}\n'
                        '\tbody: {}\n'
                        '\ttype: {}\n'
                        '\tattendee: {}\n'
                        '\tident: {}\n'.format(
                            from_,
                            to_,
                            subject,
                            body,
                            type_str,
                            attendee.id,
                            ident), exc_info=True)
                else:
                    session.add(AttractionNotification(
                        attraction_event_id=event.id,
                        attraction_id=event.attraction_id,
                        attendee_id=attendee.id,
                        notification_type=type_,
                        ident=ident,
                        sid=sid,
                        sent_time=datetime.now(pytz.UTC),
                        subject=subject,
                        body=body))
                    session.commit()
示例#7
0
 def duration_label(self):
     if self.duration:
         return humanize_timedelta(seconds=self.duration, separator=' ')
     return 'unknown duration'
示例#8
0
 def time_remaining_to_checkin_label(self):
     return humanize_timedelta(self.time_remaining_to_checkin, granularity='minutes', separator=' ')
示例#9
0
 def test_humanize_timedelta(self, test_args, test_kwargs, expected):
     assert expected == humanize_timedelta(*test_args, **test_kwargs)
示例#10
0
 def duration_label(self):
     if self.duration:
         return humanize_timedelta(seconds=self.duration, separator=' ')
     return 'unknown duration'
示例#11
0
 def time_remaining_to_checkin_label(self):
     return humanize_timedelta(self.time_remaining_to_checkin, granularity='minutes', separator=' ')