nonebot-plugin-l4d2-server 1.0.4__py3-none-any.whl → 1.0.8__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 +1 -0
- nonebot_plugin_l4d2_server/__main__.py +31 -27
- nonebot_plugin_l4d2_server/config.py +1 -1
- nonebot_plugin_l4d2_server/l4_help/Help.json +2 -39
- nonebot_plugin_l4d2_server/l4_help/__init__.py +5 -7
- nonebot_plugin_l4d2_server/l4_image/html_img.py +1 -16
- nonebot_plugin_l4d2_server/l4_image/image_tools.py +1 -2
- nonebot_plugin_l4d2_server/l4_local/__init__.py +0 -1
- nonebot_plugin_l4d2_server/l4_request/__init__.py +71 -194
- nonebot_plugin_l4d2_server/l4_request/draw_msg.py +1 -1
- nonebot_plugin_l4d2_server/l4_request/utils.py +176 -0
- nonebot_plugin_l4d2_server/utils/api/request.py +126 -108
- nonebot_plugin_l4d2_server/utils/api/utils.py +30 -0
- {nonebot_plugin_l4d2_server-1.0.4.dist-info → nonebot_plugin_l4d2_server-1.0.8.dist-info}/METADATA +3 -3
- {nonebot_plugin_l4d2_server-1.0.4.dist-info → nonebot_plugin_l4d2_server-1.0.8.dist-info}/RECORD +18 -18
- nonebot_plugin_l4d2_server/l4_image/anne_pil.py +0 -18
- {nonebot_plugin_l4d2_server-1.0.4.dist-info → nonebot_plugin_l4d2_server-1.0.8.dist-info}/WHEEL +0 -0
- {nonebot_plugin_l4d2_server-1.0.4.dist-info → nonebot_plugin_l4d2_server-1.0.8.dist-info}/entry_points.txt +0 -0
- {nonebot_plugin_l4d2_server-1.0.4.dist-info → nonebot_plugin_l4d2_server-1.0.8.dist-info}/licenses/LICENSE +0 -0
@@ -20,6 +20,7 @@ from nonebot import get_driver, require
|
|
20
20
|
require("nonebot_plugin_htmlrender")
|
21
21
|
require("nonebot_plugin_alconna")
|
22
22
|
require("nonebot_plugin_tortoise_orm")
|
23
|
+
require("nonebot_plugin_datastore")
|
23
24
|
|
24
25
|
from nonebot.plugin import PluginMetadata, inherit_supported_adapters # noqa: E402
|
25
26
|
|
@@ -16,7 +16,7 @@
|
|
16
16
|
"""
|
17
17
|
|
18
18
|
from pathlib import Path
|
19
|
-
from typing import TYPE_CHECKING, List, Optional
|
19
|
+
from typing import TYPE_CHECKING, List, Optional
|
20
20
|
|
21
21
|
import aiofiles
|
22
22
|
import ujson as json
|
@@ -37,9 +37,12 @@ from .l4_request import (
|
|
37
37
|
get_ip_server,
|
38
38
|
get_server_detail,
|
39
39
|
reload_ip,
|
40
|
+
server_find,
|
40
41
|
tj_request,
|
41
42
|
)
|
42
43
|
from .utils.api.request import L4API
|
44
|
+
from .utils.api.utils import out_msg_out
|
45
|
+
from .utils.utils import split_maohao
|
43
46
|
|
44
47
|
if TYPE_CHECKING:
|
45
48
|
from .utils.api.models import OutServer
|
@@ -111,10 +114,15 @@ async def _(
|
|
111
114
|
_id = None
|
112
115
|
logger.info(f"组:{command} ;数字:{_id}")
|
113
116
|
msg = await get_server_detail(command, _id)
|
114
|
-
if msg is
|
115
|
-
await out_msg_out(msg, is_connect=config.l4_image)
|
116
|
-
else:
|
117
|
+
if msg is None:
|
117
118
|
await out_msg_out("服务器无响应")
|
119
|
+
return
|
120
|
+
if _id is None:
|
121
|
+
logger.info(f"正在输出组:{command}")
|
122
|
+
await out_msg_out(msg)
|
123
|
+
if _id:
|
124
|
+
logger.info(f"正在输出单服务器:{command} {_id}", is_connect=config.l4_image)
|
125
|
+
await out_msg_out(msg)
|
118
126
|
|
119
127
|
|
120
128
|
@l4_find_player.handle()
|
@@ -127,21 +135,30 @@ async def _(
|
|
127
135
|
if len(tag_list) == 1:
|
128
136
|
await UniMessage.text("未设置组,正在全服查找,时间较长").send()
|
129
137
|
name = tag_list[0]
|
130
|
-
out: List[OutServer] = await
|
138
|
+
out: List[OutServer] = await server_find(is_img=False) # type: ignore
|
139
|
+
logger.info(out)
|
140
|
+
logger.info(type(out))
|
131
141
|
out_msg = "未找到玩家"
|
132
142
|
for one in out:
|
143
|
+
logger.info(one)
|
133
144
|
for player in one["player"]:
|
134
145
|
if name in player.name:
|
135
146
|
out_msg = await get_ip_server(f"{one['host']}:{one['port']}")
|
136
147
|
if len(tag_list) == 2:
|
137
148
|
group, name = tag_list
|
138
149
|
await UniMessage.text(f"正在查询{group}组").send()
|
139
|
-
out: List[OutServer] = await
|
150
|
+
out: List[OutServer] = await server_find(command=group, is_img=False) # type: ignore
|
140
151
|
out_msg = "未找到玩家"
|
141
152
|
for one in out:
|
142
153
|
for player in one["player"]:
|
143
154
|
if name in player.name:
|
144
155
|
out_msg = await get_ip_server(f"{one['host']}:{one['port']}")
|
156
|
+
if config.l4_connect and isinstance(out_msg, bytes):
|
157
|
+
out_msg = UniMessage.image(raw=out_msg) + UniMessage.text(
|
158
|
+
f"\nconnect {one['host']}:{one['port']}",
|
159
|
+
)
|
160
|
+
else:
|
161
|
+
out_msg = UniMessage.text(out_msg)
|
145
162
|
|
146
163
|
return await out_msg_out(out_msg)
|
147
164
|
|
@@ -155,17 +172,22 @@ async def _():
|
|
155
172
|
async def _(args: Message = CommandArg()):
|
156
173
|
ip: Optional[str] = args.extract_plain_text()
|
157
174
|
if ip is not None:
|
158
|
-
|
175
|
+
host, port = split_maohao(ip)
|
176
|
+
await out_msg_out(
|
177
|
+
await get_ip_server(ip),
|
178
|
+
is_connect=config.l4_connect,
|
179
|
+
host=host,
|
180
|
+
port=port,
|
181
|
+
)
|
159
182
|
|
160
183
|
|
161
184
|
@l4_reload.handle()
|
162
185
|
async def _(args: Message = CommandArg()):
|
163
186
|
arg = args.extract_plain_text().strip()
|
164
|
-
print(arg)
|
165
187
|
if not arg:
|
166
188
|
reload_ip()
|
167
189
|
logger.success("重载ip完成")
|
168
|
-
with (Path(config.l4_path) / "
|
190
|
+
with (Path(config.l4_path) / "l4d2.json").open("r", encoding="utf-8") as f:
|
169
191
|
content = f.read().strip()
|
170
192
|
ip_json = json.loads(content)
|
171
193
|
for tag, url in ip_json.items():
|
@@ -261,24 +283,6 @@ async def _(matcher: Matcher):
|
|
261
283
|
await matcher.finish(await tj_request("云", "zl"))
|
262
284
|
|
263
285
|
|
264
|
-
async def out_msg_out(
|
265
|
-
msg: Union[str, bytes, UniMessage],
|
266
|
-
is_connect: bool = False,
|
267
|
-
host: str = "",
|
268
|
-
port: str = "",
|
269
|
-
):
|
270
|
-
if isinstance(msg, UniMessage):
|
271
|
-
return await msg.finish()
|
272
|
-
if isinstance(msg, str):
|
273
|
-
await UniMessage.text(msg).finish()
|
274
|
-
if is_connect:
|
275
|
-
out = UniMessage.image(raw=msg) + UniMessage.text(
|
276
|
-
f"连接到服务器: {host}:{port}",
|
277
|
-
)
|
278
|
-
return await out.finish()
|
279
|
-
return await UniMessage.image(raw=msg).finish()
|
280
|
-
|
281
|
-
|
282
286
|
## 以下为配置修改
|
283
287
|
|
284
288
|
img_trung = on_command("l4img", aliases={"l4图片"}, permission=SUPERUSER)
|
@@ -6,10 +6,10 @@ from pydantic import BaseModel
|
|
6
6
|
|
7
7
|
DATAPATH = Path(__file__).parent.joinpath("data")
|
8
8
|
DATAOUT = Path("data/L4D2")
|
9
|
+
DATAOUT.mkdir(parents=True, exist_ok=True)
|
9
10
|
if not Path(DATAOUT / "l4d2.json").exists():
|
10
11
|
logger.info("文件 l4d2.json 不存在,已创建并初始化为 {}")
|
11
12
|
Path(DATAOUT / "l4d2.json").write_text("{}", encoding="utf-8")
|
12
|
-
print(DATAOUT.absolute())
|
13
13
|
server_all_path = DATAOUT / "l4d2"
|
14
14
|
server_all_path.mkdir(parents=True, exist_ok=True)
|
15
15
|
|
@@ -28,7 +28,7 @@
|
|
28
28
|
},
|
29
29
|
{
|
30
30
|
"name": "l4全服",
|
31
|
-
"desc": "返回可以查询的所有服务器组
|
31
|
+
"desc": "返回可以查询的所有服务器组",
|
32
32
|
"eg": "/l4全服",
|
33
33
|
"need_ck": false,
|
34
34
|
"need_sk": false,
|
@@ -36,43 +36,6 @@
|
|
36
36
|
}
|
37
37
|
]
|
38
38
|
},
|
39
|
-
"电信服anne服务": {
|
40
|
-
"desc": "电信anne服相关服务",
|
41
|
-
"data": [
|
42
|
-
{
|
43
|
-
"name": "Banne xx",
|
44
|
-
"desc": "绑定昵称/steamid",
|
45
|
-
"eg": "/Banne 爱丽数码",
|
46
|
-
"need_ck": false,
|
47
|
-
"need_sk": false,
|
48
|
-
"need_admin": false
|
49
|
-
},
|
50
|
-
{
|
51
|
-
"name": "Ranne(玩家)",
|
52
|
-
"desc": "查询anne个人信息,没有参数查自己",
|
53
|
-
"eg": "/Ranne 爱丽数码",
|
54
|
-
"need_ck": false,
|
55
|
-
"need_sk": false,
|
56
|
-
"need_admin": false
|
57
|
-
},
|
58
|
-
{
|
59
|
-
"name": "Sanne(玩家)",
|
60
|
-
"desc": "按昵称查询anne玩家信息",
|
61
|
-
"eg": "/Sanne 爱丽数码",
|
62
|
-
"need_ck": false,
|
63
|
-
"need_sk": false,
|
64
|
-
"need_admin": false
|
65
|
-
},
|
66
|
-
{
|
67
|
-
"name": "Danne(玩家)",
|
68
|
-
"desc": "删除anne玩家信息",
|
69
|
-
"eg": "/Danne 爱丽数码",
|
70
|
-
"need_ck": false,
|
71
|
-
"need_sk": false,
|
72
|
-
"need_admin": false
|
73
|
-
}
|
74
|
-
]
|
75
|
-
},
|
76
39
|
"管理员服务": {
|
77
40
|
"desc": "管理可以使用的指令",
|
78
41
|
"data": [
|
@@ -83,7 +46,7 @@
|
|
83
46
|
"need_ck": false,
|
84
47
|
"need_sk": false,
|
85
48
|
"need_admin": true
|
86
|
-
},
|
49
|
+
},
|
87
50
|
{
|
88
51
|
"name": "l4地图上传",
|
89
52
|
"desc": "进入交互上传地图文件",
|
@@ -1,8 +1,8 @@
|
|
1
|
+
import json
|
1
2
|
from pathlib import Path
|
2
3
|
from typing import Dict, Union
|
3
4
|
|
4
5
|
import aiofiles
|
5
|
-
from msgspec import json as msgjson
|
6
6
|
from PIL import Image
|
7
7
|
|
8
8
|
from ..config import ICONPATH
|
@@ -10,18 +10,16 @@ from ..l4_image.convert import core_font
|
|
10
10
|
from ..l4_image.model import PluginHelp
|
11
11
|
from .draw import get_help
|
12
12
|
|
13
|
-
__version__ = "1.0.
|
13
|
+
__version__ = "1.0.8"
|
14
14
|
TEXT_PATH = Path(__file__).parent / "texture2d"
|
15
15
|
HELP_DATA = Path(__file__).parent / "Help.json"
|
16
16
|
|
17
17
|
|
18
18
|
async def get_help_data() -> Union[Dict[str, PluginHelp], None]:
|
19
19
|
if HELP_DATA.exists():
|
20
|
-
async with aiofiles.open(HELP_DATA, "
|
21
|
-
|
22
|
-
|
23
|
-
type=Dict[str, PluginHelp],
|
24
|
-
)
|
20
|
+
async with aiofiles.open(HELP_DATA, "r", encoding="utf-8") as file:
|
21
|
+
content = await file.read()
|
22
|
+
return json.loads(content)
|
25
23
|
return None
|
26
24
|
|
27
25
|
|
@@ -45,7 +45,7 @@ async def server_ip_pic(server_dict: List[OutServer]):
|
|
45
45
|
key=lambda x: x.score,
|
46
46
|
reverse=True,
|
47
47
|
)[:max_number]
|
48
|
-
|
48
|
+
logger.debug(sorted_players)
|
49
49
|
server_info["player"] = sorted_players
|
50
50
|
else:
|
51
51
|
server_info["player"] = []
|
@@ -88,18 +88,3 @@ async def get_server_img(plugins: List[OutServer]) -> Optional[bytes]:
|
|
88
88
|
except Exception as e:
|
89
89
|
logger.warning(f"Error in get_help_img: {e}")
|
90
90
|
return None
|
91
|
-
|
92
|
-
|
93
|
-
# async def server_group_ip_pic(msg_list: List[ServerGroup]) -> bytes:
|
94
|
-
# """
|
95
|
-
# 输入一个群组字典列表,输出图片
|
96
|
-
# msg_dict:folder/name/map_/players/max_players/Players/[Name]
|
97
|
-
# """
|
98
|
-
# template = env.get_template("group_ip.html")
|
99
|
-
# html = await template.render_async(plugins=msg_list)
|
100
|
-
# return await html_to_pic(
|
101
|
-
# html=html,
|
102
|
-
# wait=0,
|
103
|
-
# viewport={"width": 1100, "height": 800},
|
104
|
-
# template_path=f"file://{template_path.absolute()}",
|
105
|
-
# )
|
@@ -155,9 +155,8 @@ def draw_text_by_line(
|
|
155
155
|
y_add = math.ceil(1.3 * h) if line_space is None else math.ceil(h + line_space)
|
156
156
|
draw = ImageDraw.Draw(img)
|
157
157
|
row = "" # 存储本行文字
|
158
|
-
length = 0
|
158
|
+
length = 0
|
159
159
|
for character in text:
|
160
|
-
# 获取当前字符的宽度
|
161
160
|
if hasattr(font, "getsize"):
|
162
161
|
w, h = font.getsize(character) # type: ignore
|
163
162
|
else:
|
@@ -1,54 +1,61 @@
|
|
1
1
|
import random
|
2
|
-
from typing import Dict, List, Optional,
|
2
|
+
from typing import Dict, List, Optional, cast
|
3
3
|
|
4
4
|
from nonebot.log import logger
|
5
5
|
from nonebot_plugin_alconna import UniMessage
|
6
6
|
|
7
|
-
from ..config import server_all_path
|
8
|
-
from ..l4_image import msg_to_image
|
7
|
+
from ..config import config, server_all_path
|
9
8
|
from ..utils.api.models import AllServer, NserverOut
|
10
9
|
from ..utils.api.request import L4API
|
11
10
|
from ..utils.utils import split_maohao
|
12
|
-
from .draw_msg import
|
11
|
+
from .draw_msg import draw_one_ip, get_much_server
|
12
|
+
from .utils import (
|
13
|
+
_build_message,
|
14
|
+
_filter_servers,
|
15
|
+
_format_players,
|
16
|
+
_get_server_json,
|
17
|
+
_handle_group_info,
|
18
|
+
_handle_single_server,
|
19
|
+
get_single_server_info,
|
20
|
+
)
|
13
21
|
|
14
22
|
try:
|
15
23
|
import ujson as json
|
16
24
|
except ImportError:
|
17
25
|
import json
|
18
26
|
|
19
|
-
from ..config import config
|
20
27
|
|
21
28
|
# 获取全部服务器信息
|
22
29
|
ALLHOST: Dict[str, List[NserverOut]] = {}
|
23
30
|
COMMAND = set()
|
24
31
|
|
25
32
|
|
26
|
-
async def get_all_server_detail():
|
33
|
+
async def get_all_server_detail() -> str:
|
27
34
|
"""
|
28
35
|
获取所有服务器的详细信息。
|
29
36
|
|
30
|
-
Args:
|
31
|
-
无
|
32
|
-
|
33
37
|
Returns:
|
34
38
|
str: 包含所有服务器详细信息的字符串。
|
35
|
-
|
36
39
|
"""
|
37
40
|
out_list: List[AllServer] = []
|
38
41
|
for group in ALLHOST:
|
39
42
|
msg_list = await get_group_detail(group)
|
40
|
-
if msg_list
|
43
|
+
if not msg_list:
|
41
44
|
continue
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
if msg["server"].max_players != 0
|
49
|
-
|
50
|
-
|
51
|
-
|
45
|
+
|
46
|
+
active_server = sum(1 for msg in msg_list if msg["server"].max_players != 0)
|
47
|
+
max_server = len(msg_list)
|
48
|
+
active_player = sum(
|
49
|
+
msg["server"].player_count
|
50
|
+
for msg in msg_list
|
51
|
+
if msg["server"].max_players != 0
|
52
|
+
)
|
53
|
+
max_player = sum(
|
54
|
+
msg["server"].max_players
|
55
|
+
for msg in msg_list
|
56
|
+
if msg["server"].max_players != 0
|
57
|
+
)
|
58
|
+
|
52
59
|
data = {
|
53
60
|
"command": group,
|
54
61
|
"active_server": active_server,
|
@@ -58,14 +65,12 @@ async def get_all_server_detail():
|
|
58
65
|
}
|
59
66
|
out_list.append(cast(AllServer, data))
|
60
67
|
|
61
|
-
#
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
continue
|
68
|
-
return out_msg
|
68
|
+
# 输出服务器信息文本
|
69
|
+
return "\n".join(
|
70
|
+
f"{one['command']} | 服务器{one['active_server']}/{one['max_server']} | 玩家{one['active_player']}/{one['max_player']}"
|
71
|
+
for one in out_list
|
72
|
+
if one["max_player"]
|
73
|
+
)
|
69
74
|
|
70
75
|
|
71
76
|
async def get_server_detail(
|
@@ -80,20 +85,18 @@ async def get_server_detail(
|
|
80
85
|
command (str): 服务器组名。
|
81
86
|
_id (Optional[str], optional): 服务器ID。默认为None。
|
82
87
|
is_img (bool, optional): 是否返回图片格式的信息。默认为True。
|
83
|
-
return_host_port (bool, optional): 是否返回host和port值。默认为False。
|
84
88
|
|
85
89
|
Returns:
|
86
|
-
Union[
|
87
|
-
|
88
|
-
否则返回服务器详细信息(图片格式返回bytes,文本格式返回str);
|
89
|
-
未找到服务器组返回None。
|
90
|
+
Union[UniMessage, None]:
|
91
|
+
返回服务器详细信息(图片或文本格式),未找到服务器组或服务器时返回None。
|
90
92
|
"""
|
91
|
-
server_json = _get_server_json(command)
|
93
|
+
server_json = _get_server_json(command, ALLHOST)
|
92
94
|
logger.info(server_json)
|
93
95
|
if server_json is None:
|
94
96
|
logger.warning("未找到这个组")
|
95
97
|
return None
|
96
98
|
|
99
|
+
# 输出组服务器信息
|
97
100
|
if _id is None:
|
98
101
|
return await _handle_group_info(server_json, command, is_img)
|
99
102
|
|
@@ -112,99 +115,10 @@ async def get_server_detail(
|
|
112
115
|
return None
|
113
116
|
|
114
117
|
|
115
|
-
def _get_server_json(command: str) -> Optional[list]:
|
116
|
-
"""
|
117
|
-
根据命令获取服务器JSON列表
|
118
|
-
|
119
|
-
Args:
|
120
|
-
command (str): 服务器组名
|
121
|
-
|
122
|
-
Returns:
|
123
|
-
Optional[list]: 服务器JSON列表,未找到组时返回None
|
124
|
-
"""
|
125
|
-
if command:
|
126
|
-
return ALLHOST.get(command)
|
127
|
-
server_json = []
|
128
|
-
for servers in ALLHOST.values():
|
129
|
-
server_json.extend(servers)
|
130
|
-
return server_json
|
131
|
-
|
132
|
-
|
133
|
-
async def _handle_group_info(
|
134
|
-
server_json: list,
|
135
|
-
command: str,
|
136
|
-
is_img: bool,
|
137
|
-
) -> Union[bytes, str, None]:
|
138
|
-
"""
|
139
|
-
处理服务器组信息请求
|
140
|
-
|
141
|
-
Args:
|
142
|
-
server_json (list): 服务器JSON列表
|
143
|
-
command (str): 服务器组名
|
144
|
-
is_img (bool): 是否返回图片格式
|
145
|
-
|
146
|
-
Returns:
|
147
|
-
Union[bytes, list, None]: 图片格式返回bytes,否则返回服务器列表
|
148
|
-
"""
|
149
|
-
logger.info(f"正在请求组服务器信息 {command}")
|
150
|
-
server_dict = await get_much_server(server_json, command)
|
151
|
-
if is_img:
|
152
|
-
return await msg_to_image(server_dict)
|
153
|
-
return str(server_dict)
|
154
|
-
|
155
|
-
|
156
|
-
async def get_single_server_info(
|
157
|
-
server_json: list,
|
158
|
-
_id: str,
|
159
|
-
) -> Optional[Tuple[str, int]]:
|
160
|
-
"""
|
161
|
-
获取单个服务器的host和port信息
|
162
|
-
|
163
|
-
Args:
|
164
|
-
server_json (list): 服务器JSON列表
|
165
|
-
_id (str): 服务器ID
|
166
|
-
|
167
|
-
Returns:
|
168
|
-
Optional[Tuple[str, int]]: 返回(host, port)元组,未找到返回None
|
169
|
-
"""
|
170
|
-
logger.info("正在获取单服务器信息")
|
171
|
-
for i in server_json:
|
172
|
-
if str(_id) == str(i["id"]):
|
173
|
-
return i["host"], i["port"]
|
174
|
-
return None
|
175
|
-
|
176
|
-
|
177
|
-
async def _handle_single_server(
|
178
|
-
server_json: list,
|
179
|
-
_id: str,
|
180
|
-
is_img: bool,
|
181
|
-
) -> Union[bytes, str, None]:
|
182
|
-
"""
|
183
|
-
处理单个服务器信息请求
|
184
|
-
|
185
|
-
Args:
|
186
|
-
server_json (list): 服务器JSON列表
|
187
|
-
_id (str): 服务器ID
|
188
|
-
is_img (bool): 是否返回图片格式
|
189
|
-
|
190
|
-
Returns:
|
191
|
-
Union[bytes, str, None]: 找到服务器时返回信息,否则返回None
|
192
|
-
"""
|
193
|
-
server_info = await get_single_server_info(server_json, _id)
|
194
|
-
if server_info is None:
|
195
|
-
return None
|
196
|
-
|
197
|
-
host, port = server_info
|
198
|
-
out_msg = await draw_one_ip(host, port)
|
199
|
-
if is_img:
|
200
|
-
return cast(bytes, out_msg)
|
201
|
-
return out_msg
|
202
|
-
|
203
|
-
|
204
118
|
async def get_group_detail(
|
205
119
|
command: str,
|
206
120
|
):
|
207
|
-
server_json =
|
121
|
+
server_json = _get_server_json(command, ALLHOST)
|
208
122
|
logger.info(server_json)
|
209
123
|
if server_json is None:
|
210
124
|
logger.warning("未找到这个组")
|
@@ -222,7 +136,6 @@ async def get_ip_server(ip: str):
|
|
222
136
|
# 以下是重载ip
|
223
137
|
def reload_ip():
|
224
138
|
global COMMAND
|
225
|
-
# print("正在读取json文件")
|
226
139
|
group_ip = []
|
227
140
|
for item in server_all_path.iterdir():
|
228
141
|
if item.is_file() and item.name.endswith("json"):
|
@@ -266,74 +179,8 @@ async def tj_request(command: str = "云", tj="tj"):
|
|
266
179
|
player_msg = ""
|
267
180
|
right_ip = []
|
268
181
|
|
269
|
-
async def _filter_servers(servers: list, tj_mode: str) -> list:
|
270
|
-
"""筛选符合条件的服务器
|
271
|
-
Args:
|
272
|
-
servers: 服务器列表
|
273
|
-
tj_mode: 筛选模式('tj'或'zl')
|
274
|
-
Returns:
|
275
|
-
符合条件的服务器列表
|
276
|
-
"""
|
277
|
-
filtered = []
|
278
|
-
for i in servers:
|
279
|
-
ser_list = await L4API.a2s_info([(i["host"], i["port"])], is_player=True)
|
280
|
-
if not ser_list:
|
281
|
-
continue
|
282
|
-
|
283
|
-
srv = ser_list[0][0]
|
284
|
-
players = ser_list[0][1]
|
285
|
-
|
286
|
-
if tj_mode == "tj" and map_type in srv.map_name:
|
287
|
-
score = sum(p.score for p in players[:4])
|
288
|
-
t = srv.map_name.split("[")[-1].split("特")[0]
|
289
|
-
if t.isdigit() and int(t) * 50 < score:
|
290
|
-
logger.info(
|
291
|
-
f"符合TJ条件的服务器: {i['host']}:{i['port']}, 地图: {srv.map_name}, 分数: {score}",
|
292
|
-
)
|
293
|
-
filtered.append(i)
|
294
|
-
elif tj_mode == "zl" and map_type in srv.map_name and len(players) <= 4:
|
295
|
-
logger.info(
|
296
|
-
f"符合ZL条件的服务器: {i['host']}:{i['port']}, 地图: {srv.map_name}, 玩家数: {len(players)}",
|
297
|
-
)
|
298
|
-
filtered.append(i)
|
299
|
-
return filtered
|
300
|
-
|
301
|
-
async def _format_players(player_list: list) -> str:
|
302
|
-
"""格式化玩家信息
|
303
|
-
Args:
|
304
|
-
player_list: 玩家对象列表
|
305
|
-
Returns:
|
306
|
-
格式化后的玩家信息字符串
|
307
|
-
"""
|
308
|
-
durations = [await convert_duration(p.duration) for p in player_list]
|
309
|
-
max_duration_len = max(len(str(d)) for d in durations)
|
310
|
-
max_score_len = max(len(str(p.score)) for p in player_list)
|
311
|
-
return "\n".join(
|
312
|
-
f"[{p.score:>{max_score_len}}] | {durations[i]:^{max_duration_len}} | {p.name[0]}***{p.name[-1]}"
|
313
|
-
for i, p in enumerate(player_list)
|
314
|
-
)
|
315
|
-
|
316
|
-
def _build_message(srv_info, players_msg: str, selected_srv: dict) -> str:
|
317
|
-
"""构建服务器信息消息
|
318
|
-
Args:
|
319
|
-
srv_info: 服务器信息对象
|
320
|
-
players_msg: 格式化后的玩家信息
|
321
|
-
selected_srv: 选中的服务器信息
|
322
|
-
Returns:
|
323
|
-
完整的消息字符串
|
324
|
-
"""
|
325
|
-
msg = f"""*{srv_info.server_name}*
|
326
|
-
游戏: {srv_info.folder}
|
327
|
-
地图: {srv_info.map_name}
|
328
|
-
人数: {srv_info.player_count}/{srv_info.max_players}"""
|
329
|
-
if srv_info.ping is not None:
|
330
|
-
msg += f"\nping: {srv_info.ping * 1000:.0f}ms\n{players_msg}"
|
331
|
-
if config.l4_show_ip:
|
332
|
-
msg += f"\nconnect {selected_srv['host']}:{selected_srv['port']}"
|
333
|
-
return msg
|
334
|
-
|
335
182
|
try:
|
336
|
-
right_ip = await _filter_servers(server_json, tj)
|
183
|
+
right_ip = await _filter_servers(server_json, tj, map_type)
|
337
184
|
|
338
185
|
if not right_ip:
|
339
186
|
logger.warning("没有找到符合条件的服务器")
|
@@ -356,8 +203,38 @@ async def tj_request(command: str = "云", tj="tj"):
|
|
356
203
|
else:
|
357
204
|
player_msg = "服务器感觉很安静啊"
|
358
205
|
|
359
|
-
return _build_message(one_server, player_msg, s)
|
206
|
+
return _build_message(one_server, player_msg, s, config)
|
360
207
|
|
361
208
|
except Exception as e:
|
362
209
|
logger.error(f"tj_request error: {e}")
|
363
210
|
return "获取服务器信息时出错"
|
211
|
+
|
212
|
+
|
213
|
+
async def server_find(
|
214
|
+
command: str = "云",
|
215
|
+
_id: Optional[str] = None,
|
216
|
+
is_img: bool = True,
|
217
|
+
):
|
218
|
+
server_json = _get_server_json(command, ALLHOST)
|
219
|
+
logger.info(server_json)
|
220
|
+
if server_json is None:
|
221
|
+
logger.warning("未找到这个组")
|
222
|
+
return None
|
223
|
+
|
224
|
+
# 输出组服务器信息
|
225
|
+
if _id is None:
|
226
|
+
return await _handle_group_info(server_json, command, is_img)
|
227
|
+
|
228
|
+
_ip = await get_single_server_info(server_json, _id)
|
229
|
+
if _ip is None:
|
230
|
+
logger.warning("未找到这个服务器")
|
231
|
+
return None
|
232
|
+
|
233
|
+
out_msg = await _handle_single_server(server_json, _id, is_img)
|
234
|
+
if isinstance(out_msg, bytes):
|
235
|
+
return UniMessage.image(raw=out_msg) + UniMessage.text(
|
236
|
+
f"connect {_ip[0]}:{_ip[1]}",
|
237
|
+
)
|
238
|
+
if isinstance(out_msg, str):
|
239
|
+
return UniMessage.text(out_msg)
|
240
|
+
return None
|
@@ -0,0 +1,176 @@
|
|
1
|
+
from typing import Dict, List, Optional, Tuple, Union, cast
|
2
|
+
|
3
|
+
from nonebot.log import logger
|
4
|
+
|
5
|
+
from ..l4_image import msg_to_image
|
6
|
+
from ..utils.api.models import NserverOut
|
7
|
+
from ..utils.api.request import L4API
|
8
|
+
from .draw_msg import convert_duration, draw_one_ip, get_much_server
|
9
|
+
|
10
|
+
|
11
|
+
def _get_server_json(
|
12
|
+
command: str,
|
13
|
+
allhost: Dict[str, List[NserverOut]],
|
14
|
+
) -> Optional[list]:
|
15
|
+
"""
|
16
|
+
根据命令获取服务器JSON列表
|
17
|
+
|
18
|
+
Args:
|
19
|
+
command (str): 服务器组名
|
20
|
+
ALLHOST (Dict): 全局服务器字典
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
Optional[list]: 服务器JSON列表,未找到组时返回None
|
24
|
+
"""
|
25
|
+
if command:
|
26
|
+
return allhost.get(command)
|
27
|
+
server_json = []
|
28
|
+
for servers in allhost.values():
|
29
|
+
server_json.extend(servers)
|
30
|
+
return server_json
|
31
|
+
|
32
|
+
|
33
|
+
async def _handle_group_info(
|
34
|
+
server_json: list,
|
35
|
+
command: str,
|
36
|
+
is_img: bool,
|
37
|
+
):
|
38
|
+
"""
|
39
|
+
处理服务器组信息请求
|
40
|
+
|
41
|
+
Args:
|
42
|
+
server_json (list): 服务器JSON列表
|
43
|
+
command (str): 服务器组名
|
44
|
+
is_img (bool): 是否返回图片格式
|
45
|
+
|
46
|
+
Returns:
|
47
|
+
Union[bytes, list, None]: 图片格式返回bytes,否则返回服务器列表
|
48
|
+
"""
|
49
|
+
logger.info(f"正在请求组服务器信息 {command}")
|
50
|
+
server_dict = await get_much_server(server_json, command)
|
51
|
+
if is_img:
|
52
|
+
return await msg_to_image(server_dict)
|
53
|
+
return server_dict
|
54
|
+
|
55
|
+
|
56
|
+
async def get_single_server_info(
|
57
|
+
server_json: list,
|
58
|
+
_id: str,
|
59
|
+
) -> Optional[Tuple[str, int]]:
|
60
|
+
"""
|
61
|
+
获取单个服务器的host和port信息
|
62
|
+
|
63
|
+
Args:
|
64
|
+
server_json (list): 服务器JSON列表
|
65
|
+
_id (str): 服务器ID
|
66
|
+
|
67
|
+
Returns:
|
68
|
+
Optional[Tuple[str, int]]: 返回(host, port)元组,未找到返回None
|
69
|
+
"""
|
70
|
+
logger.info("正在获取单服务器信息")
|
71
|
+
for i in server_json:
|
72
|
+
if str(_id) == str(i["id"]):
|
73
|
+
return i["host"], i["port"]
|
74
|
+
return None
|
75
|
+
|
76
|
+
|
77
|
+
async def _handle_single_server(
|
78
|
+
server_json: list,
|
79
|
+
_id: str,
|
80
|
+
is_img: bool,
|
81
|
+
) -> Union[bytes, str, None]:
|
82
|
+
"""
|
83
|
+
处理单个服务器信息请求
|
84
|
+
|
85
|
+
Args:
|
86
|
+
server_json (list): 服务器JSON列表
|
87
|
+
_id (str): 服务器ID
|
88
|
+
is_img (bool): 是否返回图片格式
|
89
|
+
|
90
|
+
Returns:
|
91
|
+
Union[bytes, str, None]: 找到服务器时返回信息,否则返回None
|
92
|
+
"""
|
93
|
+
server_info = await get_single_server_info(server_json, _id)
|
94
|
+
if server_info is None:
|
95
|
+
return None
|
96
|
+
|
97
|
+
host, port = server_info
|
98
|
+
out_msg = await draw_one_ip(host, port)
|
99
|
+
if is_img:
|
100
|
+
return cast(bytes, out_msg)
|
101
|
+
return out_msg
|
102
|
+
|
103
|
+
|
104
|
+
async def _filter_servers(
|
105
|
+
servers: list,
|
106
|
+
tj_mode: str,
|
107
|
+
map_type: str = "普通药役",
|
108
|
+
) -> list:
|
109
|
+
"""筛选符合条件的服务器
|
110
|
+
Args:
|
111
|
+
servers: 服务器列表
|
112
|
+
tj_mode: 筛选模式('tj'或'zl')
|
113
|
+
map_type: 地图类型筛选条件
|
114
|
+
Returns:
|
115
|
+
符合条件的服务器列表
|
116
|
+
"""
|
117
|
+
filtered = []
|
118
|
+
for i in servers:
|
119
|
+
ser_list = await L4API.a2s_info([(i["host"], i["port"])], is_player=True)
|
120
|
+
if not ser_list:
|
121
|
+
continue
|
122
|
+
|
123
|
+
srv = ser_list[0][0]
|
124
|
+
players = ser_list[0][1]
|
125
|
+
|
126
|
+
if tj_mode == "tj" and map_type in srv.map_name:
|
127
|
+
score = sum(p.score for p in players[:4])
|
128
|
+
t = srv.map_name.split("[")[-1].split("特")[0]
|
129
|
+
if t.isdigit() and int(t) * 50 < score:
|
130
|
+
logger.info(
|
131
|
+
f"符合TJ条件的服务器: {i['host']}:{i['port']}, 地图: {srv.map_name}, 分数: {score}",
|
132
|
+
)
|
133
|
+
filtered.append(i)
|
134
|
+
elif tj_mode == "zl" and map_type in srv.map_name and len(players) <= 4:
|
135
|
+
logger.info(
|
136
|
+
f"符合ZL条件的服务器: {i['host']}:{i['port']}, 地图: {srv.map_name}, 玩家数: {len(players)}",
|
137
|
+
)
|
138
|
+
filtered.append(i)
|
139
|
+
return filtered
|
140
|
+
|
141
|
+
|
142
|
+
async def _format_players(player_list: list) -> str:
|
143
|
+
"""格式化玩家信息
|
144
|
+
Args:
|
145
|
+
player_list: 玩家对象列表
|
146
|
+
Returns:
|
147
|
+
格式化后的玩家信息字符串
|
148
|
+
"""
|
149
|
+
durations = [await convert_duration(p.duration) for p in player_list]
|
150
|
+
max_duration_len = max(len(str(d)) for d in durations)
|
151
|
+
max_score_len = max(len(str(p.score)) for p in player_list)
|
152
|
+
return "\n".join(
|
153
|
+
f"[{p.score:>{max_score_len}}] | {durations[i]:^{max_duration_len}} | {p.name[0]}***{p.name[-1]}"
|
154
|
+
for i, p in enumerate(player_list)
|
155
|
+
)
|
156
|
+
|
157
|
+
|
158
|
+
def _build_message(srv_info, players_msg: str, selected_srv: dict, config) -> str:
|
159
|
+
"""构建服务器信息消息
|
160
|
+
Args:
|
161
|
+
srv_info: 服务器信息对象
|
162
|
+
players_msg: 格式化后的玩家信息
|
163
|
+
selected_srv: 选中的服务器信息
|
164
|
+
config: 配置对象
|
165
|
+
Returns:
|
166
|
+
完整的消息字符串
|
167
|
+
"""
|
168
|
+
msg = f"""*{srv_info.server_name}*
|
169
|
+
游戏: {srv_info.folder}
|
170
|
+
地图: {srv_info.map_name}
|
171
|
+
人数: {srv_info.player_count}/{srv_info.max_players}"""
|
172
|
+
if srv_info.ping is not None:
|
173
|
+
msg += f"\nping: {srv_info.ping * 1000:.0f}ms\n{players_msg}"
|
174
|
+
if config.l4_show_ip:
|
175
|
+
msg += f"\nconnect {selected_srv['host']}:{selected_srv['port']}"
|
176
|
+
return msg
|
@@ -9,12 +9,11 @@ import a2s
|
|
9
9
|
import aiofiles
|
10
10
|
import ujson as js
|
11
11
|
import ujson as json
|
12
|
-
from bs4 import BeautifulSoup
|
12
|
+
from bs4 import BeautifulSoup, Tag
|
13
13
|
from httpx import AsyncClient
|
14
|
+
from nonebot.log import logger
|
14
15
|
|
15
16
|
from ...config import config
|
16
|
-
|
17
|
-
# from nonebot.log import logger
|
18
17
|
from ..utils import split_maohao
|
19
18
|
from .api import AnnePlayerApi, AnneSearchApi, anne_ban
|
20
19
|
from .models import (
|
@@ -42,6 +41,23 @@ class L4D2Api:
|
|
42
41
|
"Content-Type": "application/x-www-form-urlencoded",
|
43
42
|
}
|
44
43
|
|
44
|
+
def safe_select(self, element: Optional[Tag], selector: str) -> List[Any]:
|
45
|
+
"""安全地调用 select 方法"""
|
46
|
+
if isinstance(element, Tag):
|
47
|
+
return element.select(selector)
|
48
|
+
return []
|
49
|
+
|
50
|
+
def safe_find_all(
|
51
|
+
self,
|
52
|
+
element: Optional[Tag],
|
53
|
+
tag: str,
|
54
|
+
class_: str = "",
|
55
|
+
) -> List[Any]:
|
56
|
+
"""安全地调用 find_all 方法"""
|
57
|
+
if isinstance(element, Tag):
|
58
|
+
return element.find_all(tag, class_=class_)
|
59
|
+
return []
|
60
|
+
|
45
61
|
async def a2s_info(
|
46
62
|
self,
|
47
63
|
ip_list: List[Tuple[str, int]],
|
@@ -53,28 +69,29 @@ class L4D2Api:
|
|
53
69
|
msg_list: List[
|
54
70
|
Tuple[Union[a2s.SourceInfo[str], a2s.GoldSrcInfo[str]], List[a2s.Player]]
|
55
71
|
] = []
|
56
|
-
sorted_msg_list = []
|
57
|
-
tasks = [] # 用来保存异步任务
|
58
|
-
if ip_list != []:
|
59
|
-
for index, i in enumerate(ip_list):
|
60
|
-
try:
|
61
|
-
tasks.append(
|
62
|
-
asyncio.create_task(
|
63
|
-
self.process_message(
|
64
|
-
i,
|
65
|
-
index,
|
66
|
-
is_server,
|
67
|
-
is_player,
|
68
|
-
),
|
69
|
-
),
|
70
|
-
)
|
71
|
-
except ValueError:
|
72
|
-
continue # 处理异常情况
|
73
72
|
|
74
|
-
|
75
|
-
|
73
|
+
if ip_list:
|
74
|
+
tasks = [
|
75
|
+
asyncio.create_task(
|
76
|
+
self.process_message(ip, index, is_server, is_player),
|
77
|
+
)
|
78
|
+
for index, ip in enumerate(ip_list)
|
79
|
+
]
|
76
80
|
|
77
|
-
|
81
|
+
try:
|
82
|
+
results = await asyncio.gather(*tasks)
|
83
|
+
msg_list = [r for r in results if r is not None]
|
84
|
+
except Exception as e:
|
85
|
+
logger.error(f"获取服务器信息时发生错误: {e}")
|
86
|
+
|
87
|
+
# 使用稳定的排序方式,避免服务器频繁变动位置
|
88
|
+
return sorted(
|
89
|
+
msg_list,
|
90
|
+
key=lambda x: (
|
91
|
+
getattr(x[0], "steam_id", float("inf")) is None,
|
92
|
+
getattr(x[0], "steam_id", float("inf")),
|
93
|
+
),
|
94
|
+
)
|
78
95
|
|
79
96
|
async def process_message(
|
80
97
|
self,
|
@@ -235,14 +252,12 @@ class L4D2Api:
|
|
235
252
|
tag_path = Path(Path(config.l4_path) / f"l4d2/{tag}.json")
|
236
253
|
|
237
254
|
async with aiofiles.open(tag_path, "w", encoding="utf-8") as f:
|
238
|
-
print(Path(Path(config.l4_path) / f"l4d2/{tag}.json"))
|
239
255
|
up_data = {}
|
240
256
|
for server in server_list:
|
241
257
|
new_dict = {}
|
242
258
|
new_dict["id"] = int(server.index) + 1
|
243
259
|
new_dict["ip"] = server.host + ":" + str(server.port)
|
244
260
|
up_data.update(new_dict)
|
245
|
-
print(up_data)
|
246
261
|
json.dump(up_data, f, ensure_ascii=False, indent=4)
|
247
262
|
return server_list
|
248
263
|
|
@@ -277,7 +292,7 @@ class L4D2Api:
|
|
277
292
|
"last_time": td_tags,
|
278
293
|
},
|
279
294
|
)
|
280
|
-
|
295
|
+
logger.debug(server_list)
|
281
296
|
return cast(List[AnneSearch], server_list)
|
282
297
|
|
283
298
|
async def get_anne_playerdetail(self, steamid: str):
|
@@ -298,98 +313,101 @@ class L4D2Api:
|
|
298
313
|
)
|
299
314
|
if tbody is None:
|
300
315
|
return None
|
301
|
-
|
316
|
+
|
317
|
+
def get_table_dict(table, keys):
|
318
|
+
trs = table.select("tr")
|
319
|
+
return {
|
320
|
+
key: trs[i].select("td")[1].text.strip() for i, key in enumerate(keys)
|
321
|
+
}
|
322
|
+
|
323
|
+
kill_tag = cast(Tag, tbody).find(
|
302
324
|
"div",
|
303
325
|
class_="card-body worldmap d-flex flex-column justify-content-center text-center",
|
304
326
|
)
|
305
327
|
|
306
|
-
tbody_tags =
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
"
|
321
|
-
"
|
322
|
-
"
|
323
|
-
"
|
324
|
-
"
|
325
|
-
|
326
|
-
|
327
|
-
"
|
328
|
-
"
|
329
|
-
"
|
330
|
-
"
|
331
|
-
"
|
332
|
-
"
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
"
|
338
|
-
"
|
339
|
-
"
|
340
|
-
"
|
341
|
-
"
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
"
|
346
|
-
"
|
347
|
-
"
|
348
|
-
"
|
349
|
-
"
|
350
|
-
"
|
351
|
-
"
|
352
|
-
|
353
|
-
|
354
|
-
"
|
355
|
-
"
|
356
|
-
"
|
357
|
-
"
|
358
|
-
"
|
359
|
-
"
|
360
|
-
"
|
361
|
-
"
|
362
|
-
|
363
|
-
|
364
|
-
"
|
365
|
-
"
|
366
|
-
"
|
367
|
-
"
|
368
|
-
"
|
369
|
-
"
|
370
|
-
"
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
"hunter_success": inf_tag.select("tr")[4].select("td")[1].text.strip(),
|
381
|
-
"tank_damage": inf_tag.select("tr")[5].select("td")[1].text.strip(),
|
382
|
-
"charger_multiple": inf_tag.select("tr")[6].select("td")[1].text.strip(),
|
383
|
-
}
|
328
|
+
tbody_tags = []
|
329
|
+
if isinstance(tbody, Tag):
|
330
|
+
tbody_tags = tbody.find_all(
|
331
|
+
"table",
|
332
|
+
class_="table content-table-noborder text-left",
|
333
|
+
)
|
334
|
+
if len(tbody_tags) < 6:
|
335
|
+
return None
|
336
|
+
|
337
|
+
info_keys = ["name", "avatar", "steamid", "playtime", "lasttime"]
|
338
|
+
detail_keys = [
|
339
|
+
"rank",
|
340
|
+
"source",
|
341
|
+
"avg_source",
|
342
|
+
"kills",
|
343
|
+
"kills_people",
|
344
|
+
"headshots",
|
345
|
+
"avg_headshots",
|
346
|
+
"map_play",
|
347
|
+
]
|
348
|
+
error_keys = [
|
349
|
+
"mistake_shout",
|
350
|
+
"kill_friend",
|
351
|
+
"down_friend",
|
352
|
+
"abandon_friend",
|
353
|
+
"put_into",
|
354
|
+
"agitate_witch",
|
355
|
+
]
|
356
|
+
inf_avg_keys = [
|
357
|
+
"avg_smoker",
|
358
|
+
"avg_boomer",
|
359
|
+
"avg_hunter",
|
360
|
+
"avg_charger",
|
361
|
+
"avg_spitter",
|
362
|
+
"avg_jockey",
|
363
|
+
"avg_tank",
|
364
|
+
]
|
365
|
+
sur_keys = [
|
366
|
+
"map_clear",
|
367
|
+
"prefect_into",
|
368
|
+
"get_oil",
|
369
|
+
"ammo_arrange",
|
370
|
+
"adrenaline_give",
|
371
|
+
"pills_give",
|
372
|
+
"first_aid_give",
|
373
|
+
"friend_up",
|
374
|
+
"diss_friend",
|
375
|
+
"save_friend",
|
376
|
+
"protect_friend",
|
377
|
+
"pro_from_smoker",
|
378
|
+
"pro_from_hunter",
|
379
|
+
"pro_from_charger",
|
380
|
+
"pro_from_jockey",
|
381
|
+
"melee_charge",
|
382
|
+
"tank_kill",
|
383
|
+
"witch_instantly_kill",
|
384
|
+
]
|
385
|
+
inf_keys = [
|
386
|
+
"sur_ace",
|
387
|
+
"sur_down",
|
388
|
+
"boommer_hit",
|
389
|
+
"hunter_prefect",
|
390
|
+
"hunter_success",
|
391
|
+
"tank_damage",
|
392
|
+
"charger_multiple",
|
393
|
+
]
|
394
|
+
|
395
|
+
info_dict = get_table_dict(tbody_tags[0], info_keys)
|
396
|
+
detail_dict = get_table_dict(tbody_tags[1], detail_keys)
|
397
|
+
error_dict = get_table_dict(tbody_tags[2], error_keys)
|
398
|
+
inf_avg_dict = get_table_dict(tbody_tags[3], inf_avg_keys)
|
399
|
+
sur_dict = get_table_dict(tbody_tags[4], sur_keys)
|
400
|
+
inf_dict = get_table_dict(tbody_tags[5], inf_keys)
|
401
|
+
|
384
402
|
info_dict = cast(AnnePlayerInfo, info_dict)
|
385
|
-
detail_dict = cast(AnnePlayerDetail,
|
386
|
-
error_dict = cast(AnnePlayerError,
|
403
|
+
detail_dict = cast(AnnePlayerDetail, detail_dict)
|
404
|
+
error_dict = cast(AnnePlayerError, error_dict)
|
387
405
|
inf_avg_dict = cast(AnnePlayerInfAvg, inf_avg_dict)
|
388
406
|
sur_dict = cast(AnnePlayerSur, sur_dict)
|
389
407
|
inf_dict = cast(AnnePlayerInf, inf_dict)
|
390
408
|
|
391
409
|
out_dict = {
|
392
|
-
"kill_msg": kill_tag.text if kill_tag
|
410
|
+
"kill_msg": kill_tag.text.strip() if kill_tag else "",
|
393
411
|
"info": info_dict,
|
394
412
|
"detail": detail_dict,
|
395
413
|
"inf_avg": inf_avg_dict,
|
@@ -0,0 +1,30 @@
|
|
1
|
+
from typing import Union
|
2
|
+
|
3
|
+
from nonebot_plugin_alconna import UniMessage
|
4
|
+
|
5
|
+
|
6
|
+
async def out_msg_out(
|
7
|
+
msg: Union[str, bytes, UniMessage],
|
8
|
+
is_connect: bool = False,
|
9
|
+
host: str = "",
|
10
|
+
port: str = "",
|
11
|
+
):
|
12
|
+
"""
|
13
|
+
统一消息输出函数
|
14
|
+
|
15
|
+
Args:
|
16
|
+
msg: 要输出的消息内容
|
17
|
+
is_connect: 是否为连接消息
|
18
|
+
host: 服务器地址
|
19
|
+
port: 服务器端口
|
20
|
+
"""
|
21
|
+
if isinstance(msg, UniMessage):
|
22
|
+
return await msg.finish()
|
23
|
+
if isinstance(msg, str):
|
24
|
+
await UniMessage.text(msg).finish()
|
25
|
+
if is_connect:
|
26
|
+
out = UniMessage.image(raw=msg) + UniMessage.text(
|
27
|
+
f"connect: {host}:{port}",
|
28
|
+
)
|
29
|
+
return await out.finish()
|
30
|
+
return await UniMessage.image(raw=msg).finish()
|
{nonebot_plugin_l4d2_server-1.0.4.dist-info → nonebot_plugin_l4d2_server-1.0.8.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: nonebot-plugin-l4d2-server
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.8
|
4
4
|
Summary: L4D2 server related operations plugin for NoneBot2
|
5
5
|
Keywords: steam,game,l4d2,nonebot2,plugin
|
6
6
|
Author-Email: Agnes_Digital <Z735803792@163.com>
|
@@ -25,13 +25,13 @@ Requires-Dist: nonebot-plugin-tortoise-orm>=0.1.4
|
|
25
25
|
Requires-Dist: aiohttp>=3.8.4
|
26
26
|
Requires-Dist: jinja2>=3.0.0
|
27
27
|
Requires-Dist: srctools>=2.3.9
|
28
|
-
Requires-Dist: httpx
|
28
|
+
Requires-Dist: httpx>=0.22.0
|
29
29
|
Requires-Dist: msgspec>=0.18.0
|
30
30
|
Requires-Dist: python-a2s>=1.4.1
|
31
31
|
Requires-Dist: ujson>=5.10.0
|
32
32
|
Requires-Dist: lxml>=5.2.2
|
33
33
|
Requires-Dist: rcon>=2.1.0
|
34
|
-
Requires-Dist: pillow>10
|
34
|
+
Requires-Dist: pillow>10.0.0
|
35
35
|
Requires-Dist: bs4>=0.0.2
|
36
36
|
Requires-Dist: rarfile>=4.2
|
37
37
|
Requires-Dist: pyunpack>=0.3
|
{nonebot_plugin_l4d2_server-1.0.4.dist-info → nonebot_plugin_l4d2_server-1.0.8.dist-info}/RECORD
RENAMED
@@ -1,13 +1,13 @@
|
|
1
|
-
nonebot_plugin_l4d2_server-1.0.
|
2
|
-
nonebot_plugin_l4d2_server-1.0.
|
3
|
-
nonebot_plugin_l4d2_server-1.0.
|
4
|
-
nonebot_plugin_l4d2_server-1.0.
|
5
|
-
nonebot_plugin_l4d2_server/__init__.py,sha256=
|
6
|
-
nonebot_plugin_l4d2_server/__main__.py,sha256=
|
7
|
-
nonebot_plugin_l4d2_server/config.py,sha256=
|
1
|
+
nonebot_plugin_l4d2_server-1.0.8.dist-info/METADATA,sha256=oxEFgnJzb8aG9Ouh5q6sjIMpF8TabEOpauUXAwyPxxU,6759
|
2
|
+
nonebot_plugin_l4d2_server-1.0.8.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
|
3
|
+
nonebot_plugin_l4d2_server-1.0.8.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
|
4
|
+
nonebot_plugin_l4d2_server-1.0.8.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
5
|
+
nonebot_plugin_l4d2_server/__init__.py,sha256=xzhXyprPmoTTjpfyqYlMweC4umuLsm8MERA1ZTqCyYc,1661
|
6
|
+
nonebot_plugin_l4d2_server/__main__.py,sha256=Ysx4PkR3kIuSsKM6h9kmPBuylxXsuLjtrOdT1LbQT9A,10511
|
7
|
+
nonebot_plugin_l4d2_server/config.py,sha256=t4BYygrrLTcsl9oBnyce0-tDhMCCkMrkEPs4DX2t4KI,2682
|
8
8
|
nonebot_plugin_l4d2_server/data/font/loli.ttf,sha256=Yrh-RPoCrn1-NG94DR0x20ASXYUt8g3Ep6BCt3CdOFk,11125812
|
9
|
-
nonebot_plugin_l4d2_server/l4_help/Help.json,sha256=
|
10
|
-
nonebot_plugin_l4d2_server/l4_help/__init__.py,sha256=
|
9
|
+
nonebot_plugin_l4d2_server/l4_help/Help.json,sha256=D0YmZYGW-imC7nVebkQ0_eODiqevQhL9aKj-cyBaqDY,1704
|
10
|
+
nonebot_plugin_l4d2_server/l4_help/__init__.py,sha256=BsrZHgZXEZ0rXNb2mQJF7o3kwDeb05vAXoYwl6znMCc,1479
|
11
11
|
nonebot_plugin_l4d2_server/l4_help/draw.py,sha256=y6yDPUnoZFvwly8cf7g9HRpT1JXTxyA9DC1TuvUinTM,6448
|
12
12
|
nonebot_plugin_l4d2_server/l4_help/icon/介绍.png,sha256=3QC6A38QC-7gDBxmtQSQdbsz7hsefU5LL-oZmJ41zTk,3806
|
13
13
|
nonebot_plugin_l4d2_server/l4_help/icon/任务.png,sha256=nyZ4_kM21ZO95nwanCFnUfCGX-PkmJXYQf9OrJVKomY,3782
|
@@ -51,11 +51,10 @@ nonebot_plugin_l4d2_server/l4_help/texture2d/bg.jpg,sha256=xTyLJLgo3E-ZH-tupsjZC
|
|
51
51
|
nonebot_plugin_l4d2_server/l4_help/texture2d/button.png,sha256=oQKoRBJDaVXz2eVD-lHkaVcV1aw0ehkNBK8TNSjTehI,12711
|
52
52
|
nonebot_plugin_l4d2_server/l4_help/texture2d/icon.png,sha256=A2p0r8aBXpNy_b_CtZTZzTrEeHbGRYzO2fNwahyLlQ0,634659
|
53
53
|
nonebot_plugin_l4d2_server/l4_image/__init__.py,sha256=-GWXUDv_z_cfJ-wyvx5J3wB9P7ng4NzRHfCq-GZD6XQ,431
|
54
|
-
nonebot_plugin_l4d2_server/l4_image/anne_pil.py,sha256=Q_PHRzB_OgPbRbnLg-asVduV477F1rQnau2DhPOzf5k,500
|
55
54
|
nonebot_plugin_l4d2_server/l4_image/convert.py,sha256=MISJq2JFcmQJaYZz6dDjQ2UusVORQt7rLSoAY_CyyWY,3894
|
56
55
|
nonebot_plugin_l4d2_server/l4_image/download.py,sha256=qRAo0Ggj5KV8RQN3LFJe547__wwC7Ww4QnT-v3pfe6w,3116
|
57
|
-
nonebot_plugin_l4d2_server/l4_image/html_img.py,sha256=
|
58
|
-
nonebot_plugin_l4d2_server/l4_image/image_tools.py,sha256=
|
56
|
+
nonebot_plugin_l4d2_server/l4_image/html_img.py,sha256=BE_GQ67KRCb-r_iaVOLPAEoloNvOA9bbxhc8o8WhLXc,2882
|
57
|
+
nonebot_plugin_l4d2_server/l4_image/image_tools.py,sha256=iHkvG2fYxYCz7B2JV69MSMlH5KXyWftcBs_prmyTyO4,14453
|
59
58
|
nonebot_plugin_l4d2_server/l4_image/img/anne/anne.html,sha256=8JOUXoWdulhoP2Axy_omuSDafbduKDZ9Y8Rz2VZWTso,1590
|
60
59
|
nonebot_plugin_l4d2_server/l4_image/img/anne/back.png,sha256=jnsYjnvd2BFcdkdsW8HgcSloWF0ZliPkqlWSIDnFUxw,245488
|
61
60
|
nonebot_plugin_l4d2_server/l4_image/img/anne/back1.jpg,sha256=hAzPHflbf4db5S3rM5xn-1wnDP8xZExikYmkKW5c4w0,113622
|
@@ -84,14 +83,15 @@ nonebot_plugin_l4d2_server/l4_image/img/template/vue.css,sha256=2sGjCFrR-3tFMB_x
|
|
84
83
|
nonebot_plugin_l4d2_server/l4_image/img/template/w.svg,sha256=LnctC2mVwjdhRMiS9ffrjUX-9KGwqb6OMmpJXvVXl70,486
|
85
84
|
nonebot_plugin_l4d2_server/l4_image/model.py,sha256=FGsCvf_BKbRNJUVy6I5BKnArMY-3JEIdqeX2gs93E5o,231
|
86
85
|
nonebot_plugin_l4d2_server/l4_image/vtfs.py,sha256=He_7zzEIOip8MXP55TS7aWPbzo6ac0wPf602nN3GWZM,1461
|
87
|
-
nonebot_plugin_l4d2_server/l4_local/__init__.py,sha256=
|
86
|
+
nonebot_plugin_l4d2_server/l4_local/__init__.py,sha256=B4E30jX4733M4eNCJvIQhsN4M0nlxLezSXMSwUYLRIk,3581
|
88
87
|
nonebot_plugin_l4d2_server/l4_local/file.py,sha256=hew1Y8kV3uSZvUGplmi09EGKC89-sUJWsWV7SCEstI8,3067
|
89
|
-
nonebot_plugin_l4d2_server/l4_request/__init__.py,sha256=
|
90
|
-
nonebot_plugin_l4d2_server/l4_request/draw_msg.py,sha256=
|
91
|
-
nonebot_plugin_l4d2_server/l4_request/utils.py,sha256=
|
88
|
+
nonebot_plugin_l4d2_server/l4_request/__init__.py,sha256=OrwOyucW-DyKVDk8LRA24h0gQIyzmhWbG73DG3O2JgM,7499
|
89
|
+
nonebot_plugin_l4d2_server/l4_request/draw_msg.py,sha256=KpSfl6ZLaxPbax0SgO07niJloeMARuQJ2T-F_XeH6uQ,8108
|
90
|
+
nonebot_plugin_l4d2_server/l4_request/utils.py,sha256=7E_Cqp4UcKjrnGBn0gbs5nGiC37RAKmUBJx7qEaXi6Q,5166
|
92
91
|
nonebot_plugin_l4d2_server/utils/api/api.py,sha256=auvDicCEKwvnm6EJYeCxCtugFby61K-zAmmaRWWEwtM,296
|
93
92
|
nonebot_plugin_l4d2_server/utils/api/models.py,sha256=p-hoxPHwadTaMRb2hqwfbaQ3pvJySrV8VbBmhA0Oi-M,2391
|
94
|
-
nonebot_plugin_l4d2_server/utils/api/request.py,sha256=
|
93
|
+
nonebot_plugin_l4d2_server/utils/api/request.py,sha256=JGAhMgPgmy2Z2w7w3GVlUGKBmxlaTTDD3bq1T2dhHIE,13567
|
94
|
+
nonebot_plugin_l4d2_server/utils/api/utils.py,sha256=rdrFK3VKP59KfNX-C8v0Q_IV3tBLm02Wo9axLTQQ87Y,762
|
95
95
|
nonebot_plugin_l4d2_server/utils/database/models.py,sha256=SLdcgwsn39r_ZkcBoqf4MLX1EfpCOjGBwWcR16u9Bqo,454
|
96
96
|
nonebot_plugin_l4d2_server/utils/utils.py,sha256=TD3cUCxmmj2GPmK1sQwP7NtkIXNO2FpuXjymaUqBDYo,6141
|
97
|
-
nonebot_plugin_l4d2_server-1.0.
|
97
|
+
nonebot_plugin_l4d2_server-1.0.8.dist-info/RECORD,,
|
@@ -1,18 +0,0 @@
|
|
1
|
-
from pathlib import Path
|
2
|
-
|
3
|
-
from PIL import Image, ImageFont
|
4
|
-
|
5
|
-
from nonebot_plugin_l4d2_server.utils.api.models import AnnePlayer2
|
6
|
-
|
7
|
-
from ..config import config
|
8
|
-
|
9
|
-
font = ImageFont.truetype(config.l4_font)
|
10
|
-
|
11
|
-
anne_path = Path(__file__).parent / "img" / "anne"
|
12
|
-
|
13
|
-
|
14
|
-
async def anne_player_info(msg: AnnePlayer2): # noqa: RUF029
|
15
|
-
back_img = Image.open(anne_path / "back1.jpg")
|
16
|
-
base_img = Image.new("RGBA", (back_img.size), (255, 255, 255, 50))
|
17
|
-
back_img.paste(base_img, (0, 0), base_img)
|
18
|
-
return msg
|
{nonebot_plugin_l4d2_server-1.0.4.dist-info → nonebot_plugin_l4d2_server-1.0.8.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|