def retrieve_private_conversation(self, request, *args, **kwargs): user2 = self.get_object() try: conversation = Conversation.objects.get_or_create_for_two_users(request.user, user2) except Exception: return Response(status=status.HTTP_404_NOT_FOUND, data={}) serializer = ConversationSerializer(conversation, data={}, context={'request': request}) serializer.is_valid(raise_exception=True) return Response(serializer.data)
def retrieve_conversation(self, request, *args, **kwargs): target = self.get_object() conversation = Conversation.objects. \ prefetch_related('conversationparticipant_set'). \ select_related('target_type'). \ get_or_create_for_target(target) serializer = ConversationSerializer( conversation, data={}, context=self.get_serializer_context()) serializer.is_valid(raise_exception=True) return Response(serializer.data)
def test_instantiation(self): serializer = ConversationSerializer(self.conversation) self.assertEqual(serializer.data['topic'], self.conversation.topic) self.assertEqual(serializer.data['id'], self.conversation.id) self.assertEqual([_['id'] for _ in serializer.data['participants']], [_.id for _ in self.conversation.participants.all()]) self.assertEqual([_['content'] for _ in serializer.data['messages']], [_.content for _ in self.conversation.messages.all()])
def send_messages(sender, instance, created, **kwargs): """When there is a message in a conversation we need to send it to any subscribed participants.""" message = instance conversation = message.conversation topic = 'conversations:message' push_exclude_users = [] for subscription in ChannelSubscription.objects.recent().filter( user__in=conversation.participants.all()): if not subscription.away_at: push_exclude_users.append(subscription.user) payload = ConversationMessageSerializer( message, context={ 'request': MockRequest(user=subscription.user) }).data send_in_channel(subscription.reply_channel, topic, payload) # Send push notifications when a message is created, but not when it is modified if created: tokens = [ item.token for item in PushSubscription.objects.filter( Q(user__in=conversation.participants.all()) & ~Q(user__in=push_exclude_users) & ~Q(user=message.author)) ] if len(tokens) > 0: message_title = message.author.display_name if isinstance(conversation.target, Group): message_title = '{} / {}'.format(conversation.target.name, message_title) notify_multiple_devices( registration_ids=tokens, message_title=message_title, message_body=message.content, # this causes each notification for a given conversation to replace previous notifications # fancier would be to make the new notifications show a summary not just the latest message tag='conversation:{}'.format(conversation.id)) # Send conversations object to participants after sending a message # (important for unread_message_count) # Exclude the author because their seen_up_to status gets updated, # so they will receive the `send_conversation_update` message topic = 'conversations:conversation' for subscription in ChannelSubscription.objects.recent()\ .filter(user__in=conversation.participants.all())\ .exclude(user=message.author): payload = ConversationSerializer( conversation, context={ 'request': MockRequest(user=subscription.user) }).data send_in_channel(subscription.reply_channel, topic, payload)
def send_messages(sender, instance, created, **kwargs): """When there is a message in a conversation we need to send it to any subscribed participants.""" message = instance conversation = message.conversation topic = 'conversations:message' for subscription in ChannelSubscription.objects.recent().filter( user__in=conversation.participants.all()).distinct(): payload = ConversationMessageSerializer( message, context={ 'request': MockRequest(user=subscription.user) }).data send_in_channel(subscription.reply_channel, topic, payload) if created and message.is_thread_reply( ) and subscription.user != message.author: payload = ConversationMessageSerializer( message.thread, context={ 'request': MockRequest(user=subscription.user) }).data send_in_channel(subscription.reply_channel, topic, payload) # Send push notification and conversation updates when a message is created, but not when it is modified if not created: return tasks.notify_message_push_subscribers(message) # Send conversations object to participants after sending a message # (important for unread_message_count) # Exclude the author because their seen_up_to status gets updated, # so they will receive the `send_conversation_update` message topic = 'conversations:conversation' # Can be skipped for thread replies, as they don't alter the conversations object if message.is_thread_reply(): return for subscription in ChannelSubscription.objects.recent()\ .filter(user__in=conversation.participants.all())\ .exclude(user=message.author).distinct(): payload = ConversationSerializer( conversation, context={ 'request': MockRequest(user=subscription.user) }).data send_in_channel(subscription.reply_channel, topic, payload)
def send_participant_left(sender, instance, **kwargs): """Notify other conversation participants when someone leaves""" conversation = instance.conversation topic = 'conversations:conversation' for subscription in ChannelSubscription.objects.recent() \ .filter(user__in=conversation.participants.all()) \ .exclude(user=instance.user): payload = ConversationSerializer( conversation, context={ 'request': MockRequest(user=subscription.user) }).data send_in_channel(subscription.reply_channel, topic, payload)
def send_conversation_update(sender, instance, **kwargs): # Update conversations object for user after updating their participation # (important for seen_up_to and unread_message_count) conversation = instance.conversation topic = 'conversations:conversation' payload = ConversationSerializer(conversation, context={ 'request': MockRequest(user=instance.user) }).data for subscription in ChannelSubscription.objects.recent().filter( user=instance.user): send_in_channel(subscription.reply_channel, topic, payload)
def send_participant_joined(sender, instance, created, **kwargs): """Notify other participants when someone joins""" if not created: return conversation = instance.conversation topic = 'conversations:conversation' for subscription in ChannelSubscription.objects.recent() \ .filter(user__in=conversation.participants.all()) \ .exclude(user=instance.user).distinct(): payload = ConversationSerializer( conversation, context={ 'request': MockRequest(user=subscription.user) }).data send_in_channel(subscription.reply_channel, topic, payload)
def retrieve_conversation(self, request, *args, **kwargs): target = self.get_object() conversation = Conversation.objects.get_or_create_for_target(target) serializer = ConversationSerializer(conversation, context={'request': request}) return Response(serializer.data)
def send_messages(sender, instance, created, **kwargs): """When there is a message in a conversation we need to send it to any subscribed participants.""" message = instance conversation = message.conversation topic = 'conversations:message' push_exclude_users = [] for subscription in ChannelSubscription.objects.recent().filter( user__in=conversation.participants.all()): if not subscription.away_at: push_exclude_users.append(subscription.user) payload = ConversationMessageSerializer( message, context={ 'request': MockRequest(user=subscription.user) }).data send_in_channel(subscription.reply_channel, topic, payload) if created and message.is_thread_reply( ) and subscription.user != message.author: payload = ConversationMessageSerializer( message.thread, context={ 'request': MockRequest(user=subscription.user) }).data send_in_channel(subscription.reply_channel, topic, payload) # Send push notification and conversation updates when a message is created, but not when it is modified if not created: return subscriptions = PushSubscription.objects.filter( Q(user__in=conversation.participants.all()) & ~Q(user__in=push_exclude_users) & ~Q(user=message.author)) message_title = message.author.display_name if isinstance(conversation.target, Group): message_title = '{} / {}'.format(conversation.target.name, message_title) click_action = None if message.is_thread_reply(): click_action = frontend_urls.thread_url(message.thread) else: click_action = frontend_urls.conversation_url(conversation, message.author) notify_subscribers( subscriptions=subscriptions, fcm_options={ 'message_title': message_title, 'message_body': message.content, 'click_action': click_action, 'message_icon': logo_url(), # this causes each notification for a given conversation to replace previous notifications # fancier would be to make the new notifications show a summary not just the latest message 'tag': 'conversation:{}'.format(conversation.id) }) # Send conversations object to participants after sending a message # (important for unread_message_count) # Exclude the author because their seen_up_to status gets updated, # so they will receive the `send_conversation_update` message topic = 'conversations:conversation' # Can be skipped for thread replies, as they don't alter the conversations object if message.is_thread_reply(): return for subscription in ChannelSubscription.objects.recent()\ .filter(user__in=conversation.participants.all())\ .exclude(user=message.author): payload = ConversationSerializer( conversation, context={ 'request': MockRequest(user=subscription.user) }).data send_in_channel(subscription.reply_channel, topic, payload)