summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-08-07 03:45:47 -0500
committerGitHub <[email protected]>2026-08-07 03:45:47 -0500
commitdb40d346c28800a1eec384a5e4f3d7d090198e4d (patch)
treecebd9fb63f26e402b85f5db4192f5dc844c48a27 /scripts
parent6c26cf048119bf4ff6af039991d3e34d76bac2ad (diff)
parentf9f86b9681909b14304909b1286b9b50362625d7 (diff)
downloadhutch-db40d346c28800a1eec384a5e4f3d7d090198e4d.tar.gz
hutch-db40d346c28800a1eec384a5e4f3d7d090198e4d.tar.bz2
hutch-db40d346c28800a1eec384a5e4f3d7d090198e4d.zip
Merge pull request #32 from krazywarez/sync-man-pages
Sync bundled man page catalog from man.sr.ht (#7)
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/sync_man_pages.py63
1 files changed, 63 insertions, 0 deletions
diff --git a/scripts/sync_man_pages.py b/scripts/sync_man_pages.py
new file mode 100755
index 0000000..c59197a
--- /dev/null
+++ b/scripts/sync_man_pages.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+"""Regenerate the bundled sr.ht man page catalog from man.sr.ht.
+
+Fetches the man.sr.ht landing page, extracts the per-service "User Manual"
+links, and writes them to ``Hutch/Resources/man-pages.json``. The scheduled
+GitHub workflow that runs this opens a pull request whenever the result differs
+from the committed copy, so the in-app list stays in sync with upstream without
+hand edits.
+
+Run locally with ``python3 scripts/sync_man_pages.py``; exits non-zero (without
+writing) if upstream markup changed enough that too few pages were found, so a
+bad scrape can never wipe the bundled list.
+"""
+import json
+import re
+import sys
+import urllib.request
+from pathlib import Path
+
+INDEX_URL = "https://man.sr.ht/"
+OUTPUT = Path(__file__).resolve().parent.parent / "Hutch" / "Resources" / "man-pages.json"
+# The suite has ~12 service manuals; a scrape returning far fewer means the page
+# structure changed and we should fail loudly rather than commit a gutted list.
+MINIMUM_EXPECTED = 8
+
+
+def fetch(url: str) -> str:
+ request = urllib.request.Request(url, headers={"User-Agent": "hutch-man-page-sync"})
+ with urllib.request.urlopen(request, timeout=30) as response:
+ return response.read().decode("utf-8")
+
+
+def build_catalog(html: str) -> list[dict[str, str]]:
+ """Extract official man-page links, deduplicated and sorted by title."""
+ entries: dict[str, str] = {}
+ for href in re.findall(r'href="([^"]+)"', html):
+ service = re.fullmatch(r"/([a-z0-9][a-z0-9.-]*\.sr\.ht)/?", href)
+ if service:
+ title = service.group(1)
+ entries[title] = f"https://man.sr.ht/{title}/"
+ elif re.fullmatch(r"sr\.ht/?", href):
+ entries["sr.ht"] = "https://man.sr.ht/sr.ht/"
+ elif re.fullmatch(r"https://srht\.site/?", href):
+ entries["srht.site"] = "https://srht.site/"
+ return [{"title": title, "url": entries[title]} for title in sorted(entries)]
+
+
+def main() -> int:
+ catalog = build_catalog(fetch(INDEX_URL))
+ if len(catalog) < MINIMUM_EXPECTED:
+ print(
+ f"Refusing to write catalog with only {len(catalog)} entries; "
+ "man.sr.ht markup may have changed.",
+ file=sys.stderr,
+ )
+ return 1
+ OUTPUT.write_text(json.dumps(catalog, indent=2, ensure_ascii=False) + "\n")
+ print(f"Wrote {len(catalog)} man page(s) to {OUTPUT}")
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())