import io import uuid import zipfile from datetime import datetime from string import Template from django.conf import settings from django.contrib.auth.decorators import login_required from django.http import HttpResponse from django.shortcuts import render from django.views.decorators.http import require_POST from main import models, util def prepend_zola_frontmatter(body, post_title, pub_date): frontmatter = "+++\n" frontmatter += f'title = "{post_title}"\n' frontmatter += f"date = {pub_date}\n" frontmatter += 'template = "post.html"\n' frontmatter += "+++\n" frontmatter += "\n" return frontmatter + body def prepend_hugo_frontmatter(body, post_title, pub_date, post_slug): frontmatter = "+++\n" frontmatter += f'title = "{post_title}"\n' frontmatter += f"date = {pub_date}\n" frontmatter += f'url = "blog/{post_slug}"\n' frontmatter += "+++\n" frontmatter += "\n" return frontmatter + body def export_index(request): return render(request, "main/export_index.html") @login_required def export_markdown(request): if request.method == "POST": # get all user posts and add them into export_posts encoded posts = models.Post.objects.filter(owner=request.user) export_posts = [] for p in posts: pub_date = p.published_at or p.created_at title = p.slug + ".md" body = f"# {p.title}\n\n" body += f"> Published on {pub_date.strftime('%b %-d, %Y')}\n\n" if p.tags: tags_line = ", ".join(p.tag_list) body += f"> Tags: {tags_line}\n\n" body += f"{p.body}\n" export_posts.append((title, io.BytesIO(body.encode()))) # create zip archive in memory export_name = "export-markdown-" + str(uuid.uuid4())[:8] container_dir = f"{request.user.username}-bocpress-blog" zip_buffer = io.BytesIO() with zipfile.ZipFile( zip_buffer, "a", zipfile.ZIP_DEFLATED, False ) as export_archive: for file_name, data in export_posts: export_archive.writestr( export_name + f"/{container_dir}/" + file_name, data.getvalue() ) response = HttpResponse(zip_buffer.getvalue(), content_type="application/zip") response["Content-Disposition"] = f"attachment; filename={export_name}.zip" return response @login_required def export_zola(request): if request.method == "POST": # load zola templates with open("./export_base_zola/config.toml") as zola_config_file: zola_config = ( zola_config_file.read() .replace("example.com", f"{request.user.username}.bocpress.co.uk") .replace("Example blog title", f"{request.user.username} blog") .replace( "Example blog description", f"{request.user.blog_byline or ''}" ) ) with open("./export_base_zola/style.css") as zola_styles_file: zola_styles = zola_styles_file.read() with open("./export_base_zola/index.html") as zola_index_file: zola_index = zola_index_file.read() with open("./export_base_zola/post.html") as zola_post_file: zola_post = zola_post_file.read() with open("./export_base_zola/_index.md") as zola_content_index_file: zola_content_index = zola_content_index_file.read() with open("./export_base_zola/404.html") as zola_404_file: zola_404 = zola_404_file.read() # get all user posts and add them into export_posts encoded posts = models.Post.objects.filter(owner=request.user) export_posts = [] for p in posts: pub_date = p.published_at or p.created_at.date() title = p.slug + ".md" body = prepend_zola_frontmatter( p.body, util.escape_quotes(p.title), pub_date ) export_posts.append((title, io.BytesIO(body.encode()))) # create zip archive in memory export_name = "export-zola-" + str(uuid.uuid4())[:8] zip_buffer = io.BytesIO() with zipfile.ZipFile( zip_buffer, "a", zipfile.ZIP_DEFLATED, False ) as export_archive: export_archive.writestr(export_name + "/config.toml", zola_config) export_archive.writestr(export_name + "/static/style.css", zola_styles) export_archive.writestr(export_name + "/templates/index.html", zola_index) export_archive.writestr(export_name + "/templates/post.html", zola_post) export_archive.writestr(export_name + "/templates/404.html", zola_404) export_archive.writestr( export_name + "/content/_index.md", zola_content_index ) for file_name, data in export_posts: export_archive.writestr( export_name + "/content/" + file_name, data.getvalue() ) response = HttpResponse(zip_buffer.getvalue(), content_type="application/zip") response["Content-Disposition"] = f"attachment; filename={export_name}.zip" return response @login_required def export_hugo(request): if request.method == "POST": # load hugo templates with open("./export_base_hugo/config.toml") as hugo_config_file: blog_title = request.user.blog_title or f"{request.user.username} blog" blog_byline = request.user.blog_byline or "" hugo_config = ( hugo_config_file.read() .replace("example.com", f"{request.user.username}.bocpress.co.uk") .replace("Example blog title", blog_title) .replace("Example blog description", blog_byline) ) with open("./export_base_hugo/theme.toml") as hugo_theme_file: hugo_theme = hugo_theme_file.read() with open("./export_base_hugo/style.css") as hugo_styles_file: hugo_styles = hugo_styles_file.read() with open("./export_base_hugo/single.html") as hugo_single_file: hugo_single = hugo_single_file.read() with open("./export_base_hugo/list.html") as hugo_list_file: hugo_list = hugo_list_file.read() with open("./export_base_hugo/index.html") as hugo_index_file: hugo_index = hugo_index_file.read() with open("./export_base_hugo/baseof.html") as hugo_baseof_file: hugo_baseof = hugo_baseof_file.read() with open("./export_base_hugo/404.html") as hugo_404_file: hugo_404 = hugo_404_file.read() # get all user posts and add them into export_posts encoded posts = models.Post.objects.filter(owner=request.user) export_posts = [] for p in posts: title = p.slug + ".md" pub_date = p.published_at or p.created_at.date() body = prepend_hugo_frontmatter( p.body, util.escape_quotes(p.title), pub_date, p.slug ) export_posts.append((title, io.BytesIO(body.encode()))) # create zip archive in memory export_name = "export-hugo-" + str(uuid.uuid4())[:8] zip_buffer = io.BytesIO() with zipfile.ZipFile( zip_buffer, "a", zipfile.ZIP_DEFLATED, False ) as export_archive: export_archive.writestr(export_name + "/config.toml", hugo_config) export_archive.writestr( export_name + "/themes/mataroa/theme.toml", hugo_theme ) export_archive.writestr( export_name + "/themes/mataroa/static/style.css", hugo_styles ) export_archive.writestr( export_name + "/themes/mataroa/layouts/index.html", hugo_index ) export_archive.writestr( export_name + "/themes/mataroa/layouts/404.html", hugo_404 ) export_archive.writestr( export_name + "/themes/mataroa/layouts/_default/single.html", hugo_single, ) export_archive.writestr( export_name + "/themes/mataroa/layouts/_default/list.html", hugo_list ) export_archive.writestr( export_name + "/themes/mataroa/layouts/_default/baseof.html", hugo_baseof, ) for file_name, data in export_posts: export_archive.writestr( export_name + "/content/" + file_name, data.getvalue() ) response = HttpResponse(zip_buffer.getvalue(), content_type="application/zip") response["Content-Disposition"] = f"attachment; filename={export_name}.zip" return response def export_unsubscribe_key(request, unsubscribe_key): if models.User.objects.filter(export_unsubscribe_key=unsubscribe_key).exists(): user = models.User.objects.get(export_unsubscribe_key=unsubscribe_key) user.mail_export_on = False user.export_unsubscribe_key = uuid.uuid4() user.save() return render( request, "main/export_unsubscribe_success.html", { "blog_user": request.blog_user, "unsubscribed": True, "email": user.email, }, ) else: return render( request, "main/export_unsubscribe_success.html", { "blog_user": request.blog_user, "unsubscribed": False, }, ) @login_required def export_print(request): return render( request, "main/export_print.html", { "posts": models.Post.objects.filter(owner=request.user).order_by( "-published_at" ), }, ) def _get_epub_author(blog_user): return f"""
{blog_user.about_as_html}
""" def _get_epub_titlepage(blog_user): return f"""{blog_user.blog_byline}
~{blog_user.username}
""" def _get_epub_chapter(post): chapter_body = post.body_as_html # process image urls image_url_like = util.get_protocol() + "//" + settings.CANONICAL_HOST + "/images/" if image_url_like in chapter_body: chapter_body = chapter_body.replace(image_url_like, "images/") # xhtml replacements chapter_body = chapter_body.replace("