participants.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. from django.contrib.auth import get_user_model
  2. from django.utils.translation import ugettext as _
  3. from misago.core.mail import build_mail, send_messages
  4. from .events import record_event
  5. from .models import ThreadParticipant
  6. UserModel = get_user_model()
  7. def has_participants(thread):
  8. return thread.threadparticipant_set.exists()
  9. def make_participants_aware(user, target):
  10. if hasattr(target, '__iter__'):
  11. make_threads_participants_aware(user, target)
  12. else:
  13. make_thread_participants_aware(user, target)
  14. def make_threads_participants_aware(user, threads):
  15. threads_dict = {}
  16. for thread in threads:
  17. thread.participant = None
  18. threads_dict[thread.pk] = thread
  19. participants_qs = ThreadParticipant.objects.filter(user=user, thread_id__in=threads_dict.keys())
  20. for participant in participants_qs:
  21. participant.user = user
  22. threads_dict[participant.thread_id].participant = participant
  23. def make_thread_participants_aware(user, thread):
  24. thread.participants_list = []
  25. thread.participant = None
  26. participants_qs = ThreadParticipant.objects.filter(thread=thread)
  27. participants_qs = participants_qs.select_related('user')
  28. for participant in participants_qs.order_by('-is_owner', 'user__slug'):
  29. participant.thread = thread
  30. thread.participants_list.append(participant)
  31. if participant.user == user:
  32. thread.participant = participant
  33. return thread.participants_list
  34. def set_users_unread_private_threads_sync(users=None, participants=None, exclude_user=None):
  35. users_ids = []
  36. if users:
  37. users_ids += [u.pk for u in users]
  38. if participants:
  39. users_ids += [p.user_id for p in participants]
  40. if exclude_user:
  41. users_ids = filter(lambda u: u != exclude_user.pk, users_ids)
  42. if not users_ids:
  43. return
  44. UserModel.objects.filter(id__in=set(users_ids)).update(sync_unread_private_threads=True)
  45. def set_owner(thread, user):
  46. """
  47. Set user as thread's owner
  48. """
  49. ThreadParticipant.objects.set_owner(thread, user)
  50. def change_owner(request, thread, user):
  51. """
  52. Replace thread's owner with other
  53. """
  54. ThreadParticipant.objects.set_owner(thread, user)
  55. set_users_unread_private_threads_sync(
  56. participants=thread.participants_list, exclude_user=request.user
  57. )
  58. if thread.participant and thread.participant.is_owner:
  59. record_event(
  60. request, thread, 'changed_owner',
  61. {'user': {
  62. 'username': user.username,
  63. 'url': user.get_absolute_url(),
  64. }}
  65. )
  66. else:
  67. record_event(request, thread, 'tookover')
  68. def add_participant(request, thread, user):
  69. """
  70. Adds single participant to thread, registers this on the event
  71. """
  72. add_participants(request, thread, [user])
  73. if request.user == user:
  74. record_event(request, thread, 'entered_thread')
  75. else:
  76. record_event(
  77. request, thread, 'added_participant',
  78. {'user': {
  79. 'username': user.username,
  80. 'url': user.get_absolute_url(),
  81. }}
  82. )
  83. def add_participants(request, thread, users):
  84. """
  85. Add multiple participants to thread, set "recound private threads" flag on them
  86. notify them about being added to thread
  87. """
  88. ThreadParticipant.objects.add_participants(thread, users)
  89. try:
  90. thread_participants = thread.participants_list
  91. except AttributeError:
  92. thread_participants = []
  93. set_users_unread_private_threads_sync(
  94. users=users, participants=thread_participants, exclude_user=request.user
  95. )
  96. emails = []
  97. for user in users:
  98. if user != request.user:
  99. emails.append(build_noticiation_email(request, thread, user))
  100. if emails:
  101. send_messages(emails)
  102. def build_noticiation_email(request, thread, user):
  103. subject = _('%(user)s has invited you to participate in private thread "%(thread)s"')
  104. subject_formats = {'thread': thread.title, 'user': request.user.username}
  105. return build_mail(
  106. request, user, subject % subject_formats, 'misago/emails/privatethread/added',
  107. {'thread': thread}
  108. )
  109. def remove_participant(request, thread, user):
  110. """
  111. Remove thread participant, set "recound private threads" flag on user
  112. """
  113. removed_owner = False
  114. remaining_participants = []
  115. for participant in thread.participants_list:
  116. if participant.user == user:
  117. removed_owner = participant.is_owner
  118. else:
  119. remaining_participants.append(participant.user)
  120. set_users_unread_private_threads_sync(participants=thread.participants_list)
  121. if not remaining_participants:
  122. thread.delete()
  123. else:
  124. thread.threadparticipant_set.filter(user=user).delete()
  125. thread.subscription_set.filter(user=user).delete()
  126. if removed_owner:
  127. thread.is_closed = True # flag thread to close
  128. if request.user == user:
  129. event_type = 'owner_left'
  130. else:
  131. event_type = 'removed_owner'
  132. else:
  133. if request.user == user:
  134. event_type = 'participant_left'
  135. else:
  136. event_type = 'removed_participant'
  137. record_event(
  138. request, thread, event_type,
  139. {'user': {
  140. 'username': user.username,
  141. 'url': user.get_absolute_url(),
  142. }}
  143. )