signals.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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 django.utils.translation import ugettext as _
  6. from misago.categories.models import Category
  7. from misago.categories.signals import delete_category_content, move_category_content
  8. from misago.core.pgutils import chunk_queryset
  9. from misago.users.signals import (
  10. anonymize_user_content, archive_user_data, delete_user_content, username_changed)
  11. from .anonymize import ANONYMIZABLE_EVENTS, anonymize_event, anonymize_post_last_likes
  12. from .models import Attachment, Poll, PollVote, Post, PostEdit, PostLike, Thread
  13. delete_post = Signal()
  14. delete_thread = Signal()
  15. merge_post = Signal(providing_args=["other_post"])
  16. merge_thread = Signal(providing_args=["other_thread"])
  17. move_post = Signal()
  18. move_thread = Signal()
  19. @receiver(merge_thread)
  20. def merge_threads(sender, **kwargs):
  21. other_thread = kwargs['other_thread']
  22. other_thread.post_set.update(
  23. category=sender.category,
  24. thread=sender,
  25. )
  26. other_thread.postedit_set.update(
  27. category=sender.category,
  28. thread=sender,
  29. )
  30. other_thread.postlike_set.update(
  31. category=sender.category,
  32. thread=sender,
  33. )
  34. other_thread.subscription_set.exclude(
  35. user__in=sender.subscription_set.values('user'),
  36. ).update(
  37. category=sender.category,
  38. thread=sender,
  39. )
  40. @receiver(merge_post)
  41. def merge_posts(sender, **kwargs):
  42. other_post = kwargs['other_post']
  43. for user in sender.mentions.iterator():
  44. other_post.mentions.add(user)
  45. @receiver(move_thread)
  46. def move_thread_content(sender, **kwargs):
  47. sender.post_set.update(category=sender.category)
  48. sender.postedit_set.update(category=sender.category)
  49. sender.postlike_set.update(category=sender.category)
  50. sender.pollvote_set.update(category=sender.category)
  51. sender.subscription_set.update(category=sender.category)
  52. Poll.objects.filter(thread=sender).update(category=sender.category)
  53. @receiver(delete_category_content)
  54. def delete_category_threads(sender, **kwargs):
  55. sender.subscription_set.all().delete()
  56. sender.pollvote_set.all().delete()
  57. sender.poll_set.all().delete()
  58. sender.postlike_set.all().delete()
  59. sender.thread_set.all().delete()
  60. sender.postedit_set.all().delete()
  61. sender.post_set.all().delete()
  62. @receiver(move_category_content)
  63. def move_category_threads(sender, **kwargs):
  64. new_category = kwargs['new_category']
  65. sender.thread_set.update(category=new_category)
  66. sender.post_set.filter(category=sender).update(category=new_category)
  67. sender.postedit_set.filter(category=sender).update(category=new_category)
  68. sender.postlike_set.filter(category=sender).update(category=new_category)
  69. sender.poll_set.filter(category=sender).update(category=new_category)
  70. sender.pollvote_set.update(category=new_category)
  71. sender.subscription_set.update(category=new_category)
  72. @receiver(delete_user_content)
  73. def delete_user_threads(sender, **kwargs):
  74. recount_categories = set()
  75. recount_threads = set()
  76. for post in chunk_queryset(sender.liked_post_set):
  77. cleaned_likes = list(filter(lambda i: i['id'] != sender.id, post.last_likes))
  78. if cleaned_likes != post.last_likes:
  79. post.last_likes = cleaned_likes
  80. post.save(update_fields=['last_likes'])
  81. for thread in chunk_queryset(sender.thread_set):
  82. recount_categories.add(thread.category_id)
  83. with transaction.atomic():
  84. thread.delete()
  85. for post in chunk_queryset(sender.post_set):
  86. recount_categories.add(post.category_id)
  87. recount_threads.add(post.thread_id)
  88. with transaction.atomic():
  89. post.delete()
  90. if recount_threads:
  91. changed_threads_qs = Thread.objects.filter(id__in=recount_threads)
  92. for thread in chunk_queryset(changed_threads_qs):
  93. thread.synchronize()
  94. thread.save()
  95. if recount_categories:
  96. for category in Category.objects.filter(id__in=recount_categories):
  97. category.synchronize()
  98. category.save()
  99. @receiver(archive_user_data)
  100. def archive_user_attachments(sender, archive=None, **kwargs):
  101. collection = archive.create_collection('attachment')
  102. queryset = sender.attachment_set.order_by('id')
  103. for attachment in chunk_queryset(queryset):
  104. collection.write_model_file(attachment.image or attachment.file)
  105. @receiver(archive_user_data)
  106. def archive_user_posts(sender, archive=None, **kwargs):
  107. collection = archive.create_collection('post')
  108. queryset = sender.post_set.order_by('id')
  109. for post in chunk_queryset(queryset):
  110. collection.write_data_file(post.posted_on, post.parsed)
  111. @receiver(archive_user_data)
  112. def archive_user_posts_edits(sender, archive=None, **kwargs):
  113. collection = archive.create_collection('post_edit')
  114. queryset = sender.postedit_set.order_by('id')
  115. for post_edit in chunk_queryset(queryset):
  116. collection.write_data_file(post_edit.edited_on, post_edit.edited_from)
  117. @receiver(archive_user_data)
  118. def archive_user_polls(sender, archive=None, **kwargs):
  119. collection = archive.create_collection('poll')
  120. queryset = sender.poll_set.order_by('id')
  121. for poll in chunk_queryset(queryset):
  122. collection.write_data_file(poll.posted_on, {
  123. _("Question"): poll.question,
  124. _("Choices"): [c['label'] for c in poll.choices],
  125. })
  126. @receiver(anonymize_user_content)
  127. def anonymize_user_in_events(sender, **kwargs):
  128. queryset = Post.objects.filter(
  129. is_event=True,
  130. event_type__in=ANONYMIZABLE_EVENTS,
  131. event_context__user__id=sender.id,
  132. )
  133. for event in chunk_queryset(queryset):
  134. anonymize_event(sender, event)
  135. @receiver([anonymize_user_content])
  136. def anonymize_user_in_likes(sender, **kwargs):
  137. for post in chunk_queryset(sender.liked_post_set):
  138. anonymize_post_last_likes(sender, post)
  139. @receiver([anonymize_user_content, username_changed])
  140. def update_usernames(sender, **kwargs):
  141. Thread.objects.filter(starter=sender).update(
  142. starter_name=sender.username,
  143. starter_slug=sender.slug,
  144. )
  145. Thread.objects.filter(last_poster=sender).update(
  146. last_poster_name=sender.username,
  147. last_poster_slug=sender.slug,
  148. )
  149. Thread.objects.filter(best_answer_marked_by=sender).update(
  150. best_answer_marked_by_name=sender.username,
  151. best_answer_marked_by_slug=sender.slug,
  152. )
  153. Post.objects.filter(poster=sender).update(
  154. poster_name=sender.username,
  155. )
  156. Post.objects.filter(last_editor=sender).update(
  157. last_editor_name=sender.username,
  158. last_editor_slug=sender.slug,
  159. )
  160. PostEdit.objects.filter(editor=sender).update(
  161. editor_name=sender.username,
  162. editor_slug=sender.slug,
  163. )
  164. PostLike.objects.filter(liker=sender).update(
  165. liker_name=sender.username,
  166. liker_slug=sender.slug,
  167. )
  168. Attachment.objects.filter(uploader=sender).update(
  169. uploader_name=sender.username,
  170. uploader_slug=sender.slug,
  171. )
  172. Poll.objects.filter(poster=sender).update(
  173. poster_name=sender.username,
  174. poster_slug=sender.slug,
  175. )
  176. PollVote.objects.filter(voter=sender).update(
  177. voter_name=sender.username,
  178. voter_slug=sender.slug,
  179. )
  180. @receiver(pre_delete, sender=get_user_model())
  181. def remove_unparticipated_private_threads(sender, **kwargs):
  182. threads_qs = kwargs['instance'].privatethread_set.all()
  183. for thread in chunk_queryset(threads_qs):
  184. if thread.participants.count() == 1:
  185. with transaction.atomic():
  186. thread.delete()