mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-15 06:12:53 +08:00
373 lines
14 KiB
Python
Executable File
373 lines
14 KiB
Python
Executable File
from utils.image_utils import BuildImage
|
||
from configs.path_config import IMAGE_PATH
|
||
from utils.manager import (
|
||
plugins2settings_manager,
|
||
admin_manager,
|
||
plugins_manager,
|
||
group_manager,
|
||
)
|
||
from typing import Optional
|
||
from services.log import logger
|
||
from pathlib import Path
|
||
from utils.utils import get_matchers
|
||
import random
|
||
import asyncio
|
||
import nonebot
|
||
import os
|
||
|
||
|
||
random_bk_path = IMAGE_PATH / "background" / "help" / "simple_help"
|
||
|
||
background = IMAGE_PATH / "background" / "0.png"
|
||
|
||
|
||
async def create_help_img(
|
||
group_id: Optional[int], help_image: Path, simple_help_image: Path
|
||
):
|
||
"""
|
||
生成帮助图片
|
||
:param group_id: 群号
|
||
:param help_image: 图片路径
|
||
:param simple_help_image: 简易帮助图片路径
|
||
"""
|
||
return await asyncio.get_event_loop().run_in_executor(
|
||
None, _create_help_img, group_id, help_image, simple_help_image
|
||
)
|
||
|
||
|
||
def _create_help_img(
|
||
group_id: Optional[int], help_image: Path, simple_help_image: Path
|
||
):
|
||
"""
|
||
生成帮助图片
|
||
:param group_id: 群号
|
||
:param help_image: 图片路径
|
||
:param simple_help_image: 简易帮助图片路径
|
||
"""
|
||
_matchers = get_matchers(True)
|
||
width = 0
|
||
matchers_data = {}
|
||
_des_tmp = {}
|
||
_plugin_name_tmp = []
|
||
_tmp = []
|
||
tmp_img = BuildImage(0, 0, plain_text="1", font_size=24)
|
||
font_height = tmp_img.h
|
||
# 插件分类
|
||
for matcher in _matchers:
|
||
plugin_name = None
|
||
_plugin = matcher.plugin
|
||
metadata = _plugin.metadata
|
||
if not _plugin:
|
||
logger.warning(f"获取 功能:{matcher.plugin_name} 失败...")
|
||
continue
|
||
_module = _plugin.module
|
||
try:
|
||
plugin_name = metadata.name if metadata else _module.__getattribute__("__zx_plugin_name__")
|
||
try:
|
||
plugin_des = metadata.description if metadata else _module.__getattribute__("__plugin_des__")
|
||
except AttributeError:
|
||
plugin_des = "_"
|
||
if (
|
||
"[hidden]" in plugin_name.lower()
|
||
or "[admin]" in plugin_name.lower()
|
||
or "[superuser]" in plugin_name.lower()
|
||
or plugin_name in _plugin_name_tmp
|
||
or plugin_name == "帮助"
|
||
):
|
||
continue
|
||
plugin_type = ("normal",)
|
||
text_type = 0
|
||
if plugins2settings_manager.get(
|
||
matcher.plugin_name
|
||
) and plugins2settings_manager[matcher.plugin_name].get("plugin_type"):
|
||
plugin_type = tuple(
|
||
plugins2settings_manager.get_plugin_data(matcher.plugin_name)[
|
||
"plugin_type"
|
||
]
|
||
)
|
||
else:
|
||
try:
|
||
plugin_type = _module.__getattribute__("__plugin_type__")
|
||
except AttributeError:
|
||
pass
|
||
if len(plugin_type) > 1:
|
||
try:
|
||
text_type = int(plugin_type[1])
|
||
except ValueError as e:
|
||
logger.warning(f"生成列向帮助排列失败 {plugin_name}: {type(e)}: {e}")
|
||
plugin_type = plugin_type[0]
|
||
else:
|
||
plugin_type = plugin_type[0]
|
||
try:
|
||
plugin_cmd = _module.__getattribute__("__plugin_cmd__")
|
||
plugin_cmd = [x for x in plugin_cmd if "[_superuser]" not in x]
|
||
except AttributeError:
|
||
plugin_cmd = []
|
||
if plugin_type not in matchers_data.keys():
|
||
matchers_data[plugin_type] = {}
|
||
if plugin_des in _des_tmp.keys():
|
||
try:
|
||
matchers_data[plugin_type][_des_tmp[plugin_des]]["cmd"] = (
|
||
matchers_data[plugin_type][_des_tmp[plugin_des]]["cmd"]
|
||
+ plugin_cmd
|
||
)
|
||
except KeyError as e:
|
||
logger.warning(f"{type(e)}: {e}")
|
||
else:
|
||
matchers_data[plugin_type][plugin_name] = {
|
||
"modules": matcher.plugin_name,
|
||
"des": plugin_des,
|
||
"cmd": plugin_cmd,
|
||
"text_type": text_type,
|
||
}
|
||
try:
|
||
if text_type == 0:
|
||
x = tmp_img.getsize(
|
||
f'{plugin_name}: {matchers_data[plugin_type][plugin_name]["des"]} ->'
|
||
+ " / ".join(matchers_data[plugin_type][plugin_name]["cmd"])
|
||
)[0]
|
||
width = width if width > x else x
|
||
except KeyError:
|
||
pass
|
||
if plugin_des not in _des_tmp:
|
||
_des_tmp[plugin_des] = plugin_name
|
||
except AttributeError as e:
|
||
if plugin_name not in _plugin_name_tmp:
|
||
logger.warning(f"获取功能 {matcher.plugin_name}: {plugin_name} 设置失败...e:{e}")
|
||
if plugin_name not in _plugin_name_tmp:
|
||
_plugin_name_tmp.append(plugin_name)
|
||
help_img_list = []
|
||
simple_help_img_list = []
|
||
types = list(matchers_data.keys())
|
||
types.sort()
|
||
ix = 0
|
||
# 详细帮助
|
||
for type_ in types:
|
||
keys = list(matchers_data[type_].keys())
|
||
keys.sort()
|
||
help_str = f"{type_ if type_ != 'normal' else '功能'}:\n\n"
|
||
simple_help_str = f"{type_ if type_ != 'normal' else '功能'}:\n\n"
|
||
for i, k in enumerate(keys):
|
||
# 禁用flag
|
||
flag = True
|
||
if plugins_manager.get_plugin_status(
|
||
matchers_data[type_][k]["modules"], "all"
|
||
):
|
||
flag = False
|
||
if group_id:
|
||
flag = flag and plugins_manager.get_plugin_status(
|
||
matchers_data[type_][k]["modules"], "group"
|
||
)
|
||
simple_help_str += (
|
||
f"{i+1}.{k}<|_|~|>"
|
||
f"{group_manager.get_plugin_status(matchers_data[type_][k]['modules'], group_id) if group_id else '_'}|"
|
||
f"{flag}\n"
|
||
)
|
||
if matchers_data[type_][k]["text_type"] == 1:
|
||
_x = tmp_img.getsize(
|
||
f"{i+1}".rjust(5)
|
||
+ f'.{k}: {matchers_data[type_][k]["des"]} {"->" if matchers_data[type_][k]["cmd"] else ""} '
|
||
)[0]
|
||
_str = (
|
||
f"{i+1}".rjust(5)
|
||
+ f'.{k}: {matchers_data[type_][k]["des"]} {"->" if matchers_data[type_][k]["cmd"] else ""} '
|
||
)
|
||
_str += matchers_data[type_][k]["cmd"][0] + "\n"
|
||
for c in matchers_data[type_][k]["cmd"][1:]:
|
||
_str += "".rjust(int(_x * 0.125) + 1) + f"{c}\n"
|
||
help_str += _str
|
||
else:
|
||
help_str += (
|
||
f"{i+1}".rjust(5)
|
||
+ f'.{k}: {matchers_data[type_][k]["des"]} {"->" if matchers_data[type_][k]["cmd"] else ""} '
|
||
+ " / ".join(matchers_data[type_][k]["cmd"])
|
||
+ "\n"
|
||
)
|
||
height = len(help_str.split("\n")) * (font_height + 5)
|
||
simple_height = len(simple_help_str.split("\n")) * (font_height + 5)
|
||
A = BuildImage(
|
||
width + 150, height, font_size=24, color="white" if not ix % 2 else "black"
|
||
)
|
||
A.text((10, 10), help_str, (255, 255, 255) if ix % 2 else (0, 0, 0))
|
||
# 生成各个分类的插件简易帮助图片
|
||
simple_width = 0
|
||
for x in [
|
||
tmp_img.getsize(x.split("<|_|~|>")[0])[0]
|
||
for x in simple_help_str.split("\n")
|
||
]:
|
||
simple_width = simple_width if simple_width > x else x
|
||
bk = BuildImage(simple_width + 20, simple_height, font_size=24, color="#6495ED")
|
||
B = BuildImage(
|
||
simple_width + 20,
|
||
simple_height,
|
||
font_size=24,
|
||
color="white" if not ix % 2 else "black",
|
||
)
|
||
# 切分,判断插件开关状态
|
||
_s_height = 10
|
||
for _s in simple_help_str.split("\n"):
|
||
text_color = (255, 255, 255) if ix % 2 else (0, 0, 0)
|
||
_line_flag = False
|
||
if "<|_|~|>" in _s:
|
||
_x = _s.split("<|_|~|>")
|
||
_flag_sp = _x[-1].split("|")
|
||
if group_id:
|
||
if _flag_sp[0].lower() != "true":
|
||
text_color = (252, 75, 13)
|
||
if _flag_sp[1].lower() == "true":
|
||
_line_flag = True
|
||
_s = _x[0]
|
||
B.text((10, _s_height), _s, text_color)
|
||
if _line_flag:
|
||
B.line(
|
||
(
|
||
7,
|
||
_s_height + int(B.getsize(_s)[1] / 2) + 2,
|
||
B.getsize(_s)[0] + 11,
|
||
_s_height + int(B.getsize(_s)[1] / 2) + 2,
|
||
),
|
||
(236, 66, 7),
|
||
3,
|
||
)
|
||
_s_height += B.getsize("1")[1] + 5
|
||
# B.text((10, 10), simple_help_str, (255, 255, 255) if ix % 2 else (0, 0, 0))
|
||
bk.paste(B, center_type="center")
|
||
bk.transparent(2)
|
||
ix += 1
|
||
help_img_list.append(A)
|
||
simple_help_img_list.append(bk)
|
||
height = 0
|
||
for img in help_img_list:
|
||
height += img.h
|
||
if not group_id:
|
||
A = BuildImage(width + 150, height + 50, font_size=24)
|
||
A.text(
|
||
(10, 10), '* 注: ‘*’ 代表可有多个相同参数 ‘?’ 代表可省略该参数 *\n\n" "功能名: 功能简介 -> 指令\n\n'
|
||
)
|
||
current_height = 50
|
||
for img in help_img_list:
|
||
A.paste(img, (0, current_height))
|
||
current_height += img.h
|
||
A.save(help_image)
|
||
# 详细帮助生成完毕
|
||
# 简易帮助图片合成
|
||
height = 0
|
||
width = 0
|
||
for img in simple_help_img_list:
|
||
if img.h > height:
|
||
height = img.h
|
||
width += img.w + 10
|
||
B = BuildImage(width + 100, height + 250, font_size=24)
|
||
width, _ = get_max_width_or_paste(simple_help_img_list, B)
|
||
bk = None
|
||
random_bk = os.listdir(random_bk_path)
|
||
if random_bk:
|
||
bk = random.choice(random_bk)
|
||
x = max(width + 50, height + 250)
|
||
B = BuildImage(
|
||
x,
|
||
x,
|
||
font_size=24,
|
||
color="#FFEFD5",
|
||
background=random_bk_path / bk,
|
||
)
|
||
B.filter("GaussianBlur", 10)
|
||
_, B = get_max_width_or_paste(simple_help_img_list, B, True)
|
||
w = 10
|
||
h = 10
|
||
for msg in ["目前支持的功能列表:", "可以通过 ‘帮助[功能名称]’ 来获取对应功能的使用方法", "或者使用 ‘详细帮助’ 来获取所有功能方法"]:
|
||
text = BuildImage(
|
||
0,
|
||
0,
|
||
plain_text=msg,
|
||
font_size=24,
|
||
font="HYWenHei-85W.ttf",
|
||
)
|
||
B.paste(text, (w, h), True)
|
||
h += 50
|
||
if msg == "目前支持的功能列表:":
|
||
w += 50
|
||
B.paste(
|
||
BuildImage(
|
||
0,
|
||
0,
|
||
plain_text="注: 红字代表功能被群管理员禁用,红线代表功能正在维护",
|
||
font_size=24,
|
||
font="HYWenHei-85W.ttf",
|
||
font_color=(231, 74, 57)
|
||
),
|
||
(300, 10),
|
||
True,
|
||
)
|
||
B.save(simple_help_image)
|
||
|
||
|
||
def get_max_width_or_paste(
|
||
simple_help_img_list: list, B: BuildImage = None, is_paste: bool = False
|
||
) -> "int, BuildImage":
|
||
"""
|
||
获取最大宽度,或直接贴图
|
||
:param simple_help_img_list: 简单帮助图片列表
|
||
:param B: 背景图
|
||
:param is_paste: 是否直接贴图
|
||
"""
|
||
current_width = 50
|
||
current_height = 180
|
||
max_width = simple_help_img_list[0].w
|
||
for i in range(len(simple_help_img_list)):
|
||
try:
|
||
if is_paste and B:
|
||
B.paste(simple_help_img_list[i], (current_width, current_height), True)
|
||
current_height += simple_help_img_list[i].h + 40
|
||
if current_height + simple_help_img_list[i + 1].h > B.h - 10:
|
||
current_height = 180
|
||
current_width += max_width + 30
|
||
max_width = 0
|
||
elif simple_help_img_list[i].w > max_width:
|
||
max_width = simple_help_img_list[i].w
|
||
except IndexError:
|
||
pass
|
||
if current_width > simple_help_img_list[0].w + 50:
|
||
current_width += simple_help_img_list[-1].w
|
||
return current_width, B
|
||
|
||
|
||
def get_plugin_help(msg: str, is_super: bool = False) -> Optional[str]:
|
||
"""
|
||
获取功能的帮助信息
|
||
:param msg: 功能cmd
|
||
:param is_super: 是否为超级用户
|
||
"""
|
||
module = plugins2settings_manager.get_plugin_module(msg)
|
||
if not module:
|
||
module = admin_manager.get_plugin_module(msg)
|
||
if module:
|
||
try:
|
||
plugin = nonebot.plugin.get_plugin(module)
|
||
metadata = plugin.metadata
|
||
if plugin:
|
||
if is_super:
|
||
result = plugin.module.__getattribute__(
|
||
"__plugin_superuser_usage__"
|
||
)
|
||
else:
|
||
result = metadata.usage if metadata else plugin.module.__getattribute__("__plugin_usage__")
|
||
if result:
|
||
width = 0
|
||
for x in result.split("\n"):
|
||
_width = len(x) * 24
|
||
width = width if width > _width else _width
|
||
height = len(result.split("\n")) * 45
|
||
A = BuildImage(width, height, font_size=24)
|
||
bk = BuildImage(
|
||
width,
|
||
height,
|
||
background=IMAGE_PATH / "background" / "1.png",
|
||
)
|
||
A.paste(bk, alpha=True)
|
||
A.text((int(width * 0.048), int(height * 0.21)), result)
|
||
return A.pic2bs4()
|
||
except AttributeError:
|
||
pass
|
||
return None
|