Beispiel #1
0
    def test_last_read_post(self):
        # scenario - topic1 :
        # post1 - user1 - unread
        # post2 - user2 - unread
        self.assertEqual(
            self.post1,
            self.topic1.last_read_post(self.profile1.user))

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        mark_read(self.topic1, user=self.profile1.user)
        self.assertEqual(
            self.post2,
            self.topic1.last_read_post(self.profile1.user))

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        # post3 - user2 - unread
        PrivatePostFactory(
            privatetopic=self.topic1,
            author=self.profile2.user,
            position_in_topic=3)
        self.assertEqual(
            self.post2,
            self.topic1.last_read_post(self.profile1.user))
Beispiel #2
0
    def post(self, request, *args, **kwargs):
        validation = get_object_or_404(Validation, pk=kwargs['pk'])
        if validation.validator:
            validation.validator = None
            validation.date_reserve = None
            validation.status = 'PENDING'
            validation.save()
            messages.info(request, _("Ce contenu n'est plus réservé."))
            return redirect(reverse('validation:list'))
        else:
            validation.validator = request.user
            validation.date_reserve = datetime.now()
            validation.status = 'PENDING_V'
            validation.save()

            versioned = validation.content.load_version(sha=validation.version)
            msg = render_to_string(
                'tutorialv2/messages/validation_reserve.md', {
                    'content':
                    versioned,
                    'url':
                    versioned.get_absolute_url() + '?version=' +
                    validation.version,
                })

            authors = list(validation.content.authors.all())
            if validation.validator in authors:
                authors.remove(validation.validator)
            if len(authors) > 0:
                if not validation.content.validation_private_message:
                    validation.content.validation_private_message = send_mp(
                        validation.validator,
                        authors,
                        _('Contenu réservé - {0}').format(
                            validation.content.title),
                        validation.content.title,
                        msg,
                        True,
                        leave=False,
                        direct=False,
                        mark_as_read=True,
                        hat=get_hat_from_settings('validation'),
                    )
                    validation.content.save(force_slug_update=False)
                else:
                    send_message_mp(
                        validation.validator,
                        validation.content.validation_private_message, msg)
                mark_read(validation.content.validation_private_message,
                          validation.validator)

            messages.info(
                request,
                _('Ce contenu a bien été réservé par {0}.').format(
                    request.user.username))

            return redirect(
                reverse('content:view',
                        args=[validation.content.pk, validation.content.slug])
                + '?version=' + validation.version)
Beispiel #3
0
    def test_reuse_old_notification(self):
        """
        When there already is a read notification for a given content, we reuse it.
        """
        topic = send_mp(author=self.user1,
                        users=[self.user2],
                        title="Testing",
                        subtitle="",
                        text="",
                        leave=False)
        send_message_mp(self.user2, topic, "", send_by_mail=True)

        notifications = Notification.objects.get_unread_notifications_of(
            self.user1)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message,
                         notifications.first().content_object)

        mark_read(topic, self.user1)

        send_message_mp(self.user2, topic, "", send_by_mail=True)

        notifications = Notification.objects.filter(
            subscription__user=self.user1)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
Beispiel #4
0
    def test_generate_a_notification_after_new_post(self):
        """
        When a user posts on a private topic, we generate a notification for all participants.
        """
        topic = send_mp(author=self.user1,
                        users=[self.user2, self.user3],
                        title="Testing",
                        subtitle="",
                        text="",
                        leave=False)

        notifications = Notification.objects.get_unread_notifications_of(
            self.user2)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message,
                         notifications.first().content_object)

        mark_read(topic, self.user2)

        notifications = Notification.objects.get_unread_notifications_of(
            self.user2)
        self.assertEqual(0, len(notifications))

        send_message_mp(self.user3, topic, "")

        notifications = Notification.objects.get_unread_notifications_of(
            self.user2)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message,
                         notifications.first().content_object)
Beispiel #5
0
 def test_no_interference(self):
     mark_read(self.topic1, self.author.user)
     topic_read_old = PrivateTopicRead.objects.filter(privatetopic=self.topic1, user=self.author.user)
     self.assertTrue(self.client.login(username=self.participant.user.username, password="******"))
     self.client.get(reverse("private-post-unread") + "?message=" + str(self.post2.pk), follow=True)
     topic_read_new = PrivateTopicRead.objects.filter(privatetopic=self.topic1, user=self.author.user)
     self.assertQuerysetEqual(topic_read_old, [repr(t) for t in topic_read_new])
Beispiel #6
0
    def test_last_read_post(self):
        # scenario - topic1 :
        # post1 - user1 - unread
        # post2 - user2 - unread
        self.assertEqual(
            self.post1,
            self.topic1.last_read_post(self.profile1.user))

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        mark_read(self.topic1, user=self.profile1.user)
        self.assertEqual(
            self.post2,
            self.topic1.last_read_post(self.profile1.user))

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        # post3 - user2 - unread
        PrivatePostFactory(
            privatetopic=self.topic1,
            author=self.profile2.user,
            position_in_topic=3)
        self.assertEqual(
            self.post2,
            self.topic1.last_read_post(self.profile1.user))
    def test_unicode(self):
        """ test the unicode return """

        ref = u'<Sujet « {0} » lu par {1}, #{2}>'.format(
            self.topic1, self.profile2.user, self.post2.pk)
        mark_read(self.topic1, self.profile2.user)
        private_topic = PrivateTopicRead.objects.filter(
            privatetopic=self.topic1, user=self.profile2.user).first()
        self.assertEqual(private_topic.__unicode__(), ref)
Beispiel #8
0
def send_mp(
    author,
    users,
    title,
    subtitle,
    text,
    send_by_mail=True,
    leave=True,
    direct=False,
    mark_as_read=False,
    hat=None,
    automatically_read=None,
):
    """
    Send a private message in a new private topic.

    :param author: sender of the message and author of the private topic
    :param users: list of users receiving the message (participants of the private topic)
    :param title: title of the private topic
    :param subtitle: subtitle of the private topic
    :param text: content of the private message
    :param send_by_mail:
    :param direct: send a mail directly without mp (ex : ban members who wont connect again)
    :param leave: if True, do not add the sender to the topic
    :param mark_as_read:
    :param hat: hat with which to send the private message
    :param automatically_read: a user or a list of users that will automatically be marked as having read of the mp
    :raise UnreachableUserError:
    """

    # Creating the thread
    limit = PrivateTopic._meta.get_field("title").max_length
    n_topic = PrivateTopic()
    n_topic.title = title[:limit]
    n_topic.subtitle = subtitle
    n_topic.pubdate = datetime.now()
    n_topic.author = author
    n_topic.save()

    # Add all participants on the MP.
    for participants in users:
        n_topic.participants.add(participants)

    topic = send_message_mp(author, n_topic, text, send_by_mail, direct, hat)
    if mark_as_read:
        mark_read(topic, author)
    if automatically_read:
        if not isinstance(automatically_read, list):
            automatically_read = [automatically_read]
        for not_notified_user in automatically_read:
            mark_read(n_topic, not_notified_user)
    if leave:
        topic.remove_participant(topic.author)
        topic.save()

    return topic
Beispiel #9
0
    def test_unicode(self):
        """ test the unicode return """

        ref = u'<Sujet "{0}" lu par {1}, #{2}>'.format(self.topic1,
                                                       self.profile2.user,
                                                       self.post2.pk)
        mark_read(self.topic1, self.profile2.user)
        pt = PrivateTopicRead.objects.filter(privatetopic=self.topic1,
                                             user=self.profile2.user)
        self.assertEqual(str(pt[0]), ref)
Beispiel #10
0
    def test_first_unread_post(self):
        # scenario - topic1 :
        # post1 - user1 - unread
        # post2 - user2 - unread
        self.assertEqual(self.post1, self.topic1.first_unread_post(self.user1))

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        # post3 - user2 - unread
        mark_read(self.topic1, self.user1)
        post3 = PrivatePostFactory(privatetopic=self.topic1, author=self.user2, position_in_topic=3)

        self.assertEqual(post3, self.topic1.first_unread_post(self.user1))
Beispiel #11
0
def send_mp(author,
            users,
            title,
            subtitle,
            text,
            send_by_mail=True,
            leave=True,
            direct=False,
            mark_as_read=False,
            hat=None,
            automaticaly_read=None):
    """
    Send MP at members.
    Most of the param are obvious, excepted :

    :param direct: send a mail directly without mp (ex : ban members who wont connect again)
    :param leave: the author leave the conversation (usefull for the bot : it wont read the response a member could
    send)
    :param automaticaly_read: a user or a list of users that will automatically be marked as reader of the mp
    """

    # Creating the thread
    limit = PrivateTopic._meta.get_field('title').max_length
    n_topic = PrivateTopic()
    n_topic.title = title[:limit]
    n_topic.subtitle = subtitle
    n_topic.pubdate = datetime.now()
    n_topic.author = author
    n_topic.save()

    # Add all participants on the MP.
    for participants in users:
        n_topic.participants.add(participants)

    topic = send_message_mp(author, n_topic, text, send_by_mail, direct, hat)
    if mark_as_read:
        mark_read(topic, author)
    if automaticaly_read:
        if not isinstance(automaticaly_read, list):
            automaticaly_read = [automaticaly_read]
        for not_notified_user in automaticaly_read:
            mark_read(n_topic, not_notified_user)
    if leave:
        move = topic.participants.first()
        topic.author = move
        topic.participants.remove(move)
        topic.save()

    return topic
Beispiel #12
0
def send_mp(
    author,
    users,
    title,
    subtitle,
    text,
    send_by_mail=True,
    leave=True,
    direct=False,
    hat=None,
    automatically_read=None,
):
    """
    Send a private message in a new private topic.

    :param author: sender of the message and author of the private topic
    :param users: list of users receiving the message (participants of the private topic)
    :param title: title of the private topic
    :param subtitle: subtitle of the private topic
    :param text: content of the private message
    :param send_by_mail:
    :param direct: send a mail directly without mp (ex : ban members who wont connect again)
    :param leave: if True, do not add the sender to the topic
    :param hat: hat with which to send the private message
    :param automatically_read: a user or a list of users that will automatically be marked as having read of the mp
    :raise UnreachableUserError:
    """

    n_topic = PrivateTopic.create(title=title,
                                  subtitle=subtitle,
                                  author=author,
                                  recipients=users)
    signals.topic_created.send(sender=PrivateTopic,
                               topic=n_topic,
                               by_email=send_by_mail)

    topic = send_message_mp(author, n_topic, text, send_by_mail, direct, hat)

    if automatically_read:
        if not isinstance(automatically_read, list):
            automatically_read = [automatically_read]
        for not_notified_user in automatically_read:
            mark_read(n_topic, not_notified_user)
    if leave:
        topic.remove_participant(topic.author)
        topic.save()

    return topic
Beispiel #13
0
    def test_mark_read(self, topic_read):
        self.assertTrue(self.topic1.is_unread(self.profile1.user))

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        mark_read(self.topic1, self.profile1.user)
        self.assertFalse(self.topic1.is_unread(self.profile1.user))
        self.assertEqual(topic_read.send.call_count, 1)

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        # post3 - user2 - unread
        PrivatePostFactory(privatetopic=self.topic1, author=self.profile2.user, position_in_topic=3)
        self.assertTrue(self.topic1.is_unread(self.profile1.user))
Beispiel #14
0
    def test_mark_read(self):
        self.assertTrue(self.topic1.never_read(self.profile1.user))

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        mark_read(self.topic1, self.profile1.user)
        self.assertFalse(self.topic1.never_read(self.profile1.user))

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        # post3 - user2 - unread
        PrivatePostFactory(privatetopic=self.topic1,
                           author=self.profile2.user,
                           position_in_topic=3)
        self.assertTrue(self.topic1.never_read(self.profile1.user))
Beispiel #15
0
    def test_mark_read_a_notification(self):
        """
        When we mark a private topic as read, we mark its notification as read.
        """
        topic = send_mp(author=self.user1,
                        users=[self.user2, self.user3],
                        title='Testing', subtitle='', text='', leave=False)

        notifications = Notification.objects.get_unread_notifications_of(self.user2)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message, notifications.first().content_object)

        mark_read(topic, self.user2)

        notifications = Notification.objects.get_unread_notifications_of(self.user2)
        self.assertEqual(0, len(notifications))
Beispiel #16
0
    def test_mark_read_a_notification(self):
        """
        When we mark a private topic as read, we mark its notification as read.
        """
        topic = send_mp(author=self.user1,
                        users=[self.user2, self.user3],
                        title='Testing', subtitle='', text='', leave=False)

        notifications = Notification.objects.get_unread_notifications_of(self.user2)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message, notifications.first().content_object)

        mark_read(topic, self.user2)

        notifications = Notification.objects.get_unread_notifications_of(self.user2)
        self.assertEqual(0, len(notifications))
Beispiel #17
0
    def test_mark_read(self):
        self.assertTrue(self.topic1.is_unread(self.profile1.user))

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        mark_read(self.topic1, self.profile1.user)
        self.assertFalse(self.topic1.is_unread(self.profile1.user))

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        # post3 - user2 - unread
        PrivatePostFactory(
            privatetopic=self.topic1,
            author=self.profile2.user,
            position_in_topic=3)
        self.assertTrue(self.topic1.is_unread(self.profile1.user))
Beispiel #18
0
    def test_is_unread(self):
        # scenario - topic1 :
        # post1 - user1 - unread
        # post2 - user2 - unread
        self.assertTrue(self.topic1.is_unread(self.user1))

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        mark_read(self.topic1, self.user1)
        self.assertFalse(self.topic1.is_unread(self.user1))

        # scenario - topic1 :
        # post1 - user1 - read
        # post2 - user2 - read
        # post3 - user2 - unread
        PrivatePostFactory(privatetopic=self.topic1, author=self.user2, position_in_topic=3)

        self.assertTrue(self.topic1.is_unread(self.user1))
Beispiel #19
0
    def test_reuse_old_notification(self):
        """
        When there already is a read notification for a given content, we reuse it.
        """
        topic = send_mp(author=self.user1, users=[self.user2], title='Testing', subtitle='', text='', leave=False)
        send_message_mp(self.user2, topic, '', send_by_mail=True)

        notifications = Notification.objects.get_unread_notifications_of(self.user1)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message, notifications.first().content_object)

        mark_read(topic, self.user1)

        send_message_mp(self.user2, topic, '', send_by_mail=True)

        notifications = Notification.objects.filter(subscription__user=self.user1)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
Beispiel #20
0
def send_mp(
        author,
        users,
        title,
        subtitle,
        text,
        send_by_mail=True,
        leave=True,
        direct=False,
        mark_as_read=False,
        hat=None):
    """
    Send MP at members.
    Most of the param are obvious, excepted :
    * direct : send a mail directly without mp (ex : ban members who wont connect again)
    * leave : the author leave the conversation (usefull for the bot : it wont read the response a member could send)
    """

    # Creating the thread
    limit = PrivateTopic._meta.get_field('title').max_length
    n_topic = PrivateTopic()
    n_topic.title = title[:limit]
    n_topic.subtitle = subtitle
    n_topic.pubdate = datetime.now()
    n_topic.author = author
    n_topic.save()

    # Add all participants on the MP.
    for participants in users:
        n_topic.participants.add(participants)

    topic = send_message_mp(author, n_topic, text, send_by_mail, direct, hat)
    if mark_as_read:
        mark_read(topic, author)

    if leave:
        move = topic.participants.first()
        topic.author = move
        topic.participants.remove(move)
        topic.save()

    return topic
Beispiel #21
0
def send_mp(
        author,
        users,
        title,
        subtitle,
        text,
        send_by_mail=True,
        leave=True,
        direct=False,
        mark_as_read=False):
    """
    Send MP at members.
    Most of the param are obvious, excepted :
    * direct : send a mail directly without mp (ex : ban members who wont connect again)
    * leave : the author leave the conversation (usefull for the bot : it wont read the response a member could send)
    """

    # Creating the thread
    limit = PrivateTopic._meta.get_field('title').max_length
    n_topic = PrivateTopic()
    n_topic.title = title[:limit]
    n_topic.subtitle = subtitle
    n_topic.pubdate = datetime.now()
    n_topic.author = author
    n_topic.save()

    # Add all participants on the MP.
    for part in users:
        n_topic.participants.add(part)

    topic = send_message_mp(author, n_topic, text, send_by_mail, direct)
    if mark_as_read:
        mark_read(topic, author)

    if leave:
        move = topic.participants.first()
        topic.author = move
        topic.participants.remove(move)
        topic.save()

    return topic
Beispiel #22
0
    def get(self, request, *args, **kwargs):
        """
        Lists all private posts of a given private topic for an authenticated member.
        ---

        parameters:
            - name: Authorization
              description: Bearer token to make an authenticated request.
              required: true
              paramType: header
            - name: X-Data-Format
              description: Specify "Html" or "Markdown" for the desired resource. Defaults to "Markdown".
              required: false
              paramType: header
            - name: page
              description: Restricts output to the given page number.
              required: false
              paramType: query
            - name: page_size
              description: Sets the number of private posts per page.
              required: false
              paramType: query
            - name: ordering
              description: Sorts the results. You can order by (-)position_in_topic, (-)pubdate or (-)update.
              paramType: query
            - name: expand
              description: Returns an object instead of an identifier representing the given field.
              required: false
              paramType: query
        responseMessages:
            - code: 401
              message: Not Authenticated
            - code: 404
              message: Not Found
        """
        response = self.list(request, *args, **kwargs)
        topic = get_object_or_404(PrivateTopic,
                                  pk=self.kwargs.get("pk_ptopic"))
        mark_read(topic, self.request.user)
        return response
Beispiel #23
0
    def get(self, request, *args, **kwargs):
        """
        Lists all private posts of a given private topic for an authenticated member.
        ---

        parameters:
            - name: Authorization
              description: Bearer token to make an authenticated request.
              required: true
              paramType: header
            - name: X-Data-Format
              description: Specify "Html" or "Markdown" for the desired resource. Defaults to "Markdown".
              required: false
              paramType: header
            - name: page
              description: Restricts output to the given page number.
              required: false
              paramType: query
            - name: page_size
              description: Sets the number of private posts per page.
              required: false
              paramType: query
            - name: ordering
              description: Sorts the results. You can order by (-)position_in_topic, (-)pubdate or (-)update.
              paramType: query
            - name: expand
              description: Returns an object instead of an identifier representing the given field.
              required: false
              paramType: query
        responseMessages:
            - code: 401
              message: Not Authenticated
            - code: 404
              message: Not Found
        """
        response = self.list(request, *args, **kwargs)
        topic = get_object_or_404(PrivateTopic, pk=self.kwargs.get('pk_ptopic'))
        mark_read(topic, self.request.user)
        return response
Beispiel #24
0
    def test_generate_a_notification_after_new_post(self):
        """
        When a user posts on a private topic, we generate a notification for all participants.
        """
        topic = send_mp(author=self.user1,
                        users=[self.user2, self.user3],
                        title='Testing', subtitle='', text='', leave=False)

        notifications = Notification.objects.get_unread_notifications_of(self.user2)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message, notifications.first().content_object)

        mark_read(topic, self.user2)

        notifications = Notification.objects.get_unread_notifications_of(self.user2)
        self.assertEqual(0, len(notifications))

        send_message_mp(self.user3, topic, '')

        notifications = Notification.objects.get_unread_notifications_of(self.user2)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message, notifications.first().content_object)
Beispiel #25
0
 def perform_list(self, instance, user=None):
     if never_privateread(instance, user):
         mark_read(instance, user)
Beispiel #26
0
 def test_never_privateread(self):
     self.assertTrue(never_privateread(self.topic1, self.profile1.user))
     mark_read(self.topic1, self.profile1.user)
     self.assertFalse(never_privateread(self.topic1, self.profile1.user))
Beispiel #27
0
 def test_never_privateread(self):
     self.assertTrue(is_privatetopic_unread(self.topic1, self.profile1.user))
     mark_read(self.topic1, self.profile1.user)
     self.assertFalse(is_privatetopic_unread(self.topic1, self.profile1.user))
Beispiel #28
0
def send_message_mp(author,
                    n_topic,
                    text,
                    send_by_mail=True,
                    direct=False,
                    hat=None,
                    no_notification_for=None):
    """
    Send a post in an MP.
    Most of the param are obvious, excepted :
    * direct : send a mail directly without mp (ex : ban members who wont connect again)
    * leave : the author leave the conversation (usefull for the bot : it wont read the response a member could send)
    """

    # Getting the position of the post
    if n_topic.last_message is None:
        pos = 1
    else:
        pos = n_topic.last_message.position_in_topic + 1

    # Add the first message
    post = PrivatePost()
    post.privatetopic = n_topic
    post.author = author
    post.text = text
    post.text_html = emarkdown(text)
    post.pubdate = datetime.now()
    post.position_in_topic = pos
    post.hat = hat
    post.save()

    n_topic.last_message = post
    n_topic.save()

    if not direct:
        signals.new_content.send(sender=post.__class__,
                                 instance=post,
                                 by_email=send_by_mail,
                                 no_notification_for=no_notification_for)

    if send_by_mail and direct:
        subject = '{} : {}'.format(settings.ZDS_APP['site']['literal_name'],
                                   n_topic.title)
        from_email = '{} <{}>'.format(
            settings.ZDS_APP['site']['literal_name'],
            settings.ZDS_APP['site']['email_noreply'])
        for recipient in n_topic.participants.values_list('email', flat=True):
            message_html = render_to_string('email/direct.html',
                                            {'msg': emarkdown(text)})
            message_txt = render_to_string('email/direct.txt', {'msg': text})

            msg = EmailMultiAlternatives(subject, message_txt, from_email,
                                         [recipient])
            msg.attach_alternative(message_html, 'text/html')
            try:
                msg.send()
            except Exception as e:
                logger.exception('Message was not sent to %s due to %s',
                                 recipient, e)
    if no_notification_for:
        if not isinstance(no_notification_for, list):
            no_notification_for = [no_notification_for]
        for not_notified_user in no_notification_for:
            mark_read(n_topic, not_notified_user)
    if author.pk not in [p.pk for p in n_topic.participants.all()
                         ] and author.pk != n_topic.author.pk:
        n_topic.participants.add(author)
        n_topic.save()

    return n_topic
Beispiel #29
0
def send_message_mp(author,
                    n_topic,
                    text,
                    send_by_mail=True,
                    direct=False,
                    hat=None,
                    no_notification_for=None):
    """
    Send a post in an MP.

    :param author: sender of the private message
    :param n_topic: topic in which it will be sent
    :param text: content of the message
    :param send_by_mail: if True, also notify by email
    :param direct: send a mail directly without private message (ex : banned members who won't connect again)
    :param hat: hat attached to the message
    :param no_notification_for: list of participants who won't be notified of the message
    """

    # Getting the position of the post
    if n_topic.last_message is None:
        pos = 1
    else:
        pos = n_topic.last_message.position_in_topic + 1

    # Add the first message
    post = PrivatePost()
    post.privatetopic = n_topic
    post.author = author
    post.text = text
    post.text_html = emarkdown(text)
    post.pubdate = datetime.now()
    post.position_in_topic = pos
    post.hat = hat
    post.save()

    n_topic.last_message = post
    n_topic.save()

    if not direct:
        signals.message_added.send(sender=post.__class__,
                                   post=post,
                                   by_email=send_by_mail,
                                   no_notification_for=no_notification_for)

    if send_by_mail and direct:
        subject = "{} : {}".format(settings.ZDS_APP["site"]["literal_name"],
                                   n_topic.title)
        from_email = "{} <{}>".format(
            settings.ZDS_APP["site"]["literal_name"],
            settings.ZDS_APP["site"]["email_noreply"])
        for recipient in n_topic.participants.values_list("email", flat=True):
            message_html = render_to_string("email/direct.html",
                                            {"msg": emarkdown(text)})
            message_txt = render_to_string("email/direct.txt", {"msg": text})

            msg = EmailMultiAlternatives(subject, message_txt, from_email,
                                         [recipient])
            msg.attach_alternative(message_html, "text/html")
            try:
                msg.send()
            except Exception as e:
                logger.exception("Message was not sent to %s due to %s",
                                 recipient, e)
    if no_notification_for:
        if not isinstance(no_notification_for, list):
            no_notification_for = [no_notification_for]
        for not_notified_user in no_notification_for:
            mark_read(n_topic, not_notified_user)

    # There's no need to inform of the new participant
    # because participants are already notified through the `message_added` signal.
    # If we tried to add the bot, that's fine (a better solution would be welcome though)
    with suppress(NotReachableError):
        n_topic.add_participant(author, silent=True)
        n_topic.save()

    return n_topic
Beispiel #30
0
    def post(self, request, *args, **kwargs):
        validation = get_object_or_404(Validation, pk=kwargs["pk"])
        if validation.validator:
            validation.validator = None
            validation.date_reserve = None
            validation.status = "PENDING"
            validation.save()
            messages.info(request, _("Ce contenu n'est plus réservé."))
            return redirect(reverse("validation:list"))
        else:
            validation.validator = request.user
            validation.date_reserve = datetime.now()
            validation.status = "PENDING_V"
            validation.save()

            versioned = validation.content.load_version(sha=validation.version)
            msg = render_to_string(
                "tutorialv2/messages/validation_reserve.md",
                {
                    "content":
                    versioned,
                    "url":
                    versioned.get_absolute_url() + "?version=" +
                    validation.version,
                },
            )

            authors = list(validation.content.authors.all())
            if validation.validator in authors:
                authors.remove(validation.validator)
            if len(authors) > 0:
                if not validation.content.validation_private_message:
                    validation.content.validation_private_message = send_mp(
                        validation.validator,
                        authors,
                        _("Contenu réservé - {0}").format(
                            validation.content.title),
                        validation.content.title,
                        msg,
                        send_by_mail=True,
                        leave=False,
                        direct=False,
                        mark_as_read=True,
                        hat=get_hat_from_settings("validation"),
                    )
                    validation.content.save()
                else:
                    send_message_mp(
                        validation.validator,
                        validation.content.validation_private_message, msg)
                mark_read(validation.content.validation_private_message,
                          validation.validator)

            messages.info(
                request,
                _("Ce contenu a bien été réservé par {0}.").format(
                    request.user.username))

            return redirect(
                reverse("content:view",
                        args=[validation.content.pk, validation.content.slug])
                + "?version=" + validation.version)