nonebot-plugin-l4d2-server 1.0.0a2__tar.gz → 1.0.1__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.
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/PKG-INFO +4 -6
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/README.md +2 -3
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/__main__.py +90 -1
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/config.py +7 -1
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_anne/__init__.py +2 -1
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/Help.json +8 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/__init__.py +1 -1
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//344/273/213/347/273/215.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//344/273/273/345/212/241.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//344/277/241/346/201/257.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//345/205/254/345/221/212.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//345/210/200/345/211/221.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//345/210/207/346/215/242.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//345/210/240/351/231/244.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//345/210/267/346/226/260.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//345/215/241/347/273/204.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//345/223/252/351/207/214.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//345/234/260/345/233/276.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//345/257/274/345/205/245.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//345/257/274/345/207/272.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//345/275/261.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/213/274/345/233/276.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/216/242/347/264/242.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/216/250/351/200/201.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/224/266/351/233/206.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/224/273/347/225/245.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/233/264/346/226/260.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/235/220/346/226/231.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/237/245/350/257/242.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/240/241/351/252/214.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/257/217/346/234/210.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/267/261/346/270/212.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/267/273/345/212/240.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//346/270/205/351/231/244.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//347/212/266/346/200/201.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//347/255/276/345/210/260.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//347/273/221/345/256/232.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//350/241/250.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//350/241/250/346/203/205.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//350/247/222/350/211/262.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//350/256/260/345/275/225.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//351/205/215/347/275/256.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/icon//351/207/215/345/220/257.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/texture2d/badge.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/texture2d/banner.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/texture2d/bg.jpg +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/texture2d/button.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/texture2d/icon.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/anne_pil.py +3 -2
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/convert.py +8 -12
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/download.py +5 -3
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/html_img.py +2 -2
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/image_tools.py +8 -5
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/anne/back.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/anne/back1.jpg +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/head/head.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/header/logo.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/header/player1.jpg +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/Bocchi_The_Rock.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/Pixel.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/Rainbow.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/vac.png +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/vac_white.png +0 -0
- nonebot_plugin_l4d2_server-1.0.1/nonebot_plugin_l4d2_server/l4_local/__init__.py +98 -0
- nonebot_plugin_l4d2_server-1.0.1/nonebot_plugin_l4d2_server/l4_local/file.py +105 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_request/__init__.py +70 -4
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_request/draw_msg.py +8 -3
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/utils/api/request.py +25 -1
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/utils/utils.py +13 -2
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/pyproject.toml +47 -1
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/LICENSE +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/__init__.py +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/data/font/loli.ttf +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_anne/ranne.py +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_help/draw.py +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/__init__.py +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/anne/anne.html +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/anne/group_ip.html +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/anne/ip.html +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/Bocchi_The_Rock.html +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/HYPixel11pxU-2.ttf +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/Pixel.html +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/Rainbow.html +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/Tutumianhuatang-Bold-2.ttf +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/bilibili.svg +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/fingerprint.svg +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/github.svg +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/l.svg +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/m.svg +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/normal.html +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/vue.css +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/img/template/w.svg +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/model.py +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_image/vtfs.py +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/l4_request/utils.py +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/utils/api/api.py +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/utils/api/models.py +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a2 → nonebot_plugin_l4d2_server-1.0.1}/nonebot_plugin_l4d2_server/utils/database/models.py +0 -0
@@ -1,9 +1,8 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: nonebot-plugin-l4d2-server
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.1
|
4
4
|
Summary: L4D2 server related operations plugin for NoneBot2
|
5
5
|
Keywords: steam,game,l4d2,nonebot2,plugin
|
6
|
-
Home-page: https://github.com/Agnes4m/nonebot_plugin_l4d2_server
|
7
6
|
Author-Email: Agnes_Digital <Z735803792@163.com>
|
8
7
|
License: GPLv3
|
9
8
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
@@ -13,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.10
|
14
13
|
Classifier: Programming Language :: Python :: 3.11
|
15
14
|
Classifier: Operating System :: OS Independent
|
16
|
-
Project-URL:
|
15
|
+
Project-URL: homepage, https://github.com/Agnes4m/nonebot_plugin_l4d2_server
|
17
16
|
Requires-Python: <4.0,>=3.9
|
18
17
|
Requires-Dist: nonebot2>=2.0.0
|
19
18
|
Requires-Dist: nonebot-plugin-htmlrender>=0.3.0
|
@@ -87,7 +86,6 @@ _✨Nonebot & Left 4 Dead 2 server操作✨_
|
|
87
86
|
|
88
87
|
以下提到的方法 任选**其一** 即可
|
89
88
|
|
90
|
-
|
91
89
|
<details open>
|
92
90
|
<summary>[推荐] 使用 nb-cli 安装</summary>
|
93
91
|
在 nonebot2 项目的根目录下打开命令行, 输入以下指令即可安装
|
@@ -164,7 +162,7 @@ conda install nonebot-plugin-l4d2-server
|
|
164
162
|
l4_style = "default"
|
165
163
|
"""图片风格,可选包括以下,默认简洁
|
166
164
|
- 暗风格
|
167
|
-
- 孤独摇滚
|
165
|
+
- 孤独摇滚
|
168
166
|
- 电玩像素
|
169
167
|
- 缤纷彩虹
|
170
168
|
"""
|
@@ -185,7 +183,7 @@ conda install nonebot-plugin-l4d2-server
|
|
185
183
|
- 水果 - html图片优化
|
186
184
|
|
187
185
|
- 感谢以下服主大力支持
|
188
|
-
- Michaela's | 机器人功能测试反馈
|
186
|
+
- Michaela's | 机器人功能测试反馈
|
189
187
|
- 东 | 提供docker部署方法等建议 | [电信服anne游戏群](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=6i7r5aJ7Jyg0ejby4rt9GWmFRF53nV1K&authKey=ekMsWepBZPL26%2BfJAG%2F95JD0fhvH39%2BIGVyKOvNlXVDbpIclJlly4kXqukL7JhWR&noverify=0&group_code=883237206)
|
190
188
|
- 迷茫 | 催命更新byd
|
191
189
|
- ArcPav | 积极反馈bug,提供改进思路
|
@@ -51,7 +51,6 @@ _✨Nonebot & Left 4 Dead 2 server操作✨_
|
|
51
51
|
|
52
52
|
以下提到的方法 任选**其一** 即可
|
53
53
|
|
54
|
-
|
55
54
|
<details open>
|
56
55
|
<summary>[推荐] 使用 nb-cli 安装</summary>
|
57
56
|
在 nonebot2 项目的根目录下打开命令行, 输入以下指令即可安装
|
@@ -128,7 +127,7 @@ conda install nonebot-plugin-l4d2-server
|
|
128
127
|
l4_style = "default"
|
129
128
|
"""图片风格,可选包括以下,默认简洁
|
130
129
|
- 暗风格
|
131
|
-
- 孤独摇滚
|
130
|
+
- 孤独摇滚
|
132
131
|
- 电玩像素
|
133
132
|
- 缤纷彩虹
|
134
133
|
"""
|
@@ -149,7 +148,7 @@ conda install nonebot-plugin-l4d2-server
|
|
149
148
|
- 水果 - html图片优化
|
150
149
|
|
151
150
|
- 感谢以下服主大力支持
|
152
|
-
- Michaela's | 机器人功能测试反馈
|
151
|
+
- Michaela's | 机器人功能测试反馈
|
153
152
|
- 东 | 提供docker部署方法等建议 | [电信服anne游戏群](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=6i7r5aJ7Jyg0ejby4rt9GWmFRF53nV1K&authKey=ekMsWepBZPL26%2BfJAG%2F95JD0fhvH39%2BIGVyKOvNlXVDbpIclJlly4kXqukL7JhWR&noverify=0&group_code=883237206)
|
154
153
|
- 迷茫 | 催命更新byd
|
155
154
|
- ArcPav | 积极反馈bug,提供改进思路
|
@@ -15,8 +15,10 @@
|
|
15
15
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
16
16
|
"""
|
17
17
|
|
18
|
+
from pathlib import Path
|
18
19
|
from typing import TYPE_CHECKING, List, Optional
|
19
20
|
|
21
|
+
import ujson as json
|
20
22
|
from nonebot.adapters import Message
|
21
23
|
from nonebot.log import logger
|
22
24
|
from nonebot.matcher import Matcher
|
@@ -26,12 +28,14 @@ from nonebot_plugin_alconna import UniMessage
|
|
26
28
|
|
27
29
|
from .config import config
|
28
30
|
from .l4_help import get_l4d2_core_help
|
31
|
+
from .l4_local import * # noqa: F403
|
29
32
|
from .l4_request import (
|
30
33
|
COMMAND,
|
31
34
|
get_all_server_detail,
|
32
35
|
get_ip_server,
|
33
36
|
get_server_detail,
|
34
37
|
reload_ip,
|
38
|
+
tj_request
|
35
39
|
)
|
36
40
|
from .utils.api.request import L4API
|
37
41
|
|
@@ -47,6 +51,9 @@ l4_all = on_command("l4all", aliases={"l4全服"})
|
|
47
51
|
l4_connect = on_command("connect", aliases={"l4连接"})
|
48
52
|
l4_find_player = on_command("l4find", aliases={"l4查找"})
|
49
53
|
|
54
|
+
ld_tj = on_command("tj", aliases={"探监"})
|
55
|
+
ld_zl = on_command("zl")
|
56
|
+
ld_kl = on_command("kl")
|
50
57
|
|
51
58
|
@l4_help.handle()
|
52
59
|
async def _(matcher: Matcher):
|
@@ -135,6 +142,88 @@ async def _(args: Message = CommandArg()):
|
|
135
142
|
if not arg:
|
136
143
|
reload_ip()
|
137
144
|
logger.success("重载ip完成")
|
145
|
+
with (Path(config.l4_path) / "config.json").open("r", encoding="utf-8") as f:
|
146
|
+
content = f.read().strip()
|
147
|
+
ip_json = json.loads(content)
|
148
|
+
for tag, url in ip_json.items():
|
149
|
+
logger.info(f"重载{tag}的ip")
|
150
|
+
await L4API.get_sourceban(tag, url)
|
138
151
|
await UniMessage.text("重载ip完成").finish()
|
152
|
+
|
153
|
+
|
154
|
+
l4_add_ban = on_command("l4addban", aliases={"l4添加ban"})
|
155
|
+
@l4_add_ban.handle()
|
156
|
+
async def _(args: Message = CommandArg()):
|
157
|
+
arg = args.extract_plain_text().strip().split(" ")
|
158
|
+
|
159
|
+
if len(arg) != 2:
|
160
|
+
await UniMessage.text("请在命令后增加响应指令名和网址").finish()
|
161
|
+
|
162
|
+
config_path = Path(config.l4_path) / "config.json"
|
163
|
+
|
164
|
+
if not config_path.is_file():
|
165
|
+
config_data = {}
|
139
166
|
else:
|
140
|
-
|
167
|
+
try:
|
168
|
+
with config_path.open("r") as f:
|
169
|
+
config_data = json.load(f)
|
170
|
+
except (json.JSONDecodeError, FileNotFoundError):
|
171
|
+
config_data = {}
|
172
|
+
|
173
|
+
config_data.update({arg[0]: arg[1]})
|
174
|
+
|
175
|
+
try:
|
176
|
+
with config_path.open("w") as f:
|
177
|
+
json.dump(config_data, f, ensure_ascii=False, indent=4)
|
178
|
+
except IOError as e:
|
179
|
+
await UniMessage.text(f"文件写入失败: {e}").finish()
|
180
|
+
|
181
|
+
await L4API.get_sourceban(arg[0], arg[1])
|
182
|
+
await UniMessage.text(f"添加成功\n组名: {arg[0]}\n网址: {arg[1]}").finish()
|
183
|
+
|
184
|
+
|
185
|
+
l4_del_ban = on_command("l4delban", aliases={"l4删除ban", "l4移除ban"})
|
186
|
+
@l4_del_ban.handle()
|
187
|
+
async def _(args: Message = CommandArg()):
|
188
|
+
arg = args.extract_plain_text().strip().split(" ")
|
189
|
+
if len(arg) not in [1,2]:
|
190
|
+
await UniMessage.text("请在命令后增加响应指令名或者带响应网址").finish()
|
191
|
+
elif len(arg) == 1:
|
192
|
+
if not Path(Path(config.l4_path) / "config.json").is_file():
|
193
|
+
await UniMessage.text("没有添加过组名").finish()
|
194
|
+
else:
|
195
|
+
with (Path(config.l4_path) / "config.json").open("r", encoding="utf-8") as f:
|
196
|
+
content = f.read().strip()
|
197
|
+
config_data = json.loads(content)
|
198
|
+
if arg[0] not in config_data:
|
199
|
+
await UniMessage.text("没有添加过这个组").finish()
|
200
|
+
else:
|
201
|
+
del config_data[arg[0]]
|
202
|
+
with Path(Path(config.l4_path) / "config.json").open("w") as f:
|
203
|
+
json.dump(config_data, f,ensure_ascii=False,indent=4)
|
204
|
+
await UniMessage.text(f"删除成功,组名:{arg[0]}").finish()
|
205
|
+
elif len(arg) == 2:
|
206
|
+
if not Path(Path(config.l4_path) / "config.json").is_file():
|
207
|
+
await UniMessage.text("没有添加过组名").finish()
|
208
|
+
else:
|
209
|
+
with (Path(config.l4_path) / "config.json").open("r", encoding="utf-8") as f:
|
210
|
+
content = f.read().strip()
|
211
|
+
config_datas = json.loads(content)
|
212
|
+
if arg[0] not in config_datas:
|
213
|
+
await UniMessage.text("没有添加过这个组").finish()
|
214
|
+
else:
|
215
|
+
config_datas[arg[0]] = arg[1]
|
216
|
+
with Path(Path(config.l4_path) / "config.json").open("w") as f:
|
217
|
+
json.dump(config_datas, f,ensure_ascii=False,indent=4)
|
218
|
+
await UniMessage.text(f"修改成功,组名:{arg[0]},网址:{arg[1]}").finish()
|
219
|
+
|
220
|
+
|
221
|
+
@ld_tj.handle()
|
222
|
+
async def _(matcher: Matcher):
|
223
|
+
await matcher.send("正在寻找牢房信息")
|
224
|
+
await matcher.finish(await tj_request("云","tj"))
|
225
|
+
|
226
|
+
@ld_zl.handle()
|
227
|
+
async def _(matcher: Matcher):
|
228
|
+
await matcher.send("正在寻找牢房信息")
|
229
|
+
await matcher.finish(await tj_request("云","zl"))
|
@@ -11,9 +11,12 @@ server_all_path.mkdir(parents=True, exist_ok=True)
|
|
11
11
|
|
12
12
|
ICONPATH = DATAPATH / "icon"
|
13
13
|
|
14
|
+
global map_index
|
15
|
+
map_index = 0
|
16
|
+
|
14
17
|
|
15
18
|
class ConfigModel(BaseModel):
|
16
|
-
l4_anne: bool =
|
19
|
+
l4_anne: bool = False
|
17
20
|
"""是否启用anne电信服相关功能"""
|
18
21
|
l4_enable: bool = True
|
19
22
|
"""是否全局启用求生功能"""
|
@@ -30,6 +33,9 @@ class ConfigModel(BaseModel):
|
|
30
33
|
l4_font: str = str(Path(__file__).parent.joinpath("data/font/loli.ttf"))
|
31
34
|
"""字体"""
|
32
35
|
l4_show_ip: bool = True
|
36
|
+
"""单服务器查询时候是否展示ip直连地址"""
|
37
|
+
l4_local: list[str] = []
|
38
|
+
"""本地服务器路径,填写路径下有`steam_appid.txt`文件"""
|
33
39
|
|
34
40
|
|
35
41
|
config = get_plugin_config(ConfigModel)
|
@@ -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.
|
13
|
+
__version__ = "1.0.1"
|
14
14
|
TEXT_PATH = Path(__file__).parent / "texture2d"
|
15
15
|
HELP_DATA = Path(__file__).parent / "Help.json"
|
16
16
|
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -1,8 +1,9 @@
|
|
1
1
|
from pathlib import Path
|
2
2
|
|
3
|
-
from nonebot_plugin_l4d2_server.utils.api.models import AnnePlayer2
|
4
3
|
from PIL import Image, ImageFont
|
5
4
|
|
5
|
+
from nonebot_plugin_l4d2_server.utils.api.models import AnnePlayer2
|
6
|
+
|
6
7
|
from ..config import config
|
7
8
|
|
8
9
|
font = ImageFont.truetype(config.l4_font)
|
@@ -10,7 +11,7 @@ font = ImageFont.truetype(config.l4_font)
|
|
10
11
|
anne_path = Path(__file__).parent / "img" / "anne"
|
11
12
|
|
12
13
|
|
13
|
-
async def anne_player_info(msg: AnnePlayer2):
|
14
|
+
async def anne_player_info(msg: AnnePlayer2): # noqa: RUF029
|
14
15
|
back_img = Image.open(anne_path / "back1.jpg")
|
15
16
|
base_img = Image.new("RGBA", (back_img.size), (255, 255, 255, 50))
|
16
17
|
back_img.paste(base_img, (0, 0), base_img)
|
@@ -21,32 +21,28 @@ def core_font(size: int) -> ImageFont.FreeTypeFont:
|
|
21
21
|
async def convert_img(
|
22
22
|
img: Image.Image,
|
23
23
|
is_base64: bool = False,
|
24
|
-
) -> bytes:
|
25
|
-
...
|
24
|
+
) -> bytes: ...
|
26
25
|
|
27
26
|
|
28
27
|
@overload
|
29
28
|
async def convert_img(
|
30
29
|
img: Image.Image,
|
31
|
-
is_base64: bool = True,
|
32
|
-
) -> str:
|
33
|
-
...
|
30
|
+
is_base64: bool = True, # noqa: FBT001
|
31
|
+
) -> str: ...
|
34
32
|
|
35
33
|
|
36
34
|
@overload
|
37
35
|
async def convert_img(
|
38
36
|
img: bytes,
|
39
37
|
is_base64: bool = False,
|
40
|
-
) -> str:
|
41
|
-
...
|
38
|
+
) -> str: ...
|
42
39
|
|
43
40
|
|
44
41
|
@overload
|
45
42
|
async def convert_img(
|
46
43
|
img: Path,
|
47
44
|
is_base64: bool = False,
|
48
|
-
) -> str:
|
49
|
-
...
|
45
|
+
) -> str: ...
|
50
46
|
|
51
47
|
|
52
48
|
async def convert_img(
|
@@ -78,7 +74,7 @@ async def convert_img(
|
|
78
74
|
async with aiofiles.open(img, "rb") as fp:
|
79
75
|
img = await fp.read()
|
80
76
|
|
81
|
-
logger.success("
|
77
|
+
logger.success("图片处理完成!")
|
82
78
|
|
83
79
|
return f"base64://{b64encode(img).decode()}"
|
84
80
|
|
@@ -90,7 +86,7 @@ def convert_img_sync(img_path: Path):
|
|
90
86
|
return f"base64://{b64encode(img).decode()}"
|
91
87
|
|
92
88
|
|
93
|
-
async def str_lenth(r: str, size: int, limit: int = 540) -> str:
|
89
|
+
async def str_lenth(r: str, size: int, limit: int = 540) -> str: # noqa: RUF029
|
94
90
|
result = ""
|
95
91
|
temp = 0
|
96
92
|
for i in r:
|
@@ -158,7 +154,7 @@ async def text2pic(text: str, max_size: int = 800, font_size: int = 24):
|
|
158
154
|
|
159
155
|
img = Image.new(
|
160
156
|
"RGB",
|
161
|
-
(max_size, len(text) * font_size //
|
157
|
+
(max_size, len(text) * font_size // 10),
|
162
158
|
(255, 255, 255),
|
163
159
|
)
|
164
160
|
img_draw = ImageDraw.ImageDraw(img)
|
@@ -27,20 +27,22 @@ async def download_url(url: str) -> bytes:
|
|
27
27
|
logger.warning(f"Error downloading {url}, retry {i}/3: {e}")
|
28
28
|
await asyncio.sleep(3)
|
29
29
|
|
30
|
-
raise Exception(f"{url}
|
30
|
+
raise Exception(f"{url} 下载失败!")
|
31
31
|
|
32
32
|
|
33
33
|
async def download_head(user_id: str) -> bytes:
|
34
34
|
url = f"http://q1.qlogo.cn/g?b=qq&nk={user_id}&s=640"
|
35
35
|
data = await download_url(url)
|
36
|
-
if
|
36
|
+
if (
|
37
|
+
hashlib.md5(data).hexdigest() == "acef72340ac0e914090bd35799f5594e"
|
38
|
+
): # noqa: S324
|
37
39
|
url = f"http://q1.qlogo.cn/g?b=qq&nk={user_id}&s=100"
|
38
40
|
data = await download_url(url)
|
39
41
|
return data
|
40
42
|
|
41
43
|
|
42
44
|
def square_to_circle(im: ImageS):
|
43
|
-
"""im
|
45
|
+
"""im是正方形,变圆形"""
|
44
46
|
size = im.size
|
45
47
|
mask = Image.new("L", size, 0)
|
46
48
|
draw = ImageDraw.Draw(mask)
|
@@ -23,7 +23,7 @@ env = jinja2.Environment(
|
|
23
23
|
|
24
24
|
async def server_ip_pic(server_dict: List[OutServer]):
|
25
25
|
"""
|
26
|
-
|
26
|
+
输入一个字典列表,输出图片
|
27
27
|
msg_dict:folder/name/map_/players/max_players/Players/[Name]
|
28
28
|
"""
|
29
29
|
for server_info in server_dict:
|
@@ -92,7 +92,7 @@ async def get_server_img(plugins: List[OutServer]) -> Optional[bytes]:
|
|
92
92
|
|
93
93
|
# async def server_group_ip_pic(msg_list: List[ServerGroup]) -> bytes:
|
94
94
|
# """
|
95
|
-
#
|
95
|
+
# 输入一个群组字典列表,输出图片
|
96
96
|
# msg_dict:folder/name/map_/players/max_players/Players/[Name]
|
97
97
|
# """
|
98
98
|
# template = env.get_template("group_ip.html")
|
@@ -44,7 +44,10 @@ def get_v4_bg(w: int, h: int, is_dark: bool = False, is_blur: bool = False):
|
|
44
44
|
return img.convert("RGBA")
|
45
45
|
|
46
46
|
|
47
|
-
async def shift_image_hue(
|
47
|
+
async def shift_image_hue(
|
48
|
+
img: Image.Image,
|
49
|
+
angle: float = 30,
|
50
|
+
) -> Image.Image: # noqa: RUF029
|
48
51
|
alpha = img.getchannel("A")
|
49
52
|
img = img.convert("HSV")
|
50
53
|
|
@@ -120,7 +123,7 @@ def draw_center_text_by_line(
|
|
120
123
|
line = line.replace("\n", "")
|
121
124
|
img.text((x, y), line, fill, font, anchor)
|
122
125
|
line, lenth = "", 0
|
123
|
-
y += h *
|
126
|
+
y += h * 1.5
|
124
127
|
else:
|
125
128
|
img.text((x, y), line, fill, font, anchor)
|
126
129
|
return y
|
@@ -198,7 +201,7 @@ def easy_paste(
|
|
198
201
|
"""
|
199
202
|
inplace method
|
200
203
|
快速粘贴, 自动获取被粘贴图像的坐标。
|
201
|
-
pos
|
204
|
+
pos应当是粘贴点坐标,direction指定粘贴点方位,例如lt为左上
|
202
205
|
"""
|
203
206
|
x, y = pos
|
204
207
|
size_x, size_y = im_paste.size
|
@@ -379,11 +382,11 @@ class CustomizeImage:
|
|
379
382
|
for i in range(color):
|
380
383
|
bg = tuple(
|
381
384
|
q.getpalette()[ # type:ignore
|
382
|
-
i * 3 : (i * 3) + 3
|
385
|
+
i * 3 : (i * 3) + 3
|
383
386
|
],
|
384
387
|
)
|
385
388
|
light_value = bg[0] * 0.3 + bg[1] * 0.6 + bg[2] * 0.1
|
386
|
-
if abs(light_value - based_light) < temp:
|
389
|
+
if abs(light_value - based_light) < temp:
|
387
390
|
bg_color = bg
|
388
391
|
temp = abs(light_value - based_light)
|
389
392
|
return bg_color # type:ignore
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,98 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
|
3
|
+
from nonebot.adapters import Event
|
4
|
+
from nonebot.log import logger
|
5
|
+
from nonebot.matcher import Matcher
|
6
|
+
from nonebot_plugin_alconna import File, UniMessage, UniMsg, on_alconna
|
7
|
+
|
8
|
+
from ..config import config, map_index
|
9
|
+
from ..l4_image.convert import text2pic
|
10
|
+
from ..utils.utils import mes_list
|
11
|
+
from .file import updown_l4d2_vpk
|
12
|
+
|
13
|
+
try:
|
14
|
+
vpk_path = config.l4_local[map_index]
|
15
|
+
except IndexError:
|
16
|
+
logger.warning("未填写本地服务器路径,如果想要使用本地服务器功能,请填写本地服务器路径")
|
17
|
+
vpk_path = ""
|
18
|
+
|
19
|
+
local_path_list = config.l4_local
|
20
|
+
if not local_path_list:
|
21
|
+
logger.warning(
|
22
|
+
"未填写本地服务器路径,如果想要使用本地服务器功能,请填写本地服务器路径",
|
23
|
+
)
|
24
|
+
else:
|
25
|
+
local_path: list[Path] = []
|
26
|
+
for folder_path in local_path_list:
|
27
|
+
path = Path(folder_path)
|
28
|
+
|
29
|
+
if path.is_dir():
|
30
|
+
for nextdir in path.iterdir():
|
31
|
+
# 如果找到了名为left4dead2的目录,返回True
|
32
|
+
if nextdir.name == "left4dead2" and nextdir.is_dir():
|
33
|
+
local_path.append(nextdir)
|
34
|
+
continue
|
35
|
+
logger.debug(f"本地服务器路径列表:{local_path}")
|
36
|
+
|
37
|
+
search_map = on_alconna(
|
38
|
+
"l4map",
|
39
|
+
aliases={"l4地图查询", "l4地图"},
|
40
|
+
priority=20,
|
41
|
+
block=True,
|
42
|
+
)
|
43
|
+
|
44
|
+
@search_map.handle()
|
45
|
+
async def _():
|
46
|
+
supath = local_path[map_index] / "addons"
|
47
|
+
vpk_list: list[str] = []
|
48
|
+
print(supath)
|
49
|
+
if supath.is_dir():
|
50
|
+
for sudir in supath.iterdir():
|
51
|
+
logger.info(f"找到文件:{sudir}")
|
52
|
+
if sudir.is_file() and sudir.name.endswith(".vpk"):
|
53
|
+
vpk_list.append(sudir.name)
|
54
|
+
if not vpk_list:
|
55
|
+
await UniMessage.text("未找到可用的VPK文件").finish()
|
56
|
+
out_msg = "\n".join(
|
57
|
+
f"{index + 1}、{line}" for index, line in enumerate(vpk_list)
|
58
|
+
)
|
59
|
+
|
60
|
+
img = await text2pic(f"服务器地图:\n{out_msg}")
|
61
|
+
await UniMessage.image(raw=img).send()
|
62
|
+
|
63
|
+
up = on_alconna(
|
64
|
+
"l4upload",
|
65
|
+
aliases={"l4地图上传"},
|
66
|
+
priority=5,
|
67
|
+
block=True,
|
68
|
+
)
|
69
|
+
|
70
|
+
@up.handle()
|
71
|
+
async def _():
|
72
|
+
await UniMessage.text("请发送地图文件").finish()
|
73
|
+
|
74
|
+
@up.got("map_url", prompt="图来")
|
75
|
+
async def _(ev: Event, msg: UniMsg, matcher: Matcher):
|
76
|
+
if not msg.has(File):
|
77
|
+
await UniMessage.text("不是文件,退出交互").finish()
|
78
|
+
args = ev.dict()
|
79
|
+
if args["notice_type"] != "offline_file":
|
80
|
+
matcher.set_arg("txt", args) # type: ignore
|
81
|
+
return
|
82
|
+
l4_file_path = config.l4_local[map_index]
|
83
|
+
map_path = Path(l4_file_path, vpk_path) # type: ignore
|
84
|
+
# 检查下载路径是否存在
|
85
|
+
if not Path(l4_file_path).exists(): # type: ignore
|
86
|
+
await UniMessage.text("你填写的路径不存在辣").finish()
|
87
|
+
if not Path(map_path).exists():
|
88
|
+
await UniMessage.text("这个路径并不是求生服务器的路径,请再看看罢").finish()
|
89
|
+
url: str = args["file"]["url"]
|
90
|
+
name: str = args["file"]["name"]
|
91
|
+
# 如果不符合格式则忽略
|
92
|
+
await up.send("已收到文件,开始下载")
|
93
|
+
vpk_files = await updown_l4d2_vpk(map_path, name, url)
|
94
|
+
if vpk_files:
|
95
|
+
mes = "解压成功,新增以下几个vpk文件"
|
96
|
+
await UniMessage.text(mes_list(mes, vpk_files)).finish()
|
97
|
+
else:
|
98
|
+
await UniMessage.text("你可能上传了相同的文件,或者解压失败了捏").finish()
|
@@ -0,0 +1,105 @@
|
|
1
|
+
import io
|
2
|
+
import platform
|
3
|
+
import zipfile
|
4
|
+
from pathlib import Path
|
5
|
+
from typing import Callable, Dict, List
|
6
|
+
from zipfile import ZipFile
|
7
|
+
|
8
|
+
import rarfile
|
9
|
+
from nonebot.log import logger
|
10
|
+
from pyunpack import Archive
|
11
|
+
|
12
|
+
from ..utils.utils import get_file, get_vpk
|
13
|
+
|
14
|
+
systems = platform.system()
|
15
|
+
|
16
|
+
|
17
|
+
async def updown_l4d2_vpk(map_paths: Path, name: str, url: str):
|
18
|
+
"""从url下载压缩包并解压到位置"""
|
19
|
+
original_vpk_files = get_vpk(map_paths)
|
20
|
+
down_file = Path(map_paths, name)
|
21
|
+
if await get_file(url, down_file) is None:
|
22
|
+
return None
|
23
|
+
msg = open_packet(name, down_file)
|
24
|
+
logger.info(msg)
|
25
|
+
|
26
|
+
extracted_vpk_files = get_vpk(map_paths)
|
27
|
+
# 获取新增vpk文件的list
|
28
|
+
return list(set(extracted_vpk_files) - set(original_vpk_files))
|
29
|
+
|
30
|
+
|
31
|
+
SUPPORTED_EXTENSIONS = (".zip", ".7z", ".rar")
|
32
|
+
|
33
|
+
|
34
|
+
def unzip_zipfile(down_file: Path, down_path: Path):
|
35
|
+
"""解压zip文件"""
|
36
|
+
with support_gbk(zipfile.ZipFile(down_file, "r")) as z:
|
37
|
+
z.extractall(down_path)
|
38
|
+
down_file.unlink()
|
39
|
+
|
40
|
+
|
41
|
+
def unpack_7zfile(down_file: Path, down_path: Path):
|
42
|
+
"""解压7z文件"""
|
43
|
+
Archive(str(down_file)).extractall(str(down_path))
|
44
|
+
down_file.unlink()
|
45
|
+
|
46
|
+
|
47
|
+
def unpack_rarfile(down_file: Path, down_path: Path):
|
48
|
+
"""解压rar文件"""
|
49
|
+
with rarfile.RarFile(down_file, "r") as z:
|
50
|
+
z.extractall(down_path)
|
51
|
+
down_file.unlink()
|
52
|
+
|
53
|
+
|
54
|
+
def open_packet(name: str, down_file: Path) -> str:
|
55
|
+
"""解压压缩包"""
|
56
|
+
down_path = down_file.parent
|
57
|
+
logger.info("文件名为:" + name)
|
58
|
+
logger.info(f"系统为{systems}")
|
59
|
+
if name.endswith(".vpk"):
|
60
|
+
return "vpk文件已下载"
|
61
|
+
|
62
|
+
for ext in SUPPORTED_EXTENSIONS:
|
63
|
+
if name.endswith(ext):
|
64
|
+
mes = f"{ext[1:]}文件已下载,正在解压"
|
65
|
+
unpack_funcs: Dict[str, Callable] = {
|
66
|
+
".zip": unzip_zipfile,
|
67
|
+
".7z": unpack_7zfile,
|
68
|
+
".rar": unpack_rarfile,
|
69
|
+
}
|
70
|
+
unpack_func = unpack_funcs.get(ext)
|
71
|
+
if not unpack_func:
|
72
|
+
raise ValueError(f"不支持的拓展名: {ext}")
|
73
|
+
unpack_func(down_file, down_path)
|
74
|
+
return mes
|
75
|
+
|
76
|
+
raise ValueError(f"不支持的文件: {name}")
|
77
|
+
|
78
|
+
|
79
|
+
def support_gbk(zip_file: ZipFile):
|
80
|
+
"""
|
81
|
+
压缩包中文恢复
|
82
|
+
"""
|
83
|
+
if isinstance(zip_file, ZipFile):
|
84
|
+
name_to_info = zip_file.NameToInfo
|
85
|
+
# copy map first
|
86
|
+
for name, info in name_to_info.copy().items():
|
87
|
+
real_name = name.encode("cp437").decode("gbk")
|
88
|
+
if real_name != name:
|
89
|
+
info.filename = real_name
|
90
|
+
del name_to_info[name]
|
91
|
+
name_to_info[real_name] = info
|
92
|
+
return zip_file
|
93
|
+
|
94
|
+
|
95
|
+
async def all_zip_to_one(data_list: List[bytes]): # noqa: RUF029
|
96
|
+
"""多压缩包文件合并"""
|
97
|
+
file_list = [io.BytesIO(data).getbuffer() for data in data_list]
|
98
|
+
data_file = io.BytesIO()
|
99
|
+
|
100
|
+
with ZipFile(data_file, mode="w") as zf:
|
101
|
+
for i, file in enumerate(file_list):
|
102
|
+
filename = f"file{i}.zip"
|
103
|
+
zf.writestr(filename, file)
|
104
|
+
|
105
|
+
return data_file.getbuffer()
|
@@ -1,18 +1,18 @@
|
|
1
|
+
import random
|
1
2
|
from typing import Dict, List, Optional, cast
|
2
3
|
|
3
4
|
from nonebot.log import logger
|
4
|
-
|
5
5
|
from ..config import server_all_path
|
6
6
|
from ..l4_image import msg_to_image
|
7
7
|
from ..utils.api.models import AllServer, NserverOut, OutServer
|
8
8
|
from ..utils.utils import split_maohao
|
9
|
-
from .draw_msg import draw_one_ip, get_much_server
|
10
|
-
|
9
|
+
from .draw_msg import draw_one_ip, get_much_server, convert_duration
|
10
|
+
from ..utils.api.request import L4API
|
11
11
|
try:
|
12
12
|
import ujson as json
|
13
13
|
except ImportError:
|
14
14
|
import json
|
15
|
-
|
15
|
+
from ..config import config
|
16
16
|
|
17
17
|
# 获取全部服务器信息
|
18
18
|
ALLHOST: Dict[str, List[NserverOut]] = {}
|
@@ -141,3 +141,69 @@ def reload_ip():
|
|
141
141
|
|
142
142
|
if item.name.endswith("txt"):
|
143
143
|
"""to do"""
|
144
|
+
|
145
|
+
async def tj_request(command: str = "云",tj ="tj"):
|
146
|
+
server_json = ALLHOST.get(command)
|
147
|
+
logger.info(server_json)
|
148
|
+
if server_json is None:
|
149
|
+
logger.warning("未找到这个组")
|
150
|
+
return None
|
151
|
+
# 返回单个
|
152
|
+
logger.info("正在anne电信服务器信息")
|
153
|
+
player_msg = ""
|
154
|
+
right_ip = []
|
155
|
+
for i in server_json:
|
156
|
+
ser_list = await L4API.a2s_info([(i["host"], i["port"])], is_player=True)
|
157
|
+
one_server = ser_list[0][0]
|
158
|
+
one_player = ser_list[0][1]
|
159
|
+
|
160
|
+
# 判断坐牢条件
|
161
|
+
if tj == "tj":
|
162
|
+
if "普通药役" in one_server.map_name:
|
163
|
+
score: int = 0
|
164
|
+
for index, player in enumerate(one_player, 1):
|
165
|
+
if index > 4:
|
166
|
+
break
|
167
|
+
score += player.score
|
168
|
+
|
169
|
+
t = one_server.map_name.split("[")[-1].split("特")[0]
|
170
|
+
if int(t)*50 < score:
|
171
|
+
right_ip.append(i)
|
172
|
+
if tj == "zl":
|
173
|
+
if "普通药役" in one_server.map_name and len(one_player) <= 4:
|
174
|
+
right_ip.append(i)
|
175
|
+
|
176
|
+
|
177
|
+
if not right_ip:
|
178
|
+
return "没有符合条件的服务器"
|
179
|
+
|
180
|
+
s = random.choice(right_ip)
|
181
|
+
ser_list = await L4API.a2s_info([(s["host"], s["port"])], is_player=True)
|
182
|
+
one_server = ser_list[0][0]
|
183
|
+
one_player = ser_list[0][1]
|
184
|
+
if len(one_player):
|
185
|
+
max_duration_len = max(
|
186
|
+
[len(str(await convert_duration(i.duration))) for i in one_player],
|
187
|
+
)
|
188
|
+
max_score_len = max(len(str(i.score)) for i in one_player)
|
189
|
+
|
190
|
+
for player in one_player:
|
191
|
+
soc = "[{:>{}}]".format(player.score, max_score_len)
|
192
|
+
chines_dur = await convert_duration(player.duration)
|
193
|
+
dur = "{:^{}}".format(chines_dur, max_duration_len)
|
194
|
+
name = f"{player.name[0]}***{player.name[-1]}"
|
195
|
+
player_msg += f"{soc} | {dur} | {name} \n"
|
196
|
+
else:
|
197
|
+
player_msg = "服务器感觉很安静啊"
|
198
|
+
msg = f"""*{one_server.server_name}*
|
199
|
+
游戏: {one_server.folder}
|
200
|
+
地图: {one_server.map_name}
|
201
|
+
人数: {one_server.player_count}/{one_server.max_players}"""
|
202
|
+
if one_server.ping is not None:
|
203
|
+
msg += f"""
|
204
|
+
ping: {one_server.ping * 1000:.0f}ms
|
205
|
+
{player_msg}"""
|
206
|
+
if config.l4_show_ip:
|
207
|
+
msg += f"""
|
208
|
+
connect {s["host"]}:{s["port"]}"""
|
209
|
+
return msg
|
@@ -29,8 +29,13 @@ async def draw_one_ip(host: str, port: int):
|
|
29
29
|
soc = "[{:>{}}]".format(player.score, max_score_len)
|
30
30
|
chines_dur = await convert_duration(player.duration)
|
31
31
|
dur = "{:^{}}".format(chines_dur, max_duration_len)
|
32
|
-
|
33
|
-
|
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"
|
34
39
|
else:
|
35
40
|
player_msg = "服务器感觉很安静啊"
|
36
41
|
|
@@ -52,7 +57,7 @@ async def get_much_server(server_json: List[NserverOut], command: str):
|
|
52
57
|
out_server: List[OutServer] = []
|
53
58
|
search_list: List[Tuple[str, int]] = []
|
54
59
|
for i in server_json:
|
55
|
-
search_list.append((i["host"], i["port"]))
|
60
|
+
search_list.append((i["host"], i["port"]))
|
56
61
|
|
57
62
|
all_server = await L4API.a2s_info(search_list, is_player=True)
|
58
63
|
|
@@ -2,13 +2,17 @@ import asyncio
|
|
2
2
|
import contextlib
|
3
3
|
import socket
|
4
4
|
from copy import deepcopy
|
5
|
+
from pathlib import Path
|
5
6
|
from typing import Any, Dict, List, Literal, Optional, Tuple, cast
|
6
7
|
|
7
8
|
import a2s
|
8
9
|
import ujson as js
|
10
|
+
import ujson as json
|
9
11
|
from bs4 import BeautifulSoup
|
10
12
|
from httpx import AsyncClient
|
11
13
|
|
14
|
+
from ...config import config
|
15
|
+
|
12
16
|
# from nonebot.log import logger
|
13
17
|
from ..utils import split_maohao
|
14
18
|
from .api import AnnePlayerApi, AnneSearchApi, anne_ban
|
@@ -154,8 +158,10 @@ class L4D2Api:
|
|
154
158
|
html_content = resp.content
|
155
159
|
return BeautifulSoup(html_content, "lxml")
|
156
160
|
|
157
|
-
async def get_sourceban(self, url: str = anne_ban):
|
161
|
+
async def get_sourceban(self, tag:str = "云", url: str = anne_ban):
|
158
162
|
"""从sourceban++获取服务器列表,目前未做名称处理"""
|
163
|
+
if not (url.startswith(("http://", "https://"))):
|
164
|
+
url = "http://" + url # 默认添加 http://
|
159
165
|
soup = await self._server_request(
|
160
166
|
url=url,
|
161
167
|
is_json=False,
|
@@ -177,6 +183,24 @@ class L4D2Api:
|
|
177
183
|
SourceBansInfo(index=index, host=host, port=port),
|
178
184
|
)
|
179
185
|
|
186
|
+
if not Path(Path(config.l4_path) / "config.json").is_file():
|
187
|
+
with Path(Path(config.l4_path) / "config.json").open("w") as f:
|
188
|
+
f.write("{}")
|
189
|
+
with (Path(config.l4_path) / "config.json").open("r", encoding="utf-8") as f:
|
190
|
+
content = f.read().strip()
|
191
|
+
ip_json = json.loads(content)
|
192
|
+
if tag in ip_json:
|
193
|
+
url = ip_json[tag]
|
194
|
+
with (Path(Path(config.l4_path) / f"l4d2/{tag}.json")).open("w") as f:
|
195
|
+
print(Path(Path(config.l4_path) / f"l4d2/{tag}.json"))
|
196
|
+
up_data = {}
|
197
|
+
for server in server_list:
|
198
|
+
new_dict = {}
|
199
|
+
new_dict["id"] = int(server.index )+ 1
|
200
|
+
new_dict["ip"] = server.host + ":" + str(server.port)
|
201
|
+
up_data.update(new_dict)
|
202
|
+
print(up_data)
|
203
|
+
json.dump(up_data, f)
|
180
204
|
return server_list
|
181
205
|
|
182
206
|
async def get_anne_steamid(self, name: str):
|
@@ -6,8 +6,10 @@ from typing import Any, Dict, List, Optional, Tuple
|
|
6
6
|
|
7
7
|
import aiofiles
|
8
8
|
import aiohttp
|
9
|
+
import nonebot
|
9
10
|
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent
|
10
11
|
from nonebot.log import logger
|
12
|
+
from nonebot_plugin_alconna import UniMessage
|
11
13
|
|
12
14
|
|
13
15
|
async def get_file(url: str, down_file: Path):
|
@@ -174,7 +176,7 @@ def split_maohao(msg: str) -> Tuple[str, int]:
|
|
174
176
|
|
175
177
|
|
176
178
|
headers = {
|
177
|
-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0",
|
179
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0",
|
178
180
|
}
|
179
181
|
|
180
182
|
|
@@ -198,7 +200,16 @@ async def url_to_msg(url: str):
|
|
198
200
|
return None
|
199
201
|
|
200
202
|
|
201
|
-
async def get_message_at(datas: str) -> Optional[int]:
|
203
|
+
async def get_message_at(datas: str) -> Optional[int]:
|
202
204
|
data: Dict[str, Any] = json.loads(datas)
|
203
205
|
at_list = [int(msg["data"]["qq"]) for msg in data["message"] if msg["type"] == "at"]
|
204
206
|
return at_list[0] if at_list else None
|
207
|
+
|
208
|
+
|
209
|
+
async def send_ip_msg(msg: str):
|
210
|
+
try:
|
211
|
+
await UniMessage.text(msg).finish()
|
212
|
+
except nonebot.adapters.qq:
|
213
|
+
msg_new = msg.split("\n")[:-2]
|
214
|
+
msg_out = "\n".join(msg_new)
|
215
|
+
await UniMessage.text(msg_out).send()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "nonebot-plugin-l4d2-server"
|
3
|
-
version = "1.0.
|
3
|
+
version = "1.0.1"
|
4
4
|
description = "L4D2 server related operations plugin for NoneBot2"
|
5
5
|
authors = [
|
6
6
|
{ name = "Agnes_Digital", email = "Z735803792@163.com" },
|
@@ -52,6 +52,52 @@ homepage = "https://github.com/Agnes4m/nonebot_plugin_l4d2_server"
|
|
52
52
|
[tool.pdm.build]
|
53
53
|
includes = []
|
54
54
|
|
55
|
+
[tool.ruff]
|
56
|
+
ignore = [
|
57
|
+
"B008",
|
58
|
+
"B905",
|
59
|
+
"E501",
|
60
|
+
"N999",
|
61
|
+
"FBT002",
|
62
|
+
"PGH003",
|
63
|
+
"RUF001",
|
64
|
+
"RUF002",
|
65
|
+
"RUF003",
|
66
|
+
"RUF006",
|
67
|
+
"RUF100",
|
68
|
+
"SIM117",
|
69
|
+
"TRY002",
|
70
|
+
"TRY003",
|
71
|
+
"FBT001",
|
72
|
+
]
|
73
|
+
select = [
|
74
|
+
"A",
|
75
|
+
"ARG",
|
76
|
+
"ASYNC",
|
77
|
+
"B",
|
78
|
+
"C4",
|
79
|
+
"COM",
|
80
|
+
"E",
|
81
|
+
"F",
|
82
|
+
"FBT",
|
83
|
+
"FLY",
|
84
|
+
"I",
|
85
|
+
"ISC",
|
86
|
+
"N",
|
87
|
+
"PIE",
|
88
|
+
"PGH",
|
89
|
+
"PTH",
|
90
|
+
"PYI",
|
91
|
+
"Q",
|
92
|
+
"RET",
|
93
|
+
"RSE",
|
94
|
+
"RUF",
|
95
|
+
"SIM",
|
96
|
+
"SLF",
|
97
|
+
"SLOT",
|
98
|
+
"TRY",
|
99
|
+
]
|
100
|
+
|
55
101
|
[build-system]
|
56
102
|
requires = [
|
57
103
|
"pdm-backend",
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|