mirror of
https://github.com/Genshin-bots/gsuid_core.git
synced 2025-05-12 06:55:49 +08:00
✨ 支持传参生成帮助图
This commit is contained in:
parent
cbfe28f7f4
commit
343cef5dc1
107
gsuid_core/help/draw_plugin_help.py
Normal file
107
gsuid_core/help/draw_plugin_help.py
Normal file
@ -0,0 +1,107 @@
|
||||
from copy import deepcopy
|
||||
from typing import Dict, List, Tuple, Callable, Optional
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
from gsuid_core.data_store import get_res_path
|
||||
from gsuid_core.utils.image.convert import convert_img
|
||||
from gsuid_core.utils.image.image_tools import (
|
||||
crop_center_img,
|
||||
easy_alpha_composite,
|
||||
)
|
||||
|
||||
from .model import PluginHelp
|
||||
|
||||
cache: Dict[str, int] = {}
|
||||
|
||||
|
||||
async def get_help(
|
||||
name: str,
|
||||
sub_text: str,
|
||||
help_data: Dict[str, PluginHelp],
|
||||
bg: Image.Image,
|
||||
icon: Image.Image,
|
||||
badge: Image.Image,
|
||||
banner: Image.Image,
|
||||
button: Image.Image,
|
||||
font: Callable[[int], ImageFont.FreeTypeFont],
|
||||
is_dark: bool = True,
|
||||
text_color: Tuple[int, int, int] = (250, 250, 250),
|
||||
sub_color: Optional[Tuple[int, int, int]] = None,
|
||||
) -> bytes:
|
||||
help_path = get_res_path('help') / f'{name}.jpg'
|
||||
|
||||
if help_path.exists() and name in cache and cache[name]:
|
||||
return await convert_img(Image.open(help_path))
|
||||
|
||||
if sub_color is None and is_dark:
|
||||
sub_color = tuple(x - 50 for x in text_color if x > 50)
|
||||
elif sub_color is None and not is_dark:
|
||||
sub_color = tuple(x + 50 for x in text_color if x < 205)
|
||||
|
||||
title = Image.new('RGBA', (900, 600))
|
||||
icon = icon.resize((300, 300))
|
||||
title.paste(icon, (300, 89), icon)
|
||||
title.paste(badge, (0, 390), badge)
|
||||
badge_s = badge.resize((720, 80))
|
||||
title.paste(badge_s, (90, 480), badge_s)
|
||||
title_draw = ImageDraw.Draw(title)
|
||||
|
||||
title_draw.text((450, 440), f'{name} 帮助', text_color, font(36), 'mm')
|
||||
title_draw.text((450, 520), sub_text, sub_color, font(26), 'mm')
|
||||
|
||||
w, h = 900, 630
|
||||
|
||||
sv_img_list: List[Image.Image] = []
|
||||
for sv_name in help_data:
|
||||
tr_size = len(help_data[sv_name]['data'])
|
||||
y = 100 + ((tr_size + 3) // 4) * 80
|
||||
h += y
|
||||
sv_img = Image.new('RGBA', (900, y))
|
||||
sv_data = help_data[sv_name]['data']
|
||||
sv_desc = help_data[sv_name]['desc']
|
||||
|
||||
bc = deepcopy(banner)
|
||||
bc_draw = ImageDraw.Draw(bc)
|
||||
bc_draw.text((30, 25), sv_name, text_color, font(35), 'lm')
|
||||
size, _ = font(35).getsize(sv_name)
|
||||
bc_draw.text((42 + size, 30), sv_desc, sub_color, font(20), 'lm')
|
||||
sv_img = easy_alpha_composite(sv_img, bc, (0, 10))
|
||||
# sv_img.paste(bc, (0, 10), bc)
|
||||
|
||||
for index, tr in enumerate(sv_data):
|
||||
bt = deepcopy(button)
|
||||
bt_draw = ImageDraw.Draw(bt)
|
||||
if len(tr['name']) > 8:
|
||||
tr_name = tr['name'][:5] + '..'
|
||||
else:
|
||||
tr_name = tr['name']
|
||||
|
||||
bt_draw.text((105, 28), tr_name, text_color, font(26), 'mm')
|
||||
bt_draw.text((105, 51), tr['eg'], sub_color, font(17), 'mm')
|
||||
offset_x = 210 * (index % 4)
|
||||
offset_y = 80 * (index // 4)
|
||||
sv_img = easy_alpha_composite(
|
||||
sv_img, bt, (26 + offset_x, 83 + offset_y)
|
||||
)
|
||||
# sv_img.paste(bt, (26 + offset_x, 83 + offset_y), bt)
|
||||
|
||||
sv_img_list.append(sv_img)
|
||||
|
||||
img = crop_center_img(bg, w, h)
|
||||
img.paste(title, (0, 0), title)
|
||||
temp = 0
|
||||
for _sm in sv_img_list:
|
||||
img.paste(_sm, (0, 600 + temp), _sm)
|
||||
temp += _sm.size[1]
|
||||
|
||||
img = img.convert('RGB')
|
||||
help_path = get_res_path('help') / f'{name}.jpg'
|
||||
img.save(
|
||||
help_path,
|
||||
'JPEG',
|
||||
quality=85,
|
||||
subsampling=0,
|
||||
)
|
||||
cache[name] = 1
|
||||
return await convert_img(img)
|
15
gsuid_core/help/model.py
Normal file
15
gsuid_core/help/model.py
Normal file
@ -0,0 +1,15 @@
|
||||
from typing import List, TypedDict
|
||||
|
||||
|
||||
class PluginSV(TypedDict):
|
||||
name: str
|
||||
desc: str
|
||||
eg: str
|
||||
need_ck: bool
|
||||
need_sk: bool
|
||||
need_admin: bool
|
||||
|
||||
|
||||
class PluginHelp(TypedDict):
|
||||
desc: str
|
||||
data: List[PluginSV]
|
65
gsuid_core/tools/gen_help.py
Normal file
65
gsuid_core/tools/gen_help.py
Normal file
@ -0,0 +1,65 @@
|
||||
import copy
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from openpyxl import load_workbook
|
||||
|
||||
sample = {
|
||||
'name': '',
|
||||
'desc': '',
|
||||
'eg': '',
|
||||
'need_ck': False,
|
||||
'need_sk': False,
|
||||
'need_admin': False,
|
||||
}
|
||||
|
||||
result = {}
|
||||
|
||||
HELP_PATH = Path(__file__).parent / 'Help.xlsx'
|
||||
OUTPUT_PATH = Path(__file__).parent / 'Help.json'
|
||||
|
||||
wb = load_workbook(str(HELP_PATH))
|
||||
ws = wb.active
|
||||
|
||||
module_name_str = ''
|
||||
for row in range(2, 999):
|
||||
# 跳过空白行
|
||||
if not ws.cell(row, 2).value:
|
||||
continue
|
||||
|
||||
_sample = copy.deepcopy(sample)
|
||||
|
||||
# 将第一列读取为模块名
|
||||
if ws.cell(row, 1):
|
||||
if ws.cell(row, 1).value is not None:
|
||||
module_name_str = ws.cell(row, 1).value
|
||||
|
||||
# if module_name_str is None and not isinstance(module_name_str, str):
|
||||
# continue
|
||||
|
||||
# 第二列为功能名
|
||||
_sample['name'] = ws.cell(row, 2).value
|
||||
# 第三列为详细信息
|
||||
_sample['desc'] = ws.cell(row, 3).value
|
||||
# 第四列为使用例
|
||||
_sample['eg'] = ws.cell(row, 4).value
|
||||
|
||||
if ws.cell(row, 5).value == '是':
|
||||
_sample['need_ck'] = True
|
||||
|
||||
if ws.cell(row, 6).value == '是':
|
||||
_sample['need_sk'] = True
|
||||
|
||||
if ws.cell(row, 7).value == '是':
|
||||
_sample['need_admin'] = True
|
||||
|
||||
if isinstance(module_name_str, str):
|
||||
module_name = module_name_str.split(' | ')[0]
|
||||
module_desc = module_name_str.split(' | ')[1]
|
||||
if module_name not in result:
|
||||
result[module_name] = {'desc': module_desc, 'data': []}
|
||||
|
||||
result[module_name]['data'].append(_sample)
|
||||
|
||||
with open(OUTPUT_PATH, 'w', encoding='utf-8') as f:
|
||||
json.dump(result, f, indent=2, ensure_ascii=False)
|
Loading…
x
Reference in New Issue
Block a user