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.
- nonebot_plugin_l4d2_server/__init__.py +10 -93
- nonebot_plugin_l4d2_server/__main__.py +140 -0
- nonebot_plugin_l4d2_server/config.py +35 -0
- nonebot_plugin_l4d2_server/data/font/loli.ttf +0 -0
- nonebot_plugin_l4d2_server/l4_anne/__init__.py +124 -0
- nonebot_plugin_l4d2_server/l4_anne/ranne.py +18 -0
- nonebot_plugin_l4d2_server/l4_help/Help.json +102 -0
- nonebot_plugin_l4d2_server/l4_help/__init__.py +57 -0
- nonebot_plugin_l4d2_server/l4_help/draw.py +206 -0
- nonebot_plugin_l4d2_server/l4_help/icon//344/273/213/347/273/215.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//344/273/273/345/212/241.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//344/277/241/346/201/257.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/205/254/345/221/212.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/210/200/345/211/221.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/210/207/346/215/242.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/210/240/351/231/244.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/210/267/346/226/260.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/215/241/347/273/204.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/223/252/351/207/214.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/234/260/345/233/276.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/257/274/345/205/245.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/257/274/345/207/272.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/275/261.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/213/274/345/233/276.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/216/242/347/264/242.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/216/250/351/200/201.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/224/266/351/233/206.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/224/273/347/225/245.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/233/264/346/226/260.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/235/220/346/226/231.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/237/245/350/257/242.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/240/241/351/252/214.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/257/217/346/234/210.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/267/261/346/270/212.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/267/273/345/212/240.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/270/205/351/231/244.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//347/212/266/346/200/201.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//347/255/276/345/210/260.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//347/273/221/345/256/232.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//350/241/250.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//350/241/250/346/203/205.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//350/247/222/350/211/262.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//350/256/260/345/275/225.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//351/205/215/347/275/256.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//351/207/215/345/220/257.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/badge.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/banner.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/bg.jpg +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/button.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/icon.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/__init__.py +16 -0
- nonebot_plugin_l4d2_server/l4_image/anne_pil.py +17 -0
- nonebot_plugin_l4d2_server/l4_image/convert.py +175 -0
- nonebot_plugin_l4d2_server/{l4d2_image → l4_image}/download.py +11 -35
- nonebot_plugin_l4d2_server/l4_image/html_img.py +105 -0
- nonebot_plugin_l4d2_server/l4_image/image_tools.py +468 -0
- nonebot_plugin_l4d2_server/{data/L4D2/image/template → l4_image/img/anne}/back.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/anne/back1.jpg +0 -0
- nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/head/head.png +0 -0
- nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/header/logo.png +0 -0
- nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/header/player1.jpg +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Bocchi_The_Rock.html +299 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Bocchi_The_Rock.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/HYPixel11pxU-2.ttf +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Pixel.html +341 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Pixel.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Rainbow.html +355 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Rainbow.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Tutumianhuatang-Bold-2.ttf +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/bilibili.svg +1 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/github.svg +1 -0
- nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/template/l.svg +0 -1
- nonebot_plugin_l4d2_server/l4_image/img/template/m.svg +1 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/normal.html +247 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/vac.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/vac_white.png +0 -0
- nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/template/w.svg +1 -1
- nonebot_plugin_l4d2_server/l4_image/model.py +15 -0
- nonebot_plugin_l4d2_server/{l4d2_image → l4_image}/vtfs.py +4 -2
- nonebot_plugin_l4d2_server/l4_request/__init__.py +143 -0
- nonebot_plugin_l4d2_server/l4_request/draw_msg.py +83 -0
- nonebot_plugin_l4d2_server/utils/api/api.py +10 -0
- nonebot_plugin_l4d2_server/utils/api/models.py +137 -0
- nonebot_plugin_l4d2_server/utils/api/request.py +337 -0
- nonebot_plugin_l4d2_server/utils/database/models.py +18 -0
- nonebot_plugin_l4d2_server/{l4d2_utils → utils}/utils.py +60 -63
- {nonebot_plugin_l4d2_server-0.6.6.dist-info → nonebot_plugin_l4d2_server-1.0.0a2.dist-info}/METADATA +57 -66
- nonebot_plugin_l4d2_server-1.0.0a2.dist-info/RECORD +96 -0
- {nonebot_plugin_l4d2_server-0.6.6.dist-info → nonebot_plugin_l4d2_server-1.0.0a2.dist-info}/WHEEL +1 -1
- nonebot_plugin_l4d2_server/data/L4D2/image/template/help.html +0 -263
- nonebot_plugin_l4d2_server/data/L4D2/image/template/help_dack.html +0 -231
- nonebot_plugin_l4d2_server/data/L4D2/image/template/m.svg +0 -1
- nonebot_plugin_l4d2_server/data/img/white.png +0 -0
- nonebot_plugin_l4d2_server/l4d2_anne/__init__.py +0 -95
- nonebot_plugin_l4d2_server/l4d2_anne/analysis.py +0 -54
- nonebot_plugin_l4d2_server/l4d2_anne/anne_telecom.py +0 -79
- nonebot_plugin_l4d2_server/l4d2_anne/server.py +0 -47
- nonebot_plugin_l4d2_server/l4d2_anne/startand.py +0 -17
- nonebot_plugin_l4d2_server/l4d2_anne/utils.py +0 -294
- nonebot_plugin_l4d2_server/l4d2_data/__init__.py +0 -105
- nonebot_plugin_l4d2_server/l4d2_data/config.py +0 -18
- nonebot_plugin_l4d2_server/l4d2_data/players.py +0 -100
- nonebot_plugin_l4d2_server/l4d2_data/serverip.py +0 -40
- nonebot_plugin_l4d2_server/l4d2_file/__init__.py +0 -222
- nonebot_plugin_l4d2_server/l4d2_file/ayromote.py +0 -64
- nonebot_plugin_l4d2_server/l4d2_file/input_json.py +0 -77
- nonebot_plugin_l4d2_server/l4d2_file/remote.py +0 -86
- nonebot_plugin_l4d2_server/l4d2_file/utils.py +0 -104
- nonebot_plugin_l4d2_server/l4d2_image/__init__.py +0 -125
- nonebot_plugin_l4d2_server/l4d2_image/htmlimg.py +0 -18
- nonebot_plugin_l4d2_server/l4d2_image/images.py +0 -92
- nonebot_plugin_l4d2_server/l4d2_image/one.py +0 -44
- nonebot_plugin_l4d2_server/l4d2_image/send_image_tool.py +0 -32
- nonebot_plugin_l4d2_server/l4d2_image/steam.py +0 -63
- nonebot_plugin_l4d2_server/l4d2_push/__init__.py +0 -225
- nonebot_plugin_l4d2_server/l4d2_queries/__init__.py +0 -326
- nonebot_plugin_l4d2_server/l4d2_queries/himi.py +0 -113
- nonebot_plugin_l4d2_server/l4d2_queries/local_ip.py +0 -41
- nonebot_plugin_l4d2_server/l4d2_queries/qqgroup.py +0 -370
- nonebot_plugin_l4d2_server/l4d2_queries/send_msg.py +0 -131
- nonebot_plugin_l4d2_server/l4d2_queries/utils.py +0 -212
- nonebot_plugin_l4d2_server/l4d2_server/__init__.py +0 -118
- nonebot_plugin_l4d2_server/l4d2_server/index.py +0 -0
- nonebot_plugin_l4d2_server/l4d2_server/rcon.py +0 -53
- nonebot_plugin_l4d2_server/l4d2_server/workshop.py +0 -82
- nonebot_plugin_l4d2_server/l4d2_update/__init__.py +0 -137
- nonebot_plugin_l4d2_server/l4d2_update/draw_update_log.py +0 -45
- nonebot_plugin_l4d2_server/l4d2_update/restart.py +0 -69
- nonebot_plugin_l4d2_server/l4d2_update/update.py +0 -53
- nonebot_plugin_l4d2_server/l4d2_utils/classcal.py +0 -53
- nonebot_plugin_l4d2_server/l4d2_utils/command.py +0 -23
- nonebot_plugin_l4d2_server/l4d2_utils/config.py +0 -201
- nonebot_plugin_l4d2_server/l4d2_utils/message.py +0 -59
- nonebot_plugin_l4d2_server/l4d2_utils/rule.py +0 -35
- nonebot_plugin_l4d2_server/l4d2_utils/seach.py +0 -43
- nonebot_plugin_l4d2_server/l4d2_utils/txt_to_img.py +0 -32
- nonebot_plugin_l4d2_server/l4d2_web/web.py +0 -277
- nonebot_plugin_l4d2_server/l4d2_web/webUI.py +0 -506
- nonebot_plugin_l4d2_server/l4d2_web/webUI_s.py +0 -94
- nonebot_plugin_l4d2_server-0.6.6.dist-info/RECORD +0 -70
- /nonebot_plugin_l4d2_server/{data/L4D2/image/template → l4_image/img/anne}/anne.html +0 -0
- /nonebot_plugin_l4d2_server/{data/L4D2/image/template → l4_image/img/anne}/group_ip.html +0 -0
- /nonebot_plugin_l4d2_server/{data/L4D2/image/template → l4_image/img/anne}/ip.html +0 -0
- /nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/template/fingerprint.svg +0 -0
- /nonebot_plugin_l4d2_server/{data/L4D2/image → l4_image/img}/template/vue.css +0 -0
- /nonebot_plugin_l4d2_server/{l4d2_data/database.py → l4_request/utils.py} +0 -0
- {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
|
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
|
-
|
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
|
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
|
-
|
107
|
+
else:
|
122
108
|
with tempfile.NamedTemporaryFile("wb+") as f:
|
123
109
|
f.write(file_data)
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
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
|
-
|
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
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
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
|