participants.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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(
  20. user=user,
  21. thread_id__in=threads_dict.keys(),
  22. )
  23. for participant in participants_qs:
  24. participant.user = user
  25. threads_dict[participant.thread_id].participant = participant
  26. def make_thread_participants_aware(user, thread):
  27. thread.participants_list = []
  28. thread.participant = None
  29. participants_qs = ThreadParticipant.objects.filter(thread=thread)
  30. participants_qs = participants_qs.select_related('user')
  31. for participant in participants_qs.order_by('-is_owner', 'user__slug'):
  32. participant.thread = thread
  33. thread.participants_list.append(participant)
  34. if participant.user == user:
  35. thread.participant = participant
  36. return thread.participants_list
  37. def set_users_unread_private_threads_sync(users=None, participants=None, exclude_user=None):
  38. users_ids = []
  39. if users:
  40. users_ids += [u.pk for u in users]
  41. if participants:
  42. users_ids += [p.user_id for p in participants]
  43. if exclude_user:
  44. users_ids = filter(lambda u: u != exclude_user.pk, users_ids)
  45. if not users_ids:
  46. return
  47. UserModel.objects.filter(id__in=set(users_ids)).update(sync_unread_private_threads=True)
  48. def set_owner(thread, user):
  49. """
  50. Set user as thread's owner
  51. """
  52. ThreadParticipant.objects.set_owner(thread, user)
  53. def change_owner(request, thread, user):
  54. """
  55. Replace thread's owner with other
  56. """
  57. ThreadParticipant.objects.set_owner(thread, user)
  58. set_users_unread_private_threads_sync(
  59. participants=thread.participants_list,
  60. exclude_user=request.user,
  61. )
  62. if thread.participant and thread.participant.is_owner:
  63. record_event(
  64. request,
  65. thread,
  66. 'changed_owner',
  67. {
  68. 'user': {
  69. 'username': user.username,
  70. 'url': user.get_absolute_url(),
  71. },
  72. },
  73. )
  74. else:
  75. record_event(request, thread, 'tookover')
  76. def add_participant(request, thread, user):
  77. """
  78. Adds single participant to thread, registers this on the event
  79. """
  80. add_participants(request, thread, [user])
  81. if request.user == user:
  82. record_event(request, thread, 'entered_thread')
  83. else:
  84. record_event(
  85. request,
  86. thread,
  87. 'added_participant',
  88. {
  89. 'user': {
  90. 'username': user.username,
  91. 'url': user.get_absolute_url(),
  92. },
  93. },
  94. )
  95. def add_participants(request, thread, users):
  96. """
  97. Add multiple participants to thread, set "recound private threads" flag on them
  98. notify them about being added to thread
  99. """
  100. ThreadParticipant.objects.add_participants(thread, users)
  101. try:
  102. thread_participants = thread.participants_list
  103. except AttributeError:
  104. thread_participants = []
  105. set_users_unread_private_threads_sync(
  106. users=users,
  107. participants=thread_participants,
  108. exclude_user=request.user,
  109. )
  110. emails = []
  111. for user in users:
  112. if user != request.user:
  113. emails.append(build_noticiation_email(request, thread, user))
  114. if emails:
  115. send_messages(emails)
  116. def build_noticiation_email(request, thread, user):
  117. subject = _('%(user)s has invited you to participate in private thread "%(thread)s"')
  118. subject_formats = {
  119. 'thread': thread.title,
  120. 'user': request.user.username,
  121. }
  122. return build_mail(
  123. request, user, subject % subject_formats, 'misago/emails/privatethread/added', {
  124. 'thread': thread,
  125. }
  126. )
  127. def remove_participant(request, thread, user):
  128. """
  129. Remove thread participant, set "recound private threads" flag on user
  130. """
  131. removed_owner = False
  132. remaining_participants = []
  133. for participant in thread.participants_list:
  134. if participant.user == user:
  135. removed_owner = participant.is_owner
  136. else:
  137. remaining_participants.append(participant.user)
  138. set_users_unread_private_threads_sync(participants=thread.participants_list)
  139. if not remaining_participants:
  140. thread.delete()
  141. else:
  142. thread.threadparticipant_set.filter(user=user).delete()
  143. thread.subscription_set.filter(user=user).delete()
  144. if removed_owner:
  145. thread.is_closed = True # flag thread to close
  146. if request.user == user:
  147. event_type = 'owner_left'
  148. else:
  149. event_type = 'removed_owner'
  150. else:
  151. if request.user == user:
  152. event_type = 'participant_left'
  153. else:
  154. event_type = 'removed_participant'
  155. record_event(
  156. request,
  157. thread,
  158. event_type,
  159. {
  160. 'user': {
  161. 'username': user.username,
  162. 'url': user.get_absolute_url(),
  163. },
  164. },
  165. )