From a3681216bde44543cacd525dbfe989eef0622939 Mon Sep 17 00:00:00 2001
From: HibiKier <775757368@qq.com>
Date: Fri, 30 Aug 2024 23:50:45 +0800
Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=E7=88=B6=E7=BA=A7=E6=8F=92?=
=?UTF-8?q?=E4=BB=B6=E5=8A=A0=E8=BD=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
zhenxun/builtin_plugins/init/init_plugin.py | 115 ++++++++---------
.../builtin_plugins/plugin_store/__init__.py | 22 ++--
.../plugin_store/data_source.py | 4 +-
zhenxun/configs/utils/__init__.py | 2 +-
zhenxun/models/plugin_info.py | 13 +-
zhenxun/utils/_build_image.py | 116 +++++++++---------
zhenxun/utils/_image_template.py | 20 ++-
zhenxun/utils/enum.py | 2 +
zhenxun/utils/message.py | 36 ++++--
9 files changed, 177 insertions(+), 153 deletions(-)
diff --git a/zhenxun/builtin_plugins/init/init_plugin.py b/zhenxun/builtin_plugins/init/init_plugin.py
index 8581dafe..da018eac 100644
--- a/zhenxun/builtin_plugins/init/init_plugin.py
+++ b/zhenxun/builtin_plugins/init/init_plugin.py
@@ -2,9 +2,9 @@ import nonebot
import aiofiles
import ujson as json
from ruamel.yaml import YAML
-from nonebot.plugin import Plugin
from nonebot.drivers import Driver
from nonebot import get_loaded_plugins
+from nonebot.plugin import Plugin, PluginMetadata
from zhenxun.services.log import logger
from zhenxun.models.task_info import TaskInfo
@@ -41,64 +41,68 @@ async def _handle_setting(
plugin_list: 插件列表
limit_list: 插件限制列表
"""
- if metadata := plugin.metadata:
- extra = metadata.extra
- extra_data = PluginExtraData(**extra)
- logger.debug(f"{metadata.name}:{plugin.name} -> {extra}", "初始化插件数据")
- setting = extra_data.setting or PluginSetting()
- if metadata.type == "library":
- extra_data.plugin_type = PluginType.HIDDEN
- if (
- extra_data.plugin_type
- == PluginType.HIDDEN
- # and extra_data.plugin_type != "功能"
- ):
- extra_data.menu_type = ""
- plugin_list.append(
- PluginInfo(
+ metadata = plugin.metadata
+ if not metadata:
+ if not plugin.sub_plugins:
+ return
+ """父插件"""
+ metadata = PluginMetadata(name=plugin.name, description="", usage="")
+ extra = metadata.extra
+ extra_data = PluginExtraData(**extra)
+ logger.debug(f"{metadata.name}:{plugin.name} -> {extra}", "初始化插件数据")
+ setting = extra_data.setting or PluginSetting()
+ if metadata.type == "library":
+ extra_data.plugin_type = PluginType.HIDDEN
+ if extra_data.plugin_type == PluginType.HIDDEN:
+ extra_data.menu_type = ""
+ if plugin.sub_plugins:
+ extra_data.plugin_type = PluginType.PARENT
+ plugin_list.append(
+ PluginInfo(
+ module=plugin.name,
+ module_path=plugin.module_name,
+ name=metadata.name,
+ author=extra_data.author,
+ version=extra_data.version,
+ level=setting.level,
+ default_status=setting.default_status,
+ limit_superuser=setting.limit_superuser,
+ menu_type=extra_data.menu_type,
+ cost_gold=setting.cost_gold,
+ plugin_type=extra_data.plugin_type,
+ admin_level=extra_data.admin_level,
+ parent=(plugin.parent_plugin.module_name if plugin.parent_plugin else None),
+ )
+ )
+ if extra_data.limits:
+ limit_list.extend(
+ PluginLimit(
module=plugin.name,
module_path=plugin.module_name,
- name=metadata.name,
- author=extra_data.author,
- version=extra_data.version,
- level=setting.level,
- default_status=setting.default_status,
- limit_superuser=setting.limit_superuser,
- menu_type=extra_data.menu_type,
- cost_gold=setting.cost_gold,
- plugin_type=extra_data.plugin_type,
- admin_level=extra_data.admin_level,
+ limit_type=limit._type,
+ watch_type=limit.watch_type,
+ status=limit.status,
+ check_type=limit.check_type,
+ result=limit.result,
+ cd=getattr(limit, "cd", None),
+ max_count=getattr(limit, "max_count", None),
)
+ for limit in extra_data.limits
)
- if extra_data.limits:
- limit_list.extend(
- PluginLimit(
- module=plugin.name,
- module_path=plugin.module_name,
- limit_type=limit._type,
- watch_type=limit.watch_type,
- status=limit.status,
- check_type=limit.check_type,
- result=limit.result,
- cd=getattr(limit, "cd", None),
- max_count=getattr(limit, "max_count", None),
- )
- for limit in extra_data.limits
- )
- if extra_data.tasks:
- task_list.extend(
- (
- task.create_status,
- TaskInfo(
- module=task.module,
- name=task.name,
- status=task.status,
- run_time=task.run_time,
- default_status=task.default_status,
- ),
- )
- for task in extra_data.tasks
+ if extra_data.tasks:
+ task_list.extend(
+ (
+ task.create_status,
+ TaskInfo(
+ module=task.module,
+ name=task.name,
+ status=task.status,
+ run_time=task.run_time,
+ default_status=task.default_status,
+ ),
)
+ for task in extra_data.tasks
+ )
@driver.on_startup
@@ -115,8 +119,7 @@ async def _():
module2id = {m["module_path"]: m["id"] for m in module_list}
for plugin in get_loaded_plugins():
load_plugin.append(plugin.module_name)
- if plugin.metadata:
- await _handle_setting(plugin, plugin_list, limit_list, task_list)
+ await _handle_setting(plugin, plugin_list, limit_list, task_list)
create_list = []
update_list = []
for plugin in plugin_list:
diff --git a/zhenxun/builtin_plugins/plugin_store/__init__.py b/zhenxun/builtin_plugins/plugin_store/__init__.py
index d9c2cc52..4ff8c940 100644
--- a/zhenxun/builtin_plugins/plugin_store/__init__.py
+++ b/zhenxun/builtin_plugins/plugin_store/__init__.py
@@ -1,12 +1,12 @@
from nonebot.permission import SUPERUSER
from nonebot.plugin import PluginMetadata
-from nonebot_plugin_alconna import Alconna, Args, Subcommand, on_alconna
from nonebot_plugin_session import EventSession
+from nonebot_plugin_alconna import Args, Alconna, Subcommand, on_alconna
-from zhenxun.configs.utils import PluginExtraData
from zhenxun.services.log import logger
from zhenxun.utils.enum import PluginType
from zhenxun.utils.message import MessageUtils
+from zhenxun.configs.utils import PluginExtraData
from .data_source import ShopManage
@@ -68,6 +68,7 @@ _matcher.shortcut(
prefix=True,
)
+
@_matcher.assign("$main")
async def _(session: EventSession):
try:
@@ -82,9 +83,7 @@ async def _(session: EventSession):
@_matcher.assign("add")
async def _(session: EventSession, plugin_id: int):
try:
- await MessageUtils.build_message(
- f"正在添加插件 Id: {plugin_id}"
- ).send()
+ await MessageUtils.build_message(f"正在添加插件 Id: {plugin_id}").send()
result = await ShopManage.add_plugin(plugin_id)
except Exception as e:
logger.error(f"添加插件 Id: {plugin_id}失败", "插件商店", session=session, e=e)
@@ -107,24 +106,29 @@ async def _(session: EventSession, plugin_id: int):
logger.info(f"移除插件 Id: {plugin_id}", "插件商店", session=session)
await MessageUtils.build_message(result).send()
+
@_matcher.assign("search")
async def _(session: EventSession, plugin_name_or_author: str):
try:
result = await ShopManage.search_plugin(plugin_name_or_author)
except Exception as e:
- logger.error(f"搜索插件 name: {plugin_name_or_author}失败", "插件商店", session=session, e=e)
+ logger.error(
+ f"搜索插件 name: {plugin_name_or_author}失败",
+ "插件商店",
+ session=session,
+ e=e,
+ )
await MessageUtils.build_message(
f"搜索插件 name: {plugin_name_or_author} 失败 e: {e}"
).finish()
logger.info(f"搜索插件 name: {plugin_name_or_author}", "插件商店", session=session)
await MessageUtils.build_message(result).send()
+
@_matcher.assign("update")
async def _(session: EventSession, plugin_id: int):
try:
- await MessageUtils.build_message(
- f"正在更新插件 Id: {plugin_id}"
- ).send()
+ await MessageUtils.build_message(f"正在更新插件 Id: {plugin_id}").send()
result = await ShopManage.update_plugin(plugin_id)
except Exception as e:
logger.error(f"更新插件 Id: {plugin_id}失败", "插件商店", session=session, e=e)
diff --git a/zhenxun/builtin_plugins/plugin_store/data_source.py b/zhenxun/builtin_plugins/plugin_store/data_source.py
index 5b20ddfd..bc8ff412 100644
--- a/zhenxun/builtin_plugins/plugin_store/data_source.py
+++ b/zhenxun/builtin_plugins/plugin_store/data_source.py
@@ -211,7 +211,7 @@ class ShopManage:
plugin_list = await PluginInfo.filter(load_status=True).values_list(
"module", "version"
)
- suc_plugin = {p[0]: p[1] for p in plugin_list if p[1]}
+ suc_plugin = {p[0]: (p[1] or "0.1") for p in plugin_list}
data_list = [
[
"已安装" if plugin_info[1]["module"] in suc_plugin else "",
@@ -226,7 +226,7 @@ class ShopManage:
]
return await ImageTemplate.table_page(
"插件列表",
- "通过安装/卸载插件 ID 来管理插件",
+ "通过添加/移除插件 ID 来管理插件",
column_name,
data_list,
text_style=row_style,
diff --git a/zhenxun/configs/utils/__init__.py b/zhenxun/configs/utils/__init__.py
index 3277222c..d23549bb 100644
--- a/zhenxun/configs/utils/__init__.py
+++ b/zhenxun/configs/utils/__init__.py
@@ -356,7 +356,7 @@ class ConfigsManager:
value = default
logger.debug(
f"获取配置 MODULE: [{module}] | "
- " KEY: [{key}] -> [{value}]"
+ f" KEY: [{key}] -> [{value}]"
)
return value
diff --git a/zhenxun/models/plugin_info.py b/zhenxun/models/plugin_info.py
index e5eb1b21..964dabad 100644
--- a/zhenxun/models/plugin_info.py
+++ b/zhenxun/models/plugin_info.py
@@ -2,8 +2,7 @@ from tortoise import fields
from zhenxun.services.db_context import Model
from zhenxun.utils.enum import BlockType, PluginType
-
-from .plugin_limit import PluginLimit
+from zhenxun.models.plugin_limit import PluginLimit # noqa: F401
class PluginInfo(Model):
@@ -45,7 +44,15 @@ class PluginInfo(Model):
"""调用所需权限等级"""
is_delete = fields.BooleanField(default=False, description="是否删除")
"""是否删除"""
+ parent = fields.CharField(max_length=255, null=True, description="父插件")
+ """父插件"""
- class Meta:
+ class Meta: # type: ignore
table = "plugin_info"
table_description = "插件基本信息"
+
+ @classmethod
+ async def _run_script(cls):
+ return [
+ "ALTER TABLE plugin_info ADD COLUMN parent character varying(255);",
+ ]
diff --git a/zhenxun/utils/_build_image.py b/zhenxun/utils/_build_image.py
index 0f12b1e3..7f353d4b 100644
--- a/zhenxun/utils/_build_image.py
+++ b/zhenxun/utils/_build_image.py
@@ -1,15 +1,17 @@
-import base64
import math
import uuid
+import base64
+import itertools
+import contextlib
from io import BytesIO
from pathlib import Path
-from typing import Literal, Tuple, TypeAlias, overload
+from typing_extensions import Self
+from typing import Literal, TypeAlias, overload
from nonebot.utils import run_sync
-from PIL import Image, ImageDraw, ImageFilter, ImageFont
from PIL.Image import Image as tImage
from PIL.ImageFont import FreeTypeFont
-from typing_extensions import Self
+from PIL import Image, ImageDraw, ImageFont, ImageFilter
from zhenxun.configs.path_config import FONT_PATH
@@ -18,7 +20,7 @@ ModeType = Literal[
]
"""图片类型"""
-ColorAlias: TypeAlias = str | Tuple[int, int, int] | Tuple[int, int, int, int] | None
+ColorAlias: TypeAlias = str | tuple[int, int, int] | tuple[int, int, int, int] | None
CenterType = Literal["center", "height", "width"]
"""
@@ -52,9 +54,7 @@ class BuildImage:
self.height = height
self.color = color
self.font = (
- self.load_font(font, font_size)
- if not isinstance(font, FreeTypeFont)
- else font
+ font if isinstance(font, FreeTypeFont) else self.load_font(font, font_size)
)
if background:
if isinstance(background, bytes):
@@ -66,14 +66,14 @@ class BuildImage:
else:
self.width = self.markImg.width
self.height = self.markImg.height
- else:
- if not width or not height:
- raise ValueError("长度和宽度不能为空...")
+ elif width and height:
self.markImg = Image.new(mode, (width, height), color) # type: ignore
+ else:
+ raise ValueError("长度和宽度不能为空...")
self.draw = ImageDraw.Draw(self.markImg)
@property
- def size(self) -> Tuple[int, int]:
+ def size(self) -> tuple[int, int]:
return self.markImg.size
@classmethod
@@ -94,9 +94,9 @@ class BuildImage:
text: str,
font: str | FreeTypeFont | Path = "HYWenHei-85W.ttf",
size: int = 10,
- font_color: str | Tuple[int, int, int] = (0, 0, 0),
+ font_color: str | tuple[int, int, int] = (0, 0, 0),
color: ColorAlias = None,
- padding: int | Tuple[int, int, int, int] | None = None,
+ padding: int | tuple[int, int, int, int] | None = None,
) -> Self:
"""构建文本图片
@@ -116,7 +116,7 @@ class BuildImage:
_font = None
if isinstance(font, FreeTypeFont):
_font = font
- elif isinstance(font, (str, Path)):
+ elif isinstance(font, str | Path):
_font = cls.load_font(font, size)
width, height = cls.get_text_size(text, _font)
if isinstance(padding, int):
@@ -161,7 +161,7 @@ class BuildImage:
row_count = math.ceil(len(img_list) / row)
if row_count == 1:
background_width = (
- sum([img.width for img in img_list]) + space * (row - 1) + padding * 2
+ sum(img.width for img in img_list) + space * (row - 1) + padding * 2
)
background_height = height * row_count + space * (row_count - 1) + padding * 2
background_image = cls(
@@ -189,20 +189,20 @@ class BuildImage:
返回:
FreeTypeFont: 字体
"""
- path = FONT_PATH / font if type(font) == str else font
+ path = FONT_PATH / font if type(font) is str else font
return ImageFont.truetype(str(path), font_size)
@overload
@classmethod
def get_text_size(
cls, text: str, font: FreeTypeFont | None = None
- ) -> Tuple[int, int]: ...
+ ) -> tuple[int, int]: ...
@overload
@classmethod
def get_text_size(
cls, text: str, font: str | None = None, font_size: int = 10
- ) -> Tuple[int, int]: ...
+ ) -> tuple[int, int]: ...
@classmethod
def get_text_size(
@@ -210,7 +210,7 @@ class BuildImage:
text: str,
font: str | FreeTypeFont | None = "HYWenHei-85W.ttf",
font_size: int = 10,
- ) -> Tuple[int, int]:
+ ) -> tuple[int, int]: # sourcery skip: remove-unnecessary-cast
"""获取该字体下文本需要的长宽
参数:
@@ -219,10 +219,10 @@ class BuildImage:
font_size: 字体大小
返回:
- Tuple[int, int]: 长宽
+ tuple[int, int]: 长宽
"""
_font = font
- if font and type(font) == str:
+ if font and type(font) is str:
_font = cls.load_font(font, font_size)
temp_image = Image.new("RGB", (1, 1), (255, 255, 255))
draw = ImageDraw.Draw(temp_image)
@@ -232,7 +232,8 @@ class BuildImage:
return text_width, text_height + 10
# return _font.getsize(str(text)) # type: ignore
- def getsize(self, msg: str) -> Tuple[int, int]:
+ def getsize(self, msg: str) -> tuple[int, int]:
+ # sourcery skip: remove-unnecessary-cast
"""
获取文字在该图片 font_size 下所需要的空间
@@ -240,7 +241,7 @@ class BuildImage:
msg: 文本
返回:
- Tuple[int, int]: 长宽
+ tuple[int, int]: 长宽
"""
temp_image = Image.new("RGB", (1, 1), (255, 255, 255))
draw = ImageDraw.Draw(temp_image)
@@ -252,11 +253,11 @@ class BuildImage:
def __center_xy(
self,
- pos: Tuple[int, int],
+ pos: tuple[int, int],
width: int,
height: int,
center_type: CenterType | None,
- ) -> Tuple[int, int]:
+ ) -> tuple[int, int]:
"""
根据居中类型定位xy
@@ -266,7 +267,7 @@ class BuildImage:
center_type: 居中类型
返回:
- Tuple[int, int]: 定位
+ tuple[int, int]: 定位
"""
# _width, _height = pos
if self.width and self.height:
@@ -285,7 +286,7 @@ class BuildImage:
def paste(
self,
image: Self | tImage,
- pos: Tuple[int, int] = (0, 0),
+ pos: tuple[int, int] = (0, 0),
center_type: CenterType | None = None,
) -> Self:
"""贴图
@@ -303,7 +304,6 @@ class BuildImage:
"""
if center_type and center_type not in ["center", "height", "width"]:
raise ValueError("center_type must be 'center', 'width' or 'height'")
- width, height = 0, 0
_image = image
if isinstance(image, BuildImage):
_image = image.markImg
@@ -317,7 +317,7 @@ class BuildImage:
@run_sync
def point(
- self, pos: Tuple[int, int], fill: Tuple[int, int, int] | None = None
+ self, pos: tuple[int, int], fill: tuple[int, int, int] | None = None
) -> Self:
"""
绘制多个或单独的像素
@@ -335,9 +335,9 @@ class BuildImage:
@run_sync
def ellipse(
self,
- pos: Tuple[int, int, int, int],
- fill: Tuple[int, int, int] | None = None,
- outline: Tuple[int, int, int] | None = None,
+ pos: tuple[int, int, int, int],
+ fill: tuple[int, int, int] | None = None,
+ outline: tuple[int, int, int] | None = None,
width: int = 1,
) -> Self:
"""
@@ -358,13 +358,13 @@ class BuildImage:
@run_sync
def text(
self,
- pos: Tuple[int, int],
+ pos: tuple[int, int],
text: str,
- fill: str | Tuple[int, int, int] = (0, 0, 0),
+ fill: str | tuple[int, int, int] = (0, 0, 0),
center_type: CenterType | None = None,
font: FreeTypeFont | str | Path | None = None,
font_size: int = 10,
- ) -> Self:
+ ) -> Self: # sourcery skip: remove-unnecessary-cast
"""
在图片上添加文字
@@ -382,11 +382,10 @@ class BuildImage:
异常:
ValueError: 居中类型错误
"""
- text = str(text)
if center_type and center_type not in ["center", "height", "width"]:
raise ValueError("center_type must be 'center', 'width' or 'height'")
max_length_text = ""
- sentence = text.split("\n")
+ sentence = str(text).split("\n")
for x in sentence:
max_length_text = x if len(x) > len(max_length_text) else max_length_text
if font:
@@ -398,7 +397,7 @@ class BuildImage:
ttf_w, ttf_h = self.getsize(max_length_text) # type: ignore
# ttf_h = ttf_h * len(sentence)
pos = self.__center_xy(pos, ttf_w, ttf_h, center_type)
- self.draw.text(pos, text, fill=fill, font=font)
+ self.draw.text(pos, str(text), fill=fill, font=font)
return self
@run_sync
@@ -437,7 +436,7 @@ class BuildImage:
if not width and not height and not ratio:
raise ValueError("缺少参数...")
if self.width and self.height:
- if not width and not height and ratio:
+ if not width and not height:
width = int(self.width * ratio)
height = int(self.height * ratio)
self.markImg = self.markImg.resize((width, height), Image.LANCZOS) # type: ignore
@@ -446,7 +445,7 @@ class BuildImage:
return self
@run_sync
- def crop(self, box: Tuple[int, int, int, int]) -> Self:
+ def crop(self, box: tuple[int, int, int, int]) -> Self:
"""
裁剪图片
@@ -475,11 +474,10 @@ class BuildImage:
"""
self.markImg = self.markImg.convert("RGBA")
x, y = self.markImg.size
- for i in range(n, x - n):
- for k in range(n, y - n):
- color = self.markImg.getpixel((i, k))
- color = color[:-1] + (int(100 * alpha_ratio),)
- self.markImg.putpixel((i, k), color)
+ for i, k in itertools.product(range(n, x - n), range(n, y - n)):
+ color = self.markImg.getpixel((i, k))
+ color = color[:-1] + (int(100 * alpha_ratio),)
+ self.markImg.putpixel((i, k), color)
self.draw = ImageDraw.Draw(self.markImg)
return self
@@ -492,7 +490,7 @@ class BuildImage:
buf = BytesIO()
self.markImg.save(buf, format="PNG")
base64_str = base64.b64encode(buf.getvalue()).decode()
- return "base64://" + base64_str
+ return f"base64://{base64_str}"
def pic2bytes(self) -> bytes:
"""获取bytes
@@ -520,8 +518,8 @@ class BuildImage:
@run_sync
def rectangle(
self,
- xy: Tuple[int, int, int, int],
- fill: Tuple[int, int, int] | None = None,
+ xy: tuple[int, int, int, int],
+ fill: tuple[int, int, int] | None = None,
outline: str | None = None,
width: int = 1,
) -> Self:
@@ -543,8 +541,8 @@ class BuildImage:
@run_sync
def polygon(
self,
- xy: list[Tuple[int, int]],
- fill: Tuple[int, int, int] = (0, 0, 0),
+ xy: list[tuple[int, int]],
+ fill: tuple[int, int, int] = (0, 0, 0),
outline: int = 1,
) -> Self:
"""
@@ -564,8 +562,8 @@ class BuildImage:
@run_sync
def line(
self,
- xy: Tuple[int, int, int, int],
- fill: Tuple[int, int, int] | str = "#D8DEE4",
+ xy: tuple[int, int, int, int],
+ fill: tuple[int, int, int] | str = "#D8DEE4",
width: int = 1,
) -> Self:
"""
@@ -605,21 +603,19 @@ class BuildImage:
)
draw = ImageDraw.Draw(mask)
for offset, fill in (width / -2.0, "black"), (width / 2.0, "white"):
- left, top = [(value + offset) * antialias for value in ellipse_box[:2]]
- right, bottom = [(value - offset) * antialias for value in ellipse_box[2:]]
+ left, top = ((value + offset) * antialias for value in ellipse_box[:2])
+ right, bottom = ((value - offset) * antialias for value in ellipse_box[2:])
draw.ellipse([left, top, right, bottom], fill=fill)
mask = mask.resize(self.markImg.size, Image.LANCZOS)
- try:
+ with contextlib.suppress(ValueError):
self.markImg.putalpha(mask)
- except ValueError:
- pass
return self
@run_sync
def circle_corner(
self,
radii: int = 30,
- point_list: list[Literal["lt", "rt", "lb", "rb"]] = ["lt", "rt", "lb", "rb"],
+ point_list: list[Literal["lt", "rt", "lb", "rb"]] | None = None,
) -> Self:
"""
矩形四角变圆
@@ -631,6 +627,8 @@ class BuildImage:
返回:
BuildImage: Self
"""
+ if point_list is None:
+ point_list = ["lt", "rt", "lb", "rb"]
# 画圆(用于分离4个角)
img = self.markImg.convert("RGBA")
alpha = img.split()[-1]
diff --git a/zhenxun/utils/_image_template.py b/zhenxun/utils/_image_template.py
index e989accc..a1d4c01b 100644
--- a/zhenxun/utils/_image_template.py
+++ b/zhenxun/utils/_image_template.py
@@ -1,11 +1,10 @@
import random
from io import BytesIO
from pathlib import Path
-from typing import Any, Callable, Dict
+from collections.abc import Callable
-from fastapi import background
-from PIL.ImageFont import FreeTypeFont
from pydantic import BaseModel
+from PIL.ImageFont import FreeTypeFont
from ._build_image import BuildImage
@@ -25,13 +24,13 @@ class RowStyle(BaseModel):
class ImageTemplate:
- color_list = ["#C2CEFE", "#FFA94C", "#3FE6A0", "#D1D4F5"]
+ color_list = ["#C2CEFE", "#FFA94C", "#3FE6A0", "#D1D4F5"] # noqa: RUF012
@classmethod
async def hl_page(
cls,
head_text: str,
- items: Dict[str, str],
+ items: dict[str, str],
row_space: int = 10,
padding: int = 30,
) -> BuildImage:
@@ -162,9 +161,9 @@ class ImageTemplate:
column_data = []
for i in range(len(column_name)):
c = []
- for l in data_list:
- if len(l) > i:
- c.append(l[i])
+ for lst in data_list:
+ if len(lst) > i:
+ c.append(lst[i])
else:
c.append("")
column_data.append(c)
@@ -188,7 +187,7 @@ class ImageTemplate:
column_name[i], font, 12, "#C8CCCF"
)
column_name_image_list.append(column_name_image)
- max_h = max([c.height for c in column_name_image_list])
+ max_h = max(c.height for c in column_name_image_list)
for i, data in enumerate(build_data_list):
width = data["width"] + padding * 2
height = (base_h + row_space) * (len(data["data"]) + 1) + padding * 2
@@ -280,10 +279,9 @@ class ImageTemplate:
width = 0
height = 0
_, h = BuildImage.get_text_size("A", font)
- image_list = []
for s in text.split("\n"):
s = s.strip() or "A"
w, _ = BuildImage.get_text_size(s, font)
- width = width if width > w else w
+ width = max(width, w)
height += h
return width, height
diff --git a/zhenxun/utils/enum.py b/zhenxun/utils/enum.py
index 86d41d13..c0b79342 100644
--- a/zhenxun/utils/enum.py
+++ b/zhenxun/utils/enum.py
@@ -42,6 +42,8 @@ class PluginType(StrEnum):
"""依赖插件,一般为没有主动触发命令的插件,受权限控制"""
HIDDEN = "HIDDEN"
"""隐藏插件,一般为没有主动触发命令的插件,不受权限控制,如消息统计"""
+ PARENT = "PARENT"
+ """父插件,仅仅标记"""
class BlockType(StrEnum):
diff --git a/zhenxun/utils/message.py b/zhenxun/utils/message.py
index eb6549f2..7ad586fd 100644
--- a/zhenxun/utils/message.py
+++ b/zhenxun/utils/message.py
@@ -2,20 +2,36 @@ from io import BytesIO
from pathlib import Path
import nonebot
+from pydantic import BaseModel
from nonebot.adapters.onebot.v11 import Message, MessageSegment
-from nonebot_plugin_alconna import At, Image, Text, UniMessage
+from nonebot_plugin_alconna import At, Text, Image, Video, Voice, UniMessage
-from zhenxun.configs.config import BotConfig
from zhenxun.services.log import logger
+from zhenxun.configs.config import BotConfig
from zhenxun.utils._build_image import BuildImage
driver = nonebot.get_driver()
MESSAGE_TYPE = (
- str | int | float | Path | bytes | BytesIO | BuildImage | At | Image | Text
+ str
+ | int
+ | float
+ | Path
+ | bytes
+ | BytesIO
+ | BuildImage
+ | At
+ | Image
+ | Text
+ | Voice
+ | Video
)
+class Config(BaseModel):
+ is_bytes: bool = False
+
+
class MessageUtils:
@classmethod
@@ -28,20 +44,16 @@ class MessageUtils:
返回:
list[Text | Text]: 构造完成的消息列表
"""
- is_bytes = False
- try:
- is_bytes = driver.config.image_to_bytes in ["True", "true"]
- except AttributeError:
- pass
+ config = nonebot.get_plugin_config(Config)
message_list = []
for msg in msg_list:
- if isinstance(msg, (Image, Text, At)):
+ if isinstance(msg, Image | Text | At | Video | Voice):
message_list.append(msg)
- elif isinstance(msg, (str, int, float)):
+ elif isinstance(msg, str | int | float):
message_list.append(Text(str(msg)))
elif isinstance(msg, Path):
if msg.exists():
- if is_bytes:
+ if config.is_bytes:
image = BuildImage.open(msg)
message_list.append(Image(raw=image.pic2bytes()))
else:
@@ -120,7 +132,7 @@ class MessageUtils:
forward_data = []
for r_list in msg_list:
s = ""
- if isinstance(r_list, (UniMessage, list)):
+ if isinstance(r_list, UniMessage | list):
for r in r_list:
if isinstance(r, Text):
s += str(r)