jumps.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. from django.core.urlresolvers import reverse
  2. from django.shortcuts import redirect
  3. from django.template import RequestContext
  4. from django.utils import timezone
  5. from django.utils.translation import ugettext as _
  6. from misago.acl.utils import ACLError403, ACLError404
  7. from misago.authn.decorators import block_guest
  8. from misago.csrf.decorators import check_csrf
  9. from misago.forums.models import Forum
  10. from misago.messages import Message
  11. from misago.readstracker.trackers import ThreadsTracker
  12. from misago.threads.models import Thread, Post
  13. from misago.threads.views.base import BaseView
  14. from misago.views import error403, error404
  15. from misago.utils import make_pagination
  16. from misago.watcher.models import ThreadWatch
  17. class JumpView(BaseView):
  18. def fetch_thread(self, thread):
  19. self.thread = Thread.objects.get(pk=thread)
  20. self.forum = self.thread.forum
  21. self.request.acl.forums.allow_forum_view(self.forum)
  22. self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
  23. def fetch_post(self, post):
  24. self.post = self.thread.post_set.get(pk=post)
  25. self.request.acl.threads.allow_post_view(self.request.user, self.thread, self.post)
  26. def redirect(self, post):
  27. pagination = make_pagination(0, self.request.acl.threads.filter_posts(self.request, self.thread, self.thread.post_set.filter(date__lt=post.date)).count() + 1, self.request.settings.posts_per_page)
  28. if pagination['total'] > 1:
  29. return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug, 'page': pagination['total']}) + ('#post-%s' % post.pk))
  30. return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}) + ('#post-%s' % post.pk))
  31. def make_jump(self):
  32. raise NotImplementedError('JumpView cannot be called directly.')
  33. def __call__(self, request, slug=None, thread=None, post=None):
  34. self.request = request
  35. try:
  36. self.fetch_thread(thread)
  37. if post:
  38. self.fetch_post(post)
  39. return self.make_jump()
  40. except (Thread.DoesNotExist, Post.DoesNotExist):
  41. return error404(self.request)
  42. except ACLError403 as e:
  43. return error403(request, e.message)
  44. except ACLError404 as e:
  45. return error404(request, e.message)
  46. class LastReplyView(JumpView):
  47. def make_jump(self):
  48. return self.redirect(self.thread.post_set.order_by('-id')[:1][0])
  49. class FindReplyView(JumpView):
  50. def make_jump(self):
  51. return self.redirect(self.post)
  52. class NewReplyView(JumpView):
  53. def make_jump(self):
  54. if not self.request.user.is_authenticated():
  55. return self.redirect(self.thread.post_set.order_by('-id')[:1][0])
  56. tracker = ThreadsTracker(self.request, self.forum)
  57. read_date = tracker.get_read_date(self.thread)
  58. post = self.thread.post_set.filter(date__gt=read_date).order_by('id')[:1]
  59. if not post:
  60. return self.redirect(self.thread.post_set.order_by('-id')[:1][0])
  61. return self.redirect(post[0])
  62. class FirstModeratedView(JumpView):
  63. def make_jump(self):
  64. if not self.request.acl.threads.can_approve(self.forum):
  65. raise ACLError404()
  66. try:
  67. return self.redirect(
  68. self.thread.post_set.get(moderated=True))
  69. except Post.DoesNotExist:
  70. return error404(self.request)
  71. class FirstReportedView(JumpView):
  72. def make_jump(self):
  73. if not self.request.acl.threads.can_mod_posts(self.forum):
  74. raise ACLError404()
  75. try:
  76. return self.redirect(
  77. self.thread.post_set.get(reported=True))
  78. except Post.DoesNotExist:
  79. return error404(self.request)
  80. class ShowHiddenRepliesView(JumpView):
  81. def make_jump(self):
  82. @block_guest
  83. @check_csrf
  84. def view(request):
  85. ignored_exclusions = request.session.get('unignore_threads', [])
  86. ignored_exclusions.append(self.thread.pk)
  87. request.session['unignore_threads'] = ignored_exclusions
  88. request.messages.set_flash(Message(_('Replies made to this thread by members on your ignore list have been revealed.')), 'success', 'threads')
  89. return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}))
  90. return view(self.request)
  91. class WatchThreadView(JumpView):
  92. def get_retreat(self):
  93. return redirect(self.request.POST.get('retreat', reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug})))
  94. def update_watcher(self, request, watcher):
  95. request.messages.set_flash(Message(_('This thread has been added to your watched threads list.')), 'success', 'threads')
  96. def make_jump(self):
  97. @block_guest
  98. @check_csrf
  99. def view(request):
  100. try:
  101. watcher = ThreadWatch.objects.get(user=request.user, thread=self.thread)
  102. except ThreadWatch.DoesNotExist:
  103. watcher = ThreadWatch()
  104. watcher.user = request.user
  105. watcher.forum = self.forum
  106. watcher.thread = self.thread
  107. watcher.last_read = timezone.now()
  108. self.update_watcher(request, watcher)
  109. if watcher.pk:
  110. watcher.save(force_update=True)
  111. else:
  112. watcher.save(force_insert=True)
  113. return self.get_retreat()
  114. return view(self.request)
  115. class WatchEmailThreadView(WatchThreadView):
  116. def update_watcher(self, request, watcher):
  117. watcher.email = True
  118. if watcher.pk:
  119. request.messages.set_flash(Message(_('You will now receive e-mail with notification when somebody replies to this thread.')), 'success', 'threads')
  120. else:
  121. request.messages.set_flash(Message(_('This thread has been added to your watched threads list. You will also receive e-mail with notification when somebody replies to it.')), 'success', 'threads')
  122. class UnwatchThreadView(WatchThreadView):
  123. def update_watcher(self, request, watcher):
  124. watcher.deleted = True
  125. watcher.delete()
  126. if watcher.email:
  127. request.messages.set_flash(Message(_('This thread has been removed from your watched threads list. You will no longer receive e-mails with notifications when somebody replies to it.')), 'success', 'threads')
  128. else:
  129. request.messages.set_flash(Message(_('This thread has been removed from your watched threads list.')), 'success', 'threads')
  130. class UnwatchEmailThreadView(WatchThreadView):
  131. def update_watcher(self, request, watcher):
  132. watcher.email = False
  133. request.messages.set_flash(Message(_('You will no longer receive e-mails with notifications when somebody replies to this thread.')), 'success', 'threads')