ci: import medium posts via rss periodically hugo/medium-sync
authorxangelo <me@xangelo.ca>
Mon, 21 Jul 2025 13:08:17 +0000 (09:08 -0400)
committerxangelo <me@xangelo.ca>
Mon, 21 Jul 2025 13:08:17 +0000 (09:08 -0400)
.github/scripts/medium_to_hugo.py [new file with mode: 0644]
.github/workflows/medium-sync.yml [new file with mode: 0644]

diff --git a/.github/scripts/medium_to_hugo.py b/.github/scripts/medium_to_hugo.py
new file mode 100644 (file)
index 0000000..222e003
--- /dev/null
@@ -0,0 +1,37 @@
+import feedparser
+import os
+import re
+import frontmatter
+from markdownify import markdownify as md
+import html
+from datetime import datetime
+
+RSS_URL = "https://medium.com/feed/@xangelo"
+OUTPUT_DIR = "content/posts"
+EXISTING_SLUGS = {f[:-3] for f in os.listdir(OUTPUT_DIR) if f.endswith(".md")}
+
+def slugify(title):
+    return re.sub(r"[^\w-]", "", re.sub(r"\s+", "-", title.lower())).strip("-")
+
+feed = feedparser.parse(RSS_URL)
+
+for entry in feed.entries:
+    slug = slugify(entry.title)
+    if slug in EXISTING_SLUGS:
+        continue
+
+    content_html = entry.get("content", [{}])[0].get("value", "") or entry.get("summary", "")
+    markdown_content = md(html.unescape(content_html))
+
+    post = frontmatter.Post(markdown_content)
+    post["title"] = entry.title
+    post["date"] = entry.published
+    post["slug"] = slug
+    post["draft"] = False
+    post["medium_link"] = entry.link
+
+    output_path = os.path.join(OUTPUT_DIR, f"{slug}.md")
+    with open(output_path, "w", encoding="utf-8") as f:
+        f.write(frontmatter.dumps(post))
+
+    print(f"Saved: {output_path}")
\ No newline at end of file
diff --git a/.github/workflows/medium-sync.yml b/.github/workflows/medium-sync.yml
new file mode 100644 (file)
index 0000000..7a7d966
--- /dev/null
@@ -0,0 +1,32 @@
+name: Sync Medium to Hugo
+
+on:
+  workflow_dispatch: {}
+  schedule:
+    - cron: "*/30 * * * *" # Runs every 30m
+
+jobs:
+  sync:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repo
+        uses: actions/checkout@v4
+
+      - name: Set up Python
+        uses: actions/setup-python@v5
+        with:
+          python-version: "3.x"
+
+      - name: Install dependencies
+        run: pip install feedparser markdownify python-frontmatter requests
+
+      - name: Run sync script
+        run: python .github/scripts/medium_to_hugo.py
+
+      - name: Commit and push changes
+        run: |
+          git config user.name "Medium Sync Bot"
+          git config user.email "actions@github.com"
+          git add content/posts/
+          git diff --quiet && git diff --staged --quiet || git commit -m "Sync new Medium posts"
+          git push