<commit_before>import json
from datetime import timedelta
from functools import wraps

import cherrypy
from email_validator import validate_email, EmailNotValidError
from pockets import listify
from pockets.autolog import log
from sqlalchemy import func

from uber.config import c
from uber.decorators import all_renderable, check_if_can_reg, credit_card, csrf_protected, id_required, log_pageview, \
    redirect_if_at_con_to_kiosk, render
from uber.errors import HTTPRedirect
from uber.models import Attendee, Email, Group, PromoCode, PromoCodeGroup, Tracking
from uber.tasks.email import send_email
from uber.utils import add_opt, check, check_pii_consent, localized_now, Charge


def check_post_con(klass):
    def wrapper(func):
        @wraps(func)
        def wrapped(self, *args, **kwargs):
            if c.POST_CON:  # TODO: replace this with a template and make that suitably generic
                return """
                <html><head></head><body style='text-align:center'>
                    <h2 style='color:red'>Hope you had a great {event}!</h2>
                    Preregistration for {event} {year} will open in a few months.
                </body></html>
                """.format(event=c.EVENT_NAME, year=(1 + int(c.EVENT_YEAR)) if c.EVENT_YEAR else '')
            else:
                return func(self, *args, **kwargs)
        return wrapped

    for name in dir(klass):
        method = getattr(klass, name)
        if not name.startswith('_') and hasattr(method, '__call__'):
            setattr(klass, name, wrapper(method))
    return klass


@all_renderable()
@check_post_con
class Root:
    def _get_unsaved(self, id, if_not_found=None):
        """
        if_not_found:  pass in an HTTPRedirect() class to raise if the unsaved attendee is not found.
                       by default we will redirect to the index page
        """
        if id in Charge.unpaid_preregs:
            return Charge.from_sessionized(Charge.unpaid_preregs[id])
        else:
            raise HTTPRedirect('index') if if_not_found is None else if_not_found

    def kiosk(self):
        """
        Landing page for kiosk laptops, this should redirect to whichever page we want at-the-door laptop kiosks
        to land on.  The reason this is a redirect is that at-the-door laptops might be imaged and hard to change
        their default landing page.  If sysadmins want to change the landing page, they can do it here.
        """
        raise HTTPRedirect(c.KIOSK_REDIRECT_URL)

    def check_prereg(self):
        return json.dumps({
            'force_refresh': not c.AT_THE_CON and (c.AFTER_PREREG_TAKEDOWN or c.BADGES_SOLD >= c.MAX_BADGE_SALES)})

    def check_if_preregistered(self, session, message='', **params):
        if 'email' in params:
            attendee = session.query(Attendee).filter(func.lower(Attendee.email) == func.lower(params['email'])).first()
            message = 'Thank you! You will receive a confirmation email if ' \
                'you are registered for {}.'.format(c.EVENT_NAME_AND_YEAR)

            subject = c.EVENT_NAME_AND_YEAR + ' Registration Confirmation'

            if attendee:
                last_email = (session.query(Email)
                                     .filter_by(to=attendee.email, subject=subject)
                                     .order_by(Email.when.desc()).first())
                if not last_email or last_email.when < (localized_now() - timedelta(days=7)):
                    send_email.delay(
                        c.REGDESK_EMAIL,
                        attendee.email,
                        subject,
                        render('emails/reg_workflow/prereg_check.txt', {'attendee': attendee}, encoding=None),
                        model=attendee.to_dict('id'))

        return {'message': message}

    @check_if_can_reg
    def index(self, session, message=''):
        if not Charge.unpaid_preregs:
            raise HTTPRedirect('form?message={}', message) if message else HTTPRedirect('form')
        else:
            charge = Charge(listify(Charge.unpaid_preregs.values()))
            for attendee in charge.attendees:
                if attendee.promo_code:
                    attendee.group_name = session.query(PromoCode).filter_by(
                        code=attendee.promo_code.code).first().group.name
            return {
                'message': message,
                'charge': charge
            }

    @check_if_can_reg
    def dealer_registration(self, message=''):
        return self.form(badge_type=c.PSEUDO_DEALER_BADGE, message=message)

    @check_if_can_reg
    def repurchase(self, session, id, **params):
        if 'csrf_token' in params:
            old_attendee = session.attendee(id).to_dict(c.UNTRANSFERABLE_ATTRS)
            del old_attendee['id']
            new_attendee = Attendee(**old_attendee)
            Charge.unpaid_preregs[new_attendee.id] = Charge.to_sessionized(new_attendee)
            Tracking.track(c.UNPAID_PREREG, new_attendee)<commit_msg>Don't try to pull the promo code's group name if it doesn't have a group Fixes https://jira.magfest.net/browse/MAGDEV-445. Whoops.<commit_after>import json
from datetime import timedelta
from functools import wraps

import cherrypy
from email_validator import validate_email, EmailNotValidError
from pockets import listify
from pockets.autolog import log
from sqlalchemy import func

from uber.config import c
from uber.decorators import all_renderable, check_if_can_reg, credit_card, csrf_protected, id_required, log_pageview, \
    redirect_if_at_con_to_kiosk, render
from uber.errors import HTTPRedirect
from uber.models import Attendee, Email, Group, PromoCode, PromoCodeGroup, Tracking
from uber.tasks.email import send_email
from uber.utils import add_opt, check, check_pii_consent, localized_now, Charge


def check_post_con(klass):
    def wrapper(func):
        @wraps(func)
        def wrapped(self, *args, **kwargs):
            if c.POST_CON:  # TODO: replace this with a template and make that suitably generic
                return """
                <html><head></head><body style='text-align:center'>
                    <h2 style='color:red'>Hope you had a great {event}!</h2>
                    Preregistration for {event} {year} will open in a few months.
                </body></html>
                """.format(event=c.EVENT_NAME, year=(1 + int(c.EVENT_YEAR)) if c.EVENT_YEAR else '')
            else:
                return func(self, *args, **kwargs)
        return wrapped

    for name in dir(klass):
        method = getattr(klass, name)
        if not name.startswith('_') and hasattr(method, '__call__'):
            setattr(klass, name, wrapper(method))
    return klass


@all_renderable()
@check_post_con
class Root:
    def _get_unsaved(self, id, if_not_found=None):
        """
        if_not_found:  pass in an HTTPRedirect() class to raise if the unsaved attendee is not found.
                       by default we will redirect to the index page
        """
        if id in Charge.unpaid_preregs:
            return Charge.from_sessionized(Charge.unpaid_preregs[id])
        else:
            raise HTTPRedirect('index') if if_not_found is None else if_not_found

    def kiosk(self):
        """
        Landing page for kiosk laptops, this should redirect to whichever page we want at-the-door laptop kiosks
        to land on.  The reason this is a redirect is that at-the-door laptops might be imaged and hard to change
        their default landing page.  If sysadmins want to change the landing page, they can do it here.
        """
        raise HTTPRedirect(c.KIOSK_REDIRECT_URL)

    def check_prereg(self):
        return json.dumps({
            'force_refresh': not c.AT_THE_CON and (c.AFTER_PREREG_TAKEDOWN or c.BADGES_SOLD >= c.MAX_BADGE_SALES)})

    def check_if_preregistered(self, session, message='', **params):
        if 'email' in params:
            attendee = session.query(Attendee).filter(func.lower(Attendee.email) == func.lower(params['email'])).first()
            message = 'Thank you! You will receive a confirmation email if ' \
                'you are registered for {}.'.format(c.EVENT_NAME_AND_YEAR)

            subject = c.EVENT_NAME_AND_YEAR + ' Registration Confirmation'

            if attendee:
                last_email = (session.query(Email)
                                     .filter_by(to=attendee.email, subject=subject)
                                     .order_by(Email.when.desc()).first())
                if not last_email or last_email.when < (localized_now() - timedelta(days=7)):
                    send_email.delay(
                        c.REGDESK_EMAIL,
                        attendee.email,
                        subject,
                        render('emails/reg_workflow/prereg_check.txt', {'attendee': attendee}, encoding=None),
                        model=attendee.to_dict('id'))

        return {'message': message}

    @check_if_can_reg
    def index(self, session, message=''):
        if not Charge.unpaid_preregs:
            raise HTTPRedirect('form?message={}', message) if message else HTTPRedirect('form')
        else:
            charge = Charge(listify(Charge.unpaid_preregs.values()))
            for attendee in charge.attendees:
                if attendee.promo_code and attendee.promo_code.group:
                    attendee.group_name = session.query(PromoCode).filter_by(
                        code=attendee.promo_code.code).first().group.name
            return {
                'message': message,
                'charge': charge
            }

    @check_if_can_reg
    def dealer_registration(self, message=''):
        return self.form(badge_type=c.PSEUDO_DEALER_BADGE, message=message)

    @check_if_can_reg
    def repurchase(self, session, id, **params):
        if 'csrf_token' in params:
            old_attendee = session.attendee(id).to_dict(c.UNTRANSFERABLE_ATTRS)
            del old_attendee['id']
            new_attendee = Attendee(**old_attendee)
            Charge.unpaid_preregs[new_attendee.id] = Charge.to_sessionized(new_attendee)
            Tracking.track(c.UNPAID_PREREG, new_attendee)
{'fraction_non_alphanumeric': 0.09212466817422083, 'fraction_numerical': 0.001081506243240586, 'mean_word_length': 2.382773528433655, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '234298', 'n_tokens_mistral': 3112, 'n_tokens_neox': 2991, 'n_words': 768}