gremmie@1: """Views for the messages application""" gremmie@1: bgneal@371: import collections gremmie@1: import datetime bgneal@371: gremmie@1: from django.shortcuts import render_to_response gremmie@1: from django.template import RequestContext gremmie@1: from django.http import HttpResponseRedirect gremmie@1: from django.contrib.auth.decorators import login_required bgneal@178: from django.contrib import messages gremmie@1: from django.shortcuts import get_object_or_404 gremmie@1: from django.core.urlresolvers import reverse gremmie@1: from django.http import Http404 bgneal@156: from django.views.decorators.http import require_POST gremmie@1: gremmie@1: from messages.models import Message gremmie@1: from messages.models import Options gremmie@1: from messages.forms import ComposeForm gremmie@1: from messages.forms import OptionsForm gremmie@1: from messages.utils import reply_subject gremmie@1: from messages.utils import quote_message gremmie@1: gremmie@1: gremmie@1: BOX_MAP = { gremmie@1: 'inbox': 'messages-inbox', gremmie@1: 'outbox': 'messages-outbox', gremmie@1: 'trash': 'messages-trash', gremmie@1: } gremmie@1: bgneal@371: MSG_DELETED, MSG_TRASHED, MSG_ERROR = range(3) bgneal@371: gremmie@1: gremmie@1: def box_redirect(request): gremmie@1: """ gremmie@1: Determines which box to redirect to by looking for a GET or gremmie@1: POST parameter. gremmie@1: """ gremmie@1: if request.method == 'GET': gremmie@1: box = request.GET.get('box', 'inbox') gremmie@1: else: gremmie@1: box = request.POST.get('box', 'inbox') gremmie@1: if BOX_MAP.has_key(box): gremmie@1: url = reverse(BOX_MAP[box]) gremmie@1: else: gremmie@1: url = reverse(BOX_MAP['inbox']) gremmie@1: return HttpResponseRedirect(url) gremmie@1: gremmie@1: gremmie@1: @login_required gremmie@1: def inbox(request): gremmie@1: """Displays the inbox for the user making the request.""" gremmie@1: msgs = Message.objects.inbox(request.user) gremmie@1: return render_to_response('messages/inbox.html', { gremmie@1: 'msgs': msgs, bgneal@371: }, gremmie@1: context_instance = RequestContext(request)) gremmie@1: gremmie@1: gremmie@1: @login_required gremmie@1: def outbox(request): gremmie@1: """Displays the outbox for the user making the request.""" gremmie@1: msgs = Message.objects.outbox(request.user) gremmie@1: return render_to_response('messages/outbox.html', { gremmie@1: 'msgs': msgs, bgneal@371: }, gremmie@1: context_instance = RequestContext(request)) gremmie@1: gremmie@1: gremmie@1: @login_required gremmie@1: def trash(request): gremmie@1: """Displays the trash for the user making the request.""" gremmie@1: msgs = Message.objects.trash(request.user) gremmie@1: return render_to_response('messages/trash.html', { gremmie@1: 'msgs': msgs, bgneal@371: }, gremmie@1: context_instance = RequestContext(request)) gremmie@1: gremmie@1: gremmie@1: @login_required gremmie@1: def view(request, msg_id): gremmie@1: """ gremmie@1: View a given message. Only the sender or receiver can see gremmie@1: the message. gremmie@1: """ gremmie@1: msg = get_object_or_404(Message, pk=msg_id) gremmie@1: if msg.sender != request.user and msg.receiver != request.user: gremmie@1: raise Http404 gremmie@1: gremmie@1: if msg.receiver == request.user and msg.read_date is None: gremmie@1: msg.read_date = datetime.datetime.now() gremmie@1: msg.save() gremmie@1: gremmie@1: box = request.GET.get('box', None) gremmie@1: gremmie@1: return render_to_response('messages/view.html', { gremmie@1: 'box': box, gremmie@1: 'msg': msg, gremmie@1: 'is_deleted': msg.is_deleted(request.user), bgneal@371: }, gremmie@1: context_instance = RequestContext(request)) gremmie@1: gremmie@1: gremmie@1: @login_required gremmie@1: def reply(request, msg_id): gremmie@1: """ gremmie@1: Process or prepare the compose form in order to reply gremmie@1: to a given message. gremmie@1: """ gremmie@1: msg = get_object_or_404(Message, pk=msg_id) gremmie@1: gremmie@1: if request.method == "POST": gremmie@1: if request.POST.get('submit_button', 'Cancel') == 'Cancel': gremmie@1: return box_redirect(request) gremmie@1: compose_form = ComposeForm(request.user, request.POST) gremmie@1: if compose_form.is_valid(): gremmie@1: compose_form.save(sender=request.user, parent_msg=msg) bgneal@178: messages.success(request, 'Reply sent.') gremmie@1: return box_redirect(request) gremmie@1: else: gremmie@1: if msg.receiver == request.user: gremmie@1: receiver_name = msg.sender.username gremmie@1: else: gremmie@1: # replying to message in outbox gremmie@1: receiver_name = msg.receiver.username gremmie@1: gremmie@1: form_data = { gremmie@1: 'receiver': receiver_name, gremmie@1: 'subject': reply_subject(msg.subject), gremmie@1: 'message': quote_message(msg.sender, msg.send_date, msg.message), gremmie@1: 'box': request.GET.get('box', 'inbox'), gremmie@1: } gremmie@1: gremmie@1: compose_form = ComposeForm(request.user, initial=form_data) gremmie@1: gremmie@1: return render_to_response('messages/compose.html', { gremmie@1: 'compose_form': compose_form, bgneal@371: }, gremmie@1: context_instance = RequestContext(request)) gremmie@1: gremmie@1: gremmie@1: @login_required gremmie@1: def compose(request, receiver=None): gremmie@1: """ gremmie@1: Process or prepare the compose form in order to create gremmie@1: a new message. gremmie@1: """ gremmie@1: if request.method == "POST": gremmie@1: if request.POST.get('submit_button', 'Cancel') == 'Cancel': gremmie@1: return HttpResponseRedirect(reverse('messages-inbox')) gremmie@1: compose_form = ComposeForm(request.user, request.POST) gremmie@1: if compose_form.is_valid(): gremmie@1: compose_form.save(sender=request.user) bgneal@178: messages.success(request, 'Message sent.') gremmie@1: return HttpResponseRedirect(reverse('messages-inbox')) gremmie@1: else: gremmie@1: if receiver is not None: gremmie@1: form_data = { gremmie@1: 'receiver': receiver, gremmie@1: } gremmie@1: compose_form = ComposeForm(request.user, initial=form_data) gremmie@1: else: gremmie@1: compose_form = ComposeForm(request.user) gremmie@1: gremmie@1: return render_to_response('messages/compose.html', { gremmie@1: 'compose_form': compose_form, bgneal@371: }, gremmie@1: context_instance = RequestContext(request)) gremmie@1: gremmie@1: bgneal@371: def _delete_message(user, msg): bgneal@371: """ bgneal@371: Deletes a given message. The user must be either the sender or bgneal@371: receiver for this to succeed. bgneal@371: If both parties have deleted the message, it is deleted from the bgneal@371: database. If only one party has deleted the message, the message bgneal@371: is just sent to the trash. bgneal@371: bgneal@371: Returns MSG_DELETED, MSG_TRASHED, or MSG_ERROR to indicate what bgneal@371: action was performed. bgneal@371: bgneal@371: """ bgneal@371: if msg.sender == user: bgneal@371: if (msg.receiver_delete_date is not None or bgneal@371: msg.read_date is None): bgneal@371: # Both parties deleted the message or receiver hasn't read it yet, bgneal@371: # we can delete it now bgneal@371: msg.delete() bgneal@371: return MSG_DELETED bgneal@371: else: bgneal@371: # receiver still has it in inbox bgneal@371: msg.sender_delete_date = datetime.datetime.now() bgneal@371: msg.save() bgneal@371: return MSG_TRASHED bgneal@371: bgneal@371: elif msg.receiver == user: bgneal@371: if msg.sender_delete_date is not None: bgneal@371: # both parties deleted the message, we can delete it now bgneal@371: msg.delete() bgneal@371: return MSG_DELETED bgneal@371: else: bgneal@371: # sender still has it in the outbox bgneal@371: msg.receiver_delete_date = datetime.datetime.now() bgneal@371: msg.save() bgneal@371: return MSG_TRASHED bgneal@371: bgneal@371: return MSG_ERROR bgneal@371: bgneal@371: gremmie@1: @login_required bgneal@156: @require_POST gremmie@1: def delete(request, msg_id): gremmie@1: """ gremmie@1: Deletes a given message. The user must be either the sender or gremmie@1: receiver for this to succeed. gremmie@1: """ gremmie@1: msg = get_object_or_404(Message, pk=msg_id) bgneal@371: result = _delete_message(request.user, msg) bgneal@371: if result == MSG_DELETED: bgneal@371: messages.success(request, 'Message deleted.') bgneal@371: elif result == MSG_TRASHED: bgneal@371: messages.success(request, 'Message sent to trash.') gremmie@1: else: bgneal@371: messages.error(request, 'Error deleting message.') gremmie@1: gremmie@1: return box_redirect(request) gremmie@1: gremmie@1: gremmie@1: @login_required gremmie@1: def delete_bulk(request): gremmie@1: """ gremmie@1: Deletes messages in bulk. The message ID's to be deleted are expected gremmie@1: to be in the delete POST array. The user must be either the sender gremmie@1: or receiver for this to succeed. gremmie@1: """ gremmie@1: if request.method == "POST": gremmie@1: delete_ids = request.POST.getlist('delete_ids') gremmie@1: try: gremmie@1: delete_ids = [int(id) for id in delete_ids] gremmie@1: except ValueError: gremmie@1: raise Http404 bgneal@371: bgneal@371: msgs = Message.objects.filter(id__in=delete_ids) bgneal@371: bgneal@371: counts = collections.defaultdict(int) gremmie@1: for msg in msgs: bgneal@371: result = _delete_message(request.user, msg) bgneal@371: counts[result] += 1 bgneal@371: bgneal@371: if counts[MSG_DELETED]: bgneal@371: messages.success(request, 'Messages deleted: %d' % counts[MSG_DELETED]) bgneal@371: if counts[MSG_TRASHED]: bgneal@371: messages.success(request, 'Messages sent to trash: %d' % counts[MSG_TRASHED]) bgneal@371: if counts[MSG_ERROR]: bgneal@371: messages.error(request, 'Message errors: %d' % counts[MSG_ERROR]) gremmie@1: gremmie@1: return box_redirect(request) gremmie@1: gremmie@1: gremmie@1: @login_required bgneal@156: @require_POST gremmie@1: def undelete(request, msg_id): gremmie@1: """ gremmie@1: Undeletes a given message. The user must be either the sender or gremmie@1: receiver for this to succeed. gremmie@1: """ gremmie@1: msg = get_object_or_404(Message, pk=msg_id) gremmie@1: if msg.sender == request.user: gremmie@1: msg.sender_delete_date = None gremmie@1: elif msg.receiver == request.user: gremmie@1: msg.receiver_delete_date = None gremmie@1: else: gremmie@1: raise Http404 gremmie@1: msg.save() bgneal@178: messages.success(request, 'Message retrieved from the trash.') gremmie@1: gremmie@1: return box_redirect(request) gremmie@1: gremmie@1: gremmie@1: @login_required gremmie@1: def undelete_bulk(request): gremmie@1: """ gremmie@1: Undeletes messages in bulk. The message ID's to be deleted are expected gremmie@1: to be in the delete POST array. The user must be either the sender gremmie@1: or receiver for this to succeed. gremmie@1: """ gremmie@1: if request.method == "POST": gremmie@1: undelete_ids = request.POST.getlist('undelete_ids') gremmie@1: try: gremmie@1: undelete_ids = [int(id) for id in undelete_ids] gremmie@1: except ValueError: gremmie@1: raise Http404 gremmie@1: msgs = Message.objects.filter(id__in = undelete_ids) gremmie@1: for msg in msgs: gremmie@1: if msg.sender == request.user: gremmie@1: msg.sender_delete_date = None gremmie@1: msg.save() gremmie@1: elif msg.receiver == request.user: gremmie@1: msg.receiver_delete_date = None gremmie@1: msg.save() bgneal@178: messages.success(request, 'Messages retrieved from the trash.') gremmie@1: gremmie@1: return box_redirect(request) gremmie@1: gremmie@1: gremmie@1: @login_required gremmie@1: def options(request): gremmie@1: """ gremmie@1: View to display/change user options. gremmie@1: """ gremmie@1: if request.method == "POST": gremmie@1: if request.POST.get('submit_button', 'Cancel') == 'Cancel': gremmie@1: return HttpResponseRedirect(reverse('messages-inbox')) gremmie@1: options = Options.objects.for_user(request.user) gremmie@1: form = OptionsForm(request.POST, instance=options) gremmie@1: if form.is_valid(): gremmie@1: form.save() bgneal@178: messages.success(request, 'Options saved.') gremmie@1: return HttpResponseRedirect(reverse('messages-inbox')) gremmie@1: else: gremmie@1: try: gremmie@1: options = Options.objects.for_user(request.user) gremmie@1: except: gremmie@1: options = Options() gremmie@1: options.user = request.user gremmie@1: options.save() gremmie@1: gremmie@1: form = OptionsForm(instance=options) gremmie@1: gremmie@1: return render_to_response('messages/options.html', { gremmie@1: 'form': form, bgneal@371: }, gremmie@1: context_instance = RequestContext(request)) gremmie@1: