108 lines
3.2 KiB
Python
108 lines
3.2 KiB
Python
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
|
|
from unidecode import unidecode
|
|
|
|
wordpress_url = getenv("URL")
|
|
|
|
handlers = {}
|
|
formatters = {}
|
|
|
|
def wrap(text):
|
|
return "\n".join(text_wrap(text, width=int(getenv("WIDTH", 80))))
|
|
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):
|
|
# TODO: Use image to ascii here
|
|
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"]["rendered"]} **
|
|
"""
|
|
# TODO: Hit the API to get the author's name
|
|
# {post["date"]} - {post["author"]}
|
|
# TODO: Nicer date formatting
|
|
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"], features="html.parser").get_text()
|
|
cutoff = text.find("…")
|
|
fudge_factor = 100 # Deal with the weird [html] link generated by the penny toys article
|
|
return wrap(unidecode(text[:cutoff - fudge_factor] + "..."))
|
|
|
|
def handle(request):
|
|
print(f"path: {request.path}")
|
|
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 post in items:
|
|
menu.append(Item(
|
|
itype=0, path=f"{url}{post['slug']}",
|
|
text=unidecode(unescape(post['title']['rendered'])),
|
|
host=request.host, port=request.port)
|
|
)
|
|
menu.append(format_excerpt(post))
|
|
return menu
|
|
|
|
if __name__ == '__main__':
|
|
pituophis.serve(getenv("HOST","127.0.0.1"), int(getenv("PORT")), handler=handle)
|