diff --git a/resources/template/sign/main.css b/resources/template/sign/main.css index 5d9a7016..8e313f64 100644 --- a/resources/template/sign/main.css +++ b/resources/template/sign/main.css @@ -280,6 +280,6 @@ body { font-size: 20px; top: 350px; left: 250px; - font-family: 'yshsFont'; + font-family: 'rxxxtFont'; width: 210px; } \ No newline at end of file diff --git a/resources/template/ss_menu/main.css b/resources/template/ss_menu/main.css new file mode 100644 index 00000000..1cde35f4 --- /dev/null +++ b/resources/template/ss_menu/main.css @@ -0,0 +1,142 @@ + + +@font-face { + font-family: fzrzFont; + /* 导入的字体文件 */ + src: url("./res/font/fzrzExtraBold.ttf"); +} + +@font-face { + font-family: syhtFont; + /* 导入的字体文件 */ + src: url("./res/font/syht.otf"); +} + +@font-face { + font-family: systFont; + /* 导入的字体文件 */ + src: url("./res/font/syst.otf"); +} + + + +body { + position: absolute; + left: -8px; + top: -8px; +} + +.wrapper{ + /* height: 1321px; */ + width: 637px; + background-image: url('res/img/bk.jpg'); + background-size: cover; + position: relative; + font-family: 'cr105Font'; + display: flex; + justify-content: center; + align-items: center; + padding: 25px 0; +} + +.zx-img { + position: absolute; + width: 222px; + bottom: 0; + right: 3px; + z-index: 0; +} + +.avatar { + height: 73px; + width: 73px; + border-radius: 50%; + position: absolute; + top: 153px; + left: 40px; + border: #F3868C 1px solid; +} + +.avatar-img { + height: 73px; + width: 73px; + border-radius: 50%; +} + +.main { + background-image: url('res/img/main.png'); + background-size: 100% 100%; + /* background-size: cover; */ + height: auto; + width: 595px; + position: relative; +} + +.head-text { + font-size: 53px; + font-family: 'fzrzFont'; + margin-left: 40px; + /* color: #F67186; */ + background: linear-gradient(to right, #F67186, #F7889C); + -webkit-background-clip: text; + background-clip: text; + color: transparent; +} + +.help-text { + font-size: 19px; + font-family: 'systFont'; + margin-left: 40px; + /* color: #F67186; */ + background: linear-gradient(to right, #F67186, #F7889C); + -webkit-background-clip: text; + background-clip: text; + color: transparent; + position: absolute; + top: 118px; + left: -5px; +} + +.menu-list { + width: 593px; + height: calc(100% - 230px); + /* background-color: blanchedalmond; */ + /* margin-left: 35px; */ + margin-top: 35px; + /* float: left; */ + display: flex; /* 使用flex布局 */ + flex-wrap: wrap; +} + + +.main-menu { + /* width: 100%; */ + z-index: 1; +} + +.title { + height: 45px; + width: 225px; + background-image: url('res/img/title.png'); + background-size: cover; + background-repeat: no-repeat; + /* background: linear-gradient(to right, #F67186, #F7889C); */ + font-family: 'fzrzFont'; + display: flex; + justify-content: center; + align-items: center; + color: white; + font-size: 30px; + border-radius: 16px; + letter-spacing:4px; + margin: 0 auto; +} + +.plugin-list { + display: flex; + /* justify-content: center; */ + /* align-items: center; */ + font-family: 'syhtFont'; + font-size: 25px; + z-index: 1; +} \ No newline at end of file diff --git a/resources/template/ss_menu/main.html b/resources/template/ss_menu/main.html new file mode 100644 index 00000000..6c91ab74 --- /dev/null +++ b/resources/template/ss_menu/main.html @@ -0,0 +1,179 @@ + + + + + + + + + test + + + + +
+
+
+
真寻BOT的使用方法
+
可以通过'帮助[功能名称或功能ID]'来获取对应功能的使用方法
+
+ +
+ + + +
+
+ + + \ No newline at end of file diff --git a/resources/template/ss_menu/main.js b/resources/template/ss_menu/main.js new file mode 100644 index 00000000..e69de29b diff --git a/resources/template/ss_menu/res/font/fzrzExtraBold.ttf b/resources/template/ss_menu/res/font/fzrzExtraBold.ttf new file mode 100644 index 00000000..8afeafca Binary files /dev/null and b/resources/template/ss_menu/res/font/fzrzExtraBold.ttf differ diff --git a/resources/template/ss_menu/res/font/syht.otf b/resources/template/ss_menu/res/font/syht.otf new file mode 100644 index 00000000..630d5467 Binary files /dev/null and b/resources/template/ss_menu/res/font/syht.otf differ diff --git a/resources/template/ss_menu/res/font/syst.otf b/resources/template/ss_menu/res/font/syst.otf new file mode 100644 index 00000000..efa94cb5 Binary files /dev/null and b/resources/template/ss_menu/res/font/syst.otf differ diff --git a/resources/template/ss_menu/res/img/1.png b/resources/template/ss_menu/res/img/1.png new file mode 100644 index 00000000..d67a5f19 Binary files /dev/null and b/resources/template/ss_menu/res/img/1.png differ diff --git a/resources/template/ss_menu/res/img/3.png b/resources/template/ss_menu/res/img/3.png new file mode 100644 index 00000000..b8898bbb Binary files /dev/null and b/resources/template/ss_menu/res/img/3.png differ diff --git a/resources/template/ss_menu/res/img/bk.jpg b/resources/template/ss_menu/res/img/bk.jpg new file mode 100644 index 00000000..2883c68e Binary files /dev/null and b/resources/template/ss_menu/res/img/bk.jpg differ diff --git a/resources/template/ss_menu/res/img/main.png b/resources/template/ss_menu/res/img/main.png new file mode 100644 index 00000000..e1f8110e Binary files /dev/null and b/resources/template/ss_menu/res/img/main.png differ diff --git a/resources/template/ss_menu/res/img/title.png b/resources/template/ss_menu/res/img/title.png new file mode 100644 index 00000000..d5417753 Binary files /dev/null and b/resources/template/ss_menu/res/img/title.png differ diff --git a/zhenxun/builtin_plugins/help/__init__.py b/zhenxun/builtin_plugins/help/__init__.py index 3f89c117..7bbcdbf3 100644 --- a/zhenxun/builtin_plugins/help/__init__.py +++ b/zhenxun/builtin_plugins/help/__init__.py @@ -1,27 +1,26 @@ +from nonebot.rule import to_me from nonebot.adapters import Bot from nonebot.plugin import PluginMetadata -from nonebot.rule import to_me +from nonebot_plugin_session import EventSession from nonebot_plugin_alconna import ( - Alconna, - AlconnaQuery, Args, Match, - Option, Query, + Option, + Alconna, + AlconnaQuery, on_alconna, store_true, ) -from nonebot_plugin_session import EventSession -from zhenxun.configs.path_config import IMAGE_PATH -from zhenxun.configs.utils import PluginExtraData, RegisterConfig from zhenxun.services.log import logger from zhenxun.utils.enum import PluginType -from zhenxun.utils.image_utils import BuildImage from zhenxun.utils.message import MessageUtils +from zhenxun.configs.path_config import IMAGE_PATH +from zhenxun.configs.utils import RegisterConfig, PluginExtraData -from ._data_source import create_help_img, get_plugin_help from ._utils import GROUP_HELP_PATH +from ._data_source import create_help_img, get_plugin_help __plugin_meta__ = PluginMetadata( name="帮助", @@ -35,8 +34,8 @@ __plugin_meta__ = PluginMetadata( RegisterConfig( key="type", value="normal", - help="帮助图片样式 ['normal', 'HTML']", - default_value="normal", + help="帮助图片样式 ['normal', 'HTML', 'zhenxun']", + default_value="zhenxun", ) ], ).dict(), @@ -67,36 +66,25 @@ async def _( session: EventSession, is_superuser: Query[bool] = AlconnaQuery("superuser.value", False), ): - logger.debug("进入help") - _is_superuser = False - if is_superuser.available: - _is_superuser = is_superuser.result + _is_superuser = is_superuser.result if is_superuser.available else False if name.available: if _is_superuser and session.id1 not in bot.config.superusers: _is_superuser = False if result := await get_plugin_help(name.result, _is_superuser): - if isinstance(result, BuildImage): - await MessageUtils.build_message(result).send(reply_to=True) - else: - await MessageUtils.build_message(result).send(reply_to=True) + await MessageUtils.build_message(result).send(reply_to=True) else: await MessageUtils.build_message("没有此功能的帮助信息...").send( reply_to=True ) - logger.info( - f"查看帮助详情: {name.result}", - "帮助", - session=session, - ) + logger.info(f"查看帮助详情: {name.result}", "帮助", session=session) + elif gid := session.id3 or session.id2: + _image_path = GROUP_HELP_PATH / f"{gid}.png" + if not _image_path.exists(): + await create_help_img(bot.self_id, gid) + await MessageUtils.build_message(_image_path).finish() else: - if gid := session.id3 or session.id2: - _image_path = GROUP_HELP_PATH / f"{gid}.png" - if not _image_path.exists(): - await create_help_img(gid) - await MessageUtils.build_message(_image_path).finish() - else: - if not SIMPLE_HELP_IMAGE.exists(): - if SIMPLE_HELP_IMAGE.exists(): - SIMPLE_HELP_IMAGE.unlink() - await create_help_img(None) - await MessageUtils.build_message(SIMPLE_HELP_IMAGE).finish() + if not SIMPLE_HELP_IMAGE.exists(): + if SIMPLE_HELP_IMAGE.exists(): + SIMPLE_HELP_IMAGE.unlink() + await create_help_img(bot.self_id, None) + await MessageUtils.build_message(SIMPLE_HELP_IMAGE).finish() diff --git a/zhenxun/builtin_plugins/help/_data_source.py b/zhenxun/builtin_plugins/help/_data_source.py index 72467b2e..604d72d3 100644 --- a/zhenxun/builtin_plugins/help/_data_source.py +++ b/zhenxun/builtin_plugins/help/_data_source.py @@ -1,7 +1,7 @@ import nonebot -from zhenxun.configs.path_config import IMAGE_PATH from zhenxun.models.plugin_info import PluginInfo +from zhenxun.configs.path_config import IMAGE_PATH from zhenxun.utils.image_utils import BuildImage, ImageTemplate from ._utils import HelpImageBuild @@ -11,14 +11,14 @@ random_bk_path = IMAGE_PATH / "background" / "help" / "simple_help" background = IMAGE_PATH / "background" / "0.png" -async def create_help_img(group_id: str | None): - """ - 说明: - 生成帮助图片 +async def create_help_img(bot_id: str, group_id: str | None): + """生成帮助图片 + 参数: - :param group_id: 群号 + bot_id: bot id + group_id: 群号 """ - await HelpImageBuild().build_image(group_id) + await HelpImageBuild().build_image(bot_id, group_id) async def get_plugin_help(name: str, is_superuser: bool) -> str | BuildImage: diff --git a/zhenxun/builtin_plugins/help/_utils.py b/zhenxun/builtin_plugins/help/_utils.py index 3f4f891d..fa5b51b9 100644 --- a/zhenxun/builtin_plugins/help/_utils.py +++ b/zhenxun/builtin_plugins/help/_utils.py @@ -1,13 +1,16 @@ import os import random -from typing import Dict + +import aiofiles +from nonebot_plugin_htmlrender import template_to_pic 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 zhenxun.models.group_console import GroupConsole +from zhenxun.builtin_plugins.sign_in.utils import AVA_URL +from zhenxun.configs.path_config import DATA_PATH, IMAGE_PATH, TEMPLATE_PATH +from zhenxun.utils.image_utils import BuildImage, group_image, build_sort_image from ._config import Item @@ -25,7 +28,7 @@ LOGO_PATH = TEMPLATE_PATH / "menu" / "res" / "logo" class HelpImageBuild: def __init__(self): self._data: list[PluginInfo] = [] - self._sort_data: Dict[str, list[PluginInfo]] = {} + self._sort_data: dict[str, list[PluginInfo]] = {} self._image_list = [] self.icon2str = { "normal": "fa fa-cog", @@ -60,23 +63,104 @@ class HelpImageBuild: self._sort_data[menu_type] = [] self._sort_data[menu_type].append(plugin) - async def build_image(self, group_id: str | None): + async def build_image(self, bot_id: str, group_id: str | None): if group_id: help_image = GROUP_HELP_PATH / f"{group_id}.png" else: - help_image = IMAGE_PATH / f"SIMPLE_HELP.png" + help_image = IMAGE_PATH / "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) + async with aiofiles.open(help_image, "wb") as f: + await f.write(byt) + elif build_type == "zhenxun": + byt = await self.build_ss_image(bot_id, group_id) + async with aiofiles.open(help_image, "wb") as f: + await f.write(byt) else: img = await self.build_pil_image(group_id) await img.save(help_image) - async def build_html_image(self, group_id: str | None) -> bytes: - from nonebot_plugin_htmlrender import template_to_pic + async def build_ss_image(self, bot_id: str, group_id: str | None) -> bytes: + """构造ss帮助图片 + 参数: + group_id: 群号 + """ + await self.sort_type() + classify = {} + for menu in self._sort_data: + self._sort_data[menu].sort(key=lambda k: len(k.name)) + for menu in self._sort_data: + for plugin in self._sort_data[menu]: + if not plugin.status: + if group_id and plugin.block_type in [ + BlockType.ALL, + BlockType.GROUP, + ]: + plugin.name = f"{plugin.name}(不可用)" + if not group_id and plugin.block_type in [ + BlockType.ALL, + BlockType.PRIVATE, + ]: + plugin.name = f"{plugin.name}(不可用)" + if not classify.get(menu): + classify[menu] = [] + classify[menu].append( + Item(plugin_name=f"{plugin.id}-{plugin.name}", sta=0) + ) + max_len = 0 + flag_index = -1 + max_data = None + plugin_list = [] + for index, plu in enumerate(classify.keys()): + data = { + "name": "主要功能" if plu in ["normal", "功能"] else plu, + "items": classify[plu], + } + 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) + _data = [] + _left = 30 + for plugin in plugin_list: + _plugins = [] + width = 50 + if len(plugin["items"]) // 2 > 6: + width = 100 + _pu1 = [] + _pu2 = [] + for i in range(len(plugin["items"])): + if i % 2: + _pu1.append(plugin["items"][i]) + else: + _pu2.append(plugin["items"][i]) + _plugins = [(30, 50, _pu1), (0, 50, _pu2)] + else: + _plugins = [(_left, 100, plugin["items"])] + _left = 15 if _left == 30 else 30 + _data.append({"name": plugin["name"], "items": _plugins, "width": width}) + return await template_to_pic( + template_path=str((TEMPLATE_PATH / "ss_menu").absolute()), + template_name="main.html", + templates={"data": {"plugin_list": _data, "ava": AVA_URL.format(bot_id)}}, + pages={ + "viewport": {"width": 637, "height": 975}, + "base_url": f"file://{TEMPLATE_PATH}", + }, + wait=2, + ) + + async def build_html_image(self, group_id: str | None) -> bytes: + """构造HTML帮助图片 + + 参数: + group_id: 群号 + """ await self.sort_type() classify = {} for menu in self._sort_data: @@ -127,7 +211,7 @@ class HelpImageBuild: plugin_list.append(data) del plugin_list[flag_index] plugin_list.insert(0, max_data) - pic = await template_to_pic( + return await template_to_pic( template_path=str((TEMPLATE_PATH / "menu").absolute()), template_name="zhenxun_menu.html", templates={"plugin_list": plugin_list}, @@ -137,10 +221,9 @@ class HelpImageBuild: }, wait=2, ) - return pic async def build_pil_image(self, group_id: str | None) -> BuildImage: - """构造帮助图片 + """构造PIL帮助图片 参数: group_id: 群号 @@ -161,7 +244,7 @@ class HelpImageBuild: sum_height = 50 * len(plugin_list) + 10 else: sum_height = (font_size + 6) * len(plugin_list) + 10 - max_width = max([x[0] for x in wh_list]) + 30 + max_width = max(x[0] for x in wh_list) + 30 bk = BuildImage( max_width + 40, sum_height + 50, @@ -175,7 +258,7 @@ class HelpImageBuild: max_width + 40, sum_height, font_size=font_size, - color="white" if not idx % 2 else "black", + color="black" if idx % 2 else "white", ) curr_h = 10 group = await GroupConsole.get_or_none(group_id=group_id) @@ -199,7 +282,7 @@ class HelpImageBuild: name_image = await self.build_name_image( # type: ignore max_width, plugin.name, - "black" if not idx % 2 else "white", + "white" if idx % 2 else "black", text_color, pos, ) @@ -213,7 +296,6 @@ class HelpImageBuild: 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)