postmodel.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. from django.db import models
  2. from django.db.models import F
  3. from django.db.models.signals import pre_save, pre_delete
  4. from django.utils import timezone
  5. from django.utils.translation import ugettext_lazy as _
  6. from misago.markdown import clear_markdown
  7. from misago.signals import (delete_user_content, merge_post, merge_thread,
  8. move_forum_content, move_post, move_thread,
  9. rename_user, sync_user_profile)
  10. from misago.utils.translation import ugettext_lazy
  11. class PostManager(models.Manager):
  12. def filter_stats(self, start, end):
  13. return self.filter(date__gte=start).filter(date__lte=end)
  14. class Post(models.Model):
  15. forum = models.ForeignKey('Forum')
  16. thread = models.ForeignKey('Thread')
  17. merge = models.PositiveIntegerField(default=0)
  18. user = models.ForeignKey('User', null=True, blank=True, on_delete=models.SET_NULL)
  19. user_name = models.CharField(max_length=255)
  20. ip = models.GenericIPAddressField()
  21. agent = models.CharField(max_length=255)
  22. post = models.TextField()
  23. post_preparsed = models.TextField()
  24. upvotes = models.PositiveIntegerField(default=0)
  25. downvotes = models.PositiveIntegerField(default=0)
  26. mentions = models.ManyToManyField('User', related_name="mention_set")
  27. date = models.DateTimeField()
  28. edits = models.PositiveIntegerField(default=0)
  29. edit_date = models.DateTimeField(null=True, blank=True)
  30. edit_reason = models.CharField(max_length=255, null=True, blank=True)
  31. edit_user = models.ForeignKey('User', related_name='+', null=True, blank=True, on_delete=models.SET_NULL)
  32. edit_user_name = models.CharField(max_length=255, null=True, blank=True)
  33. edit_user_slug = models.SlugField(max_length=255, null=True, blank=True)
  34. reported = models.BooleanField(default=False, db_index=True)
  35. moderated = models.BooleanField(default=False)
  36. deleted = models.BooleanField(default=False)
  37. protected = models.BooleanField(default=False)
  38. objects = PostManager()
  39. statistics_name = _('New Posts')
  40. class Meta:
  41. app_label = 'misago'
  42. def delete(self, *args, **kwargs):
  43. """
  44. FUGLY HAX for weird stuff that happens with
  45. relations on model deletion in MySQL
  46. """
  47. if self.reported:
  48. self.report_set.update(report_for=None)
  49. return super(Post, self).delete(*args, **kwargs)
  50. def get_date(self):
  51. return self.date
  52. def quote(self):
  53. quote = []
  54. quote.append('@%s' % self.user_name)
  55. for line in self.post.splitlines():
  56. quote.append('> %s' % line)
  57. quote.append('\r\n')
  58. return '\r\n'.join(quote)
  59. @property
  60. def post_clean(self):
  61. return clear_markdown(self.post_preparsed)
  62. def move_to(self, thread):
  63. move_post.send(sender=self, move_to=thread)
  64. self.thread = thread
  65. self.forum = thread.forum
  66. def merge_with(self, post):
  67. post.post = '%s\n- - -\n%s' % (post.post, self.post)
  68. merge_post.send(sender=self, new_post=post)
  69. def notify_mentioned(self, request, thread_type, users):
  70. from misago.acl.builder import acl
  71. from misago.acl.exceptions import ACLError403, ACLError404
  72. mentioned = self.mentions.all()
  73. for slug, user in users.items():
  74. if user.pk != request.user.pk and user not in mentioned:
  75. self.mentions.add(user)
  76. try:
  77. acl = acl(request, user)
  78. acl.forums.allow_forum_view(self.forum)
  79. acl.threads.allow_thread_view(user, self.thread)
  80. acl.threads.allow_post_view(user, self.thread, self)
  81. if not user.is_ignoring(request.user):
  82. alert = user.alert(ugettext_lazy("%(username)s has mentioned you in his reply in thread %(thread)s").message)
  83. alert.profile('username', request.user)
  84. alert.post('thread', thread_type, self.thread, self)
  85. alert.save_all()
  86. except (ACLError403, ACLError404):
  87. pass
  88. def is_reported(self):
  89. self.reported = self.report_set.filter(weight=2).count() > 0
  90. def live_report(self):
  91. try:
  92. return self.report_set.filter(weight=2)[0]
  93. except IndexError:
  94. return None
  95. def rename_user_handler(sender, **kwargs):
  96. Post.objects.filter(user=sender).update(
  97. user_name=sender.username,
  98. )
  99. Post.objects.filter(edit_user=sender).update(
  100. edit_user_name=sender.username,
  101. edit_user_slug=sender.username_slug,
  102. )
  103. rename_user.connect(rename_user_handler, dispatch_uid="rename_user_posts")
  104. def delete_user_content_handler(sender, **kwargs):
  105. from misago.models import Thread
  106. threads = []
  107. for post in sender.post_set.distinct().values('thread_id').iterator():
  108. if not post['thread_id'] in threads:
  109. threads.append(post['thread_id'])
  110. sender.post_set.all().delete()
  111. for thread in Thread.objects.filter(id__in=threads):
  112. thread.sync()
  113. thread.save(force_update=True)
  114. delete_user_content.connect(delete_user_content_handler, dispatch_uid="delete_user_posts")
  115. def move_forum_content_handler(sender, **kwargs):
  116. Post.objects.filter(forum=sender).update(forum=kwargs['move_to'])
  117. move_forum_content.connect(move_forum_content_handler, dispatch_uid="move_forum_posts")
  118. def move_thread_handler(sender, **kwargs):
  119. Post.objects.filter(thread=sender).update(forum=kwargs['move_to'])
  120. move_thread.connect(move_thread_handler, dispatch_uid="move_thread_posts")
  121. def merge_thread_handler(sender, **kwargs):
  122. Post.objects.filter(thread=sender).update(thread=kwargs['new_thread'], merge=F('merge') + kwargs['merge'])
  123. merge_thread.connect(merge_thread_handler, dispatch_uid="merge_threads_posts")
  124. def sync_user_handler(sender, **kwargs):
  125. sender.posts = sender.post_set.count()
  126. sync_user_profile.connect(sync_user_handler, dispatch_uid="sync_user_posts")