Source

Mango / views.py

Full commit
#!/usr/bin/python
# -*- coding: utf-8 -*-

import hashlib
import urllib

import disqus

from django.core.mail import EmailMultiAlternatives
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, HttpResponseServerError
from django.template.defaultfilters import slugify
from django.template.loader import render_to_string

from mango.settings import DISQUS, DISQUS_API_KEY, FORUM, SITE_TITLE, SOURCE_SUFFIX, SUBSCRIPTIONS
from mango.decorators import baseurl
from mango.exceptions import EmptySettingError
from mango.forms import CommentForm, ContactForm
from mango.main import Category, Document, Index
if SUBSCRIPTIONS:
    from mango.models import Subscription
from mango.templatetags.mango_extras import _convert, convert
from mango.utils import html_response, logger, primary_author_email, replace, text_response

@baseurl
def archives(request):
    return html_response('archives.dhtml', request)

@baseurl
def category(request, category):
    return html_response('category.dhtml', request, {'category': category})

@baseurl
def contact(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            subject = form.cleaned_data['subject']
            message = form.cleaned_data['message']
            sender = u'%s <%s>' % (form.cleaned_data['sender_name'], form.cleaned_data['sender_email'])

            try:
                recipients = [primary_author_email()]
            except EmptySettingError, error:
                logger.error(error.message)
                return HttpResponseServerError(error.html())

            headers = {'Reply-To': sender}
            if form.cleaned_data['cc_sender']:
                headers['Cc'] = sender # `cc` argument added in Django 1.3
                recipients.append(sender)

            msg = EmailMultiAlternatives(subject, message, sender, recipients, headers=headers)
            msg.attach_alternative(replace(convert(message)), 'text/html')
            msg.send(fail_silently=False)
            return HttpResponseRedirect(reverse(message_sent))
    else:
        form = ContactForm()

    return html_response('contact.dhtml', request, {'form': form})

@baseurl
def index(request):
    return html_response('index.dhtml', request)

@baseurl
def message_sent(request):
    return html_response('contact.dhtml', request)

@baseurl
def page_not_found(request):
    return html_response('404.dhtml', request, status_code=404)

@baseurl
def post(request, path):
    path_ = path
    path = u'%s%s/' % (reverse(index), path)
    found = Index.get().find_match(path)
    if not isinstance(found, (Category, Document)):
        return page_not_found(request)

    rel = found.urls['canon']['rel']
    if path != rel:
        return HttpResponseRedirect(found.permalink())

    if isinstance(found, Category):
        return category(request, found)

    document = found # we've confirmed that the we're to serve a Document
    thread = document._thread

    comment = request.session.pop('comment', None) if thread else None
    if comment is not None:
        comment = render_to_string('comment.dhtml', {'comment': comment})

    while True: # avoids excessive indentation
        form = CommentForm()
        if request.method != 'POST': break

        form = CommentForm(request.POST, request=request)
        if not form.is_valid(): break

        author_name = form.cleaned_data['author_name']
        author_email = form.cleaned_data['author_email']
        author_url = form.cleaned_data['author_url']
        message = form.cleaned_data['message']
        subscribe = form.cleaned_data['subscribe']

        if subscribe and SUBSCRIPTIONS: # don't assume that SUBSCRIPTIONS is True
            subscriptions = Subscription.objects.filter(
                    subscriber_email=author_email, url=document.permalink())
            if not subscriptions:
                subscription = Subscription(subscriber_name=author_name,
                        subscriber_email=author_email, url=document.permalink())
                subscription.save()
            logger.debug('%s is %s subscribed to comments on %s' % (author_name,
                    'already' if subscriptions else 'now', document.title_text))

        if not thread: break

        try:
            # send request to Disqus
            comment = DISQUS.create_post(FORUM, thread,
                    message=message,
                    author_name=author_name,
                    author_email=author_email,
                    author_url=author_url,
                    ip_address=request.META['REMOTE_ADDR'])
        except disqus.APIError, error:
            logger.warning('Disqus API error: %s' % error)
            break

        # store comment so that it can be displayed to
        # its author even if withheld for moderation
        comment.html = _convert(comment.message)
        request.session['comment'] = comment

        # send e-mail notification
        post_url = request.build_absolute_uri(reverse(post, args=(path_,)))
        params = {
            'api_key': hashlib.sha1(DISQUS_API_KEY).hexdigest(),
            'post_id': comment.id,
            'thread_id': thread.id,
            'url': post_url,
        }
        links = {
            'approve':  ('api_key', 'post_id', 'url'),
            'close':    ('api_key', 'thread_id'),
            'delete':   ('api_key', 'post_id'),
            'spam':     ('api_key', 'post_id', 'thread_id'),
        }
        author = u'%s <%s>' % (author_name, author_email)
        subject = u'[%s] Comment: "%s"' % (SITE_TITLE, document.title_text)
        context = {
            'comment': message,
            'commenter': author,
            'urls': dict([('post', post_url)] + [(action, u'%s?%s' % (
                    request.build_absolute_uri(reverse('mango.handlers.moderate', args=(action,))),
                    urllib.urlencode([(k, params[k]) for k in keys])))
                    for action, keys in links.items()]),
        }
        try:
            recipient = primary_author_email()
        except EmptySettingError, error:
            logger.error(error.message)
            return HttpResponseServerError(error.html())

        msg = EmailMultiAlternatives(subject, render_to_string('email/moderator.dtext', context),
                to=[recipient], headers={'Reply-To': author})
        msg.attach_alternative(render_to_string('email/moderator.dhtml', context), 'text/html')
        msg.send(fail_silently=False)

        return HttpResponseRedirect(reverse('mango.handlers.redirect', args=(path_, comment.id)))

    return html_response('%s.dhtml' % document.type, request, {
        'comments': document.comments(),
        'document': document,
        'form': form,
        'new_comment': comment,
        'thread': thread,
    })

@baseurl
def search(request):
    query = request.GET.get('query')
    if not query:
        message = 'Please submit a GET request with a parameter named "query".'
        return text_response(message, 400)

    # convert query to a list of search terms
    terms = []
    for index, fragment in enumerate(query.strip().lower().split('"')):
        if index % 2: # every second fragment is quoted
            terms.append(fragment)
        else:
            for word in fragment.split():
                terms.append(word)

    # determine which documents match the search terms
    pages, posts = [], []
    for document in Index.get().descendants(include_pages=True):
        for term in terms:
            if document.body.lower().find(term) == -1:
                break
        else:
            if document.type == 'page':
                pages.append(document)
            else:
                posts.append(document)

    return html_response('searchresults.dhtml', request,
            {'results': {'pages': pages, 'posts': posts}, 'terms': terms})

@baseurl
def tagged_as(request, tag):
    tag = slugify(tag)
    documents = []
    for document in Index.get().descendants(include_pages=True):
        if tag in [slugify(t) for t in document.meta.get('tags', [])]:
            documents.append(document)
    return html_response('tag.dhtml', request, {'documents': documents, 'tag': tag})

@baseurl
def tags(request):
    return html_response('tags.dhtml', request)

@baseurl
def view_source(request, path):
    path = u'%s%s/' % (reverse(index), path)
    found = Index.get().find_match(path)

    if isinstance(found, Category):
        return HttpResponseRedirect(found.permalink())

    if isinstance(found, Document):
        rel = found.urls['canon']['rel']
        if path == rel:
            return text_response(found.body)
        else:
            return HttpResponseRedirect('%s%s' % (found.permalink(), SOURCE_SUFFIX))

    return page_not_found(request)