def publish_message_to_centrifugo(sender, instance, created, **kwargs):
    """ Publishes each saved message to Centrifugo. """
    if created is True:
        client = Client(
            "{0}api/".format(getattr(settings, "CENTRIFUGE_ADDRESS")),
            getattr(settings, "CENTRIFUGE_SECRET"))
        # we ensure the client is still in the thread (he may have left or have been removed)
        active_participants = [
            participation.participant.id
            for participation in Participation.objects.filter(
                thread=instance.thread, date_left__isnull=True).select_related(
                    'participant')
        ]
        client.publish(
            build_channel(settings.CENTRIFUGO_MESSAGE_NAMESPACE,
                          instance.thread.id, active_participants),
            {
                "id": instance.id,
                "body": instance.body,
                "sender": instance.sender.id,
                "thread": instance.thread.id,
                "sent_at": str(instance.sent_at),
                "is_notification":
                True,  # ATTENTION: check against sender too to be sure to not notify him his message
            })
def publish_participation_to_thread(sender, instance, created, **kwargs):
    """ Warns users everytime a thread including them is published. This is done via channel subscription.  """
    if kwargs.get("created_and_add_participants") is True:
        request_participant_id = kwargs.get("request_participant_id")
        if request_participant_id is not None:
            client = Client(
                "{0}api/".format(getattr(settings, "CENTRIFUGE_ADDRESS")), getattr(settings, "CENTRIFUGE_SECRET")
            )
            active_participants = [
                participation.participant
                for participation in Participation.objects.filter(
                    thread=instance, date_left__isnull=True
                ).select_related("participant")
            ]
            for participant in active_participants:
                client.publish(
                    build_channel(settings.CENTRIFUGO_THREAD_NAMESPACE, participant.id, [participant.id]),
                    {
                        "message_channel_to_connect_to": build_channel(
                            settings.CENTRIFUGO_MESSAGE_NAMESPACE, instance.id, [p.id for p in active_participants]
                        )
                    },
                )
def publish_message_to_centrifugo(sender, instance, created, **kwargs):
    """ Publishes each saved message to Centrifugo. """
    if created is True:
        client = Client(
            "{0}api/".format(getattr(settings, "CENTRIFUGE_ADDRESS")), getattr(settings, "CENTRIFUGE_SECRET")
        )
        # we ensure the client is still in the thread (he may have left or have been removed)
        active_participants = [
            participation.participant.id
            for participation in Participation.objects.filter(
                thread=instance.thread, date_left__isnull=True
            ).select_related("participant")
        ]
        client.publish(
            build_channel(settings.CENTRIFUGO_MESSAGE_NAMESPACE, instance.thread.id, active_participants),
            {
                "id": instance.id,
                "body": instance.body,
                "sender": instance.sender.id,
                "thread": instance.thread.id,
                "sent_at": str(instance.sent_at),
                "is_notification": True,  # ATTENTION: check against sender too to be sure to not notify him his message
            },
        )
def publish_participation_to_thread(sender, instance, created, **kwargs):
    """ Warns users everytime a thread including them is published. This is done via channel subscription.  """
    if kwargs.get('created_and_add_participants') is True:
        request_participant_id = kwargs.get('request_participant_id')
        if request_participant_id is not None:
            client = Client(
                "{0}api/".format(getattr(settings, "CENTRIFUGE_ADDRESS")),
                getattr(settings, "CENTRIFUGE_SECRET"))
            active_participants = [
                participation.participant
                for participation in Participation.objects.filter(
                    thread=instance, date_left__isnull=True).select_related(
                        'participant')
            ]
            for participant in active_participants:
                client.publish(
                    build_channel(settings.CENTRIFUGO_THREAD_NAMESPACE,
                                  participant.id, [participant.id]),
                    {
                        "message_channel_to_connect_to":
                        build_channel(settings.CENTRIFUGO_MESSAGE_NAMESPACE,
                                      instance.id,
                                      [p.id for p in active_participants])
                    })
 def test_integration(self):
     # we hit whatever view just to set the cookie
     self.selenium.get(self.live_server_url + reverse('dummy'))
     self.selenium.add_cookie(self.cookie)
     self.selenium.refresh()
     # we create threads which call signals telling centrifugo to connect
     self.thread1 = Thread.managers.get_or_create_thread(self.request, "The #1 Thread", self.participant1.id, self.participant2.id)
     self.thread2 = Thread.managers.get_or_create_thread(self.request, "The #2 Thread", self.participant1.id, self.participant3.id)
     # the following conversation does not include the current user, we do not want it on the screen!
     self.thread_unrelated = Thread.objects.create(name="The unrelated Thread")  # the conversation does not involve the current user, we do not want it on the screen!
     self.participationU1 = Participation.objects.create(participant=self.participant2, thread=self.thread_unrelated)
     self.participationU2 = Participation.objects.create(participant=self.participant3, thread=self.thread_unrelated)
     # we load the index page which contains the logic (in javascript)
     self.selenium.get(self.live_server_url + reverse('index'))
     # we wait a little bit
     time.sleep(4)
     # we create a message
     # this will trigger a publishing signal in django-rest-messaging-centrifugo
     body11 = "hi #11"
     body12 = "hi #12"
     body21 = "hi #21"
     body22 = "hi #22"
     bodyU1 = "We do not want to see this! #1"
     bodyU2 = "We do not want to see this! #2"
     m11 = Message.objects.create(sender=self.participant1, thread=self.thread1, body=body11)
     m12 = Message.objects.create(sender=self.participant2, thread=self.thread1, body=body12)
     m21 = Message.objects.create(sender=self.participant3, thread=self.thread2, body=body21)
     m22 = Message.objects.create(sender=self.participant1, thread=self.thread2, body=body22)
     mU1 = Message.objects.create(sender=self.participant2, thread=self.thread_unrelated, body=bodyU1)
     mU2 = Message.objects.create(sender=self.participant3, thread=self.thread_unrelated, body=bodyU2)
     # the channels are private
     # this means that Centrifugo will check the users ids to know if the user may connect
     # if we query a private channel the user does not belong to, we never see the message
     client = Client("{0}api/".format(getattr(settings, "CENTRIFUGE_ADDRESS")), getattr(settings, "CENTRIFUGE_SECRET"))
     forbidden_message = "Message forbidden"
     client.publish(
         build_channel(namespace=settings.CENTRIFUGO_MESSAGE_NAMESPACE, name=self.thread_unrelated.id, user_ids=[p.id for p in self.thread_unrelated.participants.all()]),
         forbidden_message
     )
     # we wait a little bit
     time.sleep(4)
     # now the messages should be displayed
     m11 = self.selenium.find_element_by_id('message__{0}'.format(m11.id))
     m12 = self.selenium.find_element_by_id('message__{0}'.format(m12.id))
     m21 = self.selenium.find_element_by_id('message__{0}'.format(m21.id))
     m22 = self.selenium.find_element_by_id('message__{0}'.format(m22.id))
     self.assertTrue(body11 in m11.text)
     self.assertTrue(body12 in m12.text)
     self.assertTrue(body21 in m21.text)
     self.assertTrue(body22 in m22.text)
     # the following ensures we get the new threads created during the connection
     self.thread4 = Thread.managers.get_or_create_thread(self.request, "The #4 Thread", self.participant4.id, self.participant1.id)
     time.sleep(4)
     message_channel_to_connect_to = 'messages:4#4,1'.format(self.thread4.id, self.thread4.participants.all()[0].id, self.thread4.participants.all()[1].id)
     thread_messages = self.selenium.find_element_by_id('thread__{0}'.format(message_channel_to_connect_to))
     self.assertTrue(message_channel_to_connect_to in thread_messages.text)
     # we should not find the unrelated messages
     self.assertRaises(Exception, self.selenium.find_element_by_id, 'message__{0}'.format(mU1.id))
     self.assertRaises(Exception, self.selenium.find_element_by_id, 'message__{0}'.format(mU2.id))
     self.assertRaises(Exception, self.selenium.find_element_by_id, 'message__{0}'.format(mU2.id))
     self.assertEqual([], self.selenium.find_elements_by_xpath("//*[contains(text(), '{0}')]".format(forbidden_message)))