nonebot-plugin-l4d2-server 1.0.8__py3-none-any.whl → 1.0.9__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.
@@ -10,7 +10,7 @@ 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.8"
13
+ __version__ = "1.0.9"
14
14
  TEXT_PATH = Path(__file__).parent / "texture2d"
15
15
  HELP_DATA = Path(__file__).parent / "Help.json"
16
16
 
@@ -152,20 +152,26 @@ async def text2pic(text: str, max_size: int = 800, font_size: int = 24):
152
152
  if text.endswith("\n"):
153
153
  text = text[:-1]
154
154
 
155
+ # 更准确的高度计算
156
+ line_count = text.count("\n") + 1
157
+ line_height = int(font_size * 1.2) # 每行高度,包含行间距
158
+ estimated_height = line_count * line_height + 80 # 加上上下边距
159
+
155
160
  img = Image.new(
156
161
  "RGB",
157
- (max_size, len(text) * font_size // 10),
162
+ (max_size, estimated_height),
158
163
  (255, 255, 255),
159
164
  )
160
165
  img_draw = ImageDraw.ImageDraw(img)
161
166
  y = draw_center_text_by_line(
162
167
  img_draw,
163
- (50, 50),
168
+ (50, 30),
164
169
  text,
165
170
  core_font(font_size),
166
171
  "black",
167
172
  max_size - 80,
168
173
  True, # noqa: FBT003
169
174
  )
170
- img = img.crop((0, 0, max_size, int(y + 80)))
175
+ # 裁剪时留一些余量
176
+ img = img.crop((0, 0, max_size, int(y + 55)))
171
177
  return await convert_img(img)
@@ -45,7 +45,15 @@ else:
45
45
 
46
46
  @search_map.handle()
47
47
  async def _():
48
- supath = local_path[map_index] / "addons"
48
+ try:
49
+ supath = local_path[map_index] / "addons"
50
+ except IndexError:
51
+ logger.warning(
52
+ "未填写本地服务器路径,如果想要使用本地服务器功能,请填写本地服务器路径",
53
+ )
54
+ await UniMessage.text(
55
+ "未填写本地服务器路径,如果想要使用本地服务器功能,请填写本地服务器路径",
56
+ ).finish()
49
57
  vpk_list: list[str] = []
50
58
  if supath.is_dir():
51
59
  for sudir in supath.iterdir():
@@ -54,6 +62,27 @@ else:
54
62
  vpk_list.append(sudir.name)
55
63
  if not vpk_list:
56
64
  await UniMessage.text("未找到可用的VPK文件").finish()
65
+
66
+ # 添加排序逻辑(数字升序)
67
+ def sort_key(filename: str):
68
+ # 提取文件名开头的数字(如果有)
69
+ num_part = ""
70
+ for char in filename:
71
+ if char.isdigit():
72
+ num_part += char
73
+ elif num_part: # 遇到非数字且已经有数字部分时停止
74
+ break
75
+
76
+ # 返回一个元组作为排序依据:(数字值, 整个文件名)
77
+ # 使用正数表示升序,没有数字的用无穷大排在最后
78
+ return (
79
+ int(num_part) if num_part else float("inf"),
80
+ filename,
81
+ )
82
+
83
+ # 按数字升序,然后按字母和中文排序
84
+ vpk_list.sort(key=sort_key)
85
+
57
86
  out_msg = "\n".join(
58
87
  f"{index + 1}、{line}" for index, line in enumerate(vpk_list)
59
88
  )
@@ -119,7 +119,7 @@ async def get_group_detail(
119
119
  command: str,
120
120
  ):
121
121
  server_json = _get_server_json(command, ALLHOST)
122
- logger.info(server_json)
122
+ logger.debug(server_json)
123
123
  if server_json is None:
124
124
  logger.warning("未找到这个组")
125
125
  return None
@@ -170,7 +170,7 @@ def reload_ip():
170
170
  async def tj_request(command: str = "云", tj="tj"):
171
171
  map_type = "普通药役"
172
172
  server_json = ALLHOST.get(command)
173
- logger.info(server_json)
173
+ logger.debug(server_json)
174
174
  if server_json is None:
175
175
  logger.warning("未找到这个组")
176
176
  return None
@@ -186,8 +186,9 @@ async def tj_request(command: str = "云", tj="tj"):
186
186
  logger.warning("没有找到符合条件的服务器")
187
187
  return "没有符合条件的服务器"
188
188
 
189
+ server_list_str = [f"{ip['host']}:{ip['port']}" for ip in right_ip]
189
190
  logger.info(
190
- f"符合条件的服务器列表: {[f'{ip['host']}:{ip['port']}' for ip in right_ip]}",
191
+ f"符合条件的服务器列表: {server_list_str}",
191
192
  )
192
193
  s = random.choice(right_ip)
193
194
  logger.info(f"最终选择的服务器: {s['host']}:{s['port']}")
@@ -216,7 +217,7 @@ async def server_find(
216
217
  is_img: bool = True,
217
218
  ):
218
219
  server_json = _get_server_json(command, ALLHOST)
219
- logger.info(server_json)
220
+ logger.debug(server_json)
220
221
  if server_json is None:
221
222
  logger.warning("未找到这个组")
222
223
  return None
@@ -1,5 +1,3 @@
1
- import asyncio
2
-
3
1
  # from logging import log
4
2
  import io
5
3
  from pathlib import Path
@@ -15,9 +13,9 @@ from ..utils.api.request import L4API
15
13
 
16
14
  async def draw_one_ip(host: str, port: int, is_img: bool = config.l4_image):
17
15
  """输出单个ip"""
18
- try:
19
- ser_list = await L4API.a2s_info([(host, port)], is_player=True)
20
- except asyncio.exceptions.TimeoutError:
16
+ ser_list = await L4API.a2s_info([(host, port)], is_player=True)
17
+ if not ser_list or ser_list[0][0].max_players == 0:
18
+ # except asyncio.exceptions.TimeoutError:
21
19
  return "服务器无响应"
22
20
  one_server = ser_list[0][0]
23
21
  one_player = ser_list[0][1]
@@ -40,15 +38,10 @@ async def draw_one_ip(host: str, port: int, is_img: bool = config.l4_image):
40
38
  soc = "[{:>{}}]".format(player.score, max_score_len)
41
39
  chines_dur = await convert_duration(player.duration)
42
40
  dur = "{:^{}}".format(chines_dur, max_duration_len)
43
- name_leg = len(player.name)
44
- if name_leg > 2:
45
- xing = ":)" * (name_leg - 2)
46
- name = f"{player.name[0]}{xing}{player.name[-1]}"
47
- else:
48
- name = player.name
41
+ name = player.name
49
42
  player_msg += f"{soc} | {dur} | {name} \n"
50
43
  else:
51
- player_msg = "服务器感觉很安静啊"
44
+ player_msg = "服务器感觉很安静啊\n"
52
45
  return player_msg
53
46
 
54
47
  def build_server_message(server, player_info: str) -> str:
@@ -59,13 +52,35 @@ async def draw_one_ip(host: str, port: int, is_img: bool = config.l4_image):
59
52
  Returns:
60
53
  完整的服务器信息字符串
61
54
  """
55
+
56
+ # 处理服务器类型显示
57
+ type_map = {
58
+ "d": "Dedicated",
59
+ "l": "Listen",
60
+ }
61
+ platform_map = {
62
+ "w": "Windows",
63
+ "l": "Linux",
64
+ }
65
+ # 解析原始数据 (例如 "d(w)" -> type='d', platform='w')
66
+ server_type = server.server_type[0] if server.server_type else "d"
67
+ platform = server.platform[0] if server.platform else "w"
68
+
69
+ # 处理VAC状态显示
70
+ vac_status = "启用" if server.vac_enabled else "禁用"
71
+ # 处理密码状态显示
72
+ pw_status = "是" if server.password_protected else "否"
73
+
62
74
  msg = f"""-{server.server_name}-
63
75
  游戏: {server.folder}
64
76
  地图: {server.map_name}
65
- 人数: {server.player_count}/{server.max_players}"""
77
+ 人数: {server.player_count} / {server.max_players}"""
66
78
  if server.ping is not None:
67
79
  msg += f"""
68
- ping: {server.ping * 1000:.0f}ms
80
+ 延迟: {server.ping * 1000:.0f} ms
81
+ 类型: {type_map.get(server_type, '未知')} ({platform_map.get(platform, '未知')})
82
+ VAC : {vac_status}
83
+ 密码: {pw_status}\n
69
84
  {player_info}"""
70
85
  if config.l4_show_ip:
71
86
  msg += f"""
@@ -112,7 +127,7 @@ connect {host}:{port}"""
112
127
 
113
128
  # 计算图片尺寸
114
129
  margin = 20
115
- line_spacing = 5
130
+ line_spacing = 7
116
131
  img_width = max(title_width, content_width) + 2 * margin
117
132
  content_lines_count = len(content.split("\n")) if content else 0
118
133
  img_height = max(
@@ -141,13 +156,87 @@ connect {host}:{port}"""
141
156
  if content:
142
157
  content_x = margin
143
158
  content_y = title_y + title_height + margin
144
- draw.text(
145
- (content_x, content_y),
146
- content,
147
- font=font,
148
- fill=(255, 255, 255),
149
- spacing=line_spacing,
150
- )
159
+
160
+ # 定义不同参数值的颜色(冒号后的内容)
161
+ value_colors = {
162
+ "游戏: ": (200, 180, 255), # 淡紫
163
+ "地图: ": (166, 202, 253), # 淡蓝
164
+ "人数: ": (100, 255, 100), # 绿色
165
+ "延迟: ": (100, 255, 100), # 绿色
166
+ "类型: ": (180, 220, 255), # 淡蓝
167
+ "密码: ": (255, 255, 255), # 白色
168
+ # connect不修改,保持原逻辑
169
+ }
170
+
171
+ # 按行绘制内容
172
+ current_y = content_y
173
+ for line in content_lines:
174
+ # 检查是否是参数行
175
+ colored = False
176
+ for prefix, color in value_colors.items():
177
+ if line.startswith(prefix):
178
+ # 绘制完整参数名(白色)
179
+ prefix_part = prefix
180
+ prefix_width = (
181
+ font.getbbox(prefix_part)[2]
182
+ - font.getbbox(prefix_part)[0]
183
+ )
184
+ draw.text(
185
+ (content_x, current_y),
186
+ prefix_part,
187
+ font=font,
188
+ fill=(255, 255, 255),
189
+ )
190
+
191
+ # 绘制参数值(带颜色)
192
+ value_part = line[len(prefix) :].strip()
193
+ draw.text(
194
+ (content_x + prefix_width, current_y),
195
+ value_part,
196
+ font=font,
197
+ fill=color,
198
+ )
199
+
200
+ colored = True
201
+ break
202
+ # 特殊处理VAC行
203
+ if not colored and line.startswith("VAC :"):
204
+ prefix = "VAC : "
205
+ prefix_width = (
206
+ font.getbbox(prefix)[2] - font.getbbox(prefix)[0]
207
+ )
208
+ draw.text(
209
+ (content_x, current_y),
210
+ prefix,
211
+ font=font,
212
+ fill=(255, 255, 255),
213
+ )
214
+
215
+ value_part = line[len(prefix) :].strip()
216
+ vac_color = (
217
+ (70, 209, 110)
218
+ if value_part == "启用"
219
+ else (255, 90, 90)
220
+ ) # 启用绿/禁用红
221
+ draw.text(
222
+ (content_x + prefix_width, current_y),
223
+ value_part,
224
+ font=font,
225
+ fill=vac_color,
226
+ )
227
+
228
+ colored = True
229
+
230
+ # 普通行(玩家信息)和connect保持原样
231
+ if not colored:
232
+ draw.text(
233
+ (content_x, current_y),
234
+ line,
235
+ font=font,
236
+ fill=(255, 255, 255),
237
+ )
238
+
239
+ current_y += line_height + line_spacing
151
240
 
152
241
  return img
153
242
  except Exception as e:
@@ -1,4 +1,4 @@
1
- from typing import Dict, List, Optional, Tuple, Union, cast
1
+ from typing import Dict, List, Optional, Tuple, Union
2
2
 
3
3
  from nonebot.log import logger
4
4
 
@@ -95,10 +95,7 @@ async def _handle_single_server(
95
95
  return None
96
96
 
97
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
98
+ return await draw_one_ip(host, port, is_img=is_img)
102
99
 
103
100
 
104
101
  async def _filter_servers(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nonebot-plugin-l4d2-server
3
- Version: 1.0.8
3
+ Version: 1.0.9
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>
@@ -1,13 +1,13 @@
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
1
+ nonebot_plugin_l4d2_server-1.0.9.dist-info/METADATA,sha256=ctmdb9rfE5_n965rELNjZ1l-KWaXoKndwjj0Ewh2Ye0,6759
2
+ nonebot_plugin_l4d2_server-1.0.9.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
+ nonebot_plugin_l4d2_server-1.0.9.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
4
+ nonebot_plugin_l4d2_server-1.0.9.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
5
5
  nonebot_plugin_l4d2_server/__init__.py,sha256=xzhXyprPmoTTjpfyqYlMweC4umuLsm8MERA1ZTqCyYc,1661
6
6
  nonebot_plugin_l4d2_server/__main__.py,sha256=Ysx4PkR3kIuSsKM6h9kmPBuylxXsuLjtrOdT1LbQT9A,10511
7
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
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
10
+ nonebot_plugin_l4d2_server/l4_help/__init__.py,sha256=_e2uAaiECMGhbunurdN3dImu00l5j1uDCLBMxPlqolM,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,7 +51,7 @@ 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/convert.py,sha256=MISJq2JFcmQJaYZz6dDjQ2UusVORQt7rLSoAY_CyyWY,3894
54
+ nonebot_plugin_l4d2_server/l4_image/convert.py,sha256=2wc72nyfEIjyOZS_98BrzD6G9xFzlD9GlsUGOjBLJV4,4132
55
55
  nonebot_plugin_l4d2_server/l4_image/download.py,sha256=qRAo0Ggj5KV8RQN3LFJe547__wwC7Ww4QnT-v3pfe6w,3116
56
56
  nonebot_plugin_l4d2_server/l4_image/html_img.py,sha256=BE_GQ67KRCb-r_iaVOLPAEoloNvOA9bbxhc8o8WhLXc,2882
57
57
  nonebot_plugin_l4d2_server/l4_image/image_tools.py,sha256=iHkvG2fYxYCz7B2JV69MSMlH5KXyWftcBs_prmyTyO4,14453
@@ -83,15 +83,15 @@ nonebot_plugin_l4d2_server/l4_image/img/template/vue.css,sha256=2sGjCFrR-3tFMB_x
83
83
  nonebot_plugin_l4d2_server/l4_image/img/template/w.svg,sha256=LnctC2mVwjdhRMiS9ffrjUX-9KGwqb6OMmpJXvVXl70,486
84
84
  nonebot_plugin_l4d2_server/l4_image/model.py,sha256=FGsCvf_BKbRNJUVy6I5BKnArMY-3JEIdqeX2gs93E5o,231
85
85
  nonebot_plugin_l4d2_server/l4_image/vtfs.py,sha256=He_7zzEIOip8MXP55TS7aWPbzo6ac0wPf602nN3GWZM,1461
86
- nonebot_plugin_l4d2_server/l4_local/__init__.py,sha256=B4E30jX4733M4eNCJvIQhsN4M0nlxLezSXMSwUYLRIk,3581
86
+ nonebot_plugin_l4d2_server/l4_local/__init__.py,sha256=gNNUNXGKHA8UXQaDKomND4VEutGpAghpYE4Va13gb5I,4736
87
87
  nonebot_plugin_l4d2_server/l4_local/file.py,sha256=hew1Y8kV3uSZvUGplmi09EGKC89-sUJWsWV7SCEstI8,3067
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
88
+ nonebot_plugin_l4d2_server/l4_request/__init__.py,sha256=p8ndsNC4QCJ97K9fZwCQ2y6jOa5-QU14soQ3dIZzIKg,7544
89
+ nonebot_plugin_l4d2_server/l4_request/draw_msg.py,sha256=2HvUpVdge4lHG3y7LpB1Babi7jTkpoVP325V3MTvgBA,12151
90
+ nonebot_plugin_l4d2_server/l4_request/utils.py,sha256=UyRceC5FOS_GeUNKJtL1OpXwq-f5QiVxSpy6rgj52p8,5102
91
91
  nonebot_plugin_l4d2_server/utils/api/api.py,sha256=auvDicCEKwvnm6EJYeCxCtugFby61K-zAmmaRWWEwtM,296
92
92
  nonebot_plugin_l4d2_server/utils/api/models.py,sha256=p-hoxPHwadTaMRb2hqwfbaQ3pvJySrV8VbBmhA0Oi-M,2391
93
93
  nonebot_plugin_l4d2_server/utils/api/request.py,sha256=JGAhMgPgmy2Z2w7w3GVlUGKBmxlaTTDD3bq1T2dhHIE,13567
94
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.8.dist-info/RECORD,,
97
+ nonebot_plugin_l4d2_server-1.0.9.dist-info/RECORD,,