示例#1
0
def edit_poster(poster_id):
    sqlsession = Session()
    # Look up Poster
    poster = (sqlsession.query(models.Poster)
                        .options(
                            joinedload(models.Poster.emails))
                        .filter(models.Poster.id == poster_id)).one()

    if request.method == 'POST':
        changed = False
        if 'remove_email' in request.form:
            email = request.form['remove_email']
            (sqlsession.query(models.PosterEmail)
                       .filter(models.PosterEmail.poster_id == poster_id)
                       .filter(models.PosterEmail.address == email)).delete()
            changed = True
        if 'add_email' in request.form:
            email = request.form['add_email']
            new_email = models.PosterEmail(address=email, poster=poster)
            sqlsession.add(new_email)
            changed = True
        if 'name' in request.form:
            poster.name = request.form['name']
            sqlsession.add(poster)
            changed = True

        if changed:
            sqlsession.commit()
        return redirect(url_for('edit_poster', poster_id=poster_id), 303)

    return render_template('edit_poster.html', poster=poster,
                           msg=request.form.get('msg'),
                           error=request.form.get('error'))
示例#2
0
def assign_task(thread_id):
    """Assign a new task to a thread.
    """
    sqlsession = Session()
    thread = (sqlsession.query(models.Thread)
                        .filter(models.Thread.id == thread_id)).one()
    task = (sqlsession.query(models.Task)
                      .filter(models.Task.id == request.form['task'])).one()
    poster_req = (sqlsession.query(models.Poster)
                            .filter(models.Poster.id == request.form['poster']))
    poster = poster_req.one()
    # Note that, although the Poster definitely exists, here we don't check
    # that he took part in the thread

    try:
        # Assign task
        task_assignation = models.TaskAssignation(
                thread=thread,
                task=task,
                poster=poster)
        sqlsession.add(task_assignation)
        # Update Poster's score
        poster_req.update({
                models.Poster.score: models.Poster.score + task.reward})
        sqlsession.commit()
    except IntegrityError:
        pass
    return redirect(url_for('thread', thread_id=thread_id), 303)
示例#3
0
def scores():
    """Scores.

    Display a list of contributors with their current number of points.
    """
    sqlsession = Session()
    posters = (sqlsession.query(models.Poster)
                         .order_by(models.Poster.score.desc())).all()
    return render_template('scores.html', posters=posters)
示例#4
0
def add_email():
    """Create a new Poster or add an address to an existing Poster.
    """
    sqlsession = Session()
    email = request.form['email']
    # Look up a Poster with that email
    poster_email = (sqlsession.query(models.PosterEmail)
                              .options(
                                  joinedload(models.PosterEmail.poster))
                              .filter(models.PosterEmail.address == email))
    try:
        poster_email = poster_email.one()
    except NoResultFound:
        pass
    else:
        return redirect(url_for(
                'edit_poster', poster=poster_email.poster.id,
                error="This email is already associated to a poster"))

    # If we got poster the info to create a new poster
    if 'name' in request.form and 'poster_id' not in request.form:
        new_poster = models.Poster(name=request.form['name'])
        sqlsession.add(new_poster)
        new_email = models.PosterEmail(address=email, poster=new_poster)
        sqlsession.add(new_email)
        sqlsession.commit()
        return redirect(url_for('edit_poster', poster_id=new_poster.id,
                                msg='Poster created'), 303)
    elif 'name' not in request.form and 'poster_id' in request.form:
        poster_id = int(request.form['poster_id'])
        poster = (sqlsession.query(models.Poster)
                            .filter(models.Poster.id == poster_id)).one()
        new_email = models.PosterEmail(address=email, poster=poster)
        sqlsession.add(new_email)
        sqlsession.commit()
        return redirect(url_for('edit_poster', poster_id=poster.id), 303)
    # If both are set, something is going on, just display the forms again

    # Renders the form that will allow to choose an existing Poster or to
    # create a new one
    # In both cases, redirect here
    all_posters = sqlsession.query(models.Poster).all()
    return render_template('add_email.html', email=email,
                           posters=all_posters)
示例#5
0
def vote():
    """Main view.

    Shows the list of threads that require resolution.
    """
    sqlsession = Session()
    threads = (sqlsession.query(models.Thread)
                         .options(
                             joinedload(models.Thread.task_assignations)
                                 .joinedload(models.TaskAssignation.task),
                             joinedload(models.Thread.messages))
                         .order_by(models.Thread.last_msg.desc())).all()
    return render_template('vote.html', threads=threads)
示例#6
0
def thread(thread_id):
    """Shows a thread and allows to vote on it.
    """
    sqlsession = Session()
    thread = (sqlsession.query(models.Thread)
                        .options(
                            joinedload(models.Thread.messages)
                                .joinedload(models.Message.poster_email)
                                .joinedload(models.PosterEmail.poster),
                            joinedload(models.Thread.task_assignations))
                        .filter(models.Thread.id == thread_id)).one()
    tasks = (sqlsession.query(models.Task)).all()
    posters = set(msg.poster_email.poster
                  for msg in thread.messages
                  if msg.poster_email is not None)
    # The email addresses participating in this thread but not yet associated
    # to a Poster
    registerable_senders = [msg.from_
                            for msg in thread.messages
                            if not msg.poster_email]
    return render_template('thread.html',
                           thread=thread, tasks=tasks, posters=posters,
                           registerable_senders=registerable_senders)
示例#7
0
def main():
    logging.basicConfig(level=logging.INFO)

    host, use_ssl, port, user, password = config.INBOX
    if callable(user):
        user = user()
    if callable(password):
        password = password()

    for msg in get_messages(host, use_ssl, port, user, password):
        # Feed it to Python's standard RFC 2822-based message parser
        parser = Parser()
        msg = parser.parsestr(msg)

        # Headers of interest
        msgid = msg["Message-ID"]
        replyto = msg["In-Reply-To"]
        subject = decode_subject(msg["Subject"])
        from_ = email.utils.parseaddr(msg["From"])[1]
        date = email.utils.parsedate_tz(msg["Date"])
        if date:
            date = datetime.fromtimestamp(email.utils.mktime_tz(date))

        logger.debug("Parsing message from %r" % (from_,))

        # Find text content
        if msg.is_multipart():
            logger.debug("Message is multipart with %d parts" % (len(msg.get_payload()),))
            # RFC 2046 says that the last part is preferred
            text = None
            is_html = True
            for part in msg.get_payload():
                if part.get_content_type() == "text/plain" or (part.get_content_type() == "text/html" and is_html):
                    charset = part.get_charsets()[0]
                    text = part.get_payload(decode=True).decode(charset, "replace")
                    is_html = part.get_content_type() == "text/html"
            if text is not None:
                logger.debug("Found a text part (text/%s)" % ("html" if is_html else "plain"))
            else:
                logger.debug("Didn't find a text part")
            if text is None:
                text = msg.preamble
                is_html = False
                if text:
                    logger.debug("Using preamble")
        else:
            charset = msg.get_charsets()[0]
            text = msg.get_payload(decode=True).decode(charset, "replace")
            content_type = msg.get_content_type()
            is_html = content_type == "text/html"
            logger.debug("Message is not multipart (%s)" % (content_type,))

        if not text:
            logger.warning("Message from %r has no text!" % (from_,))
            text = "(No text content found)"
        elif is_html:
            try:
                import html2text
            except ImportError:
                warnings.warn("Can't convert HTML to text -- html2text " "library not found")
            else:
                logger.debug("Converting HTML with html2text")
                h = html2text.HTML2Text()
                text = h.handle(text)
            is_html = False

        # Find thread this message is a part of
        sqlsession = Session()
        thread = None
        if replyto:
            try:
                parent_msg = sqlsession.query(models.Message).filter(models.Message.id == replyto).one()
            except NoResultFound:
                pass
            else:
                thread = parent_msg.thread
                logger.debug("Message is part of existing thread %d" % (thread.id,))
        if thread is None:
            thread = models.Thread(last_msg=date)
            thread_created = True
            sqlsession.add(thread)
        else:
            thread_created = False
            # FIXME : This should be synchronized somehow
            # Update last_msg date field
            if thread.last_msg < date:
                thread.last_msg = date
                sqlsession.add(thread)

        # Insert message
        message = models.Message(id=msgid, thread=thread, date=date, from_=from_, subject=subject, text=text)
        sqlsession.add(message)
        try:
            sqlsession.commit()
        except IntegrityError:
            sqlsession.rollback()
            logger.info("Got IntegrityError inserting message, skipping")
        else:
            if thread_created:
                logger.debug("Created new thread %d" % (thread.id,))