Kumi
3968fd4248
Enhanced the issue creation script by adding functionality to input and format the period dates when creating new issues. The script now supports custom period start and end dates and updates the issue title accordingly in the markdown file. This change ensures more accurate issue titles and periods, improving clarity and organization of issues. Additionally added error handling for the Hugo command and Python file operations, improving robustness and reliability.
174 lines
5.5 KiB
Python
Executable file
174 lines
5.5 KiB
Python
Executable file
#!/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
|
|
"""
|
|
subprocess.run(
|
|
["hugo", "new", f"weekly/issue-{issue_number}/_index.md"], check=True
|
|
)
|
|
|
|
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)
|
|
|
|
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)
|