-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.py
108 lines (92 loc) · 3.24 KB
/
server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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)