import uuid
import os
import hashlib
from datetime import datetime
from pathlib import Path
import html2image
import click
import frontmatter
html = """
{date}
James Ravenscroft
@jamesravey@fosstodon.org
"""
def generate_filename_hash(title: str, pubdate: str):
"""Generate the filename for the title card based on post title and pub date"""
fhash = hashlib.new("sha256")
fhash.update(f"{title}:{pubdate}".encode("utf8"))
return fhash.hexdigest()
@click.group()
def cli():
pass
@cli.command()
@click.option("--input-file", "-i", required=True, type=click.Path(exists=True))
@click.option("--workspace-path", "-w", required=True, type=click.Path(exists=True))
def single(workspace_path, input_file):
"""Generate a title card for a single post"""
generate_card(input_file, workspace_path)
@cli.command()
@click.option("--subdir", "-i", required=True, type=click.Path(exists=True))
@click.option("--workspace-path", "-w", required=True, type=click.Path(exists=True))
def tree(workspace_path, subdir):
"""Retursively walk subdir and generate title cards for all posts"""
for root, dirs, files in os.walk(subdir):
for file in files:
if file.endswith(".md"):
generate_card(os.path.join(root, file), workspace_path)
def generate_card(input_file, workspace_path):
print(f"Loading {input_file}")
front_matter = frontmatter.load(input_file)
title: str = str(front_matter.get("title"))
date: str = str(front_matter.get("date", datetime.now().isoformat()))
if title and date:
parsed_date = datetime.fromisoformat(date).strftime("%b %d, %Y")
parsed_html = html.replace("{title}", title).replace("{date}", parsed_date)
# file_name = f"{uuid.uuid4()}.png"
file_name = f"{generate_filename_hash(title, date)}.png"
hti = html2image.Html2Image()
output_path = Path(workspace_path) / "static" / "social" / file_name
if os.path.exists(output_path):
print(f"{output_path} Already exists, using cached image")
return
hti.temp_path = Path(workspace_path) / "tmp"
if not os.path.exists(hti.temp_path):
os.mkdir(hti.temp_path)
files = hti.screenshot(
html_str=[parsed_html], save_as=file_name, size=[(1128, 600)]
)
# move from tmp location to workspace folder
output_path = output_path.absolute().as_posix()
os.rename(files[0], output_path)
if "preview" in front_matter:
# strip '/social/' from the existing preview value
old_fin = front_matter["preview"][:8]
old_fill_path = Path(workspace_path) / "static" / "social" / old_fin
if os.path.exists(old_fill_path):
print(f"Move {old_fill_path} into cleanup...")
os.rename(old_fill_path, old_fill_path + ".cleanup")
front_matter["preview"] = f"/social/{file_name}"
frontmatter.dump(front_matter, input_file)
if __name__ == "__main__":
cli()