owenrusk.dev

errands

small jobs the runtime does for the studio.

git clone https://owenrusk.dev/errands.git

commit fc52f839dd62aa1e4d5b4074277637f14ee46c43
parent 061212799d09811db597cde12d9dbb84327bad87
author Owen Rusk <owen@papermothgames.com>
date   2024-11-14 12:44:10 -0600
posts: publish scheduled journal posts when they're due
errands/posts.py+43-0
errands/settings.py+5-0
diff --git a/errands/posts.py b/errands/posts.py
new file mode 100644
index 0000000..911ebc1
--- /dev/null
+++ b/errands/posts.py
@@ -0,0 +1,43 @@
+# the journal on papermothgames.com. posts wait in the site's scheduled/ with a
+# date in their front matter. once it's passed they move to posts/ and the
+# site publishes.
+import re
+import shlex
+import subprocess
+from datetime import datetime
+from pathlib import Path
+
+from . import settings
+
+DATE = re.compile(r"^date:\s*(.+?)\s*$", re.MULTILINE)
+
+
+def when(path: Path) -> datetime | None:
+    text = path.read_text()
+    if not text.startswith("---\n"):
+        return None
+    end = text.find("\n---", 4)
+    found = DATE.search(text[4:end])
+    if not found:
+        return None
+    return datetime.fromisoformat(found.group(1))
+
+
+def due(now: datetime, site: Path) -> list[Path]:
+    ready = []
+    for path in sorted((site / "scheduled").glob("*.md")):
+        at = when(path)
+        if at is not None and at <= now:
+            ready.append(path)
+    return ready
+
+
+def publish_due(now: datetime | None = None, site: Path | None = None, run=subprocess.run) -> list[str]:
+    now = now or datetime.now().astimezone()
+    site = site or settings.SITE
+    published = []
+    for path in due(now, site):
+        path.rename(site / "posts" / path.name)
+        run(shlex.split(settings.SITE_PUBLISH), cwd=site, check=True)
+        published.append(path.stem)
+    return published
diff --git a/errands/settings.py b/errands/settings.py
index 7fca9c8..802d2a1 100644
--- a/errands/settings.py
+++ b/errands/settings.py
@@ -1,5 +1,6 @@
 # everything comes from the environment. nothing secret lives in this file.
 import os
+from pathlib import Path
 
 
 def env(name: str, default: str | None = None) -> str:
@@ -11,3 +12,7 @@ def env(name: str, default: str | None = None) -> str:
 
 SUPPORT_ADDRESS = "support@papermothgames.com"
 SUPPORT_NAME = "Paper Moth Games"
+
+# the site's checkout, and how it publishes
+SITE = Path(os.environ.get("ERRANDS_SITE", "/srv/papermoth-site"))
+SITE_PUBLISH = os.environ.get("ERRANDS_SITE_PUBLISH", "make publish")