bgneal@425
|
1 """
|
bgneal@425
|
2 Views for the messages application.
|
bgneal@425
|
3
|
bgneal@425
|
4 """
|
bgneal@425
|
5 import datetime
|
bgneal@425
|
6
|
bgneal@425
|
7 from django.contrib.auth.decorators import login_required
|
bgneal@806
|
8 from django.views.decorators.http import require_POST
|
bgneal@436
|
9 from django.contrib import messages as django_messages
|
bgneal@801
|
10 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
bgneal@425
|
11 from django.core.urlresolvers import reverse
|
bgneal@425
|
12 from django.shortcuts import get_object_or_404
|
bgneal@805
|
13 from django.shortcuts import render, redirect
|
bgneal@425
|
14
|
bgneal@810
|
15 from messages.models import Flag, Message, Options
|
bgneal@810
|
16 from messages.forms import OptionsForm, ComposeForm, ReportForm
|
bgneal@566
|
17 from messages.utils import reply_subject
|
bgneal@436
|
18 from messages import MSG_BOX_LIMIT
|
bgneal@813
|
19 from core.functions import email_admins, quote_message
|
bgneal@425
|
20
|
bgneal@425
|
21
|
bgneal@436
|
22 MSGS_PER_PAGE = 20 # message pagination value
|
bgneal@425
|
23
|
bgneal@813
|
24 REPORT_SUBJECT = 'A user has flagged a private message'
|
bgneal@813
|
25 REPORT_MSG = """Hello,
|
bgneal@813
|
26
|
bgneal@813
|
27 A user has flagged a private message for review.
|
bgneal@813
|
28 """
|
bgneal@813
|
29
|
bgneal@425
|
30
|
bgneal@436
|
31 def _quota_check(box_name, count, request):
|
bgneal@436
|
32 """
|
bgneal@436
|
33 Checks the message box count against MSG_BOX_LIMIT.
|
bgneal@436
|
34 Emits a message to the user if the quota is exceeded.
|
bgneal@441
|
35
|
bgneal@568
|
36 Returns the percent used as an integer between 0-100.
|
bgneal@568
|
37
|
bgneal@436
|
38 """
|
bgneal@436
|
39 if count >= MSG_BOX_LIMIT:
|
bgneal@436
|
40 django_messages.warning(request,
|
bgneal@436
|
41 "Your %s is full. Please delete some messages." % box_name)
|
bgneal@436
|
42
|
bgneal@568
|
43 return 100 * count / MSG_BOX_LIMIT
|
bgneal@568
|
44
|
bgneal@436
|
45
|
bgneal@801
|
46 def _get_page(request, qs):
|
bgneal@801
|
47 """Paginates the given queryset and returns a page object"""
|
bgneal@801
|
48 paginator = Paginator(qs, MSGS_PER_PAGE)
|
bgneal@801
|
49 try:
|
bgneal@801
|
50 page = paginator.page(request.GET.get('page', '1'))
|
bgneal@801
|
51 except PageNotAnInteger:
|
bgneal@801
|
52 page = paginator.page(1)
|
bgneal@801
|
53 except EmptyPage:
|
bgneal@801
|
54 page = paginator.page(paginator.num_pages)
|
bgneal@801
|
55 return page
|
bgneal@801
|
56
|
bgneal@801
|
57
|
bgneal@425
|
58 @login_required
|
bgneal@801
|
59 def inbox(request):
|
bgneal@425
|
60
|
bgneal@801
|
61 msg_list = Message.objects.inbox(request.user)
|
bgneal@801
|
62 msg_count = msg_list.count()
|
bgneal@801
|
63 pct_used = _quota_check('inbox', msg_count, request)
|
bgneal@801
|
64
|
bgneal@801
|
65 page = _get_page(request, msg_list)
|
bgneal@801
|
66
|
bgneal@801
|
67 return render(request, 'messages/inbox.html', {
|
bgneal@801
|
68 'tab': 'inbox',
|
bgneal@801
|
69 'page': page,
|
bgneal@801
|
70 'inbox_pct': pct_used,
|
bgneal@801
|
71 'outbox_pct': None,
|
bgneal@801
|
72 })
|
bgneal@801
|
73
|
bgneal@801
|
74
|
bgneal@801
|
75 @login_required
|
bgneal@801
|
76 def outbox(request):
|
bgneal@801
|
77
|
bgneal@801
|
78 msg_list = Message.objects.outbox(request.user)
|
bgneal@801
|
79 msg_count = msg_list.count()
|
bgneal@801
|
80 pct_used = _quota_check('outbox', msg_count, request)
|
bgneal@801
|
81
|
bgneal@801
|
82 page = _get_page(request, msg_list)
|
bgneal@801
|
83
|
bgneal@801
|
84 return render(request, 'messages/outbox.html', {
|
bgneal@801
|
85 'tab': 'outbox',
|
bgneal@801
|
86 'page': page,
|
bgneal@801
|
87 'inbox_pct': None,
|
bgneal@801
|
88 'outbox_pct': pct_used,
|
bgneal@425
|
89 })
|
bgneal@425
|
90
|
bgneal@425
|
91
|
bgneal@428
|
92 @login_required
|
bgneal@802
|
93 def trash(request):
|
bgneal@802
|
94
|
bgneal@802
|
95 msg_list = Message.objects.trash(request.user)
|
bgneal@802
|
96
|
bgneal@802
|
97 page = _get_page(request, msg_list)
|
bgneal@802
|
98
|
bgneal@802
|
99 return render(request, 'messages/trash.html', {
|
bgneal@802
|
100 'tab': 'trash',
|
bgneal@802
|
101 'page': page,
|
bgneal@802
|
102 'inbox_pct': None,
|
bgneal@802
|
103 'outbox_pct': None,
|
bgneal@802
|
104 })
|
bgneal@802
|
105
|
bgneal@802
|
106
|
bgneal@802
|
107 @login_required
|
bgneal@803
|
108 def options(request):
|
bgneal@803
|
109 """
|
bgneal@803
|
110 This view handles the displaying and changing of private message options.
|
bgneal@803
|
111
|
bgneal@803
|
112 """
|
bgneal@803
|
113 if request.method == 'POST':
|
bgneal@803
|
114 options = Options.objects.for_user(request.user)
|
bgneal@803
|
115 form = OptionsForm(request.POST, instance=options, prefix='opts')
|
bgneal@803
|
116 if form.is_valid():
|
bgneal@803
|
117 form.save()
|
bgneal@803
|
118 django_messages.success(request, 'Options saved.')
|
bgneal@812
|
119 return redirect('messages-options')
|
bgneal@803
|
120 else:
|
bgneal@803
|
121 options = Options.objects.for_user(request.user)
|
bgneal@803
|
122 form = OptionsForm(instance=options, prefix='opts')
|
bgneal@803
|
123
|
bgneal@803
|
124 return render(request, 'messages/options.html', {
|
bgneal@803
|
125 'tab': 'options',
|
bgneal@803
|
126 'form': form,
|
bgneal@803
|
127 })
|
bgneal@803
|
128
|
bgneal@803
|
129
|
bgneal@803
|
130 @login_required
|
bgneal@804
|
131 def compose(request):
|
bgneal@428
|
132 """
|
bgneal@804
|
133 Process or prepare the compose form to create a new private message.
|
bgneal@428
|
134
|
bgneal@428
|
135 """
|
bgneal@804
|
136 if request.method == 'POST':
|
bgneal@804
|
137 compose_form = ComposeForm(request.user, request.POST)
|
bgneal@804
|
138 if compose_form.is_valid():
|
bgneal@804
|
139 compose_form.save()
|
bgneal@804
|
140 django_messages.success(request, 'Message sent.')
|
bgneal@804
|
141 compose_form = ComposeForm(request.user)
|
bgneal@804
|
142 else:
|
bgneal@804
|
143 receiver = request.GET.get('to')
|
bgneal@804
|
144 if receiver:
|
bgneal@804
|
145 form_data = {'receiver': receiver}
|
bgneal@804
|
146 compose_form = ComposeForm(request.user, initial=form_data)
|
bgneal@804
|
147 else:
|
bgneal@804
|
148 compose_form = ComposeForm(request.user)
|
bgneal@804
|
149
|
bgneal@804
|
150 _quota_check('outbox', Message.objects.outbox(request.user).count(), request)
|
bgneal@804
|
151
|
bgneal@804
|
152 return render(request, 'messages/compose.html', {
|
bgneal@804
|
153 'tab': 'compose',
|
bgneal@804
|
154 'compose_form': compose_form,
|
bgneal@428
|
155 })
|
bgneal@428
|
156
|
bgneal@428
|
157
|
bgneal@804
|
158 @login_required
|
bgneal@804
|
159 def view(request, msg_id):
|
bgneal@425
|
160 """
|
bgneal@805
|
161 This view function displays a private message for reading to the user. If
|
bgneal@805
|
162 the user is a recipient of the message, a reply can be composed and sent.
|
bgneal@425
|
163
|
bgneal@425
|
164 """
|
bgneal@812
|
165 msg = get_object_or_404(Message.objects.select_related(), pk=msg_id)
|
bgneal@812
|
166
|
bgneal@805
|
167 if request.method == 'POST':
|
bgneal@805
|
168 form = ComposeForm(request.user, request.POST)
|
bgneal@805
|
169 if form.is_valid():
|
bgneal@805
|
170 form.save()
|
bgneal@805
|
171 django_messages.success(request, 'Reply sent.')
|
bgneal@805
|
172 return redirect('messages-inbox')
|
bgneal@805
|
173 else:
|
bgneal@805
|
174 if msg.sender != request.user and msg.receiver != request.user:
|
bgneal@805
|
175 django_messages.error(request,
|
bgneal@805
|
176 "You don't have permission to read that message.")
|
bgneal@805
|
177 return redirect('messages-inbox')
|
bgneal@425
|
178
|
bgneal@805
|
179 initial_data = {
|
bgneal@805
|
180 'receiver': msg.sender.username,
|
bgneal@805
|
181 'subject': reply_subject(msg.subject),
|
bgneal@805
|
182 'message': quote_message(msg.sender.username, msg.message),
|
bgneal@805
|
183 'parent_id': msg.pk,
|
bgneal@805
|
184 }
|
bgneal@425
|
185
|
bgneal@805
|
186 if msg.receiver == request.user:
|
bgneal@805
|
187 if msg.read_date is None:
|
bgneal@805
|
188 msg.read_date = datetime.datetime.now()
|
bgneal@805
|
189 msg.save()
|
bgneal@805
|
190 else:
|
bgneal@805
|
191 initial_data['receiver'] = msg.receiver.username
|
bgneal@425
|
192
|
bgneal@805
|
193 form = ComposeForm(request.user, initial=initial_data)
|
bgneal@425
|
194
|
bgneal@810
|
195 try:
|
bgneal@810
|
196 msg_flag = msg.flag
|
bgneal@810
|
197 except Flag.DoesNotExist:
|
bgneal@810
|
198 msg_flag = None
|
bgneal@810
|
199
|
bgneal@805
|
200 return render(request, 'messages/view_message.html', {
|
bgneal@805
|
201 'msg': msg,
|
bgneal@805
|
202 'form': form,
|
bgneal@810
|
203 'msg_flag': msg_flag,
|
bgneal@805
|
204 })
|
bgneal@425
|
205
|
bgneal@425
|
206
|
bgneal@806
|
207 def _delete_pms(user, pm_ids):
|
bgneal@425
|
208 """
|
bgneal@806
|
209 Process the request to delete the list of PM ids by user.
|
bgneal@425
|
210
|
bgneal@807
|
211 Returns the number of PM's deleted.
|
bgneal@807
|
212
|
bgneal@425
|
213 """
|
bgneal@806
|
214 msgs = Message.objects.filter(id__in=pm_ids)
|
bgneal@806
|
215 now = datetime.datetime.now()
|
bgneal@425
|
216
|
bgneal@807
|
217 count = 0
|
bgneal@425
|
218 for msg in msgs:
|
bgneal@425
|
219 if msg.sender == user:
|
bgneal@806
|
220 if msg.receiver_delete_date is not None or msg.read_date is None:
|
bgneal@425
|
221 # Both parties deleted the message or receiver hasn't read it
|
bgneal@425
|
222 # yet, we can delete it now
|
bgneal@425
|
223 msg.delete()
|
bgneal@425
|
224 else:
|
bgneal@806
|
225 # receiver still has PM in their inbox
|
bgneal@806
|
226 msg.sender_delete_date = now
|
bgneal@425
|
227 msg.save()
|
bgneal@807
|
228 count += 1
|
bgneal@425
|
229 elif msg.receiver == user:
|
bgneal@425
|
230 if msg.sender_delete_date is not None:
|
bgneal@425
|
231 # both parties deleted the message, we can delete it now
|
bgneal@425
|
232 msg.delete()
|
bgneal@425
|
233 else:
|
bgneal@806
|
234 # sender still has PM in their inbox
|
bgneal@806
|
235 msg.receiver_delete_date = now
|
bgneal@425
|
236 msg.save()
|
bgneal@807
|
237 count += 1
|
bgneal@807
|
238
|
bgneal@807
|
239 return count
|
bgneal@425
|
240
|
bgneal@425
|
241
|
bgneal@806
|
242 @login_required
|
bgneal@806
|
243 @require_POST
|
bgneal@806
|
244 def delete(request):
|
bgneal@806
|
245 """
|
bgneal@806
|
246 Deletes the requested PM's. The user must be either a sender or receiver for
|
bgneal@806
|
247 this to work.
|
bgneal@806
|
248
|
bgneal@806
|
249 """
|
bgneal@806
|
250 pm_ids = request.POST.getlist('pm_ids')
|
bgneal@806
|
251 if pm_ids:
|
bgneal@807
|
252 count = _delete_pms(request.user, pm_ids)
|
bgneal@807
|
253 msg = '{} message{} deleted.'.format(count, '' if count == 1 else 's')
|
bgneal@807
|
254 django_messages.success(request, msg)
|
bgneal@806
|
255
|
bgneal@806
|
256 # Figure out where to redirect to
|
bgneal@806
|
257 src = request.POST.get('src', 'inbox')
|
bgneal@806
|
258 try:
|
bgneal@806
|
259 page = int(request.POST.get('page', '1'))
|
bgneal@806
|
260 except ValueError:
|
bgneal@806
|
261 page = 1
|
bgneal@806
|
262
|
bgneal@807
|
263 view_name = 'messages-inbox' if src == 'inbox' else 'messages-outbox'
|
bgneal@806
|
264 url = reverse(view_name) + '?page={}'.format(page)
|
bgneal@806
|
265 return redirect(url)
|
bgneal@806
|
266
|
bgneal@806
|
267
|
bgneal@807
|
268 def _undelete_pms(user, msg_ids):
|
bgneal@425
|
269 """
|
bgneal@425
|
270 Attempts to "undelete" the messages given by the msg_ids list.
|
bgneal@425
|
271 This will only succeed if the user is either the sender or receiver.
|
bgneal@425
|
272
|
bgneal@807
|
273 Returns the number of PM's undeleted.
|
bgneal@807
|
274
|
bgneal@425
|
275 """
|
bgneal@425
|
276 msgs = Message.objects.filter(id__in=msg_ids)
|
bgneal@807
|
277 count = 0
|
bgneal@425
|
278 for msg in msgs:
|
bgneal@425
|
279 if msg.sender == user:
|
bgneal@425
|
280 msg.sender_delete_date = None
|
bgneal@425
|
281 msg.save()
|
bgneal@807
|
282 count += 1
|
bgneal@425
|
283 elif msg.receiver == user:
|
bgneal@425
|
284 msg.receiver_delete_date = None
|
bgneal@425
|
285 msg.save()
|
bgneal@807
|
286 count += 1
|
bgneal@807
|
287 return count
|
bgneal@425
|
288
|
bgneal@425
|
289
|
bgneal@807
|
290 @login_required
|
bgneal@807
|
291 @require_POST
|
bgneal@807
|
292 def undelete(request):
|
bgneal@425
|
293 """
|
bgneal@807
|
294 Undeletes the requested PM's. The user must be either a sender or receiver for
|
bgneal@807
|
295 this to work.
|
bgneal@425
|
296
|
bgneal@425
|
297 """
|
bgneal@807
|
298 pm_ids = request.POST.getlist('pm_ids')
|
bgneal@807
|
299 if pm_ids:
|
bgneal@807
|
300 count = _undelete_pms(request.user, pm_ids)
|
bgneal@807
|
301 msg = '{} message{} undeleted.'.format(count, '' if count == 1 else 's')
|
bgneal@807
|
302 django_messages.success(request, msg)
|
bgneal@425
|
303
|
bgneal@807
|
304 # Figure out where to redirect to
|
bgneal@807
|
305 try:
|
bgneal@807
|
306 page = int(request.POST.get('page', '1'))
|
bgneal@807
|
307 except ValueError:
|
bgneal@807
|
308 page = 1
|
bgneal@425
|
309
|
bgneal@807
|
310 url = reverse('messages-trash') + '?page={}'.format(page)
|
bgneal@807
|
311 return redirect(url)
|
bgneal@810
|
312
|
bgneal@810
|
313
|
bgneal@810
|
314 @login_required
|
bgneal@810
|
315 def report(request, msg_id):
|
bgneal@810
|
316 """This view is for reporting a PM as spam or abuse.
|
bgneal@810
|
317
|
bgneal@810
|
318 """
|
bgneal@810
|
319 msg = get_object_or_404(Message.objects.select_related(), pk=msg_id)
|
bgneal@810
|
320 if msg.receiver != request.user:
|
bgneal@810
|
321 django_messages.error(request, "You can't report this message.")
|
bgneal@810
|
322 return redirect('messages-inbox')
|
bgneal@810
|
323 try:
|
bgneal@810
|
324 msg.flag
|
bgneal@810
|
325 except Flag.DoesNotExist:
|
bgneal@810
|
326 pass
|
bgneal@810
|
327 else:
|
bgneal@810
|
328 django_messages.error(request, "This message has already been reported.")
|
bgneal@810
|
329 return redirect('messages-inbox')
|
bgneal@810
|
330
|
bgneal@810
|
331 if request.method == 'POST':
|
bgneal@810
|
332 form = ReportForm(request.POST)
|
bgneal@810
|
333 if form.is_valid():
|
bgneal@810
|
334 flag = form.save(commit=False)
|
bgneal@810
|
335 flag.message = msg
|
bgneal@810
|
336 flag.save()
|
bgneal@813
|
337 email_admins(REPORT_SUBJECT, REPORT_MSG)
|
bgneal@810
|
338 django_messages.success(request,
|
bgneal@810
|
339 'Message reported. An admin will be notified. Thank you.')
|
bgneal@810
|
340 return redirect('messages-inbox')
|
bgneal@810
|
341 else:
|
bgneal@810
|
342 form = ReportForm()
|
bgneal@810
|
343
|
bgneal@810
|
344 return render(request, 'messages/report_message.html', {
|
bgneal@810
|
345 'msg': msg,
|
bgneal@810
|
346 'form': form,
|
bgneal@810
|
347 })
|