libreinternet.club/services/webmention.py

63 lines
1.9 KiB
Python

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 in ("GET", "HEAD"):
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")