zhenxun_bot/plugins/help/data_source.py

290 lines
11 KiB
Python
Raw Normal View History

2021-07-30 21:21:51 +08:00
from utils.image_utils import CreateImg
2021-10-03 14:24:07 +08:00
from configs.path_config import IMAGE_PATH
from utils.manager import plugins2settings_manager
from typing import Optional
from services.log import logger
2021-08-17 23:17:08 +08:00
from pathlib import Path
2021-10-03 14:24:07 +08:00
from utils.utils import get_matchers
import random
import asyncio
2021-06-15 10:57:08 +08:00
import nonebot
2021-10-03 14:24:07 +08:00
import os
2021-05-20 19:23:32 +08:00
2021-10-03 14:24:07 +08:00
random_bk_path = Path(IMAGE_PATH) / "background" / "help" / "simple_help"
2021-05-20 19:23:32 +08:00
2021-10-03 14:24:07 +08:00
background = Path(IMAGE_PATH) / "background" / "0.png"
2021-05-20 19:23:32 +08:00
2021-10-03 14:24:07 +08:00
async def create_help_img(help_image: Path, simple_help_image: Path):
"""
生成帮助图片
:param help_image: 图片路径
:param simple_help_image: 简易帮助图片路径
"""
return await asyncio.get_event_loop().run_in_executor(
None, _create_help_img, help_image, simple_help_image
2021-07-30 21:21:51 +08:00
)
2021-05-20 19:23:32 +08:00
2021-10-03 14:24:07 +08:00
def _create_help_img(help_image: Path, simple_help_image: Path):
"""
生成帮助图片
:param help_image: 图片路径
:param simple_help_image: 简易帮助图片路径
"""
_matchers = get_matchers()
width = 0
matchers_data = {}
_des_tmp = {}
_plugin_name_tmp = []
_tmp = []
tmp_img = CreateImg(0, 0, plain_text="1", font_size=24)
font_height = tmp_img.h
for matcher in _matchers:
plugin_name = None
_plugin = nonebot.plugin.get_plugin(matcher.module)
_module = _plugin.module
try:
plugin_name = _module.__getattribute__("__zx_plugin_name__")
try:
plugin_des = _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.module
) and plugins2settings_manager[matcher.module].get("plugin_type"):
plugin_type = tuple(
plugins2settings_manager.get_plugin_data(matcher.module)[
"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] = {
"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.module}: {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):
simple_help_str += f"{i+1}.{k}\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 = CreateImg(
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)[0] for x in simple_help_str.split("\n")]:
simple_width = simple_width if simple_width > x else x
bk = CreateImg(
simple_width + 20, simple_height, font_size=24, color="#6495ED"
)
B = CreateImg(
simple_width + 20,
simple_height,
font_size=24,
color="white" if not ix % 2 else "black",
)
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
A = CreateImg(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 = CreateImg(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 = CreateImg(
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 = CreateImg(
0,
0,
plain_text=msg,
font_size=24,
color=(255, 255, 255, 0),
font='yuanshen.ttf'
)
B.paste(text, (w, h), True)
h += 50
if msg == '目前支持的功能列表:':
w += 50
B.save(simple_help_image)
2021-05-20 19:23:32 +08:00
2021-10-03 14:24:07 +08:00
def get_max_width_or_paste(
simple_help_img_list: list, B: CreateImg = None, is_paste: bool = False
) -> "int, CreateImg":
"""
获取最大宽度或直接贴图
: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
2021-05-20 19:23:32 +08:00
2021-10-03 14:24:07 +08:00
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 module:
try:
plugin = nonebot.plugin.get_plugin(module)
if plugin:
if is_super:
result = plugin.module.__getattribute__(
"__plugin_superuser_usage__"
)
else:
result = plugin.module.__getattribute__("__plugin_usage__")
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 = CreateImg(width, height, font_size=24)
bk = CreateImg(
width, height, background=Path(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