diff options
Diffstat (limited to 'pgcommitfest/commitfest/ajax.py')
-rw-r--r-- | pgcommitfest/commitfest/ajax.py | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/pgcommitfest/commitfest/ajax.py b/pgcommitfest/commitfest/ajax.py new file mode 100644 index 0000000..b9c3db4 --- /dev/null +++ b/pgcommitfest/commitfest/ajax.py @@ -0,0 +1,137 @@ +from django.shortcuts import get_object_or_404 +from django.http import HttpResponse, Http404 +from django.conf import settings +from django.views.decorators.csrf import csrf_exempt +from django.contrib.auth.decorators import login_required +from django.db import transaction + +import httplib +import socket +import urllib +import simplejson + +class HttpResponseServiceUnavailable(HttpResponse): + status_code = 503 + +class Http503(Exception): + pass + +from models import CommitFest, Patch, MailThread, MailThreadAttachment, PatchHistory + +def _archivesAPI(suburl, params=None): + try: + socket.setdefaulttimeout(settings.ARCHIVES_TIMEOUT) + h = httplib.HTTPConnection(settings.ARCHIVES_SERVER, + settings.ARCHIVES_PORT, + True, + settings.ARCHIVES_TIMEOUT) + if params: + url = "%s?%s" % (suburl, urllib.urlencode(params)) + else: + url = suburl + h.request('GET', url, headers={ + 'Host': settings.ARCHIVES_HOST, + }) + resp = h.getresponse() + if resp.status != 200: + if resp.status == 404: + raise Http404() + raise Exception("JSON call failed: %s" % resp.status) + + r = simplejson.load(resp) + resp.close() + h.close() + except socket.error, e: + raise Http503("Failed to communicate with archives backend: %s" % e) + return r + +def getThreads(request): + search = request.GET.has_key('s') and request.GET['s'] or None + + # Make a JSON api call to the archives server + r = _archivesAPI('/list/pgsql-hackers/latest.json', {'n': 100}) + if search: + return sorted([x for x in r if x['subj'].lower().find(search)>=0 or x['from'].lower().find(search)>=0], key=lambda x: x['date'], reverse=True) + else: + return sorted(r, key=lambda x: x['date'], reverse=True) + + +def parse_and_add_attachments(threadinfo, mailthread): + for t in threadinfo: + if t['att']: + MailThreadAttachment.objects.get_or_create(mailthread=mailthread, + messageid=t['msgid'], + defaults={ + 'date': t['date'], + 'author': t['from'] + }) + # In theory we should remove objects if they don't have an + # attachment, but how could that ever happen? Ignore for now. + [email protected]_on_success +def attachThread(request): + cf = get_object_or_404(CommitFest, pk=int(request.POST['cf'])) + patch = get_object_or_404(Patch, pk=int(request.POST['p']), commitfests=cf) + msgid = request.POST['msg'] + + + r = sorted(_archivesAPI('/message-id.json/%s' % msgid), key=lambda x: x['date']) + # We have the full thread metadata - using the first and last entry, + # construct a new mailthread in our own model. + # First, though, check if it's already there. + if MailThread.objects.filter(messageid=r[0]['msgid'], patch=patch).exists(): + # It already existed. Pretend everything is fine. + return 'OK' + + # Now create a new mailthread entry + m = MailThread(messageid=r[0]['msgid'], + patch=patch, + subject=r[0]['subj'], + firstmessage=r[0]['date'], + firstauthor=r[0]['from'], + latestmessage=r[-1]['date'], + latestauthor=r[-1]['from'], + latestsubject=r[-1]['subj'], + latestmsgid=r[-1]['msgid'], + ) + m.save() + parse_and_add_attachments(r, m) + PatchHistory(patch=patch, by=request.user, what='Attached mail thread %s' % r[0]['msgid']).save() + patch.set_modified() + patch.save() + + return 'OK' + [email protected]_on_success +def detachThread(request): + cf = get_object_or_404(CommitFest, pk=int(request.POST['cf'])) + patch = get_object_or_404(Patch, pk=int(request.POST['p']), commitfests=cf) + thread = get_object_or_404(MailThread, patch=patch, messageid=request.POST['msg']) + + thread.delete() + PatchHistory(patch=patch, by=request.user, what='Detached mail thread %s' % request.POST['msg']).save() + patch.set_modified() + patch.save() + + return 'OK' + + +_ajax_map={ + 'getThreads': getThreads, + 'attachThread': attachThread, + 'detachThread': detachThread, +} + +# Main entrypoint for /ajax/<command>/ +@csrf_exempt +@login_required +def main(request, command): + if not _ajax_map.has_key(command): + raise Http404 + try: + resp = HttpResponse(content_type='application/json') + simplejson.dump(_ajax_map[command](request), resp) + return resp + except Http503, e: + return HttpResponseServiceUnavailable(e, mimetype='text/plain') + |