summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosias <me@josias.dev>2021-10-22 22:11:19 -0700
committerJosias <me@josias.dev>2021-10-22 22:11:19 -0700
commit5525a9c8d9a98e6dfb2b8f8ebcd455cd87b1ca2b (patch)
tree4fd46905750ef7f0c0a9c7c52a1f8e7025f8ea98
Add initial program that works, with README and example
-rw-r--r--README.md20
-rwxr-xr-xgmi2rss104
l---------index.gmi1
-rw-r--r--requirements.txt1
-rw-r--r--test.gmi15
5 files changed, 141 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ce7077f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,20 @@
+# gmi2rss
+
+A simple tool to convert [Gemini feeds](gemini://gemini.circumlunar.space/docs/companion/subscription.gmi) to Atom.
+
+Not because it didn't exist before, but just because I couldn't find it.
+
+## Installation
+
+```
+$ git clone https://git.josias.dev/gmi2rss && cd gmi2rss
+$ pip install -r requirements.txt
+```
+
+## Usage
+
+To use, provide the script with the Gemini document to parse, as well as the URL for the feed (needs to be fixed for anything other than a directory).
+
+```
+$ ./gmi2rss test.gmi gemini://example.com
+```
diff --git a/gmi2rss b/gmi2rss
new file mode 100755
index 0000000..93eb028
--- /dev/null
+++ b/gmi2rss
@@ -0,0 +1,104 @@
+#!/bin/env python3
+from datetime import datetime
+import dateutil
+import os
+import re
+import string
+import sys
+
+from feedgen.feed import FeedGenerator
+
+def find_links(document):
+ """
+ Returns an array of all link lines in a gemtext document
+ """
+ return [line for line in document.split('\n') if line.startswith('=> ')]
+
+def parse_feed_link(line):
+ """
+ Parses a feed link line into its link, date, and title
+ """
+ if not is_feed_link(line):
+ raise ValueError("Line not a valid feed link")
+
+ parts = re.split('\s+', line)
+ return {
+ 'link': parts[1],
+ 'date': parts[2],
+ 'title': ' '.join(parts[4:]),
+ }
+
+def is_feed_link(line):
+ """
+ Determines whether or not the link line is a valid gemini feed link
+ """
+ if not line.startswith("=>"):
+ return False
+
+ parts = re.split('\s+', line)
+
+ # ['=>', 'gemini://example.com', '1970-01-01', '-', 'Epoch']
+ if len(parts) < 5:
+ return False
+
+ date = parts[2]
+
+ if len(date) != 10:
+ return False
+
+ for ch in date:
+ if not ch.isdigit() and not ch == '-':
+ return False
+
+ return True
+
+def main():
+ if len(sys.argv) < 2:
+ print("Usage: gmi2rss FILE URL")
+ return
+
+ with open(sys.argv[1]) as file:
+ doc = file.read()
+
+ root = sys.argv[2]
+
+ title = ""
+ subtitle = ""
+ # Currenly assumes whitespace after # or ##
+ for line in doc.split('\n'):
+ if line.startswith('# '):
+ title = ' '.join(re.split('\s+', line)[1:])
+ elif title != "" and line.startswith("## "):
+ subtitle = ' '.join(re.split('\s+', line)[1:])
+ break
+ elif title != "" and line != "":
+ break
+
+ feed_links = [parse_feed_link(link) for link in find_links(doc) if is_feed_link(link)]
+
+ fg = FeedGenerator()
+ fg.title(title)
+ fg.subtitle(subtitle)
+ fg.id(root)
+ fg.link(href=root, rel="self")
+
+ latest_date = "1970-01-01T00:00:00Z" # the beginning of the universe, as far as we're concerned
+ for link in feed_links:
+ fe = fg.add_entry()
+ fe.title(link['title'])
+ url = os.path.join(root, link['link'])
+ fe.id(url)
+ fe.link(href=url, rel="alternate")
+
+ date = link['date'] + 'T12:00:00Z'
+ if date > latest_date:
+ latest_date = date
+ fe.updated(date)
+
+ if latest_date != "1970-01-01T00:00:00Z":
+ fg.updated(latest_date)
+
+ print(fg.atom_str(pretty=True).decode('UTF-8'), end='')
+
+if __name__ == "__main__":
+ main()
diff --git a/index.gmi b/index.gmi
new file mode 120000
index 0000000..42061c0
--- /dev/null
+++ b/index.gmi
@@ -0,0 +1 @@
+README.md \ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..42f0315
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+feedgen == 0.9.0
diff --git a/test.gmi b/test.gmi
new file mode 100644
index 0000000..4ff2a06
--- /dev/null
+++ b/test.gmi
@@ -0,0 +1,15 @@
+# Test
+
+## Subtitle
+
+This is a test Gemini feed.
+
+=> gemini://example.com 2020-01-01 - Hello, world!
+=> gemini://example.net 2021-01-02 - Hello, solar system!
+=> gemini://example.org 2021-01-03 - Hello, galaxy!
+
+Some more text here.
+
+=> gemini://example.com/index.html A non-feed link
+
+Even more text.