Coverage for an_website/host_info/host_info.py: 82.000%
50 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-16 19:56 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-16 19:56 +0000
1# This program is free software: you can redistribute it and/or modify
2# it under the terms of the GNU Affero General Public License as
3# published by the Free Software Foundation, either version 3 of the
4# License, or (at your option) any later version.
5#
6# This program is distributed in the hope that it will be useful,
7# but WITHOUT ANY WARRANTY; without even the implied warranty of
8# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9# GNU Affero General Public License for more details.
10#
11# You should have received a copy of the GNU Affero General Public License
12# along with this program. If not, see <https://www.gnu.org/licenses/>.
14"""
15The host info page of the website.
17Only to inform, not to brag.
18"""
20from __future__ import annotations
22import shutil
23import sys
24from collections.abc import Mapping
25from ctypes import c_char
26from multiprocessing import Array
27from typing import Final
29import regex
30from tornado.web import HTTPError as HTTPEwwow
32from .. import CONTAINERIZED, DIR as ROOT_DIR, NAME, traversable_to_file
33from ..utils.request_handler import HTMLRequestHandler
34from ..utils.utils import ModuleInfo, PageInfo, run
36SCREENFETCH: Final = (
37 shutil.which("bash") or "bash",
38 traversable_to_file(ROOT_DIR / "vendored" / "screenfetch").as_posix(),
39)
40UWUFETCH_PATH: Final = shutil.which("uwufetch")
41ENV: Final[Mapping[str, str]] = {
42 "USER": NAME,
43 "SHELL": (
44 f"{sys.implementation.name}{'.'.join(str(_) for _ in sys.version_info[:3])}"
45 ),
46}
49def get_module_info() -> ModuleInfo:
50 """Create and return the ModuleInfo for this module."""
51 return ModuleInfo(
52 handlers=(
53 (r"/host-info", HostInfo),
54 (r"/host-info/uwu", UwUHostInfo),
55 ),
56 name="Host-Informationen",
57 short_name="Host-Info",
58 description="Informationen über den Host-Server dieser Webseite",
59 path="/host-info",
60 aliases=("/server-info",),
61 sub_pages=(
62 PageInfo(
63 name="Howost-Infowmationyen",
64 short_name="Howost-Infow",
65 description=(
66 "Infowmationyen übew den Howost-Sewvew diesew W-Webseite"
67 ),
68 path="/host-info/uwu",
69 keywords=("UWU",),
70 hidden=CONTAINERIZED or not UWUFETCH_PATH,
71 ),
72 ),
73 keywords=("Host", "Informationen", "Screenfetch"),
74 hidden=CONTAINERIZED,
75 )
78def minify_ansi_art(string: bytes) -> bytes:
79 """Minify an ANSI art string."""
80 return regex.sub(
81 rb"(?m)\s+\x1B\[0m$", b"\x1B[0m", string
82 ) # for arch: 1059 → 898
85class HostInfo(HTMLRequestHandler):
86 """The request handler for the host info page."""
88 RATELIMIT_GET_LIMIT = 1
90 SCREENFETCH_CACHE = Array(c_char, 1024**2)
92 async def get(self, *, head: bool = False) -> None:
93 """
94 Handle GET requests to the host info page.
96 Use screenFetch to generate the page.
97 """
98 if head:
99 return
101 logo = self.SCREENFETCH_CACHE.value
103 if not logo:
104 logo = minify_ansi_art((await run(*SCREENFETCH, "-L"))[1])
105 self.SCREENFETCH_CACHE.value = logo
107 screenfetch_bytes = (await run(*SCREENFETCH, "-n", env=ENV))[1]
109 if self.content_type == "text/plain":
110 return await self.finish(logo + b"\n\n" + screenfetch_bytes)
112 await self.render(
113 "ansi2html.html",
114 ansi=[
115 logo.decode("UTF-8"),
116 screenfetch_bytes.decode("UTF-8"),
117 ],
118 powered_by="https://github.com/KittyKatt/screenFetch",
119 powered_by_name="screenFetch",
120 )
123class UwUHostInfo(HTMLRequestHandler):
124 """The wequest handwew fow the coowew host info page."""
126 RATELIMIT_GET_LIMIT = 1
128 async def get(self, *, head: bool = False) -> None:
129 """
130 Handwe the GET wequests to coowew the host info page.
132 Use UwUFetch to genyewate the page.
133 """
134 cache_enabwed = int(
135 head or not self.get_bool_argument("cache_disabled", False)
136 )
138 if UWUFETCH_PATH:
139 wetuwn_code, uwufetch_bytes, _ = await run(
140 UWUFETCH_PATH,
141 "-w",
142 env={"UWUFETCH_CACHE_ENABLED": str(cache_enabwed), **ENV},
143 )
144 else:
145 wetuwn_code, uwufetch_bytes = 127, b""
147 if wetuwn_code == 127:
148 raise HTTPEwwow(
149 503,
150 reason="This sewvew h-hasn't instawwed UwUFetch",
151 )
153 if wetuwn_code:
154 raise HTTPEwwow(
155 500,
156 reason=f"UwUFetch has exited with wetuwn code {wetuwn_code}",
157 )
159 if head:
160 return
162 if self.content_type == "text/plain":
163 return await self.finish(uwufetch_bytes)
165 uwufetch = uwufetch_bytes.decode("UTF-8")
166 await self.render(
167 "ansi2html.html",
168 ansi=uwufetch.split("\n\n"),
169 powered_by="https://github.com/TheDarkBug/uwufetch",
170 powered_by_name="UwUFetch",
171 )