nonebot-plugin-l4d2-server 1.0.3__py3-none-any.whl → 1.0.4__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.
@@ -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, Union
20
20
 
21
21
  import aiofiles
22
22
  import ujson as json
@@ -24,10 +24,11 @@ from nonebot.adapters import Message
24
24
  from nonebot.log import logger
25
25
  from nonebot.matcher import Matcher
26
26
  from nonebot.params import CommandArg, CommandStart, RawCommand
27
+ from nonebot.permission import SUPERUSER
27
28
  from nonebot.plugin import on_command
28
29
  from nonebot_plugin_alconna import UniMessage
29
30
 
30
- from .config import config
31
+ from .config import config, config_manager
31
32
  from .l4_help import get_l4d2_core_help
32
33
  from .l4_local import * # noqa: F403
33
34
  from .l4_request import (
@@ -45,7 +46,7 @@ if TYPE_CHECKING:
45
46
 
46
47
  reload_ip()
47
48
 
48
- l4_help = on_command("l4help", aliases={"l4帮助", "l4d2帮助"})
49
+ l4_help = on_command("l4help", aliases={"l4d2帮助"})
49
50
  l4_request = on_command("anne", aliases=COMMAND, priority=10)
50
51
  l4_reload = on_command("l4reload", aliases={"l4刷新,l4重载"})
51
52
  l4_all = on_command("l4all", aliases={"l4全服"})
@@ -59,13 +60,11 @@ config_path = Path(config.l4_path) / "config.json"
59
60
 
60
61
 
61
62
  @l4_help.handle()
62
- async def _(matcher: Matcher):
63
+ async def _():
63
64
  """帮助"""
64
65
  logger.info("开始执行[l4d2帮助]")
65
66
  im = await get_l4d2_core_help()
66
- if isinstance(im, str):
67
- await matcher.finish(im)
68
- await UniMessage.image(raw=im).send()
67
+ await out_msg_out(im)
69
68
 
70
69
 
71
70
  @l4_request.handle()
@@ -74,11 +73,31 @@ async def _(
74
73
  command: str = RawCommand(),
75
74
  args: Message = CommandArg(),
76
75
  ):
77
- """例:
78
- 指令: /橘5
79
- start: /(command开头指令)
80
- command: /橘(响应的全部指令)
81
- args: 5(响应的指令后的数字)
76
+ """
77
+ 异步函数,用于处理特定的指令。
78
+
79
+ Args:
80
+ start (str, optional): 指令的开头部分,默认为 CommandStart() 返回的值。
81
+ command (str, optional): 完整的指令字符串,默认为 RawCommand() 返回的值。
82
+ args (Message, optional): 指令后的参数,默认为 CommandArg() 返回的值。
83
+
84
+ Returns:
85
+ None
86
+
87
+ Examples:
88
+ 示例指令:"/橘5"
89
+ - start: "/" (指令的开头部分)
90
+ - command: "/橘" (完整的指令字符串)
91
+ - args: "5" (指令后的参数)
92
+
93
+ Notes:
94
+ 1. 如果 start 存在,会将 command 中的 start 部分替换为空字符串。
95
+ 2. 如果 command 等于 "anne",则将其替换为 "云"。
96
+ 3. 提取 args 中的纯文本内容,如果内容非空且不是数字,则返回。
97
+ 4. 如果 args 为空,则将其设置为 None。
98
+ 5. 使用 logger 记录处理过程中的信息。
99
+ 6. 调用 get_server_detail 函数获取服务器详情,并根据返回结果发送相应的消息。
100
+ 7. 如果 get_server_detail 返回 None,则发送 "服务器无响应" 的文本消息。
82
101
  """
83
102
 
84
103
  if start:
@@ -93,12 +112,9 @@ async def _(
93
112
  logger.info(f"组:{command} ;数字:{_id}")
94
113
  msg = await get_server_detail(command, _id)
95
114
  if msg is not None:
96
- if isinstance(msg, str):
97
- await UniMessage.text(msg).finish()
98
- if isinstance(msg, bytes):
99
- await UniMessage.image(raw=msg).finish()
115
+ await out_msg_out(msg, is_connect=config.l4_image)
100
116
  else:
101
- await UniMessage.text("服务器无响应").finish()
117
+ await out_msg_out("服务器无响应")
102
118
 
103
119
 
104
120
  @l4_find_player.handle()
@@ -120,32 +136,26 @@ async def _(
120
136
  if len(tag_list) == 2:
121
137
  group, name = tag_list
122
138
  await UniMessage.text(f"正在查询{group}组").send()
123
- out: List[OutServer] = await get_server_detail(group, is_img=False) # type: ignore
139
+ out: List[OutServer] = await get_server_detail(group=group, is_img=False) # type: ignore
124
140
  out_msg = "未找到玩家"
125
141
  for one in out:
126
142
  for player in one["player"]:
127
143
  if name in player.name:
128
144
  out_msg = await get_ip_server(f"{one['host']}:{one['port']}")
129
145
 
130
- return await UniMessage.text(out_msg).finish()
146
+ return await out_msg_out(out_msg)
131
147
 
132
148
 
133
149
  @l4_all.handle()
134
150
  async def _():
135
- await UniMessage.text(await get_all_server_detail()).finish()
151
+ await out_msg_out(await get_all_server_detail())
136
152
 
137
153
 
138
154
  @l4_connect.handle()
139
155
  async def _(args: Message = CommandArg()):
140
156
  ip: Optional[str] = args.extract_plain_text()
141
157
  if ip is not None:
142
- await UniMessage.text(await get_ip_server(ip)).finish()
143
-
144
-
145
- # anne部分
146
- if config.l4_anne:
147
- logger.info("加载anne功能")
148
- from .l4_anne import * # noqa: F403
158
+ await out_msg_out(await get_ip_server(ip), is_connect=config.l4_image)
149
159
 
150
160
 
151
161
  @l4_reload.handle()
@@ -161,7 +171,7 @@ async def _(args: Message = CommandArg()):
161
171
  for tag, url in ip_json.items():
162
172
  logger.info(f"重载{tag}的ip")
163
173
  await L4API.get_sourceban(tag, url)
164
- await UniMessage.text("重载ip完成").finish()
174
+ await out_msg_out("重载ip完成")
165
175
 
166
176
 
167
177
  l4_add_ban = on_command("l4addban", aliases={"l4添加ban"})
@@ -192,7 +202,7 @@ async def _(args: Message = CommandArg()):
192
202
  await UniMessage.text(f"文件写入失败: {e}").finish()
193
203
 
194
204
  await L4API.get_sourceban(arg[0], arg[1])
195
- await UniMessage.text(f"添加成功\n组名: {arg[0]}\n网址: {arg[1]}").finish()
205
+ await out_msg_out(f"添加成功\n组名: {arg[0]}\n网址: {arg[1]}")
196
206
 
197
207
 
198
208
  l4_del_ban = on_command("l4delban", aliases={"l4删除ban", "l4移除ban"})
@@ -219,7 +229,7 @@ async def _(args: Message = CommandArg()):
219
229
  del config_data[arg[0]]
220
230
  async with aiofiles.open(config_path, "w", encoding="utf-8") as f:
221
231
  json.dump(config_data, f, ensure_ascii=False, indent=4)
222
- await UniMessage.text(f"删除成功,组名:{arg[0]}").finish()
232
+ await out_msg_out(f"删除成功,组名:{arg[0]}")
223
233
  elif len(arg) == 2:
224
234
  if not Path(Path(config.l4_path) / "config.json").is_file():
225
235
  await UniMessage.text("没有添加过组名").finish()
@@ -236,7 +246,7 @@ async def _(args: Message = CommandArg()):
236
246
  config_datas[arg[0]] = arg[1]
237
247
  async with aiofiles.open(config_path, "w", encoding="utf-8") as f:
238
248
  json.dump(config_datas, f, ensure_ascii=False, indent=4)
239
- await UniMessage.text(f"修改成功,组名:{arg[0]},网址:{arg[1]}").finish()
249
+ await out_msg_out(f"修改成功,组名:{arg[0]},网址:{arg[1]}")
240
250
 
241
251
 
242
252
  @ld_tj.handle()
@@ -249,3 +259,39 @@ async def _(matcher: Matcher):
249
259
  async def _(matcher: Matcher):
250
260
  await matcher.send("正在寻找牢房信息")
251
261
  await matcher.finish(await tj_request("云", "zl"))
262
+
263
+
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
+ ## 以下为配置修改
283
+
284
+ img_trung = on_command("l4img", aliases={"l4图片"}, permission=SUPERUSER)
285
+
286
+
287
+ @img_trung.handle()
288
+ async def _(args: Message = CommandArg()):
289
+ arg = args.extract_plain_text().strip().lower()
290
+ if arg == "开启":
291
+ config_manager.update_image_config(enabled=True)
292
+ await out_msg_out("[l4]已开启图片模式")
293
+ elif arg == "关闭":
294
+ config_manager.update_image_config(enabled=False)
295
+ await out_msg_out("[l4]已关闭图片模式")
296
+ else:
297
+ await UniMessage.text("请在参数后加上开启或关闭").finish()
@@ -20,11 +20,9 @@ map_index = 0
20
20
 
21
21
 
22
22
  class ConfigModel(BaseModel):
23
- l4_anne: bool = False
24
- """是否启用anne电信服相关功能"""
25
23
  l4_enable: bool = True
26
24
  """是否全局启用求生功能"""
27
- l4_image: bool = False
25
+ l4_image: bool = True
28
26
  """是否启用图片"""
29
27
  l4_connect: bool = True
30
28
  """是否在查服命令后加入connect ip"""
@@ -43,3 +41,54 @@ class ConfigModel(BaseModel):
43
41
 
44
42
 
45
43
  config = get_plugin_config(ConfigModel)
44
+
45
+
46
+ class ConfigManager:
47
+ """配置项管理类,提供类型安全的配置更新方法"""
48
+
49
+ def __init__(self):
50
+ self._config = config
51
+
52
+ def update_image_config(self, enabled: bool) -> None:
53
+ """更新图片配置
54
+
55
+ Args:
56
+ enabled: 是否启用图片功能
57
+ """
58
+ self._config.l4_image = enabled
59
+
60
+ def update_style_config(self, style: str) -> None:
61
+ """更新图片风格配置
62
+
63
+ Args:
64
+ style: 图片风格名称
65
+ """
66
+ if not isinstance(style, str):
67
+ raise TypeError("style必须是字符串")
68
+ self._config.l4_style = style
69
+
70
+ def update_connect_config(self, enabled: bool) -> None:
71
+ """更新connect ip配置
72
+
73
+ Args:
74
+ enabled: 是否在查服命令后加入connect ip
75
+ """
76
+ self._config.l4_connect = enabled
77
+
78
+ def update(self, **kwargs) -> None:
79
+ """通用配置更新方法
80
+
81
+ Args:
82
+ **kwargs: 要更新的配置项键值对
83
+
84
+ Raises:
85
+ ValueError: 当传入无效的配置项时
86
+ """
87
+ for key, value in kwargs.items():
88
+ if hasattr(self._config, key):
89
+ setattr(self._config, key, value)
90
+ else:
91
+ raise ValueError(f"无效的配置项: {key}")
92
+
93
+
94
+ config_manager = ConfigManager()
@@ -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.3"
13
+ __version__ = "1.0.4"
14
14
  TEXT_PATH = Path(__file__).parent / "texture2d"
15
15
  HELP_DATA = Path(__file__).parent / "Help.json"
16
16
 
@@ -1,11 +1,12 @@
1
1
  import random
2
- from typing import Dict, List, Optional, cast
2
+ from typing import Dict, List, Optional, Tuple, Union, cast
3
3
 
4
4
  from nonebot.log import logger
5
+ from nonebot_plugin_alconna import UniMessage
5
6
 
6
7
  from ..config import server_all_path
7
8
  from ..l4_image import msg_to_image
8
- from ..utils.api.models import AllServer, NserverOut, OutServer
9
+ from ..utils.api.models import AllServer, NserverOut
9
10
  from ..utils.api.request import L4API
10
11
  from ..utils.utils import split_maohao
11
12
  from .draw_msg import convert_duration, draw_one_ip, get_much_server
@@ -79,48 +80,127 @@ async def get_server_detail(
79
80
  command (str): 服务器组名。
80
81
  _id (Optional[str], optional): 服务器ID。默认为None。
81
82
  is_img (bool, optional): 是否返回图片格式的信息。默认为True。
83
+ return_host_port (bool, optional): 是否返回host和port值。默认为False。
82
84
 
83
85
  Returns:
84
- Union[bytes, List[OutServer], None]: 返回服务器详细信息。如果为图片格式,返回bytes类型;
85
- 如果不是图片格式,返回List[OutServer]类型;如果未找到服务器组,返回None
86
-
86
+ Union[bytes, str, None, Tuple[str, int]]:
87
+ 如果return_host_port为True且_id不为None,返回(host, port)元组;
88
+ 否则返回服务器详细信息(图片格式返回bytes,文本格式返回str);
89
+ 未找到服务器组返回None。
87
90
  """
88
- if command:
89
- server_json = ALLHOST.get(command)
90
- else:
91
- server_json = []
92
- for servers in ALLHOST.values():
93
- server_json.extend(servers)
94
-
91
+ server_json = _get_server_json(command)
95
92
  logger.info(server_json)
96
93
  if server_json is None:
97
94
  logger.warning("未找到这个组")
98
95
  return None
99
96
 
100
97
  if _id is None:
101
- # 输出组信息
102
- logger.info(f"正在请求组服务器信息 {command}")
103
- server_dict = await get_much_server(server_json, command)
104
- if is_img:
105
- out_msg = await msg_to_image(server_dict)
106
- else:
107
- out_msg = server_dict
108
- return out_msg
98
+ return await _handle_group_info(server_json, command, is_img)
109
99
 
110
- # 返回单个
111
- logger.info("正在请求单服务器信息")
112
- out_msg = ""
100
+ _ip = await get_single_server_info(server_json, _id)
101
+ if _ip is None:
102
+ logger.warning("未找到这个服务器")
103
+ return None
104
+
105
+ out_msg = await _handle_single_server(server_json, _id, is_img)
106
+ if isinstance(out_msg, bytes):
107
+ return UniMessage.image(raw=out_msg) + UniMessage.text(
108
+ f"connect {_ip[0]}:{_ip[1]}",
109
+ )
110
+ if isinstance(out_msg, str):
111
+ return UniMessage.text(out_msg)
112
+ return None
113
+
114
+
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("正在获取单服务器信息")
113
171
  for i in server_json:
114
172
  if str(_id) == str(i["id"]):
115
- out_msg = await draw_one_ip(i["host"], i["port"])
116
- if is_img:
117
- return cast(bytes, out_msg)
118
- if not is_img:
119
- return cast(List[OutServer], out_msg)
120
- # print(out_msg)
173
+ return i["host"], i["port"]
121
174
  return None
122
175
 
123
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
+
124
204
  async def get_group_detail(
125
205
  command: str,
126
206
  ):
@@ -1,56 +1,193 @@
1
1
  import asyncio
2
2
 
3
3
  # from logging import log
4
+ import io
5
+ from pathlib import Path
4
6
  from typing import List, Tuple
5
7
 
8
+ from nonebot.log import logger
9
+ from PIL import Image, ImageDraw, ImageFont
10
+
6
11
  from ..config import config
7
12
  from ..utils.api.models import NserverOut, OutServer
8
13
  from ..utils.api.request import L4API
9
14
 
10
15
 
11
- async def draw_one_ip(host: str, port: int):
16
+ async def draw_one_ip(host: str, port: int, is_img: bool = config.l4_image):
12
17
  """输出单个ip"""
13
- # 先用文字凑合
14
18
  try:
15
19
  ser_list = await L4API.a2s_info([(host, port)], is_player=True)
16
20
  except asyncio.exceptions.TimeoutError:
17
21
  return "服务器无响应"
18
- player_msg = ""
19
22
  one_server = ser_list[0][0]
20
23
  one_player = ser_list[0][1]
21
24
 
22
- if len(one_player):
23
- max_duration_len = max(
24
- [len(str(await convert_duration(i.duration))) for i in one_player],
25
- )
26
- max_score_len = max(len(str(i.score)) for i in one_player)
27
-
28
- for player in one_player:
29
- soc = "[{:>{}}]".format(player.score, max_score_len)
30
- chines_dur = await convert_duration(player.duration)
31
- dur = "{:^{}}".format(chines_dur, max_duration_len)
32
- name_leg = len(player.name)
33
- if name_leg > 2:
34
- xing = "*" * (name_leg - 2)
35
- name = f"{player.name[0]}{xing}{player.name[-1]}"
36
- else:
37
- name = player.name
38
- player_msg += f"{soc} | {dur} | {name} \n"
39
- else:
40
- player_msg = "服务器感觉很安静啊"
41
-
42
- msg = f"""*{one_server.server_name}*
43
- 游戏: {one_server.folder}
44
- 地图: {one_server.map_name}
45
- 人数: {one_server.player_count}/{one_server.max_players}"""
46
- if one_server.ping is not None:
47
- msg += f"""
48
- ping: {one_server.ping * 1000:.0f}ms
49
- {player_msg}"""
50
- if config.l4_show_ip:
51
- msg += f"""
25
+ async def format_player_info(players: list) -> str:
26
+ """格式化玩家信息
27
+ Args:
28
+ players: 玩家对象列表
29
+ Returns:
30
+ 格式化后的玩家信息字符串
31
+ """
32
+ player_msg = ""
33
+ if len(players):
34
+ max_duration_len = max(
35
+ [len(str(await convert_duration(i.duration))) for i in players],
36
+ )
37
+ max_score_len = max(len(str(i.score)) for i in players)
38
+
39
+ for player in players:
40
+ soc = "[{:>{}}]".format(player.score, max_score_len)
41
+ chines_dur = await convert_duration(player.duration)
42
+ 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
49
+ player_msg += f"{soc} | {dur} | {name} \n"
50
+ else:
51
+ player_msg = "服务器感觉很安静啊"
52
+ return player_msg
53
+
54
+ def build_server_message(server, player_info: str) -> str:
55
+ """构建服务器信息消息
56
+ Args:
57
+ server: 服务器对象
58
+ player_info: 格式化后的玩家信息字符串
59
+ Returns:
60
+ 完整的服务器信息字符串
61
+ """
62
+ msg = f"""-{server.server_name}-
63
+ 游戏: {server.folder}
64
+ 地图: {server.map_name}
65
+ 人数: {server.player_count}/{server.max_players}"""
66
+ if server.ping is not None:
67
+ msg += f"""
68
+ ping: {server.ping * 1000:.0f}ms
69
+ {player_info}"""
70
+ if config.l4_show_ip:
71
+ msg += f"""
52
72
  connect {host}:{port}"""
53
- return msg
73
+ return msg
74
+
75
+ def draw_text_on_image(
76
+ text: str,
77
+ font: ImageFont.FreeTypeFont,
78
+ draw: ImageDraw.ImageDraw,
79
+ ) -> Image.Image:
80
+ """在图片上绘制文本
81
+ Args:
82
+ text: 要绘制的文本
83
+ font: PIL字体对象
84
+ draw: PIL绘图对象
85
+ Returns:
86
+ 包含绘制文本的PIL图片对象
87
+ """
88
+ try:
89
+ # 分割文本为标题行和内容行
90
+ lines = text.split("\n")
91
+ if not lines:
92
+ return Image.new("RGB", (600, 400), color=(73, 109, 137))
93
+
94
+ title = lines[0]
95
+ content = "\n".join(lines[1:]) if len(lines) > 1 else ""
96
+
97
+ # 计算各部分文字尺寸
98
+ title_bbox = font.getbbox(title)
99
+ title_width = title_bbox[2] - title_bbox[0]
100
+ title_height = title_bbox[3] - title_bbox[1]
101
+
102
+ content_width = 0
103
+ content_height = 0
104
+ if content:
105
+ content_lines = content.split("\n")
106
+ line_height = font.getbbox("A")[3] - font.getbbox("A")[1]
107
+ content_height = len(content_lines) * line_height
108
+ content_width = max(
109
+ font.getbbox(line)[2] - font.getbbox(line)[0]
110
+ for line in content_lines
111
+ )
112
+
113
+ # 计算图片尺寸
114
+ margin = 20
115
+ line_spacing = 5
116
+ img_width = max(title_width, content_width) + 2 * margin
117
+ content_lines_count = len(content.split("\n")) if content else 0
118
+ img_height = max(
119
+ title_height
120
+ + content_height
121
+ + (line_spacing + 1) * max(0, content_lines_count - 1)
122
+ + 2 * margin,
123
+ 300,
124
+ )
125
+
126
+ # 加载背景图片
127
+ bg_path = (
128
+ Path(__file__).parent.parent / "l4_image" / "img" / "anne" / "back.png"
129
+ )
130
+ try:
131
+ img = Image.open(bg_path)
132
+ # 调整背景图尺寸
133
+ img = img.resize((int(img_width), int(img_height)))
134
+ logger.info(f"图片像素大小: {img.width}x{img.height}")
135
+ draw = ImageDraw.Draw(img)
136
+
137
+ title_x = (img_width - title_width) // 2
138
+ title_y = margin
139
+ draw.text((title_x, title_y), title, font=font, fill=(255, 255, 255))
140
+
141
+ if content:
142
+ content_x = margin
143
+ 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
+ )
151
+
152
+ return img
153
+ except Exception as e:
154
+ logger.error(f"加载背景图片失败: {e}")
155
+ img = Image.new(
156
+ "RGB",
157
+ (int(img_width), int(img_height)),
158
+ color=(73, 109, 137),
159
+ )
160
+ draw = ImageDraw.Draw(img)
161
+ draw.text((title_x, title_y), title, font=font, fill=(255, 255, 255))
162
+ if content:
163
+ draw.text(
164
+ (content_x, content_y),
165
+ content,
166
+ font=font,
167
+ fill=(255, 255, 255),
168
+ spacing=line_spacing,
169
+ )
170
+ return img
171
+ except Exception as e:
172
+ logger.error(f"绘制图片时出错: {e}")
173
+ error_img = Image.new("RGB", (600, 400), color=(255, 0, 0))
174
+ error_draw = ImageDraw.Draw(error_img)
175
+ error_draw.text((10, 10), "图片生成失败", fill=(255, 255, 255))
176
+ return error_img
177
+
178
+ player_info = await format_player_info(one_player)
179
+ server_message = build_server_message(one_server, player_info)
180
+
181
+ if is_img:
182
+ # 加载字体
183
+ font_path = Path(__file__).parent.parent / "data" / "font" / "loli.ttf"
184
+ font = ImageFont.truetype(str(font_path), 18)
185
+ draw = ImageDraw.Draw(Image.new("RGB", (600, 400), color=(73, 109, 137)))
186
+ img = draw_text_on_image(server_message, font, draw)
187
+ img_byte_arr = io.BytesIO()
188
+ img.save(img_byte_arr, format="PNG")
189
+ return img_byte_arr.getvalue()
190
+ return server_message
54
191
 
55
192
 
56
193
  async def get_much_server(server_json: List[NserverOut], command: str):
@@ -64,7 +201,7 @@ async def get_much_server(server_json: List[NserverOut], command: str):
64
201
  for index, i in enumerate(all_server):
65
202
  out_server.append(
66
203
  {
67
- "server": i[0],
204
+ "server": i[0], # type: ignore
68
205
  "player": i[1],
69
206
  "host": server_json[index]["host"],
70
207
  "port": server_json[index]["port"],
@@ -22,7 +22,7 @@ class NserverOut(TypedDict):
22
22
 
23
23
 
24
24
  class OutServer(TypedDict):
25
- server: a2s.SourceInfo
25
+ server: a2s.SourceInfo[str]
26
26
  player: List[a2s.Player]
27
27
  host: str
28
28
  port: int
@@ -3,7 +3,7 @@ import contextlib
3
3
  import socket
4
4
  from copy import deepcopy
5
5
  from pathlib import Path
6
- from typing import Any, Dict, List, Literal, Optional, Tuple, cast
6
+ from typing import Any, Dict, List, Literal, Optional, Tuple, Union, cast
7
7
 
8
8
  import a2s
9
9
  import aiofiles
@@ -47,8 +47,12 @@ class L4D2Api:
47
47
  ip_list: List[Tuple[str, int]],
48
48
  is_server: bool = True,
49
49
  is_player: bool = False,
50
- ) -> List[Tuple[a2s.SourceInfo, List[a2s.Player]]]:
51
- msg_list: List[Tuple[a2s.SourceInfo, List[a2s.Player]]] = []
50
+ ) -> List[
51
+ Tuple[Union[a2s.SourceInfo[str], a2s.GoldSrcInfo[str]], List[a2s.Player]]
52
+ ]:
53
+ msg_list: List[
54
+ Tuple[Union[a2s.SourceInfo[str], a2s.GoldSrcInfo[str]], List[a2s.Player]]
55
+ ] = []
52
56
  sorted_msg_list = []
53
57
  tasks = [] # 用来保存异步任务
54
58
  if ip_list != []:
@@ -80,19 +84,24 @@ class L4D2Api:
80
84
  is_player: bool,
81
85
  ):
82
86
  play: List[a2s.Player] = []
87
+ server: Union[a2s.SourceInfo, a2s.GoldSrcInfo]
83
88
  if is_server:
84
89
  try:
85
- server: a2s.SourceInfo = await a2s.ainfo(ip, timeout=3, encoding="utf8")
90
+ server = await a2s.ainfo(
91
+ ip,
92
+ timeout=3,
93
+ encoding="utf8",
94
+ )
86
95
 
87
96
  if server is not None:
88
- server.steam_id = index
97
+ server.steam_id = index # type: ignore
89
98
 
90
99
  except (
91
100
  asyncio.exceptions.TimeoutError,
92
101
  ConnectionRefusedError,
93
102
  socket.gaierror,
94
103
  ):
95
- server: a2s.SourceInfo = a2s.SourceInfo(
104
+ server = a2s.SourceInfo(
96
105
  protocol=0,
97
106
  server_name="服务器无响应",
98
107
  map_name="无",
@@ -137,7 +146,7 @@ class L4D2Api:
137
146
  json: Optional[Dict[str, Any]] = None,
138
147
  data: Optional[Dict[str, Any]] = None,
139
148
  is_json: bool = True,
140
- ):
149
+ ) -> Union[Dict[str, Any], BeautifulSoup]: # type: ignore
141
150
  header = deepcopy(self._HEADER)
142
151
 
143
152
  if json is not None:
@@ -181,7 +190,17 @@ class L4D2Api:
181
190
  return BeautifulSoup(html_content, "lxml")
182
191
 
183
192
  async def get_sourceban(self, tag: str = "云", url: str = anne_ban):
184
- """从sourceban++获取服务器列表,目前未做名称处理"""
193
+ """
194
+ 异步函数,从sourceban++获取服务器列表,目前未做名称处理。
195
+
196
+ Args:
197
+ tag (str): 用于标识不同来源的标签,默认为"云"。
198
+ url (str): SourceBan的URL,默认为anne_ban。
199
+
200
+ Returns:
201
+ list: 包含服务器信息的列表。
202
+
203
+ """
185
204
  if not (url.startswith(("http://", "https://"))):
186
205
  url = "http://" + url # 默认添加 http://
187
206
  soup = await self._server_request(
@@ -272,14 +291,14 @@ class L4D2Api:
272
291
  if not isinstance(soup, BeautifulSoup):
273
292
  return None
274
293
 
275
- tbody = soup.find(
294
+ tbody = cast(BeautifulSoup, soup).find(
276
295
  "div",
277
296
  class_="content text-center text-md-left",
278
297
  style="background-color: #f2f2f2;",
279
298
  )
280
299
  if tbody is None:
281
300
  return None
282
- kill_tag = tbody.find(
301
+ kill_tag = cast(BeautifulSoup, tbody).find(
283
302
  "div",
284
303
  class_="card-body worldmap d-flex flex-column justify-content-center text-center",
285
304
  )
@@ -7,6 +7,7 @@ from typing import Any, Dict, List, Optional, Tuple
7
7
  import aiofiles
8
8
  import aiohttp
9
9
  import nonebot
10
+ from aiohttp import ClientTimeout
10
11
  from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent
11
12
  from nonebot.log import logger
12
13
  from nonebot_plugin_alconna import UniMessage
@@ -184,7 +185,11 @@ async def url_to_byte(url: str):
184
185
  """获取URL数据的字节流"""
185
186
 
186
187
  async with aiohttp.ClientSession() as session:
187
- async with session.get(url, headers=headers, timeout=600) as response:
188
+ async with session.get(
189
+ url,
190
+ headers=headers,
191
+ timeout=ClientTimeout(total=600),
192
+ ) as response:
188
193
  if response.status == 200:
189
194
  return await response.read()
190
195
  return None
@@ -194,7 +199,11 @@ async def url_to_msg(url: str):
194
199
  """获取URL数据的字节流"""
195
200
 
196
201
  async with aiohttp.ClientSession() as session:
197
- async with session.get(url, headers=headers, timeout=600) as response:
202
+ async with session.get(
203
+ url,
204
+ headers=headers,
205
+ timeout=ClientTimeout(total=600),
206
+ ) as response:
198
207
  if response.status == 200:
199
208
  return await response.text()
200
209
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nonebot-plugin-l4d2-server
3
- Version: 1.0.3
3
+ Version: 1.0.4
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>
@@ -32,7 +32,7 @@ Requires-Dist: ujson>=5.10.0
32
32
  Requires-Dist: lxml>=5.2.2
33
33
  Requires-Dist: rcon>=2.1.0
34
34
  Requires-Dist: pillow>10
35
- Requires-Dist: beautifulsoup4>=4.12.3
35
+ Requires-Dist: bs4>=0.0.2
36
36
  Requires-Dist: rarfile>=4.2
37
37
  Requires-Dist: pyunpack>=0.3
38
38
  Requires-Dist: aiofiles>=24.1.0
@@ -47,7 +47,7 @@ Description-Content-Type: text/markdown
47
47
 
48
48
  <div align="center">
49
49
 
50
- # nonebot_plugin_l4d2_server 1.0.0a1
50
+ # nonebot_plugin_l4d2_server 1.0.4
51
51
 
52
52
  _✨Nonebot & Left 4 Dead 2 server操作✨_
53
53
  <div align = "center">
@@ -77,15 +77,12 @@ _✨Nonebot & Left 4 Dead 2 server操作✨_
77
77
 
78
78
  ## 顶置公告(如果以前用0.x.x版本暂时别更新)
79
79
 
80
- - **版本** 1.x.x进行了破坏式更新,目前处于测试阶段,使用旧插件的不要更新
80
+ - **版本** 1.x.x进行了破坏式更新,使用旧插件的不要更新
81
81
 
82
- ## 更改部分
82
+ ## 指令
83
83
 
84
- - 取消了网页控制台(没有卵用)
85
- - 取消了自动重启(与其他插件功能重复)
86
- - 取消了git拉取更新(nb规范用pypi)
87
- - 增加pil和浏览器渲染做选择(可以选择pil以节省性能性能)
88
- - 删除无用部分(依赖太多难以维护)
84
+ - 在json文件设置的前缀指令,例如设置"云",则指令 云 输出组服务器,云1 输出1号服务器
85
+ - l4图片开启/关闭 超管指令 可以修改输出单图是否为图片输出
89
86
 
90
87
  ## 安装
91
88
 
@@ -142,8 +139,7 @@ conda install nonebot-plugin-l4d2-server
142
139
  ## 主要功能
143
140
 
144
141
  - [ ] 求生服务器-本地多路径操作(传地图等)
145
- - [ ] 批量查询指定ip服务器状态和玩家
146
- - [ ] [求生电信服anne](https://github.com/fantasylidong/CompetitiveWithAnne)[查询~](https://sb.trygek.com/l4d_stats/ranking/index.php)
142
+ - [x] 批量查询指定ip服务器状态和玩家
147
143
 
148
144
  ## [数据结构](./docs/standand.md)
149
145
 
@@ -152,8 +148,6 @@ conda install nonebot-plugin-l4d2-server
152
148
  ## env设置
153
149
 
154
150
  """bash
155
- l4_anne = False
156
- """是否启用anne电信服相关功能"""
157
151
  l4_enable = True
158
152
  """是否全局启用求生功能"""
159
153
  l4_image = False
@@ -172,6 +166,15 @@ conda install nonebot-plugin-l4d2-server
172
166
  - 缤纷彩虹
173
167
  """
174
168
 
169
+ ## 和0.x.x更改部分
170
+
171
+ - 取消了网页控制台(没有卵用)
172
+ - 取消了自动重启(与其他插件功能重复)
173
+ - 取消了git拉取更新(nb规范用pypi)
174
+ - 增加pil和浏览器渲染做选择(可以选择pil以节省性能性能)
175
+ - 删除无用部分(依赖太多难以维护)
176
+ - 删除了anne部分,已移植到[这里](https://github.com/Agnes4m/L4D2UID),通过core插件调用
177
+
175
178
  ## 其他
176
179
 
177
180
  - 本人技术很差,如果您有发现BUG或者更好的建议,欢迎提Issue & Pr
@@ -1,15 +1,13 @@
1
- nonebot_plugin_l4d2_server-1.0.3.dist-info/METADATA,sha256=po5LeZo-Nk7oQNuaxa5Ve_3AANnFc4RxG8fnBbcqeK0,6688
2
- nonebot_plugin_l4d2_server-1.0.3.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
- nonebot_plugin_l4d2_server-1.0.3.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
4
- nonebot_plugin_l4d2_server-1.0.3.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
1
+ nonebot_plugin_l4d2_server-1.0.4.dist-info/METADATA,sha256=kZdrFtRaRtfYjXvIapyyUJnulUxQPjtbzRAOHAVyBkA,6763
2
+ nonebot_plugin_l4d2_server-1.0.4.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
+ nonebot_plugin_l4d2_server-1.0.4.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
4
+ nonebot_plugin_l4d2_server-1.0.4.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
5
5
  nonebot_plugin_l4d2_server/__init__.py,sha256=PIufOk1bxOx-nYqdoinoB7BcntIETNFwfzqKnmu-teE,1624
6
- nonebot_plugin_l4d2_server/__main__.py,sha256=AGqPjt0O6dW_E3D93hcqehtsPsvzSRC1qEtx6HqEAGo,8455
7
- nonebot_plugin_l4d2_server/config.py,sha256=ZLYJr9lVs1Q5en1m4EA0wF7H366EVm8-6AnN8dcyy7c,1394
6
+ nonebot_plugin_l4d2_server/__main__.py,sha256=Z8laU36rLdNq-Qfroj-1t6dbt4rfKLetvJ1cY937oGo,10232
7
+ nonebot_plugin_l4d2_server/config.py,sha256=_UKAn1g5BbykMNc6LXRujKoGhpxIM5JAdh3z301BLHk,2665
8
8
  nonebot_plugin_l4d2_server/data/font/loli.ttf,sha256=Yrh-RPoCrn1-NG94DR0x20ASXYUt8g3Ep6BCt3CdOFk,11125812
9
- nonebot_plugin_l4d2_server/l4_anne/__init__.py,sha256=zX4kTu4LAsqm7_li0-GcihnbYI65SBPkfUCPTs79U8k,4124
10
- nonebot_plugin_l4d2_server/l4_anne/ranne.py,sha256=vtNQJ-74rJiwVI3IYS3ZgFk_LaCviKU1yxrGk3DFvQs,532
11
9
  nonebot_plugin_l4d2_server/l4_help/Help.json,sha256=hz_k-qmGmGJKwCa8wmkHTLzXu6C-G-E_g7xdK-t6fNk,2673
12
- nonebot_plugin_l4d2_server/l4_help/__init__.py,sha256=YNR3eob0XvRb_-4wIP9ZcSMey0RuFS4RlHMZ217Bn0E,1535
10
+ nonebot_plugin_l4d2_server/l4_help/__init__.py,sha256=sZRp6HJE2hvEcSST7CXJk8eAyv6rj4kLIcOK_7xUTI0,1535
13
11
  nonebot_plugin_l4d2_server/l4_help/draw.py,sha256=y6yDPUnoZFvwly8cf7g9HRpT1JXTxyA9DC1TuvUinTM,6448
14
12
  nonebot_plugin_l4d2_server/l4_help/icon/介绍.png,sha256=3QC6A38QC-7gDBxmtQSQdbsz7hsefU5LL-oZmJ41zTk,3806
15
13
  nonebot_plugin_l4d2_server/l4_help/icon/任务.png,sha256=nyZ4_kM21ZO95nwanCFnUfCGX-PkmJXYQf9OrJVKomY,3782
@@ -88,12 +86,12 @@ nonebot_plugin_l4d2_server/l4_image/model.py,sha256=FGsCvf_BKbRNJUVy6I5BKnArMY-3
88
86
  nonebot_plugin_l4d2_server/l4_image/vtfs.py,sha256=He_7zzEIOip8MXP55TS7aWPbzo6ac0wPf602nN3GWZM,1461
89
87
  nonebot_plugin_l4d2_server/l4_local/__init__.py,sha256=nz9KUxmuvRrryHakQQ4B30oC9jeGWZ3sON1tCKb-lS0,3603
90
88
  nonebot_plugin_l4d2_server/l4_local/file.py,sha256=hew1Y8kV3uSZvUGplmi09EGKC89-sUJWsWV7SCEstI8,3067
91
- nonebot_plugin_l4d2_server/l4_request/__init__.py,sha256=ukb90pROfHtLbIRSya5pRAGSpzB9Bb5gPi3kAH2-41Y,9588
92
- nonebot_plugin_l4d2_server/l4_request/draw_msg.py,sha256=efmlEBqbbOozf50InPNqONGIZ0D2hI4xAGPDROIcHBY,2883
89
+ nonebot_plugin_l4d2_server/l4_request/__init__.py,sha256=9Yo6mQ_bIBvMwQubC3Ctie6H2Qzx7ScwCQyVS9y25TE,11682
90
+ nonebot_plugin_l4d2_server/l4_request/draw_msg.py,sha256=koAVWrsDoLCTmwXY-NJTi5yjL1y1ND3daFkDWccQjcU,8071
93
91
  nonebot_plugin_l4d2_server/l4_request/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
92
  nonebot_plugin_l4d2_server/utils/api/api.py,sha256=auvDicCEKwvnm6EJYeCxCtugFby61K-zAmmaRWWEwtM,296
95
- nonebot_plugin_l4d2_server/utils/api/models.py,sha256=EKAAM5RsFK-hV-a80tc4r35ToNRhnCWVuQ-7imwBjwE,2386
96
- nonebot_plugin_l4d2_server/utils/api/request.py,sha256=hugBaPBK-gUr5Xemyk7dSHP1JlzYrEZcXPinkNX0AuU,14987
93
+ nonebot_plugin_l4d2_server/utils/api/models.py,sha256=p-hoxPHwadTaMRb2hqwfbaQ3pvJySrV8VbBmhA0Oi-M,2391
94
+ nonebot_plugin_l4d2_server/utils/api/request.py,sha256=aAsXtxvm7erXLfFCbs6NmsZCRGpsg3tsMdWvSn8SkNU,15575
97
95
  nonebot_plugin_l4d2_server/utils/database/models.py,sha256=SLdcgwsn39r_ZkcBoqf4MLX1EfpCOjGBwWcR16u9Bqo,454
98
- nonebot_plugin_l4d2_server/utils/utils.py,sha256=C-QzwtUCbq7QXmHplpmo3OTKbRztE1W7V-IywvufDl0,5971
99
- nonebot_plugin_l4d2_server-1.0.3.dist-info/RECORD,,
96
+ nonebot_plugin_l4d2_server/utils/utils.py,sha256=TD3cUCxmmj2GPmK1sQwP7NtkIXNO2FpuXjymaUqBDYo,6141
97
+ nonebot_plugin_l4d2_server-1.0.4.dist-info/RECORD,,
@@ -1,125 +0,0 @@
1
- from nonebot import log as log
2
- from nonebot import on_command
3
- from nonebot.adapters import Event, Message
4
- from nonebot.log import logger
5
- from nonebot.params import CommandArg
6
- from nonebot_plugin_alconna import UniMessage
7
-
8
- from ..utils.api.request import L4API
9
- from ..utils.database.models import SteamUser
10
- from ..utils.utils import get_message_at
11
- from .ranne import get_anne_rank_out
12
-
13
- anne_bind = on_command("Banne", aliases={"l4绑定", "anne绑定"}, priority=5, block=True)
14
- anne_search = on_command("Sanne", aliases={"anne搜索"})
15
- anne_rank = on_command("Ranne", aliases={"anne成绩"}, block=True, priority=1)
16
-
17
- anne_del = on_command(
18
- "Danne",
19
- aliases={"l4删除", "anne删除", "l4解绑", "anne解绑"},
20
- priority=5,
21
- block=True,
22
- )
23
-
24
-
25
- @anne_search.handle()
26
- async def _(args: Message = CommandArg()):
27
- name: str = args.extract_plain_text().strip()
28
- print(name)
29
- user_list = await L4API.get_anne_steamid(name)
30
- if user_list is None:
31
- await UniMessage.text("未找到玩家").finish()
32
- msg = f"---有{len(user_list)}个玩家---"
33
- for index, user in enumerate(user_list, start=1):
34
- if index >= 10:
35
- break
36
- msg += f"""
37
- {index}. {user["name"]} | [{user["score"]}] | {user["play_time"]}
38
- {user["steamid"]}
39
- """
40
- if msg:
41
- await UniMessage.text("\n".join(msg.splitlines())).finish()
42
- else:
43
- await UniMessage.text("没有找到玩家").finish()
44
-
45
-
46
- @anne_bind.handle()
47
- async def _(ev: Event, args: Message = CommandArg()):
48
- arg: str = args.extract_plain_text()
49
- if not arg:
50
- await UniMessage.text("虚空绑定?").finish()
51
-
52
- user = await SteamUser.get_or_none(userid=int(ev.get_user_id()))
53
- if user is None:
54
- user = await SteamUser.create(userid=int(ev.get_user_id()))
55
-
56
- if len(arg) == 17:
57
- # steamid64
58
- logger.info(f"SteamID64:{arg}")
59
- user.SteamID64 = arg
60
- msg = "绑定steamid64"
61
-
62
- elif arg.startswith("STEAM_"):
63
- # steamid
64
- logger.info(f"SteamID:{arg}")
65
- user.SteamID = arg
66
- msg = "绑定steamid"
67
-
68
- else:
69
- # name
70
- logger.info(f"Name:{arg}")
71
- user.Name = arg
72
- msg = "绑定名字"
73
- await user.save()
74
-
75
- return await UniMessage.text(f"{msg}成功").finish()
76
-
77
-
78
- @anne_del.handle()
79
- async def _(ev: Event):
80
- if record := await SteamUser.get_or_none(userid=int(ev.get_user_id())):
81
- logger.info(f"删除用户:{record}")
82
- await record.delete()
83
- await record.save()
84
- return await UniMessage.text("删除成功").finish()
85
- return await UniMessage.text("没有绑定信息呢").finish()
86
-
87
-
88
- @anne_rank.handle()
89
- async def _(ev: Event, args: Message = CommandArg()):
90
- uid = await get_message_at(str(ev.json()))
91
- if uid is None:
92
- uid = int(int(ev.get_user_id()))
93
- steamid = ""
94
- arg: str = args.extract_plain_text().strip()
95
- logger.info(f"arg:{arg}")
96
- # 优先从数据库查询
97
- if not arg:
98
- msg = await SteamUser.get_or_none(userid=uid)
99
- if msg is not None:
100
- steamid = msg.SteamID
101
- if not steamid:
102
- name = msg.Name
103
- if not name:
104
- await UniMessage.text("未绑定名字/steamid").finish()
105
- msg_dict = await L4API.get_anne_steamid(name)
106
- if not msg_dict:
107
- await UniMessage.text("绑定的昵称找不到呢").finish()
108
- steamid = msg_dict[0]["steamid"]
109
- logger.info(f"steamid:{steamid}")
110
-
111
- # 再从arg中查找
112
- else:
113
- if arg.startswith("STEAM_"):
114
- steamid = arg
115
- else:
116
- arg_dict = await L4API.get_anne_steamid(arg)
117
- if not arg_dict:
118
- await UniMessage.text("未找到该昵称玩家").finish()
119
- steamid = arg_dict[0]["steamid"]
120
- if not steamid:
121
- await UniMessage.text("未找到玩家,请使用指令`l4搜索`查找").finish()
122
- out_msg = await get_anne_rank_out(steamid)
123
- if out_msg is None:
124
- await UniMessage.text("未找到玩家").finish()
125
- await UniMessage.text(out_msg).finish()
@@ -1,18 +0,0 @@
1
- # coding=utf-8
2
- # anne战绩查询
3
- from ..utils.api.request import L4API
4
-
5
-
6
- async def get_anne_rank_out(steamid: str):
7
- msg = await L4API.get_anne_playerdetail(steamid)
8
- if msg is None:
9
- return None
10
- return f"""电信anne查询结果:
11
- 昵称:{msg['info']['name']}
12
- 排名:{msg['detail']['rank']}
13
- 分数:{msg['detail']["source"]}
14
- 击杀:{msg['detail']["kills"]}
15
- 爆头率:{msg['detail']["avg_source"]}
16
- 时间:{msg['info']['playtime']}
17
- 上次:{msg['info']['lasttime']}
18
- """