def delete_comment() -> None: comment_id = int(input("Comment ID: ")) if comment := db.query(Comment).get(comment_id): db.delete(comment) print(f"Deleted comment \"{comment.name}\".") save_tip() return
def concrete(): name = input(input_question) if obj := db.query(row_class).filter_by(name=name).first(): print(f"{deleted_prefix} \"{obj.name}\".") db.delete(obj) save_tip() return
def get_blog_post_by_id() -> BlogPost: try: blog_post_id = int(input("Blog Post ID: ")) except ValueError: print("Invalid ID!") raise PostNotFoundException() if (blog_post := db.query(BlogPost).get(blog_post_id)) is None: print(f"No post with ID {blog_post_id}!") raise PostNotFoundException()
def delete_author() -> None: author_name = input("Author Name: ") if author := db.query(Author).filter_by(name=author_name).first(): for blog_post in author.blog_posts: print(f"Deleted blog post \"{blog_post.name}\".") shutil.rmtree(blog_post.slug_path) db.delete(blog_post) db.delete(author) print(f"Deleted author \"{author.name}\".") save_tip() return
def show_posts() -> None: if posts := db.query(BlogPost).all(): longest_title = max(len(post.name) for post in posts) longest_author = max(len(post.author.name) for post in posts) print(f"| ID | {'Title'.rjust(longest_title)} | {'Author'.rjust(longest_author)} | " f"Hits | Commentable | In Graph | Hidden |") print(f"|-----|-{'-' * longest_title}-|-{'-' * longest_author}-|------|-------------|----------|--------|") for post in posts: print(f"| {str(post.id).rjust(3)} | {post.name.rjust(longest_title)} | " f"{post.author.name.rjust(longest_author)} | " f"{str(post.hits).rjust(4)} | " f" {x_if_true(post.allow_comments)} | " f" {x_if_true(post.include_in_graph)} | " f" {x_if_true(post.hidden)} |")
def generate_sitemap() -> str: # Semi-minimal sitemap implementation according to https://www.sitemaps.org/protocol.html urlset = eT.Element("urlset", xmlns="http://www.sitemaps.org/schemas/sitemap/0.9") insert_url = functools.partial(_insert_url, urlset, get_base_url()) insert_url(loc="", priority=1) for post in db.query(BlogPost): insert_url(loc=url_for("home.route_blog_post", blog_post_id=post.id, _name=post.slug), priority=0.8) for tag in db.query(Tag): insert_url(loc=url_for("home.route_tag", tag_id=tag.id, _name=tag.slug), priority=0.6) for author in db.query(Author): insert_url(loc=url_for("home.route_author", author_id=author.id, _name=author.slug), priority=0.4) return XML_HEADER + eT.tostring(urlset, encoding="unicode", method="xml")
def route_root() -> any: quote = random.choice(route_root.quotes) friends = db.query(Friend).all() category_tags = [ tag for tag in db.query(Tag).filter_by(main_section=True) if tag.blog_posts ] blog_posts = get_all_visible_blog_posts().order_by( BlogPost.timestamp.desc()).limit(5).all() return render_template("home.html", title="Root", header="Welcome to the Flesh-Network.", sub_header=quote, blog_posts=blog_posts, friends=friends, category_tags=category_tags, quote=quote)
def spellcheck() -> None: en_checker = SpellChecker(language="en") de_checker = SpellChecker(language="de") for post in db.query(BlogPost): markdown = read_file(post.markdown_path) for i, line in enumerate(markdown.splitlines()): words = [re.sub(r"[^a-zA-Z ]", "", word) for word in line.replace("-", " ").split()] words = [word for word in words if word] unknown_en_words = en_checker.unknown(words) unknown_de_words = de_checker.unknown(words) unknown_words = [word for word in unknown_en_words if word in unknown_de_words] for unknown_word in unknown_words: print(f"In \"{post.name}\" (line {i + 1}): Unknown word \"{unknown_word}\".") done()
def detach_tag() -> None: tag_name = input("Tag Name: ") if not (tag := db.query(Tag).filter_by(name=tag_name).first()): print("Tag not found!") return
def get_all_nodes() -> any: return db.query(BlogPost).filter_by(include_in_graph=True)
def create_blog_post() -> None: author_name = input("Author Name: ") if not (author := db.query(Author).filter_by(name=author_name).first()): print(f"No author with name: \"{author_name}\".") exit()
def get_all_blog_posts() -> any: return db.query(BlogPost).filter_by(include_in_graph=False)
def handle_404_error(exception: HTTPException) -> any: random_blog_posts = random.sample(db.query(BlogPost).all(), 5) return render_template("error_404.html", title=format_exception(exception), blog_posts=random_blog_posts, exception=exception, return_to_root=True), exception.code
def route_blog_post(blog_post_id: int, _name: str = "") -> any: if (blog_post := db.query(BlogPost).get(blog_post_id)) is None: abort(404)
def show_rows(row_class: type) -> None: if rows := db.query(row_class).all(): print(f"Currently registered {row_class.__name__}s:") for row in rows: print(f" * {str(row.id).rjust(3)} - \"{row.name}\"")
def select_object(row_class: type) -> None: object_id = int(input(f"{row_class.__name__} ID: ")) if not (result := db.query(row_class).get(object_id)): print(f"No object of type {row_class.__name__} with ID {object_id} exists.") return
print(f"Attached tag \"{tag.name}\" to post \"{blog_post.name}\"!") tag_association = TagAssociation(blog_post.id, tag.id) db.add(tag_association) save_tip() def detach_tag() -> None: tag_name = input("Tag Name: ") if not (tag := db.query(Tag).filter_by(name=tag_name).first()): print("Tag not found!") return blog_post = get_blog_post_by_id() if (tag_association := db.query(TagAssociation).filter_by(blog_post_id=blog_post.id, tag_id=tag.id) .first()) is None: print("Tag is not attached to post!") return print(f"Detached tag \"{tag.name}\" from post \"{blog_post.name}\"!") db.delete(tag_association) save_tip() def exit_program() -> None: print("Exiting...\n") sys.exit(0) def save_changes() -> None: print("Saving changes... ", end="")
def get_all_visible_blog_posts() -> any: return db.query(BlogPost).filter_by(hidden=False)
def route_backlinks() -> Response: return render_template("backlinks.html", title="Backlinks", return_to_root=True, hostnames=db.query(ReferrerHostname).all())
def route_tag(tag_id: int, _name: str = "") -> any: # The "name" parameter is called "_name" to avoid unused variable # warnings in PyCharm. It is not beautiful but better than someone # removing them just by following suggestions. if (tag := db.query(Tag).get(tag_id)) is None: abort(404)
def route_author(author_id: int, _name: str = "") -> any: if (author := db.query(Author).get(author_id)) is None: abort(404)
# A file reference if decoded_reference := has_prefix(reference, "file:"): name_mapping = { fr.clear_name: fr.name for fr in blog_post.file_resources } if hashed_file_name := name_mapping.get(decoded_reference): return "/" + in_res_path(hashed_file_name) # If the filename isn't in the mapping, the file doesn't exist. critical_error(f"Missing resource \"{decoded_reference}\"!") # An author reference if decoded_reference := has_prefix(reference, "author:"): if author := db.query(Author).filter_by( name=decoded_reference).first(): return f"/authors/{author.id}/{author.slug}/" critical_error(f"Missing author \"{decoded_reference}\"!") # A post reference if decoded_reference := has_prefix(reference, "post:"): if post := db.query(BlogPost).get(int(decoded_reference)): return f"/posts/{post.id}/{post.slug}/" critical_error(f"Missing post \"{decoded_reference}\"!") # A tag reference if decoded_reference := has_prefix(reference, "tag:"): if tag := db.query(Tag).filter_by(name=decoded_reference).first(): return f"/tags/{tag.id}/{tag.slug}/"
def get_all_posts() -> any: return db.query(BlogPost)