gopher-wp-bridge/server.py
2023-06-25 10:33:22 -04:00

111 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from os import getenv
from urllib.parse import urljoin
from html import unescape
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 = {}
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
def img(tag):
if "alt" in tag:
return f"<Image Omitted: {tag['alt']}>"
return "<Image Omitted (no alt text)>"
def format_post(post):
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)
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}===>")
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)