Coverage for an_website/lolwut/lolwut.py: 78.049%

41 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"""The page that generates art.""" 

15 

16from __future__ import annotations 

17 

18from collections.abc import Awaitable 

19from typing import ClassVar, Final 

20 

21import regex 

22from redis.asyncio import Redis 

23from tornado.web import HTTPError 

24 

25from .. import EVENT_REDIS 

26from ..utils.base_request_handler import BaseRequestHandler 

27from ..utils.request_handler import APIRequestHandler, HTMLRequestHandler 

28from ..utils.utils import ModuleInfo 

29 

30 

31def get_module_info() -> ModuleInfo: 

32 """Create and return the ModuleInfo for this module.""" 

33 args = r"(?:\d+/)*\d+" 

34 return ModuleInfo( 

35 handlers=( 

36 (r"/LOLWUT", LOLWUT), 

37 (rf"/LOLWUT/({args})", LOLWUT), 

38 (r"/api/LOLWUT", LOLWUTAPI), 

39 (rf"/api/LOLWUT/({args})", LOLWUTAPI), 

40 (rf"(?i)(?:/api)?/lolwut(?:/{args})?", LOLWUTRedirectHandler), 

41 ), 

42 name="LOLWUT", 

43 description="LOLWUT; präsentiert von Redis", 

44 path="/LOLWUT", 

45 keywords=( 

46 "LOLWUT", 

47 "Redis", 

48 ), 

49 ) 

50 

51 

52def generate_art(redis: Redis[str], args: str | None) -> Awaitable[bytes]: 

53 """Generate art.""" 

54 return redis.lolwut(*(args.split("/") if args else ())) 

55 

56 

57class LOLWUT(HTMLRequestHandler): 

58 """The request handler for the LOLWUT page.""" 

59 

60 async def get(self, args: None | str = None, *, head: bool = False) -> None: 

61 """Handle GET requests to the LOLWUT page.""" 

62 if not EVENT_REDIS.is_set(): 

63 raise HTTPError(503) 

64 

65 art = await generate_art(self.redis, args) 

66 

67 if head: 

68 return 

69 

70 await self.render( 

71 "ansi2html.html", 

72 ansi=art, 

73 powered_by="https://redis.io", 

74 powered_by_name="Redis", 

75 ) 

76 

77 

78class LOLWUTAPI(APIRequestHandler): 

79 """The request handler for the LOLWUT API.""" 

80 

81 POSSIBLE_CONTENT_TYPES: ClassVar[tuple[str, ...]] = ( 

82 "text/plain", 

83 *APIRequestHandler.POSSIBLE_CONTENT_TYPES, 

84 ) 

85 

86 async def get(self, args: None | str = None) -> None: 

87 """Handle GET requests to the LOLWUT API.""" 

88 if not EVENT_REDIS.is_set(): 

89 raise HTTPError(503) 

90 

91 art = await generate_art(self.redis, args) 

92 

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

94 return await self.finish(art) 

95 

96 await self.finish({"LOLWUT": art}) 

97 

98 

99class LOLWUTRedirectHandler(BaseRequestHandler): 

100 """Redirect to the LOLWUT page.""" 

101 

102 REPL_PATTERN: Final = regex.compile(r"/lolwut(/|\?|$)", regex.IGNORECASE) 

103 

104 def get(self) -> None: 

105 """Handle requests to the lolwut (sic!) page.""" 

106 self.redirect( 

107 LOLWUTRedirectHandler.REPL_PATTERN.sub( 

108 LOLWUTRedirectHandler.repl_match, self.request.full_url(), 1 

109 ) 

110 ) 

111 

112 head = get 

113 post = get 

114 

115 @staticmethod 

116 def repl_match(match: regex.Match[str]) -> str: 

117 """Return the correct replacement for the given match.""" 

118 return f"/LOLWUT{match.group(1)}"