示例#1
0
def add_coffee(runid=None):
    logger = logging.getLogger('views.add_coffee')
    runs = Run.query.filter(Run.time >= sydney_timezone_now()).filter_by(
        is_open=True).all()
    form = CoffeeForm(request.form)
    form.runid.choices = [(-1, '')] + [(r.id, r.prettyprint()) for r in runs]
    if runid:
        run = Run.query.filter_by(id=runid).first()
        localmodified = run.time.replace(
            tzinfo=pytz.timezone("Australia/Sydney"))
        if sydney_timezone_now() > localmodified:
            flash("You can't add coffees to this run", "danger")
            return redirect(url_for("view_run", runid=runid))
        form.runid.data = runid
    users = User.query.all()
    form.person.choices = [(user.id, user.name) for user in users]

    if request.method == "GET":
        form.person.data = current_user.id
        return render_template("coffeeform.html",
                               form=form,
                               formtype="Add",
                               current_user=current_user)

    if form.validate_on_submit():
        logger.info('Form: %s', form.data)
        coffee = Coffee(form.data["coffee"], form.data['price'],
                        form.data['runid'])
        person = User.query.filter_by(id=form.data["person"]).first()
        coffee.personid = person.id
        coffee.addict = person
        if form.data["runid"] == -1:
            coffee.starttime = form.data["starttime"]
            coffee.endtime = form.data["endtime"]
        else:
            coffee.runid = form.data["runid"]
            run = Run.query.filter_by(id=form.data["runid"]).first()
        coffee.modified = sydney_timezone_now()
        db.session.add(coffee)
        db.session.commit()
        write_to_events("created", "coffee", coffee.id)
        if form.data["runid"] != -1:
            try:
                events.coffee_added(coffee.runid, coffee.id)
            except Exception as e:
                logging.exception('Error while trying to send notifications.')
                flash(
                    'Error occurred while trying to send notifications. Please tell Maddy, Elmo, or Katie.\n{}'
                    .format(cgi.escape(str(e), quote=True)), "failure")
        flash("Coffee order added", "success")
        return redirect(url_for("view_coffee", coffeeid=coffee.id))
    else:
        for field, errors in form.errors.items():
            flash("Error in %s: %s" % (field, "; ".join(errors)), "danger")
        return render_template("coffeeform.html",
                               form=form,
                               current_user=current_user)
示例#2
0
def list_runs(slackclient, user, channel, match):
    """Handle the 'open runs' command.

  This command only displays the open runs. If there are multiple runs
  currently open, it orders them by time (on the assumption that you want
  things in the first available run).

  Args:
    slackclient: the slackclient.SlackClient object for the current
      connection to Slack.
    user: the slackclient.User object for the user who send the
      message to us.
    channel: the slackclient.Channel object for the channel the
      message was received on.
    match: the object returned by re.match (an _sre.SRE_Match object).
  """
    now = sydney_timezone_now()
    q = Run.query.filter_by(is_open=True).order_by('time').all()
    if not q:
        channel.send_message('No open runs')
        return (True, None)
    for run in q:
        person = User.query.filter_by(id=run.person).first()
        time_to_run = run.time - now
        channel.send_message('Run {}: {} is going to {} in {} (at {})'.format(
            run.id, person.name, run.cafe.name,
            flask_babel.format_timedelta(time_to_run), run.time))
    return (True, None)
示例#3
0
def write_to_events(action, objtype, objid, user=None):
    if user:
        event = Event(user.id, action, objtype, objid)
    else:
        event = Event(current_user.id, action, objtype, objid)
    event.time = sydney_timezone_now()
    db.session.add(event)
    db.session.commit()
    return event.id
示例#4
0
    def create_run(self, slackclient, user, channel, match):
        """Create an open run

        Args:
            slackclient: the slackclient.SlackClient object for the current
                connection to Slack.
            user: the slackclient.User object for the user who send the
                message to us.
            channel: the slackclient.Channel object for the channel the
                message was received on.
            match: the object returned by re.match (an _sre.SRE_Match object).
        """
        logger = logging.getLogger('create_run')
        logger.info('Matches: %s', pprint.pformat(match.groupdict()))
        cafeid = match.group('cafeid')
        if cafeid and cafeid.isdigit():
            cafe = Cafe.query.filter_by(id=int(cafeid)).first()
        if not cafe:
            channel.send_message('Cafe does not exist. These are the available cafes:')
            self.list_cafes(slackclient, user, channel, match=None)
            return

        pickup = match.groupdict().get('pickup', None)
        timestr = match.groupdict().get('time', None)

        # Get the person creating the run
        person = utils.get_or_create_user(user.id, self.TEAM_ID, user.name)
        logger.info('User: %s', dbuser)

        # Assume valid? Create the run
        run = Run(timestr)
        run.person = person
        run.fetcher = person
        run.cafeid = cafeid
        run.pickup = pickup
        run.modified = sydney_timezone_now()
        run.is_open = True

        db.session.add(run)
        db.session.commit()

        # Create the event
        self.write_to_events("created", "run", run.id, run.person)

        # Notify Slack
        try:
            events.run_created(run.id)
        except Exception as e:
            logging.exception('Error while trying to send notifications.')
示例#5
0
def edit_coffee(coffeeid):
    coffee = Coffee.query.filter(Coffee.id == coffeeid).first_or_404()
    form = CoffeeForm(request.form, obj=coffee)
    runs = Run.query.filter_by(is_open=True).all()
    form.runid.choices = [(r.id, r.prettyprint()) for r in runs]

    # Make sure it is possible to edit coffees in a run that has already been
    # closed. We do this by adding the existing coffee run to the dropdown.
    if coffee.run and coffee.run.id not in [r.id for r in runs]:
        form.runid.choices.append((coffee.run.id, coffee.run.prettyprint()))

    c = coffeespecs.Coffee.fromJSON(coffee.coffee)
    users = User.query.all()
    form.person.choices = [(user.id, user.name) for user in users]

    if request.method == "GET":
        form.coffee.data = str(c)
        form.runid.data = coffee.runid
        return render_template("coffeeform.html",
                               form=form,
                               formtype="Edit",
                               price=coffee.price,
                               current_user=current_user)

    if request.method == "POST" and form.validate_on_submit():
        coffee.coffee = coffeespecs.Coffee(form.data["coffee"]).toJSON()
        coffee.price = form.data["price"]
        coffee.runid = form.data['runid']
        coffee.person = form.data['person']
        coffee.modified = sydney_timezone_now()
        db.session.commit()
        write_to_events("updated", "coffee", coffee.id)
        flash("Coffee edited", "success")
        return redirect(url_for("view_coffee", coffeeid=coffee.id))
    else:
        for field, errors in form.errors.items():
            flash("Error in %s: %s" % (field, "; ".join(errors)), "danger")
        return render_template("coffeeform.html",
                               form=form,
                               formtype="Edit",
                               current_user=current_user)
示例#6
0
def add_run(cafeid=None):
    form = RunForm(request.form)
    users = User.query.all()
    form.person.choices = [(user.id, user.name) for user in users]
    cafes = Cafe.query.all()
    if not cafes:
        flash(
            "There are no cafes currently configured. Please add one before creating a run",
            "warning")
        return redirect(url_for("home"))
    form.cafeid.choices = [(cafe.id, cafe.name) for cafe in cafes]

    if request.method == "GET":
        if cafeid:
            form.cafeid.data = cafeid
        form.person.data = current_user.id

        # Generate a time for the run. The algorithm here is we want the
        # default run time to be at least 15 minutes in the future, and also a
        # multiple of 15 minutes (since it look nicer).
        # This means that by default, the run will be between 15 and 30 minutes
        # from the current time.
        t = sydney_timezone_now().replace(second=0, microsecond=0)
        t += datetime.timedelta(minutes=15)
        t += datetime.timedelta(
            minutes=15 -
            (t.minute % 15))  # truncate up to the nearest 15 minutes
        form.time.data = t
        form.is_open.data = True

        return render_template("runform.html",
                               form=form,
                               formtype="Add",
                               current_user=current_user)

    if form.validate_on_submit():
        # Add run
        run = Run(form.data["time"])
        person = User.query.filter_by(id=form.data["person"]).first()
        run.person = person.id
        run.fetcher = person
        run.cafeid = form.data["cafeid"]
        run.pickup = form.data["pickup"]
        run.modified = sydney_timezone_now()
        run.is_open = form.data["is_open"]

        db.session.add(run)
        db.session.commit()
        try:
            events.run_created(run.id)
        except Exception as e:
            logging.exception('Error while trying to send notifications.')
            flash(
                'Error occurred while trying to send notifications. Please tell Maddy, Elmo, or Katie.\n{}'
                .format(cgi.escape(str(e), quote=True)), "failure")
        write_to_events("created", "run", run.id)
        flash("Run added", "success")
        return redirect(url_for("view_run", runid=run.id))
    else:
        for field, errors in form.errors.items():
            flash("Error in %s: %s" % (field, "; ".join(errors)), "danger")
        return render_template("runform.html",
                               form=form,
                               formtype="Add",
                               current_user=current_user)
示例#7
0
def order_coffee(slackclient, user, channel, match):
    """Handle adding coffee to existing orders.

  Args:
    slackclient: the slackclient.SlackClient object for the current
      connection to Slack.
    user: the slackclient.User object for the user who send the
      message to us.
    channel: the slackclient.Channel object for the channel the
      message was received on.
    match: the object returned by re.match (an _sre.SRE_Match object).
  """
    logger = logging.getLogger('order_coffee')
    logger.info('Matches: %s', pprint.pformat(match.groupdict()))
    runid = match.groupdict().get('runid', None)
    run = None
    if runid and runid.isdigit():
        run = Run.query.filter_by(id=int(runid)).first()
    if not run:
        # Pick a run
        runs = Run.query.filter_by(is_open=True).order_by('time').all()
        if len(runs) > 1:

            def resolve_run_feedback():
                channel.send_message(
                    'More than one open run, please specify by adding run=<id> on the end.'
                )
                list_runs(slackclient, user, channel, match=None)

            return (False, resolve_run_feedback)
        if len(runs) == 0:

            def resolve_closed_feedback():
                channel.send_message('No open runs')

            return (False, resolve_closed_feedback)
        run = runs[0]

    # Create the coffee
    c = coffeespecs.Coffee(match.groupdict().get('order', None))
    validation_errors = list(c.validation_errors())
    if validation_errors:

        def resolve_validation_feedback():
            channel.send_message(
                'That coffee is not valid missing the following specs: {}. Got: {}'
                .format(
                    ', '.join(spec.name for spec in validation_errors),
                    c,
                ))

        return (False, resolve_validation_feedback)
    coffee = Coffee(c, 0, run.id)

    # Find the user that requested this
    dbuser = utils.get_or_create_user(user.id, TEAM_ID, user.name)
    logger.info('User: %s', dbuser)

    # Put it all together
    coffee.person = dbuser.id
    db.session.add(coffee)
    db.session.commit()
    events.coffee_added(run.id, coffee.id)

    # Write the event
    event = Event(coffee.person, "created", "coffee", coffee.id)
    event.time = sydney_timezone_now()
    db.session.add(event)
    db.session.commit()
    logger.info('Parsed coffee: %s', coffee)

    runuser = User.query.filter_by(id=run.person).first()
    if runuser.slack_user_id:
        mention_runner = '<@{}>'.format(runuser.slack_user_id)
    else:
        mention_runner = runuser.name
    channel.send_message('That\'s a {} for {} (added to {}\'s run.)'.format(
        coffee.pretty_print(), mention(user), mention_runner))
    return (True, None)