Exemple #1
0
def post_group_topics(
    request: Request,
    title: str,
    markdown: str,
    link: str,
    tags: str,
) -> HTTPFound:
    """Post a new topic to a group."""
    if link:
        new_topic = Topic.create_link_topic(
            group=request.context,
            author=request.user,
            title=title,
            link=link,
        )

        # if they specified both a link and markdown, use the markdown to post
        # an initial comment on the topic
        if markdown:
            new_comment = Comment(
                topic=new_topic,
                author=request.user,
                markdown=markdown,
            )
            request.db_session.add(new_comment)
    else:
        new_topic = Topic.create_text_topic(
            group=request.context,
            author=request.user,
            title=title,
            markdown=markdown,
        )

    try:
        new_topic.tags = tags.split(',')
    except ValidationError:
        raise ValidationError({'tags': ['Invalid tags']})

    request.db_session.add(new_topic)

    request.db_session.add(
        LogTopic(LogEventType.TOPIC_POST, request, new_topic))

    # flush the changes to the database so the new topic's ID is generated
    request.db_session.flush()

    raise HTTPFound(location=new_topic.permalink)
Exemple #2
0
def text_topic(db, session_group, session_user):
    """Create a text topic in the db and delete it as teardown."""
    new_topic = Topic.create_text_topic(
        session_group, session_user, 'A Text Topic', 'the text')
    db.add(new_topic)
    db.commit()

    yield new_topic

    db.delete(new_topic)
    db.commit()
Exemple #3
0
    def _generate_link_metadata(self, topic: Topic) -> None:
        """Generate metadata for a link topic (domain)."""
        if not topic.link:
            return

        parsed_domain = get_domain_from_url(topic.link)
        domain = self.public_suffix_list.get_public_suffix(parsed_domain)

        topic.content_metadata = {
            'domain': domain,
        }
Exemple #4
0
def link_topic(db, session_group, session_user):
    """Create a link topic in the db and delete it as teardown."""
    new_topic = Topic.create_link_topic(session_group, session_user,
                                        'A Link Topic', 'http://example.com')
    db.add(new_topic)
    db.commit()

    yield new_topic

    db.delete(new_topic)
    db.commit()
Exemple #5
0
def topic(db, session_group, session_user):
    """Create a topic in the db, delete it as teardown (including comments)."""
    new_topic = Topic.create_text_topic(
        session_group, session_user, 'Some title', 'some text')
    db.add(new_topic)
    db.commit()

    yield new_topic

    db.query(Comment).filter_by(topic_id=new_topic.topic_id).delete()
    db.delete(new_topic)
    db.commit()
Exemple #6
0
def link_topic(db, session_group, session_user):
    """Create a link topic, delete it as teardown (including comments)."""
    new_topic = Topic.create_link_topic(session_group, session_user,
                                        "A Link Topic", "http://example.com")
    db.add(new_topic)
    db.commit()

    yield new_topic

    db.query(Comment).filter_by(topic_id=new_topic.topic_id).delete()
    db.delete(new_topic)
    db.commit()
Exemple #7
0
def text_topic(db, session_group, session_user):
    """Create a text topic, delete it as teardown (including comments)."""
    new_topic = Topic.create_text_topic(session_group, session_user,
                                        "A Text Topic", "the text")
    db.add(new_topic)
    db.commit()

    yield new_topic

    db.query(Comment).filter_by(topic_id=new_topic.topic_id).delete()
    db.delete(new_topic)
    db.commit()
Exemple #8
0
    def create_topic(self) -> Topic:
        """Create and return an actual Topic for this scheduled topic."""
        # if no user is specified, use the "generic"/automatic user (ID -1)
        if self.user:
            user = self.user
        else:
            user = (Session.object_session(self).query(User).filter(
                User.user_id == -1).one())

        topic = Topic.create_text_topic(self.group, user, self.title,
                                        self.markdown)
        topic.tags = self.tags
        topic.schedule = self

        return topic
Exemple #9
0
    def _generate_text_metadata(topic: Topic) -> None:
        """Generate metadata for a text topic (word count and excerpt)."""
        html_tree = HTMLParser().parseFragment(topic.rendered_html)

        # extract the text from all of the HTML elements
        extracted_text = ''.join(
            [element_text for element_text in html_tree.itertext()])

        # sanitize unicode, remove leading/trailing whitespace, etc.
        extracted_text = simplify_string(extracted_text)

        # create a short excerpt by truncating the simplified string
        excerpt = truncate_string(
            extracted_text,
            length=200,
            truncate_at_chars=' ',
        )

        topic.content_metadata = {
            'word_count': word_count(extracted_text),
            'excerpt': excerpt,
        }
Exemple #10
0
def get_settings_theme_previews(request: Request) -> dict:
    """Generate the theme preview page."""
    # get the generic/unknown user and a random group to display on the example posts
    fake_user = request.query(User).filter(User.user_id == -1).one()
    group = request.query(Group).order_by(func.random()).limit(1).one()

    fake_link_topic = Topic.create_link_topic(group, fake_user,
                                              "Example Link Topic",
                                              "https://tildes.net/")

    fake_text_topic = Topic.create_text_topic(group, fake_user,
                                              "Example Text Topic",
                                              "No real text")
    fake_text_topic.content_metadata = {
        "excerpt": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
    }

    fake_topics = [fake_link_topic, fake_text_topic]

    # manually add other necessary attributes to the fake topics
    for fake_topic in fake_topics:
        fake_topic.topic_id = sys.maxsize
        fake_topic.tags = ["tag one", "tag two"]
        fake_topic.num_comments = 123
        fake_topic.num_votes = 12
        fake_topic.created_time = utc_now() - timedelta(hours=12)

    # create a fake top-level comment that appears to be written by the user
    markdown = (
        "This is what a regular comment written by yourself would look like.\n\n"
        "It has **formatting** and a [link](https://tildes.net).")
    fake_top_comment = Comment(fake_link_topic, request.user, markdown)
    fake_top_comment.comment_id = sys.maxsize
    fake_top_comment.created_time = utc_now() - timedelta(hours=12, minutes=30)

    child_comments_markdown = [
        ("This reply has received an Exemplary label. It also has a blockquote:\n\n"
         "> Hello World!"),
        ("This is a reply written by the topic's OP with a code block in it:\n\n"
         "```js\n"
         "function foo() {\n"
         "    ['1', '2', '3'].map(parseInt);\n"
         "}\n"
         "```"),
        ("This reply is new and has the *Mark New Comments* stripe on its left "
         "(even if you don't have that feature enabled)."),
    ]

    fake_comments = [fake_top_comment]

    # vary the ID and created_time on each fake comment so CommentTree works properly
    current_comment_id = fake_top_comment.comment_id
    current_created_time = fake_top_comment.created_time
    for markdown in child_comments_markdown:
        current_comment_id -= 1
        current_created_time += timedelta(minutes=5)

        fake_comment = Comment(fake_link_topic,
                               fake_user,
                               markdown,
                               parent_comment=fake_top_comment)
        fake_comment.comment_id = current_comment_id
        fake_comment.created_time = current_created_time
        fake_comment.parent_comment_id = fake_top_comment.comment_id

        fake_comments.append(fake_comment)

    # add other necessary attributes to all of the fake comments
    for fake_comment in fake_comments:
        fake_comment.num_votes = 0

    fake_tree = CommentTree(fake_comments, CommentTreeSortOption.NEWEST,
                            request.user)

    # add a fake Exemplary label to the first child comment
    fake_comments[1].labels = [
        CommentLabel(fake_comments[1], fake_user, CommentLabelOption.EXEMPLARY,
                     1.0)
    ]

    # the comment to mark as new is the last one, so set a visit time just before it
    fake_last_visit_time = fake_comments[-1].created_time - timedelta(
        minutes=1)

    return {
        "theme_options": THEME_OPTIONS,
        "fake_topics": fake_topics,
        "fake_comment_tree": fake_tree,
        "last_visit": fake_last_visit_time,
    }
Exemple #11
0
def post_group_topics(
    request: Request,
    title: str,
    markdown: str,
    link: str,
    tags: str,
    confirm_repost: bool,
) -> Union[HTTPFound, Response]:
    """Post a new topic to a group."""
    group = request.context

    if link:
        # check to see if this link has been posted before
        previous_topics = (request.query(Topic).filter(
            Topic.link == link).order_by(desc(
                Topic.created_time)).limit(5).all())

        if previous_topics and not confirm_repost:
            # Render partial form for Intercooler.js request, whole page for normal POST
            # (I don't like this much, there must be a better way to handle this)
            if "X-IC-Request" in request.headers:
                template = "tildes:templates/includes/new_topic_form.jinja2"
            else:
                template = "tildes:templates/new_topic.jinja2"

            return render_to_response(
                template,
                {
                    "group": group,
                    "title": title,
                    "link": link,
                    "markdown": markdown,
                    "tags": tags,
                    "previous_topics": previous_topics,
                },
                request=request,
            )

        new_topic = Topic.create_link_topic(group=group,
                                            author=request.user,
                                            title=title,
                                            link=link)

        # if they specified both a link and markdown, use the markdown to post an
        # initial comment on the topic
        if markdown:
            new_comment = Comment(topic=new_topic,
                                  author=request.user,
                                  markdown=markdown)
            request.db_session.add(new_comment)

            request.db_session.add(
                LogComment(LogEventType.COMMENT_POST, request, new_comment))
    else:
        new_topic = Topic.create_text_topic(group=group,
                                            author=request.user,
                                            title=title,
                                            markdown=markdown)

    try:
        new_topic.tags = tags.split(",")
    except ValidationError:
        raise ValidationError({"tags": ["Invalid tags"]})

    # remove any tag that's the same as the group's name
    new_topic.tags = [tag for tag in new_topic.tags if tag != str(group.path)]

    request.apply_rate_limit("topic_post")

    request.db_session.add(new_topic)

    request.db_session.add(
        LogTopic(LogEventType.TOPIC_POST, request, new_topic))

    # if the user added tags to the topic, show the field by default in the future
    if tags and not request.user.show_tags_on_new_topic:
        request.user.show_tags_on_new_topic = True
        request.db_session.add(request.user)

    # flush the changes to the database so the new topic's ID is generated
    request.db_session.flush()

    raise HTTPFound(location=new_topic.permalink)
Exemple #12
0
def test_no_convert_partial_caps_title(session_user, session_group):
    """Ensure that partially-caps titles are not converted to title case."""
    topic = Topic.create_link_topic(session_group, session_user,
                                    "This is a TITLE", "http://example.com")
    assert topic.title == "This is a TITLE"
Exemple #13
0
def test_convert_all_caps(session_user, session_group):
    """Ensure that all-caps titles are converted to title case."""
    topic = Topic.create_link_topic(session_group, session_user, "THE TITLE",
                                    "http://example.com")
    assert topic.title == "The Title"