2024-02-25 03:18:34 +08:00
|
|
|
|
import os
|
|
|
|
|
|
import random
|
|
|
|
|
|
from typing import Dict
|
|
|
|
|
|
|
|
|
|
|
|
from zhenxun.configs.config import Config
|
|
|
|
|
|
from zhenxun.configs.path_config import DATA_PATH, IMAGE_PATH, TEMPLATE_PATH
|
|
|
|
|
|
from zhenxun.models.group_console import GroupConsole
|
|
|
|
|
|
from zhenxun.models.plugin_info import PluginInfo
|
|
|
|
|
|
from zhenxun.utils.enum import BlockType, PluginType
|
|
|
|
|
|
from zhenxun.utils.image_utils import BuildImage, build_sort_image, group_image
|
|
|
|
|
|
|
|
|
|
|
|
from ._config import Item
|
|
|
|
|
|
|
|
|
|
|
|
GROUP_HELP_PATH = DATA_PATH / "group_help"
|
|
|
|
|
|
GROUP_HELP_PATH.mkdir(exist_ok=True, parents=True)
|
|
|
|
|
|
for f in os.listdir(GROUP_HELP_PATH):
|
|
|
|
|
|
group_help_image = GROUP_HELP_PATH / f
|
|
|
|
|
|
group_help_image.unlink()
|
|
|
|
|
|
|
|
|
|
|
|
BACKGROUND_PATH = IMAGE_PATH / "background" / "help" / "simple_help"
|
|
|
|
|
|
|
|
|
|
|
|
LOGO_PATH = TEMPLATE_PATH / "menu" / "res" / "logo"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class HelpImageBuild:
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
self._data: list[PluginInfo] = []
|
|
|
|
|
|
self._sort_data: Dict[str, list[PluginInfo]] = {}
|
|
|
|
|
|
self._image_list = []
|
|
|
|
|
|
self.icon2str = {
|
|
|
|
|
|
"normal": "fa fa-cog",
|
|
|
|
|
|
"原神相关": "fa fa-circle-o",
|
|
|
|
|
|
"常规插件": "fa fa-cubes",
|
|
|
|
|
|
"联系管理员": "fa fa-envelope-o",
|
|
|
|
|
|
"抽卡相关": "fa fa-credit-card-alt",
|
|
|
|
|
|
"来点好康的": "fa fa-picture-o",
|
|
|
|
|
|
"数据统计": "fa fa-bar-chart",
|
|
|
|
|
|
"一些工具": "fa fa-shopping-cart",
|
|
|
|
|
|
"商店": "fa fa-shopping-cart",
|
|
|
|
|
|
"其它": "fa fa-tags",
|
|
|
|
|
|
"群内小游戏": "fa fa-gamepad",
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async def sort_type(self):
|
|
|
|
|
|
"""
|
|
|
|
|
|
对插件按照菜单类型分类
|
|
|
|
|
|
"""
|
|
|
|
|
|
if not self._data:
|
2024-07-31 18:34:22 +08:00
|
|
|
|
self._data = await PluginInfo.filter(
|
2024-08-15 23:52:19 +08:00
|
|
|
|
menu_type__not="",
|
2024-08-15 21:29:49 +08:00
|
|
|
|
load_status=True,
|
2024-08-18 22:26:53 +08:00
|
|
|
|
plugin_type__in=[PluginType.NORMAL, PluginType.DEPENDANT],
|
2024-07-31 18:34:22 +08:00
|
|
|
|
)
|
2024-02-25 03:18:34 +08:00
|
|
|
|
if not self._sort_data:
|
|
|
|
|
|
for plugin in self._data:
|
|
|
|
|
|
menu_type = plugin.menu_type or "normal"
|
2024-07-31 19:10:31 +08:00
|
|
|
|
if menu_type == "normal":
|
|
|
|
|
|
menu_type = "功能"
|
2024-02-25 03:18:34 +08:00
|
|
|
|
if not self._sort_data.get(menu_type):
|
|
|
|
|
|
self._sort_data[menu_type] = []
|
|
|
|
|
|
self._sort_data[menu_type].append(plugin)
|
|
|
|
|
|
|
2024-02-27 16:12:56 +08:00
|
|
|
|
async def build_image(self, group_id: str | None):
|
2024-02-25 03:18:34 +08:00
|
|
|
|
if group_id:
|
|
|
|
|
|
help_image = GROUP_HELP_PATH / f"{group_id}.png"
|
|
|
|
|
|
else:
|
|
|
|
|
|
help_image = IMAGE_PATH / f"SIMPLE_HELP.png"
|
|
|
|
|
|
build_type = Config.get_config("help", "TYPE")
|
|
|
|
|
|
if build_type == "HTML":
|
|
|
|
|
|
byt = await self.build_html_image(group_id)
|
|
|
|
|
|
with open(help_image, "wb") as f:
|
|
|
|
|
|
f.write(byt)
|
|
|
|
|
|
else:
|
|
|
|
|
|
img = await self.build_pil_image(group_id)
|
|
|
|
|
|
await img.save(help_image)
|
|
|
|
|
|
|
2024-02-27 16:12:56 +08:00
|
|
|
|
async def build_html_image(self, group_id: str | None) -> bytes:
|
2024-02-25 03:18:34 +08:00
|
|
|
|
from nonebot_plugin_htmlrender import template_to_pic
|
|
|
|
|
|
|
|
|
|
|
|
await self.sort_type()
|
|
|
|
|
|
classify = {}
|
|
|
|
|
|
for menu in self._sort_data:
|
|
|
|
|
|
for plugin in self._sort_data[menu]:
|
|
|
|
|
|
sta = 0
|
|
|
|
|
|
if not plugin.status:
|
|
|
|
|
|
if group_id and plugin.block_type in [
|
|
|
|
|
|
BlockType.ALL,
|
|
|
|
|
|
BlockType.GROUP,
|
|
|
|
|
|
]:
|
|
|
|
|
|
sta = 2
|
|
|
|
|
|
if not group_id and plugin.block_type in [
|
|
|
|
|
|
BlockType.ALL,
|
2024-02-26 03:04:32 +08:00
|
|
|
|
BlockType.PRIVATE,
|
2024-02-25 03:18:34 +08:00
|
|
|
|
]:
|
|
|
|
|
|
sta = 2
|
|
|
|
|
|
if group_id and (
|
|
|
|
|
|
group := await GroupConsole.get_or_none(group_id=group_id)
|
|
|
|
|
|
):
|
|
|
|
|
|
if f"{plugin.module}:super," in group.block_plugin:
|
|
|
|
|
|
sta = 2
|
|
|
|
|
|
if f"{plugin.module}," in group.block_plugin:
|
|
|
|
|
|
sta = 1
|
|
|
|
|
|
if classify.get(menu):
|
|
|
|
|
|
classify[menu].append(Item(plugin_name=plugin.name, sta=sta))
|
|
|
|
|
|
else:
|
|
|
|
|
|
classify[menu] = [Item(plugin_name=plugin.name, sta=sta)]
|
|
|
|
|
|
max_len = 0
|
|
|
|
|
|
flag_index = -1
|
|
|
|
|
|
max_data = None
|
|
|
|
|
|
plugin_list = []
|
|
|
|
|
|
for index, plu in enumerate(classify.keys()):
|
|
|
|
|
|
if plu in self.icon2str.keys():
|
|
|
|
|
|
icon = self.icon2str[plu]
|
|
|
|
|
|
else:
|
|
|
|
|
|
icon = "fa fa-pencil-square-o"
|
|
|
|
|
|
logo = LOGO_PATH / random.choice(os.listdir(LOGO_PATH))
|
|
|
|
|
|
data = {
|
|
|
|
|
|
"name": plu if plu != "normal" else "功能",
|
|
|
|
|
|
"items": classify[plu],
|
|
|
|
|
|
"icon": icon,
|
|
|
|
|
|
"logo": str(logo.absolute()),
|
|
|
|
|
|
}
|
|
|
|
|
|
if len(classify[plu]) > max_len:
|
|
|
|
|
|
max_len = len(classify[plu])
|
|
|
|
|
|
flag_index = index
|
|
|
|
|
|
max_data = data
|
|
|
|
|
|
plugin_list.append(data)
|
|
|
|
|
|
del plugin_list[flag_index]
|
|
|
|
|
|
plugin_list.insert(0, max_data)
|
|
|
|
|
|
pic = await template_to_pic(
|
|
|
|
|
|
template_path=str((TEMPLATE_PATH / "menu").absolute()),
|
|
|
|
|
|
template_name="zhenxun_menu.html",
|
|
|
|
|
|
templates={"plugin_list": plugin_list},
|
|
|
|
|
|
pages={
|
|
|
|
|
|
"viewport": {"width": 1903, "height": 975},
|
|
|
|
|
|
"base_url": f"file://{TEMPLATE_PATH}",
|
|
|
|
|
|
},
|
|
|
|
|
|
wait=2,
|
|
|
|
|
|
)
|
|
|
|
|
|
return pic
|
|
|
|
|
|
|
2024-02-27 16:12:56 +08:00
|
|
|
|
async def build_pil_image(self, group_id: str | None) -> BuildImage:
|
2024-02-25 03:18:34 +08:00
|
|
|
|
"""构造帮助图片
|
|
|
|
|
|
|
|
|
|
|
|
参数:
|
|
|
|
|
|
group_id: 群号
|
|
|
|
|
|
"""
|
|
|
|
|
|
self._image_list = []
|
|
|
|
|
|
await self.sort_type()
|
|
|
|
|
|
font_size = 24
|
|
|
|
|
|
build_type = Config.get_config("help", "TYPE")
|
|
|
|
|
|
font = BuildImage.load_font("HYWenHei-85W.ttf", 20)
|
|
|
|
|
|
for idx, menu_type in enumerate(self._sort_data.keys()):
|
|
|
|
|
|
plugin_list = self._sort_data[menu_type]
|
2024-07-31 18:34:22 +08:00
|
|
|
|
wh_list = [
|
|
|
|
|
|
BuildImage.get_text_size(f"{x.id}.{x.name}", font) for x in plugin_list
|
|
|
|
|
|
]
|
2024-02-25 03:18:34 +08:00
|
|
|
|
wh_list.append(BuildImage.get_text_size(menu_type, font))
|
|
|
|
|
|
# sum_height = sum([x[1] for x in wh_list])
|
|
|
|
|
|
if build_type == "VV":
|
|
|
|
|
|
sum_height = 50 * len(plugin_list) + 10
|
|
|
|
|
|
else:
|
|
|
|
|
|
sum_height = (font_size + 6) * len(plugin_list) + 10
|
2024-07-31 18:34:22 +08:00
|
|
|
|
max_width = max([x[0] for x in wh_list]) + 30
|
2024-02-25 03:18:34 +08:00
|
|
|
|
bk = BuildImage(
|
|
|
|
|
|
max_width + 40,
|
|
|
|
|
|
sum_height + 50,
|
|
|
|
|
|
font_size=30,
|
|
|
|
|
|
color="#a7d1fc",
|
|
|
|
|
|
font="CJGaoDeGuo.otf",
|
|
|
|
|
|
)
|
|
|
|
|
|
title_size = bk.getsize(menu_type)
|
|
|
|
|
|
max_width = max_width if max_width > title_size[0] else title_size[0]
|
|
|
|
|
|
B = BuildImage(
|
|
|
|
|
|
max_width + 40,
|
|
|
|
|
|
sum_height,
|
|
|
|
|
|
font_size=font_size,
|
|
|
|
|
|
color="white" if not idx % 2 else "black",
|
|
|
|
|
|
)
|
|
|
|
|
|
curr_h = 10
|
2024-02-28 00:38:54 +08:00
|
|
|
|
group = await GroupConsole.get_or_none(group_id=group_id)
|
|
|
|
|
|
for i, plugin in enumerate(plugin_list):
|
|
|
|
|
|
text_color = (255, 255, 255) if idx % 2 else (0, 0, 0)
|
|
|
|
|
|
if group and f"{plugin.module}," in group.block_plugin:
|
|
|
|
|
|
text_color = (252, 75, 13)
|
|
|
|
|
|
pos = None
|
|
|
|
|
|
# 禁用状态划线
|
|
|
|
|
|
if plugin.block_type in [BlockType.ALL, BlockType.GROUP] or (
|
|
|
|
|
|
group and f"super:{plugin.module}," in group.block_plugin
|
|
|
|
|
|
):
|
|
|
|
|
|
w = curr_h + int(B.getsize(plugin.name)[1] / 2) + 2
|
|
|
|
|
|
pos = (
|
|
|
|
|
|
7,
|
|
|
|
|
|
w,
|
|
|
|
|
|
B.getsize(plugin.name)[0] + 35,
|
|
|
|
|
|
w,
|
|
|
|
|
|
)
|
|
|
|
|
|
if build_type == "VV":
|
|
|
|
|
|
name_image = await self.build_name_image( # type: ignore
|
|
|
|
|
|
max_width,
|
|
|
|
|
|
plugin.name,
|
|
|
|
|
|
"black" if not idx % 2 else "white",
|
|
|
|
|
|
text_color,
|
|
|
|
|
|
pos,
|
|
|
|
|
|
)
|
|
|
|
|
|
await B.paste(name_image, (0, curr_h), center_type="width")
|
|
|
|
|
|
curr_h += name_image.h + 5
|
|
|
|
|
|
else:
|
2024-07-31 18:34:22 +08:00
|
|
|
|
await B.text((10, curr_h), f"{plugin.id}.{plugin.name}", text_color)
|
2024-02-28 00:38:54 +08:00
|
|
|
|
if pos:
|
|
|
|
|
|
await B.line(pos, (236, 66, 7), 3)
|
|
|
|
|
|
curr_h += font_size + 5
|
2024-02-25 03:18:34 +08:00
|
|
|
|
await bk.text((0, 14), menu_type, center_type="width")
|
|
|
|
|
|
await bk.paste(B, (0, 50))
|
|
|
|
|
|
await bk.transparent(2)
|
|
|
|
|
|
# await bk.acircle_corner(point_list=['lt', 'rt'])
|
|
|
|
|
|
self._image_list.append(bk)
|
|
|
|
|
|
image_group, h = group_image(self._image_list)
|
2024-07-31 19:10:31 +08:00
|
|
|
|
|
|
|
|
|
|
async def _a(image: BuildImage):
|
|
|
|
|
|
await image.filter("GaussianBlur", 5)
|
|
|
|
|
|
|
2024-02-25 03:18:34 +08:00
|
|
|
|
B = await build_sort_image(
|
|
|
|
|
|
image_group,
|
|
|
|
|
|
h,
|
|
|
|
|
|
background_path=BACKGROUND_PATH,
|
2024-07-31 19:10:31 +08:00
|
|
|
|
background_handle=_a,
|
2024-02-25 03:18:34 +08:00
|
|
|
|
)
|
|
|
|
|
|
w = 10
|
|
|
|
|
|
h = 10
|
|
|
|
|
|
for msg in [
|
|
|
|
|
|
"目前支持的功能列表:",
|
2024-07-31 18:34:22 +08:00
|
|
|
|
"可以通过 ‘帮助 [功能名称或功能Id]’ 来获取对应功能的使用方法",
|
2024-02-25 03:18:34 +08:00
|
|
|
|
]:
|
|
|
|
|
|
text = await BuildImage.build_text_image(msg, "HYWenHei-85W.ttf", 24)
|
|
|
|
|
|
await B.paste(text, (w, h))
|
|
|
|
|
|
h += 50
|
|
|
|
|
|
if msg == "目前支持的功能列表:":
|
|
|
|
|
|
w += 50
|
|
|
|
|
|
text = await BuildImage.build_text_image(
|
|
|
|
|
|
"注: 红字代表功能被群管理员禁用,红线代表功能正在维护",
|
|
|
|
|
|
"HYWenHei-85W.ttf",
|
|
|
|
|
|
24,
|
|
|
|
|
|
(231, 74, 57),
|
|
|
|
|
|
)
|
|
|
|
|
|
await B.paste(
|
|
|
|
|
|
text,
|
|
|
|
|
|
(300, 10),
|
|
|
|
|
|
)
|
|
|
|
|
|
return B
|