Exemple #1
0
def post_comment_reply(request: Request, markdown: str) -> dict:
    """Post a reply to a comment with Intercooler."""
    parent_comment = request.context
    new_comment = Comment(
        topic=parent_comment.topic,
        author=request.user,
        markdown=markdown,
        parent_comment=parent_comment,
    )
    request.db_session.add(new_comment)

    request.db_session.add(
        LogComment(LogEventType.COMMENT_POST, request, new_comment))

    if CommentNotification.should_create_reply_notification(new_comment):
        notification = CommentNotification(
            parent_comment.user, new_comment,
            CommentNotificationType.COMMENT_REPLY)
        request.db_session.add(notification)

    _mark_comment_read_from_interaction(request, parent_comment)

    # commit and then re-query the new comment to get complete data
    request.tm.commit()

    new_comment = (request.query(Comment).join_all_relationships().filter_by(
        comment_id=new_comment.comment_id).one())

    return {"comment": new_comment}
Exemple #2
0
def post_toplevel_comment(request: Request, markdown: str) -> dict:
    """Post a new top-level comment on a topic with Intercooler."""
    topic = request.context

    new_comment = Comment(topic=topic, author=request.user, markdown=markdown)
    request.db_session.add(new_comment)

    request.db_session.add(LogComment(LogEventType.COMMENT_POST, request, new_comment))

    if CommentNotification.should_create_reply_notification(new_comment):
        notification = CommentNotification(
            topic.user, new_comment, CommentNotificationType.TOPIC_REPLY
        )
        request.db_session.add(notification)

    # commit and then re-query the new comment to get complete data
    request.tm.commit()

    new_comment = (
        request.query(Comment)
        .join_all_relationships()
        .filter_by(comment_id=new_comment.comment_id)
        .one()
    )

    return {"comment": new_comment, "topic": topic}
Exemple #3
0
def test_prevent_duplicate_notifications(db, user_list, topic):
    """Test that notifications are cleaned up for edits.

    Flow:
        1. A comment is created by user A that mentions user B. Notifications are
           generated, and yield A mentioning B.
        2. The comment is edited to mention C and not B.
        3. The comment is edited to mention B and C.
        4. The comment is deleted.
    """
    # 1
    comment = Comment(topic, user_list[0], f"@{user_list[1].username}")
    db.add(comment)
    db.commit()
    mentions = CommentNotification.get_mentions_for_comment(db, comment)
    assert len(mentions) == 1
    assert mentions[0].user == user_list[1]
    db.add_all(mentions)
    db.commit()

    # 2
    comment.markdown = f"@{user_list[2].username}"
    db.commit()
    mentions = CommentNotification.get_mentions_for_comment(db, comment)
    assert len(mentions) == 1
    to_delete, to_add = CommentNotification.prevent_duplicate_notifications(
        db, comment, mentions)
    assert len(to_delete) == 1
    assert mentions == to_add
    assert to_delete[0].user.username == user_list[1].username

    # 3
    comment.markdown = f"@{user_list[1].username} @{user_list[2].username}"
    db.commit()
    mentions = CommentNotification.get_mentions_for_comment(db, comment)
    assert len(mentions) == 2
    to_delete, to_add = CommentNotification.prevent_duplicate_notifications(
        db, comment, mentions)
    assert not to_delete
    assert len(to_add) == 1

    # 4
    comment.is_deleted = True
    db.commit()
    notifications = (db.query(CommentNotification.user_id).filter(
        and_(
            CommentNotification.comment_id == comment.comment_id,
            CommentNotification.notification_type ==
            CommentNotificationType.USER_MENTION,
        )).all())
    assert not notifications
Exemple #4
0
def post_comment_on_topic(request: Request, markdown: str) -> HTTPFound:
    """Post a new top-level comment on a topic."""
    topic = request.context

    new_comment = Comment(topic=topic, author=request.user, markdown=markdown)
    request.db_session.add(new_comment)

    request.db_session.add(
        LogComment(LogEventType.COMMENT_POST, request, new_comment))

    if CommentNotification.should_create_reply_notification(new_comment):
        notification = CommentNotification(topic.user, new_comment,
                                           CommentNotificationType.TOPIC_REPLY)
        request.db_session.add(notification)

    raise HTTPFound(location=topic.permalink)
Exemple #5
0
def test_mention_filtering_top_level(db, user_list, session_group):
    """Test notification filtering for top-level comments."""
    topic = Topic.create_text_topic(session_group, user_list[0], "Some title",
                                    "some text")
    comment = Comment(topic, user_list[1], f"@{user_list[0].username}")
    mentions = CommentNotification.get_mentions_for_comment(db, comment)
    assert not mentions
Exemple #6
0
def test_mention_filtering_parent_comment(db, topic, user_list):
    """Test notification filtering for parent comments."""
    parent_comment = Comment(topic, user_list[0], "Comment content.")
    comment = Comment(topic, user_list[1], f"@{user_list[0].username}",
                      parent_comment)
    mentions = CommentNotification.get_mentions_for_comment(db, comment)
    assert not mentions
Exemple #7
0
def test_get_mentions_for_comment_escapes_with_backslash(
        db, user_list, comment):
    """Test that backslash escaped mentions are ignored."""
    comment.markdown = "@foo @bar. \@baz!"
    mentions = CommentNotification.get_mentions_for_comment(db, comment)
    assert len(mentions) == 2
    assert "baz" not in [mention.user for mention in mentions]
Exemple #8
0
def test_get_mentions_for_comment(db, user_list, comment):
    """Test that notifications are generated and returned."""
    comment.markdown = "@foo @bar. @baz!"
    mentions = CommentNotification.get_mentions_for_comment(db, comment)
    assert len(mentions) == 3
    for index, user in enumerate(user_list):
        assert mentions[index].user == user
Exemple #9
0
def post_comment_reply(request: Request, markdown: str) -> dict:
    """Post a reply to a comment with Intercooler."""
    parent_comment = request.context
    new_comment = Comment(
        topic=parent_comment.topic,
        author=request.user,
        markdown=markdown,
        parent_comment=parent_comment,
    )
    request.db_session.add(new_comment)

    if parent_comment.user != request.user:
        notification = CommentNotification(
            parent_comment.user,
            new_comment,
            CommentNotificationType.COMMENT_REPLY,
        )
        request.db_session.add(notification)

    # commit and then re-query the new comment to get complete data
    request.tm.commit()

    new_comment = (request.query(Comment).join_all_relationships().filter_by(
        comment_id=new_comment.comment_id).one())

    return {'comment': new_comment}
Exemple #10
0
def post_toplevel_comment(request: Request, markdown: str) -> dict:
    """Post a new top-level comment on a topic with Intercooler."""
    topic = request.context

    new_comment = Comment(
        topic=topic,
        author=request.user,
        markdown=markdown,
    )
    request.db_session.add(new_comment)

    if topic.user != request.user and not topic.is_deleted:
        notification = CommentNotification(
            topic.user,
            new_comment,
            CommentNotificationType.TOPIC_REPLY,
        )
        request.db_session.add(notification)

    # commit and then re-query the new comment to get complete data
    request.tm.commit()

    new_comment = (request.query(Comment).join_all_relationships().filter_by(
        comment_id=new_comment.comment_id).one())

    return {'comment': new_comment, 'topic': topic}
Exemple #11
0
def test_mention_filtering_parent_comment(mocker, db, topic, user_list):
    """Test notification filtering for parent comments."""
    parent_comment = Comment(topic, user_list[0], "Comment content.")
    parent_comment.user_id = user_list[0].user_id
    comment = mocker.Mock(
        user_id=user_list[1].user_id,
        markdown=f"@{user_list[0].username}",
        parent_comment=parent_comment,
    )
    mentions = CommentNotification.get_mentions_for_comment(db, comment)
    assert not mentions
Exemple #12
0
def post_comment_reply(request: Request, markdown: str) -> dict:
    """Post a reply to a comment with Intercooler."""
    parent_comment = request.context

    wait_mins = _reply_wait_minutes(request, request.user, parent_comment.user)
    if wait_mins:
        incr_counter("comment_back_and_forth_warnings")
        raise HTTPUnprocessableEntity(
            f"You can't reply to this user yet. Please wait {wait_mins} minutes."
        )

    new_comment = Comment(
        topic=parent_comment.topic,
        author=request.user,
        markdown=markdown,
        parent_comment=parent_comment,
    )
    request.db_session.add(new_comment)

    request.db_session.add(
        LogComment(LogEventType.COMMENT_POST, request, new_comment))

    if CommentNotification.should_create_reply_notification(new_comment):
        notification = CommentNotification(
            parent_comment.user, new_comment,
            CommentNotificationType.COMMENT_REPLY)
        request.db_session.add(notification)

    _mark_comment_read_from_interaction(request, parent_comment)

    # commit and then re-query the new comment to get complete data
    request.tm.commit()

    new_comment = (request.query(Comment).join_all_relationships().filter_by(
        comment_id=new_comment.comment_id).one())

    return {"comment": new_comment}
    def process_message(self, message: Message) -> None:
        """Process a message from the stream."""
        comment = (self.db_session.query(Comment).filter_by(
            comment_id=message.fields["comment_id"]).one())

        # don't generate mentions for deleted/removed comments
        if comment.is_deleted or comment.is_removed:
            return

        new_mentions = CommentNotification.get_mentions_for_comment(
            self.db_session, comment)

        if message.stream == "comments.insert":
            for user_mention in new_mentions:
                self.db_session.add(user_mention)
        elif message.stream == "comments.update.markdown":
            to_delete, to_add = CommentNotification.prevent_duplicate_notifications(
                self.db_session, comment, new_mentions)

            for user_mention in to_delete:
                self.db_session.delete(user_mention)

            for user_mention in to_add:
                self.db_session.add(user_mention)
    def run(self, msg: Message) -> None:
        """Process a delivered message."""
        comment = (self.db_session.query(Comment).filter_by(
            comment_id=msg.body["comment_id"]).one())

        # don't generate mentions for deleted/removed comments
        if comment.is_deleted or comment.is_removed:
            return

        new_mentions = CommentNotification.get_mentions_for_comment(
            self.db_session, comment)

        if msg.delivery_info["routing_key"] == "comment.created":
            for user_mention in new_mentions:
                self.db_session.add(user_mention)
        elif msg.delivery_info["routing_key"] == "comment.edited":
            to_delete, to_add = CommentNotification.prevent_duplicate_notifications(
                self.db_session, comment, new_mentions)

            for user_mention in to_delete:
                self.db_session.delete(user_mention)

            for user_mention in to_add:
                self.db_session.add(user_mention)
Exemple #15
0
def post_comment_on_topic(request: Request, markdown: str) -> HTTPFound:
    """Post a new top-level comment on a topic."""
    topic = request.context

    new_comment = Comment(
        topic=topic,
        author=request.user,
        markdown=markdown,
    )
    request.db_session.add(new_comment)

    if topic.user != request.user and not topic.is_deleted:
        notification = CommentNotification(
            topic.user,
            new_comment,
            CommentNotificationType.TOPIC_REPLY,
        )
        request.db_session.add(notification)

    raise HTTPFound(location=topic.permalink)
Exemple #16
0
def test_mention_filtering_self_mention(db, user_list, topic):
    """Test notification filtering for self-mentions."""
    comment = Comment(topic, user_list[0], f"@{user_list[0]}")
    mentions = CommentNotification.get_mentions_for_comment(db, comment)
    assert not mentions