From 6616a748c0345b298a1f131f128e649d002cb757 Mon Sep 17 00:00:00 2001 From: Spencer Killen Date: Tue, 14 Jul 2026 00:15:08 -0600 Subject: [PATCH] Add rudimentary webmention service --- .gitignore | 2 ++ requirements.txt | 1 + services/mentions.pickle | Bin 0 -> 114 bytes services/webmention.py | 63 +++++++++++++++++++++++++++++++++ services/webmention_nginx.conf | 14 ++++++++ www/index.html | 8 +++-- 6 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 requirements.txt create mode 100644 services/mentions.pickle create mode 100644 services/webmention.py create mode 100644 services/webmention_nginx.conf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..58e9f3f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__ +env/ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7469669 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +fastcgi==0.0.3 diff --git a/services/mentions.pickle b/services/mentions.pickle new file mode 100644 index 0000000000000000000000000000000000000000..7f0a25a2fdf35440e5e643f7b04e2aca3994b58a GIT binary patch literal 114 zcmXBJF%H5o3qS+*v9)? zVDTQ-A4!yF!3)C^3-;F4xs^n)?OFAH7{_|Ka?T_!1z4w{Or)^gZ|k=+$3iShMMz!B IEuzKXJ_au;OaK4? literal 0 HcmV?d00001 diff --git a/services/webmention.py b/services/webmention.py new file mode 100644 index 0000000..55139bb --- /dev/null +++ b/services/webmention.py @@ -0,0 +1,63 @@ +import sys +import os +from fastcgi import fastcgi +from urllib.parse import parse_qs +from pathlib import Path +import pickle +from dataclasses import dataclass + +CACHE_PATH = Path(__file__).parent / "mentions.pickle" + +print("FastCGI server starting... unix socket to be located at") +print(Path.cwd()/"fcgi.sock") + +@dataclass +class Mention: + source: str + target: str + + @staticmethod + def load_past_mentions() -> list["Mention"]: + if CACHE_PATH.exists(): + with open(CACHE_PATH, "rb") as fo: + return pickle.load(fo) + return [] + + @staticmethod + def save_past_mentions(mentions: list["Mention"]): + with open(CACHE_PATH, "wb") as fo: + return pickle.dump(mentions, fo) + + @classmethod + def add_mention(cls, mention: "Mention"): + cache = cls.load_past_mentions() + if mention not in cache: + cache.append(mention) + cls.save_past_mentions(cache) + +@fastcgi() +def handler(): + try: + url = os.environ["REQUEST_URL"] + method = os.environ["REQUEST_METHOD"] + if method == "POST": + payload = sys.stdin.read() + data = parse_qs(payload) + source = data["source"][-1] + target = data["target"][-1] + Mention.add_mention(Mention(source, target)) + if source == target: + raise Exception() + print("Status: 202 Accepted\r") + print("Content-Type: text/plain; charset=utf-8\r\n\r") + print("Thanks for mentioning us!") + print(source) + elif method == "GET": + print("Status: 200 OK\r") + print("Content-Type: text/plain; charset=utf-8\r\n\r") + for mention in Mention.load_past_mentions(): + print(f"<{mention.source}> mentioned <{mention.target}>") + else: + raise Exception() + except Exception as e: + print("Status: 400 Bad Request\r\n\r") diff --git a/services/webmention_nginx.conf b/services/webmention_nginx.conf new file mode 100644 index 0000000..deb80ce --- /dev/null +++ b/services/webmention_nginx.conf @@ -0,0 +1,14 @@ +# A basic nginx configuration to test webmention.py +# Update unix: path to be the correct file + +server { + listen 80 default_server; + listen [::]:80 default_server; + + location / { + add_header Link "; rel=\"webmention\"" always; + fastcgi_pass unix:/home/gopher/libreinternet.club/services/fcgi.sock; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param REQUEST_URL $request_uri; + } +} diff --git a/www/index.html b/www/index.html index a9df694..d5dcc53 100644 --- a/www/index.html +++ b/www/index.html @@ -1,19 +1,21 @@ - + Libre Internet Club - + - + + @ University of Alberta +
Webmention us at https://webmention.libreinternet.club