Mango /

# -*- coding: utf-8 -*-

import hashlib
import re
import urllib

from django import http
from django.conf import settings
from django.core.mail import EmailMultiAlternatives, send_mail
from django.shortcuts import render_to_response
from django.template import RequestContext, loader
from django.template.defaultfilters import slugify

import mango
from mango.settings import *
from mango.exceptions import EmptySettingError
from mango.forms import CommentForm, ContactForm
from mango.models import Category, Document
    from mango.models import Subscription
from mango.utils import primary_author_email

def _defaults(request, context=None):
    if context is None:
        context = {}

    # make Mango's settings accessible to templates
    for key, value in mango.settings.__dict__.items():
        if not key.startswith('_'):
            context[key] = value

    # set top-level category
    toplevel = Category.toplevel()

    context['archives'] = toplevel.archives()
    context['posts'] = toplevel.descendants()
    context['tags'] = toplevel.tags()

    context['stylesheets'] = []
    for media, filenames in CSS[1:]:
        for filename in filenames:
            stylesheet = {'media': media, 'href': CSS[0] + filename}

    context['scripts'] = [JS[0] + filename for filename in JS[1:]]

    return RequestContext(request, context)

def archives(request):
    context = _defaults(request)
    return render_to_response('archives.dhtml', context_instance=context)

def category(request, category):
    context = _defaults(request, context={'category': category})
    return render_to_response('category.dhtml', context)

def contact(request, message_sent=False):
    if message_sent:
        context = _defaults(request)
        return render_to_response('contact.dhtml', context_instance=context)

    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'])

                recipients = [primary_author_email()]
            except EmptySettingError as e:
                return http.HttpResponseServerError(e.html())

            if form.cleaned_data['cc_sender']:

            send_mail(subject, message, sender, recipients, fail_silently=False)
            return http.HttpResponseRedirect('thanks/')
        form = ContactForm()

    context = _defaults(request, context={'form': form})
    return render_to_response('contact.dhtml', context_instance=context)

def index(request):
    context = _defaults(request)
    return render_to_response('index.dhtml', context_instance=context)

def page_not_found(request):
    t = loader.get_template('404.dhtml')
    return http.HttpResponseNotFound(t.render(_defaults(request,
            {'request_path': request.path})))

def post(request, path, view_source=False):
    path = u'/%s/' % path
    found = Category.toplevel().find_match(path)
    if not isinstance(found, (Category, Document)):
        return page_not_found(request)

    if isinstance(found, Category):
        if view_source or path != found.urls['canon']['rel']:
            return http.HttpResponseRedirect(found.urls['canon']['abs'])
        return category(request, found)

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

    if path != document.urls['canon']['rel']:
        url = document.urls['canon']['abs']
        url = url + 'm/' if view_source else url
        return http.HttpResponseRedirect(url)

    if view_source:
        return http.HttpResponse(document.body, content_type=PLAIN)

    form = CommentForm()
    thread = None
    comment = request.session.get('comment')
    if comment:
        del request.session['comment']
        comment = loader.render_to_string('comment.dhtml', {'comment': comment})

    comments = []
    if FORUM:
        # This call is only here for legacy and migration support, it will never return a value on Mango made threads
        thread = DISQUS.get_thread_by_url(FORUM, document.urls['canon']['abs'])
        if not thread:
            thread = DISQUS.thread_by_identifier(FORUM, document.title, document.urls['canon']['rel'])['thread']

        if request.method == 'POST':
            form = CommentForm(request.POST, request=request)
            if form.is_valid():
                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.urls['canon']['abs'])
                    if not subscriptions:
                        subscription = Subscription(subscriber_name=author_name,
                                subscriber_email=author_email, url=document.urls['canon']['abs'])
                    if settings.DEBUG:
                        print '%s is %s subscribed to comments on %s' % (author_name,
                                'already' if subscriptions else 'now', thread.title)

                # send request to Disqus
                comment = DISQUS.create_post(FORUM, thread,

                # store comment so that it can be displayed to the author even if withheld for moderation
                request.session['comment'] = comment

                # send e-mail notification
                author = u'%s <%s>' % (author_name, author_email)
                subject = u'[%s] Comment: "%s"' % (SITE_TITLE, document.title)
                context = {
                    'commenter': author,
                    'comment': message,
                    'base_url': BASE_URL,
                    'path': path,
                    'api_key': hashlib.sha1(DISQUS_API_KEY).hexdigest(),
                    recipient = primary_author_email()
                except EmptySettingError as e:
                    return http.HttpResponseServerError(e.html())

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

                return http.HttpResponseRedirect('redirect/')

        for c in DISQUS.get_thread_posts(FORUM, thread, limit=9999, exclude='killed'):
            if c.has_been_moderated:
        comments.sort(key=lambda comment: comment.created_at)

    context = _defaults(request, context={
        'comments': comments,
        'document': document,
        'form': form,
        'new_comment': comment,
        'thread': thread,
    return render_to_response('%s.dhtml' % document.type, context_instance=context)

def search(request):
    query = request.GET.get('query')
    if not query:
        message = 'Please submit a GET request with a parameter named "query".'
        return http.HttpResponseBadRequest(message, content_type=PLAIN)

    # convert query to a list of search terms
    query = re.sub(r'\s+', ' ', query.strip().lower())
    if query.count('"') % 2:
        query += '"'
    query = query.replace('""', '')
    query = re.sub(r'"(.+?)"', lambda m:' ', '+'), query)
    terms = [term.replace('+', ' ') for term in query.split()]

    # determine which documents match the search terms
    results = {'pages': [], 'posts': []}
    for document in Category.toplevel().descendants(pages=True):
        for term in terms:
            if document.body.lower().find(term) == -1:
            if document.type == 'page':

    context = _defaults(request, context={'results': results, 'terms': terms})
    return render_to_response('searchresults.dhtml', context_instance=context)

def tagged_as(request, tag):
    tag = slugify(tag)
    documents = []
    for document in Category.toplevel().descendants(pages=True):
        if tag in [slugify(t) for t in document.meta.get('tags', [])]:
    context = _defaults(request, context={'tag': tag, 'documents': documents})
    return render_to_response('tag.dhtml', context_instance=context)

def tags(request):
    context = _defaults(request)
    return render_to_response('tags.dhtml', context_instance=context)