nonebot-plugin-l4d2-server 0.6.6__py3-none-any.whl → 1.0.0a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nonebot_plugin_l4d2_server/__init__.py +9 -92
- nonebot_plugin_l4d2_server/__main__.py +90 -0
- nonebot_plugin_l4d2_server/config.py +30 -0
- nonebot_plugin_l4d2_server/data/L4D2/image/head/head.png +0 -0
- nonebot_plugin_l4d2_server/data/L4D2/image/header/logo.png +0 -0
- nonebot_plugin_l4d2_server/data/L4D2/image/header/player1.jpg +0 -0
- nonebot_plugin_l4d2_server/data/L4D2/image/template/anne.html +50 -42
- nonebot_plugin_l4d2_server/data/L4D2/image/template/back.png +0 -0
- nonebot_plugin_l4d2_server/data/L4D2/image/template/group_ip.html +1 -2
- nonebot_plugin_l4d2_server/data/L4D2/image/template/help.html +1 -2
- nonebot_plugin_l4d2_server/data/L4D2/image/template/help_dack.html +259 -221
- nonebot_plugin_l4d2_server/data/L4D2/image/template/ip.html +1 -2
- nonebot_plugin_l4d2_server/data/font/loli.ttf +0 -0
- nonebot_plugin_l4d2_server/data/icon//344/273/213/347/273/215.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//344/273/273/345/212/241.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//344/277/241/346/201/257.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/205/254/345/221/212.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/210/200/345/211/221.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/210/207/346/215/242.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/210/240/351/231/244.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/210/267/346/226/260.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/215/241/347/273/204.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/223/252/351/207/214.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/234/260/345/233/276.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/257/274/345/205/245.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/257/274/345/207/272.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/275/261.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/213/274/345/233/276.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/216/242/347/264/242.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/216/250/351/200/201.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/224/266/351/233/206.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/224/273/347/225/245.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/233/264/346/226/260.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/235/220/346/226/231.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/237/245/350/257/242.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/240/241/351/252/214.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/257/217/346/234/210.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/267/261/346/270/212.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/267/273/345/212/240.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/270/205/351/231/244.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//347/212/266/346/200/201.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//347/255/276/345/210/260.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//347/273/221/345/256/232.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//350/241/250.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//350/241/250/346/203/205.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//350/247/222/350/211/262.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//350/256/260/345/275/225.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//351/205/215/347/275/256.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//351/207/215/345/220/257.png +0 -0
- nonebot_plugin_l4d2_server/data/img/l4d2.png +0 -0
- nonebot_plugin_l4d2_server/data/img/linux.png +0 -0
- nonebot_plugin_l4d2_server/data/img/vac.png +0 -0
- nonebot_plugin_l4d2_server/data/img/white.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/Help.json +65 -0
- nonebot_plugin_l4d2_server/l4_help/__init__.py +57 -0
- nonebot_plugin_l4d2_server/l4_help/draw.py +206 -0
- nonebot_plugin_l4d2_server/l4_help/icon//344/273/213/347/273/215.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//344/273/273/345/212/241.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//344/277/241/346/201/257.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/205/254/345/221/212.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/210/200/345/211/221.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/210/207/346/215/242.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/210/240/351/231/244.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/210/267/346/226/260.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/215/241/347/273/204.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/223/252/351/207/214.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/234/260/345/233/276.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/257/274/345/205/245.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/257/274/345/207/272.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/275/261.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/213/274/345/233/276.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/216/242/347/264/242.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/216/250/351/200/201.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/224/266/351/233/206.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/224/273/347/225/245.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/233/264/346/226/260.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/235/220/346/226/231.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/237/245/350/257/242.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/240/241/351/252/214.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/257/217/346/234/210.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/267/261/346/270/212.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/267/273/345/212/240.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/270/205/351/231/244.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//347/212/266/346/200/201.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//347/255/276/345/210/260.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//347/273/221/345/256/232.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//350/241/250.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//350/241/250/346/203/205.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//350/247/222/350/211/262.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//350/256/260/345/275/225.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//351/205/215/347/275/256.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//351/207/215/345/220/257.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/badge.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/banner.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/bg.jpg +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/button.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/icon.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/__init__.py +16 -0
- nonebot_plugin_l4d2_server/l4_image/convert.py +175 -0
- nonebot_plugin_l4d2_server/{l4d2_image → l4_image}/download.py +6 -30
- nonebot_plugin_l4d2_server/{l4d2_image/__init__.py → l4_image/html_img.py} +54 -45
- nonebot_plugin_l4d2_server/l4_image/image_tools.py +468 -0
- nonebot_plugin_l4d2_server/l4_image/img/anne/anne.html +60 -0
- nonebot_plugin_l4d2_server/l4_image/img/anne/back.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/anne/group_ip.html +259 -0
- nonebot_plugin_l4d2_server/l4_image/img/anne/ip.html +55 -0
- nonebot_plugin_l4d2_server/l4_image/img/head/head.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/header/logo.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/header/player1.jpg +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Bocchi_The_Rock.html +312 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Bocchi_The_Rock.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/HYPixel11pxU-2.ttf +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Pixel.html +350 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Pixel.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Rainbow.html +321 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Rainbow.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Tutumianhuatang-Bold-2.ttf +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/bilibili.svg +1 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/fingerprint.svg +15 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/github.svg +1 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/l.svg +9 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/m.svg +1 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/normal.html +257 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/vue.css +531 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/w.svg +1 -0
- nonebot_plugin_l4d2_server/l4_image/img/template//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
- nonebot_plugin_l4d2_server/l4_image/model.py +15 -0
- nonebot_plugin_l4d2_server/{l4d2_image → l4_image}/vtfs.py +2 -0
- nonebot_plugin_l4d2_server/l4_request/__init__.py +84 -0
- nonebot_plugin_l4d2_server/l4_request/draw_msg.py +88 -0
- nonebot_plugin_l4d2_server/utils/api/api.py +4 -0
- nonebot_plugin_l4d2_server/utils/api/models.py +29 -0
- nonebot_plugin_l4d2_server/utils/api/request.py +119 -0
- nonebot_plugin_l4d2_server/utils/database/models.py +29 -0
- nonebot_plugin_l4d2_server/{l4d2_utils → utils}/utils.py +52 -55
- {nonebot_plugin_l4d2_server-0.6.6.dist-info → nonebot_plugin_l4d2_server-1.0.0a1.dist-info}/METADATA +47 -64
- nonebot_plugin_l4d2_server-1.0.0a1.dist-info/RECORD +144 -0
- {nonebot_plugin_l4d2_server-0.6.6.dist-info → nonebot_plugin_l4d2_server-1.0.0a1.dist-info}/WHEEL +1 -1
- nonebot_plugin_l4d2_server/l4d2_anne/__init__.py +0 -95
- nonebot_plugin_l4d2_server/l4d2_anne/analysis.py +0 -54
- nonebot_plugin_l4d2_server/l4d2_anne/anne_telecom.py +0 -79
- nonebot_plugin_l4d2_server/l4d2_anne/server.py +0 -47
- nonebot_plugin_l4d2_server/l4d2_anne/startand.py +0 -17
- nonebot_plugin_l4d2_server/l4d2_anne/utils.py +0 -294
- nonebot_plugin_l4d2_server/l4d2_data/__init__.py +0 -105
- nonebot_plugin_l4d2_server/l4d2_data/config.py +0 -18
- nonebot_plugin_l4d2_server/l4d2_data/database.py +0 -0
- nonebot_plugin_l4d2_server/l4d2_data/players.py +0 -100
- nonebot_plugin_l4d2_server/l4d2_data/serverip.py +0 -40
- nonebot_plugin_l4d2_server/l4d2_file/__init__.py +0 -222
- nonebot_plugin_l4d2_server/l4d2_file/ayromote.py +0 -64
- nonebot_plugin_l4d2_server/l4d2_file/input_json.py +0 -77
- nonebot_plugin_l4d2_server/l4d2_file/remote.py +0 -86
- nonebot_plugin_l4d2_server/l4d2_file/utils.py +0 -104
- nonebot_plugin_l4d2_server/l4d2_image/htmlimg.py +0 -18
- nonebot_plugin_l4d2_server/l4d2_image/images.py +0 -92
- nonebot_plugin_l4d2_server/l4d2_image/one.py +0 -44
- nonebot_plugin_l4d2_server/l4d2_image/send_image_tool.py +0 -32
- nonebot_plugin_l4d2_server/l4d2_image/steam.py +0 -63
- nonebot_plugin_l4d2_server/l4d2_push/__init__.py +0 -225
- nonebot_plugin_l4d2_server/l4d2_queries/__init__.py +0 -326
- nonebot_plugin_l4d2_server/l4d2_queries/himi.py +0 -113
- nonebot_plugin_l4d2_server/l4d2_queries/local_ip.py +0 -41
- nonebot_plugin_l4d2_server/l4d2_queries/qqgroup.py +0 -370
- nonebot_plugin_l4d2_server/l4d2_queries/send_msg.py +0 -131
- nonebot_plugin_l4d2_server/l4d2_queries/utils.py +0 -212
- nonebot_plugin_l4d2_server/l4d2_server/__init__.py +0 -118
- nonebot_plugin_l4d2_server/l4d2_server/index.py +0 -0
- nonebot_plugin_l4d2_server/l4d2_server/rcon.py +0 -53
- nonebot_plugin_l4d2_server/l4d2_server/workshop.py +0 -82
- nonebot_plugin_l4d2_server/l4d2_update/__init__.py +0 -137
- nonebot_plugin_l4d2_server/l4d2_update/draw_update_log.py +0 -45
- nonebot_plugin_l4d2_server/l4d2_update/restart.py +0 -69
- nonebot_plugin_l4d2_server/l4d2_update/update.py +0 -53
- nonebot_plugin_l4d2_server/l4d2_utils/classcal.py +0 -53
- nonebot_plugin_l4d2_server/l4d2_utils/command.py +0 -23
- nonebot_plugin_l4d2_server/l4d2_utils/config.py +0 -201
- nonebot_plugin_l4d2_server/l4d2_utils/message.py +0 -59
- nonebot_plugin_l4d2_server/l4d2_utils/rule.py +0 -35
- nonebot_plugin_l4d2_server/l4d2_utils/seach.py +0 -43
- nonebot_plugin_l4d2_server/l4d2_utils/txt_to_img.py +0 -32
- nonebot_plugin_l4d2_server/l4d2_web/web.py +0 -277
- nonebot_plugin_l4d2_server/l4d2_web/webUI.py +0 -506
- nonebot_plugin_l4d2_server/l4d2_web/webUI_s.py +0 -94
- nonebot_plugin_l4d2_server-0.6.6.dist-info/RECORD +0 -70
- {nonebot_plugin_l4d2_server-0.6.6.dist-info → nonebot_plugin_l4d2_server-1.0.0a1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,65 @@
|
|
1
|
+
{
|
2
|
+
"基础服务": {
|
3
|
+
"desc": "无需任何权限",
|
4
|
+
"data": [
|
5
|
+
{
|
6
|
+
"name": "l4全服",
|
7
|
+
"desc": "返回可以查询的所有服务器组",
|
8
|
+
"eg": "l4全服",
|
9
|
+
"need_ck": false,
|
10
|
+
"need_sk": false,
|
11
|
+
"need_admin": false
|
12
|
+
},
|
13
|
+
{
|
14
|
+
"name": "(组指令)",
|
15
|
+
"desc": "返回一个组的服务器信息",
|
16
|
+
"eg": "云",
|
17
|
+
"need_ck": false,
|
18
|
+
"need_sk": false,
|
19
|
+
"need_admin": false
|
20
|
+
},
|
21
|
+
{
|
22
|
+
"name": "雀魂切换uid",
|
23
|
+
"desc": "切换你的雀魂UID",
|
24
|
+
"eg": "雀魂切换uid123456",
|
25
|
+
"need_ck": false,
|
26
|
+
"need_sk": false,
|
27
|
+
"need_admin": false
|
28
|
+
}
|
29
|
+
]
|
30
|
+
},
|
31
|
+
"查询服务": {
|
32
|
+
"desc": "查询一些基本信息, 需要在金之间拥有一定场次的对局",
|
33
|
+
"data": [
|
34
|
+
{
|
35
|
+
"name": "雀魂搜索",
|
36
|
+
"desc": "搜索雀魂玩家",
|
37
|
+
"eg": "雀魂搜索Wuyi",
|
38
|
+
"need_ck": true,
|
39
|
+
"need_sk": false,
|
40
|
+
"need_admin": false
|
41
|
+
},
|
42
|
+
{
|
43
|
+
"name": "雀魂查询",
|
44
|
+
"desc": "查询雀魂数据一览",
|
45
|
+
"eg": "雀魂查询1148850",
|
46
|
+
"need_ck": true,
|
47
|
+
"need_sk": false,
|
48
|
+
"need_admin": false
|
49
|
+
}
|
50
|
+
]
|
51
|
+
},
|
52
|
+
"其他服务": {
|
53
|
+
"desc": "一些杂项服务",
|
54
|
+
"data": [
|
55
|
+
{
|
56
|
+
"name": "雀魂帮助",
|
57
|
+
"desc": "呼出该帮助界面",
|
58
|
+
"eg": "雀魂帮助",
|
59
|
+
"need_ck": false,
|
60
|
+
"need_sk": false,
|
61
|
+
"need_admin": false
|
62
|
+
}
|
63
|
+
]
|
64
|
+
}
|
65
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
from typing import Dict, Union
|
3
|
+
|
4
|
+
import aiofiles
|
5
|
+
from msgspec import json as msgjson
|
6
|
+
from PIL import Image
|
7
|
+
|
8
|
+
from ..config import ICONPATH
|
9
|
+
from ..l4_image.convert import core_font
|
10
|
+
from ..l4_image.model import PluginHelp
|
11
|
+
from .draw import get_help
|
12
|
+
|
13
|
+
__version__ = "1.0.0a1"
|
14
|
+
TEXT_PATH = Path(__file__).parent / "texture2d"
|
15
|
+
HELP_DATA = Path(__file__).parent / "Help.json"
|
16
|
+
|
17
|
+
|
18
|
+
async def get_help_data() -> Union[Dict[str, PluginHelp], None]:
|
19
|
+
if HELP_DATA.exists():
|
20
|
+
async with aiofiles.open(HELP_DATA, "rb") as file:
|
21
|
+
return msgjson.decode(
|
22
|
+
await file.read(),
|
23
|
+
type=Dict[str, PluginHelp],
|
24
|
+
)
|
25
|
+
return None
|
26
|
+
|
27
|
+
|
28
|
+
async def get_l4d2_core_help() -> Union[bytes, str]:
|
29
|
+
help_data = await get_help_data()
|
30
|
+
if help_data is None:
|
31
|
+
return "暂未找到帮助数据..."
|
32
|
+
|
33
|
+
bg_out = Image.open(TEXT_PATH / "bg.jpg")
|
34
|
+
bg_new = Image.new(
|
35
|
+
"RGBA",
|
36
|
+
(bg_out.width, bg_out.height),
|
37
|
+
(255, 255, 255, 100),
|
38
|
+
)
|
39
|
+
bg_out.paste(bg_new, None, bg_new)
|
40
|
+
|
41
|
+
return await get_help(
|
42
|
+
"CS2UID",
|
43
|
+
f"版本号:{__version__}",
|
44
|
+
help_data,
|
45
|
+
bg_out,
|
46
|
+
Image.open(TEXT_PATH / "icon.png"),
|
47
|
+
Image.open(TEXT_PATH / "badge.png"),
|
48
|
+
Image.open(TEXT_PATH / "banner.png"),
|
49
|
+
Image.open(TEXT_PATH / "button.png"),
|
50
|
+
core_font,
|
51
|
+
is_dark=False,
|
52
|
+
column=4,
|
53
|
+
is_gaussian=False,
|
54
|
+
text_color=(23, 67, 91),
|
55
|
+
sub_c=(49, 110, 144),
|
56
|
+
icon_path=ICONPATH,
|
57
|
+
)
|
@@ -0,0 +1,206 @@
|
|
1
|
+
from copy import deepcopy
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import Callable, Dict, List, Optional, Tuple
|
4
|
+
|
5
|
+
from nonebot_plugin_datastore import get_plugin_data
|
6
|
+
from PIL import Image, ImageDraw, ImageFilter, ImageFont
|
7
|
+
|
8
|
+
from ..l4_image.convert import convert_img, pic_quality
|
9
|
+
from ..l4_image.image_tools import crop_center_img
|
10
|
+
from ..l4_image.model import PluginHelp
|
11
|
+
|
12
|
+
cache: Dict[str, int] = {}
|
13
|
+
Micon_path = Path(__file__).parent / "icon"
|
14
|
+
DEFAULT_ICON = Micon_path / "拼图.png"
|
15
|
+
plugin_data = get_plugin_data()
|
16
|
+
|
17
|
+
|
18
|
+
def cx(w: int, x: int) -> int:
|
19
|
+
return int((w - x) / 2)
|
20
|
+
|
21
|
+
|
22
|
+
def _get_icon(name: str, icon_path: Path) -> Optional[Image.Image]:
|
23
|
+
path = icon_path / f"{name}.png"
|
24
|
+
icon = None
|
25
|
+
if path.exists():
|
26
|
+
icon = Image.open(path)
|
27
|
+
else:
|
28
|
+
for i in icon_path.glob("*.png"):
|
29
|
+
if i.stem in name:
|
30
|
+
icon = Image.open(i)
|
31
|
+
break
|
32
|
+
|
33
|
+
return icon
|
34
|
+
|
35
|
+
|
36
|
+
def get_icon(name: str, icon_path: Optional[Path]) -> Image.Image:
|
37
|
+
if icon_path is not None:
|
38
|
+
icon = _get_icon(name, icon_path)
|
39
|
+
if icon is None:
|
40
|
+
icon = _get_icon(name, Micon_path)
|
41
|
+
else:
|
42
|
+
icon = _get_icon(name, Micon_path)
|
43
|
+
|
44
|
+
if icon is None:
|
45
|
+
icon = Image.open(DEFAULT_ICON)
|
46
|
+
|
47
|
+
return icon.resize((36, 36))
|
48
|
+
|
49
|
+
|
50
|
+
async def get_help(
|
51
|
+
name: str,
|
52
|
+
sub_text: str,
|
53
|
+
help_data: Dict[str, PluginHelp],
|
54
|
+
bg: Image.Image,
|
55
|
+
icon: Image.Image,
|
56
|
+
badge: Image.Image,
|
57
|
+
banner: Image.Image,
|
58
|
+
button: Image.Image,
|
59
|
+
font: Callable[[int], ImageFont.FreeTypeFont],
|
60
|
+
is_dark: bool = True,
|
61
|
+
text_color: Tuple[int, int, int] = (250, 250, 250),
|
62
|
+
sub_c: Optional[Tuple[int, int, int]] = None,
|
63
|
+
op_color: Optional[Tuple[int, int, int]] = None,
|
64
|
+
title_color: Tuple[int, int, int] = (250, 250, 250),
|
65
|
+
sub_title_color: Tuple[int, int, int] = (235, 235, 235),
|
66
|
+
sv_color: Tuple[int, int, int] = (250, 250, 250),
|
67
|
+
sv_desc_color: Tuple[int, int, int] = (235, 235, 235),
|
68
|
+
column: int = 5,
|
69
|
+
is_gaussian: bool = False,
|
70
|
+
gaussian_blur: int = 20,
|
71
|
+
is_icon: bool = True,
|
72
|
+
icon_path: Optional[Path] = None,
|
73
|
+
extra_message: Optional[List[str]] = None,
|
74
|
+
enable_cache: bool = True,
|
75
|
+
) -> bytes:
|
76
|
+
if sub_c is None and is_dark:
|
77
|
+
sub_c = tuple(x - 50 if x > 50 else x for x in text_color) # type: ignore
|
78
|
+
elif sub_c is None and not is_dark:
|
79
|
+
sub_c = tuple(x + 50 if x < 205 else x for x in text_color) # type: ignore
|
80
|
+
|
81
|
+
if op_color is None and is_dark:
|
82
|
+
op_color = tuple(x - 90 if x > 90 else x for x in text_color) # type: ignore
|
83
|
+
elif op_color is None and not is_dark:
|
84
|
+
op_color = tuple(x + 90 if x < 160 else x for x in text_color) # type: ignore
|
85
|
+
|
86
|
+
_h = 600
|
87
|
+
|
88
|
+
if extra_message:
|
89
|
+
_h += 100
|
90
|
+
|
91
|
+
w, h = 50 + 260 * column, _h + 30
|
92
|
+
button_x = 260
|
93
|
+
button_y = 103 # 80
|
94
|
+
|
95
|
+
title = Image.new("RGBA", (w, _h))
|
96
|
+
icon = icon.resize((300, 300))
|
97
|
+
|
98
|
+
title.paste(icon, (cx(w, 300), 89), icon)
|
99
|
+
title.paste(badge, (cx(w, 900), 390), badge)
|
100
|
+
badge_s = badge.resize((720, 80))
|
101
|
+
title.paste(badge_s, (cx(w, 720), 480), badge_s)
|
102
|
+
|
103
|
+
title_draw = ImageDraw.Draw(title)
|
104
|
+
|
105
|
+
if extra_message:
|
106
|
+
all_lenth = 300 * (len(extra_message) - 1) + 720
|
107
|
+
first_x = (w - all_lenth) / 2
|
108
|
+
for _i, message in enumerate(extra_message):
|
109
|
+
_x = int(first_x + _i * 300)
|
110
|
+
title.paste(badge_s, (_x, 556), badge_s)
|
111
|
+
title_draw.text((_x + 360, 596), message, sub_c, font(26), "mm")
|
112
|
+
|
113
|
+
title_draw.text(
|
114
|
+
(cx(w, 0), 440),
|
115
|
+
f"{name} 帮助",
|
116
|
+
title_color,
|
117
|
+
font(36),
|
118
|
+
"mm",
|
119
|
+
)
|
120
|
+
title_draw.text((cx(w, 0), 520), sub_text, sub_title_color, font(26), "mm")
|
121
|
+
|
122
|
+
if is_dark:
|
123
|
+
icon_mask = Image.new("RGBA", (36, 36), (255, 255, 255))
|
124
|
+
else:
|
125
|
+
icon_mask = Image.new("RGBA", (36, 36), (10, 10, 10))
|
126
|
+
|
127
|
+
sv_img_list: List[Image.Image] = []
|
128
|
+
for sv_name in help_data:
|
129
|
+
tr_size = len(help_data[sv_name]["data"])
|
130
|
+
y = 100 + ((tr_size + column - 1) // column) * button_y
|
131
|
+
h += y
|
132
|
+
|
133
|
+
# 生成单个服务的背景, 依据默认column
|
134
|
+
sv_img = Image.new("RGBA", (w, y))
|
135
|
+
sv_data = help_data[sv_name]["data"]
|
136
|
+
sv_desc = help_data[sv_name]["desc"]
|
137
|
+
|
138
|
+
bc = deepcopy(banner)
|
139
|
+
bc_draw = ImageDraw.Draw(bc)
|
140
|
+
bc_draw.text((30, 25), sv_name, sv_color, font(35), "lm")
|
141
|
+
|
142
|
+
if hasattr(font, "getsize"):
|
143
|
+
size, _ = font(35).getsize(sv_name) # type: ignore
|
144
|
+
else:
|
145
|
+
bbox = font(35).getbbox(sv_name)
|
146
|
+
size, _ = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
147
|
+
|
148
|
+
bc_draw.text((42 + size, 30), sv_desc, sv_desc_color, font(20), "lm")
|
149
|
+
sv_img.paste(bc, (0, 10), bc)
|
150
|
+
# sv_img = easy_alpha_composite(sv_img, bc, (0, 10))
|
151
|
+
|
152
|
+
# 开始绘制各个按钮
|
153
|
+
for index, tr in enumerate(sv_data):
|
154
|
+
bt = deepcopy(button)
|
155
|
+
bt_draw = ImageDraw.Draw(bt)
|
156
|
+
|
157
|
+
# 限制长度
|
158
|
+
tr_name = tr["name"]
|
159
|
+
|
160
|
+
if is_icon:
|
161
|
+
f = 38
|
162
|
+
icon = get_icon(tr["name"], icon_path)
|
163
|
+
bt.paste(icon_mask, (14, 20), icon)
|
164
|
+
else:
|
165
|
+
f = 0
|
166
|
+
|
167
|
+
# 标题
|
168
|
+
bt_draw.text((20 + f, 28), tr_name, text_color, font(26), "lm")
|
169
|
+
# 使用范例
|
170
|
+
bt_draw.text((20 + f, 50), tr["eg"], sub_c, font(17), "lm")
|
171
|
+
# 简单介绍
|
172
|
+
bt_draw.text((20, 78), tr["desc"], op_color, font(16), "lm")
|
173
|
+
|
174
|
+
offset_x = button_x * (index % column)
|
175
|
+
offset_y = button_y * (index // column)
|
176
|
+
sv_img.paste(bt, (25 + offset_x, 83 + offset_y), bt)
|
177
|
+
|
178
|
+
sv_img_list.append(sv_img)
|
179
|
+
|
180
|
+
img = crop_center_img(bg, w, h)
|
181
|
+
if is_gaussian:
|
182
|
+
img = img.filter(ImageFilter.GaussianBlur(gaussian_blur))
|
183
|
+
|
184
|
+
img.paste(title, (0, 0), title)
|
185
|
+
temp = 0
|
186
|
+
for _sm in sv_img_list:
|
187
|
+
img.paste(_sm, (0, _h + temp), _sm)
|
188
|
+
temp += _sm.size[1]
|
189
|
+
|
190
|
+
img = img.convert("RGBA")
|
191
|
+
all_white = Image.new("RGBA", img.size, (255, 255, 255))
|
192
|
+
img = Image.alpha_composite(all_white, img)
|
193
|
+
|
194
|
+
img = img.convert("RGB")
|
195
|
+
help_path = plugin_data.data_dir.joinpath("help") / f"{name}.jpg"
|
196
|
+
help_path.parent.mkdir(parents=True, exist_ok=True)
|
197
|
+
if enable_cache:
|
198
|
+
img.save(
|
199
|
+
help_path,
|
200
|
+
"JPEG",
|
201
|
+
quality=pic_quality,
|
202
|
+
subsampling=0,
|
203
|
+
)
|
204
|
+
cache[name] = 1
|
205
|
+
|
206
|
+
return await convert_img(img)
|
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
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from typing import List
|
2
|
+
|
3
|
+
from ..utils.api.models import OutServer
|
4
|
+
from .html_img import server_ip_pic
|
5
|
+
|
6
|
+
|
7
|
+
async def msg_to_image(server_dict: List[OutServer], mode="html"):
|
8
|
+
"""信息构造图片"""
|
9
|
+
if mode == "html":
|
10
|
+
"""用浏览器作图"""
|
11
|
+
return await server_ip_pic(server_dict)
|
12
|
+
if mode == "pil":
|
13
|
+
"""用pil作图"""
|
14
|
+
return None
|
15
|
+
"""返回文字"""
|
16
|
+
return None
|
@@ -0,0 +1,175 @@
|
|
1
|
+
from base64 import b64encode
|
2
|
+
from io import BytesIO
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import Union, overload
|
5
|
+
|
6
|
+
import aiofiles
|
7
|
+
from nonebot.log import logger
|
8
|
+
from PIL import Image, ImageDraw, ImageFont
|
9
|
+
|
10
|
+
from .image_tools import draw_center_text_by_line
|
11
|
+
|
12
|
+
FONT_PATH = Path(__file__).parent.parent / "data/font/loli.ttf"
|
13
|
+
pic_quality: int = 95
|
14
|
+
|
15
|
+
|
16
|
+
def core_font(size: int) -> ImageFont.FreeTypeFont:
|
17
|
+
return ImageFont.truetype(str(FONT_PATH), size=size)
|
18
|
+
|
19
|
+
|
20
|
+
@overload
|
21
|
+
async def convert_img(
|
22
|
+
img: Image.Image,
|
23
|
+
is_base64: bool = False,
|
24
|
+
) -> bytes:
|
25
|
+
...
|
26
|
+
|
27
|
+
|
28
|
+
@overload
|
29
|
+
async def convert_img(
|
30
|
+
img: Image.Image,
|
31
|
+
is_base64: bool = True,
|
32
|
+
) -> str:
|
33
|
+
...
|
34
|
+
|
35
|
+
|
36
|
+
@overload
|
37
|
+
async def convert_img(
|
38
|
+
img: bytes,
|
39
|
+
is_base64: bool = False,
|
40
|
+
) -> str:
|
41
|
+
...
|
42
|
+
|
43
|
+
|
44
|
+
@overload
|
45
|
+
async def convert_img(
|
46
|
+
img: Path,
|
47
|
+
is_base64: bool = False,
|
48
|
+
) -> str:
|
49
|
+
...
|
50
|
+
|
51
|
+
|
52
|
+
async def convert_img(
|
53
|
+
img: Union[Image.Image, str, Path, bytes],
|
54
|
+
is_base64: bool = False,
|
55
|
+
):
|
56
|
+
"""
|
57
|
+
:说明:
|
58
|
+
将PIL.Image对象转换为bytes或者base64格式。
|
59
|
+
:参数:
|
60
|
+
* img (Image): 图片。
|
61
|
+
* is_base64 (bool): 是否转换为base64格式, 不填默认转为bytes。
|
62
|
+
:返回:
|
63
|
+
* res: bytes对象或base64编码图片。
|
64
|
+
"""
|
65
|
+
logger.info("处理图片中....")
|
66
|
+
|
67
|
+
if isinstance(img, Image.Image):
|
68
|
+
img = img.convert("RGB")
|
69
|
+
result_buffer = BytesIO()
|
70
|
+
img.save(result_buffer, format="JPEG", quality=95)
|
71
|
+
res = result_buffer.getvalue()
|
72
|
+
if is_base64:
|
73
|
+
res = "base64://" + b64encode(res).decode()
|
74
|
+
return res
|
75
|
+
if isinstance(img, bytes):
|
76
|
+
pass
|
77
|
+
else:
|
78
|
+
async with aiofiles.open(img, "rb") as fp:
|
79
|
+
img = await fp.read()
|
80
|
+
|
81
|
+
logger.success("图片处理完成!")
|
82
|
+
|
83
|
+
return f"base64://{b64encode(img).decode()}"
|
84
|
+
|
85
|
+
|
86
|
+
def convert_img_sync(img_path: Path):
|
87
|
+
with img_path.open("rb") as fp:
|
88
|
+
img = fp.read()
|
89
|
+
|
90
|
+
return f"base64://{b64encode(img).decode()}"
|
91
|
+
|
92
|
+
|
93
|
+
async def str_lenth(r: str, size: int, limit: int = 540) -> str:
|
94
|
+
result = ""
|
95
|
+
temp = 0
|
96
|
+
for i in r:
|
97
|
+
if i == "\n":
|
98
|
+
temp = 0
|
99
|
+
result += i
|
100
|
+
continue
|
101
|
+
|
102
|
+
if temp >= limit:
|
103
|
+
result += "\n" + i
|
104
|
+
temp = 0
|
105
|
+
else:
|
106
|
+
result += i
|
107
|
+
|
108
|
+
if i.isdigit():
|
109
|
+
temp += round(size / 10 * 6)
|
110
|
+
elif i == "/":
|
111
|
+
temp += round(size / 10 * 2.2)
|
112
|
+
elif i == ".":
|
113
|
+
temp += round(size / 10 * 3)
|
114
|
+
elif i == "%":
|
115
|
+
temp += round(size / 10 * 9.4)
|
116
|
+
else:
|
117
|
+
temp += size
|
118
|
+
return result
|
119
|
+
|
120
|
+
|
121
|
+
def get_str_size(
|
122
|
+
r: str,
|
123
|
+
font: ImageFont.FreeTypeFont,
|
124
|
+
limit: int = 540,
|
125
|
+
) -> str:
|
126
|
+
result = ""
|
127
|
+
line = ""
|
128
|
+
for i in r:
|
129
|
+
if i == "\n":
|
130
|
+
result += f"{line}\n"
|
131
|
+
line = ""
|
132
|
+
continue
|
133
|
+
|
134
|
+
line += i
|
135
|
+
|
136
|
+
if hasattr(font, "getsize"):
|
137
|
+
size, _ = font.getsize(line) # type: ignore
|
138
|
+
else:
|
139
|
+
bbox = font.getbbox(line)
|
140
|
+
size, _ = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
141
|
+
|
142
|
+
if size >= limit:
|
143
|
+
result += f"{line}\n"
|
144
|
+
line = ""
|
145
|
+
else:
|
146
|
+
result += line
|
147
|
+
return result
|
148
|
+
|
149
|
+
|
150
|
+
def get_height(content: str, size: int) -> int:
|
151
|
+
line_count = content.count("\n")
|
152
|
+
return (line_count + 1) * size
|
153
|
+
|
154
|
+
|
155
|
+
async def text2pic(text: str, max_size: int = 800, font_size: int = 24):
|
156
|
+
if text.endswith("\n"):
|
157
|
+
text = text[:-1]
|
158
|
+
|
159
|
+
img = Image.new(
|
160
|
+
"RGB",
|
161
|
+
(max_size, len(text) * font_size // 3),
|
162
|
+
(255, 255, 255),
|
163
|
+
)
|
164
|
+
img_draw = ImageDraw.ImageDraw(img)
|
165
|
+
y = draw_center_text_by_line(
|
166
|
+
img_draw,
|
167
|
+
(50, 50),
|
168
|
+
text,
|
169
|
+
core_font(font_size),
|
170
|
+
"black",
|
171
|
+
max_size - 80,
|
172
|
+
True,
|
173
|
+
)
|
174
|
+
img = img.crop((0, 0, max_size, int(y + 80)))
|
175
|
+
return await convert_img(img)
|