signals.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. from django.contrib.auth import get_user_model
  2. from django.db import transaction
  3. from django.db.models.signals import pre_delete
  4. from django.dispatch import Signal, receiver
  5. from misago.categories.models import Category
  6. from misago.categories.signals import delete_category_content, move_category_content
  7. from misago.core.pgutils import chunk_queryset
  8. from misago.users.signals import anonymize_user_content, delete_user_content, username_changed
  9. from .anonymize import ANONYMIZABLE_EVENTS, anonymize_event, anonymize_post_last_likes
  10. from .models import Attachment, Poll, PollVote, Post, PostEdit, PostLike, Thread
  11. delete_post = Signal()
  12. delete_thread = Signal()
  13. merge_post = Signal(providing_args=["other_post"])
  14. merge_thread = Signal(providing_args=["other_thread"])
  15. move_post = Signal()
  16. move_thread = Signal()
  17. @receiver(merge_thread)
  18. def merge_threads(sender, **kwargs):
  19. other_thread = kwargs['other_thread']
  20. other_thread.post_set.update(
  21. category=sender.category,
  22. thread=sender,
  23. )
  24. other_thread.postedit_set.update(
  25. category=sender.category,
  26. thread=sender,
  27. )
  28. other_thread.postlike_set.update(
  29. category=sender.category,
  30. thread=sender,
  31. )
  32. other_thread.subscription_set.exclude(
  33. user__in=sender.subscription_set.values('user'),
  34. ).update(
  35. category=sender.category,
  36. thread=sender,
  37. )
  38. @receiver(merge_post)
  39. def merge_posts(sender, **kwargs):
  40. other_post = kwargs['other_post']
  41. for user in sender.mentions.iterator():
  42. other_post.mentions.add(user)
  43. @receiver(move_thread)
  44. def move_thread_content(sender, **kwargs):
  45. sender.post_set.update(category=sender.category)
  46. sender.postedit_set.update(category=sender.category)
  47. sender.postlike_set.update(category=sender.category)
  48. sender.pollvote_set.update(category=sender.category)
  49. sender.subscription_set.update(category=sender.category)
  50. Poll.objects.filter(thread=sender).update(category=sender.category)
  51. @receiver(delete_category_content)
  52. def delete_category_threads(sender, **kwargs):
  53. sender.subscription_set.all().delete()
  54. sender.pollvote_set.all().delete()
  55. sender.poll_set.all().delete()
  56. sender.postlike_set.all().delete()
  57. sender.thread_set.all().delete()
  58. sender.postedit_set.all().delete()
  59. sender.post_set.all().delete()
  60. @receiver(move_category_content)
  61. def move_category_threads(sender, **kwargs):
  62. new_category = kwargs['new_category']
  63. sender.thread_set.update(category=new_category)
  64. sender.post_set.filter(category=sender).update(category=new_category)
  65. sender.postedit_set.filter(category=sender).update(category=new_category)
  66. sender.postlike_set.filter(category=sender).update(category=new_category)
  67. sender.poll_set.filter(category=sender).update(category=new_category)
  68. sender.pollvote_set.update(category=new_category)
  69. sender.subscription_set.update(category=new_category)
  70. @receiver(delete_user_content)
  71. def delete_user_threads(sender, **kwargs):
  72. recount_categories = set()
  73. recount_threads = set()
  74. for post in chunk_queryset(sender.liked_post_set):
  75. cleaned_likes = list(filter(lambda i: i['id'] != sender.id, post.last_likes))
  76. if cleaned_likes != post.last_likes:
  77. post.last_likes = cleaned_likes
  78. post.save(update_fields=['last_likes'])
  79. for thread in chunk_queryset(sender.thread_set):
  80. recount_categories.add(thread.category_id)
  81. with transaction.atomic():
  82. thread.delete()
  83. for post in chunk_queryset(sender.post_set):
  84. recount_categories.add(post.category_id)
  85. recount_threads.add(post.thread_id)
  86. with transaction.atomic():
  87. post.delete()
  88. if recount_threads:
  89. changed_threads_qs = Thread.objects.filter(id__in=recount_threads)
  90. for thread in chunk_queryset(changed_threads_qs):
  91. thread.synchronize()
  92. thread.save()
  93. if recount_categories:
  94. for category in Category.objects.filter(id__in=recount_categories):
  95. category.synchronize()
  96. category.save()
  97. @receiver(anonymize_user_content)
  98. def anonymize_user_in_events(sender, **kwargs):
  99. queryset = Post.objects.filter(
  100. is_event=True,
  101. event_type__in=ANONYMIZABLE_EVENTS,
  102. event_context__user__id=sender.id,
  103. )
  104. for event in chunk_queryset(queryset):
  105. anonymize_event(sender, event)
  106. @receiver([anonymize_user_content])
  107. def anonymize_user_in_likes(sender, **kwargs):
  108. for post in chunk_queryset(sender.liked_post_set):
  109. anonymize_post_last_likes(sender, post)
  110. @receiver([anonymize_user_content, username_changed])
  111. def update_usernames(sender, **kwargs):
  112. Thread.objects.filter(starter=sender).update(
  113. starter_name=sender.username,
  114. starter_slug=sender.slug,
  115. )
  116. Thread.objects.filter(last_poster=sender).update(
  117. last_poster_name=sender.username,
  118. last_poster_slug=sender.slug,
  119. )
  120. Thread.objects.filter(best_answer_marked_by=sender).update(
  121. best_answer_marked_by_name=sender.username,
  122. best_answer_marked_by_slug=sender.slug,
  123. )
  124. Post.objects.filter(poster=sender).update(
  125. poster_name=sender.username,
  126. )
  127. Post.objects.filter(last_editor=sender).update(
  128. last_editor_name=sender.username,
  129. last_editor_slug=sender.slug,
  130. )
  131. PostEdit.objects.filter(editor=sender).update(
  132. editor_name=sender.username,
  133. editor_slug=sender.slug,
  134. )
  135. PostLike.objects.filter(liker=sender).update(
  136. liker_name=sender.username,
  137. liker_slug=sender.slug,
  138. )
  139. Attachment.objects.filter(uploader=sender).update(
  140. uploader_name=sender.username,
  141. uploader_slug=sender.slug,
  142. )
  143. Poll.objects.filter(poster=sender).update(
  144. poster_name=sender.username,
  145. poster_slug=sender.slug,
  146. )
  147. PollVote.objects.filter(voter=sender).update(
  148. voter_name=sender.username,
  149. voter_slug=sender.slug,
  150. )
  151. @receiver(pre_delete, sender=get_user_model())
  152. def remove_unparticipated_private_threads(sender, **kwargs):
  153. threads_qs = kwargs['instance'].privatethread_set.all()
  154. for thread in chunk_queryset(threads_qs):
  155. if thread.participants.count() == 1:
  156. with transaction.atomic():
  157. thread.delete()