mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-15 14:22:55 +08:00
✨ 新增超级用户与管理员帮助模板
This commit is contained in:
parent
7890cc577f
commit
8aed7f27b9
116
resources/template/help/main.css
Normal file
116
resources/template/help/main.css
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
|
||||||
|
|
||||||
|
@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{
|
||||||
|
width: 1400px;
|
||||||
|
position: relative;
|
||||||
|
background-image: url('res/img/bk.jpg');
|
||||||
|
background-size: cover;
|
||||||
|
font-family: 'cr105Font';
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 60px;
|
||||||
|
font-family: 'fzrzFont';
|
||||||
|
/* margin-left: 40px; */
|
||||||
|
/* color: #F67186; */
|
||||||
|
background: linear-gradient(to right, #F67186, #F7889C);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
background-image: url('res/img/main.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
/* background-size: cover; */
|
||||||
|
height: 100%;
|
||||||
|
width: 1370px;
|
||||||
|
position: relative;
|
||||||
|
padding: 20px;
|
||||||
|
/* box-shadow: 5px 5px 10px 0 rgba(0,0,0,0.5); */
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-border {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding-left: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items {
|
||||||
|
border: #F67186 2px solid;
|
||||||
|
border-radius: 20px;
|
||||||
|
width: 675px;
|
||||||
|
padding: 30px;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
background-image: url('res/img/title.png');
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
height: 55px;
|
||||||
|
width: 350px;
|
||||||
|
font-family: 'fzrzFont';
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: white;
|
||||||
|
font-size: 35px;
|
||||||
|
border-radius: 16px;
|
||||||
|
letter-spacing:4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.usage-title {
|
||||||
|
font-size: 30px;
|
||||||
|
position: absolute;
|
||||||
|
top: -30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-des {
|
||||||
|
color: #F78094;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-family: 'fzrzFont';
|
||||||
|
font-size: 30px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-usage {
|
||||||
|
color: #F78094;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-family: 'fzrzFont';
|
||||||
|
font-size: 20px;
|
||||||
|
border: #F67186 5px dotted;
|
||||||
|
padding: 60px 10px 10px 10px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
62
resources/template/help/main.html
Normal file
62
resources/template/help/main.html
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-cn">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>test</title>
|
||||||
|
<!-- <link rel="stylesheet" href="./res/font-awesome/css/font-awesome.min.css"> -->
|
||||||
|
<link rel="stylesheet" href="main.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="wrapper">
|
||||||
|
<div class="main">
|
||||||
|
<div class="title">
|
||||||
|
{{data.nickname}}的{{data.help_name}}帮助
|
||||||
|
</div>
|
||||||
|
<div class="items-border">
|
||||||
|
{% for plugin in data['plugin_list'] %}
|
||||||
|
<div class="items">
|
||||||
|
<div class="item-title">
|
||||||
|
{{plugin.name}}
|
||||||
|
</div>
|
||||||
|
<div class="item-des">
|
||||||
|
简介: {{plugin.description}}
|
||||||
|
</div>
|
||||||
|
<div class="item-usage">
|
||||||
|
<p class="usage-title">用法:</p>
|
||||||
|
{{plugin.usage}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<!-- <div class="items">
|
||||||
|
<div class="item-title">
|
||||||
|
刷屏禁言
|
||||||
|
</div>
|
||||||
|
<div class="item-des">
|
||||||
|
简介: 刷屏禁言相关操作
|
||||||
|
</div>
|
||||||
|
<div class="item-usage">
|
||||||
|
用法:<br>
|
||||||
|
指令:<br>
|
||||||
|
设置刷屏: 查看当前设置<br>
|
||||||
|
-c [count]: 检测最大次数<br>
|
||||||
|
-t [time]: 规定时间内<br>
|
||||||
|
-d [duration]: 禁言时长<br>
|
||||||
|
示例:<br>
|
||||||
|
设置刷屏 -c 10: 设置最大次数为10<br>
|
||||||
|
设置刷屏 -t 100 -d 20: 设置规定时间和禁言时长<br>
|
||||||
|
设置刷屏 -d 10: 设置禁言时长为10<br>
|
||||||
|
* 即 X 秒内发送同样消息 N 次,禁言 M 分钟 *
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script type="text/javascript" src="main.js">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</html>
|
||||||
0
resources/template/help/main.js
Normal file
0
resources/template/help/main.js
Normal file
BIN
resources/template/help/res/font/fzrzExtraBold.ttf
Normal file
BIN
resources/template/help/res/font/fzrzExtraBold.ttf
Normal file
Binary file not shown.
BIN
resources/template/help/res/font/syht.otf
Normal file
BIN
resources/template/help/res/font/syht.otf
Normal file
Binary file not shown.
BIN
resources/template/help/res/font/syst.otf
Normal file
BIN
resources/template/help/res/font/syst.otf
Normal file
Binary file not shown.
BIN
resources/template/help/res/img/bk.jpg
Normal file
BIN
resources/template/help/res/img/bk.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 706 KiB |
BIN
resources/template/help/res/img/main.png
Normal file
BIN
resources/template/help/res/img/main.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
BIN
resources/template/help/res/img/title.png
Normal file
BIN
resources/template/help/res/img/title.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
@ -1,160 +0,0 @@
|
|||||||
import nonebot
|
|
||||||
from nonebot.plugin import PluginMetadata
|
|
||||||
from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
|
|
||||||
from nonebot_plugin_alconna.matcher import AlconnaMatcher
|
|
||||||
from nonebot_plugin_session import EventSession
|
|
||||||
|
|
||||||
from zhenxun.configs.path_config import IMAGE_PATH
|
|
||||||
from zhenxun.configs.utils import PluginExtraData
|
|
||||||
from zhenxun.models.plugin_info import PluginInfo
|
|
||||||
from zhenxun.models.task_info import TaskInfo
|
|
||||||
from zhenxun.services.log import logger
|
|
||||||
from zhenxun.utils.enum import PluginType
|
|
||||||
from zhenxun.utils.exception import EmptyError
|
|
||||||
from zhenxun.utils.image_utils import (
|
|
||||||
BuildImage,
|
|
||||||
build_sort_image,
|
|
||||||
group_image,
|
|
||||||
text2image,
|
|
||||||
)
|
|
||||||
from zhenxun.utils.message import MessageUtils
|
|
||||||
from zhenxun.utils.rules import admin_check, ensure_group
|
|
||||||
|
|
||||||
__plugin_meta__ = PluginMetadata(
|
|
||||||
name="群组管理员帮助",
|
|
||||||
description="管理员帮助列表",
|
|
||||||
usage="""
|
|
||||||
管理员帮助
|
|
||||||
""".strip(),
|
|
||||||
extra=PluginExtraData(
|
|
||||||
author="HibiKier",
|
|
||||||
version="0.1",
|
|
||||||
plugin_type=PluginType.ADMIN,
|
|
||||||
admin_level=1,
|
|
||||||
).dict(),
|
|
||||||
)
|
|
||||||
|
|
||||||
_matcher = on_alconna(
|
|
||||||
Alconna("管理员帮助"),
|
|
||||||
rule=admin_check(1) & ensure_group,
|
|
||||||
priority=5,
|
|
||||||
block=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
ADMIN_HELP_IMAGE = IMAGE_PATH / "ADMIN_HELP.png"
|
|
||||||
if ADMIN_HELP_IMAGE.exists():
|
|
||||||
ADMIN_HELP_IMAGE.unlink()
|
|
||||||
|
|
||||||
|
|
||||||
async def build_help() -> BuildImage:
|
|
||||||
"""构造管理员帮助图片
|
|
||||||
|
|
||||||
异常:
|
|
||||||
EmptyError: 管理员帮助为空
|
|
||||||
|
|
||||||
返回:
|
|
||||||
BuildImage: 管理员帮助图片
|
|
||||||
"""
|
|
||||||
plugin_list = await PluginInfo.filter(
|
|
||||||
plugin_type__in=[PluginType.ADMIN, PluginType.SUPER_AND_ADMIN]
|
|
||||||
).all()
|
|
||||||
data_list = []
|
|
||||||
for plugin in plugin_list:
|
|
||||||
if _plugin := nonebot.get_plugin_by_module_name(plugin.module_path):
|
|
||||||
if _plugin.metadata:
|
|
||||||
data_list.append({"plugin": plugin, "metadata": _plugin.metadata})
|
|
||||||
font = BuildImage.load_font("HYWenHei-85W.ttf", 20)
|
|
||||||
image_list = []
|
|
||||||
for data in data_list:
|
|
||||||
plugin = data["plugin"]
|
|
||||||
metadata = data["metadata"]
|
|
||||||
try:
|
|
||||||
usage = None
|
|
||||||
description = None
|
|
||||||
if metadata.usage:
|
|
||||||
usage = await text2image(
|
|
||||||
metadata.usage,
|
|
||||||
padding=5,
|
|
||||||
color=(255, 255, 255),
|
|
||||||
font_color=(0, 0, 0),
|
|
||||||
)
|
|
||||||
if metadata.description:
|
|
||||||
description = await text2image(
|
|
||||||
metadata.description,
|
|
||||||
padding=5,
|
|
||||||
color=(255, 255, 255),
|
|
||||||
font_color=(0, 0, 0),
|
|
||||||
)
|
|
||||||
width = 0
|
|
||||||
height = 100
|
|
||||||
if usage:
|
|
||||||
width = usage.width
|
|
||||||
height += usage.height
|
|
||||||
if description and description.width > width:
|
|
||||||
width = description.width
|
|
||||||
height += description.height
|
|
||||||
font_width, font_height = BuildImage.get_text_size(
|
|
||||||
plugin.name + f"[{plugin.level}]", font
|
|
||||||
)
|
|
||||||
if font_width > width:
|
|
||||||
width = font_width
|
|
||||||
A = BuildImage(width + 30, height + 120, "#EAEDF2")
|
|
||||||
await A.text((15, 10), plugin.name + f"[{plugin.level}]")
|
|
||||||
await A.text((15, 70), "简介:")
|
|
||||||
if not description:
|
|
||||||
description = BuildImage(A.width - 30, 30, (255, 255, 255))
|
|
||||||
await description.circle_corner(10)
|
|
||||||
await A.paste(description, (15, 100))
|
|
||||||
if not usage:
|
|
||||||
usage = BuildImage(A.width - 30, 30, (255, 255, 255))
|
|
||||||
await usage.circle_corner(10)
|
|
||||||
await A.text((15, description.height + 115), "用法:")
|
|
||||||
await A.paste(usage, (15, description.height + 145))
|
|
||||||
await A.circle_corner(10)
|
|
||||||
image_list.append(A)
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(
|
|
||||||
f"获取群管理员插件 {plugin.module}: {plugin.name} 设置失败...",
|
|
||||||
"管理员帮助",
|
|
||||||
e=e,
|
|
||||||
)
|
|
||||||
if task_list := await TaskInfo.all():
|
|
||||||
task_str = "\n".join([task.name for task in task_list])
|
|
||||||
task_str = "通过 开启/关闭群被动 来控制群被动\n----------\n" + task_str
|
|
||||||
task_image = await text2image(task_str, padding=5, color=(255, 255, 255))
|
|
||||||
await task_image.circle_corner(10)
|
|
||||||
A = BuildImage(task_image.width + 50, task_image.height + 85, "#EAEDF2")
|
|
||||||
await A.text((25, 10), "被动技能")
|
|
||||||
await A.paste(task_image, (25, 50))
|
|
||||||
await A.circle_corner(10)
|
|
||||||
image_list.append(A)
|
|
||||||
if not image_list:
|
|
||||||
raise EmptyError()
|
|
||||||
image_group, _ = group_image(image_list)
|
|
||||||
A = await build_sort_image(image_group, color=(255, 255, 255), padding_top=160)
|
|
||||||
text = await BuildImage.build_text_image(
|
|
||||||
"群管理员帮助",
|
|
||||||
size=40,
|
|
||||||
)
|
|
||||||
tip = await BuildImage.build_text_image(
|
|
||||||
"注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数", size=25, font_color="red"
|
|
||||||
)
|
|
||||||
await A.paste(text, (50, 30))
|
|
||||||
await A.paste(tip, (50, 90))
|
|
||||||
await A.save(ADMIN_HELP_IMAGE)
|
|
||||||
return BuildImage(1, 1)
|
|
||||||
|
|
||||||
|
|
||||||
@_matcher.handle()
|
|
||||||
async def _(
|
|
||||||
session: EventSession,
|
|
||||||
arparma: Arparma,
|
|
||||||
):
|
|
||||||
if not ADMIN_HELP_IMAGE.exists():
|
|
||||||
try:
|
|
||||||
await build_help()
|
|
||||||
except EmptyError:
|
|
||||||
await MessageUtils.build_message("管理员帮助为空").finish(reply_to=True)
|
|
||||||
await MessageUtils.build_message(ADMIN_HELP_IMAGE).send()
|
|
||||||
logger.info("查看管理员帮助", arparma.header_result, session=session)
|
|
||||||
63
zhenxun/builtin_plugins/admin/admin_help/__init__.py
Normal file
63
zhenxun/builtin_plugins/admin/admin_help/__init__.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
from nonebot.plugin import PluginMetadata
|
||||||
|
from nonebot_plugin_session import EventSession
|
||||||
|
from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
from zhenxun.configs.config import Config
|
||||||
|
from zhenxun.utils.enum import PluginType
|
||||||
|
from zhenxun.utils.exception import EmptyError
|
||||||
|
from zhenxun.utils.message import MessageUtils
|
||||||
|
from zhenxun.utils.rules import admin_check, ensure_group
|
||||||
|
from zhenxun.configs.utils import RegisterConfig, PluginExtraData
|
||||||
|
|
||||||
|
from .normal_help import build_help
|
||||||
|
from .config import ADMIN_HELP_IMAGE
|
||||||
|
from .html_help import build_html_help
|
||||||
|
|
||||||
|
__plugin_meta__ = PluginMetadata(
|
||||||
|
name="群组管理员帮助",
|
||||||
|
description="管理员帮助列表",
|
||||||
|
usage="""
|
||||||
|
管理员帮助
|
||||||
|
""".strip(),
|
||||||
|
extra=PluginExtraData(
|
||||||
|
author="HibiKier",
|
||||||
|
version="0.1",
|
||||||
|
plugin_type=PluginType.ADMIN,
|
||||||
|
admin_level=1,
|
||||||
|
configs=[
|
||||||
|
RegisterConfig(
|
||||||
|
key="type",
|
||||||
|
value="zhenxun",
|
||||||
|
help="管理员帮助样式,normal, zhenxun",
|
||||||
|
default_value="zhenxun",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
).dict(),
|
||||||
|
)
|
||||||
|
|
||||||
|
_matcher = on_alconna(
|
||||||
|
Alconna("管理员帮助"),
|
||||||
|
rule=admin_check(1) & ensure_group,
|
||||||
|
priority=5,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@_matcher.handle()
|
||||||
|
async def _(
|
||||||
|
session: EventSession,
|
||||||
|
arparma: Arparma,
|
||||||
|
):
|
||||||
|
if not ADMIN_HELP_IMAGE.exists():
|
||||||
|
try:
|
||||||
|
if Config.get_config("admin_help", "type") == "zhenxun":
|
||||||
|
await build_html_help()
|
||||||
|
else:
|
||||||
|
await build_help()
|
||||||
|
except EmptyError:
|
||||||
|
await MessageUtils.build_message("当前管理员帮助为空...").finish(
|
||||||
|
reply_to=True
|
||||||
|
)
|
||||||
|
await MessageUtils.build_message(ADMIN_HELP_IMAGE).send()
|
||||||
|
logger.info("查看管理员帮助", arparma.header_result, session=session)
|
||||||
23
zhenxun/builtin_plugins/admin/admin_help/config.py
Normal file
23
zhenxun/builtin_plugins/admin/admin_help/config.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from pydantic import BaseModel
|
||||||
|
from nonebot.plugin import PluginMetadata
|
||||||
|
|
||||||
|
from zhenxun.models.plugin_info import PluginInfo
|
||||||
|
from zhenxun.configs.path_config import IMAGE_PATH
|
||||||
|
|
||||||
|
ADMIN_HELP_IMAGE = IMAGE_PATH / "ADMIN_HELP.png"
|
||||||
|
if ADMIN_HELP_IMAGE.exists():
|
||||||
|
ADMIN_HELP_IMAGE.unlink()
|
||||||
|
|
||||||
|
|
||||||
|
class PluginData(BaseModel):
|
||||||
|
"""
|
||||||
|
插件信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
plugin: PluginInfo
|
||||||
|
"""插件信息"""
|
||||||
|
metadata: PluginMetadata
|
||||||
|
"""元数据"""
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
arbitrary_types_allowed = True
|
||||||
55
zhenxun/builtin_plugins/admin/admin_help/html_help.py
Normal file
55
zhenxun/builtin_plugins/admin/admin_help/html_help.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
from nonebot_plugin_htmlrender import template_to_pic
|
||||||
|
|
||||||
|
from zhenxun.configs.config import BotConfig
|
||||||
|
from zhenxun.models.task_info import TaskInfo
|
||||||
|
from zhenxun.utils._build_image import BuildImage
|
||||||
|
from zhenxun.configs.path_config import TEMPLATE_PATH
|
||||||
|
from zhenxun.builtin_plugins.admin.admin_help.config import ADMIN_HELP_IMAGE
|
||||||
|
|
||||||
|
from .utils import get_plugins
|
||||||
|
|
||||||
|
|
||||||
|
async def get_task() -> dict[str, str] | None:
|
||||||
|
"""获取被动技能帮助"""
|
||||||
|
if task_list := await TaskInfo.all():
|
||||||
|
return {
|
||||||
|
"name": "被动技能",
|
||||||
|
"description": "控制群组中的被动技能状态",
|
||||||
|
"usage": "通过 开启/关闭群被动 来控制群被<br>----------<br>"
|
||||||
|
+ "<br>".join([task.name for task in task_list]),
|
||||||
|
}
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
async def build_html_help():
|
||||||
|
"""构建帮助图片"""
|
||||||
|
plugins = await get_plugins()
|
||||||
|
plugin_list = [
|
||||||
|
{
|
||||||
|
"name": data.plugin.name,
|
||||||
|
"description": data.metadata.description.replace("\n", "<br>"),
|
||||||
|
"usage": data.metadata.usage.replace("\n", "<br>"),
|
||||||
|
}
|
||||||
|
for data in plugins
|
||||||
|
]
|
||||||
|
if task := await get_task():
|
||||||
|
plugin_list.append(task)
|
||||||
|
plugin_list.sort(key=lambda p: len(p["description"]) + len(p["usage"]))
|
||||||
|
pic = await template_to_pic(
|
||||||
|
template_path=str((TEMPLATE_PATH / "help").absolute()),
|
||||||
|
template_name="main.html",
|
||||||
|
templates={
|
||||||
|
"data": {
|
||||||
|
"plugin_list": plugin_list,
|
||||||
|
"nickname": BotConfig.self_nickname,
|
||||||
|
"help_name": "群管理员",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pages={
|
||||||
|
"viewport": {"width": 1024, "height": 1024},
|
||||||
|
"base_url": f"file://{TEMPLATE_PATH}",
|
||||||
|
},
|
||||||
|
wait=2,
|
||||||
|
)
|
||||||
|
result = await BuildImage.open(pic).resize(0.5)
|
||||||
|
await result.save(ADMIN_HELP_IMAGE)
|
||||||
127
zhenxun/builtin_plugins/admin/admin_help/normal_help.py
Normal file
127
zhenxun/builtin_plugins/admin/admin_help/normal_help.py
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
from PIL.ImageFont import FreeTypeFont
|
||||||
|
from nonebot.plugin import PluginMetadata
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
from zhenxun.models.task_info import TaskInfo
|
||||||
|
from zhenxun.models.plugin_info import PluginInfo
|
||||||
|
from zhenxun.utils._build_image import BuildImage
|
||||||
|
from zhenxun.utils.image_utils import text2image, group_image, build_sort_image
|
||||||
|
|
||||||
|
from .utils import get_plugins
|
||||||
|
from .config import ADMIN_HELP_IMAGE
|
||||||
|
|
||||||
|
|
||||||
|
async def build_usage_des_image(
|
||||||
|
metadata: PluginMetadata,
|
||||||
|
) -> tuple[BuildImage | None, BuildImage | None]:
|
||||||
|
"""构建用法和描述图片
|
||||||
|
|
||||||
|
参数:
|
||||||
|
metadata: PluginMetadata
|
||||||
|
|
||||||
|
返回:
|
||||||
|
tuple[BuildImage | None, BuildImage | None]: 用法和描述图片
|
||||||
|
"""
|
||||||
|
usage = None
|
||||||
|
description = None
|
||||||
|
if metadata.usage:
|
||||||
|
usage = await text2image(
|
||||||
|
metadata.usage,
|
||||||
|
padding=5,
|
||||||
|
color=(255, 255, 255),
|
||||||
|
font_color=(0, 0, 0),
|
||||||
|
)
|
||||||
|
if metadata.description:
|
||||||
|
description = await text2image(
|
||||||
|
metadata.description,
|
||||||
|
padding=5,
|
||||||
|
color=(255, 255, 255),
|
||||||
|
font_color=(0, 0, 0),
|
||||||
|
)
|
||||||
|
return usage, description
|
||||||
|
|
||||||
|
|
||||||
|
async def build_image(
|
||||||
|
plugin: PluginInfo, metadata: PluginMetadata, font: FreeTypeFont
|
||||||
|
) -> BuildImage:
|
||||||
|
"""构建帮助图片
|
||||||
|
|
||||||
|
参数:
|
||||||
|
plugin: PluginInfo
|
||||||
|
metadata: PluginMetadata
|
||||||
|
font: FreeTypeFont
|
||||||
|
|
||||||
|
返回:
|
||||||
|
BuildImage: 帮助图片
|
||||||
|
|
||||||
|
"""
|
||||||
|
usage, description = await build_usage_des_image(metadata)
|
||||||
|
width = 0
|
||||||
|
height = 100
|
||||||
|
if usage:
|
||||||
|
width = usage.width
|
||||||
|
height += usage.height
|
||||||
|
if description and description.width > width:
|
||||||
|
width = description.width
|
||||||
|
height += description.height
|
||||||
|
font_width, _ = BuildImage.get_text_size(f"{plugin.name}[{plugin.level}]", font)
|
||||||
|
if font_width > width:
|
||||||
|
width = font_width
|
||||||
|
A = BuildImage(width + 30, height + 120, "#EAEDF2")
|
||||||
|
await A.text((15, 10), f"{plugin.name}[{plugin.level}]")
|
||||||
|
await A.text((15, 70), "简介:")
|
||||||
|
if not description:
|
||||||
|
description = BuildImage(A.width - 30, 30, (255, 255, 255))
|
||||||
|
await description.circle_corner(10)
|
||||||
|
await A.paste(description, (15, 100))
|
||||||
|
if not usage:
|
||||||
|
usage = BuildImage(A.width - 30, 30, (255, 255, 255))
|
||||||
|
await usage.circle_corner(10)
|
||||||
|
await A.text((15, description.height + 115), "用法:")
|
||||||
|
await A.paste(usage, (15, description.height + 145))
|
||||||
|
await A.circle_corner(10)
|
||||||
|
return A
|
||||||
|
|
||||||
|
|
||||||
|
async def build_help():
|
||||||
|
"""构造管理员帮助图片
|
||||||
|
|
||||||
|
返回:
|
||||||
|
BuildImage: 管理员帮助图片
|
||||||
|
"""
|
||||||
|
font = BuildImage.load_font("HYWenHei-85W.ttf", 20)
|
||||||
|
image_list = []
|
||||||
|
for data in await get_plugins():
|
||||||
|
plugin = data.plugin
|
||||||
|
metadata = data.metadata
|
||||||
|
try:
|
||||||
|
A = await build_image(plugin, metadata, font)
|
||||||
|
image_list.append(A)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(
|
||||||
|
f"获取群管理员插件 {plugin.module}: {plugin.name} 设置失败...",
|
||||||
|
"管理员帮助",
|
||||||
|
e=e,
|
||||||
|
)
|
||||||
|
if task_list := await TaskInfo.all():
|
||||||
|
task_str = "\n".join([task.name for task in task_list])
|
||||||
|
task_str = "通过 开启/关闭群被动 来控制群被动\n----------\n" + task_str
|
||||||
|
task_image = await text2image(task_str, padding=5, color=(255, 255, 255))
|
||||||
|
await task_image.circle_corner(10)
|
||||||
|
A = BuildImage(task_image.width + 50, task_image.height + 85, "#EAEDF2")
|
||||||
|
await A.text((25, 10), "被动技能")
|
||||||
|
await A.paste(task_image, (25, 50))
|
||||||
|
await A.circle_corner(10)
|
||||||
|
image_list.append(A)
|
||||||
|
image_group, _ = group_image(image_list)
|
||||||
|
A = await build_sort_image(image_group, color=(255, 255, 255), padding_top=160)
|
||||||
|
text = await BuildImage.build_text_image(
|
||||||
|
"群管理员帮助",
|
||||||
|
size=40,
|
||||||
|
)
|
||||||
|
tip = await BuildImage.build_text_image(
|
||||||
|
"注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数", size=25, font_color="red"
|
||||||
|
)
|
||||||
|
await A.paste(text, (50, 30))
|
||||||
|
await A.paste(tip, (50, 90))
|
||||||
|
await A.save(ADMIN_HELP_IMAGE)
|
||||||
22
zhenxun/builtin_plugins/admin/admin_help/utils.py
Normal file
22
zhenxun/builtin_plugins/admin/admin_help/utils.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import nonebot
|
||||||
|
|
||||||
|
from zhenxun.utils.enum import PluginType
|
||||||
|
from zhenxun.utils.exception import EmptyError
|
||||||
|
from zhenxun.models.plugin_info import PluginInfo
|
||||||
|
|
||||||
|
from .config import PluginData
|
||||||
|
|
||||||
|
|
||||||
|
async def get_plugins() -> list[PluginData]:
|
||||||
|
"""获取插件数据"""
|
||||||
|
plugin_list = await PluginInfo.filter(
|
||||||
|
plugin_type__in=[PluginType.ADMIN, PluginType.SUPER_AND_ADMIN]
|
||||||
|
).all()
|
||||||
|
data_list = []
|
||||||
|
for plugin in plugin_list:
|
||||||
|
if _plugin := nonebot.get_plugin_by_module_name(plugin.module_path):
|
||||||
|
if _plugin.metadata:
|
||||||
|
data_list.append(PluginData(plugin=plugin, metadata=_plugin.metadata))
|
||||||
|
if not data_list:
|
||||||
|
raise EmptyError()
|
||||||
|
return data_list
|
||||||
0
zhenxun/builtin_plugins/help/detail_help.py
Normal file
0
zhenxun/builtin_plugins/help/detail_help.py
Normal file
@ -1,158 +0,0 @@
|
|||||||
import nonebot
|
|
||||||
from nonebot.permission import SUPERUSER
|
|
||||||
from nonebot.plugin import PluginMetadata
|
|
||||||
from nonebot_plugin_session import EventSession
|
|
||||||
from nonebot_plugin_alconna.matcher import AlconnaMatcher
|
|
||||||
from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
|
||||||
from zhenxun.utils.enum import PluginType
|
|
||||||
from zhenxun.models.task_info import TaskInfo
|
|
||||||
from zhenxun.utils.exception import EmptyError
|
|
||||||
from zhenxun.utils.message import MessageUtils
|
|
||||||
from zhenxun.configs.utils import PluginExtraData
|
|
||||||
from zhenxun.models.plugin_info import PluginInfo
|
|
||||||
from zhenxun.configs.path_config import IMAGE_PATH
|
|
||||||
from zhenxun.utils.image_utils import (
|
|
||||||
BuildImage,
|
|
||||||
text2image,
|
|
||||||
group_image,
|
|
||||||
build_sort_image,
|
|
||||||
)
|
|
||||||
|
|
||||||
__plugin_meta__ = PluginMetadata(
|
|
||||||
name="超级用户帮助",
|
|
||||||
description="超级用户帮助",
|
|
||||||
usage="""
|
|
||||||
超级用户帮助
|
|
||||||
""".strip(),
|
|
||||||
extra=PluginExtraData(
|
|
||||||
author="HibiKier",
|
|
||||||
version="0.1",
|
|
||||||
plugin_type=PluginType.SUPERUSER,
|
|
||||||
).dict(),
|
|
||||||
)
|
|
||||||
|
|
||||||
_matcher = on_alconna(
|
|
||||||
Alconna("超级用户帮助"),
|
|
||||||
permission=SUPERUSER,
|
|
||||||
priority=5,
|
|
||||||
block=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
SUPERUSER_HELP_IMAGE = IMAGE_PATH / "SUPERUSER_HELP.png"
|
|
||||||
if SUPERUSER_HELP_IMAGE.exists():
|
|
||||||
SUPERUSER_HELP_IMAGE.unlink()
|
|
||||||
|
|
||||||
|
|
||||||
async def build_help() -> BuildImage:
|
|
||||||
"""构造超级用户帮助图片
|
|
||||||
|
|
||||||
异常:
|
|
||||||
EmptyError: 超级用户帮助为空
|
|
||||||
|
|
||||||
返回:
|
|
||||||
BuildImage: 超级用户帮助图片
|
|
||||||
"""
|
|
||||||
plugin_list = await PluginInfo.filter(plugin_type=PluginType.SUPERUSER).all()
|
|
||||||
data_list = []
|
|
||||||
for plugin in plugin_list:
|
|
||||||
if _plugin := nonebot.get_plugin_by_module_name(plugin.module_path):
|
|
||||||
if _plugin.metadata:
|
|
||||||
data_list.append({"plugin": plugin, "metadata": _plugin.metadata})
|
|
||||||
font = BuildImage.load_font("HYWenHei-85W.ttf", 20)
|
|
||||||
image_list = []
|
|
||||||
for data in data_list:
|
|
||||||
plugin = data["plugin"]
|
|
||||||
metadata = data["metadata"]
|
|
||||||
try:
|
|
||||||
usage = None
|
|
||||||
description = None
|
|
||||||
if metadata.usage:
|
|
||||||
usage = await text2image(
|
|
||||||
metadata.usage,
|
|
||||||
padding=5,
|
|
||||||
color=(255, 255, 255),
|
|
||||||
font_color=(0, 0, 0),
|
|
||||||
)
|
|
||||||
if metadata.description:
|
|
||||||
description = await text2image(
|
|
||||||
metadata.description,
|
|
||||||
padding=5,
|
|
||||||
color=(255, 255, 255),
|
|
||||||
font_color=(0, 0, 0),
|
|
||||||
)
|
|
||||||
width = 0
|
|
||||||
height = 100
|
|
||||||
if usage:
|
|
||||||
width = usage.width
|
|
||||||
height += usage.height
|
|
||||||
if description and description.width > width:
|
|
||||||
width = description.width
|
|
||||||
height += description.height
|
|
||||||
font_width, font_height = BuildImage.get_text_size(
|
|
||||||
plugin.name + f"[{plugin.level}]", font
|
|
||||||
)
|
|
||||||
if font_width > width:
|
|
||||||
width = font_width
|
|
||||||
A = BuildImage(width + 30, height + 120, "#EAEDF2")
|
|
||||||
await A.text((15, 10), plugin.name + f"[{plugin.level}]")
|
|
||||||
await A.text((15, 70), "简介:")
|
|
||||||
if not description:
|
|
||||||
description = BuildImage(A.width - 30, 30, (255, 255, 255))
|
|
||||||
await description.circle_corner(10)
|
|
||||||
await A.paste(description, (15, 100))
|
|
||||||
if not usage:
|
|
||||||
usage = BuildImage(A.width - 30, 30, (255, 255, 255))
|
|
||||||
await usage.circle_corner(10)
|
|
||||||
await A.text((15, description.height + 115), "用法:")
|
|
||||||
await A.paste(usage, (15, description.height + 145))
|
|
||||||
await A.circle_corner(10)
|
|
||||||
image_list.append(A)
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(
|
|
||||||
f"获取超级用户管理员插件 {plugin.module}: {plugin.name} 设置失败...",
|
|
||||||
"超级用户帮助",
|
|
||||||
e=e,
|
|
||||||
)
|
|
||||||
if task_list := await TaskInfo.all():
|
|
||||||
task_str = "\n".join([task.name for task in task_list])
|
|
||||||
task_str = "通过 开启/关闭群被动 来控制群被动\n----------\n" + task_str
|
|
||||||
task_image = await text2image(task_str, padding=5, color=(255, 255, 255))
|
|
||||||
await task_image.circle_corner(10)
|
|
||||||
A = BuildImage(task_image.width + 50, task_image.height + 85, "#EAEDF2")
|
|
||||||
await A.text((25, 10), "被动技能")
|
|
||||||
await A.paste(task_image, (25, 50))
|
|
||||||
await A.circle_corner(10)
|
|
||||||
image_list.append(A)
|
|
||||||
if not image_list:
|
|
||||||
raise EmptyError()
|
|
||||||
image_group, _ = group_image(image_list)
|
|
||||||
A = await build_sort_image(image_group, color=(255, 255, 255), padding_top=160)
|
|
||||||
text = await BuildImage.build_text_image(
|
|
||||||
"超级用户帮助",
|
|
||||||
size=40,
|
|
||||||
)
|
|
||||||
tip = await BuildImage.build_text_image(
|
|
||||||
"注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数", size=25, font_color="red"
|
|
||||||
)
|
|
||||||
await A.paste(text, (50, 30))
|
|
||||||
await A.paste(tip, (50, 90))
|
|
||||||
await A.save(SUPERUSER_HELP_IMAGE)
|
|
||||||
return BuildImage(1, 1)
|
|
||||||
|
|
||||||
|
|
||||||
@_matcher.handle()
|
|
||||||
async def _(
|
|
||||||
session: EventSession,
|
|
||||||
matcher: AlconnaMatcher,
|
|
||||||
arparma: Arparma,
|
|
||||||
):
|
|
||||||
if not SUPERUSER_HELP_IMAGE.exists():
|
|
||||||
try:
|
|
||||||
await build_help()
|
|
||||||
except EmptyError:
|
|
||||||
await MessageUtils.build_message("超级用户帮助为空").finish(reply_to=True)
|
|
||||||
await MessageUtils.build_message(SUPERUSER_HELP_IMAGE).send()
|
|
||||||
logger.info("查看超级用户帮助", arparma.header_result, session=session)
|
|
||||||
59
zhenxun/builtin_plugins/superuser/super_help/__init__.py
Normal file
59
zhenxun/builtin_plugins/superuser/super_help/__init__.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
from nonebot.permission import SUPERUSER
|
||||||
|
from nonebot.plugin import PluginMetadata
|
||||||
|
from nonebot_plugin_session import EventSession
|
||||||
|
from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
from zhenxun.configs.config import Config
|
||||||
|
from zhenxun.utils.enum import PluginType
|
||||||
|
from zhenxun.utils.exception import EmptyError
|
||||||
|
from zhenxun.utils.message import MessageUtils
|
||||||
|
from zhenxun.configs.utils import RegisterConfig, PluginExtraData
|
||||||
|
|
||||||
|
from .normal_help import build_help
|
||||||
|
from .config import SUPERUSER_HELP_IMAGE
|
||||||
|
from .zhenxun_help import build_html_help
|
||||||
|
|
||||||
|
__plugin_meta__ = PluginMetadata(
|
||||||
|
name="超级用户帮助",
|
||||||
|
description="超级用户帮助",
|
||||||
|
usage="""
|
||||||
|
超级用户帮助
|
||||||
|
""".strip(),
|
||||||
|
extra=PluginExtraData(
|
||||||
|
author="HibiKier",
|
||||||
|
version="0.1",
|
||||||
|
plugin_type=PluginType.SUPERUSER,
|
||||||
|
configs=[
|
||||||
|
RegisterConfig(
|
||||||
|
key="type",
|
||||||
|
value="zhenxun",
|
||||||
|
help="超级用户帮助样式,normal, zhenxun",
|
||||||
|
default_value="zhenxun",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
).dict(),
|
||||||
|
)
|
||||||
|
|
||||||
|
_matcher = on_alconna(
|
||||||
|
Alconna("超级用户帮助"),
|
||||||
|
permission=SUPERUSER,
|
||||||
|
priority=5,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@_matcher.handle()
|
||||||
|
async def _(session: EventSession, arparma: Arparma):
|
||||||
|
if not SUPERUSER_HELP_IMAGE.exists():
|
||||||
|
try:
|
||||||
|
if Config.get_config("admin_help", "type") == "zhenxun":
|
||||||
|
await build_html_help()
|
||||||
|
else:
|
||||||
|
await build_help()
|
||||||
|
except EmptyError:
|
||||||
|
await MessageUtils.build_message("当前超级用户帮助为空...").finish(
|
||||||
|
reply_to=True
|
||||||
|
)
|
||||||
|
await MessageUtils.build_message(SUPERUSER_HELP_IMAGE).send()
|
||||||
|
logger.info("查看超级用户帮助", arparma.header_result, session=session)
|
||||||
23
zhenxun/builtin_plugins/superuser/super_help/config.py
Normal file
23
zhenxun/builtin_plugins/superuser/super_help/config.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from pydantic import BaseModel
|
||||||
|
from nonebot.plugin import PluginMetadata
|
||||||
|
|
||||||
|
from zhenxun.models.plugin_info import PluginInfo
|
||||||
|
from zhenxun.configs.path_config import IMAGE_PATH
|
||||||
|
|
||||||
|
SUPERUSER_HELP_IMAGE = IMAGE_PATH / "SUPERUSER_HELP.png"
|
||||||
|
if SUPERUSER_HELP_IMAGE.exists():
|
||||||
|
SUPERUSER_HELP_IMAGE.unlink()
|
||||||
|
|
||||||
|
|
||||||
|
class PluginData(BaseModel):
|
||||||
|
"""
|
||||||
|
插件信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
plugin: PluginInfo
|
||||||
|
"""插件信息"""
|
||||||
|
metadata: PluginMetadata
|
||||||
|
"""元数据"""
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
arbitrary_types_allowed = True
|
||||||
127
zhenxun/builtin_plugins/superuser/super_help/normal_help.py
Normal file
127
zhenxun/builtin_plugins/superuser/super_help/normal_help.py
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
from PIL.ImageFont import FreeTypeFont
|
||||||
|
from nonebot.plugin import PluginMetadata
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
from zhenxun.models.task_info import TaskInfo
|
||||||
|
from zhenxun.models.plugin_info import PluginInfo
|
||||||
|
from zhenxun.utils._build_image import BuildImage
|
||||||
|
from zhenxun.utils.image_utils import text2image, group_image, build_sort_image
|
||||||
|
|
||||||
|
from .utils import get_plugins
|
||||||
|
from .config import SUPERUSER_HELP_IMAGE
|
||||||
|
|
||||||
|
|
||||||
|
async def build_usage_des_image(
|
||||||
|
metadata: PluginMetadata,
|
||||||
|
) -> tuple[BuildImage | None, BuildImage | None]:
|
||||||
|
"""构建用法和描述图片
|
||||||
|
|
||||||
|
参数:
|
||||||
|
metadata: PluginMetadata
|
||||||
|
|
||||||
|
返回:
|
||||||
|
tuple[BuildImage | None, BuildImage | None]: 用法和描述图片
|
||||||
|
"""
|
||||||
|
usage = None
|
||||||
|
description = None
|
||||||
|
if metadata.usage:
|
||||||
|
usage = await text2image(
|
||||||
|
metadata.usage,
|
||||||
|
padding=5,
|
||||||
|
color=(255, 255, 255),
|
||||||
|
font_color=(0, 0, 0),
|
||||||
|
)
|
||||||
|
if metadata.description:
|
||||||
|
description = await text2image(
|
||||||
|
metadata.description,
|
||||||
|
padding=5,
|
||||||
|
color=(255, 255, 255),
|
||||||
|
font_color=(0, 0, 0),
|
||||||
|
)
|
||||||
|
return usage, description
|
||||||
|
|
||||||
|
|
||||||
|
async def build_image(
|
||||||
|
plugin: PluginInfo, metadata: PluginMetadata, font: FreeTypeFont
|
||||||
|
) -> BuildImage:
|
||||||
|
"""构建帮助图片
|
||||||
|
|
||||||
|
参数:
|
||||||
|
plugin: PluginInfo
|
||||||
|
metadata: PluginMetadata
|
||||||
|
font: FreeTypeFont
|
||||||
|
|
||||||
|
返回:
|
||||||
|
BuildImage: 帮助图片
|
||||||
|
|
||||||
|
"""
|
||||||
|
usage, description = await build_usage_des_image(metadata)
|
||||||
|
width = 0
|
||||||
|
height = 100
|
||||||
|
if usage:
|
||||||
|
width = usage.width
|
||||||
|
height += usage.height
|
||||||
|
if description and description.width > width:
|
||||||
|
width = description.width
|
||||||
|
height += description.height
|
||||||
|
font_width, _ = BuildImage.get_text_size(f"{plugin.name}[{plugin.level}]", font)
|
||||||
|
if font_width > width:
|
||||||
|
width = font_width
|
||||||
|
A = BuildImage(width + 30, height + 120, "#EAEDF2")
|
||||||
|
await A.text((15, 10), f"{plugin.name}[{plugin.level}]")
|
||||||
|
await A.text((15, 70), "简介:")
|
||||||
|
if not description:
|
||||||
|
description = BuildImage(A.width - 30, 30, (255, 255, 255))
|
||||||
|
await description.circle_corner(10)
|
||||||
|
await A.paste(description, (15, 100))
|
||||||
|
if not usage:
|
||||||
|
usage = BuildImage(A.width - 30, 30, (255, 255, 255))
|
||||||
|
await usage.circle_corner(10)
|
||||||
|
await A.text((15, description.height + 115), "用法:")
|
||||||
|
await A.paste(usage, (15, description.height + 145))
|
||||||
|
await A.circle_corner(10)
|
||||||
|
return A
|
||||||
|
|
||||||
|
|
||||||
|
async def build_help():
|
||||||
|
"""构造超级用户帮助图片
|
||||||
|
|
||||||
|
返回:
|
||||||
|
BuildImage: 超级用户帮助图片
|
||||||
|
"""
|
||||||
|
font = BuildImage.load_font("HYWenHei-85W.ttf", 20)
|
||||||
|
image_list = []
|
||||||
|
for data in await get_plugins():
|
||||||
|
plugin = data.plugin
|
||||||
|
metadata = data.metadata
|
||||||
|
try:
|
||||||
|
A = await build_image(plugin, metadata, font)
|
||||||
|
image_list.append(A)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(
|
||||||
|
f"获取群超级用户插件 {plugin.module}: {plugin.name} 设置失败...",
|
||||||
|
"超级用户帮助",
|
||||||
|
e=e,
|
||||||
|
)
|
||||||
|
if task_list := await TaskInfo.all():
|
||||||
|
task_str = "\n".join([task.name for task in task_list])
|
||||||
|
task_str = "通过 开启/关闭群被动 来控制群被动\n----------\n" + task_str
|
||||||
|
task_image = await text2image(task_str, padding=5, color=(255, 255, 255))
|
||||||
|
await task_image.circle_corner(10)
|
||||||
|
A = BuildImage(task_image.width + 50, task_image.height + 85, "#EAEDF2")
|
||||||
|
await A.text((25, 10), "被动技能")
|
||||||
|
await A.paste(task_image, (25, 50))
|
||||||
|
await A.circle_corner(10)
|
||||||
|
image_list.append(A)
|
||||||
|
image_group, _ = group_image(image_list)
|
||||||
|
A = await build_sort_image(image_group, color=(255, 255, 255), padding_top=160)
|
||||||
|
text = await BuildImage.build_text_image(
|
||||||
|
"群超级用户帮助",
|
||||||
|
size=40,
|
||||||
|
)
|
||||||
|
tip = await BuildImage.build_text_image(
|
||||||
|
"注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数", size=25, font_color="red"
|
||||||
|
)
|
||||||
|
await A.paste(text, (50, 30))
|
||||||
|
await A.paste(tip, (50, 90))
|
||||||
|
await A.save(SUPERUSER_HELP_IMAGE)
|
||||||
22
zhenxun/builtin_plugins/superuser/super_help/utils.py
Normal file
22
zhenxun/builtin_plugins/superuser/super_help/utils.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import nonebot
|
||||||
|
|
||||||
|
from zhenxun.utils.enum import PluginType
|
||||||
|
from zhenxun.utils.exception import EmptyError
|
||||||
|
from zhenxun.models.plugin_info import PluginInfo
|
||||||
|
|
||||||
|
from .config import PluginData
|
||||||
|
|
||||||
|
|
||||||
|
async def get_plugins() -> list[PluginData]:
|
||||||
|
"""获取插件数据"""
|
||||||
|
plugin_list = await PluginInfo.filter(
|
||||||
|
plugin_type__in=[PluginType.SUPERUSER, PluginType.SUPER_AND_ADMIN]
|
||||||
|
).all()
|
||||||
|
data_list = []
|
||||||
|
for plugin in plugin_list:
|
||||||
|
if _plugin := nonebot.get_plugin_by_module_name(plugin.module_path):
|
||||||
|
if _plugin.metadata:
|
||||||
|
data_list.append(PluginData(plugin=plugin, metadata=_plugin.metadata))
|
||||||
|
if not data_list:
|
||||||
|
raise EmptyError()
|
||||||
|
return data_list
|
||||||
59
zhenxun/builtin_plugins/superuser/super_help/zhenxun_help.py
Normal file
59
zhenxun/builtin_plugins/superuser/super_help/zhenxun_help.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
from nonebot_plugin_htmlrender import template_to_pic
|
||||||
|
|
||||||
|
from zhenxun.configs.config import BotConfig
|
||||||
|
from zhenxun.models.task_info import TaskInfo
|
||||||
|
from zhenxun.utils._build_image import BuildImage
|
||||||
|
from zhenxun.configs.path_config import TEMPLATE_PATH
|
||||||
|
|
||||||
|
from .utils import get_plugins
|
||||||
|
from .config import SUPERUSER_HELP_IMAGE
|
||||||
|
|
||||||
|
|
||||||
|
async def get_task() -> dict[str, str] | None:
|
||||||
|
"""获取被动技能帮助"""
|
||||||
|
if task_list := await TaskInfo.all():
|
||||||
|
return {
|
||||||
|
"name": "被动技能",
|
||||||
|
"description": "控制群组中的被动技能状态",
|
||||||
|
"usage": "通过 开启/关闭群被动 来控制群被动 <br> ---------- <br> "
|
||||||
|
+ "<br>".join([task.name for task in task_list]),
|
||||||
|
}
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
async def build_html_help():
|
||||||
|
"""构建帮助图片"""
|
||||||
|
plugins = await get_plugins()
|
||||||
|
plugin_list = []
|
||||||
|
for data in plugins:
|
||||||
|
if data.metadata.extra:
|
||||||
|
if superuser_help := data.metadata.extra.get("superuser_help"):
|
||||||
|
data.metadata.usage += f"<br>以下为超级用户额外命令<br>{superuser_help}"
|
||||||
|
plugin_list.append(
|
||||||
|
{
|
||||||
|
"name": data.plugin.name,
|
||||||
|
"description": data.metadata.description.replace("\n", "<br>"),
|
||||||
|
"usage": data.metadata.usage.replace("\n", "<br>"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if task := await get_task():
|
||||||
|
plugin_list.append(task)
|
||||||
|
plugin_list.sort(key=lambda p: len(p["description"]) + len(p["usage"]))
|
||||||
|
pic = await template_to_pic(
|
||||||
|
template_path=str((TEMPLATE_PATH / "help").absolute()),
|
||||||
|
template_name="main.html",
|
||||||
|
templates={
|
||||||
|
"data": {
|
||||||
|
"plugin_list": plugin_list,
|
||||||
|
"nickname": BotConfig.self_nickname,
|
||||||
|
"help_name": "超级用户",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pages={
|
||||||
|
"viewport": {"width": 1024, "height": 1024},
|
||||||
|
"base_url": f"file://{TEMPLATE_PATH}",
|
||||||
|
},
|
||||||
|
wait=2,
|
||||||
|
)
|
||||||
|
result = await BuildImage.open(pic).resize(0.5)
|
||||||
|
await result.save(SUPERUSER_HELP_IMAGE)
|
||||||
@ -17,6 +17,32 @@ _yaml.indent = 2
|
|||||||
_yaml.allow_unicode = True
|
_yaml.allow_unicode = True
|
||||||
|
|
||||||
|
|
||||||
|
class Example(BaseModel):
|
||||||
|
"""
|
||||||
|
示例
|
||||||
|
"""
|
||||||
|
|
||||||
|
exec: str
|
||||||
|
"""执行命令"""
|
||||||
|
description: str = ""
|
||||||
|
"""命令描述"""
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseModel):
|
||||||
|
"""
|
||||||
|
具体参数说明
|
||||||
|
"""
|
||||||
|
|
||||||
|
command: str
|
||||||
|
"""命令"""
|
||||||
|
params: list[str] = []
|
||||||
|
"""参数"""
|
||||||
|
description: str = ""
|
||||||
|
"""描述"""
|
||||||
|
examples: list[Example] = []
|
||||||
|
"""示例列表"""
|
||||||
|
|
||||||
|
|
||||||
class RegisterConfig(BaseModel):
|
class RegisterConfig(BaseModel):
|
||||||
"""
|
"""
|
||||||
注册配置项
|
注册配置项
|
||||||
@ -167,6 +193,8 @@ class PluginExtraData(BaseModel):
|
|||||||
"""插件基本配置"""
|
"""插件基本配置"""
|
||||||
limits: list[BaseBlock | PluginCdBlock | PluginCountBlock] | None = None
|
limits: list[BaseBlock | PluginCdBlock | PluginCountBlock] | None = None
|
||||||
"""插件限制"""
|
"""插件限制"""
|
||||||
|
commands: list[Command] = []
|
||||||
|
"""命令列表,用于说明帮助"""
|
||||||
tasks: list[Task] | None = None
|
tasks: list[Task] | None = None
|
||||||
"""技能被动"""
|
"""技能被动"""
|
||||||
superuser_help: str | None = None
|
superuser_help: str | None = None
|
||||||
|
|||||||
@ -9,8 +9,6 @@ from zhenxun.services.log import logger
|
|||||||
|
|
||||||
driver = nonebot.get_driver()
|
driver = nonebot.get_driver()
|
||||||
|
|
||||||
PLUGINS_METHOD = []
|
|
||||||
|
|
||||||
|
|
||||||
class PluginInit(ABC):
|
class PluginInit(ABC):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -1,23 +1,22 @@
|
|||||||
import os
|
import os
|
||||||
import random
|
|
||||||
import re
|
import re
|
||||||
|
import random
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Awaitable, Callable
|
from collections.abc import Callable, Awaitable
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import imagehash
|
import imagehash
|
||||||
from imagehash import ImageHash
|
|
||||||
from nonebot.utils import is_coroutine_callable
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
from nonebot.utils import is_coroutine_callable
|
||||||
|
|
||||||
from zhenxun.configs.path_config import IMAGE_PATH, TEMP_PATH
|
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
from zhenxun.utils.http_utils import AsyncHttpx
|
from zhenxun.utils.http_utils import AsyncHttpx
|
||||||
|
from zhenxun.configs.path_config import TEMP_PATH, IMAGE_PATH
|
||||||
|
|
||||||
from ._build_image import BuildImage, ColorAlias
|
from ._build_image import BuildImage, ColorAlias
|
||||||
from ._build_mat import BuildMat, MatType
|
from ._build_mat import MatType, BuildMat # noqa: F401
|
||||||
from ._image_template import ImageTemplate, RowStyle
|
from ._image_template import RowStyle, ImageTemplate # noqa: F401
|
||||||
|
|
||||||
# TODO: text2image 长度错误
|
# TODO: text2image 长度错误
|
||||||
|
|
||||||
@ -192,8 +191,9 @@ async def text2image(
|
|||||||
s.strip(), font, font_size, font_color
|
s.strip(), font, font_size, font_color
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
height = sum(img.height + 8 for img in image_list) + pw
|
||||||
width += pw
|
width += pw
|
||||||
height += ph
|
# height += ph
|
||||||
A = BuildImage(
|
A = BuildImage(
|
||||||
width + left_padding,
|
width + left_padding,
|
||||||
height + top_padding + 2,
|
height + top_padding + 2,
|
||||||
@ -386,7 +386,7 @@ def get_img_hash(image_file: str | Path) -> str:
|
|||||||
with open(image_file, "rb") as fp:
|
with open(image_file, "rb") as fp:
|
||||||
hash_value = imagehash.average_hash(Image.open(fp))
|
hash_value = imagehash.average_hash(Image.open(fp))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"获取图片Hash出错", "禁言检测", e=e)
|
logger.warning("获取图片Hash出错", "禁言检测", e=e)
|
||||||
return str(hash_value)
|
return str(hash_value)
|
||||||
|
|
||||||
|
|
||||||
@ -407,7 +407,7 @@ async def get_download_image_hash(url: str, mark: str) -> str:
|
|||||||
img_hash = get_img_hash(TEMP_PATH / f"compare_download_{mark}_img.jpg")
|
img_hash = get_img_hash(TEMP_PATH / f"compare_download_{mark}_img.jpg")
|
||||||
return str(img_hash)
|
return str(img_hash)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"下载读取图片Hash出错", e=e)
|
logger.warning("下载读取图片Hash出错", e=e)
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user