mirror of
https://github.com/rottenwheel/revuo-weekly.git
synced 2024-11-10 05:03:35 +01:00
Compare commits
8 Commits
caadb6f075
...
b759140df9
Author | SHA1 | Date | |
---|---|---|---|
|
b759140df9 | ||
|
7e77c3643d | ||
|
cf25a22641 | ||
|
3968fd4248 | ||
|
e231c4d8c5 | ||
|
f3207b7a7d | ||
|
c10217ea48 | ||
|
d93c0a86bc |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
.DS_Store
|
||||
public/
|
||||
resources/
|
||||
.hugo-build.lock
|
||||
.hugo_build.lock
|
||||
venv/
|
4493
assets/img/cover-template.svg
Normal file
4493
assets/img/cover-template.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 376 KiB |
@ -6,6 +6,8 @@ name: Revuo
|
||||
title: Support Revuo
|
||||
---
|
||||
|
||||
Revuo Monero is an audience-funded newsletter: domain & hosting expenses are covered with the help of readers. Editorial time spent accumulating resources and news is solely volunteered by [rottenwheel](https://www.rottenwheel.com/).
|
||||
Revuo Monero is an audience-funded newsletter: domain & hosting expenses are covered with the help of generous readers. Editorial time spent curating resources and news is solely volunteered by [rottenwheel](https://www.rottenwheel.com/).
|
||||
|
||||
Kuno: Revuo Monero code enhancements and rebranding [fundraiser](https://kuno.anne.media/fundraiser/kaib/).
|
||||
|
||||
No paywalls. No ads. No analytics.
|
177
new_issue.py
Executable file
177
new_issue.py
Executable file
@ -0,0 +1,177 @@
|
||||
#!/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)
|
Loading…
Reference in New Issue
Block a user