nonebot-plugin-l4d2-server 1.0.8__tar.gz → 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/PKG-INFO +1 -1
  2. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/__main__.py +6 -18
  3. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/__init__.py +1 -1
  4. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/convert.py +9 -3
  5. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_local/__init__.py +30 -1
  6. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_request/__init__.py +26 -4
  7. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_request/draw_msg.py +92 -22
  8. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_request/utils.py +4 -5
  9. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/utils/utils.py +23 -0
  10. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/pyproject.toml +1 -1
  11. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/LICENSE +0 -0
  12. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/README.md +0 -0
  13. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/__init__.py +0 -0
  14. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/config.py +0 -0
  15. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/data/font/loli.ttf +0 -0
  16. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/Help.json +0 -0
  17. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/draw.py +0 -0
  18. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//344/273/213/347/273/215.png" +0 -0
  19. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//344/273/273/345/212/241.png" +0 -0
  20. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//344/277/241/346/201/257.png" +0 -0
  21. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//345/205/254/345/221/212.png" +0 -0
  22. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//345/210/200/345/211/221.png" +0 -0
  23. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//345/210/207/346/215/242.png" +0 -0
  24. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//345/210/240/351/231/244.png" +0 -0
  25. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//345/210/267/346/226/260.png" +0 -0
  26. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//345/215/241/347/273/204.png" +0 -0
  27. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//345/223/252/351/207/214.png" +0 -0
  28. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//345/234/260/345/233/276.png" +0 -0
  29. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//345/257/274/345/205/245.png" +0 -0
  30. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//345/257/274/345/207/272.png" +0 -0
  31. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//345/275/261.png" +0 -0
  32. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/213/274/345/233/276.png" +0 -0
  33. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/216/242/347/264/242.png" +0 -0
  34. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/216/250/351/200/201.png" +0 -0
  35. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/224/266/351/233/206.png" +0 -0
  36. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/224/273/347/225/245.png" +0 -0
  37. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/233/264/346/226/260.png" +0 -0
  38. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/235/220/346/226/231.png" +0 -0
  39. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/237/245/350/257/242.png" +0 -0
  40. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/240/241/351/252/214.png" +0 -0
  41. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/257/217/346/234/210.png" +0 -0
  42. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/267/261/346/270/212.png" +0 -0
  43. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/267/273/345/212/240.png" +0 -0
  44. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//346/270/205/351/231/244.png" +0 -0
  45. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//347/212/266/346/200/201.png" +0 -0
  46. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//347/255/276/345/210/260.png" +0 -0
  47. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//347/273/221/345/256/232.png" +0 -0
  48. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//350/241/250.png" +0 -0
  49. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//350/241/250/346/203/205.png" +0 -0
  50. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//350/247/222/350/211/262.png" +0 -0
  51. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//350/256/260/345/275/225.png" +0 -0
  52. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//351/205/215/347/275/256.png" +0 -0
  53. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/icon//351/207/215/345/220/257.png" +0 -0
  54. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/texture2d/badge.png +0 -0
  55. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/texture2d/banner.png +0 -0
  56. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/texture2d/bg.jpg +0 -0
  57. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/texture2d/button.png +0 -0
  58. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_help/texture2d/icon.png +0 -0
  59. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/__init__.py +0 -0
  60. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/download.py +0 -0
  61. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/html_img.py +0 -0
  62. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/image_tools.py +0 -0
  63. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/anne/anne.html +0 -0
  64. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/anne/back.png +0 -0
  65. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/anne/back1.jpg +0 -0
  66. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/anne/group_ip.html +0 -0
  67. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/anne/ip.html +0 -0
  68. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/head/head.png +0 -0
  69. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/header/logo.png +0 -0
  70. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/header/player1.jpg +0 -0
  71. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/Bocchi_The_Rock.html +0 -0
  72. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/Bocchi_The_Rock.png +0 -0
  73. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/HYPixel11pxU-2.ttf +0 -0
  74. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/Pixel.html +0 -0
  75. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/Pixel.png +0 -0
  76. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/Rainbow.html +0 -0
  77. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/Rainbow.png +0 -0
  78. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/Tutumianhuatang-Bold-2.ttf +0 -0
  79. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/bilibili.svg +0 -0
  80. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/fingerprint.svg +0 -0
  81. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/github.svg +0 -0
  82. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/l.svg +0 -0
  83. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/m.svg +0 -0
  84. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/normal.html +0 -0
  85. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/vac.png +0 -0
  86. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/vac_white.png +0 -0
  87. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/vue.css +0 -0
  88. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/img/template/w.svg +0 -0
  89. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/model.py +0 -0
  90. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_image/vtfs.py +0 -0
  91. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/l4_local/file.py +0 -0
  92. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/utils/api/api.py +0 -0
  93. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/utils/api/models.py +0 -0
  94. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/utils/api/request.py +0 -0
  95. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/utils/api/utils.py +0 -0
  96. {nonebot_plugin_l4d2_server-1.0.8 → nonebot_plugin_l4d2_server-1.1.0}/nonebot_plugin_l4d2_server/utils/database/models.py +0 -0
@@ -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.1.0
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>
@@ -42,7 +42,7 @@ from .l4_request import (
42
42
  )
43
43
  from .utils.api.request import L4API
44
44
  from .utils.api.utils import out_msg_out
45
- from .utils.utils import split_maohao
45
+ from .utils.utils import log_and_send, read_config, split_maohao, write_config
46
46
 
47
47
  if TYPE_CHECKING:
48
48
  from .utils.api.models import OutServer
@@ -131,6 +131,8 @@ async def _(
131
131
  ):
132
132
  # 以后有时间补img格式
133
133
  msg: str = args.extract_plain_text().strip()
134
+ if not msg:
135
+ return UniMessage.text("请在指令后添加要找的昵称哦")
134
136
  tag_list: List[str] = msg.split(" ", maxsplit=1)
135
137
  if len(tag_list) == 1:
136
138
  await UniMessage.text("未设置组,正在全服查找,时间较长").send()
@@ -202,29 +204,15 @@ l4_add_ban = on_command("l4addban", aliases={"l4添加ban"})
202
204
  @l4_add_ban.handle()
203
205
  async def _(args: Message = CommandArg()):
204
206
  arg = args.extract_plain_text().strip().split(" ")
205
-
206
207
  if len(arg) != 2:
207
208
  await UniMessage.text("请在命令后增加响应指令名和网址").finish()
208
209
 
209
- if not config_path.is_file():
210
- config_data = {}
211
- else:
212
- try:
213
- with config_path.open("r") as f:
214
- config_data = json.load(f)
215
- except (json.JSONDecodeError, FileNotFoundError):
216
- config_data = {}
217
-
210
+ config_data = read_config(config_path)
218
211
  config_data.update({arg[0]: arg[1]})
219
-
220
- try:
221
- with config_path.open("w") as f:
222
- json.dump(config_data, f, ensure_ascii=False, indent=4)
223
- except IOError as e:
224
- await UniMessage.text(f"文件写入失败: {e}").finish()
212
+ write_config(config_path, config_data)
225
213
 
226
214
  await L4API.get_sourceban(arg[0], arg[1])
227
- await out_msg_out(f"添加成功\n组名: {arg[0]}\n网址: {arg[1]}")
215
+ await log_and_send(l4_add_ban, f"添加成功\n组名: {arg[0]}\n网址: {arg[1]}")
228
216
 
229
217
 
230
218
  l4_del_ban = on_command("l4delban", aliases={"l4删除ban", "l4移除ban"})
@@ -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.1.0"
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,6 +119,7 @@ async def get_group_detail(
119
119
  command: str,
120
120
  ):
121
121
  server_json = _get_server_json(command, ALLHOST)
122
+ # logger.debug(f"获取组服务器信息: {server_json}")
122
123
  logger.info(server_json)
123
124
  if server_json is None:
124
125
  logger.warning("未找到这个组")
@@ -170,7 +171,7 @@ def reload_ip():
170
171
  async def tj_request(command: str = "云", tj="tj"):
171
172
  map_type = "普通药役"
172
173
  server_json = ALLHOST.get(command)
173
- logger.info(server_json)
174
+ logger.debug(server_json)
174
175
  if server_json is None:
175
176
  logger.warning("未找到这个组")
176
177
  return None
@@ -186,8 +187,9 @@ async def tj_request(command: str = "云", tj="tj"):
186
187
  logger.warning("没有找到符合条件的服务器")
187
188
  return "没有符合条件的服务器"
188
189
 
190
+ server_list_str = [f"{ip['host']}:{ip['port']}" for ip in right_ip]
189
191
  logger.info(
190
- f"符合条件的服务器列表: {[f'{ip['host']}:{ip['port']}' for ip in right_ip]}",
192
+ f"符合条件的服务器列表: {server_list_str}",
191
193
  )
192
194
  s = random.choice(right_ip)
193
195
  logger.info(f"最终选择的服务器: {s['host']}:{s['port']}")
@@ -211,11 +213,15 @@ async def tj_request(command: str = "云", tj="tj"):
211
213
 
212
214
 
213
215
  async def server_find(
214
- command: str = "",
216
+ command: str = "",
215
217
  _id: Optional[str] = None,
216
218
  is_img: bool = True,
217
219
  ):
218
- server_json = _get_server_json(command, ALLHOST)
220
+ all_command = get_all_json_filenames()
221
+ server_json = []
222
+ for one_command in all_command:
223
+ server_j = _get_server_json(one_command, ALLHOST)
224
+ server_json.extend(server_j)
219
225
  logger.info(server_json)
220
226
  if server_json is None:
221
227
  logger.warning("未找到这个组")
@@ -238,3 +244,19 @@ async def server_find(
238
244
  if isinstance(out_msg, str):
239
245
  return UniMessage.text(out_msg)
240
246
  return None
247
+
248
+
249
+ def get_all_json_filenames():
250
+ """
251
+ 获取 server_all_path 路径下所有 json 文件的文件名(不带扩展名)的列表。
252
+ """
253
+ json_files = []
254
+ for item in server_all_path.iterdir():
255
+ if item.is_file() and item.suffix == ".json":
256
+ json_files.append(item.stem)
257
+ return json_files
258
+
259
+
260
+ # 使用示例
261
+
262
+ # all_json_names 现在是一个包含所有 json 文件名(不带扩展名)的 list
@@ -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,16 @@ async def draw_one_ip(host: str, port: int, is_img: bool = config.l4_image):
59
52
  Returns:
60
53
  完整的服务器信息字符串
61
54
  """
55
+
56
+ vac_status = "启用" if server.vac_enabled else "禁用"
62
57
  msg = f"""-{server.server_name}-
63
58
  游戏: {server.folder}
64
59
  地图: {server.map_name}
65
- 人数: {server.player_count}/{server.max_players}"""
60
+ 人数: {server.player_count} / {server.max_players}"""
66
61
  if server.ping is not None:
67
62
  msg += f"""
68
- ping: {server.ping * 1000:.0f}ms
63
+ 延迟: {server.ping * 1000:.0f} ms
64
+ VAC : {vac_status}\n
69
65
  {player_info}"""
70
66
  if config.l4_show_ip:
71
67
  msg += f"""
@@ -112,7 +108,7 @@ connect {host}:{port}"""
112
108
 
113
109
  # 计算图片尺寸
114
110
  margin = 20
115
- line_spacing = 5
111
+ line_spacing = 7
116
112
  img_width = max(title_width, content_width) + 2 * margin
117
113
  content_lines_count = len(content.split("\n")) if content else 0
118
114
  img_height = max(
@@ -141,13 +137,87 @@ connect {host}:{port}"""
141
137
  if content:
142
138
  content_x = margin
143
139
  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
- )
140
+
141
+ # 定义不同参数值的颜色(冒号后的内容)
142
+ value_colors = {
143
+ "游戏: ": (200, 180, 255), # 淡紫
144
+ "地图: ": (166, 202, 253), # 淡蓝
145
+ "人数: ": (100, 255, 100), # 绿色
146
+ "延迟: ": (100, 255, 100), # 绿色
147
+ "类型: ": (180, 220, 255), # 淡蓝
148
+ "密码: ": (255, 255, 255), # 白色
149
+ # connect不修改,保持原逻辑
150
+ }
151
+
152
+ # 按行绘制内容
153
+ current_y = content_y
154
+ for line in content_lines:
155
+ # 检查是否是参数行
156
+ colored = False
157
+ for prefix, color in value_colors.items():
158
+ if line.startswith(prefix):
159
+ # 绘制完整参数名(白色)
160
+ prefix_part = prefix
161
+ prefix_width = (
162
+ font.getbbox(prefix_part)[2]
163
+ - font.getbbox(prefix_part)[0]
164
+ )
165
+ draw.text(
166
+ (content_x, current_y),
167
+ prefix_part,
168
+ font=font,
169
+ fill=(255, 255, 255),
170
+ )
171
+
172
+ # 绘制参数值(带颜色)
173
+ value_part = line[len(prefix) :].strip()
174
+ draw.text(
175
+ (content_x + prefix_width, current_y),
176
+ value_part,
177
+ font=font,
178
+ fill=color,
179
+ )
180
+
181
+ colored = True
182
+ break
183
+ # 特殊处理VAC行
184
+ if not colored and line.startswith("VAC :"):
185
+ prefix = "VAC : "
186
+ prefix_width = (
187
+ font.getbbox(prefix)[2] - font.getbbox(prefix)[0]
188
+ )
189
+ draw.text(
190
+ (content_x, current_y),
191
+ prefix,
192
+ font=font,
193
+ fill=(255, 255, 255),
194
+ )
195
+
196
+ value_part = line[len(prefix) :].strip()
197
+ vac_color = (
198
+ (70, 209, 110)
199
+ if value_part == "启用"
200
+ else (255, 90, 90)
201
+ ) # 启用绿/禁用红
202
+ draw.text(
203
+ (content_x + prefix_width, current_y),
204
+ value_part,
205
+ font=font,
206
+ fill=vac_color,
207
+ )
208
+
209
+ colored = True
210
+
211
+ # 普通行(玩家信息)和connect保持原样
212
+ if not colored:
213
+ draw.text(
214
+ (content_x, current_y),
215
+ line,
216
+ font=font,
217
+ fill=(255, 255, 255),
218
+ )
219
+
220
+ current_y += line_height + line_spacing
151
221
 
152
222
  return img
153
223
  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
 
@@ -22,11 +22,13 @@ def _get_server_json(
22
22
  Returns:
23
23
  Optional[list]: 服务器JSON列表,未找到组时返回None
24
24
  """
25
+ logger.debug(f"获取服务器组 {allhost} 的信息")
25
26
  if command:
26
27
  return allhost.get(command)
27
28
  server_json = []
28
29
  for servers in allhost.values():
29
30
  server_json.extend(servers)
31
+ logger.debug(f"获取到的服务器组信息: {server_json}")
30
32
  return server_json
31
33
 
32
34
 
@@ -95,10 +97,7 @@ async def _handle_single_server(
95
97
  return None
96
98
 
97
99
  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
100
+ return await draw_one_ip(host, port, is_img=is_img)
102
101
 
103
102
 
104
103
  async def _filter_servers(
@@ -13,6 +13,29 @@ from nonebot.log import logger
13
13
  from nonebot_plugin_alconna import UniMessage
14
14
 
15
15
 
16
+ async def log_and_send(matcher, message: str, level="info"):
17
+ getattr(logger, level)(message)
18
+ await matcher.finish(UniMessage.text(message))
19
+
20
+
21
+ def read_config(config_path: Path) -> dict:
22
+ if not config_path.is_file():
23
+ return {}
24
+ try:
25
+ with config_path.open("r", encoding="utf-8") as f:
26
+ return json.load(f)
27
+ except (json.JSONDecodeError, FileNotFoundError):
28
+ return {}
29
+
30
+
31
+ def write_config(config_path: Path, data: dict) -> None:
32
+ try:
33
+ with config_path.open("w", encoding="utf-8") as f:
34
+ json.dump(data, f, ensure_ascii=False, indent=4)
35
+ except IOError as e:
36
+ raise RuntimeError(f"配置写入失败: {e}") from e
37
+
38
+
16
39
  async def get_file(url: str, down_file: Path):
17
40
  """
18
41
  下载指定Url到指定位置
@@ -47,7 +47,7 @@ classifiers = [
47
47
  "Operating System :: OS Independent",
48
48
  ]
49
49
  readme = "README.md"
50
- version = "1.0.8"
50
+ version = "1.1.0"
51
51
 
52
52
  [project.license]
53
53
  text = "GPLv3"