postmodel.py 6.5 KB

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