posting.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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.forms import FormLayout
  8. from misago.forums.models import Forum
  9. from misago.markdown import post_markdown
  10. from misago.messages import Message
  11. from misago.threads.forms import PostForm
  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, slugify
  16. class PostingView(BaseView):
  17. def fetch_target(self, kwargs):
  18. if self.mode == 'new_thread':
  19. self.fetch_forum(kwargs)
  20. if self.mode in ('edit_thread', 'new_post', 'new_post_quick'):
  21. self.fetch_thread(kwargs)
  22. def fetch_forum(self, kwargs):
  23. self.forum = Forum.objects.get(pk=kwargs['forum'], type='forum')
  24. self.request.acl.forums.allow_forum_view(self.forum)
  25. self.request.acl.threads.allow_new_threads(self.forum)
  26. self.parents = Forum.objects.forum_parents(self.forum.pk, True)
  27. def fetch_thread(self, kwargs):
  28. self.thread = Thread.objects.get(pk=kwargs['thread'])
  29. self.forum = self.thread.forum
  30. self.request.acl.forums.allow_forum_view(self.forum)
  31. self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
  32. self.request.acl.threads.allow_reply(self.thread)
  33. self.parents = Forum.objects.forum_parents(self.forum.pk, True)
  34. if kwargs.get('quote'):
  35. self.quote = Post.objects.select_related('user').get(pk=kwargs['quote'], thread=self.thread.pk)
  36. def get_form(self, bound=False):
  37. if bound:
  38. return PostForm(self.request.POST,request=self.request,mode=self.mode)
  39. if self.quote:
  40. quote_post = []
  41. if self.quote.user:
  42. quote_post.append('@%s' % self.quote.user.username)
  43. else:
  44. quote_post.append('@%s' % self.quote.user_name)
  45. for line in self.quote.post.split('\n'):
  46. quote_post.append('> %s' % line)
  47. quote_post.append('\n')
  48. return PostForm(request=self.request,mode=self.mode,initial={'post': '\n'.join(quote_post)})
  49. return PostForm(request=self.request,mode=self.mode)
  50. def __call__(self, request, **kwargs):
  51. self.request = request
  52. self.forum = None
  53. self.thread = None
  54. self.quote = None
  55. self.post = None
  56. self.parents = None
  57. self.mode = kwargs.get('mode')
  58. if self.request.POST.get('quick_reply') and self.mode == 'new_post':
  59. self.mode = 'new_post_quick'
  60. try:
  61. self.fetch_target(kwargs)
  62. if not request.user.is_authenticated():
  63. raise ACLError403(_("Guest, you have to sign-in to post."))
  64. except (Forum.DoesNotExist, Thread.DoesNotExist, Post.DoesNotExist):
  65. return error404(self.request)
  66. except ACLError403 as e:
  67. return error403(request, e.message)
  68. except ACLError404 as e:
  69. return error404(request, e.message)
  70. message = request.messages.get_message('threads')
  71. if request.method == 'POST':
  72. form = self.get_form(True)
  73. if form.is_valid():
  74. now = timezone.now()
  75. moderation = False
  76. if not request.acl.threads.acl[self.forum.pk]['can_approve']:
  77. if self.mode == 'new_thread' and request.acl.threads.acl[self.forum.pk]['can_start_threads'] == 1:
  78. moderation = True
  79. if self.mode in ['new_post', 'new_post_quick'] and request.acl.threads.acl[self.forum.pk]['can_write_posts'] == 1:
  80. moderation = True
  81. # Get or create new thread
  82. if self.mode in ['new_thread']:
  83. thread = Thread.objects.create(
  84. forum=self.forum,
  85. name=form.cleaned_data['thread_name'],
  86. slug=slugify(form.cleaned_data['thread_name']),
  87. start=now,
  88. last=now,
  89. moderated=moderation,
  90. )
  91. if moderation:
  92. thread.replies_moderated += 1
  93. else:
  94. thread = self.thread
  95. # Create new message
  96. post = Post.objects.create(
  97. forum=self.forum,
  98. thread=thread,
  99. merge=thread.merges,
  100. user=request.user,
  101. user_name=request.user.username,
  102. ip=request.session.get_ip(request),
  103. agent=request.META.get('HTTP_USER_AGENT'),
  104. post=form.cleaned_data['post'],
  105. post_preparsed=post_markdown(request, form.cleaned_data['post']),
  106. date=now,
  107. moderated=moderation,
  108. )
  109. if self.mode == 'new_thread':
  110. thread.start_post = post
  111. thread.start_poster = request.user
  112. thread.start_poster_name = request.user.username
  113. thread.start_poster_slug = request.user.username_slug
  114. if request.user.rank and request.user.rank.style:
  115. thread.start_poster_style = request.user.rank.style
  116. if not moderation:
  117. thread.last = now
  118. thread.last_post = post
  119. thread.last_poster = request.user
  120. thread.last_poster_name = request.user.username
  121. thread.last_poster_slug = request.user.username_slug
  122. if request.user.rank and request.user.rank.style:
  123. thread.last_poster_style = request.user.rank.style
  124. if self.mode in ['new_post', 'new_post_quick']:
  125. if moderation:
  126. thread.replies_moderated += 1
  127. else:
  128. thread.replies += 1
  129. thread.score += 5
  130. if (self.request.settings.thread_length > 0
  131. and not thread.closed
  132. and thread.replies >= self.request.settings.thread_length):
  133. thread.closed = True
  134. post.set_checkpoint(self.request, 'limit')
  135. thread.save(force_update=True)
  136. # Update forum and monitor
  137. if not moderation:
  138. if self.mode == 'new_thread':
  139. self.request.monitor['threads'] = int(self.request.monitor['threads']) + 1
  140. self.forum.threads += 1
  141. self.forum.threads_delta += 1
  142. if self.mode in ['new_thread', 'new_post', 'new_post_quick']:
  143. self.request.monitor['posts'] = int(self.request.monitor['posts']) + 1
  144. self.forum.posts += 1
  145. self.forum.posts_delta += 1
  146. self.forum.last_thread = thread
  147. self.forum.last_thread_name = thread.name
  148. self.forum.last_thread_slug = thread.slug
  149. self.forum.last_thread_date = thread.last
  150. self.forum.last_poster = thread.last_poster
  151. self.forum.last_poster_name = thread.last_poster_name
  152. self.forum.last_poster_slug = thread.last_poster_slug
  153. self.forum.last_poster_style = thread.last_poster_style
  154. self.forum.save(force_update=True)
  155. # Update user
  156. if not moderation:
  157. if self.mode == 'new_thread':
  158. request.user.threads += 1
  159. request.user.posts += 1
  160. request.user.last_post = thread.last
  161. request.user.save(force_update=True)
  162. if self.mode == 'new_thread':
  163. if moderation:
  164. request.messages.set_flash(Message(_("New thread has been posted. It will be hidden from other members until moderator reviews it.")), 'success', 'threads')
  165. else:
  166. request.messages.set_flash(Message(_("New thread has been posted.")), 'success', 'threads')
  167. return redirect(reverse('thread', kwargs={'thread': thread.pk, 'slug': thread.slug}) + ('#post-%s' % post.pk))
  168. if self.mode in ['new_post', 'new_post_quick']:
  169. if moderation:
  170. request.messages.set_flash(Message(_("Your reply has been posted. It will be hidden from other members until moderator reviews it.")), 'success', 'threads_%s' % post.pk)
  171. else:
  172. request.messages.set_flash(Message(_("Your reply has been posted.")), 'success', 'threads_%s' % post.pk)
  173. pagination = make_pagination(0, self.request.acl.threads.filter_posts(self.request, self.thread, self.thread.post_set).count(), self.request.settings.posts_per_page)
  174. if pagination['total'] > 1:
  175. return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug, 'page': pagination['total']}) + ('#post-%s' % post.pk))
  176. return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}) + ('#post-%s' % post.pk))
  177. message = Message(form.non_field_errors()[0], 'error')
  178. else:
  179. form = self.get_form()
  180. return request.theme.render_to_response('threads/posting.html',
  181. {
  182. 'mode': self.mode,
  183. 'forum': self.forum,
  184. 'thread': self.thread,
  185. 'post': self.post,
  186. 'parents': self.parents,
  187. 'message': message,
  188. 'form': FormLayout(form),
  189. },
  190. context_instance=RequestContext(request));