nonebot-plugin-l4d2-server 0.6.6__py3-none-any.whl → 1.0.0a2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. nonebot_plugin_l4d2_server/__init__.py +10 -93
  2. nonebot_plugin_l4d2_server/__main__.py +140 -0
  3. nonebot_plugin_l4d2_server/config.py +35 -0
  4. nonebot_plugin_l4d2_server/data/font/loli.ttf +0 -0
  5. nonebot_plugin_l4d2_server/l4_anne/__init__.py +124 -0
  6. nonebot_plugin_l4d2_server/l4_anne/ranne.py +18 -0
  7. nonebot_plugin_l4d2_server/l4_help/Help.json +102 -0
  8. nonebot_plugin_l4d2_server/l4_help/__init__.py +57 -0
  9. nonebot_plugin_l4d2_server/l4_help/draw.py +206 -0
  10. nonebot_plugin_l4d2_server/l4_help/icon//344/273/213/347/273/215.png +0 -0
  11. nonebot_plugin_l4d2_server/l4_help/icon//344/273/273/345/212/241.png +0 -0
  12. nonebot_plugin_l4d2_server/l4_help/icon//344/277/241/346/201/257.png +0 -0
  13. nonebot_plugin_l4d2_server/l4_help/icon//345/205/254/345/221/212.png +0 -0
  14. nonebot_plugin_l4d2_server/l4_help/icon//345/210/200/345/211/221.png +0 -0
  15. nonebot_plugin_l4d2_server/l4_help/icon//345/210/207/346/215/242.png +0 -0
  16. nonebot_plugin_l4d2_server/l4_help/icon//345/210/240/351/231/244.png +0 -0
  17. nonebot_plugin_l4d2_server/l4_help/icon//345/210/267/346/226/260.png +0 -0
  18. nonebot_plugin_l4d2_server/l4_help/icon//345/215/241/347/273/204.png +0 -0
  19. nonebot_plugin_l4d2_server/l4_help/icon//345/223/252/351/207/214.png +0 -0
  20. nonebot_plugin_l4d2_server/l4_help/icon//345/234/260/345/233/276.png +0 -0
  21. nonebot_plugin_l4d2_server/l4_help/icon//345/257/274/345/205/245.png +0 -0
  22. nonebot_plugin_l4d2_server/l4_help/icon//345/257/274/345/207/272.png +0 -0
  23. nonebot_plugin_l4d2_server/l4_help/icon//345/275/261.png +0 -0
  24. nonebot_plugin_l4d2_server/l4_help/icon//346/213/274/345/233/276.png +0 -0
  25. nonebot_plugin_l4d2_server/l4_help/icon//346/216/242/347/264/242.png +0 -0
  26. nonebot_plugin_l4d2_server/l4_help/icon//346/216/250/351/200/201.png +0 -0
  27. nonebot_plugin_l4d2_server/l4_help/icon//346/224/266/351/233/206.png +0 -0
  28. nonebot_plugin_l4d2_server/l4_help/icon//346/224/273/347/225/245.png +0 -0
  29. nonebot_plugin_l4d2_server/l4_help/icon//346/233/264/346/226/260.png +0 -0
  30. nonebot_plugin_l4d2_server/l4_help/icon//346/235/220/346/226/231.png +0 -0
  31. nonebot_plugin_l4d2_server/l4_help/icon//346/237/245/350/257/242.png +0 -0
  32. nonebot_plugin_l4d2_server/l4_help/icon//346/240/241/351/252/214.png +0 -0
  33. nonebot_plugin_l4d2_server/l4_help/icon//346/257/217/346/234/210.png +0 -0
  34. nonebot_plugin_l4d2_server/l4_help/icon//346/267/261/346/270/212.png +0 -0
  35. nonebot_plugin_l4d2_server/l4_help/icon//346/267/273/345/212/240.png +0 -0
  36. nonebot_plugin_l4d2_server/l4_help/icon//346/270/205/351/231/244.png +0 -0
  37. nonebot_plugin_l4d2_server/l4_help/icon//347/212/266/346/200/201.png +0 -0
  38. nonebot_plugin_l4d2_server/l4_help/icon//347/255/276/345/210/260.png +0 -0
  39. nonebot_plugin_l4d2_server/l4_help/icon//347/273/221/345/256/232.png +0 -0
  40. nonebot_plugin_l4d2_server/l4_help/icon//350/241/250.png +0 -0
  41. nonebot_plugin_l4d2_server/l4_help/icon//350/241/250/346/203/205.png +0 -0
  42. nonebot_plugin_l4d2_server/l4_help/icon//350/247/222/350/211/262.png +0 -0
  43. nonebot_plugin_l4d2_server/l4_help/icon//350/256/260/345/275/225.png +0 -0
  44. nonebot_plugin_l4d2_server/l4_help/icon//351/205/215/347/275/256.png +0 -0
  45. nonebot_plugin_l4d2_server/l4_help/icon//351/207/215/345/220/257.png +0 -0
  46. nonebot_plugin_l4d2_server/l4_help/texture2d/badge.png +0 -0
  47. nonebot_plugin_l4d2_server/l4_help/texture2d/banner.png +0 -0
  48. nonebot_plugin_l4d2_server/l4_help/texture2d/bg.jpg +0 -0
  49. nonebot_plugin_l4d2_server/l4_help/texture2d/button.png +0 -0
  50. nonebot_plugin_l4d2_server/l4_help/texture2d/icon.png +0 -0
  51. nonebot_plugin_l4d2_server/l4_image/__init__.py +16 -0
  52. nonebot_plugin_l4d2_server/l4_image/anne_pil.py +17 -0
  53. nonebot_plugin_l4d2_server/l4_image/convert.py +175 -0
  54. nonebot_plugin_l4d2_server/{l4d2_image → l4_image}/download.py +11 -35
  55. nonebot_plugin_l4d2_server/l4_image/html_img.py +105 -0
  56. nonebot_plugin_l4d2_server/l4_image/image_tools.py +468 -0
  57. nonebot_plugin_l4d2_server/{data/L4D2/image/template → l4_image/img/anne}/back.png +0 -0
  58. nonebot_plugin_l4d2_server/l4_image/img/anne/back1.jpg +0 -0
  59. nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/head/head.png +0 -0
  60. nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/header/logo.png +0 -0
  61. nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/header/player1.jpg +0 -0
  62. nonebot_plugin_l4d2_server/l4_image/img/template/Bocchi_The_Rock.html +299 -0
  63. nonebot_plugin_l4d2_server/l4_image/img/template/Bocchi_The_Rock.png +0 -0
  64. nonebot_plugin_l4d2_server/l4_image/img/template/HYPixel11pxU-2.ttf +0 -0
  65. nonebot_plugin_l4d2_server/l4_image/img/template/Pixel.html +341 -0
  66. nonebot_plugin_l4d2_server/l4_image/img/template/Pixel.png +0 -0
  67. nonebot_plugin_l4d2_server/l4_image/img/template/Rainbow.html +355 -0
  68. nonebot_plugin_l4d2_server/l4_image/img/template/Rainbow.png +0 -0
  69. nonebot_plugin_l4d2_server/l4_image/img/template/Tutumianhuatang-Bold-2.ttf +0 -0
  70. nonebot_plugin_l4d2_server/l4_image/img/template/bilibili.svg +1 -0
  71. nonebot_plugin_l4d2_server/l4_image/img/template/github.svg +1 -0
  72. nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/template/l.svg +0 -1
  73. nonebot_plugin_l4d2_server/l4_image/img/template/m.svg +1 -0
  74. nonebot_plugin_l4d2_server/l4_image/img/template/normal.html +247 -0
  75. nonebot_plugin_l4d2_server/l4_image/img/template/vac.png +0 -0
  76. nonebot_plugin_l4d2_server/l4_image/img/template/vac_white.png +0 -0
  77. nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/template/w.svg +1 -1
  78. nonebot_plugin_l4d2_server/l4_image/model.py +15 -0
  79. nonebot_plugin_l4d2_server/{l4d2_image → l4_image}/vtfs.py +4 -2
  80. nonebot_plugin_l4d2_server/l4_request/__init__.py +143 -0
  81. nonebot_plugin_l4d2_server/l4_request/draw_msg.py +83 -0
  82. nonebot_plugin_l4d2_server/utils/api/api.py +10 -0
  83. nonebot_plugin_l4d2_server/utils/api/models.py +137 -0
  84. nonebot_plugin_l4d2_server/utils/api/request.py +337 -0
  85. nonebot_plugin_l4d2_server/utils/database/models.py +18 -0
  86. nonebot_plugin_l4d2_server/{l4d2_utils → utils}/utils.py +60 -63
  87. {nonebot_plugin_l4d2_server-0.6.6.dist-info → nonebot_plugin_l4d2_server-1.0.0a2.dist-info}/METADATA +57 -66
  88. nonebot_plugin_l4d2_server-1.0.0a2.dist-info/RECORD +96 -0
  89. {nonebot_plugin_l4d2_server-0.6.6.dist-info → nonebot_plugin_l4d2_server-1.0.0a2.dist-info}/WHEEL +1 -1
  90. nonebot_plugin_l4d2_server/data/L4D2/image/template/help.html +0 -263
  91. nonebot_plugin_l4d2_server/data/L4D2/image/template/help_dack.html +0 -231
  92. nonebot_plugin_l4d2_server/data/L4D2/image/template/m.svg +0 -1
  93. nonebot_plugin_l4d2_server/data/img/white.png +0 -0
  94. nonebot_plugin_l4d2_server/l4d2_anne/__init__.py +0 -95
  95. nonebot_plugin_l4d2_server/l4d2_anne/analysis.py +0 -54
  96. nonebot_plugin_l4d2_server/l4d2_anne/anne_telecom.py +0 -79
  97. nonebot_plugin_l4d2_server/l4d2_anne/server.py +0 -47
  98. nonebot_plugin_l4d2_server/l4d2_anne/startand.py +0 -17
  99. nonebot_plugin_l4d2_server/l4d2_anne/utils.py +0 -294
  100. nonebot_plugin_l4d2_server/l4d2_data/__init__.py +0 -105
  101. nonebot_plugin_l4d2_server/l4d2_data/config.py +0 -18
  102. nonebot_plugin_l4d2_server/l4d2_data/players.py +0 -100
  103. nonebot_plugin_l4d2_server/l4d2_data/serverip.py +0 -40
  104. nonebot_plugin_l4d2_server/l4d2_file/__init__.py +0 -222
  105. nonebot_plugin_l4d2_server/l4d2_file/ayromote.py +0 -64
  106. nonebot_plugin_l4d2_server/l4d2_file/input_json.py +0 -77
  107. nonebot_plugin_l4d2_server/l4d2_file/remote.py +0 -86
  108. nonebot_plugin_l4d2_server/l4d2_file/utils.py +0 -104
  109. nonebot_plugin_l4d2_server/l4d2_image/__init__.py +0 -125
  110. nonebot_plugin_l4d2_server/l4d2_image/htmlimg.py +0 -18
  111. nonebot_plugin_l4d2_server/l4d2_image/images.py +0 -92
  112. nonebot_plugin_l4d2_server/l4d2_image/one.py +0 -44
  113. nonebot_plugin_l4d2_server/l4d2_image/send_image_tool.py +0 -32
  114. nonebot_plugin_l4d2_server/l4d2_image/steam.py +0 -63
  115. nonebot_plugin_l4d2_server/l4d2_push/__init__.py +0 -225
  116. nonebot_plugin_l4d2_server/l4d2_queries/__init__.py +0 -326
  117. nonebot_plugin_l4d2_server/l4d2_queries/himi.py +0 -113
  118. nonebot_plugin_l4d2_server/l4d2_queries/local_ip.py +0 -41
  119. nonebot_plugin_l4d2_server/l4d2_queries/qqgroup.py +0 -370
  120. nonebot_plugin_l4d2_server/l4d2_queries/send_msg.py +0 -131
  121. nonebot_plugin_l4d2_server/l4d2_queries/utils.py +0 -212
  122. nonebot_plugin_l4d2_server/l4d2_server/__init__.py +0 -118
  123. nonebot_plugin_l4d2_server/l4d2_server/index.py +0 -0
  124. nonebot_plugin_l4d2_server/l4d2_server/rcon.py +0 -53
  125. nonebot_plugin_l4d2_server/l4d2_server/workshop.py +0 -82
  126. nonebot_plugin_l4d2_server/l4d2_update/__init__.py +0 -137
  127. nonebot_plugin_l4d2_server/l4d2_update/draw_update_log.py +0 -45
  128. nonebot_plugin_l4d2_server/l4d2_update/restart.py +0 -69
  129. nonebot_plugin_l4d2_server/l4d2_update/update.py +0 -53
  130. nonebot_plugin_l4d2_server/l4d2_utils/classcal.py +0 -53
  131. nonebot_plugin_l4d2_server/l4d2_utils/command.py +0 -23
  132. nonebot_plugin_l4d2_server/l4d2_utils/config.py +0 -201
  133. nonebot_plugin_l4d2_server/l4d2_utils/message.py +0 -59
  134. nonebot_plugin_l4d2_server/l4d2_utils/rule.py +0 -35
  135. nonebot_plugin_l4d2_server/l4d2_utils/seach.py +0 -43
  136. nonebot_plugin_l4d2_server/l4d2_utils/txt_to_img.py +0 -32
  137. nonebot_plugin_l4d2_server/l4d2_web/web.py +0 -277
  138. nonebot_plugin_l4d2_server/l4d2_web/webUI.py +0 -506
  139. nonebot_plugin_l4d2_server/l4d2_web/webUI_s.py +0 -94
  140. nonebot_plugin_l4d2_server-0.6.6.dist-info/RECORD +0 -70
  141. /nonebot_plugin_l4d2_server/{data/L4D2/image/template → l4_image/img/anne}/anne.html +0 -0
  142. /nonebot_plugin_l4d2_server/{data/L4D2/image/template → l4_image/img/anne}/group_ip.html +0 -0
  143. /nonebot_plugin_l4d2_server/{data/L4D2/image/template → l4_image/img/anne}/ip.html +0 -0
  144. /nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/template/fingerprint.svg +0 -0
  145. /nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/template/vue.css +0 -0
  146. /nonebot_plugin_l4d2_server/{l4d2_data/database.py → l4_request/utils.py} +0 -0
  147. {nonebot_plugin_l4d2_server-0.6.6.dist-info → nonebot_plugin_l4d2_server-1.0.0a2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,337 @@
1
+ import asyncio
2
+ import contextlib
3
+ import socket
4
+ from copy import deepcopy
5
+ from typing import Any, Dict, List, Literal, Optional, Tuple, cast
6
+
7
+ import a2s
8
+ import ujson as js
9
+ from bs4 import BeautifulSoup
10
+ from httpx import AsyncClient
11
+
12
+ # from nonebot.log import logger
13
+ from ..utils import split_maohao
14
+ from .api import AnnePlayerApi, AnneSearchApi, anne_ban
15
+ from .models import (
16
+ AnnePlayer2,
17
+ AnnePlayerDetail,
18
+ AnnePlayerError,
19
+ AnnePlayerInf,
20
+ AnnePlayerInfAvg,
21
+ AnnePlayerInfo,
22
+ AnnePlayerSur,
23
+ AnneSearch,
24
+ SourceBansInfo,
25
+ )
26
+
27
+
28
+ class L4D2Api:
29
+ ssl_verify = False
30
+ _HEADER: Dict[str, str] = { # noqa: RUF012
31
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
32
+ "(KHTML, like Gecko)"
33
+ "Chrome/126.0.0.0"
34
+ "Safari/537.36 Edg/126.0.0.0",
35
+ "Content-Type": "application/x-www-form-urlencoded",
36
+ }
37
+
38
+ async def a2s_info(
39
+ self,
40
+ ip_list: List[Tuple[str, int]],
41
+ is_server: bool = True,
42
+ is_player: bool = False,
43
+ ) -> List[Tuple[a2s.SourceInfo, List[a2s.Player]]]:
44
+ msg_list: List[Tuple[a2s.SourceInfo, List[a2s.Player]]] = []
45
+ sorted_msg_list = []
46
+ tasks = [] # 用来保存异步任务
47
+ if ip_list != []:
48
+ for index, i in enumerate(ip_list):
49
+ try:
50
+ tasks.append(
51
+ asyncio.create_task(
52
+ self.process_message(
53
+ i,
54
+ index,
55
+ is_server,
56
+ is_player,
57
+ ),
58
+ ),
59
+ )
60
+ except ValueError:
61
+ continue # 处理异常情况
62
+
63
+ msg_list = await asyncio.gather(*tasks)
64
+ sorted_msg_list = sorted(msg_list, key=lambda x: x[0].steam_id)
65
+
66
+ return sorted_msg_list
67
+
68
+ async def process_message(
69
+ self,
70
+ ip: Tuple[str, int],
71
+ index: int,
72
+ is_server: bool,
73
+ is_player: bool,
74
+ ):
75
+ server: a2s.SourceInfo = a2s.SourceInfo()
76
+ play: List[a2s.Player] = []
77
+ if is_server:
78
+ try:
79
+ server = await a2s.ainfo(ip)
80
+ if server is not None:
81
+ server.steam_id = index
82
+
83
+ except (
84
+ asyncio.exceptions.TimeoutError,
85
+ ConnectionRefusedError,
86
+ socket.gaierror,
87
+ ):
88
+ server.steam_id = index
89
+ server.player_count = 0
90
+ server.max_players = 0
91
+ server.server_name = "服务器无响应"
92
+ server.map_name = "无"
93
+ server.folder = "m"
94
+ server.vac_enabled = False
95
+
96
+ if is_player:
97
+ with contextlib.suppress(
98
+ asyncio.exceptions.TimeoutError,
99
+ ConnectionRefusedError,
100
+ socket.gaierror,
101
+ ):
102
+ play = await a2s.aplayers(ip)
103
+ return server, play
104
+
105
+ async def _server_request(
106
+ self,
107
+ url: str,
108
+ method: Literal["GET", "POST"] = "GET",
109
+ header: Dict[str, str] = _HEADER,
110
+ params: Optional[Dict[str, Any]] = None,
111
+ json: Optional[Dict[str, Any]] = None,
112
+ data: Optional[Dict[str, Any]] = None,
113
+ is_json: bool = True,
114
+ ):
115
+ header = deepcopy(self._HEADER)
116
+
117
+ if json is not None:
118
+ method = "POST"
119
+
120
+ async with AsyncClient(verify=self.ssl_verify) as client:
121
+ resp = await client.request(
122
+ method,
123
+ url=url,
124
+ headers=header,
125
+ params=params,
126
+ json=json,
127
+ data=data,
128
+ timeout=300,
129
+ )
130
+
131
+ if is_json:
132
+ try:
133
+ raw_data = await resp.json()
134
+ except: # noqa: E722
135
+ _raw_data = resp.text
136
+ try:
137
+ raw_data = js.loads(_raw_data)
138
+ except: # noqa: E722
139
+ raw_data = {
140
+ "result": {"error_code": -999, "data": _raw_data},
141
+ }
142
+ try:
143
+ if not raw_data["result"]:
144
+ return raw_data
145
+ except Exception:
146
+ return raw_data
147
+ if (
148
+ "result" in raw_data
149
+ and "error_code" in raw_data["result"]
150
+ and raw_data["code"] != 0
151
+ ):
152
+ return raw_data["result"]["error_code"]
153
+ return raw_data
154
+ html_content = resp.content
155
+ return BeautifulSoup(html_content, "lxml")
156
+
157
+ async def get_sourceban(self, url: str = anne_ban):
158
+ """从sourceban++获取服务器列表,目前未做名称处理"""
159
+ soup = await self._server_request(
160
+ url=url,
161
+ is_json=False,
162
+ )
163
+
164
+ if not isinstance(soup, BeautifulSoup):
165
+ return []
166
+ server_list = []
167
+ tbody = soup.select_one("tbody")
168
+ if tbody is None:
169
+ return []
170
+ tr_tags = tbody.select("tr")
171
+ for index, tr in enumerate(tr_tags):
172
+ td_tags = tr.select("td")
173
+ for num, td in enumerate(td_tags):
174
+ if num == 4:
175
+ host, port = split_maohao(td.text)
176
+ server_list.append(
177
+ SourceBansInfo(index=index, host=host, port=port),
178
+ )
179
+
180
+ return server_list
181
+
182
+ async def get_anne_steamid(self, name: str):
183
+ """从电信anne服搜索昵称获取steamid"""
184
+ soup = await self._server_request(
185
+ url=AnneSearchApi,
186
+ data={"search": name},
187
+ method="POST",
188
+ is_json=False,
189
+ )
190
+ if not isinstance(soup, BeautifulSoup):
191
+ return None
192
+ server_list = []
193
+ tbody = soup.select_one("tbody")
194
+ if tbody is None:
195
+ return None
196
+ tr_tags = tbody.select("tr")
197
+ for tr in tr_tags:
198
+ onclick = tr.get("onclick")
199
+ if onclick is None or isinstance(onclick, list):
200
+ continue
201
+ steamid = onclick.split("steamid=")[1].replace("'", "")
202
+ td_tags = tr.select("td")
203
+ server_list.append(
204
+ {
205
+ "steamid": steamid,
206
+ "rank": td_tags[0].text.strip(),
207
+ "name": td_tags[1].text.strip(),
208
+ "score": td_tags[2].text.strip(),
209
+ "play_time": td_tags[3].text.strip(),
210
+ "last_time": td_tags,
211
+ },
212
+ )
213
+ print(server_list)
214
+ return cast(List[AnneSearch], server_list)
215
+
216
+ async def get_anne_playerdetail(self, steamid: str):
217
+ """从电信anne服通过steamid获取战绩"""
218
+ soup = await self._server_request(
219
+ url=AnnePlayerApi,
220
+ method="GET",
221
+ params={"steamid": steamid},
222
+ is_json=False,
223
+ )
224
+ if not isinstance(soup, BeautifulSoup):
225
+ return None
226
+
227
+ tbody = soup.find(
228
+ "div",
229
+ class_="content text-center text-md-left",
230
+ style="background-color: #f2f2f2;",
231
+ )
232
+ if tbody is None:
233
+ return None
234
+ kill_tag = tbody.find(
235
+ "div",
236
+ class_="card-body worldmap d-flex flex-column justify-content-center text-center",
237
+ )
238
+
239
+ tbody_tags = tbody.find_all(
240
+ "table",
241
+ class_="table content-table-noborder text-left",
242
+ )
243
+ print(len(tbody_tags))
244
+ info_tag = tbody_tags[0]
245
+ detail_tag = tbody_tags[1]
246
+ error_tag = tbody_tags[2]
247
+ inf_avg_tag = tbody_tags[3]
248
+ sur_tag = tbody_tags[4]
249
+ inf_tag = tbody_tags[5]
250
+
251
+ info_tr = info_tag.select("tr")
252
+ info_dict = {
253
+ "name": info_tr[0].select("td")[1].text.strip(),
254
+ "avatar": info_tr[1].select("td")[1].text.strip(),
255
+ "steamid": info_tr[2].select("td")[1].text.strip(),
256
+ "playtime": info_tr[3].select("td")[1].text.strip(),
257
+ "lasttime": info_tr[4].select("td")[1].text.strip(),
258
+ }
259
+ detail_tag = {
260
+ "rank": detail_tag.select("tr")[0].select("td")[1].text.strip(),
261
+ "source": detail_tag.select("tr")[1].select("td")[1].text.strip(),
262
+ "avg_source": detail_tag.select("tr")[2].select("td")[1].text.strip(),
263
+ "kills": detail_tag.select("tr")[3].select("td")[1].text.strip(),
264
+ "kills_people": detail_tag.select("tr")[4].select("td")[1].text.strip(),
265
+ "headshots": detail_tag.select("tr")[5].select("td")[1].text.strip(),
266
+ "avg_headshots": detail_tag.select("tr")[6].select("td")[1].text.strip(),
267
+ "map_play": detail_tag.select("tr")[7].select("td")[1].text.strip(),
268
+ }
269
+ error_tag = {
270
+ "mistake_shout": error_tag.select("tr")[0].select("td")[1].text.strip(),
271
+ "kill_friend": error_tag.select("tr")[1].select("td")[1].text.strip(),
272
+ "down_friend": error_tag.select("tr")[2].select("td")[1].text.strip(),
273
+ "abandon_friend": error_tag.select("tr")[3].select("td")[1].text.strip(),
274
+ "put_into": error_tag.select("tr")[4].select("td")[1].text.strip(),
275
+ "agitate_witch": error_tag.select("tr")[5].select("td")[1].text.strip(),
276
+ }
277
+ inf_avg_dict = {
278
+ "avg_smoker": inf_avg_tag.select("tr")[0].select("td")[1].text.strip(),
279
+ "avg_boomer": inf_avg_tag.select("tr")[1].select("td")[1].text.strip(),
280
+ "avg_hunter": inf_avg_tag.select("tr")[2].select("td")[1].text.strip(),
281
+ "avg_charger": inf_avg_tag.select("tr")[3].select("td")[1].text.strip(),
282
+ "avg_spitter": inf_avg_tag.select("tr")[4].select("td")[1].text.strip(),
283
+ "avg_jockey": inf_avg_tag.select("tr")[5].select("td")[1].text.strip(),
284
+ "avg_tank": inf_avg_tag.select("tr")[6].select("td")[1].text.strip(),
285
+ }
286
+ sur_dict = {
287
+ "map_clear": sur_tag.select("tr")[0].select("td")[1].text.strip(),
288
+ "prefect_into": sur_tag.select("tr")[1].select("td")[1].text.strip(),
289
+ "get_oil": sur_tag.select("tr")[2].select("td")[1].text.strip(),
290
+ "ammo_arrange": sur_tag.select("tr")[3].select("td")[1].text.strip(),
291
+ "adrenaline_give": sur_tag.select("tr")[4].select("td")[1].text.strip(),
292
+ "pills_give": sur_tag.select("tr")[5].select("td")[1].text.strip(),
293
+ "first_aid_give": sur_tag.select("tr")[6].select("td")[1].text.strip(),
294
+ "friend_up": sur_tag.select("tr")[7].select("td")[1].text.strip(),
295
+ "diss_friend": sur_tag.select("tr")[8].select("td")[1].text.strip(),
296
+ "save_friend": sur_tag.select("tr")[9].select("td")[1].text.strip(),
297
+ "protect_friend": sur_tag.select("tr")[10].select("td")[1].text.strip(),
298
+ "pro_from_smoker": sur_tag.select("tr")[11].select("td")[1].text.strip(),
299
+ "pro_from_hunter": sur_tag.select("tr")[12].select("td")[1].text.strip(),
300
+ "pro_from_charger": sur_tag.select("tr")[13].select("td")[1].text.strip(),
301
+ "pro_from_jockey": sur_tag.select("tr")[14].select("td")[1].text.strip(),
302
+ "melee_charge": sur_tag.select("tr")[15].select("td")[1].text.strip(),
303
+ "tank_kill": sur_tag.select("tr")[16].select("td")[1].text.strip(),
304
+ "witch_instantly_kill": sur_tag.select("tr")[17]
305
+ .select("td")[1]
306
+ .text.strip(),
307
+ }
308
+ inf_dict = {
309
+ "sur_ace": inf_tag.select("tr")[0].select("td")[1].text.strip(),
310
+ "sur_down": inf_tag.select("tr")[1].select("td")[1].text.strip(),
311
+ "boommer_hit": inf_tag.select("tr")[2].select("td")[1].text.strip(),
312
+ "hunter_prefect": inf_tag.select("tr")[3].select("td")[1].text.strip(),
313
+ "hunter_success": inf_tag.select("tr")[4].select("td")[1].text.strip(),
314
+ "tank_damage": inf_tag.select("tr")[5].select("td")[1].text.strip(),
315
+ "charger_multiple": inf_tag.select("tr")[6].select("td")[1].text.strip(),
316
+ }
317
+ info_dict = cast(AnnePlayerInfo, info_dict)
318
+ detail_dict = cast(AnnePlayerDetail, detail_tag)
319
+ error_dict = cast(AnnePlayerError, error_tag)
320
+ inf_avg_dict = cast(AnnePlayerInfAvg, inf_avg_dict)
321
+ sur_dict = cast(AnnePlayerSur, sur_dict)
322
+ inf_dict = cast(AnnePlayerInf, inf_dict)
323
+
324
+ out_dict = {
325
+ "kill_msg": kill_tag.text if kill_tag is not None else "",
326
+ "info": info_dict,
327
+ "detail": detail_dict,
328
+ "inf_avg": inf_avg_dict,
329
+ "sur": sur_dict,
330
+ "inf": inf_dict,
331
+ "error": error_dict,
332
+ }
333
+
334
+ return cast(AnnePlayer2, out_dict)
335
+
336
+
337
+ L4API = L4D2Api()
@@ -0,0 +1,18 @@
1
+ from nonebot_plugin_tortoise_orm import add_model
2
+ from tortoise import fields
3
+ from tortoise.models import Model
4
+
5
+ add_model(__name__)
6
+
7
+
8
+ class SteamUser(Model):
9
+ """个人资料"""
10
+
11
+ userid = fields.BigIntField(pk=True)
12
+ SteamID = fields.TextField(null=True)
13
+ SteamID64 = fields.TextField(null=True)
14
+ Name = fields.TextField(null=True)
15
+
16
+ class Meta: # type: ignore
17
+ table = "steam_user"
18
+ table_description = "个人资料"
@@ -1,19 +1,13 @@
1
1
  import json
2
+ import os
2
3
  import tempfile
3
4
  from pathlib import Path
4
5
  from typing import Any, Dict, List, Optional, Tuple
5
6
 
6
7
  import aiofiles
7
- import httpx
8
+ import aiohttp
8
9
  from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent
9
10
  from nonebot.log import logger
10
- from nonebot.matcher import Matcher
11
-
12
- from ..l4d2_image.steam import url_to_byte
13
- from .config import l4_config, systems
14
-
15
- # from .rule import
16
- from .txt_to_img import mode_txt_to_img
17
11
 
18
12
 
19
13
  async def get_file(url: str, down_file: Path):
@@ -21,10 +15,7 @@ async def get_file(url: str, down_file: Path):
21
15
  下载指定Url到指定位置
22
16
  """
23
17
  try:
24
- if l4_config.l4_only:
25
- maps = await url_to_byte(url)
26
- else:
27
- maps = httpx.get(url).content # noqa: ASYNC100
18
+ maps = await url_to_byte(url)
28
19
  logger.info("已获取文件,尝试新建文件并写入")
29
20
  if maps:
30
21
  async with aiofiles.open(down_file, "wb") as mfile:
@@ -47,7 +38,7 @@ def get_vpk(map_path: Path, file_: str = ".vpk") -> List[str]:
47
38
  def mes_list(mes: str, name_list: List[str]) -> str:
48
39
  if name_list:
49
40
  for idx, name in enumerate(name_list):
50
- mes += f"\n{idx+1}、{name}"
41
+ mes += f"\n{idx + 1}、{name}"
51
42
  return mes
52
43
 
53
44
 
@@ -82,16 +73,11 @@ def solve(msg: str):
82
73
  return "\n".join(lines)
83
74
 
84
75
 
85
- async def get_message_at(datas: str) -> List[int]:
86
- data: Dict[str, Any] = json.loads(datas)
87
- return [int(msg["data"]["qq"]) for msg in data["message"] if msg["type"] == "at"]
88
-
89
-
90
76
  def at_to_usrid(at: List[int]):
91
77
  return at[0] if at else None
92
78
 
93
79
 
94
- async def save_file(file: bytes, path_name):
80
+ async def save_file(file: bytes, path_name: str):
95
81
  """保存文件"""
96
82
  async with aiofiles.open(path_name, "wb") as files:
97
83
  await files.write(file)
@@ -99,7 +85,7 @@ async def save_file(file: bytes, path_name):
99
85
 
100
86
  async def upload_file(bot: Bot, event: MessageEvent, file_data: bytes, filename: str):
101
87
  """上传临时文件"""
102
- if systems in ["win", "other"]:
88
+ if os.name == "nt":
103
89
  with tempfile.TemporaryDirectory() as temp_dir:
104
90
  async with aiofiles.open(Path(temp_dir) / filename, "wb") as f:
105
91
  await f.write(file_data)
@@ -118,23 +104,23 @@ async def upload_file(bot: Bot, event: MessageEvent, file_data: bytes, filename:
118
104
  name=filename,
119
105
  )
120
106
  (Path().joinpath(filename)).unlink()
121
- elif systems == "linux":
107
+ else:
122
108
  with tempfile.NamedTemporaryFile("wb+") as f:
123
109
  f.write(file_data)
124
- if isinstance(event, GroupMessageEvent):
125
- await bot.call_api(
126
- "upload_group_file",
127
- group_id=event.group_id,
128
- file=f.name,
129
- name=filename,
130
- )
131
- else:
132
- await bot.call_api(
133
- "upload_private_file",
134
- user_id=event.user_id,
135
- file=f.name,
136
- name=filename,
137
- )
110
+ if isinstance(event, GroupMessageEvent):
111
+ await bot.call_api(
112
+ "upload_group_file",
113
+ group_id=event.group_id,
114
+ file=f.name,
115
+ name=filename,
116
+ )
117
+ else:
118
+ await bot.call_api(
119
+ "upload_private_file",
120
+ user_id=event.user_id,
121
+ file=f.name,
122
+ name=filename,
123
+ )
138
124
 
139
125
 
140
126
  sub_menus = []
@@ -159,7 +145,7 @@ def register_menu_func(
159
145
 
160
146
 
161
147
  def register_menu(*args, **kwargs):
162
- def decorator(f):
148
+ def decorator(f): # noqa: ANN001
163
149
  register_menu_func(*args, **kwargs)
164
150
  return f
165
151
 
@@ -176,32 +162,43 @@ async def extract_last_digit(msg: str) -> Tuple[str, str]:
176
162
  return msg, ""
177
163
 
178
164
 
179
- async def str_to_picstr(push_msg: str, matcher: Matcher, keyword: Optional[str] = None):
180
- """判断图片输出还是正常输出"""
181
- if l4_config.l4_image:
182
- lines = push_msg.splitlines()
183
- first_str = lines[0]
184
- last_str = lines[-1]
185
- push_msg = "\n".join(lines[1:-1])
186
- if l4_config.l4_connect:
187
- await mode_txt_to_img(first_str, push_msg, last_str)
188
- else:
189
- await mode_txt_to_img(first_str, push_msg)
190
- else:
191
- if l4_config.l4_connect or keyword == "connect":
192
- await matcher.send(push_msg)
193
- else:
194
- await matcher.send("\n".join(push_msg.splitlines()[1:-2]))
195
-
196
-
197
- def split_maohao(msg: str) -> List[str]:
165
+ def split_maohao(msg: str) -> Tuple[str, int]:
198
166
  """分割大小写冒号"""
199
167
  if ":" in msg:
200
- msgs: List[str] = msg.split(":")
201
- elif ":" in msg:
202
- msgs: List[str] = msg.split(":")
203
- elif msg.replace(".", "").isdigit():
204
- msgs: List[str] = [msg, "20715"]
205
- else:
206
- msgs = []
207
- return [msgs[0], msgs[-1]]
168
+ return msg.split(":")[0], int(msg.split(":")[-1])
169
+ if ":" in msg:
170
+ return msg.split(":")[0], int(msg.split(":")[-1])
171
+ if msg.replace(".", "").isdigit():
172
+ return msg, 20715
173
+ return "", -1
174
+
175
+
176
+ headers = {
177
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0", # noqa: E501
178
+ }
179
+
180
+
181
+ async def url_to_byte(url: str):
182
+ """获取URL数据的字节流"""
183
+
184
+ async with aiohttp.ClientSession() as session:
185
+ async with session.get(url, headers=headers, timeout=600) as response:
186
+ if response.status == 200:
187
+ return await response.read()
188
+ return None
189
+
190
+
191
+ async def url_to_msg(url: str):
192
+ """获取URL数据的字节流"""
193
+
194
+ async with aiohttp.ClientSession() as session:
195
+ async with session.get(url, headers=headers, timeout=600) as response:
196
+ if response.status == 200:
197
+ return await response.text()
198
+ return None
199
+
200
+
201
+ async def get_message_at(datas: str) -> Optional[int]: # noqa: F811
202
+ data: Dict[str, Any] = json.loads(datas)
203
+ at_list = [int(msg["data"]["qq"]) for msg in data["message"] if msg["type"] == "at"]
204
+ return at_list[0] if at_list else None