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)
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()
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, }
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()
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()
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()
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()
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
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, }
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, }
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)
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"
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"