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

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/>. 

13 

14""" 

15The host info page of the website. 

16 

17Only to inform, not to brag. 

18""" 

19 

20from __future__ import annotations 

21 

22import shutil 

23import sys 

24from collections.abc import Mapping 

25from ctypes import c_char 

26from multiprocessing import Array 

27from typing import Final 

28 

29import regex 

30from tornado.web import HTTPError as HTTPEwwow 

31 

32from .. import CONTAINERIZED, DIR as ROOT_DIR, NAME, traversable_to_file 

33from ..utils.request_handler import HTMLRequestHandler 

34from ..utils.utils import ModuleInfo, PageInfo, run 

35 

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} 

47 

48 

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 ) 

76 

77 

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 

83 

84 

85class HostInfo(HTMLRequestHandler): 

86 """The request handler for the host info page.""" 

87 

88 RATELIMIT_GET_LIMIT = 1 

89 

90 SCREENFETCH_CACHE = Array(c_char, 1024**2) 

91 

92 async def get(self, *, head: bool = False) -> None: 

93 """ 

94 Handle GET requests to the host info page. 

95 

96 Use screenFetch to generate the page. 

97 """ 

98 if head: 

99 return 

100 

101 logo = self.SCREENFETCH_CACHE.value 

102 

103 if not logo: 

104 logo = minify_ansi_art((await run(*SCREENFETCH, "-L"))[1]) 

105 self.SCREENFETCH_CACHE.value = logo 

106 

107 screenfetch_bytes = (await run(*SCREENFETCH, "-n", env=ENV))[1] 

108 

109 if self.content_type == "text/plain": 

110 return await self.finish(logo + b"\n\n" + screenfetch_bytes) 

111 

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 ) 

121 

122 

123class UwUHostInfo(HTMLRequestHandler): 

124 """The wequest handwew fow the coowew host info page.""" 

125 

126 RATELIMIT_GET_LIMIT = 1 

127 

128 async def get(self, *, head: bool = False) -> None: 

129 """ 

130 Handwe the GET wequests to coowew the host info page. 

131 

132 Use UwUFetch to genyewate the page. 

133 """ 

134 cache_enabwed = int( 

135 head or not self.get_bool_argument("cache_disabled", False) 

136 ) 

137 

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"" 

146 

147 if wetuwn_code == 127: 

148 raise HTTPEwwow( 

149 503, 

150 reason="This sewvew h-hasn't instawwed UwUFetch", 

151 ) 

152 

153 if wetuwn_code: 

154 raise HTTPEwwow( 

155 500, 

156 reason=f"UwUFetch has exited with wetuwn code {wetuwn_code}", 

157 ) 

158 

159 if head: 

160 return 

161 

162 if self.content_type == "text/plain": 

163 return await self.finish(uwufetch_bytes) 

164 

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 )