#!/usr/bin/env python3 import subprocess import pathlib import argparse import datetime import tempfile import tomllib def get_period_string( start: datetime.datetime, end: datetime.datetime, year: bool = False, ) -> str: """Get a string representation of the period Args: start (datetime.datetime): The start of the period end (datetime.datetime): The end of the period year (bool, optional): Include the year in the string. Defaults to False. Returns: str: The period string """ if period_start.year == period_end.year: if period_start.month == period_end.month: period_string = ( f"{period_start.strftime('%B %d')} - {period_end.strftime('%d')}" ) else: period_string = ( f"{period_start.strftime('%B %d')} - {period_end.strftime('%B %d')}" ) if year: period_string += f", {period_start.year}" else: period_string = ( f"{period_start.strftime('%B %d, %Y')} - {period_end.strftime('%B %d, %Y')}" ) return period_string def create_issue( issue_number: int, period_start: datetime.datetime, period_end: datetime.datetime ) -> None: """Create a new issue Args: issue_number (int): The issue number period_start (datetime.datetime): The start of the period period_end (datetime.datetime): The end of the period Raises: subprocess.CalledProcessError: If the Hugo command fails IOError: If any of the Python file operations fail """ # Use the Hugo CLI to create a new issue subprocess.run( ["hugo", "new", f"weekly/issue-{issue_number}/_index.md"], check=True ) # Read the content of the new file with open(f"content/weekly/issue-{issue_number}/_index.md", "r") as f: content = f.read() # Get line that starts with "title" and replace it with the new title lines = content.split("\n") period_string = get_period_string(period_start, period_end, True) for i, line in enumerate(lines): if line.startswith("title:"): lines[i] = f'title: "Issue {issue_number}: {period_string}"' content = "\n".join(lines) # Overwrite the file with the new content with open(f"content/weekly/issue-{issue_number}/_index.md", "w") as f: f.write(content) def create_issue_image( site_title: str, issue_number: int, period_start: datetime.datetime, period_end: datetime.datetime, ) -> None: """Create a cover image for the issue Args: site_title (str): The title of the site issue_number (int): The issue number period_start (datetime.datetime): The start of the period period_end (datetime.datetime): The end of the period Raises: FileNotFoundError: If the cover template is not found IOError: If any of the file operations fail """ with open("assets/img/cover-template.svg") as f: cover_template = f.read() period_string = get_period_string(period_start, period_end) cover_template = cover_template.replace("__SITE__", site_title) cover_template = cover_template.replace("__TITLE__", f"Issue {issue_number}") cover_template = cover_template.replace("__DATE__", period_string) with tempfile.TemporaryDirectory() as tempdir: cover_path = pathlib.Path(tempdir) / "cover.svg" with open(cover_path, "w") as f: f.write(cover_template) subprocess.run( [ "inkscape", str(cover_path), "--export-filename", f"content/weekly/issue-{issue_number}/cover.png", ] ) def get_latest_issue() -> int: """Get the latest issue number from the weekly directory Returns: int: The latest issue number """ issues = list(pathlib.Path("content/weekly").iterdir()) latest_issue = max(issues, key=lambda x: int(x.name.split("-")[1])) return int(latest_issue.name.split("-")[1]) if __name__ == "__main__": with open("hugo.toml", "rb") as f: hugo_config = tomllib.load(f) parser = argparse.ArgumentParser(description="Create a new issue") parser.add_argument("--issue", type=int, help="Issue number") parser.add_argument("--period-start", type=str, help="Period start") parser.add_argument("--period-end", type=str, help="Period end") parser.add_argument("--quiet", "-q", action="store_true", help="Quiet mode") args = parser.parse_args() if not (args.period_start and args.period_end): if not args.quiet: # Query the user for the period start and end today = datetime.datetime.now().strftime("%Y-%m-%d") period_start_str = input(f"Period start [{today}]: ") or today period_start = datetime.datetime.strptime(period_start_str, "%Y-%m-%d") seven_days = (period_start + datetime.timedelta(days=7)).strftime( "%Y-%m-%d" ) period_end_str = input(f"Period end [{seven_days}]: ") or seven_days period_end = datetime.datetime.strptime(period_end_str, "%Y-%m-%d") else: # Assume the period is the next 7 days - # TODO: Check if this is correct period_start = datetime.datetime.now() period_end = datetime.datetime.now() + datetime.timedelta(days=7) if args.issue: new_issue = args.issue else: latest_issue = get_latest_issue() new_issue = int(latest_issue) + 1 create_issue(new_issue, period_start, period_end) create_issue_image(hugo_config["title"], new_issue, period_start, period_end)