summaryrefslogtreecommitdiff
path: root/src/technical_renaissance/app.py
blob: 5519027a24a5eceef68e110d1d122e8d3d7ef886 (plain) (blame)
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
import os
import pathlib
import random
import tomllib
from pathlib import Path
from typing import TypedDict
from xml.etree import ElementTree

from robyn import Request, Response, Robyn
from robyn.templating import JinjaTemplate


User = TypedDict("User", {"name": str, "url": str, "description": str, "feed": str})


def load_users(path: Path) -> list[User]:
    with path.open("rb") as f:
        return tomllib.load(f)["user"]


current_file_path = pathlib.Path(__file__).parent.resolve()
users = load_users(current_file_path / "config.toml")

app = Robyn(__file__)

app.serve_directory(
    route="/static",
    directory_path=os.path.join(current_file_path, "static"),
)
JINJA_TEMPLATE = JinjaTemplate(os.path.join(current_file_path, "templates"))


def index_of(request: Request) -> int:
    name = request.query_params.get("from", "")
    for i, user in enumerate(users):
        if user["name"] == name:
            return i
    return 0


def redirect(url: str) -> Response:
    return Response(status_code=302, headers={"Location": url}, description="")


@app.get("/")
async def index(_request: Request):
    return JINJA_TEMPLATE.render_template("index.html", users=users)


@app.get("/next")
async def next_user(request: Request):
    current = index_of(request)
    next_index = (current + 1) % len(users)
    return redirect(users[next_index]["url"])


@app.get("/prev")
async def prev_user(request: Request):
    current = index_of(request)
    prev_index = (current - 1) % len(users)
    return redirect(users[prev_index]["url"])


@app.get("/random")
async def random_user(_request: Request):
    return redirect(random.choice(users)["url"])


def build_opml() -> str:
    opml = ElementTree.Element("opml", version="2.0")
    head = ElementTree.SubElement(opml, "head")
    ElementTree.SubElement(head, "title").text = "Technical Renaissance Webring"
    body = ElementTree.SubElement(opml, "body")
    for user in users:
        if user["feed"]:
            ElementTree.SubElement(
                body,
                "outline",
                text=user["name"],
                type="rss",
                xmlUrl=user["feed"],
                htmlUrl=user["url"],
            )
    return ElementTree.tostring(opml, encoding="unicode", xml_declaration=True)

app.start(host="127.0.0.1", port=8080)