gopher-wp-bridge/server.py

112 lines
3.3 KiB
Python
Raw Normal View History

from os import getenv
from urllib.parse import urljoin
from html import unescape
2023-06-25 10:33:22 -04:00
from textwrap import wrap as text_wrap
import pituophis
from pituophis import Item, Request
from requests import get
from parse import parse
from bs4 import BeautifulSoup
wordpress_url = getenv("URL")
handlers = {}
formatters = {}
2023-06-25 10:33:22 -04:00
def wrap(text):
return "\n".join(text_wrap(text, width=int(getenv("WIDTH", 80))))
def excise_special_characters(text):
# TODO: Actually use .encode("ascii", "excise_special_characters") and register a custom handler
for char, replacement in {
"": '"',
"": "'",
"": '"',
"w": "w",
}.items():
text = text.replace(char, replacement)
return text
def register_handler(path: str):
def decorator_handler(func):
handlers[path] = func
return func
return decorator_handler
def register_formatter(func):
formatters[func.__name__] = func
return func
@register_formatter
def h1(tag):
return f"\n === {tag.get_text()} === \n"
@register_formatter
def h2(tag):
return f"\n == {tag.get_text()} == \n"
@register_formatter
def h3(tag):
return f"\n = {tag.get_text()} = \n"
@register_formatter
def p(tag):
return tag.get_text()
@register_formatter
2023-06-25 10:33:22 -04:00
def img(tag):
if "alt" in tag:
return f"<Image Omitted: {tag['alt']}>"
return "<Image Omitted (no alt text)>"
def format_post(post):
2023-06-25 10:33:22 -04:00
post = post[0]
header = f"""
** {post["title"]} **
{post["date"]} - {post["author"]}
"""
soup = BeautifulSoup(post["content"]["rendered"], features="html.parser")
tags = soup.find_all(formatters.keys())
return header + "\n".join(
wrap(formatters[tag.name](tag))
for tag in tags
)
@register_handler("/post/{slug}")
def post(request: Request, slug: str):
post = get(urljoin(wordpress_url, f"wp-json/wp/v2/posts?slug={slug}")).json()
return format_post(post)
@register_handler("/page/{slug}")
def post(request: Request, slug: str):
page = get(urljoin(wordpress_url, f"wp-json/wp/v2/pages?slug={slug}")).json()
return format_post(page)
2023-06-25 10:33:22 -04:00
def format_excerpt(post):
text = BeautifulSoup(post["excerpt"]["rendered"]).get_text()
cutoff = text.find("")
fudge_factor = 100 # Deal with the weird [html] link generated by the penny toys article
return wrap(excise_special_characters(text[:cutoff - fudge_factor] + "..."))
def handle(request):
for path, handler in handlers.items():
parse_result = parse(path, request.path)
if parse_result is not None:
return handler(request, **parse_result.named)
menu = [getenv("HEADER_TEXT")]
posts = get(urljoin(wordpress_url, "wp-json/wp/v2/posts?filter[posts_per_page]=-1")).json()
pages = get(urljoin(wordpress_url, "wp-json/wp/v2/pages?filter[posts_per_page]=-1")).json()
for heading, items, url in (
("Pages", pages, "/page/"),
("Posts", posts, "/post/")
):
menu.append(f"<==={heading}===>")
2023-06-25 10:33:22 -04:00
for i, post in enumerate(items):
menu.append(Item(itype=0, path=f"{url}{post['slug']}", text=unescape(post['title']['rendered']), host=request.host, port=request.port))
menu.append(format_excerpt(post))
return menu
if __name__ == '__main__':
pituophis.serve("127.0.0.1", int(getenv("PORT")), handler=handle)